Setting Up CI/CD with GitHub Actions
A step-by-step guide to building a robust CI/CD pipeline with GitHub Actions — from linting and testing to preview deployments and production releases.
Author
Robert Baker
Published
Read time
2 min read
A good CI/CD pipeline catches bugs before they reach production and automates the tedious parts of deployment. GitHub Actions makes this straightforward with YAML-based workflows that live alongside your code.
A Production-Ready Pipeline
Here’s the workflow structure we use on most projects:
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- run: bun install --frozen-lockfile
- run: bun run typecheck
- run: bun run lint
- run: bun run test
This runs on every push and pull request, ensuring code quality stays consistent.
Key Pipeline Stages
1. Install Dependencies
Always use a lockfile to ensure reproducible builds:
bun install --frozen-lockfile # Bun
npm ci # npm
pnpm install --frozen-lockfile # pnpm
2. Type Checking
Catch type errors before they become runtime bugs. Run tsc --noEmit or your framework’s typecheck command.
3. Linting
Enforce code style and catch common mistakes. We use oxlint for speed — it’s 50-100x faster than ESLint for the checks it supports.
4. Testing
Run your full test suite. In monorepos, use Turborepo to run tests in parallel across packages:
bun turbo run test
5. Build
Verify the project actually compiles. Build artifacts can be uploaded for deployment:
- run: bun run build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
Preview Deployments
Every pull request should get a preview URL. Cloudflare Pages and Vercel do this automatically, but you can set it up manually:
deploy-preview:
if: github.event_name == 'pull_request'
needs: quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bun install --frozen-lockfile
- run: bun run build
- name: Deploy Preview
run: npx wrangler pages deploy dist --branch=${{ github.head_ref }}
Caching for Speed
Cache dependencies to cut CI time by 60-80%:
- uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lockb') }}
restore-keys: bun-${{ runner.os }}-
Branch Protection Rules
CI is only useful if you enforce it. Configure branch protection on main:
- Require status checks to pass before merging
- Require pull request reviews
- Require branches to be up to date before merging
- Do not allow bypassing the above settings
Secrets Management
Never hardcode secrets. Use GitHub’s encrypted secrets:
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
API_KEY: ${{ secrets.API_KEY }}
Rotate secrets regularly and use environment-specific secrets for staging vs production.
Monitoring Your Pipeline
Track these metrics over time:
- CI duration — should stay under 5 minutes for most projects
- Flaky test rate — investigate any test that fails intermittently
- Deploy frequency — healthy teams deploy multiple times per day
A well-tuned CI/CD pipeline is one of the highest-leverage investments you can make in your development workflow.
Share this article
Get expert development help fast
Our engineering team turns complex ideas into production-ready software tailored to your business.
Post essentials
- Published on September 28, 2025 with real-world implementation examples.
- Designed for fast implementation with 2 min read worth of guidance.
- Validated by Robert Baker team.
Expert contributor
Robert Baker
Robert Baker cares deeply about reliable, well-architected solutions. Every guide we publish is battle-tested in real projects before it reaches the blog.
Browse more articlesShare article
Help your peers level up — share this article with colleagues who'd find it useful.
Email this articleContinue leveling up your engineering skills
Dive deeper with related guides chosen to complement this topic and accelerate your next project.
Field-tested Building Design Systems and Component Libraries
How to create reusable UI component libraries that scale across projects. Covers architecture decisions, documentation, testing, and versioning.
Field-tested TypeScript Best Practices for 2026
Modern TypeScript patterns every developer should know — strict mode, branded types, const assertions, discriminated unions, and more.
Field-tested Mobile-First Web Development in 2026
How to build fast, responsive websites that work beautifully on every device. Covers responsive design, performance budgets, and Core Web Vitals.
Get engineering insights every week
Subscribe for framework updates, architecture patterns, and deep dives tailored to busy engineering teams.
Subscribe to Our Newsletter
Get tech tips, special offers, and updates delivered to your inbox.