5.3 KiB
5.3 KiB
CI/CD Integration
GitHub Actions workflows for Foundry projects.
Basic Workflow
# .github/workflows/test.yml
name: Test
on:
push:
branches: [main]
pull_request:
env:
FOUNDRY_PROFILE: ci
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Run tests
run: forge test -vvv
With Caching
name: Test
on: [push, pull_request]
env:
FOUNDRY_PROFILE: ci
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
cache: true
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
lib
cache
out
key: ${{ runner.os }}-foundry-${{ hashFiles('**/foundry.toml') }}
restore-keys: |
${{ runner.os }}-foundry-
- name: Build
run: forge build
- name: Run tests
run: forge test -vvv
Full Pipeline
name: CI
on:
push:
branches: [main]
pull_request:
env:
FOUNDRY_PROFILE: ci
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
cache: true
- name: Build
run: forge build --sizes
test:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
cache: true
- name: Run tests
run: forge test -vvv
coverage:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
cache: true
- name: Generate coverage
run: forge coverage --report lcov
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
files: lcov.info
gas-report:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
cache: true
- name: Gas snapshot
run: forge snapshot --check --tolerance 5
Fork Testing in CI
jobs:
fork-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
cache: true
- name: Run fork tests
run: forge test --match-test "testFork" -vvv
env:
MAINNET_RPC_URL: ${{ secrets.MAINNET_RPC_URL }}
Gas Snapshot Tracking
Check for regressions
- name: Gas snapshot check
run: |
forge snapshot
forge snapshot --diff .gas-snapshot
Comment on PR
- name: Compare gas
run: forge snapshot --diff .gas-snapshot > gas-diff.txt
- name: Post gas diff
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const diff = fs.readFileSync('gas-diff.txt', 'utf8');
if (diff.trim()) {
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '## Gas Changes\n```\n' + diff + '\n```'
});
}
Deployment
jobs:
deploy:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: production
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Deploy
run: |
forge script script/Deploy.s.sol \
--rpc-url ${{ secrets.RPC_URL }} \
--broadcast \
--verify
env:
PRIVATE_KEY: ${{ secrets.DEPLOYER_PRIVATE_KEY }}
ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }}
CI Profile
Configure higher fuzz runs for CI in foundry.toml:
[profile.default]
fuzz.runs = 256
invariant.runs = 256
[profile.ci]
fuzz.runs = 10000
invariant.runs = 1000
verbosity = 3
Use with FOUNDRY_PROFILE=ci forge test.
Secrets Management
Required secrets for CI:
MAINNET_RPC_URL: For fork testingDEPLOYER_PRIVATE_KEY: For deploymentETHERSCAN_API_KEY: For verification
Never commit secrets to the repository.
Matrix Testing
Test across Solidity versions:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
solc: ["0.8.20", "0.8.25", "0.8.30"]
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Test with Solc ${{ matrix.solc }}
run: forge test
env:
FOUNDRY_SOLC_VERSION: ${{ matrix.solc }}