Course navigationPhase 33
Volume 08 · Phase 33

CI/CD with GitHub Actions

Build a trustworthy GitHub Actions pipeline that verifies pull requests, creates immutable release artifacts, uses least privilege, caches safely, and controls deployment concurrency.

16lessons + labs
3klesson words
10source references
What you will ship

Phase outcome and project increment

Learning outcome

Build a trustworthy GitHub Actions pipeline that verifies pull requests, creates immutable release artifacts, uses least privilege, caches safely, and controls deployment concurrency.

Concrete deliverable

.github/workflows/ci.yml plus release/deploy workflows that build once, tag by commit SHA, and gate promotion.

Figure 33.1 — Where this phase lives in TaskFlow
pull request
deterministic install
lint/typecheck/test/build
trusted main
immutable artifact
environment gate
deployment
Trace the flow left-to-right for implementation and right-to-left for debugging. At every arrow, ask what data crosses the boundary and what proves it is trustworthy.
Instructor mental model

Principles to keep while coding

01

CI verifies changes on pull requests; release workflows should operate from trusted code and immutable commit identities.

02

Use frozen lockfile installs so CI fails when dependency manifests and the lockfile disagree.

03

Give GitHub Actions tokens the minimum permissions each job requires.

04

Build once and promote the same artifact instead of rebuilding different binaries for each environment.

Code-along path

Guided phase lab

Do these in order. Each step should end with evidence before the next one starts.

  1. 01

    Create CI triggered by pull_request with read-only contents permission and explicit concurrency cancellation.

  2. 02

    Set up Node and pnpm, then install with --frozen-lockfile so manifests cannot drift from the lockfile.

  3. 03

    Run lint/typecheck/tests/build as separate clear steps or jobs with understandable failure ownership.

  4. 04

    Add dependency/package cache only after correctness works; key it from lockfile inputs.

  5. 05

    Create trusted-main release workflow that tags an image/artifact with the commit SHA rather than latest only.

  6. 06

    Add environment protection/permissions for deployment and ensure stale production runs are not silently canceled mid-release.

Debugging studio

Failures you should know how to diagnose

Failure drill 1

Using pull_request_target with untrusted checkout/secrets

Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.

Failure drill 2

Broad write permissions for all jobs

Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.

Failure drill 3

Rebuilding different artifacts in each environment

Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.

Failure drill 4

CI green because important workspace checks never ran

Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.

Watch-order style

Lessons

The source chapters come first. Every phase now ends with a guided build, a debugging workshop, and an independent challenge so reading turns into transferable skill.

01

CI/CD Mental Model and Pipeline Architecture

CI/CD Mental Model and Pipeline Architecture Continuous Integration answers: can this change safely join the main branch? Continuous Delivery answers: do we have a verified artifact that cou

2 min
02

GitHub Actions Workflow Triggers Permissions and Concurrency

Workflow Triggers, Permissions, and Concurrency Use pull_request for untrusted PR verification and push/main for trusted release work. Give GITHUB_TOKEN the minimum permissions required. Con

2 min
03

Node pnpm Monorepo Cache and Deterministic Install

Node, pnpm, Monorepo Cache, and Deterministic Install CI reproduces the repository using the committed lockfile. pnpm install --frozen-lockfile should fail if package manifests and the lockf

2 min
04

Quality Gates Lint Typecheck Test and Build

Quality Gates: Lint, Typecheck, Test, and Build A pull request should fail before merge when static analysis, typechecking, tests, or a production build fails. These checks answer different

2 min
05

PostgreSQL Service Containers and Prisma Migrations in CI

PostgreSQL Service Containers and Prisma Migrations in CI Repository and HTTP integration tests need a real PostgreSQL database. GitHub Actions service containers provide an isolated test da

2 min
06

Test Matrices Artifacts and Failure Diagnostics

Test Matrices, Artifacts, and Failure Diagnostics Artifacts should help diagnose failed or expensive jobs, not become an uncontrolled data dump. Upload browser traces, coverage, release mani

2 min
07

Docker Buildx Cache and Immutable Image Tags

