CloudOpsGuide
ci-cd

GitHub Actions Deep Dive: Workflows, Matrix Builds, and Secrets

Intermediate
13 minutes
October 2026
CloudOpsGuide Team

GitHub Actions Deep Dive: Workflows, Matrix Builds, and Secrets

GitHub Actions looks simple until you need matrix builds, reusable workflows, and environment protection rules. This is the deeper tour — the syntax and features you reach for after the quickstart.

Table of Contents

Anatomy: where things live

Workflows are YAML files in .github/workflows/. That's the hard rule — anywhere else and GitHub won't see them. A workflow has events that trigger it (on:), jobs that run in parallel by default, and steps inside each job that run sequentially on one runner.

name: ci
on:
  push:
    branches: [main]
  pull_request:
  workflow_dispatch:        # manual button
  schedule:
    - cron: "0 6 * * 1"     # Monday 06:00 UTC

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test

Contexts and expressions

${{ }} expressions pull from contexts — the runtime data model:

${{ github.sha }}            # commit that triggered
${{ github.ref_name }}        # branch/tag name
${{ github.actor }}           # who triggered it
${{ github.event_name }}      # push, pull_request, ...
${{ runner.os }}              # Linux/Windows/macOS
${{ secrets.AWS_KEY }}        # stored secrets
${{ vars.APP_ENV }}           # repo/environment variables
${{ job.status }}             # running status

Print the whole event payload when debugging: run: echo '${{ toJSON(github) }}'.

Matrix builds: test everything at once

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest]
        node: [20, 22]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci && npm test

Four jobs, two lines of matrix. fail-fast: false keeps other combos running when one fails.

Job dependencies, artifacts, and outputs

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.v.outputs.version }}
    steps:
      - id: v
        run: echo "version=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
      - uses: actions/upload-artifact@v4
        with: { name: dist, path: dist/ }

  deploy:
    needs: build                              # waits for build
    environment: production                   # gates + secrets scoping
    steps:
      - uses: actions/download-artifact@v4
        with: { name: dist }
      - run: echo "deploying ${{ needs.build.outputs.version }}"

Secrets and environments

Settings → Secrets and variables → Actions: repo secrets for everything, environment secrets scoped to deploy targets. Attach protection rules to an environment: — required reviewers, restricted branches — and a deploy job pauses for approval before running.

For cloud auth, skip static keys entirely: use OIDC federation with permissions: id-token: write and assume a short-lived role. No secrets in GitHub at all.

Caching: the speed knob

- uses: actions/setup-node@v4
  with:
    node-version: 22
    cache: npm          # one line: restores node_modules by lockfile hash

For anything else, actions/cache with a key derived from the dependency lockfile. Uncached CI is slow CI.

Starter workflows and reuse

GitHub suggests ready-made workflows in Actions → New workflow (the actions/starter-workflows repo powers this). For organization-wide patterns, reusable workflows (on: workflow_call) let one canonical pipeline serve every repo.

Pitfalls worth knowing

  • Workflows only run on the branch/tag rules you give on: — a typo silently disables CI.
  • pull_request from forks runs with read-only tokens and no secrets (by design, for security).
  • Each job gets a fresh VM — pass state via artifacts, not the filesystem.
  • Pin actions to major versions (@v4) or full SHAs for supply-chain safety.

Start from a starter workflow, then grow into matrix builds and OIDC deploys as the need arrives — Actions rewards incremental adoption.

Related Articles


Last Updated: October 2026 Author: CloudOpsGuide Team Difficulty: Intermediate Estimated Reading Time: 13 minutes