agentsclimarketplace

Github actions

Skill milanhorvatovic/skill-system-foundry/.agents/skills/github-actions

Guides the creation, modification, and review of GitHub Actions workflows in the Skill System Foundry repository. Covers workflow YAML syntax, trigger configuration, permission models, SHA-pinned actions, matrix strategies, artifact passing, and concurrency control. Triggers when asked to create or modify a workflow, add a CI job, configure triggers or permissions, pin an action to a SHA, troubleshoot a failing workflow, or review a workflow change. Also triggers on phrases like "add a workflow," "fix the CI," "pin this action," "workflow permissions," or "why is this action failing." Use this skill for any work involving .github/workflows/ YAML files.From its SKILL.md

Install
npx -y skills add milanhorvatovic/skill-system-foundry --skill github-actions

Assembled 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.

SKILL.md

9.7 KB, as published. Nobody here has run it

GitHub Actions Skill

Guides the creation, modification, and review of GitHub Actions workflows in the Skill System Foundry repository. Codifies the conventions established across the repository's existing workflows.

Repository Workflows

WorkflowFileTriggerJobs
Tests + coveragepython-tests.yamlPush to main, PRs, workflow_calltest (matrix), validate-examples, reference-conformance, bundle-extract-smoke
Coverage badgecoverage-badge.yamlworkflow_run after Python testsbadge
CI helper testsci-helper-tests.yamlPush/PR (path-filtered to CI helpers)helper-tests (matrix)
Shell lintshellcheck.yamlPush/PR (path-filtered to .sh)shellcheck
Action-pin verifyverify-action-pins.yamlPush to main, PRsverify
Workflow lintactionlint.yamlPush to main, PRsactionlint
Codex code reviewcodex-code-review.yamlPR events (non-draft)review (read-only), publish (write)
Release-label checkverify-pr-release-label.yamlPR eventsverify-release-label (required)
Supply-chain scorecardscorecard.yamlSchedule, push to main, branch-protection changeanalysis
CodeQLcodeql.yamlPush to main, PRs, scheduleanalyze
Tool-catalog drifttool-catalog-drift.yamlSchedule, workflow_dispatchdetect-and-pr
Release preprelease-prep.yamlworkflow_dispatchprepare, test, open-pr
Release tagrelease-on-merge.yamlRelease PR merged to maintag
Release bundlerelease.yamlv*.*.* tag pushrelease

Hard Requirements

Actions Pinned to Commit SHAs

Every action must be pinned to a full 40-character commit SHA, not a tag. Include a comment with the tag and semver for readability:

# Correct
- uses: actions/checkout@de0fac2e5ef641dbfe0fef2a1de4a5c3a0d70dce  # @v6 as 6.0.2

# Wrong — tag-only reference
- uses: actions/checkout@v4

When updating an action version:

  1. Find the new tag's commit SHA on the action's repository releases page
  2. Replace the SHA in the workflow
  3. Update the comment to reflect the new tag and version

