The Pipeline in Action
Five stages: Code ? Build ? Test ? Deploy ? Live. Press Run Pipeline to send an artifact through. Press Fail at Test to see the failure notification flow back.
Code example
A GitHub Actions workflow that builds, tests, and deploys on every push to main.
# .github/workflows/deploy.yml
name: CI/CD Pipeline
on:
push:
branches: [main]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm test
- run: npm run build
deploy:
needs: build-and-test # only runs if tests pass
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
- name: Deploy to production
run: |
ssh deploy@prod "docker pull myapp:${{ github.sha }} && \
docker stop app || true && \
docker run -d --name app -p 80:3000 myapp:${{ github.sha }}"
// tests/api.test.js — runs in the Test stage
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { createServer } from '../src/server.js';
let server;
beforeAll(async () => {
server = await createServer({ port: 0 }); // random port
});
afterAll(() => server.close());
describe('GET /api/users/:id', () => {
it('returns 200 with user object', async () => {
const res = await fetch(`http://localhost:${server.port}/api/users/1`);
expect(res.status).toBe(200);
const body = await res.json();
expect(body).toMatchObject({
id: 1, name: expect.any(String)
});
});
it('returns 404 for unknown user', async () => {
const res = await fetch(`http://localhost:${server.port}/api/users/9999`);
expect(res.status).toBe(404);
});
});
Key concepts
Continuous Integration
Every commit to main automatically triggers a build and test run. The goal: catch bugs within minutes of introduction, not days later during a manual release.
Continuous Deployment
After tests pass, code deploys to production automatically — no human gate. Requires high test confidence. Some teams use Continuous Delivery instead: auto to staging, manual gate to prod.
Fail Fast
A pipeline must block broken code. If any stage fails, it halts and notifies the team. The earlier a failure is caught (build > test > deploy), the cheaper it is to fix.
Build Artifact
The output of the Build stage — a Docker image, compiled binary, or zip bundle. Artifacts are versioned and immutable: what you test is exactly what you deploy.