Docker Buildx, Cache, and Immutable Image Tags Phase 32 created reproducible images. Phase 33 builds them in CI using Buildx and GitHub Actions cache. Every release image receives an immutab

2 min
08

GHCR GITHUB TOKEN and Release Manifests

GHCR, GITHUB_TOKEN, and Release Manifests GitHub Container Registry can be authenticated with the workflow-scoped GITHUB_TOKEN. Only the image-publishing job needs packages: write. A release

2 min
09

Secrets OIDC and Protected Environments

Secrets, OIDC, and Protected Environments Long-lived cloud keys in repository secrets are avoidable on providers that support GitHub OIDC. The deployment job requests a short-lived identity

2 min
10

Supply Chain Hardening Action Pinning and Dependabot

Supply-Chain Hardening: Action Pinning and Dependabot A GitHub Action executes code inside your workflow. GitHub recommends full-length commit SHA pinning as the immutable reference. The rea

2 min
11

Branch Protection Release Gates and Rollback Friendly Design

Branch Protection, Release Gates, and Rollback-Friendly Design CI becomes meaningful when protected branches require its checks before merge. Release and deployment pipelines should serializ

2 min
12

Hands On Lab and Phase Exit

Hands-On Lab and Phase Exit Implement CI, integration testing, and release-image workflows in a branch. Break each gate deliberately and prove it fails for the expected reason. Then restore

2 min
LAB

Guided Build Lab

Purpose Build a trustworthy GitHub Actions pipeline that verifies pull requests, creates immutable release artifacts, uses least privilege, caches safely, and controls deployment concurrency

3 min
LAB

Debugging Workshop

Goal Learn to diagnose this phase's failures systematically instead of reinstalling packages, changing random configuration, or copying a fix without understanding it.

2 min
LAB

Phase Synthesis & Independent Challenge

Mission Rebuild the capability of Phase 33 without following the exact code line-by-line. The goal is transfer: can you use the ideas when the variable names, UI, or route shape changes?

2 min
LAB

Mastery Capstone Lab

Integrate Phase 33 without following a transcript.

2 min
Practice ladder

Exercises that increase independence

Guided

Create CI triggered by pull_request with read-only contents permission and explicit concurrency cancellation.

Practice

Run lint/typecheck/tests/build as separate clear steps or jobs with understandable failure ownership.

Debug

reproduce and diagnose — Using pull_request_target with untrusted checkout/secrets.

Independent

deliver .github/workflows/ci.yml plus release/deploy workflows that build once, tag by commit SHA, and gate promotion.

Explain-back

Can read/write a GitHub Actions workflow and Can explain trigger trust boundaries.

Mastery gate

Do not leave the phase only because you reached the bottom

Phase exit criteria

Knowledge check

Scenario and concept quiz

These questions test engineering choices rather than whether you remember a lesson title.

0/0 correct · 0/8 answered
01Which practice best matches Phase 33's engineering goal?
02Which practice best matches Phase 33's engineering goal?
03Which practice best matches Phase 33's engineering goal?
04Which practice best matches Phase 33's engineering goal?
05You are working through the Phase 33 lab. Which next action is the most disciplined step?
06You are working through the Phase 33 lab. Which next action is the most disciplined step?
07You are working through the Phase 33 lab. Which next action is the most disciplined step?
08You are working through the Phase 33 lab. Which next action is the most disciplined step?
Source snapshot

Reference files

Attempt the work first. Use snapshots to compare a checkpoint, not as a substitute for understanding.

reference/TaskFlow_GitHub_Actions_Snapshot/.github/dependabot.yml
version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule:
      interval: weekly

  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: weekly
reference/TaskFlow_GitHub_Actions_Snapshot/.github/workflows/ci.yml
name: CI

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

permissions:
  contents: read

concurrency:
  group: ci-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  verify:
    runs-on: ubuntu-latest
    timeout-minutes: 20
reference/TaskFlow_GitHub_Actions_Snapshot/.github/workflows/deployment-gate.example.yml
name: Deployment Gate Example

on:
  workflow_dispatch:
    inputs:
      image_sha:
        description: Full commit SHA already published by release-images
        required: true

