GitHub Actions Basics: CI on Every Push
You will write a GitHub Actions workflow that lints and tests your code on every push. By the end, broken code is caught automatically before it can be merged into main.
Learning Objectives
- Define triggers, jobs, and steps in workflow YAML.
- Cache dependencies to speed up runs.
- Make the workflow a required status check.
- Time: ~3 hours · Difficulty: Intermediate · Prereqs: a GitHub repo with tests.
Architecture Overview
graph LR
Push[git push] -->|on: push| WF[Workflow]
WF --> J1[lint job]
WF --> J2[test job]
J1 --> St[Status check]
J2 --> St
St -->|required| Main[protected main]
Environment Setup
You will need: a GitHub repo with a test command (for example pytest or npm test).
Before you begin: workflows live in .github/workflows/.
Step-by-Step Execution
01
Write the workflow
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.11', cache: 'pip' }
- run: pip install -r requirements.txt
- run: pytest -q
02
Push and watch the run
$ git push && gh run watch
CI ยท test (push) completed success
03
Require the check on main
Set the workflow as a required status check in branch protection so failing code cannot merge.
gh api repos/:owner/:repo/branches/main/protection -X PUT -f required_status_checks.strict=trueProgress So Far
graph LR
A[01 Workflow YAML] -->|done| B[02 Push + run]
B -->|done| C[03 Required check]
style A fill:#1a4a1a,stroke:#00ff00,color:#fff
style B fill:#1a4a1a,stroke:#00ff00,color:#fff
style C fill:#1a4a1a,stroke:#00ff00,color:#fff
Testing & Validation
gh run list --limit 1 && gh run view --log-failed 2>/dev/null | headThe latest run should show success. Push a deliberately failing test and confirm the workflow goes red and blocks the merge.
Troubleshooting
- Workflow not triggering: the file must be in
.github/workflows/on the default branch. - Cache misses: ensure the cache key matches the lockfile path.
- Secrets needed: add them under repo Settings, reference via
${{ secrets.NAME }}.
Extension Ideas
- Add build + deploy stages in Full CI/CD Pipeline.
- Scan images (see Docker Images) in CI.
- Deploy to Azure with a service principal from Azure CLI Setup.
Key Results
- Ran lint and tests automatically on every push and PR.
- Sped up runs with dependency caching.
- Made CI a required check protecting main.
- Confirmed failing code is blocked from merge.