Production-grade platform engineering handbook — Kubernetes, Terraform, Flux CD, GitHub Actions, AWS, and more.
67
84%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Passed
No known issues
Generate production-ready composite GitHub Actions or audit existing ones against best practices.
/platform-skills:composite-actions generate # interview → full repo scaffold → optional PR
/platform-skills:composite-actions review # audit an existing action.yml
/platform-skills:composite-actions secure # harden an action in place
/platform-skills:composite-actions test # generate a test workflow + act commandsTriggers: generate, create, new action, scaffold, write action, build action
Run a guided interview, then generate a complete, production-ready composite action with all supporting files. If the target repo already exists, open a PR.
Step 1 — Purpose
What does this action do? Describe it in one or two sentences. (e.g. "Build a Docker image and push it to GHCR using OIDC", "Send a Slack notification with build status and PR link")
Derive the action name from the description (kebab-case, under 30 chars). Confirm with the user.
Step 2 — Repo destination
Where should this action live?
- New dedicated repo — best for shared/public actions (Marketplace-publishable)
- Existing repo — internal action, placed under
.github/actions/<name>/oractions/<name>/
If existing repo: ask for owner/repo. Verify it exists with gh repo view owner/repo. Then ask:
Which subdirectory? (default:
.github/actions/<action-name>)
If the repo exists and is accessible, the action will be created on a branch and a PR will be opened automatically.
Step 3 — Pinning strategy
How should external actions be pinned?
- SHA pinning (recommended — supply chain secure, immutable)
- Semver floating tag (e.g.
@v4— easier to maintain, lower security)
Resolve SHAs for all external actions used via gh api repos/{owner}/{repo}/git/refs/tags/{tag} if SHA pinning is chosen.
Step 4 — Inputs
What inputs does this action need? For each input, collect:
- Name (snake_case)
- Type:
string/boolean/choice- Required or optional?
- If optional: default value
- Is it a secret? (webhook URL, kubeconfig, token, password, API key)
List all inputs in a table and confirm before proceeding.
Step 5 — Outputs
What values should this action expose as outputs? For each:
- Name (snake_case)
- Description (one sentence)
Step 6 — Cloud credentials
Does this action need cloud credentials?
- AWS via OIDC (no long-lived keys —
id-token: writerequired)- Azure via OIDC
- Both
- Neither
Step 7 — Notifications and PR comments
Should this action send notifications or post PR comments?
- Slack webhook notification
- GitHub PR comment (requires
pull-requests: write)- Both
- Neither
Step 8 — Job summary
Should this action write a job summary visible in the Actions UI? (Recommended: yes — adds a Markdown summary table with inputs, outputs, and status)
Step 9 — Confirm and generate
Show the user a summary of what will be generated:
Action: <name>
Description: <description>
Destination: <new repo | owner/repo/.github/actions/name>
Pinning: <SHA | semver>
Inputs: <count> (<N> are secrets)
Outputs: <count>
Cloud: <AWS OIDC | Azure OIDC | none>
Notifications: <Slack | PR comment | none>
Job summary: yes/no
Files to generate:
action.yml
README.md
CHANGELOG.md
.gitignore
scripts/<script>.sh (if logic warrants external scripts)
.github/dependabot.yml
.github/workflows/test-action.yml
.github/workflows/release.ymlAsk for confirmation before generating.
Generate with:
name, description, author filled from the interviewdescription: noting which are secrets::group:: / ::endgroup::) around each logical phaseenv: blocks — never ${{ inputs.secret }} in run:::add-mask:: on every secret value immediately after it is read${{ github.action_path }} for all file referencesshell: bash on every run: stepuses: pinned per the chosen strategy$GITHUB_STEP_SUMMARY written in a final if: always() steptimeout-minutes: on every network-bound stepbranding: block with an appropriate icon and colorGenerate an awesome-docs-compatible README with:
# <action-name>
> <one-line description>
<!-- To add animated diagrams to this README, run: /platform-skills:awesome-docs generate -->
## Architecture
*(Shows where this action fits in a CI/CD pipeline — add diagram with `/platform-skills:awesome-docs generate`)*
## Quick start
\`\`\`yaml
- uses: <owner>/<repo>@v1
with:
<required inputs with example values>
\`\`\`
## Inputs
| Input | Type | Required | Secret | Default | Description |
|---|---|---|---|---|---|
## Outputs
| Output | Description |
|---|---|
## Variables and secrets
Explain which inputs are secrets and how to wire them from the caller:
\`\`\`yaml
- uses: <owner>/<repo>@v1
with:
image_name: my-service # plain variable — safe to hardcode
webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }} # secret — must come from secrets store
\`\`\`
## Permissions
\`\`\`yaml
permissions:
<minimum required permissions>
\`\`\`
## Idempotency
<Is it safe to re-run? What happens on a second run?>
## Concurrency (recommended)
\`\`\`yaml
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: <true for build/validate, false for deploy/release>
\`\`\`
## Full example
\`\`\`yaml
<complete caller workflow showing all inputs>
\`\`\`
## Changelog
See [CHANGELOG.md](CHANGELOG.md)version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
commit-message:
prefix: "chore(deps)"
labels:
- "dependencies"A test workflow that:
push and pull_request paths matching the action directory./ or ./.github/actions/<name>)act instructions in a comment headerpush to tags matching v[0-9]+.[0-9]+.[0-9]+actionlintAfter generating all files:
# Clone the target repo
gh repo clone owner/repo /tmp/action-scaffold
# Create feature branch
git -C /tmp/action-scaffold checkout -b feat/add-<action-name>-composite-action
# Write all generated files into the appropriate subdirectory
# Commit
git -C /tmp/action-scaffold add .github/actions/<name>/
git -C /tmp/action-scaffold commit -m "feat(actions): add <action-name> composite action"
# Push
git -C /tmp/action-scaffold push -u origin feat/add-<action-name>-composite-action
# Open PR
gh pr create \
--repo owner/repo \
--title "feat(actions): add <action-name> composite action" \
--body "$(cat <<'EOF'
## Summary
- Adds `<action-name>` composite action to `.github/actions/<name>/`
- Inputs: <list>
- Outputs: <list>
- Pinning: <SHA | semver>
- Secrets: <list of secret inputs>
## Test plan
- [ ] Test workflow passes on this branch
- [ ] Matrix covers all input combinations
- [ ] `actionlint` passes
- [ ] Tested locally with `act`
- [ ] README inputs/outputs table reviewed
- [ ] Secret inputs confirmed to use `env:` isolation
## Usage
\`\`\`yaml
- uses: owner/repo/.github/actions/<name>@<sha>
with:
<example inputs>
\`\`\`
EOF
)"After PR creation, output:
PR opened:
<PR URL>Run
/platform-skills:awesome-docs generateon the README to add architecture flow, lifecycle loop, and field carousel diagrams.
Triggers: review, audit, check, lint my action, is this action safe
Audit an existing action.yml against the production checklist. Ask the user to paste or provide the path to the file.
Evaluate and report findings in three tiers:
CRITICAL (must fix before use)
uses: with mutable tag (@v4, @main, @latest) — supply chain riskrun: step missing shell: — error on many runners${{ inputs.* }} interpolated directly in run: commands — injection risk${{ secrets.* }} inside the action — always empty, silent failureWARNING (should fix)
::add-mask:: after reading./ instead of ${{ github.action_path }}== true instead of == 'true'$GITHUB_STEP_SUMMARY writtentimeout-minutes on network-bound stepsid: on steps that produce outputsINFORMATIONAL
branding: blockdescription: on inputs or outputsdependabot.yml for the actions ecosystemReport format:
## Review: <action-name>
### CRITICAL (N findings)
❌ Line 14: `uses: actions/checkout@v4` — pin to SHA. Current SHA: <resolved SHA>
❌ Line 22: `run: deploy.sh --env ${{ inputs.environment }}` — injection risk. Use env: block.
### WARNING (N findings)
⚠️ No input validation step
⚠️ inputs.webhook_url not masked after reading
### INFORMATIONAL (N findings)
ℹ️ No branding: block — add icon and color for Marketplace
### Score: N/20 — <Poor | Fair | Good | Excellent>Triggers: secure, harden, fix, pin actions, add shell
Fix an existing action.yml in place. Apply all CRITICAL and WARNING fixes automatically:
uses: with a mutable tag, call gh api to resolve to the current SHA and add the version as a commentshell: bash — to every run: step missing itenv: blocks — replace ${{ inputs.* }} in run: with env variable references::add-mask:: — on every step that reads a secret input$GITHUB_STEP_SUMMARY step if none existsReport what was changed:
## Hardening applied to action.yml
✅ 3 actions pinned to SHA (actions/checkout, docker/setup-buildx-action, docker/build-push-action)
✅ shell: bash added to 2 steps
✅ inputs.webhook_url moved to env: block in step "Send notification"
✅ ::add-mask:: added for webhook_url
✅ Input validation step injected at position 1
✅ Job summary step injected (if: always())Triggers: test, generate test, write test workflow, act
Generate a complete test workflow for an existing composite action.
Ask:
action.ymlGenerate:
.github/workflows/test-<action-name>.yml — triggers on PR + push for the action's directoryact commands with correct flags for local testingAlso output:
# Local test commands
# Default inputs
act -W .github/workflows/test-<action-name>.yml \
-P ubuntu-latest=catthehacker/ubuntu:act-22.04
# With secrets
act -W .github/workflows/test-<action-name>.yml \
-P ubuntu-latest=catthehacker/ubuntu:act-22.04 \
--secret SLACK_WEBHOOK_URL=https://hooks.slack.com/test \
--secret KUBECONFIG=<base64-encoded>
# Dry run
act -W .github/workflows/test-<action-name>.yml --dry-runTriggers: migrate, extract, refactor workflows, consolidate steps, duplicate steps
Detect repeated step blocks across workflow files and extract them into a composite action.
Ask the user for the directory containing workflow files (default: .github/workflows/), then:
*.yml files and find step sequences that appear in 3 or more jobsCandidate: setup-node-and-cache (appears in 5 workflows, 4 steps each = 20 step-lines saved)
Steps:
- uses: actions/checkout@...
- uses: actions/setup-node@...
- run: npm ci
- run: npm run buildgenerate interview — pre-fill answers from the detected steps; ask only what cannot be inferred (action name, outputs, pinning strategy).github/actions/<name>/uses: callReport:
## Migration complete
✅ Extracted 4 steps → .github/actions/setup-node-and-cache/action.yml
✅ Replaced in 5 workflows:
- .github/workflows/ci.yml (steps 3–6)
- .github/workflows/deploy.yml (steps 2–5)
- .github/workflows/lint.yml (steps 1–4)
- .github/workflows/test.yml (steps 3–6)
- .github/workflows/release.yml (steps 4–7)
Lines saved: 20 step-lines across 5 files → 1 composite action call eachTriggers: publish, marketplace, submit to marketplace, list on marketplace
Walk through the GitHub Actions Marketplace publishing checklist and generate all required metadata.
Confirm each is met:
action.yml in the root of the repository (not a subdirectory — Marketplace requires root placement)name: is unique on the Marketplace (search https://github.com/marketplace?type=actions&query=<name>)description: under 125 charactersauthor: set (your GitHub username or org)branding: block present with icon: and color:README.md at root covers: what it does, inputs/outputs table, full examplev1.0.0)If branding: is missing, suggest 3 icon/color combinations based on the action's purpose:
# For a build/push action:
branding:
icon: 'box'
color: 'blue'
# For a security scan:
branding:
icon: 'shield'
color: 'orange'
# For a notification action:
branding:
icon: 'bell'
color: 'green'Valid Feather icons: activity, alert-circle, archive, bell, box, check-circle, cloud, code, cpu, database, download, eye, file, flag, git-branch, globe, heart, home, key, layers, lock, mail, monitor, package, play, plus, refresh-cw, search, send, server, settings, shield, star, tag, terminal, tool, trash, upload, user, users, zap
Valid colors: white, yellow, blue, green, orange, red, purple, gray-dark
# Tag the release
git tag v1.0.0
git push origin v1.0.0
# Create floating major tag
git tag -f v1
git push origin v1 --force
# Verify release workflow ran (actionlint gate + SHA pinning check)
gh run list --workflow release.yml --limit 5Go to: https://github.com/<owner>/<repo>/releases/new
v1.0.0After publish, output:
## Marketplace listing
✅ Action published: https://github.com/marketplace/actions/<action-name>
Next steps:
- Add a Marketplace badge to README.md:
[](https://github.com/marketplace/actions/<name>)
- Set up dependabot to auto-update your own pinned SHA when you release new versions
- Watch for usage feedback in the Discussions tabFull documentation: references/composite-actions.md
Examples:
examples/github-actions/composite-actions/docker-build-push/ — GHCR push, OIDC, multi-platformexamples/github-actions/composite-actions/notify-slack/ — Slack webhook, secrets flowexamples/github-actions/composite-actions/k8s-deploy/ — kubectl, EKS/AKS/GKE OIDCexamples/github-actions/composite-actions/terraform-plan/ — Terraform plan, PR commentexamples/github-actions/composite-actions/security-scan/ — Trivy, severity gate, annotationsexamples/github-actions/composite-actions/release-tag/ — semver bump, $GITHUB_OUTPUT chainingexamples/github-actions/composite-actions/pr-comment/ — github-script, token scopingexamples/github-actions/composite-actions/setup-env/ — multi-runtime (Node/Python/Go), tutorial baseline.claude-plugin
.github
commands
docs
examples
agent-self-improve
argocd
awesome-docs
aws
cloudfront
functions
lambda-edge
functions
azure
compliance
conventional-commits
datadog
llm-observability
demo
documentation
dora
dynatrace
fluxcd
github-actions
composite-actions
configure-cloud
db-migrate
docker-build-push
k8s-deploy
notify-slack
pr-comment
release-tag
security-scan
setup-env
setup-terraform
terraform-plan
helm
web-service
templates
kubernetes
kyverno
mcp
observability
openshift
pr-review
ownership
runtime-security
supply-chain
terraform
references
scripts
skills
platform-skills
tests