permissions:
  contents: read
  id-token: write

concurrency:
  group: production
  cancel-in-progress: false

jobs:
  gate:
    runs-on: ubuntu-latest
reference/TaskFlow_GitHub_Actions_Snapshot/.github/workflows/integration.yml
name: Integration Tests

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

permissions:
  contents: read

jobs:
  api-integration:
    runs-on: ubuntu-latest
    timeout-minutes: 25

    services:
      postgres:
        image: postgres:18
        env:
reference/TaskFlow_GitHub_Actions_Snapshot/.github/workflows/release-images.yml
name: Build Release Images

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read
  packages: write

concurrency:
  group: release-images-${{ github.ref }}
  cancel-in-progress: false

jobs:
  images:
    runs-on: ubuntu-latest
    timeout-minutes: 30
reference/TaskFlow_GitHub_Actions_Snapshot/CI_CD_ARCHITECTURE.md
# TaskFlow CI/CD Architecture

Pull request -> CI + integration tests -> merge protection -> main -> build immutable web/api images -> GHCR -> protected environment -> Phase 34 deployment.

Rules:
1. CI proves source.
2. Release builds one immutable artifact per commit.
3. Deployment promotes an already-built artifact; it does not rebuild source.
4. Production environment may require approval and exposes secrets only after protection rules pass.
5. Prefer OIDC to long-lived cloud credentials.
6. `GITHUB_TOKEN` gets only the permissions required by each workflow/job.
reference/TaskFlow_GitHub_Actions_Snapshot/README.md
# TaskFlow GitHub Actions Snapshot

This snapshot is educational and intentionally stops before actual cloud deployment. Phase 33 produces tested, immutable container candidates. Phase 34 connects those candidates to the selected hosting platform.

Workflow examples use current major action tags for readability. GitHub's security guidance recommends full-length commit SHA pinning for immutable third-party action references in hardened production repositories.
reference/TaskFlow_GitHub_Actions_Snapshot/SOURCES.md
# Sources used for Phase 33

- GitHub Docs: PostgreSQL service containers
- GitHub Docs: Secure use reference
- GitHub Docs: workflow syntax and GITHUB_TOKEN permissions
- GitHub Docs: OpenID Connect reference
- GitHub Docs: deployments, environments, concurrency
- Official action release pages for checkout, setup-node, upload-artifact
- Official Docker action release pages for setup-buildx, login, metadata, build-push
- pnpm/action-setup official releases
reference/TaskFlow_GitHub_Actions_Snapshot/VERSION_LOCK.md
# Phase 33 verified action lines (2026-09-18)

- actions/checkout: v7 line (latest observed v7.0.1)
- actions/setup-node: v7 line (latest observed v7.0.0)
- pnpm/action-setup: v6 line (latest observed v6.0.9)
- actions/upload-artifact: v7 line (latest observed v7.0.1)
- docker/setup-buildx-action: v4 line (latest observed v4.3.0)
- docker/login-action: v4 line (latest observed v4.6.0)
- docker/metadata-action: v6 line (latest observed v6.2.0)
- docker/build-push-action: v7 line (latest observed v7.2.0)

For production hardening, pin third-party actions to verified full commit SHAs and let Dependabot maintain them. The workflow examples use major tags for readability.
reference/TaskFlow_GitHub_Actions_Snapshot/tests/ci-cd-test-matrix.md
# Phase 33 verification matrix

- PR lint failure blocks CI.
- Type error blocks CI.
- Unit test failure blocks CI.
- PostgreSQL integration test uses committed migrations.
- Missing migration causes integration failure rather than schema drift.
- Docker build succeeds for web and API.
- Release image is tagged with full commit SHA.
- Release workflow has `packages: write` but CI does not.
- Production deployment concurrency prevents overlapping releases.
- Production environment can require approval before secrets are exposed.
- Workflow action dependencies are reviewed/pinned for production.
- Secrets are never echoed.
- Fork PRs do not receive production secrets.
- OIDC-based cloud auth is preferred over static cloud access keys.