| name | github-actions-guidelines |
| description | CI/CD guidelines for GitHub Actions including pipeline structure, caching, secrets management, deployment strategies, and quality gates. Auto-loaded when working with workflow files. |
| category | guideline |
| user-invocable | false |
CI/CD Guidelines
Core Principles
- Automate everything - No manual steps in the release process
- Fail fast - Run quick checks first
- Reproducible builds - Same inputs produce same outputs
- Security first - Scan for vulnerabilities, manage secrets
- Observable - Know what's deployed where
Pipeline Structure
Standard Pipeline Stages
Customize for your project: Examples below use npm commands and Node 20 LTS. Adjust node-version, install/script commands, and {{BUILD_OUTPUT}} path (dist, build, .next, out) to match your project. For yarn/pnpm, replace npm ci with yarn install --frozen-lockfile or pnpm install --frozen-lockfile and update the cache: value.
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
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
typecheck:
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 typecheck
test:
needs: [lint, typecheck]
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 test:coverage
- uses: codecov/codecov-action@v3
with:
files: ./coverage/lcov.info
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
path: {{BUILD_OUTPUT}}/
security:
needs: [build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm audit --audit-level=high
- uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
Pull Request Checks
name: PR Checks
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
pr-validation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check PR size
run: |
ADDITIONS=$(gh pr view ${{ github.event.pull_request.number }} --json additions -q '.additions')
if [ "$ADDITIONS" -gt 800 ]; then
echo "::warning::Large PR with $ADDITIONS additions. Consider splitting."
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Validate commits
run: |
git log origin/main..HEAD --format='%s' | while read msg; do
if ! echo "$msg" | grep -qE '^(feat|fix|docs|style|refactor|perf|test|chore|ci|revert)(\(.+\))?: .+'; then
echo "::error::Invalid commit message: $msg"
exit 1
fi
done
- name: Test changed files
run: |
npm ci
npm test -- --changedSince=origin/main
Caching
Dependency Caching
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- uses: actions/cache@v4
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
Build Caching
- uses: actions/cache@v4
with:
path: |
{{FRAMEWORK_CACHE}}
{{BUILD_OUTPUT}}/.cache
key: ${{ runner.os }}-build-${{ hashFiles('src/**') }}
restore-keys: |
${{ runner.os }}-build-
Secrets Management
Using Secrets
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: |
# Secrets are masked in logs
./deploy.sh
- name: Deploy to production
environment: production
env:
API_KEY: ${{ secrets.PROD_API_KEY }}
run: ./deploy.sh
Secrets Best Practices
- run: echo ${{ secrets.API_KEY }}
- env:
API_KEY: ${{ secrets.API_KEY }}
run: ./script.sh
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/deploy
aws-region: us-east-1
Known Gotchas
Workflow Permissions
permissions:
contents: read
pull-requests: write
issues: write
Checkout Depth
- uses: actions/checkout@v4
with:
fetch-depth: 0
Concurrent Runs
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: false
Environment Variables in Scripts
- run: echo $MY_VAR
- env:
MY_VAR: ${{ vars.MY_VAR }}
run: echo $MY_VAR
Additional References