Files
2025-11-30 09:01:14 +08:00

290 lines
5.3 KiB
Markdown

# CI/CD Integration
GitHub Actions workflows for Foundry projects.
## Basic Workflow
```yaml
# .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
```yaml
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
```yaml
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
```yaml
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
```yaml
- name: Gas snapshot check
run: |
forge snapshot
forge snapshot --diff .gas-snapshot
```
### Comment on PR
```yaml
- 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
```yaml
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`:
```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 testing
- `DEPLOYER_PRIVATE_KEY`: For deployment
- `ETHERSCAN_API_KEY`: For verification
**Never commit secrets to the repository.**
## Matrix Testing
Test across Solidity versions:
```yaml
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 }}
```