GitHub Actions
Write your first GitHub Actions workflow — triggers, jobs, steps, and runners
Knowledge Debt detected
You can study this freely — but your score may plateau if these foundations have gaps. The Mastery badge requires them to be solid.
Explanation
GitHub Actions is GitHub's built-in CI/CD platform. Workflows live in your repo as YAML files, trigger on events (push, PR, schedule), and run on GitHub-hosted machines.
Workflow file location:
.github/ workflows/ ci.yml # your workflow file deploy.yml # another workflow
Anatomy of a workflow:
yaml name: CI # display name (optional) on: # triggers push: branches: [main] pull_request: branches: [main] jobs: # one or more jobs test: # job id (arbitrary name) runs-on: ubuntu-latest # which runner (OS) steps: # ordered list of steps - uses: actions/checkout@v4 # checkout the repo - uses: actions/setup-python@v5 # install Python with: python-version: '3.12' - run: pip install -r requirements.txt - run: pytest
Key concepts:
| Concept | Meaning | |---------|---------| | on | When the workflow triggers — push, PR, schedule, or manual | | jobs | Independent units of work; run in parallel by default | | steps | Sequential actions within a job | | uses | Reference a reusable action from the marketplace | | run | Execute a shell command | | runs-on | The OS for the runner (ubuntu-latest, macos-latest, windows-latest) |
Triggering on specific branches or paths:
yaml on: push: branches: [main, develop] paths: ['src/**', 'tests/**'] # only trigger if these paths changed pull_request: branches: [main] schedule: - cron: '0 2 * * *' # nightly at 2 AM UTC workflow_dispatch: # allow manual trigger from GitHub UI
Multiple jobs (parallel execution):
yaml jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: pip install flake8 && flake8 . test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: pip install -r requirements.txt && pytest # lint and test run at the same time (parallel)
Job dependencies (sequential):
yaml jobs: test: runs-on: ubuntu-latest steps: [...] deploy: needs: test # deploy only runs after test passes runs-on: ubuntu-latest steps: [...]
Examples
Minimal Python CI workflow
Every PR to main will now automatically run this. Red = do not merge. Green = code works.
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Lint
run: flake8 . --max-line-length=100
- name: Run tests
run: pytest --tb=short -qNode.js workflow with multiple parallel jobs
Parallel jobs mean CI completes in the time of the slowest job, not the sum of all jobs.
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm test
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20', cache: 'npm' }
- run: npm ci && npx tsc --noEmit
# lint, test, typecheck all run in parallel
# Total CI time = slowest single jobHow well did you understand this?
Next in CI/CD
Secrets & Environments