GitHub Actions Tutorial — Project: Node.js CI
Project: Node.js CI Pipeline
Build a complete CI pipeline for a Node.js project with linting, testing across multiple Node versions, coverage reporting, and build artifact upload.
Requirements
| Feature | Implementation |
|---|---|
| Trigger on push and PR | on: push + on: pull_request |
| Test on Node 18 and 20 | matrix.node-version |
| Cache npm dependencies | actions/setup-node cache |
| Run lint + test + build | Separate steps |
| Upload coverage report | actions/upload-artifact |
| Fail fast on lint errors | Lint runs before test matrix |
Complete Workflow
name: Node.js CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
test:
needs: lint
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20]
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test -- --coverage
- name: Upload coverage
if: matrix.node-version == 20
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
retention-days: 14
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 7
Design Decisions
| Decision | Reasoning |
|---|---|
| Lint before test matrix | Fail early — don’t waste matrix cycles on lint errors |
fail-fast: false |
See results for all Node versions, not just the first failure |
| Coverage only on Node 20 | One report is enough; avoids duplicate artifacts |
| Separate build job | Only runs if all tests pass |
| 14-day coverage retention | Long enough for review; shorter than default 90 days |
Expected Output
✅ lint (15s)
✅ npm run lint — 0 errors, 0 warnings
✅ test (Node 18) (45s)
✅ 42 tests passed
✅ test (Node 20) (43s)
✅ 42 tests passed
✅ Coverage report uploaded
✅ build (20s)
✅ Build artifact uploaded (dist/)
Verification
After the workflow runs:
- Check the Actions tab — all jobs should be green
- Download the coverage-report artifact and open
coverage/index.html - Download the build-output artifact and verify the
dist/contents
← Back to: Chapter 15: Practice Projects
Next: Project — Docker + GHCR →