GitHub Actions study materials
GitHub Actions study resources

GitHub Actions cheat sheet

GitHub Actions ยท Keep the key ideas within reach.

Quick reference

Workflow creation

  • A workflow is a YAML file in .github/workflows/ of the repository; GitHub discovers every .yml/.yaml file there on the default branch and on branches that contain it for push/pull_request events.

  • Top-level keys: name, run-name, on, permissions, env, defaults, concurrency, jobs. Unknown top-level keys fail validation with an 'Invalid workflow file' error.

  • on accepts a single event, a list of events, a schedule cron list, or a map with filters such as branches, branches-ignore, paths, paths-ignore, and types.

  • Job identifiers must start with a letter or underscore and contain only alphanumeric characters, '-' and '_'; the identifier, not name, is what needs references.

  • Steps run sequentially inside a job; each run step is a separate shell process, so shell variables do not persist between steps - use $GITHUB_ENV or $GITHUB_OUTPUT to pass values.

  • Expression syntax ${{ }} is evaluated by the runner before the step executes; contexts include github, env, vars, secrets, inputs, matrix, needs, steps, job, and runner.

  • permissions can be set workflow-wide or per job; setting any permission switches all unspecified scopes to none, so list every scope the job needs.

  • Reusable workflows are called with uses: owner/repo/.github/workflows/file.yml@ref at job level and receive values through with: mapped to on.workflow_call.inputs.

Quick reference

Automation

  • Event payload is available at $GITHUB_EVENT_PATH as JSON; github.event_name and github.event.action identify the trigger, and types: filters which actions fire the workflow.

  • schedule uses POSIX cron in UTC; the shortest interval is 5 minutes, and scheduled runs on the default branch are disabled automatically after 60 days of repository inactivity.

  • workflow_dispatch supports typed inputs (string, choice, boolean, environment) exposed via the inputs context; repository_dispatch accepts an arbitrary client_payload.

  • Concurrency group ${{ github.workflow }}-${{ github.ref }} with cancel-in-progress: true supersedes stale runs; without cancel-in-progress, at most one running and one pending run are kept.

  • GITHUB_TOKEN scopes come from the permissions block, are limited to the repository, and expire when the job finishes; a job cannot use GITHUB_TOKEN to trigger another workflow run.

  • GITHUB_STEP_SUMMARY writes Markdown to the run summary page; ::warning::, ::error::, and ::notice:: workflow commands create annotations.

  • Path and branch filters are ANDed across categories but ORed within a list; a workflow skipped by filters leaves the check in a pending state that can block required status checks.

  • Self-hosted runners are selected by runs-on labels; they do not receive automatic security updates and keep no state between jobs unless configured otherwise.

Quick reference

CI/CD pipeline management

  • Job graph is defined by needs; jobs without dependencies run in parallel, and a failed job skips dependents unless they use if: always() or if: failure().

  • strategy.matrix expands a job per combination; include adds or augments combinations, exclude removes them, and fail-fast: false lets other legs finish after one fails.

  • actions/cache restores by key with optional restore-keys prefix fallback; caches are immutable once written, so the key must encode a hash of the lockfile to refresh.

  • actions/upload-artifact and download-artifact move files between jobs; artifacts persist for a retention period (default 90 days) and are scoped to the run.

  • if conditions are evaluated before matrix expansion for job-level conditions and can reference success(), failure(), cancelled(), always(), and github.ref.

  • Environments add protection rules (required reviewers, wait timers, deployment branch policies); secrets scoped to an environment are only available to jobs that declare environment:.

  • continue-on-error: true at step or job level marks the result as a failure that does not fail the run; steps.<id>.outcome records the raw result while conclusion records the post-continue result.

  • Required status checks match by job name, so renaming a job breaks branch protection until the rule is updated; skipped jobs report success for path-filtered workflows only when configured as such.

Quick reference

Intermediate practice for DevOps and developers

  • Secrets are not passed to workflows triggered from forks; pull_request_target runs in the base repository context with secrets, so never check out and execute untrusted PR code under it.

  • Pin third-party actions to a full commit SHA for supply-chain safety; a tag such as @v4 is mutable and can be repointed.

  • Default GITHUB_TOKEN permissions depend on repository/org settings; declare an explicit least-privilege permissions: block rather than relying on the default.

  • OIDC federation (permissions: id-token: write) lets a job assume a cloud role without long-lived credentials; the token is short-lived and bound to the workflow ref and environment.

  • actions/checkout defaults to fetch-depth: 1; set fetch-depth: 0 for tools that need history or tags, and set persist-credentials: false when the token must not remain in git config.

  • Composite actions group steps in action.yml with runs.using: composite; they cannot use uses at the top level of the action but can call other actions inside steps.

  • Debugging: re-run with debug logging enabled by setting the ACTIONS_STEP_DEBUG secret to true; ACTIONS_RUNNER_DEBUG adds runner-level diagnostics.

  • Job containers and service containers share a network namespace, so a service is reachable on its label hostname (for example postgres:5432) from steps in the job.

Quick reference

CI/CD pipeline management

  • Workflow run statuses progress queued โ†’ in_progress โ†’ completed with conclusion success, failure, cancelled, skipped, or timed_out; if: functions read these states within a run.

  • timeout-minutes defaults to 360 per job and 6 hours per step is not configurable; a hung step consumes the job timeout and is cancelled at the limit.

  • strategy.max-parallel caps concurrent matrix legs independently of the total matrix size, which matters on limited self-hosted capacity.

  • A job that is skipped because of needs reports skipped, which satisfies required checks only if the branch protection rule allows skipped jobs; otherwise the PR stays blocked.

  • workflow_run triggers a follow-up workflow after another completes and can read github.event.workflow_run.conclusion to gate deployment on success.

  • Rollback strategy: deploy by immutable artifact or image digest produced in the build job, so re-deploying a prior digest requires no rebuild.

  • environment deployments record a deployment history and URL; steps.deployment.outputs.page_url style outputs come from the action performing the deploy, not from GitHub itself.

  • Manual approval gates live in environment protection rules, not in workflow YAML; the YAML only declares the environment name.

Quick reference

Intermediate practice for DevOps and developers

  • actions/setup-node, setup-python, and setup-java read version files (package.json engines, .python-version, pom.xml) when node-version-file, python-version-file, or java-version-file is supplied.

  • Dependency caching built into setup actions keys on the lockfile hash; for monorepos set cache-dependency-path to the relevant lockfile.

  • GITHUB_OUTPUT, GITHUB_ENV, GITHUB_PATH, and GITHUB_STEP_SUMMARY are per-step files; writing name=value to GITHUB_OUTPUT creates a step output, while multiline values need a delimiter heredoc.

  • env precedence: step-level overrides job-level, which overrides workflow-level; the vars context holds non-secret configuration variables set at repo, environment, or org level.

  • act runs workflows locally in Docker but does not replicate GitHub-hosted runner images or secret scoping exactly, so treat local results as indicative only.

  • github.sha on a pull_request event is the merge commit, not the head commit; use github.event.pull_request.head.sha when the PR head is required.

  • Masking: any value matching a registered secret is redacted in logs, but derived or transformed values (base64, substrings) are not masked automatically.

  • Job-level if runs before the runner is allocated; runner context is unavailable there, so conditions on runner OS must use matrix or runs-on values instead.