120 companion flashcards · AI-assisted study content · Open the deck →
This deck is a hands-on collection of recipes and quick answers for working with GitHub Actions, the automation platform built into GitHub. It walks through the core building blocks of a workflow, including jobs, steps, runners, and the various events that can trigger a run. You will also find practical guidance on scheduling jobs with cron expressions and filtering triggers by branch, which are essential skills for setting up reliable CI/CD pipelines.
The cards are ideal if you are getting started with continuous integration and deployment on GitHub, preparing for a DevOps or developer interview, or just want a fast reference to revisit when configuring your own repositories. Because the questions focus on definitions, syntax, and common patterns, the deck works best alongside a real project where you can experiment with writing and modifying actual workflow files in your editor of choice.
To get the most out of this material, try answering each card out loud before flipping it over, and follow up by opening a sample repository to practice writing the YAML yourself. Spacing your reviews across several short sessions, rather than cramming, will help the syntax details like cron expressions and trigger filters stick in long-term memory. Treat each card as a prompt to explore the topic a little further in the official documentation when something feels unfamiliar.
GitHub Actions is a CI/CD and workflow automation platform built directly into GitHub. It allows you to run jobs in response to repository events using workflows that are defined in YAML files. These workflow files use either the .yaml or .yml extension and live under the .github/workflows/ directory inside your repository, where GitHub automatically discovers them.
At the top of the YAML hierarchy sits the workflow, which is an automated, configurable process that runs one or more jobs whenever a triggering event occurs. A job is a set of steps that all execute on the same runner, and by default jobs run in parallel with one another. Each step inside a job is either a shell command declared with run: or an invocation of an action declared with uses:. The runner itself is the server that executes the job; GitHub-hosted runners come in Ubuntu, Windows, and macOS flavors, while self-hosted runners are machines that you provision and register with your repository or organization.
The simplest workflow therefore has the shape of a workflow block with an on: trigger clause, a jobs: section listing one or more jobs, and within each job a sequence of steps that either run commands or invoke actions such as actions/checkout@v4, which checks your repository code out onto the runner so subsequent steps can operate on it.
Every workflow must begin with an on: clause that lists the events which cause it to run. Common triggers include push, pull_request, and workflow_dispatch. The workflow_dispatch event in particular allows a workflow to be started manually from the Actions tab in the GitHub UI, from the REST API, or from the GitHub CLI, making it a convenient hook for on-demand jobs.
Scheduled runs are configured with on: schedule:, which accepts POSIX cron syntax evaluated against UTC. For example, on: schedule: - cron: '30 2 * * *' would run the workflow daily at 02:30 UTC. Push and pull_request triggers can be narrowed with branch filters, such as on: push: branches: [main] to limit runs to commits pushed to the main branch, or on: pull_request: branches: [main, develop] to scope pull request runs to those target branches. By default both events run on all branches, but explicit branches or paths filters quickly override that behavior.
Path-based filtering offers finer control. The paths: filter under on: push restricts the trigger to commits that change files matching the given glob patterns, while paths-ignore: excludes commits that modify the listed patterns. Together, these allow you to keep expensive workflows from running when only unrelated files such as documentation or images have been touched.
A job is identified by a key under jobs: and is configured with runs-on: to declare which runner label it should use, such as ubuntu-latest. Jobs run in parallel by default, but you can express dependencies between them with needs: job_id. By default, dependent jobs only run after the named needs job completes successfully, providing a straightforward way to express sequenced pipelines.
For repetitive jobs, the matrix strategy lets you run the same job multiple times in parallel with different variable combinations, defined under jobs.
Conditional execution is controlled with the if: key on jobs and steps. The expressions success(), failure(), always(), and cancelled() are particularly useful: success() runs only when previous steps or jobs succeeded, failure() runs only when something failed, always() runs regardless of outcome, and cancelled() runs only when the workflow was cancelled. Concurrency, configured at the workflow level, provides another control knob, grouping runs so that duplicate executions of the same workflow on the same branch cancel one another, typically with cancel-in-progress: true.
Environment variables can be set at three scopes. A step-level env: block applies only to that step, a job-level env: applies to all steps within the job, and a workflow-level env: placed under on: and above jobs: applies to every step in every job. The default working directory is the repository root, also known as GITHUB_WORKSPACE, which can be overridden with working-directory: at the job or step level.
Steps and jobs exchange data through outputs. A step declares its outputs in its id block, and downstream steps read them with ${{ steps.step_id.outputs.output_name }}. Jobs similarly declare outputs under jobs.
The shell used by run: defaults to bash on Linux runners and can be changed per step with shell: pwsh, shell: sh, shell: python, and so on, or globally for a job with defaults.run.shell. Multiline scripts are written with a pipe block under run: or a heredoc inside the script. Conditional steps can read these context variables directly, such as if: github.event_name == 'pull_request' to run only on pull requests, or if: "! contains(github.event.head_commit.message, '[skip ci]')" to skip workflows based on commit message patterns.
Every workflow run is automatically provisioned with a GITHUB_TOKEN, which is used to authenticate with the GitHub API. The default scope of this token is read-only on most permissions, so any workflow that needs to write back to the repository or otherwise perform privileged actions must explicitly elevate its permissions. The permissions: key, usable at both workflow and job level, controls this; permissions: contents: read grants read-only repository content access, permissions: read-all grants read-only access across all available scopes, and job-level settings override workflow-level settings.
When a workflow needs to commit and push code as part of its automation, a common pattern is to set permissions: contents: write on the job, configure git with the recommended bot identity github-actions[bot] and the email 41898282+github-actions[bot]@users.noreply.github.com, and then use the GITHUB_TOKEN for authentication. The peter-evans/create-pull-request action is a popular tool for automating the creation of pull requests from a branch after commits are pushed.
Security considerations are especially important around pull_request events. The pull_request_target trigger runs in the base repository context with write permissions and is a frequent source of script injection attacks, so it should be used with extreme caution. Self-hosted runners on public repositories carry a similar risk: malicious pull requests from forks can run untrusted code on your own infrastructure. The standard mitigations are to require approval for first-time contributors, use fork-PR approval settings, and prefer ephemeral runners. GitHub-hosted runners, by contrast, start fresh for each job and have open egress to the public internet, so private networking requires a self-hosted runner.
Workflows often need to share files between jobs or expose build outputs for download. Artifacts serve this role: actions/upload-artifact@v4 stores files under a name: and path:, and a later job retrieves them with actions/download-artifact@v4. Repository artifacts are retained for 90 days by default, after which they are deleted. Each individual artifact is capped at 10 GB and the total upload per workflow run is also limited to 10 GB across all artifacts, so larger outputs need to be handled through GitHub Packages or external storage.
Caching speeds up builds by reusing dependencies between runs. The actions/cache@v4 action stores files keyed by a combination of path and key, with hashFiles() used to generate keys that invalidate automatically when dependency manifests change. For example, a key like \({{ runner.os }}-npm-\){{ hashFiles('**/package-lock.json') }} will produce a fresh cache whenever package-lock.json changes. The key is an exact match for upload and download, while restore-keys: provides comma-separated prefix matches as a fallback when the exact key is missing. Many setup actions, including actions/setup-node@v4 with cache: 'npm' and actions/setup-go@v5 with cache: true, integrate this caching automatically based on lockfile hashes.
Jobs that need databases or other backing services can declare them under services:, which spins up additional containers alongside the job. A PostgreSQL service, for instance, can be started with services: postgres: image: postgres:16 env: POSTGRES_PASSWORD: postgres ports: ['5432:5432'], and health checks added through options: like --health-cmd="pg_isready" ensure the service is ready before the job proceeds. The job and its services share a custom network where services are reachable by their service name as host.
GitHub Actions supports reuse at two levels. Within a single workflow, an action invoked at the step level with uses: is a reusable unit of work, with inputs passed through with: and outputs referenced through steps.step_id.outputs. Across workflows, a reusable workflow is invoked at the job level with uses: owner/repo/.github/workflows/file.yml@ref, allowing whole pipelines to be shared between repositories. A reusable workflow is triggered by the on: workflow_call: event, can declare inputs under on.workflow_call.inputs, and accepts secrets either explicitly through secrets: NAME in the with: block or with secrets: inherit to forward them all from the caller.
Deployments typically use the environment: key on a job, which links the job to a named deployment environment with its own secrets, protection rules, and URL. A deployment protection rule gates deployments to that environment, often requiring manual approval or a passing status check before a production job is allowed to proceed. A common release-driven pattern uses on: release: types: [published] as a trigger, paired with a job using environment: production to publish artifacts once a GitHub Release is created, distinguishing the GitHub Release object (which wraps a git tag with notes and assets) from a plain git tag.
Most language ecosystems have dedicated setup actions that bootstrap the toolchain in a single step. actions/setup-node@v4 with node-version: '20.x' installs Node.js, actions/setup-python@v5 with python-version: '3.12' installs Python, actions/setup-java@v4 with distribution: 'temurin' and java-version: '21' sets up a JDK, and actions/setup-go@v5 with go-version: '1.22' cache: true installs Go with automatic module caching. These actions, like actions/checkout, are best pinned to a full-length commit SHA in production workflows rather than to floating tags like @v4 or branches like @main, which trade stability for convenience. When pinning third-party actions, the recommended pattern is uses: owner/action@full_commit_sha, ensuring that updates to the action cannot silently change your pipeline behavior.
Drill this topic
120 flashcards on GitHub Actions CI/CD Recipes — free, no signup needed to start.
Study GitHub Actions CI/CD Recipes flashcardsLearnWiki pages are generated with AI assistance from LearnCoachAssist's reviewed study catalog and may contain errors — verify anything critical against your course materials.