From 8d88aace1f68e8552a66fe58b9dc452cf4feffc7 Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Tue, 22 Jul 2025 13:19:08 -0400 Subject: [PATCH 1/8] Add GitHub Actions workflow for automatic testnet deployment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements issue #142 - adds CI/CD pipeline that automatically deploys all smart contracts to testnet on merge to dev branch. Features: - Triggers on push to dev branch - Builds contracts with forge build - Runs tests with fork testing - Deploys all 4 contracts: ButteredBread, YieldDistributor, NFTMultiplier, VotingStreakMultiplier - Uses GitHub Secrets for secure credential management 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .github/workflows/deploy-testnet.yml | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/deploy-testnet.yml diff --git a/.github/workflows/deploy-testnet.yml b/.github/workflows/deploy-testnet.yml new file mode 100644 index 00000000..1b885ae9 --- /dev/null +++ b/.github/workflows/deploy-testnet.yml @@ -0,0 +1,53 @@ +name: Deploy All Contracts to Testnet + +on: + push: + branches: + - dev + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Build contracts + run: forge build + + - name: Run tests + run: forge test --fork-url ${{ secrets.TESTNET_RPC_URL }} -vvvv + + - name: Deploy ButteredBread + env: + TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} + PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} + run: | + forge script script/deploy/DeployButteredBread.s.sol:DeployButteredBread --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" + + - name: Deploy YieldDistributor + env: + TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} + PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} + run: | + forge script script/deploy/DeployYieldDistributor.s.sol:DeployYieldDistributor --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" + + - name: Deploy NFTMultiplier + env: + TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} + PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} + run: | + forge script script/deploy/DeployNFTMultiplier.s.sol:DeployNFTMultiplier --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" + + - name: Deploy VotingStreakMultiplier + env: + TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} + PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} + run: | + forge script script/deploy/DeployVotingStreakMultiplier.s.sol:DeployVotingStreakMultiplier --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" \ No newline at end of file From da1e2954166c86a817fa3034670d99f8812ffe98 Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Tue, 22 Jul 2025 13:52:15 -0400 Subject: [PATCH 2/8] Add staging branch trigger to testnet deployment workflow --- .github/workflows/deploy-testnet.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy-testnet.yml b/.github/workflows/deploy-testnet.yml index 1b885ae9..285791e8 100644 --- a/.github/workflows/deploy-testnet.yml +++ b/.github/workflows/deploy-testnet.yml @@ -4,6 +4,7 @@ on: push: branches: - dev + - staging jobs: build-and-deploy: From dabe818ed1450e9c762af7ae358801e9645d6cf6 Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Tue, 22 Jul 2025 14:08:05 -0400 Subject: [PATCH 3/8] Add comprehensive testnet deployment documentation --- TESTNET_DEPLOYMENT.md | 74 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 TESTNET_DEPLOYMENT.md diff --git a/TESTNET_DEPLOYMENT.md b/TESTNET_DEPLOYMENT.md new file mode 100644 index 00000000..e6d85ec7 --- /dev/null +++ b/TESTNET_DEPLOYMENT.md @@ -0,0 +1,74 @@ +# Testnet Deployment Setup + +This repository includes automated testnet deployment via GitHub Actions. The workflow automatically deploys all smart contracts to testnet when code is pushed to the `dev` or `staging` branches. + +## Required GitHub Secrets + +Before the deployment workflow can run successfully, you must configure the following secrets in your GitHub repository settings: + +### 1. TESTNET_RPC_URL +- **Description**: The RPC endpoint URL for your target testnet +- **Example**: `https://rpc.gnosischain.com` (for Gnosis Chain testnet) +- **Format**: Full HTTPS URL including protocol + +### 2. TESTNET_PRIVATE_KEY +- **Description**: Private key for the wallet that will deploy the contracts +- **Format**: 64-character hexadecimal string (with or without `0x` prefix) +- **Security**: This wallet should be used ONLY for testnet deployments and contain only testnet tokens + +## Setting Up GitHub Secrets + +1. Navigate to your GitHub repository +2. Go to **Settings** > **Secrets and variables** > **Actions** +3. Click **New repository secret** +4. Add each secret with the exact names listed above + +## Deployed Contracts + +The workflow deploys the following contracts in sequence: + +1. **ButteredBread** - `script/deploy/DeployButteredBread.s.sol` +2. **YieldDistributor** - `script/deploy/DeployYieldDistributor.s.sol` +3. **NFTMultiplier** - `script/deploy/DeployNFTMultiplier.s.sol` +4. **VotingStreakMultiplier** - `script/deploy/DeployVotingStreakMultiplier.s.sol` + +## Workflow Triggers + +The deployment workflow runs automatically on: +- Push to `dev` branch (production testnet deployment) +- Push to `staging` branch (testing/validation deployment) + +## Workflow Steps + +1. **Build**: Compiles all contracts using `forge build` +2. **Test**: Runs tests with fork testing using the testnet RPC +3. **Deploy**: Executes each deployment script in sequence +4. **Logging**: Contract addresses and transaction hashes are logged in the workflow output + +## Monitoring Deployments + +- View deployment logs in the **Actions** tab of your GitHub repository +- Each deployment step will show the deployed contract addresses +- Failed deployments will stop the workflow and show error details + +## Security Considerations + +- Never use mainnet private keys for testnet deployments +- Testnet private keys should be separate from any production keys +- Monitor the testnet wallet balance to ensure sufficient gas funds +- Regularly rotate testnet private keys for security + +## Troubleshooting + +### Common Issues + +1. **Insufficient Gas**: Ensure the deployment wallet has enough testnet tokens +2. **RPC Errors**: Verify the TESTNET_RPC_URL is correct and accessible +3. **Private Key Format**: Ensure the private key is properly formatted (64 hex characters) +4. **Contract Dependencies**: Some contracts may depend on others being deployed first + +### Getting Help + +- Check the GitHub Actions logs for detailed error messages +- Verify all secrets are properly set in repository settings +- Ensure the target testnet is operational and accessible \ No newline at end of file From cfee5d8886590311335da0444bcdeed518b54af0 Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Tue, 22 Jul 2025 19:33:30 -0400 Subject: [PATCH 4/8] Add deployment tracking, verification, and artifact generation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Generate deployment.json with contract addresses and timestamps - Add contract verification on block explorer with ETHERSCAN_API_KEY - Handle verification failures gracefully with status tracking - Upload deployment artifacts with 30-day retention - Update documentation with new secret requirements and artifact details 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .github/workflows/deploy-testnet.yml | 95 ++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy-testnet.yml b/.github/workflows/deploy-testnet.yml index 285791e8..05c25f92 100644 --- a/.github/workflows/deploy-testnet.yml +++ b/.github/workflows/deploy-testnet.yml @@ -25,30 +25,117 @@ jobs: - name: Run tests run: forge test --fork-url ${{ secrets.TESTNET_RPC_URL }} -vvvv + - name: Initialize deployment tracking + run: | + echo '{"timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'", "network": "testnet", "contracts": {}}' > deployment.json + - name: Deploy ButteredBread env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} run: | - forge script script/deploy/DeployButteredBread.s.sol:DeployButteredBread --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" + forge script script/deploy/DeployButteredBread.s.sol:DeployButteredBread --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" --json > butteredbread_deploy.json + ADDRESS=$(jq -r '.transactions[0].contractAddress // empty' butteredbread_deploy.json) + if [ -n "$ADDRESS" ] && [ "$ADDRESS" != "null" ]; then + jq --arg addr "$ADDRESS" '.contracts.ButteredBread = $addr' deployment.json > temp.json && mv temp.json deployment.json + echo "ButteredBread deployed to: $ADDRESS" + fi - name: Deploy YieldDistributor env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} run: | - forge script script/deploy/DeployYieldDistributor.s.sol:DeployYieldDistributor --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" + forge script script/deploy/DeployYieldDistributor.s.sol:DeployYieldDistributor --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" --json > yielddistributor_deploy.json + ADDRESS=$(jq -r '.transactions[0].contractAddress // empty' yielddistributor_deploy.json) + if [ -n "$ADDRESS" ] && [ "$ADDRESS" != "null" ]; then + jq --arg addr "$ADDRESS" '.contracts.YieldDistributor = $addr' deployment.json > temp.json && mv temp.json deployment.json + echo "YieldDistributor deployed to: $ADDRESS" + fi - name: Deploy NFTMultiplier env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} run: | - forge script script/deploy/DeployNFTMultiplier.s.sol:DeployNFTMultiplier --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" + forge script script/deploy/DeployNFTMultiplier.s.sol:DeployNFTMultiplier --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" --json > nftmultiplier_deploy.json + ADDRESS=$(jq -r '.transactions[0].contractAddress // empty' nftmultiplier_deploy.json) + if [ -n "$ADDRESS" ] && [ "$ADDRESS" != "null" ]; then + jq --arg addr "$ADDRESS" '.contracts.NFTMultiplier = $addr' deployment.json > temp.json && mv temp.json deployment.json + echo "NFTMultiplier deployed to: $ADDRESS" + fi - name: Deploy VotingStreakMultiplier env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} run: | - forge script script/deploy/DeployVotingStreakMultiplier.s.sol:DeployVotingStreakMultiplier --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" \ No newline at end of file + forge script script/deploy/DeployVotingStreakMultiplier.s.sol:DeployVotingStreakMultiplier --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" --json > votingstreakMultiplier_deploy.json + ADDRESS=$(jq -r '.transactions[0].contractAddress // empty' votingstreakMultiplier_deploy.json) + if [ -n "$ADDRESS" ] && [ "$ADDRESS" != "null" ]; then + jq --arg addr "$ADDRESS" '.contracts.VotingStreakMultiplier = $addr' deployment.json > temp.json && mv temp.json deployment.json + echo "VotingStreakMultiplier deployed to: $ADDRESS" + fi + + - name: Verify contracts on block explorer + env: + TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} + ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }} + run: | + echo "Starting contract verification..." + VERIFICATION_FAILED=false + + # Verify ButteredBread + BUTTEREDBREAD_ADDR=$(jq -r '.contracts.ButteredBread // empty' deployment.json) + if [ -n "$BUTTEREDBREAD_ADDR" ] && [ "$BUTTEREDBREAD_ADDR" != "null" ]; then + echo "Verifying ButteredBread at $BUTTEREDBREAD_ADDR..." + forge verify-contract "$BUTTEREDBREAD_ADDR" src/ButteredBread.sol:ButteredBread --rpc-url "$TESTNET_RPC_URL" --etherscan-api-key "$ETHERSCAN_API_KEY" || VERIFICATION_FAILED=true + fi + + # Verify YieldDistributor + YIELDDISTRIBUTOR_ADDR=$(jq -r '.contracts.YieldDistributor // empty' deployment.json) + if [ -n "$YIELDDISTRIBUTOR_ADDR" ] && [ "$YIELDDISTRIBUTOR_ADDR" != "null" ]; then + echo "Verifying YieldDistributor at $YIELDDISTRIBUTOR_ADDR..." + forge verify-contract "$YIELDDISTRIBUTOR_ADDR" src/YieldDistributor.sol:YieldDistributor --rpc-url "$TESTNET_RPC_URL" --etherscan-api-key "$ETHERSCAN_API_KEY" || VERIFICATION_FAILED=true + fi + + # Verify NFTMultiplier + NFTMULTIPLIER_ADDR=$(jq -r '.contracts.NFTMultiplier // empty' deployment.json) + if [ -n "$NFTMULTIPLIER_ADDR" ] && [ "$NFTMULTIPLIER_ADDR" != "null" ]; then + echo "Verifying NFTMultiplier at $NFTMULTIPLIER_ADDR..." + forge verify-contract "$NFTMULTIPLIER_ADDR" src/NFTMultiplier.sol:NFTMultiplier --rpc-url "$TESTNET_RPC_URL" --etherscan-api-key "$ETHERSCAN_API_KEY" || VERIFICATION_FAILED=true + fi + + # Verify VotingStreakMultiplier + VOTINGSTREAKMULTIPLIER_ADDR=$(jq -r '.contracts.VotingStreakMultiplier // empty' deployment.json) + if [ -n "$VOTINGSTREAKMULTIPLIER_ADDR" ] && [ "$VOTINGSTREAKMULTIPLIER_ADDR" != "null" ]; then + echo "Verifying VotingStreakMultiplier at $VOTINGSTREAKMULTIPLIER_ADDR..." + forge verify-contract "$VOTINGSTREAKMULTIPLIER_ADDR" src/VotingStreakMultiplier.sol:VotingStreakMultiplier --rpc-url "$TESTNET_RPC_URL" --etherscan-api-key "$ETHERSCAN_API_KEY" || VERIFICATION_FAILED=true + fi + + # Update deployment.json with verification status + if [ "$VERIFICATION_FAILED" = "true" ]; then + jq '.verification_status = "partial_failure"' deployment.json > temp.json && mv temp.json deployment.json + echo "⚠️ Some contract verifications failed. Check logs above for details." + else + jq '.verification_status = "success"' deployment.json > temp.json && mv temp.json deployment.json + echo "✅ All contracts verified successfully!" + fi + + - name: Upload deployment artifacts + uses: actions/upload-artifact@v4 + with: + name: deployment-artifacts + path: | + deployment.json + *_deploy.json + retention-days: 30 + + - name: Display deployment summary + run: | + echo "📋 Deployment Summary" + echo "====================" + cat deployment.json | jq '.' + echo "" + echo "🔗 Contract Addresses:" + jq -r '.contracts | to_entries[] | "- \(.key): \(.value)"' deployment.json \ No newline at end of file From 41f20d519b705573ec7a880b68e4bc2a35071d1d Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Tue, 22 Jul 2025 19:33:56 -0400 Subject: [PATCH 5/8] Update documentation with verification and artifact details --- TESTNET_DEPLOYMENT.md | 45 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/TESTNET_DEPLOYMENT.md b/TESTNET_DEPLOYMENT.md index e6d85ec7..235f9950 100644 --- a/TESTNET_DEPLOYMENT.md +++ b/TESTNET_DEPLOYMENT.md @@ -16,6 +16,12 @@ Before the deployment workflow can run successfully, you must configure the foll - **Format**: 64-character hexadecimal string (with or without `0x` prefix) - **Security**: This wallet should be used ONLY for testnet deployments and contain only testnet tokens +### 3. ETHERSCAN_API_KEY +- **Description**: API key for contract verification on block explorer (e.g., Etherscan, Gnosisscan) +- **Format**: Alphanumeric string provided by the block explorer service +- **Purpose**: Enables automatic contract source code verification after deployment +- **Optional**: Verification will be skipped if this secret is not provided + ## Setting Up GitHub Secrets 1. Navigate to your GitHub repository @@ -42,8 +48,38 @@ The deployment workflow runs automatically on: 1. **Build**: Compiles all contracts using `forge build` 2. **Test**: Runs tests with fork testing using the testnet RPC -3. **Deploy**: Executes each deployment script in sequence -4. **Logging**: Contract addresses and transaction hashes are logged in the workflow output +3. **Deploy**: Executes each deployment script in sequence, capturing contract addresses +4. **Verify**: Attempts to verify each deployed contract on the block explorer +5. **Artifact Generation**: Creates `deployment.json` with all contract addresses and verification status +6. **Logging**: Contract addresses and transaction hashes are logged in the workflow output + +## Deployment Artifacts + +After each deployment, the workflow generates several artifacts: + +### deployment.json +Contains the complete deployment information: +```json +{ + "timestamp": "2024-01-01T12:00:00Z", + "network": "testnet", + "contracts": { + "ButteredBread": "0x1234...", + "YieldDistributor": "0x5678...", + "NFTMultiplier": "0x9abc...", + "VotingStreakMultiplier": "0xdef0..." + }, + "verification_status": "success" +} +``` + +### Individual deployment files +- `butteredbread_deploy.json` +- `yielddistributor_deploy.json` +- `nftmultiplier_deploy.json` +- `votingstreakMultiplier_deploy.json` + +These artifacts are automatically uploaded and retained for 30 days. ## Monitoring Deployments @@ -66,6 +102,11 @@ The deployment workflow runs automatically on: 2. **RPC Errors**: Verify the TESTNET_RPC_URL is correct and accessible 3. **Private Key Format**: Ensure the private key is properly formatted (64 hex characters) 4. **Contract Dependencies**: Some contracts may depend on others being deployed first +5. **Verification Failures**: + - Check that ETHERSCAN_API_KEY is valid and has sufficient rate limits + - Ensure the block explorer supports the target network + - Verification may fail if contracts are not yet indexed (try again later) +6. **Missing Contract Addresses**: If deployment.json shows null addresses, check individual deployment logs for errors ### Getting Help From e8e707c9aaf8a8bb5369548925f2681d915fa324 Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Tue, 22 Jul 2025 20:13:27 -0400 Subject: [PATCH 6/8] Fix environment variable naming for private key in workflow --- .github/workflows/deploy-testnet.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/deploy-testnet.yml b/.github/workflows/deploy-testnet.yml index 05c25f92..2563b94e 100644 --- a/.github/workflows/deploy-testnet.yml +++ b/.github/workflows/deploy-testnet.yml @@ -32,9 +32,9 @@ jobs: - name: Deploy ButteredBread env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} - PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} + TESTNET_PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} run: | - forge script script/deploy/DeployButteredBread.s.sol:DeployButteredBread --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" --json > butteredbread_deploy.json + forge script script/deploy/DeployButteredBread.s.sol:DeployButteredBread --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$TESTNET_PRIVATE_KEY" --json > butteredbread_deploy.json ADDRESS=$(jq -r '.transactions[0].contractAddress // empty' butteredbread_deploy.json) if [ -n "$ADDRESS" ] && [ "$ADDRESS" != "null" ]; then jq --arg addr "$ADDRESS" '.contracts.ButteredBread = $addr' deployment.json > temp.json && mv temp.json deployment.json @@ -44,9 +44,9 @@ jobs: - name: Deploy YieldDistributor env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} - PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} + TESTNET_PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} run: | - forge script script/deploy/DeployYieldDistributor.s.sol:DeployYieldDistributor --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" --json > yielddistributor_deploy.json + forge script script/deploy/DeployYieldDistributor.s.sol:DeployYieldDistributor --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$TESTNET_PRIVATE_KEY" --json > yielddistributor_deploy.json ADDRESS=$(jq -r '.transactions[0].contractAddress // empty' yielddistributor_deploy.json) if [ -n "$ADDRESS" ] && [ "$ADDRESS" != "null" ]; then jq --arg addr "$ADDRESS" '.contracts.YieldDistributor = $addr' deployment.json > temp.json && mv temp.json deployment.json @@ -56,9 +56,9 @@ jobs: - name: Deploy NFTMultiplier env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} - PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} + TESTNET_PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} run: | - forge script script/deploy/DeployNFTMultiplier.s.sol:DeployNFTMultiplier --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" --json > nftmultiplier_deploy.json + forge script script/deploy/DeployNFTMultiplier.s.sol:DeployNFTMultiplier --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$TESTNET_PRIVATE_KEY" --json > nftmultiplier_deploy.json ADDRESS=$(jq -r '.transactions[0].contractAddress // empty' nftmultiplier_deploy.json) if [ -n "$ADDRESS" ] && [ "$ADDRESS" != "null" ]; then jq --arg addr "$ADDRESS" '.contracts.NFTMultiplier = $addr' deployment.json > temp.json && mv temp.json deployment.json @@ -68,9 +68,9 @@ jobs: - name: Deploy VotingStreakMultiplier env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} - PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} + TESTNET_PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} run: | - forge script script/deploy/DeployVotingStreakMultiplier.s.sol:DeployVotingStreakMultiplier --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$PRIVATE_KEY" --json > votingstreakMultiplier_deploy.json + forge script script/deploy/DeployVotingStreakMultiplier.s.sol:DeployVotingStreakMultiplier --rpc-url "$TESTNET_RPC_URL" --broadcast --private-key "$TESTNET_PRIVATE_KEY" --json > votingstreakMultiplier_deploy.json ADDRESS=$(jq -r '.transactions[0].contractAddress // empty' votingstreakMultiplier_deploy.json) if [ -n "$ADDRESS" ] && [ "$ADDRESS" != "null" ]; then jq --arg addr "$ADDRESS" '.contracts.VotingStreakMultiplier = $addr' deployment.json > temp.json && mv temp.json deployment.json From af9b8227cd1909b18fcd57f6c945c4bdc404d81c Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Sat, 9 Aug 2025 15:06:07 -0400 Subject: [PATCH 7/8] Add pull_request trigger to workflow for PR testing --- .github/workflows/deploy-testnet.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/deploy-testnet.yml b/.github/workflows/deploy-testnet.yml index 2563b94e..6d605e50 100644 --- a/.github/workflows/deploy-testnet.yml +++ b/.github/workflows/deploy-testnet.yml @@ -5,6 +5,10 @@ on: branches: - dev - staging + pull_request: + branches: + - dev + - staging jobs: build-and-deploy: From 7dc9f80c4cfab3cc6a4032151819e32d19a006ba Mon Sep 17 00:00:00 2001 From: Ron Turetzky Date: Sat, 9 Aug 2025 16:11:20 -0400 Subject: [PATCH 8/8] Fix workflow for PRs from forks - make steps conditional on secrets availability --- .github/workflows/deploy-testnet.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-testnet.yml b/.github/workflows/deploy-testnet.yml index 6d605e50..33299093 100644 --- a/.github/workflows/deploy-testnet.yml +++ b/.github/workflows/deploy-testnet.yml @@ -26,14 +26,21 @@ jobs: - name: Build contracts run: forge build - - name: Run tests + - name: Run tests (with fork) + if: ${{ secrets.TESTNET_RPC_URL != '' }} run: forge test --fork-url ${{ secrets.TESTNET_RPC_URL }} -vvvv + + - name: Run tests (without fork) + if: ${{ secrets.TESTNET_RPC_URL == '' }} + run: forge test -vvvv - name: Initialize deployment tracking + if: ${{ secrets.TESTNET_RPC_URL != '' && secrets.TESTNET_PRIVATE_KEY != '' }} run: | echo '{"timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'", "network": "testnet", "contracts": {}}' > deployment.json - name: Deploy ButteredBread + if: ${{ secrets.TESTNET_RPC_URL != '' && secrets.TESTNET_PRIVATE_KEY != '' }} env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} TESTNET_PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} @@ -46,6 +53,7 @@ jobs: fi - name: Deploy YieldDistributor + if: ${{ secrets.TESTNET_RPC_URL != '' && secrets.TESTNET_PRIVATE_KEY != '' }} env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} TESTNET_PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} @@ -58,6 +66,7 @@ jobs: fi - name: Deploy NFTMultiplier + if: ${{ secrets.TESTNET_RPC_URL != '' && secrets.TESTNET_PRIVATE_KEY != '' }} env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} TESTNET_PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} @@ -70,6 +79,7 @@ jobs: fi - name: Deploy VotingStreakMultiplier + if: ${{ secrets.TESTNET_RPC_URL != '' && secrets.TESTNET_PRIVATE_KEY != '' }} env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} TESTNET_PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }} @@ -82,6 +92,7 @@ jobs: fi - name: Verify contracts on block explorer + if: ${{ secrets.TESTNET_RPC_URL != '' && secrets.ETHERSCAN_API_KEY != '' }} env: TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }} ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }} @@ -127,6 +138,7 @@ jobs: fi - name: Upload deployment artifacts + if: ${{ secrets.TESTNET_RPC_URL != '' && secrets.TESTNET_PRIVATE_KEY != '' }} uses: actions/upload-artifact@v4 with: name: deployment-artifacts @@ -136,6 +148,7 @@ jobs: retention-days: 30 - name: Display deployment summary + if: ${{ secrets.TESTNET_RPC_URL != '' && secrets.TESTNET_PRIVATE_KEY != '' }} run: | echo "📋 Deployment Summary" echo "===================="