Gha create
Generates GitHub Actions workflows following elite-level security and efficiency best practices. Use when writing new CI/CD workflows, modifying existing workflows, or reviewing workflows for hardening opportunities. Applies SHA-pinned actions, least-privilege permissions, OIDC authentication, injection prevention, path filtering, native caching, and concurrency control. Do NOT use for non-GitHub-Actions CI/CD systems or general DevOps tasks unrelated to workflow authoring.From its SKILL.md
npx -y skills add PSDN-AI/nexus-skills --skill gha-createAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
16.2 KB, as published. Nobody here has run it
GHA Create
Most AI-generated and tutorial-sourced GitHub Actions workflows use mutable tags, omit permissions blocks, hardcode long-lived secrets, and lack concurrency controls. This Skill provides a codified engineering standard that agents follow when authoring workflows, so the output is production-grade from the first draft.
Table of Contents
- When Should You Use This?
- How This Skill Can Be Used
- Prerequisites
- Quick Start
- Quick Reference Checklist
- Pillar 1: Security Best Practices
- Pillar 2: Efficiency Best Practices
- Workflow Generation Process
- Advanced Reuse Patterns
- Validation
- Common Pitfalls
- References
When Should You Use This?
- You are writing a new GitHub Actions workflow from scratch.
- You are modifying or reviewing an existing workflow for hardening.
- You want to transform a naive workflow into a production-grade pipeline.
- You need a quick reference for GitHub Actions security and efficiency rules.
How This Skill Can Be Used
| Model | How it works | When to use |
|---|---|---|
| A — Script Execution | Run validate_workflow.sh against a workflow file to check compliance | You have bash and want automated rule checking |
| B — Knowledge-Driven | An LLM reads this SKILL.md and applies rules when generating workflows | No bash available, or the LLM is generating workflows from scratch |
| C — Hybrid | An LLM generates workflows using this spec, then validates with the script | Best coverage — combines generation with automated checking |
Prerequisites
Required (for Knowledge-Driven mode):
- None — any AI agent can read and apply these rules
Required (for Script Execution / Hybrid mode):
bash(4.0+),grep,awk
Quick Start
Knowledge-Driven (Agent reads rules, writes workflows)
Generate a CI workflow for my Node.js project following gha-create best practices
The agent reads this SKILL.md, applies all 8 rules, and produces a hardened workflow.
CLI (Validate existing workflows)
# Validate a single workflow
./skills/gha-create/scripts/validate_workflow.sh .github/workflows/ci.yml
# Validate all workflows in a directory
for f in .github/workflows/*.yml; do
./skills/gha-create/scripts/validate_workflow.sh "$f"
done
Quick Reference Checklist
When writing or reviewing a workflow, verify every item:
| ID | Rule | Check |
|---|---|---|
| S1 | SHA Pinning | Every uses: pinned to full 40-char SHA with # vX.Y.Z comment |
| S2 | Least-Privilege Permissions | Top-level permissions: contents: read present |
| S3 | OIDC Authentication | OIDC preferred over static secrets for cloud auth |
| S4 | Injection Prevention | No ${{ github.event.* }} in run: blocks — map to env: first |
| E1 | Path Filtering | Triggers use paths: or paths-ignore: |
| E2 | Native Caching | Every setup-* action has cache: parameter enabled |
| E3 | Concurrency Control | concurrency: group with cancel-in-progress: true |
| E4 | Matrix Optimization | fail-fast: true on strategy.matrix |
Pillar 1: Security Best Practices
S1: SHA Pinning
Every third-party action must be pinned to a full 40-character commit SHA with a trailing version comment.
# BAD - mutable tag can be moved to point at malicious code
- uses: actions/checkout@v4
# GOOD - immutable reference with human-readable version comment
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Why: Tags are mutable Git refs. An attacker who compromises an action repository can move a tag to inject malicious code into every workflow that references it. SHA pins are immutable.
Exceptions: Local actions (uses: ./my-action) do not need SHA pinning.
See SECURITY_PRACTICES.md for edge cases and SHA lookup methods.
S2: Least-Privilege Permissions
Always include an explicit top-level permissions: block. Start restrictive, elevate only at the job level with a justification comment.
# BAD - no permissions block (defaults to read-write-all in classic repos)
on: push
jobs:
build:
runs-on: ubuntu-latest
# GOOD - explicit least privilege at top level
on: push
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
deploy:
permissions:
contents: read
packages: write # Needed to push to GHCR
See SECURITY_PRACTICES.md for common permission patterns.
S3: OIDC Authentication
Prefer OpenID Connect (short-lived tokens) over static secrets for cloud provider authentication.
# BAD - static long-lived credentials stored as secrets
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# GOOD - OIDC federation with short-lived token
permissions:
id-token: write
steps:
- uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0
with:
role-to-assume: arn:aws:iam::123456789012:role/deploy
aws-region: us-east-1
Note: OIDC requires cloud provider configuration. When OIDC is not possible, static secrets are acceptable.
See SECURITY_PRACTICES.md for AWS, GCP, and Azure examples.
S4: Injection Prevention
Never interpolate untrusted event context directly in run: blocks. Map to an environment variable first.
# BAD - attacker-controlled input injected directly into shell
- run: echo "Title: ${{ github.event.pull_request.title }}"
# GOOD - map to env, then reference the shell variable
- env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: echo "Title: $PR_TITLE"
Dangerous contexts (attacker-controlled, never use directly in run:):
github.event.issue.title, github.event.issue.body, github.event.pull_request.title, github.event.pull_request.body, github.event.pull_request.head.ref, github.event.comment.body, github.event.review.body, github.event.head_commit.message, github.event.commits.*.message, github.event.commits.*.author.name, github.event.pages.*.page_name
See SECURITY_PRACTICES.md for the complete list and alternatives.
Pillar 2: Efficiency Best Practices
E1: Path Filtering
Use paths or paths-ignore on push and pull_request triggers to skip workflows when only irrelevant files change.
# BAD - runs on every push regardless of what changed
on: [push, pull_request]
# GOOD - only runs when source code or dependencies change
on:
push:
branches: [main]
paths: ['src/**', 'package*.json', '.github/workflows/ci.yml']
pull_request:
paths: ['src/**', 'package*.json', '.github/workflows/ci.yml']
When to skip path filtering: Release workflows, security scans, and deployment workflows that must run on every push to main.
See EFFICIENCY_PRACTICES.md for monorepo patterns.
E2: Native Caching
Every setup-* action should enable its built-in cache parameter instead of using a separate actions/cache step.
# BAD - separate cache step (verbose, error-prone)
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version: 20
# GOOD - built-in cache (one step, automatic key generation)
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version: 20
cache: 'npm'
See EFFICIENCY_PRACTICES.md for cache parameters per setup action.
E3: Concurrency Control
Add a concurrency group to kill obsolete runs when new commits are pushed rapidly.
# BAD - no concurrency control (stale runs waste minutes)
# GOOD - cancel redundant runs
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Exception — Deployments: Deployment workflows should use cancel-in-progress: false to avoid interrupting an active deploy.
Exception — Incremental push workflows: When a push workflow uses incremental diff logic (e.g., github.event.before to test only the delta), a branch-level group like workflow-refs/heads/main causes new pushes to cancel in-progress runs. The cancelled run's changes are never tested because the new run only covers its own delta. Use a per-commit group key for push events to ensure every merge is validated:
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}
cancel-in-progress: true
This gives push runs unique groups (per SHA, never cancelled) while PR runs still share a group (per branch, stale runs cancelled).
See EFFICIENCY_PRACTICES.md for group naming patterns.
E4: Matrix Optimization
When using strategy.matrix, keep fail-fast: true (the default) and use include/exclude to avoid wasting runner minutes on irrelevant combinations.
# BAD - fail-fast disabled, all matrix jobs run even after first failure
strategy:
fail-fast: false
matrix:
node-version: [18, 20, 22]
# GOOD - fail-fast enabled, stops early on failure
strategy:
fail-fast: true
matrix:
node-version: [18, 20, 22]
See EFFICIENCY_PRACTICES.md for dynamic matrices and max-parallel.
Workflow Generation Process
When generating a GitHub Actions workflow from scratch, follow these steps in order:
-
Define triggers — Identify events (
push,pull_request,workflow_dispatch). Apply path filtering (E1) unless the workflow must run on every change (e.g., deployments, security scans). -
Set top-level permissions — Add
permissions: contents: readimmediately after the trigger block. Never omit this (S2). -
Add concurrency control — Add a
concurrency:group withcancel-in-progress: true(E3). For deployment workflows, usecancel-in-progress: false. -
Define jobs — For each job: a. Elevate permissions at the job level only if needed (S2). Add a comment explaining why. b. Pin every
uses:to a full 40-char SHA with a version comment (S1). Use SHA_LOOKUP.md orgh apito find current SHAs. c. Enable native caching on allsetup-*steps (E2). d. Map any untrusted event context toenv:before using inrun:blocks (S4). e. Use OIDC for cloud provider authentication when possible (S3). -
Optimize with matrix — If testing across versions or platforms, use
strategy.matrixwithfail-fast: true(E4). Useinclude/excludeto skip unnecessary combinations. -
Validate — Run
validate_workflow.shagainst the output, or manually verify against the Quick Reference Checklist.
Advanced Reuse Patterns
When a workflow becomes large because the same logic is repeated across repositories, extract the shared logic instead of copying the entire file.
Prefer Reusable Workflows for repeated multi-job pipelines
Use a reusable workflow (workflow_call) when the same CI, build, or deploy pipeline appears in multiple repositories or business units. This keeps the calling workflows short while centralizing the standard in one place.
Important: If you call a reusable workflow from another repository, pin it to a full commit SHA just like any other uses: reference.
Prefer Composite Actions for repeated step sequences
If the repetition is only a sequence of steps inside one job (for example setup, auth, packaging, or publish steps), use a composite action instead of a reusable workflow. Composite actions are a better fit for step-level reuse; reusable workflows are a better fit for job- or pipeline-level reuse.
Do not extract purely for appearance
If a workflow is used in only one repository and is not repeated elsewhere, keep it inline unless extraction materially improves reuse, reviewability, or governance. Do not split a workflow out just to make the top-level YAML look shorter.
Validation
Automated Validation
./skills/gha-create/scripts/validate_workflow.sh <workflow-file>
Exit code 0 = all checks pass. Exit code 1 = violations found.
The validator checks all 8 rules (S1-S4, E1-E4). Some rules (S3, E1, E4) are advisory — they produce warnings but do not cause a hard failure.
Manual Validation
Walk through the Quick Reference Checklist for each workflow file.
Common Pitfalls
- Forgetting the version comment on SHA pins:
@abc123def...without# v4.2.2is technically compliant but unreadable. Always add the comment so humans can see which version is pinned. - Using
permissions: write-all: This is worse than omitting the block entirely because it signals intentional over-permissioning. Always enumerate specific permissions. - Cancelling deployment workflows: Setting
cancel-in-progress: trueon a deployment can leave infrastructure in a half-deployed state. Usecancel-in-progress: falsefor deploy jobs. - Cancelling incremental push workflows: If a push workflow tests only the delta since
github.event.before, a branch-level concurrency group can cancel in-progress runs, leaving some merged changes untested. Use a per-commit group key for push events (see E3 exceptions). - Caching with separate
actions/cache: The setup actions (setup-node, setup-python, etc.) have built-in cache support that is simpler and less error-prone. Use the built-in parameter. - Path filtering on deployment workflows: Deployment workflows triggered by pushes to
mainshould generally NOT use path filters — you want every merged PR to trigger a deploy. - OIDC is not always available: Self-hosted runners, non-cloud targets, and some organizational policies may prevent OIDC setup. Static secrets are acceptable when OIDC is genuinely not an option. The validator treats this as advisory.
- Interpolating
github.event.pull_request.numberinrun:: Unlike.titleor.body, numeric fields like.numberare not injection vectors. However, the safest habit is to always map event context toenv:regardless. The validator flags all dangerous subfields listed in the S4 section.
References
Detailed Rule Documentation
- Security Practices (S1-S4) — Detailed rules, edge cases, and examples
- Efficiency Practices (E1-E4) — Detailed rules, edge cases, and examples
- SHA Lookup Guide — How to find current SHAs for GitHub Actions
Reference Workflow Templates
- node-ci.yml — Node.js CI pipeline (S1, S2, E1-E4)
- docker-build.yml — Docker build and push to GHCR (S1, S2, E1, E3)
- oidc-deploy.yml — OIDC-based AWS deployment (S1, S2, S3, E3)
Before/After Examples
- before.yml — Naive workflow violating all rules
- after.yml — Same workflow transformed to meet the standard