Beginner
Quick reference for GitHub Actions — workflow syntax, triggers, jobs and steps, matrix builds, secrets, caching, artifacts, permissions, expressions, and useful context variables.
CI/CDWorkflowsRunnersSecrets
Workflow Skeleton
Minimal file
# .github/workflows/ci.yml
name: CI
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm test
Triggers
on:
push:
branches: [main]
paths: ["src/**"]
pull_request:
branches: [main]
schedule:
- cron: "0 6 * * *" # daily 06:00 UTC
workflow_dispatch: # manual run
workflow_call: # reusable
Common events
| Event |
Fires on |
push | Commit to branch/tag |
pull_request | PR opened/updated |
schedule | Cron (UTC) |
workflow_dispatch | Manual button |
Jobs & Steps
Dependencies
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
deploy:
needs: test # wait for test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
Runners
runs-on: ubuntu-latest # windows-latest, macos-latest
runs-on: [self-hosted, linux, gpu]
Matrix
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
node: ["20", "22"]
runs-on: ${{ matrix.os }}
Secrets & Permissions
permissions:
contents: read
pull-requests: write
steps:
- run: ./deploy.sh
env:
TOKEN: ${{ secrets.API_TOKEN }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
environment: production # protection rules apply
Cache & Artifacts
Cache
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: npm-${{ runner.os }}-
Artifacts
- uses: actions/upload-artifact@v4
with: { name: dist, path: dist/ }
- uses: actions/download-artifact@v4
with: { name: dist }
Contexts & Expressions
| Expression |
Value |
github.ref | Branch/tag ref |
github.sha | Commit SHA |
github.event_name | Trigger event |
runner.os | Linux / Windows / macOS |
secrets.NAME | A stored secret |
Step conditions
if: success() # default
if: failure() # run only if a prior step failed
if: always() # run regardless
if: github.event_name == 'push'