GitHub Actions — Intermediate
Composite Actions — Packaging Multiple Steps as One
A sequence of steps repeated across many workflows (checkout, setup, run a specific lint config) is a real duplication problem — a composite action packages multiple steps into a single, reusable action, callable as one line in any workflow:
shell: bash is required on every run: step inside a composite action — unlike a normal workflow step, composite actions don't inherit a default shell, and omitting it is a common, confusing first-time error.
Job Outputs — Passing Data Between Jobs
Jobs run in isolated runners by default and don't share state — outputs is the mechanism for a downstream job to consume a value a previous job computed:
>> "$GITHUB_OUTPUT" is the current mechanism for setting a step output — the older ::set-output:: workflow command syntax is deprecated, worth knowing since older workflow examples online still use it.
Environment Protection Rules — Gated Deploys
Beyond a bare environment: production declaration, protection rules turn an environment into an actual approval gate — required reviewers, a wait timer, or branch restrictions, configured per-environment in repo settings:
Environment secrets (distinct from repository or organization secrets) are also scoped by these same protection rules — a secret defined at the environment level is only readable by a job that's actually deploying to that protected environment, which is what makes environment-scoped secrets meaningfully more restrictive than repository-wide ones.
Concurrency Control — Preventing Overlapping Runs
Multiple pushes to the same branch in quick succession can trigger multiple overlapping workflow runs, wasting runner capacity on now-superseded work:
For a deploy workflow specifically, cancel-in-progress: true needs care — cancelling a deploy job mid-flight can leave infrastructure in a partially-applied state, so this is often set true for CI/test workflows but deliberately false (queue instead of cancel) for deploy workflows where mid-flight cancellation is actively dangerous.
Reusable Workflows with Secrets
Beyond the basic workflow_call pattern from Fundamentals, a reusable workflow can explicitly declare which secrets it needs, making the secret-passing contract visible rather than implicit:

