Buildkite
Buildkite: hybrid CI with self-hosted agents and a hosted control plane. Pipelines as YAML, dynamic steps, and the patterns at scale.
CI/CD — Buildkite
EXAMPLE
# ===== The model =====
# Buildkite.com hosts the UI + scheduler.
# YOU run agents on your infrastructure (laptops, VMs, k8s, on-prem).
# Pipelines defined in YAML inside the repo or uploaded dynamically.
# ===== Install an agent =====
# macOS:
brew install buildkite/buildkite/buildkite-agent
buildkite-agent start --token <token>
# Docker:
docker run -d --name agent -e BUILDKITE_AGENT_TOKEN=<token> \
-v /var/run/docker.sock:/var/run/docker.sock \
buildkite/agent:3 start
# Kubernetes:
helm install agent buildkite/agent --set agentToken=<token> --set replicas=4
# ===== Pipeline YAML =====
# .buildkite/pipeline.yml
steps:
- label: ":eslint: Lint"
command: npm ci && npm run lint
agents: { queue: 'default' }
- label: ":jest: Test"
command: npm test -- --coverage
artifact_paths:
- 'coverage/**/*'
- wait
- label: ":docker: Build image"
command: docker build -t shop:$BUILDKITE_COMMIT .
plugins:
- docker-compose#v4.16.0:
run: app
- block: ":rocket: Deploy?"
branches: main
- label: ":aws: Deploy"
command: ./deploy.sh
branches: main
env:
AWS_REGION: ap-southeast-2
# 'wait' = barrier between phases.
# 'block' = manual approval gate.
# ===== Dynamic pipeline (upload) =====
# Some steps depend on the diff; generate the pipeline on the fly:
# .buildkite/pipeline.yml
steps:
- label: 'Generate'
command: ./scripts/gen-pipeline.sh | buildkite-agent pipeline upload
# Script outputs YAML to stdout; agent uploads it.
# ===== Queues + tags =====
# Agents register with a 'queue' (e.g. 'mac-arm', 'docker', 'gpu').
# Steps select queues with agents: { queue: 'gpu' }.
# Tag agents for capabilities; pin steps accordingly.
# ===== Artifacts =====
- label: 'Build'
command: npm run build
artifact_paths:
- 'dist/**/*'
- label: 'Deploy'
command: |
buildkite-agent artifact download 'dist/**/*' .
./upload-to-s3.sh dist/
# ===== Secrets =====
# Two options:
# 1. Environment variables set on the agent (e.g. via systemd / .env)
# 2. buildkite-agent secret get my-secret (Buildkite cloud-managed)
# Plugins (aws-ssm, vault) integrate with external secret stores.
# ===== Plugins =====
plugins:
- docker#v5.10.0:
image: 'node:20-alpine'
workdir: /app
mount-buildkite-agent: true
- test-collector#v1.10.2:
files: 'junit.xml'
format: 'junit'
# Plugins are versioned and shareable across pipelines.
# ===== Triggers (cross-pipeline) =====
- trigger: shared-libs-deploy
label: 'Deploy shared libs'
build:
branch: main
message: 'Triggered by ${BUILDKITE_PIPELINE_SLUG}'
# ===== Matrix =====
- label: 'Test :node-{{matrix}}'
command: nvm use {{matrix}} && npm test
matrix:
- '18'
- '20'
- '22'
# ===== Patterns to internalise =====
# - Agents close to your code + secrets (great for regulated industries)
# - Dynamic pipeline upload for monorepo / per-app builds
# - Plugins instead of duplicated docker / aws / test-collector setup
# - Manual approval ('block') before risky steps
# ===== Pitfalls =====
# - Long-running agents collecting junk (clean workspaces between builds)
# - Secrets baked into agent images
# - Pipelines that grow into the YAML without dynamic upload
# - 'wait' steps everywhere -> sequential when parallelism would do
Why it matters
Buildkite shines when you want self-hosted agents but a hosted UI: low-latency runners, secrets close to your code, dynamic pipelines for monorepos. YAML pipelines + plugins + block steps cover most needs; pair with queues + tags as the team grows.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
# .buildkite/pipeline.yml
steps:
- label: ":hammer: test"
command: npm test
- wait
- label: ":docker: build"
command: docker build -t app .
Try it Yourself »
Discussion
Loading…