GitHub Actions
GitHub Actions is CI/CD that lives where your code lives — YAML workflows in .github/workflows/ that run automatically on events like pushes, pull requests, and schedules. There's no separate service to wire up, which makes it the path of least resistance for automating a GitHub repo.
For most projects it's all you'll ever need: run lint/test/build on every PR, deploy on merge, and reach for the Marketplace when you want a prebuilt action. Start simple and add complexity only as you need it.
TL;DR
- Workflows are YAML files in
.github/workflows/, triggered by events. - Every PR should run lint → test → build.
- Cache dependencies and parallelize jobs for speed.
- Pin action versions, scope permissions, and use OIDC instead of long-lived secrets.
Quick Example
A CI workflow that runs on pushes and PRs — checkout, install with caching, then verify:
Core Concepts
Jobs run in parallel by default; add needs: only for real dependencies — e.g. deploy needs [lint, test, build].
Useful Patterns
Caching
Caching can cut build times dramatically. Built-in for common setups, or fine-grained with actions/cache:
Security
- Pin action versions — use a tag (
@v4) or, better, a commit SHA; never@main. - Scope permissions — set
permissions:to the minimum (contents: read). - Use OIDC for cloud auth — short-lived tokens instead of stored cloud keys.
- Don't interpolate secrets into commands — pass them as
env:so they aren't logged. - Fork PRs can't read secrets by design; be very careful with
pull_request_target.
Debugging
- Set repo secrets
ACTIONS_RUNNER_DEBUG: trueandACTIONS_STEP_DEBUG: truefor verbose logs. - Drop into a live runner on failure with
mxschmitt/action-tmate@v3(if: failure()). - Download raw logs from the job's gear menu.
Comparison
Common Mistakes
Unpinned actions
Secrets interpolated into a command
FAQ
Where do workflows live and when do they run?
In .github/workflows/*.yml. Each file declares triggers under on: — pushes, pull requests, schedules (cron), or manual workflow_dispatch. GitHub runs the matching workflow automatically when those events occur.
How do I make workflows faster?
Cache dependencies (built-in cache: or actions/cache), run independent jobs in parallel (they do by default), use matrix builds wisely, and split slow suites. Caching alone often cuts build time dramatically.
How should I authenticate to a cloud from Actions?
Prefer OIDC: grant id-token: write and assume a cloud role for short-lived credentials, so there are no long-lived cloud keys stored as secrets. It's more secure and removes secret-rotation toil.
GitHub-hosted or self-hosted runners?
GitHub-hosted runners are simplest and need no maintenance. Use self-hosted runners when you need specific hardware/OS, access to a private network, or to control cost at high volume — at the price of operating and securing them yourself.
Why can't a forked PR access my secrets?
By design — a malicious fork could otherwise exfiltrate them. Workflows from forks run without secrets. If you must run privileged work on fork PRs, use pull_request_target very carefully, since it runs with the base repo's permissions.
Related Topics
- CI/CD Pipelines — The fundamentals
- GitLab CI — GitLab's equivalent
- Jenkins — Self-hosted alternative
- Docker — Building images in CI
- Secrets Management — Handling CI credentials