cicd-github-actions

SKILL.md

GitHub Actions CI/CD

Core Objectives

  • Security: Minimal permissions, secrets handling, OIDC
  • Performance: Caching, matrix builds, parallelization
  • Maintainability: Reusable workflows, composite actions
  • Reliability: Concurrency control, retry logic

Essential Checklist

  • Workflows use minimal permissions (permissions: {} at root)
  • Secrets never logged or exposed in artifacts
  • Concurrency control configured
  • Timeout values set on all jobs
  • Caching implemented for dependencies
  • PR workflows use pull_request, not pull_request_target

Minimal Permissions

name: CI

on:
  push:
    branches: [main]
  pull_request:

# Default: no permissions
permissions: {}

jobs:
  test:
    runs-on: ubuntu-latest
    # Job-level permissions
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm test

Caching

- uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'

# Or explicit caching
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

Matrix Builds

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        node-version: [18, 20, 22]
        os: [ubuntu-latest, macos-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm ci
      - run: npm test

Concurrency Control

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Secrets Handling

env:
  # Reference secrets in env
  API_KEY: ${{ secrets.API_KEY }}

steps:
  - name: Use secret safely
    run: |
      # Mask in logs
      echo "::add-mask::${{ secrets.API_KEY }}"
      # Use in command
      curl -H "Authorization: Bearer $API_KEY" https://api.acme.com

Reusable Workflows

# .github/workflows/reusable-build.yml
name: Reusable Build

on:
  workflow_call:
    inputs:
      node-version:
        required: false
        type: string
        default: '20'
    secrets:
      NPM_TOKEN:
        required: false

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci
      - run: npm run build
# Calling workflow
jobs:
  build:
    uses: ./.github/workflows/reusable-build.yml
    with:
      node-version: '20'
    secrets:
      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

Job Outputs

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.value }}
    steps:
      - id: version
        run: echo "value=$(cat VERSION)" >> $GITHUB_OUTPUT

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying ${{ needs.build.outputs.version }}"

Detailed References

Weekly Installs
3
GitHub Stars
9
First Seen
13 days ago
Installed on
opencode3
github-copilot3
codex3
kimi-cli3
gemini-cli3
cursor3