Conversation
Single workflow that handles: - CI: build, test, format check - Upgrade safety validation - Testnet deploy on PR (optional) - Mainnet deploy on merge to main (optional) - 3-tier snapshot rotation after deploy Configurable via inputs: - deploy-on-pr: enable testnet deploy on pull requests - deploy-on-main: enable mainnet deploy on push to main - run-upgrade-safety: enable/disable upgrade validation - check-formatting: enable/disable format check
- Add --rpc-url to forge verify-contract (required for --guess-constructor-args) - Use process substitution instead of pipe to properly propagate exit codes - Track verification failures and exit 1 if any contract fails after 3 attempts - Add GitHub Actions ::error:: annotations for visibility
Resolves 'Multiple contracts found with the name' error by finding the source file path and using format 'src/Contract.sol:Contract' to disambiguate from lib/ dependencies.
The previous fallback path '$BASELINE/../previous' fails when the baseline directory doesn't exist because '../' can't resolve through a non-existent directory. Using '$upgrades-path/previous' directly avoids this issue.
- Remove validation-script input (no longer needed) - Use npx @openzeppelin/upgrades-core validate directly - Loop through all baseline contracts automatically - Consuming repos don't need ValidateUpgrade.s.sol anymore
- Generate ValidateUpgrades.s.sol dynamically at runtime - Use forge script with --sig to pass contract names - Cleanup generated script after validation - More consistent with Foundry toolchain
flatten-snapshots now runs on push to main when: - deploy-mainnet succeeds (normal post-deploy flattening) - deploy-mainnet is skipped (baseline init without deployment) This enables repos to establish their initial baseline without requiring mainnet deployment to be enabled.
…t control New input 'init-baseline-without-deploy' (default: false) controls whether flatten-snapshots runs when deploy-mainnet is skipped (deploy-on-main: false). This gives repos explicit control over baseline initialization behavior: - false (default): baseline only created after successful mainnet deploy - true: baseline can be initialized on merge even without deployment
Mainnet deployments (on merge to main):
- Creates GitHub Release with tag 'mainnet-{sha}'
- Includes contract addresses, Blockscout links, tx hashes
- Attaches flattened contract sources as assets
- Includes commit details (message, author)
Testnet deployments (on PRs):
- Posts deployment info as PR comment
- Creates GitHub Pre-release with tag 'testnet-{sha}'
- Includes PR reference and commit info
New inputs:
- create-release: boolean (default: true)
- release-prefix: string for custom tag prefixes
Removed testnet pre-release creation on PRs. Releases are now only created for mainnet deployments (merge to main). PR deployments still get: - Deployment summary in workflow - PR comment with contract addresses and tx links
Replaced network-config-path JSON file requirement with direct inputs: - testnet-blockscout-url (default: Sepolia) - testnet-name (default: Sepolia) - mainnet-blockscout-url (default: Sepolia) - mainnet-name (default: Sepolia) This eliminates the need for deploy-networks.json in consuming repos. Repos can override these inputs if deploying to different networks.
Validates that foundry.toml has required settings for deterministic bytecode: - bytecode_hash = "none" - cbor_metadata = false Fails CI with clear error message if settings are missing.
Creates deployments/{network}/deployment.json with schema:
{
"contracts": [
{ "sourcePathAndName": "src/Contract.sol:Contract", "address": "0x..." }
]
}
- Testnet: deployments/testnet/deployment.json
- Mainnet: deployments/{network-name}/deployment.json
Artifacts uploaded via actions/upload-artifact@v4 for downstream consumption.
franrolotti
left a comment
There was a problem hiding this comment.
@RonTuretzky Only three comments - workflow is green on saving-circles PR #72. We haven’t enabled/configured mainnet deploy yet (partly due to the testnet/mainnet secrets noted below).
| type: string | ||
| default: '' | ||
|
|
||
| secrets: |
There was a problem hiding this comment.
deploy-testnet and deploy-mainnet use the same secrets.RPC_URL and secrets.PRIVATE_KEY. This causes trouble to deploy-on-pr (testnet) and deploy-on-main (mainnet) at the same time with different networks
| mainnet-blockscout-url: | ||
| description: 'Blockscout URL for mainnet verification and explorer links' | ||
| type: string | ||
| default: 'https://eth-sepolia.blockscout.com' | ||
| mainnet-name: | ||
| description: 'Mainnet network name for display' | ||
| type: string | ||
| default: 'Sepolia' |
There was a problem hiding this comment.
mainnet-blockscout-url (and mainnet-name) default to Sepolia
.github/workflows/_foundry-cicd.yml
Outdated
| name: deployment-testnet | ||
| path: deployments/testnet/deployment.json | ||
|
|
||
| - name: Verify contracts on Blockscout |
There was a problem hiding this comment.
some repos may have [etherscan] in foundry.toml that references ${ETHERSCAN_API_KEY} and will fail unless they remove it (like i did with saving-circles). Might be worth documenting this in the consumer instructions. Just pointing it out.
Combines our enhancements with the change detection feature from main: - Keeps skip-if-no-changes and contract-paths inputs from main - Keeps detect-changes job from main - Preserves our direct network config inputs (replaces JSON config) - Preserves compiler config validation - Preserves init-baseline-without-deploy flag - Preserves release options and GitHub release creation - Preserves dynamic upgrade validation script generation - Preserves deployment artifact creation - Preserves improved verification with fully qualified names
Split the monolithic _foundry-cicd.yml into focused, reusable workflows: - _foundry-detect-changes.yml: Smart contract change detection - _foundry-ci.yml: Build, test, format check, compiler validation - _foundry-upgrade-safety.yml: Upgrade safety validation - _foundry-deploy.yml: Deploy with verification (testnet/mainnet) - _foundry-post-mainnet.yml: Flatten snapshots and create releases The main _foundry-cicd.yml now acts as an orchestrator that calls these sub-workflows, providing the same one-line import experience for consumers while enabling granular imports for advanced use cases.
- Add foundry-upgradeable-counter-example as submodule at examples/foundry-counter - Add working-directory input to all sub-workflows for flexible testing - Create integration-test.yml that validates workflow changes against the example project - Pass working-directory through orchestrator to all sub-workflows Integration tests run automatically when workflow files change, validating changes before they affect external consumers.
- Update README with comprehensive documentation: - Quick start for _foundry-cicd.yml orchestrator - All workflow inputs and secrets reference - Development section explaining integration testing - How local ./ refs test current branch before affecting consumers - Working with the submodule - Architecture decisions - Update foundry-counter submodule to latest (6c84d40): - Clean ERC-7201 namespaced storage pattern - Upgrade-safe storage layout
Forge output structure strips src/ and test/upgrades/ prefixes: - src/Counter.sol -> out/Counter.sol/Counter.json - test/upgrades/baseline/Counter.sol -> out/baseline/Counter.sol/Counter.json Updated contract path format to match Forge's output structure: - Use Counter.sol:Counter instead of src/Counter.sol:Counter - Use baseline/Counter.sol:Counter instead of test/upgrades/baseline/Counter.sol:Counter This fixes the "No such file or directory" error when OZ Foundry Upgrades tries to read contract artifacts.
|
@RonTuretzky can we merge this? |
I am unhappy with the state of this repo |
- Split shared PRIVATE_KEY/RPC_URL into separate TESTNET/MAINNET secrets to allow simultaneous testnet and mainnet deployments - Add foundry.toml validation to detect and fail early if [etherscan] sections reference undefined ETHERSCAN_API_KEY environment variable - Update README to document new separate testnet/mainnet secrets - Network config file already has correct mainnet/testnet values (Ethereum vs Sepolia)
No description provided.