Workflow Structure
Workflows live in .github/workflows/*.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 Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Test
run: npm testTriggers (on)
on:
push:
branches: [main, develop]
paths:
- "src/**" # only trigger on source changes
pull_request:
schedule:
- cron: "0 6 * * 1" # every Monday at 6am UTC
workflow_dispatch: # manual trigger from GitHub UIEnvironment Variables and Secrets
env:
NODE_ENV: test # workflow-level
jobs:
deploy:
runs-on: ubuntu-latest
env:
APP_URL: https://staging.example.com # job-level
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.DEPLOY_API_KEY }} # from GitHub Secrets
run: ./scripts/deploy.shMatrix Builds
Test across multiple versions in parallel:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [18, 20, 22]
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm testCaching
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-Job Dependencies
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: npm test
deploy:
needs: test # only runs if test passes
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh