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

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

Debugging

Comparison

See GitLab CI and Jenkins.

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

References