Skip to main content
CodeOath
← All posts

CI/CD & DevOps65 min total · 17 parts

CI/CD Pipelines Explained: From Push to Production

Part 7 of 17 · ~1 min

Jobs, Steps, and Runners

Every job above spins up on a completely fresh machine — its own disk, its own clean checkout, nothing left over from whatever ran an hour ago or from a different job in the same workflow. That's deliberate, and it's the thing that catches Marcus off guard the first week: he adds a step to unit-tests assuming a file lint wrote earlier in the same run would still be sitting there, and it isn't, because lint and unit-tests aren't just running at different times — they're running on two entirely separate computers that were never going to share a disk.

Two mechanisms exist specifically to bridge that gap on purpose. The first is artifacts — one job deliberately publishes something, and a later job deliberately fetches it:

jobs:
  build-app:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: web-dist
          path: dist/

  build-image:
    needs: [lint, unit-tests, build-app]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/download-artifact@v4
        with:
          name: web-dist
          path: dist/
      - run: docker build -t ghcr.io/snapledger/web:${{ github.sha }} .
      - run: docker push ghcr.io/snapledger/web:${{ github.sha }}

build-app compiles once; build-image downloads the exact output instead of recompiling from scratch inside the Docker build, which is the same "compile once, ship the result" idea as the multi-stage Dockerfile from this team's earlier build, just moved up a level from Docker stages to pipeline jobs.

The second mechanism, caching, looks similar but means something different: it's a purely optional speedup, never a required handoff, and a cache miss should degrade to "a bit slower," never to "broken." That distinction earns its own chapter next, because it's where the team's build times actually start to matter.