craigthompson.dev

$ cat case-studies/ci-cd.md

Build only what changed, ship every merge

// ci/cd & release engineering · 2019 → today

Build only what changed, ship every merge

I built a CI/CD platform from scratch and have kept evolving it as the team and codebase grew. Today it runs on self-hosted Buildkite defined in Terraform, driven by an in-house TypeScript build-and-deploy engine. It models the monorepo’s dependency graph, so each change builds and deploys only the packages it affects.

Every merge to master, end to end
  1. merge
    to master
  2. package graph
    what's affected?
  3. build in parallel
    affected packages only
    • lib
    • service
    • app
  4. Validate gate
    • format
    • lint
    • types
    • tests
    • drift
  5. staging
    auto-deploy
  6. production
    live, no release train
How it evolved: pipelines → a graph-aware release engine
  1. hosted pipelines
  2. Buildkite + build engine
  3. continuous deployment
  4. merge queue · staging
  5. one Validate gate
# in practice
  • Merged work reaches customers automatically. There has been no release train since 2022.
  • A small fix rebuilds a handful of packages, not the whole platform.
  • Every PR passes one required quality gate, and /deploy on a PR puts it into a test environment.
  • Deploys wait for healthy tasks and detect rollbacks, so a bad release stops itself.

$ ls case-studies/

Search and jump