๐ CI/CD
Continuous Integration and Continuous Deployment โ automate builds, tests, and deployments so every push can ship safely.
CI/CD is essential for production Web3 apps: run tests on every commit, deploy contracts and frontends from a single pipeline, and avoid manual mistakes.
๐ฏ Why CI/CD Matters for Web3
- Catch bugs before mainnet โ Run tests and lint on every PR
- Reproducible deployments โ Same steps every time, no โI forgot to run Xโ
- Audit trail โ Who deployed what, when, from which commit
- Security โ Run secret scanning, dependency checks, and contract verification in the pipeline
๐ Key Concepts
| Term | Meaning |
|---|---|
| CI | Automatically build and test code on every push/PR |
| CD | Automatically deploy (or prepare artifacts) after successful CI |
| Pipeline | Sequence of steps (install โ test โ build โ deploy) |
| Workflow | The config file that defines your pipeline |
๐ ๏ธ Popular CI/CD Platforms
- GitHub Actions โ Native to GitHub, free for public repos, generous free tier for private
- GitLab CI/CD โ Built into GitLab, powerful and flexible
- CircleCI โ Fast, good for complex workflows
- Vercel / Netlify โ Auto-deploy from Git (CD-focused)
- Railway / Render โ Git-based deploys with env and Docker support
๐ GitHub Actions: Quick Start
Create .github/workflows/ci.yml in your repo:
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm testThis runs npm ci, npm run lint, and npm test on every push and PR to main/develop.
๐ฆ Build and Test (Node / Hardhat)
Example for a typical Web3 monorepo (app + contracts):
# .github/workflows/build-and-test.yml
name: Build and Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test-contracts:
name: Test contracts
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- name: Compile contracts
run: npx hardhat compile
- name: Run contract tests
run: npx hardhat test
test-app:
name: Test app
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build๐ Using Secrets in CI/CD
Never commit API keys or private keys. Use your platformโs secrets and inject them as environment variables.
GitHub Actions: Encrypted secretsย
- Repo โ Settings โ Secrets and variables โ Actions
- Add e.g.
PRIVATE_KEY,ALCHEMY_API_KEY,VERCEL_TOKEN
# Use secrets in a job
jobs:
deploy:
runs-on: ubuntu-latest
env:
PRIVATE_KEY: ${{ secrets.DEPLOYER_PRIVATE_KEY }}
RPC_URL: ${{ secrets.SEPOLIA_RPC_URL }}
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx hardhat run scripts/deploy.js --network sepoliaBest practice: Use a deployer wallet with minimal funds; never use a wallet holding real user assets.
๐ข Deploy from CI (CD)
Deploy frontend to Vercel
Vercel GitHub integrationย deploys automatically. For custom control, use the Vercel CLIย in Actions:
# .github/workflows/deploy-vercel.yml
name: Deploy to Vercel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
working-directory: ./Deploy with Docker (e.g. Railway)
# .github/workflows/deploy-railway.yml
name: Deploy to Railway
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Railway CLI
run: npm i -g @railway/cli
- name: Deploy
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
run: railway up --service my-appSee Railwayโs deployment docsย for tokens and service names.
โ Good Practices
- Run tests and lint on every PR โ Block merge if they fail
- Use matrix builds for multiple Node versions if you support them
- Cache dependencies โ
cache: 'npm'or actions/cacheย to speed up runs - Pin actions by tag โ Prefer
@v4over@main - Store all secrets in the platform โ Never log or commit them
- Document your workflows โ Brief comment in the YAML or a CONTRIBUTING.md
๐ Further Reading
- GitHub Actions documentationย
- Hardhat CI documentationย
- Vercel deploymentsย
- Environment Variables โ Keep secrets out of the repo