This rule is enforced by .github/scripts/verify-action-pins.py, which the verify-action-pins.yaml workflow runs on every PR and push to main. Any uses: line that is not a 40-character lowercase commit SHA (or ./local-path / docker://...) fails CI. Run the script locally with python .github/scripts/verify-action-pins.py to check before pushing.

App Token Identity

When minting a GitHub App token with actions/create-github-app-token, use the client-id input — app-id is deprecated (the action carries a deprecationMessage pointing to client-id). Across these OSS repos each automation identity wires a <PREFIX>_CLIENT_ID repository variable for the App's client ID plus a repository secret holding its PEM private key; the private-key secret name is not uniform (AUTOMATION_PRIVATE_KEY for the automation App, RELEASE_APP_PRIVATE_KEY for the release App), so take the exact names from the list below:

  • oss-automation-bot — vars.AUTOMATION_CLIENT_ID + secrets.AUTOMATION_PRIVATE_KEY (the workhorse: dependency automation, opening/approving PRs). Wired in this repo's tool-catalog-drift.yaml and the release-PR approval in release-prep.yaml.
  • oss-release-bot — vars.RELEASE_CLIENT_ID + secrets.RELEASE_APP_PRIVATE_KEY (the release identity: opens the release PR, tags, and publishes). Wired in release-prep.yaml, release-on-merge.yaml, and release.yaml.
# Correct
- uses: actions/create-github-app-token@<sha>  # @v3 as 3.x
  with:
    client-id: ${{ vars.AUTOMATION_CLIENT_ID }}
    private-key: ${{ secrets.AUTOMATION_PRIVATE_KEY }}
<!-- yaml-ignore -->
# Wrong — deprecated app-id input
- uses: actions/create-github-app-token@<sha>  # @v3 as 3.x
  with:
    app-id: ${{ vars.AUTOMATION_APP_ID }}
    private-key: ${{ secrets.AUTOMATION_PRIVATE_KEY }}

Least-Privilege Permissions

Scope permissions as narrowly as possible. Default to contents: read. Only add write permissions where required, and prefer job-level over workflow-level permissions:

# Preferred: job-level permissions
jobs:
  test:
    permissions:
      contents: read
  deploy:
    permissions:
      contents: write

# Acceptable: workflow-level when all jobs need the same
permissions:
  contents: read

The Codex code review workflow demonstrates the ideal pattern: a read-only review job followed by a write-capable publish job, isolating the permission boundary.

No Hardcoded Secrets

Secrets are accessed via ${{ secrets.VARIABLE_NAME }}, variables via ${{ vars.VARIABLE_NAME }}. Never echo secrets to logs. Shell scripts called by workflows validate required environment variables at the top with ${VAR:?}.

Conventions

Trigger Configuration

  • Push to main — for CI that should run on every merge (tests, badge updates)
  • pull_request — for validation that gates merges (tests, lint, code review)
  • Path filtering — use paths: to avoid triggering on unrelated changes. shellcheck.yaml only runs when .sh files change
  • Activity types — specify explicit types for PR workflows when not all events are relevant: types: [opened, reopened, synchronize, ready_for_review]

Runner Selection

  • ubuntu-latest is the default for all jobs
  • Add windows-latest via matrix only when cross-platform testing is needed (currently only python-tests.yaml)
  • Do not add macOS unless explicitly required — it consumes more CI minutes

Matrix Strategy

Use matrix for cross-platform or multi-version testing. Set fail-fast: false so all combinations run even if one fails:

strategy:
  fail-fast: false
  matrix:
    os: [ubuntu-latest, windows-latest]
    python-version: ["3.12"]

Concurrency Control

Use concurrency groups with cancel-in-progress: true to avoid redundant runs on rapid pushes:

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

The Codex review workflow uses PR-number-based concurrency: codex-review-${{ github.event.pull_request.number }}.

Artifact Passing Between Jobs

When jobs with different permission scopes need to share data, use upload/download artifact pairs:

  1. Job A (read-only) uploads an artifact
  2. Job B (write) downloads and processes it

This pattern is used by both python-tests.yaml (coverage total) and codex-code-review.yaml (review output). Never pass data through workflow outputs for sensitive content.

Timeout Discipline

Set explicit timeout-minutes on jobs that call external services or could hang:

jobs:
  review:
    timeout-minutes: 30
  publish:
    timeout-minutes: 5

Jobs that only run shell commands or Python scripts can rely on the GitHub default (6 hours) but consider setting a reasonable limit.

Adding a New Workflow

  1. Create .github/workflows/<name>.yaml
  2. Define the trigger (push, pull_request, release, workflow_dispatch)
  3. Set the minimum required permissions at job level
  4. Pin all actions to commit SHAs with version comments
  5. Add path filtering if the workflow only applies to specific file types
  6. Add concurrency control if the workflow could run redundantly
  7. Test the workflow on a branch before merging to main

Modifying an Existing Workflow

  1. Identify which workflow file to change
  2. Check if the change affects permissions — if adding a write operation, it may need to move to a separate job with elevated permissions
  3. If adding a new action, pin it to a commit SHA immediately
  4. If changing triggers, verify the workflow still runs when expected and does not run unnecessarily
  5. Test on a branch — push a PR to verify the workflow triggers correctly

Reviewing Workflow Changes

Check these in order:

  1. Are all actions SHA-pinned? Enforced automatically by verify-action-pins.yaml; rely on the gate instead of reviewing this by eye.
  2. Are permissions minimal? Does the workflow request more access than it needs? Does a write permission belong at job level instead of workflow level?
  3. Is the permission boundary maintained? Read-only analysis and write-capable publishing should be in separate jobs
  4. Are new environment variables validated? Scripts called by the workflow should check ${VAR:?} at the top
  5. Is path filtering appropriate? Does the workflow run on changes it does not need to process?
  6. Are concurrency groups set? Could rapid pushes cause redundant runs?

Common Mistakes

  • Using a tag reference (@v4) instead of a SHA — breaks reproducibility and is a security risk
  • Granting contents: write at workflow level when only one job needs it
  • Missing path filter — workflow runs on every PR even when irrelevant files changed
  • Forgetting to update the version comment after changing a SHA
  • Passing sensitive data through workflow outputs instead of artifacts
  • Missing timeout-minutes on jobs that call external APIs
  • Adding a new action without verifying its SHA from the official repository

Keep looking

Skills are one crate of 627,559. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.