GitHub Actions study materials
GitHub Actions study resources

GitHub Actions: CI/CD pipeline management: graphs, matrices, and deployments

GitHub Actions · Work through your exam, one topic at a time.

All guide sections

CI/CD pipeline management: graphs, matrices, and deployments

What this domain tests

This domain is about the pipeline shape rather than a single job: dependency graphs, matrix expansion, reusable workflows, and the deployment controls (environments, approvals, concurrency, OIDC) that make a release safe to automate.

Job graphs and matrices

  • needs defines the DAG; a downstream job waits for all listed jobs and is skipped if any of them fail unless its if says otherwise.
  • Job outputs are written to $GITHUB_OUTPUT and read as needs.<job>.outputs.<name>. Outputs containing secrets are skipped, so the value arrives empty.
  • A matrix can produce at most 256 jobs per workflow run. exclude removes combinations; include adds keys to matching combinations and creates extra jobs for entries that match none.
  • fail-fast: false lets the remaining matrix legs finish so you see every failure at once; max-parallel limits concurrent legs.

Reusable workflows versus composite actions

  • Reusable workflows use on: workflow_call and are called at job level with uses: org/repo/.github/workflows/x.yml@ref, passing with: and secrets: inherit. Nesting is limited to four levels.
  • Composite actions (runs: using: composite) wrap steps and cannot receive secrets directly.

Environments and deployment control

  • Adding environment: to a job unlocks environment secrets and protection rules: required reviewers, wait timers, and allowed deployment branches.
  • Use permissions: id-token: write plus a cloud trust policy for OIDC instead of stored long-lived keys.
  • Put concurrency on deploy jobs with cancel-in-progress: false so a release in flight is never cut off.

Worked example

jobs:
  build:
    runs-on: ubuntu-latest
    outputs: {tag: "${{ steps.meta.outputs.tag }}"}
    steps:
      - id: meta
        run: echo "tag=${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
  deploy:
    needs: build
    if: needs.build.outputs.tag != ''
    environment: ${{ matrix.env }}
    strategy: {matrix: {env: [staging, production]}, max-parallel: 1}
    concurrency: {group: deploy-${{ matrix.env }}, cancel-in-progress: false}
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh ${{ needs.build.outputs.tag }}

Reasoning: build once and promote the same tag; the if guard catches an empty output instead of deploying undefined; per-environment concurrency serialises deploys while allowing staging and production to differ.

Traps that cost marks

  • matrix.include adding a stray key can create an extra unintended job.
  • Environment protection rules only apply when the job declares environment:; environment secrets are invisible otherwise.
  • Artifacts must be uploaded and downloaded explicitly between jobs - runners share no filesystem.
  • cancel-in-progress: true on a production deploy group can kill a release mid-rollout.