What is GitHub Actions?
What is CI/CD?
Before understanding GitHub Actions, it helps to understand the problem it solves.
Without CI/CD, the release process looks like this:
- Developer writes code locally
- Manually runs tests (maybe)
- Manually builds the app
- SSHs into the server and manually deploys
This is slow, error-prone, and doesn't scale with a team.
With CI/CD, every code push automatically:
- Runs all tests
- Builds the app
- Deploys if tests pass
GitHub Actions automates this pipeline directly from your GitHub repository.
Core Concepts
Workflow
A workflow is an automated process defined in a YAML file stored at .github/workflows/<name>.yml. A repo can have multiple workflows (e.g., one for CI on every push, one for deployment on merge to main).
Trigger (on)
The trigger defines what event starts the workflow:
on:
push:
branches: [main] # runs when code is pushed to main
pull_request: # runs on every PR
schedule:
- cron: '0 0 * * *' # runs daily at midnight UTC
workflow_dispatch: # manual trigger from the GitHub UI
Job
A job is a set of steps that run on the same machine. Jobs run in parallel by default. You can add needs to make one job wait for another.
jobs:
test:
runs-on: ubuntu-latest
steps: [...]
deploy:
needs: test # deploy only runs if test passes
runs-on: ubuntu-latest
steps: [...]
Step
A step is a single task within a job — either a shell command (run) or a pre-built action (uses).
steps:
- uses: actions/checkout@v4 # action: checks out your repo code
- uses: actions/setup-node@v4 # action: installs Node.js
with:
node-version: '20'
- run: npm install # shell command
- run: npm test # shell command
Runner
A runner is the machine that executes the job. GitHub provides hosted runners:
ubuntu-latest— most common, fast, freewindows-latest— for Windows-specific buildsmacos-latest— for iOS/Mac builds
You can also use self-hosted runners — your own server registered with GitHub Actions.
Action
An action is a reusable step published to the GitHub Marketplace. Instead of writing 20 lines of shell to set up Node.js, you use actions/setup-node@v4 in one line. Popular actions include:
| Action | Purpose |
|---|---|
actions/checkout | Clone your repo into the runner |
actions/setup-node | Install a specific Node.js version |
docker/build-push-action | Build and push Docker images |
appleboy/ssh-action | SSH into a remote server and run commands |
A Minimal CI Workflow
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
Save this as .github/workflows/ci.yml and push it. Every subsequent push or PR to main will automatically run your tests.
Secrets
Never hardcode API keys, passwords, or SSH keys in workflow files. Store them as secrets in your repo settings (Settings → Secrets and variables → Actions) and reference them in workflows:
- run: npm run deploy
env:
API_KEY: ${{ secrets.API_KEY }}
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
Secrets are masked in logs — they never appear in plain text.