GitHub Actions Cheatsheet
Workflow Syntax
Use this GitHub Actions reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Top-Level Keys
| Key | Required | Description |
|---|---|---|
name | no | Display name in the Actions UI |
on | yes | Event(s) that trigger the workflow |
env | no | Workflow-level environment variables |
defaults | no | Default run shell and working directory |
concurrency | no | Cancel or queue duplicate runs |
permissions | no | GITHUB_TOKEN permission overrides |
jobs | yes | Map of job IDs to job definitions |
on — Trigger Syntax
# Single event
on: push
# Multiple events
on: [push, pull_request]
# Event with filters
on:
push:
branches: [main, 'release/**']
branches-ignore: ['dependabot/**']
tags: ['v*']
paths: ['src/**', '!src/**/*.test.ts']
pull_request:
types: [opened, synchronize, reopened]
schedule:
- cron: '0 6 * * 1-5'
workflow_dispatch:
inputs:
environment:
description: 'Target environment'
required: true
default: staging
type: choice
options: [staging, production]env — Environment Variables
# Workflow level env: NODE_ENV: test API_URL: https://api.example.com jobs: build: # Job level (merges with workflow env) env: LOG_LEVEL: debug steps: - run: echo "NODE_ENV=$NODE_ENV" # Step level (highest precedence) env: NODE_ENV: production
defaults
defaults:
run:
shell: bash
working-directory: ./appPer-job override:
jobs:
build:
defaults:
run:
working-directory: ./packages/coreconcurrency
# Cancel in-progress runs for the same branch concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # Queue instead of cancel (omit cancel-in-progress or set false) concurrency: group: deploy-production cancel-in-progress: false
jobs — Job Keys
| Key | Required | Description |
|---|---|---|
runs-on | yes | Runner label(s) |
steps | yes* | Ordered list of steps (*or uses for reusable workflows) |
needs | no | Job dependencies (run after these job IDs) |
if | no | Conditional expression |
env | no | Job-level env vars |
outputs | no | Values passed to dependent jobs |
strategy | no | Matrix / fail-fast config |
timeout-minutes | no | Job timeout (default 360) |
continue-on-error | no | true = don't fail workflow if job fails |
services | no | Docker service containers |
container | no | Run all steps inside a container |
permissions | no | Per-job GITHUB_TOKEN scopes |
environment | no | Deployment environment (gates, URLs) |
concurrency | no | Job-level concurrency group |
steps — Step Keys
| Key | Description |
|---|---|
name | Display label |
id | Reference in steps.<id>.outputs |
uses | Action reference (owner/repo@ref) |
run | Shell command(s) |
with | Input parameters for uses |
env | Step-level env vars |
if | Conditional |
continue-on-error | Allow step failure without failing job |
timeout-minutes | Step timeout |
working-directory | Override working dir for run |
shell | Override shell for run |
Expressions
# Syntax: ${{ <expression> }}
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
# Functions
${{ contains(github.event.head_commit.message, '[skip ci]') }}
${{ startsWith(github.ref, 'refs/tags/v') }}
${{ toJSON(matrix) }}
${{ fromJSON(steps.meta.outputs.json).version }}
${{ format('Hello {0}', github.actor) }}
${{ join(matrix.os, ', ') }}
# Status functions (use in if: without ${{ }})
if: success()
if: failure()
if: always()
if: cancelled()
if: failure() && steps.build.conclusion == 'failure'Outputs
jobs:
build:
outputs:
version: ${{ steps.get-version.outputs.version }}
steps:
- id: get-version
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
deploy:
needs: build
steps:
- run: echo "Deploying ${{ needs.build.outputs.version }}"Multi-line run
- run: |
echo "Line 1"
echo "Line 2"
npm ci
npm testSetting Output / Env from a Step
# Set output echo "my-key=my-value" >> $GITHUB_OUTPUT # Set env var for subsequent steps echo "MY_VAR=hello" >> $GITHUB_ENV # Add to PATH echo "/custom/bin" >> $GITHUB_PATH # Step summary (rendered Markdown in the UI) echo "## Build Summary" >> $GITHUB_STEP_SUMMARY echo "| Key | Value |" >> $GITHUB_STEP_SUMMARY
services — Docker Sidecars
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- run: psql -h localhost -U postgres -c '\l'
env:
PGPASSWORD: postgres