agentleFS
KhaledSaeed18KhaledSaeed18/dotclaude/skills/engineering/github-actions-pipeline/SKILL.md

github-actions-pipeline

Skill5 starsChanged 4 months agoMITView on GitHub

Design, write, or fix GitHub Actions workflows for a project: a CI pipeline with the right triggers, concurrency, caching, matrix, and least-privilege permissions; pinned actions; reusable workflows and composite actions; deploy workflows with environments and OIDC instead of long-lived secrets; and the debugging moves for slow, flaky, or failing runs. Use when adding CI to a repository, when a pipeline is slow or flaky, when a workflow needs deploy or release steps, or when a security review flags workflow permissions.

  • Installs packages
  • Commits and pushes

We split this skill into the rules it gives an agent

2 rules. About 0 are common, 0 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Never pull_request_target with a checkout of the PR head unless you understand it: it runs with write permissions on untrusted code.

    line 53
  2. Very specific:

    No long-lived cloud keys in secrets.

    line 57

≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

A pipeline is trusted when it is fast enough to run on every push, deterministic enough that a red is a real failure, and locked down enough that a compromised dependency cannot use it. Design for those three before adding steps.

A CI workflow skeleton

name: ci
on:
  pull_request:
  push:
    branches: [main]

permissions:
  contents: read            # top-level default; widen per job only

concurrency:
  group: ci-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    strategy:
      fail-fast: false
      matrix:
        node: [20, 22]
    steps:
      - uses: actions/checkout@v4      # pin to a SHA in security-sensitive repos
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - run: pnpm lint
      - run: pnpm typecheck
      - run: pnpm test -- --reporter=junit --outputFile=junit.xml
      - uses: actions/upload-artifact@v4
        if: always()
        with: { name: test-results-${{ matrix.node }}, path: junit.xml }

Rules

Triggers

  • pull_request for validation, push to the default branch for post-merge and deploy, workflow_dispatch for manual runs, schedule for nightly or dependency checks. Path filters (paths:) to skip irrelevant runs, remembering that a required check that is skipped blocks merging unless the branch rule allows it.
  • Never pull_request_target with a checkout of the PR head unless you understand it: it runs with write permissions on untrusted code.

Permissions

  • Top-level permissions: contents: read; each job adds only what it needs (pull-requests: write to comment, id-token: write for OIDC, packages: write to publish).
  • No long-lived cloud keys in secrets; use OIDC federation (aws-actions/configure-aws-credentials with a role, google-github-actions/auth, Azure federated credentials).
  • Secrets never printed; ::add-mask:: for derived values; no set -x in steps that touch them.

Pinning

  • Third-party actions pinned to a full commit SHA with a version comment, bumped by Dependabot (package-ecosystem: github-actions). First-party actions/* at a major tag is an acceptable compromise in low-risk repos.
  • Tool versions from the repo's own files (.nvmrc, .tool-versions, package.json engines), not hard-coded twice.

Speed

  • Cache the package manager store via the setup action's cache: input; cache build outputs (actions/cache keyed on lockfile hash plus source hash) only when the build is expensive and the cache is safe.
  • Split into jobs that run in parallel (lint, typecheck, test, build) when each takes over a minute; keep one job when they are all fast, because job startup costs 20 to 40 seconds.
  • timeout-minutes on every job so a hang fails instead of consuming the runner for six hours.
  • concurrency with cancel-in-progress on pull requests so pushes supersede stale runs.

Determinism

  • --frozen-lockfile / npm ci / pip install -r with hashes; no latest tags; pinned runner images when the OS matters (ubuntu-24.04 over ubuntu-latest for reproducibility).
  • Retries only for steps with known transient failure (network installs), via a retry action with a small count; a retried test is a flaky test to fix, not to hide.

Reuse

  • A reusable workflow (on: workflow_call) for a pipeline shared across repos; a composite action (action.yml with runs: using: composite) for a bundle of steps shared across jobs. Version them by tag.

Deploy workflows

jobs:
  deploy:
    needs: [test]
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://app.example.com
    permissions: { id-token: write, contents: read }
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with: { role-to-assume: arn:aws:iam::123456789012:role/gh-deploy, aws-region: eu-west-1 }
      - run: ./scripts/deploy.sh

Environments carry the protection rules (required reviewers, wait timers, branch restrictions) and the environment-scoped secrets. Deploy from an artifact built in the tested job (actions/download-artifact), not from a fresh build, so what was tested is what ships.

Releases

Tag-triggered (on: push: tags: ['v*']), build, create the release with gh release create or softprops/action-gh-release, attach artifacts, publish packages with provenance (npm publish --provenance needs id-token: write).

Debugging

  • Re-run with debug logging (ACTIONS_STEP_DEBUG secret or the "enable debug logging" checkbox) and read the raw log; gh run view <id> --log-failed gets the failing step's log locally (the fix-ci skill covers the loop).
  • Reproduce locally with the same commands and the same tool versions; act for a rough approximation of the runner.
  • For a flaky test, capture the seed and the artifact, and quarantine with a tracked issue rather than a retry.
  • Timing: the run summary shows per-step durations; the slowest step is usually dependency install without cache or a test suite that should be sharded.

Review checklist

Least-privilege permissions; no pull_request_target misuse; actions pinned; frozen installs; caching keyed correctly; timeouts; concurrency; artifacts uploaded on failure; deploy from tested artifact with an environment and OIDC; no secrets in logs.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.