Overview
This series teaches GitHub Actions through heavily annotated, self-contained code examples. Each example focuses on a single concept and includes inline annotations explaining what each line does, why it matters, and what value or state results from it.
Series Structure
The examples are organized into three levels based on complexity:
- Beginner — Core workflow syntax, basic triggers, single jobs, and fundamental step types
- Intermediate — Multi-job workflows, secrets, environment variables, matrices, and caching
- Advanced — Reusable workflows, custom actions, complex event handling, and deployment patterns
Structure of Each Example
Every example follows a consistent five-part format:
- Brief Explanation — what the workflow does and why it matters (2-3 sentences)
- Mermaid Diagram — visual representation of workflow execution, job dependencies, or trigger flow (when appropriate)
- Heavily Annotated YAML — workflow files with
# =>comments describing each directive and its effect - Key Takeaway — the core insight to retain from the example (1-2 sentences)
- Why It Matters — production relevance and real-world impact (50-100 words)
How to Use This Series
Each page presents annotated YAML workflow files. Read the annotations alongside the code to understand both the mechanics and the intent. The examples build on each other within each level, so reading sequentially gives the fullest understanding.
Examples by Level
Beginner (Examples 1–28)
- Example 1: Minimal Workflow File
- Example 2: Workflow Name and Job Name
- Example 3: The
onKey with a Single Event - Example 4: The
pushTrigger - Example 5: The
pull_requestTrigger - Example 6: Multiple Triggers on One Workflow
- Example 7: Branch Filters on
push - Example 8: Path Filters on
push - Example 9: The
scheduleTrigger (Cron Syntax) - Example 10: The
workflow_dispatchTrigger (Manual Run) - Example 11: Ubuntu, Windows, and macOS Runners
- Example 12: Pinning a Specific Runner Version
- Example 13: The
runStep with Multi-Line Commands - Example 14: The
usesStep withactions/checkout - Example 15: The
usesStep withactions/setup-node - Example 16: The
usesStep withactions/setup-python - Example 17: Passing Inputs to Actions with
with - Example 18: Setting
envat the Workflow Level - Example 19: Setting
envat the Job Level - Example 20: Setting
envat the Step Level - Example 21: Changing the Working Directory for
runSteps - Example 22: Skipping Steps with
ifConditionals - Example 23:
ifon Jobs - Example 24: Sequential Jobs with
needs - Example 25: Accessing Outputs from Required Jobs
- Example 26: Setting
timeout-minutes - Example 27: Using
continue-on-error - Example 28: Combining Triggers, Env, Needs, and Conditionals
Intermediate (Examples 29–57)
- Example 29: Secrets Context
- Example 30: Environment Variables at Workflow, Job, and Step Level
- Example 31: strategy.matrix for Cross-Platform Builds
- Example 32: Matrix Include and Exclude
- Example 33: actions/cache for Build Dependencies
- Example 34: actions/cache for Go Modules
- Example 35: actions/upload-artifact and download-artifact
- Example 36: Job Outputs Passed to Downstream Jobs
- Example 37: needs with Conditional Execution
- Example 38: Concurrency Groups
- Example 39: Per-Job Concurrency Groups
- Example 40: permissions Key and GITHUB_TOKEN
- Example 41: success(), failure(), always(), cancelled()
- Example 42: github Context
- Example 43: env, steps, job, and runner Contexts
- Example 44: hashFiles() Built-in Function
- Example 45: fromJSON() and toJSON() Functions
- Example 46: Services (Docker Containers as Test Dependencies)
- Example 47: Container Jobs
- Example 48: Local Composite Action
- Example 49: workflow_call Trigger (Reusable Workflows Basics)
- Example 50: github.event Context Details
- Example 51: repository_dispatch Trigger
- Example 52: Environment Protection Rules
- Example 53: Expressions — Operators and Built-in Functions
- Example 54: Multi-Stage Pipeline with All Contexts
- Example 55: Passing Secrets Across Jobs with Inherited Secrets
- Example 56: Dynamic Matrix from Step Output
- Example 57: Combining Services, Containers, and Artifacts
Advanced (Examples 58–85)
- Example 58: Reusable Workflow with Inputs, Outputs, and Secrets
- Example 59: Composite Action in action.yml
- Example 60: JavaScript Action with action.yml and index.js
- Example 61: Docker Container Action
- Example 62: Matrix with include/exclude and Dynamic fromJSON
- Example 63: Workflow Chaining with workflow_run
- Example 64: Deployment Environments with Required Approvals
- Example 65: OIDC Federated Identity for AWS (No Long-Lived Credentials)
- Example 66: OIDC for GCP and Azure
- Example 67: Self-Hosted Runners and Runner Groups
- Example 68: GitHub Apps for Workflow Authentication
- Example 69: GitHub API in Workflows with gh CLI and Octokit
- Example 70: Release Automation with Semantic Release
- Example 71: Monorepo CI with Path Filters and Conditional Jobs
- Example 72: Advanced Dependency Caching Strategies
- Example 73: Build Artifact Retention and Cross-Job Sharing
- Example 74: Security Hardening — Pin Actions to SHA and Least-Privilege Permissions
- Example 75: Workflow Dispatch with Complex Inputs
- Example 76: Caching Build Outputs for Incremental Compilation
- Example 77: Artifact Attestation and SLSA Provenance
- Example 78: Large Runner Features and GPU Workflows
- Example 79: Concurrency Control and Workflow Cancellation
- Example 80: Status Checks and Branch Protection Integration
- Example 81: Debugging Workflows with tmate and Step Summaries
- Example 82: Calling GitHub REST API with Pagination
- Example 83: Workflow Job Dependencies and Fan-Out/Fan-In Patterns
- Example 84: OpenID Connect Token Claims and Advanced Trust Policies
- Example 85: Complete Production Workflow — Integration of All Advanced Patterns
Last updated March 19, 2026