LIVE REAL-REPO RUN — HIGHER-DENSITY DEMO · Ran the $79 GitHub Actions Cost Audit analyzer against github.com/huggingface/transformers (54 workflow files, 67 files scanned). 122 findings · $17,055/mo in estimated CI waste. Compare with vercel/next.js demo (56 findings, $8,215/mo — 0.46x findings, 0.48x $/mo). Same deterministic engine, two real public repos, very different findings — proves the analyzer doesn't manufacture findings. Order your own $79 audit →
SHARE THIS HONEST DEMO
Share on X Share on LinkedIn Share on Reddit
GitHub Actions Cost Audit · by Milo Antaeus

Your GitHub Actions Cost Audit Report

Static-analysis CI/CD cost audit · https://github.com/huggingface/transformers · Generated 2026-05-16 22:49 UTC

Workflows scanned: 54 Dockerfiles: 12 Patterns checked: 10 Confidence: deterministic (no LLM-in-the-loop)

Executive summary

122 ranked GitHub Actions cost-leak findings across 54 workflow file(s) (67 total files scanned, including 12 Dockerfile(s)). Implementing the top 3 could save approximately $17,055/month$204,660/year.

RECURRING GitHub Actions billing savings — verifiable in github.com/<org>/settings/billing next billing cycle. Estimates calibrated to per-minute runner rates ($0.008/min Linux, $0.016/min Windows, $0.08/min macOS) and conservative run frequency (~20 runs/day per push-triggered workflow).

#OpportunitySeverity$/mo saved
1Job `assign_reviewers` installs pip deps without cachingCRITICAL$250
2Job `benchmark` installs pip deps without cachingCRITICAL$250
3Job `benchmark-v2` installs pip deps without cachingCRITICAL$250
4Job `check_new_failures` installs pip deps without cachingCRITICAL$250
5Job `process_new_failures_with_commit_info` installs pip deps without cachingCRITICAL$250
TOTAL ESTIMATED MONTHLY SAVINGS: $17,055

Opportunity #1 — Job `assign_reviewers` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/assign-reviewers.yml:12

What we found: Job `assign_reviewers` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/assign-reviewers.yml:12)

jobs:
  assign_reviewers:
    permissions:
       pull-requests: write
    runs-on: ubuntu-22.04
    steps:

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #2 — Job `benchmark` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/benchmark.yml:1

What we found: Job `benchmark` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/benchmark.yml:1)

name: Self-hosted runner (benchmark)

on:
  push:
    branches: [main]

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #3 — Job `benchmark-v2` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/benchmark_v2.yml:43

What we found: Job `benchmark-v2` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/benchmark_v2.yml:43)

jobs:
  benchmark-v2:
    name: Benchmark v2
    runs-on: ${{ inputs.runner }}
    if: |
      (github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'run-benchmark')) ||

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #4 — Job `check_new_failures` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/check_failed_tests.yml:34

What we found: Job `check_new_failures` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/check_failed_tests.yml:34)

is_check_failures_ok:
        description: "Whether the failure checking infrastructure succeeded"
        value: ${{ jobs.check_new_failures.result != 'failure' && jobs.process_new_failures_with_commit_info.result != 'failure' }}

env:
  HF_HOME: /mnt/cache
  TRANSFORMERS_IS_CI: yes

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #5 — Job `process_new_failures_with_commit_info` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/check_failed_tests.yml:34

What we found: Job `process_new_failures_with_commit_info` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/check_failed_tests.yml:34)

is_check_failures_ok:
        description: "Whether the failure checking infrastructure succeeded"
        value: ${{ jobs.check_new_failures.result != 'failure' && jobs.process_new_failures_with_commit_info.result != 'failure' }}

env:
  HF_HOME: /mnt/cache
  TRANSFORMERS_IS_CI: yes

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #6 — Job `check_tiny_models` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/check_tiny_models.yml:6

What we found: Job `check_tiny_models` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/check_tiny_models.yml:6)

push:
    branches:
      - check_tiny_models*
  repository_dispatch:
  schedule:
    - cron: "0 2 * * *"

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #7 — Job `comment` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/circleci-failure-summary-comment.yml:11

What we found: Job `comment` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/circleci-failure-summary-comment.yml:11)

jobs:
  comment:
    runs-on: ubuntu-22.04
    permissions:
      pull-requests: write
    env:

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #8 — Job `collated_reports` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/collated-reports.yml:24

What we found: Job `collated_reports` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/collated-reports.yml:24)

jobs:
  collated_reports:
    name: Collated reports
    runs-on: ubuntu-22.04
    if: always()
    steps:

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #9 — Job `run_doctests` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/doctest_job.yml:25

What we found: Job `run_doctests` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/doctest_job.yml:25)

jobs:
  run_doctests:
    name: " "
    strategy:
      max-parallel: 8  # 8 jobs at a time
      fail-fast: false

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #10 — Job `setup` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/doctests.yml:18

What we found: Job `setup` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/doctests.yml:18)

jobs:
  setup:
    name: Setup
    runs-on: 
      group: aws-g5-4xlarge-cache
    container:

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #11 — Job `send_results` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/doctests.yml:69

What we found: Job `send_results` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/doctests.yml:69)

secrets: inherit

  send_results:
    name: Send results to webhook
    runs-on: ubuntu-22.04
    if: always()
    needs: [call_doctest_job]

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #12 — Job `get-python-versions` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/extras-smoke-test.yml:14

What we found: Job `get-python-versions` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/extras-smoke-test.yml:14)

jobs:
  get-python-versions:
    name: Get supported Python versions
    runs-on: ubuntu-latest
    outputs:
      versions: ${{ steps.extract-versions.outputs.versions }}

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #13 — Job `test-extras` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/extras-smoke-test.yml:37

What we found: Job `test-extras` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/extras-smoke-test.yml:37)

echo "versions=$VERSIONS" >> $GITHUB_OUTPUT

  test-extras:
    name: Test extras on Python ${{ matrix.python-version }}
    needs: get-python-versions
    runs-on: ubuntu-latest
    strategy:

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #14 — Job `run_models_gpu` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/model_jobs.yml:23

What we found: Job `run_models_gpu` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/model_jobs.yml:23)

report_name_prefix:
        required: false
        default: run_models_gpu
        type: string
      runner_type:
        required: false
        type: string

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #15 — Job `run_models_gpu` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/model_jobs_intel_gaudi.yml:20

What we found: Job `run_models_gpu` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/model_jobs_intel_gaudi.yml:20)

report_name_prefix:
        required: false
        default: run_models_gpu
        type: string

env:
  RUN_SLOW: yes

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #16 — Job `notify_new_model` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/new_model_pr_merged_notification.yml:15

What we found: Job `notify_new_model` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/new_model_pr_merged_notification.yml:15)

jobs:
  notify_new_model:
    name: Notify new model
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #17 — Job `run-repo-consistency-checks` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/pr-repo-consistency-bot.yml:117

What we found: Job `run-repo-consistency-checks` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/pr-repo-consistency-bot.yml:117)

core.setOutput('comment_id', botComment.id);

  run-repo-consistency-checks:
    runs-on: ubuntu-22.04
    needs: [get-pr-info, check-timestamps, init_comment_with_url]
    outputs:
      changes_detected: ${{ steps.run_repo_checks.outputs.changes_detected || steps.run_style_checks.outputs.changes_detected }}

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #18 — Job `build_and_test` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/release.yml:13

What we found: Job `build_and_test` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/release.yml:13)

jobs:
  build_and_test:
    name: build release
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #19 — Job `get-tests` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/self-comment-ci.yml:64

What we found: Job `get-tests` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/self-comment-ci.yml:64)

# use a python script to handle this complex logic.
  get-tests:
    runs-on: ubuntu-22.04
    needs: [get-pr-number, check-timestamps]
    outputs:
      models: ${{ steps.models_to_run.outputs.models }}

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #20 — Job `run_pipelines_torch_gpu` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/self-scheduled-intel-gaudi.yml:112

What we found: Job `run_pipelines_torch_gpu` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/self-scheduled-intel-gaudi.yml:112)

secrets: inherit

  run_pipelines_torch_gpu:
    if: ${{ inputs.job == 'run_pipelines_torch_gpu' }}
    name: Pipelines
    strategy:
      fail-fast: false

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #21 — Job `run_examples_gpu` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/self-scheduled-intel-gaudi.yml:182

What we found: Job `run_examples_gpu` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/self-scheduled-intel-gaudi.yml:182)

path: reports/${{ env.machine_type }}_run_pipelines_torch_gpu_test_reports

  run_examples_gpu:
    if: ${{ inputs.job == 'run_examples_gpu' }}
    name: Examples directory
    strategy:
      fail-fast: false

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #22 — Job `run_torch_cuda_extensions_gpu` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/self-scheduled-intel-gaudi.yml:255

What we found: Job `run_torch_cuda_extensions_gpu` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/self-scheduled-intel-gaudi.yml:255)

path: reports/${{ env.machine_type }}_run_examples_gpu_test_reports

  run_torch_cuda_extensions_gpu:
    if: ${{ inputs.job == 'run_torch_cuda_extensions_gpu' }}
    name: Intel Gaudi deepspeed tests
    strategy:
      fail-fast: false

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #23 — Job `run_torch_cuda_extensions_gpu` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/self-scheduled.yml:5

What we found: Job `run_torch_cuda_extensions_gpu` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/self-scheduled.yml:5)

# Note that each job's dependencies go into a corresponding docker file.
#
# For example for `run_torch_cuda_extensions_gpu` the docker image is
# `huggingface/transformers-pytorch-deepspeed-latest-gpu`, which can be found at
# `docker/transformers-pytorch-deepspeed-latest-gpu/Dockerfile`

on:

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #24 — Job `run_quantization_torch_gpu` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/self-scheduled.yml:71

What we found: Job `run_quantization_torch_gpu` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/self-scheduled.yml:71)

setup:
    name: Setup
    if: contains(fromJSON('["run_models_gpu", "run_trainer_and_fsdp_gpu", "run_quantization_torch_gpu"]'), inputs.job)
    strategy:
      matrix:
        machine_type: [aws-g5-4xlarge-cache, aws-g5-12xlarge-cache]
    runs-on:

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #25 — Job `run_pipelines_torch_gpu` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/self-scheduled.yml:178

What we found: Job `run_pipelines_torch_gpu` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/self-scheduled.yml:178)

secrets: inherit

  run_pipelines_torch_gpu:
    if: ${{ inputs.job == 'run_pipelines_torch_gpu' }}
    name: PyTorch pipelines
    strategy:
      fail-fast: false

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #26 — Job `run_examples_gpu` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/self-scheduled.yml:250

What we found: Job `run_examples_gpu` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/self-scheduled.yml:250)

path: /transformers/reports/${{ env.machine_type }}_run_pipelines_torch_gpu_test_reports

  run_examples_gpu:
    if: ${{ inputs.job == 'run_examples_gpu' }}
    name: Examples directory
    strategy:
      fail-fast: false

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #27 — Job `run_kernels_gpu` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/self-scheduled.yml:512

What we found: Job `run_kernels_gpu` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/self-scheduled.yml:512)

path: /transformers/reports/${{ env.machine_type }}_run_quantization_torch_gpu_${{ env.matrix_folders }}_test_reports

  run_kernels_gpu:
    if: ${{ inputs.job == 'run_kernels_gpu' }}
    name: Kernel tests
    strategy:
      fail-fast: false

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #28 — Job `run_extract_warnings` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/self-scheduled.yml:586

What we found: Job `run_extract_warnings` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/self-scheduled.yml:586)

path: /transformers/reports/${{ env.machine_type }}_run_kernels_gpu_test_reports

  run_extract_warnings:
    # Let's only do this for the job `run_models_gpu` to simplify the (already complex) logic.
    if: ${{ always() && inputs.job == 'run_models_gpu' }}
    name: Extract warnings in CI artifacts
    runs-on: ubuntu-22.04

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #29 — Job `send_results` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/slack-report.yml:32

What we found: Job `send_results` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/slack-report.yml:32)

outputs:
      is_slack_reporting_job_ok:
        description: "Whether the send_results job succeeded (not failed)"
        value: ${{ jobs.send_results.result != 'failure' }}

env:
  TRANSFORMERS_CI_RESULTS_UPLOAD_TOKEN: ${{ secrets.TRANSFORMERS_CI_RESULTS_UPLOAD_TOKEN }}

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #30 — Job `ssh_runner` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/ssh-runner.yml:56

What we found: Job `ssh_runner` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/ssh-runner.yml:56)

echo "RUNNER=$RUNNER" >> $GITHUB_OUTPUT

  ssh_runner:
    name: "SSH"
    needs: get_runner
    runs-on:
      group: ${{ needs.get_runner.outputs.RUNNER }}

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #31 — Job `close_stale_issues` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/stale.yml:11

What we found: Job `close_stale_issues` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/stale.yml:11)

jobs:
  close_stale_issues:
    name: Close Stale Issues
    if: github.repository == 'huggingface/transformers'
    runs-on: ubuntu-22.04
    permissions:

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #32 — Job `build_and_package` installs pip deps without caching $250/mo

Confidence: 85% · Rule: gha_cache_missing_for_package_manager
CRITICAL

Where: .github/workflows/update_metdata.yml:13

What we found: Job `build_and_package` runs `pip install` (or equivalent) on every workflow trigger but has neither `actions/cache@v*` nor a `setup-pip@v*` step with the `cache:` parameter. That means GitHub re-downloads and re-installs every dependency from scratch each run — typically 30-180 wasted seconds per job. At ~20 runs/day × 90s × $0.008/min for Linux, this single gap costs ~$72/mo per workflow. The fix is one step (or a `cache:` parameter on the existing setup-* action) — copy the After snippet into your workflow YAML.

Before (.github/workflows/update_metdata.yml:13)

jobs:
  build_and_package:
    runs-on: ubuntu-22.04
    defaults:
      run:
        shell: bash -l {0}

After

# Option A — built-in caching via setup-* action (preferred):
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'    # or 'yarn' / 'pnpm'

# Option B — standalone actions/cache step:
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Opportunity #33 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/add-model-like.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/add-model-like.yml:3)

name: Add model like runner

on:
  push:
    branches:
      - none # put main here when this is fixed
  #pull_request:

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #34 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/build-docker-images.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/build-docker-images.yml:3)

name: Build docker images (scheduled)

on:
  push:
    branches:
      - build_ci_docker_image*
  repository_dispatch:

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #35 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/build-nightly-ci-docker-images.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/build-nightly-ci-docker-images.yml:3)

name: Build docker images (Nightly CI)

on:
  workflow_call:
    inputs:
      job:
        required: true

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #36 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/build-past-ci-docker-images.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/build-past-ci-docker-images.yml:3)

name: Build docker images (Past CI)

on:
  push:
    branches:
      - build_past_ci_docker_image*

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #37 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/build_documentation.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/build_documentation.yml:3)

name: Build documentation

on:
  workflow_dispatch:
  push:
    branches:
      - main

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #38 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/check_tiny_models.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/check_tiny_models.yml:3)

name: Check Tiny Models

on:
  push:
    branches:
      - check_tiny_models*
  repository_dispatch:

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #39 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/codeql.yml:4

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/codeql.yml:4)

name: CodeQL Security Analysis

on:
  push:
    branches: ["main", "fix_security_issue_*"]
  # pull_request:
  #   branches: ["main"]

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #40 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/doctests.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/doctests.yml:3)

name: Doctests

on:
  push:
    branches:
      - run_doctest*
  repository_dispatch:

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #41 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/new_model_pr_merged_notification.yml:4

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/new_model_pr_merged_notification.yml:4)

name: New model PR merged notification

on:
  push:
    branches:
      - main
    paths:

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #42 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/push-important-models.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/push-important-models.yml:3)

name: Slow tests on important models (on Push - A10)

on:
  push:
    branches: [ main ]

permissions:

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #43 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/release-conda.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/release-conda.yml:3)

name: Release - Conda

on:
  push:
    tags:
      - v*
    branches:

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #44 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/release.yml:2

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/release.yml:2)

name: Release
on:
  push:
    tags:
      - v*
    branches:

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #45 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/self-nightly-caller.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/self-nightly-caller.yml:3)

name: Nvidia CI with nightly torch

on:
  repository_dispatch:
  # triggered when the daily scheduled Nvidia CI is completed.
  # This way, we can compare the results more easily.
  workflow_run:

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #46 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/self-nightly-past-ci-caller.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/self-nightly-past-ci-caller.yml:3)

name: Self-hosted runner (nightly-past-ci-caller)

on:
  schedule:
    - cron: "17 2,14 * * *"
  push:
    branches:

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #47 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/self-scheduled-amd-mi250-caller.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/self-scheduled-amd-mi250-caller.yml:3)

name: Self-hosted runner (AMD mi250 scheduled CI caller)

on:
  workflow_run:
    workflows: ["Self-hosted runner (AMD scheduled CI caller)"]
    branches: ["main"]
    types: [completed]

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #48 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/self-scheduled-amd-mi325-caller.yml:7

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/self-scheduled-amd-mi325-caller.yml:7)

#              2gpu scale set: amd-mi325-ci-2gpu

on:
  workflow_run:
    workflows: ["Self-hosted runner (AMD scheduled CI caller)"]
    branches: ["main"]
    types: [completed]

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #49 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/self-scheduled-amd-mi355-caller.yml:7

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/self-scheduled-amd-mi355-caller.yml:7)

#              2gpu : amd-mi355-ci-2gpu
 
on:
  workflow_run:
    workflows: ["Self-hosted runner (AMD scheduled CI caller)"]
    branches: ["main"]
    types: [completed]

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #50 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/self-scheduled-caller.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/self-scheduled-caller.yml:3)

name: Nvidia CI

on:
  repository_dispatch:
  schedule:
    - cron: "17 2 * * *"
  push:

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #51 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/self-scheduled-flash-attn-caller.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/self-scheduled-flash-attn-caller.yml:3)

name: Nvidia CI - Flash Attn

on:
  repository_dispatch:
  schedule:
    - cron: "17 2 * * *"
  push:

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #52 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/trufflehog.yml:1

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/trufflehog.yml:1)

on:
  push:

name: Secret Leaks

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #53 — Workflow runs on push/PR but doesn't cancel in-progress duplicate runs $200/mo

Confidence: 80% · Rule: gha_no_concurrency_cancel_in_progress
HIGH

Where: .github/workflows/update_metdata.yml:3

What we found: This workflow runs on `push` and/or `pull_request` but does not set `concurrency.cancel-in-progress: true`. Every push to a PR triggers a new run, and the older (now-obsolete) run keeps executing to completion. With ~5 PRs/day × 4 push events each, that's ~20 redundant runs/day that the next-newest push made irrelevant. Adding a 3-line `concurrency:` block at workflow scope tells GitHub to cancel earlier in-progress runs in the same group as soon as a newer one starts.

Before (.github/workflows/update_metdata.yml:3)

name: Update Transformers metadata

on:
  push:
    branches:
      - main
      - update_transformers_metadata*

After

# Add at workflow root (above `jobs:`):
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #54 — Docker build in job `latest-with-torch-nightly-docker` missing GHA layer cache $120/mo

Confidence: 75% · Rule: gha_docker_buildx_no_gha_cache
MEDIUM

Where: .github/workflows/build-nightly-ci-docker-images.yml:43

What we found: Job `latest-with-torch-nightly-docker` runs `docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6` without both `cache-from: type=gha` AND `cache-to: type=gha,mode=max`. Without GHA layer cache, every Docker build rebuilds all layers from scratch — for moderately complex images that's 5-15 minutes of compounded waste per run. The GHA cache type uses the free GitHub Actions Cache (no external registry needed). Add both keys to the step's `with:` block.

Before (.github/workflows/build-nightly-ci-docker-images.yml:43)

-
        name: Build and push
        uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1
        with:
          context: ./docker/transformers-all-latest-gpu
          build-args: |
            REF=main

After

- uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: myimage:latest
    cache-from: type=gha
    cache-to: type=gha,mode=max

Opportunity #55 — Docker build in job `nightly-torch-deepspeed-docker` missing GHA layer cache $120/mo

Confidence: 75% · Rule: gha_docker_buildx_no_gha_cache
MEDIUM

Where: .github/workflows/build-nightly-ci-docker-images.yml:43

What we found: Job `nightly-torch-deepspeed-docker` runs `docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6` without both `cache-from: type=gha` AND `cache-to: type=gha,mode=max`. Without GHA layer cache, every Docker build rebuilds all layers from scratch — for moderately complex images that's 5-15 minutes of compounded waste per run. The GHA cache type uses the free GitHub Actions Cache (no external registry needed). Add both keys to the step's `with:` block.

Before (.github/workflows/build-nightly-ci-docker-images.yml:43)

-
        name: Build and push
        uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1
        with:
          context: ./docker/transformers-all-latest-gpu
          build-args: |
            REF=main

After

- uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: myimage:latest
    cache-from: type=gha
    cache-to: type=gha,mode=max

Opportunity #56 — Docker build in job `past-pytorch-docker` missing GHA layer cache $120/mo

Confidence: 75% · Rule: gha_docker_buildx_no_gha_cache
MEDIUM

Where: .github/workflows/build-past-ci-docker-images.yml:52

What we found: Job `past-pytorch-docker` runs `docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6` without both `cache-from: type=gha` AND `cache-to: type=gha,mode=max`. Without GHA layer cache, every Docker build rebuilds all layers from scratch — for moderately complex images that's 5-15 minutes of compounded waste per run. The GHA cache type uses the free GitHub Actions Cache (no external registry needed). Add both keys to the step's `with:` block.

Before (.github/workflows/build-past-ci-docker-images.yml:52)

-
        name: Build and push
        uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1
        with:
          context: ./docker/transformers-past-gpu
          build-args: |
            REF=main

After

- uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: myimage:latest
    cache-from: type=gha
    cache-to: type=gha,mode=max

Opportunity #57 — Docker build in job `past-tensorflow-docker` missing GHA layer cache $120/mo

Confidence: 75% · Rule: gha_docker_buildx_no_gha_cache
MEDIUM

Where: .github/workflows/build-past-ci-docker-images.yml:52

What we found: Job `past-tensorflow-docker` runs `docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6` without both `cache-from: type=gha` AND `cache-to: type=gha,mode=max`. Without GHA layer cache, every Docker build rebuilds all layers from scratch — for moderately complex images that's 5-15 minutes of compounded waste per run. The GHA cache type uses the free GitHub Actions Cache (no external registry needed). Add both keys to the step's `with:` block.

Before (.github/workflows/build-past-ci-docker-images.yml:52)

-
        name: Build and push
        uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1
        with:
          context: ./docker/transformers-past-gpu
          build-args: |
            REF=main

After

- uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: myimage:latest
    cache-from: type=gha
    cache-to: type=gha,mode=max

Opportunity #58 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/add-model-like.yml:17

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/add-model-like.yml:17)

contents: read

jobs:
  run_tests_templates_like:
    name: "Add new model like template tests"
    runs-on: ubuntu-22.04
    steps:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #59 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/anti-slop.yml:12

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/anti-slop.yml:12)

types: [opened, reopened]

jobs:
  anti-slop:
    runs-on: ubuntu-latest
    steps:
      - uses: peakoss/anti-slop@85daca1880e9e1af197fc06ea03349daf08f4202 # v0.2.1

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #60 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/assign-reviewers.yml:11

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/assign-reviewers.yml:11)

contents: read

jobs:
  assign_reviewers:
    permissions:
       pull-requests: write
    runs-on: ubuntu-22.04

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #61 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/benchmark_v2.yml:42

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/benchmark_v2.yml:42)

contents: read

jobs:
  benchmark-v2:
    name: Benchmark v2
    runs-on: ${{ inputs.runner }}
    if: |

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #62 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/benchmark_v2_a10_caller.yml:9

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/benchmark_v2_a10_caller.yml:9)

contents: read

jobs:
  benchmark-v2-default:
    name: Benchmark v2 - Default Models
    uses: ./.github/workflows/benchmark_v2.yml
    with:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #63 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/benchmark_v2_mi325_caller.yml:9

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/benchmark_v2_mi325_caller.yml:9)

contents: read

jobs:
  benchmark-v2-default:
    name: Benchmark v2 - Default Models
    uses: ./.github/workflows/benchmark_v2.yml
    with:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #64 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/build_documentation.yml:15

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/build_documentation.yml:15)

contents: read

jobs:
   build:
    uses: huggingface/doc-builder/.github/workflows/build_main_documentation.yml@2430c1ec91d04667414e2fa31ecfc36c153ea391  # main
    with:
      commit_sha: ${{ github.sha }}

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #65 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/check-workflow-permissions.yml:18

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/check-workflow-permissions.yml:18)

contents: read

jobs:
  advisor:
    uses: huggingface/security-workflows/.github/workflows/permissions-advisor-reusable.yml@1b6a139c28db347498b30338da6a602e0a06f56c  # main
    permissions:
      actions: read

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #66 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/check_failed_tests.yml:52

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/check_failed_tests.yml:52)

contents: read

jobs:
  setup_check_new_failures:
    name: "Setup matrix for finding commits"
    runs-on: ubuntu-22.04
    outputs:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #67 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/check_tiny_models.yml:18

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/check_tiny_models.yml:18)

contents: read

jobs:
  check_tiny_models:
    name: Check tiny models
    runs-on: ubuntu-22.04
    steps:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #68 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/circleci-failure-summary-comment.yml:10

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/circleci-failure-summary-comment.yml:10)

contents: read

jobs:
  comment:
    runs-on: ubuntu-22.04
    permissions:
      pull-requests: write

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #69 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/codeql.yml:14

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/codeql.yml:14)

contents: read

jobs:
  codeql:
    name: CodeQL Analysis
    uses: huggingface/security-workflows/.github/workflows/codeql-reusable.yml@1b6a139c28db347498b30338da6a602e0a06f56c  # main
    permissions:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #70 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/collated-reports.yml:23

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/collated-reports.yml:23)

contents: read

jobs:
  collated_reports:
    name: Collated reports
    runs-on: ubuntu-22.04
    if: always()

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #71 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/doctest_job.yml:24

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/doctest_job.yml:24)

contents: read

jobs:
  run_doctests:
    name: " "
    strategy:
      max-parallel: 8  # 8 jobs at a time

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #72 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/doctests.yml:17

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/doctests.yml:17)

contents: read

jobs:
  setup:
    name: Setup
    runs-on: 
      group: aws-g5-4xlarge-cache

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #73 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/extras-smoke-test.yml:13

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/extras-smoke-test.yml:13)

contents: read

jobs:
  get-python-versions:
    name: Get supported Python versions
    runs-on: ubuntu-latest
    outputs:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #74 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/get-pr-info.yml:68

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/get-pr-info.yml:68)

contents: read

jobs:
  get-pr-info:
    runs-on: ubuntu-22.04
    name: Get PR commit SHA better
    outputs:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #75 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/get-pr-number.yml:12

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/get-pr-number.yml:12)

contents: read

jobs:
  get-pr-number:
    runs-on: ubuntu-22.04
    name: Get PR number
    outputs:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #76 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/model_jobs.yml:50

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/model_jobs.yml:50)

contents: read

jobs:
  run_models_gpu:
    name: " "
    strategy:
      max-parallel: 8

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #77 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/model_jobs_intel_gaudi.yml:34

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/model_jobs_intel_gaudi.yml:34)

contents: read

jobs:
  run_models_gpu:
    name: " "
    strategy:
      max-parallel: 8

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #78 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/new_model_pr_merged_notification.yml:14

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/new_model_pr_merged_notification.yml:14)

contents: read

jobs:
  notify_new_model:
    name: Notify new model
    runs-on: ubuntu-22.04
    steps:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #79 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/pr_slow_ci_suggestion.yml:9

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/pr_slow_ci_suggestion.yml:9)

contents: read

jobs:
  get-pr-number:
    name: Get PR number
    uses: ./.github/workflows/get-pr-number.yml

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #80 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/push-important-models.yml:10

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/push-important-models.yml:10)

contents: read

jobs:
  get_modified_models:
    name: "Get all modified files"
    runs-on: ubuntu-latest
    outputs:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #81 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/release-conda.yml:16

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/release-conda.yml:16)

contents: read

jobs:
  build_and_package:
    runs-on: ubuntu-22.04
    defaults:
      run:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #82 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/release.yml:12

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/release.yml:12)

contents: read

jobs:
  build_and_test:
    name: build release
    runs-on: ubuntu-latest
    steps:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #83 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/self-nightly-caller.yml:24

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/self-nightly-caller.yml:24)

contents: read

jobs:
  build_nightly_torch_ci_images:
    name: Build CI Docker Images with nightly torch
    uses: ./.github/workflows/build-nightly-ci-docker-images.yml
    with:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #84 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/self-nightly-past-ci-caller.yml:13

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/self-nightly-past-ci-caller.yml:13)

contents: read

jobs:
  get_number:
    name: Get number
    runs-on: ubuntu-22.04
    outputs:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #85 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/self-past-caller.yml:22

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/self-past-caller.yml:22)

contents: read

jobs:
  model-ci:
    name: Model CI
    uses: ./.github/workflows/self-scheduled.yml
    with:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #86 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/self-scheduled-amd-caller.yml:10

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/self-scheduled-amd-caller.yml:10)

contents: read

jobs:
  run_scheduled_amd_ci:
    name: Trigger Scheduled AMD CI
    runs-on: ubuntu-22.04
    if: ${{ always() }}

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #87 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/self-scheduled-amd-mi250-caller.yml:15

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/self-scheduled-amd-mi250-caller.yml:15)

contents: read

jobs:
  model-ci:
    name: Model CI
    uses: huggingface/hf-workflows/.github/workflows/transformers_amd_ci_scheduled.yaml@63657f571a92cc9759159442936061c51d6d9ae4 # main
    with:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #88 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/self-scheduled-amd-mi325-caller.yml:19

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/self-scheduled-amd-mi325-caller.yml:19)

contents: read

jobs:
  model-ci:
    name: Model CI
    uses: huggingface/hf-workflows/.github/workflows/transformers_amd_ci_scheduled_arc_scale_set.yaml@63657f571a92cc9759159442936061c51d6d9ae4 # main
    with:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #89 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/self-scheduled-amd-mi355-caller.yml:19

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/self-scheduled-amd-mi355-caller.yml:19)

contents: read

jobs:
  model-ci:
    name: Model CI
    uses: huggingface/hf-workflows/.github/workflows/transformers_amd_ci_scheduled_arc_scale_set.yaml@63657f571a92cc9759159442936061c51d6d9ae4 # main
    with:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #90 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/self-scheduled-caller.yml:33

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/self-scheduled-caller.yml:33)

contents: read

jobs:
  setup:
    name: Setup
    runs-on: ubuntu-22.04
    steps:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #91 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/self-scheduled-flash-attn-caller.yml:33

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/self-scheduled-flash-attn-caller.yml:33)

contents: read

jobs:
  setup:
    name: Setup
    runs-on: ubuntu-22.04
    steps:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #92 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/self-scheduled-intel-gaudi.yml:34

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/self-scheduled-intel-gaudi.yml:34)

contents: read

jobs:
  setup:
    if: contains(fromJSON('["run_models_gpu", "run_trainer_and_fsdp_gpu"]'), inputs.job)
    name: Setup
    runs-on: ubuntu-latest

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #93 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/self-scheduled-intel-gaudi3-caller.yml:12

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/self-scheduled-intel-gaudi3-caller.yml:12)

contents: read

jobs:
  model-ci:
    name: Model CI
    uses: ./.github/workflows/self-scheduled-intel-gaudi.yml
    with:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #94 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/self-scheduled.yml:68

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/self-scheduled.yml:68)

contents: read

jobs:
  setup:
    name: Setup
    if: contains(fromJSON('["run_models_gpu", "run_trainer_and_fsdp_gpu", "run_quantization_torch_gpu"]'), inputs.job)
    strategy:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #95 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/slack-report.yml:41

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/slack-report.yml:41)

contents: read

jobs:
  send_results:
    name: Send results to webhook
    runs-on: ubuntu-22.04
    if: always() && !cancelled()

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #96 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/ssh-runner.yml:29

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/ssh-runner.yml:29)

contents: read

jobs:
  get_runner:
    name: "Get runner to use"
    runs-on: ubuntu-22.04
    outputs:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #97 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/stale.yml:10

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/stale.yml:10)

contents: read

jobs:
  close_stale_issues:
    name: Close Stale Issues
    if: github.repository == 'huggingface/transformers'
    runs-on: ubuntu-22.04

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #98 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/trl-ci-bot.yml:16

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/trl-ci-bot.yml:16)

issues: read

jobs:
  dispatch:
    if: >
      github.event.issue.pull_request &&
      contains(github.event.comment.body, '/trl-ci')

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #99 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/trufflehog.yml:9

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/trufflehog.yml:9)

contents: read

jobs:
  trufflehog:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #100 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/update_metdata.yml:12

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/update_metdata.yml:12)

contents: read

jobs:
  build_and_package:
    runs-on: ubuntu-22.04
    defaults:
      run:

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #101 — Workflow has no `concurrency:` block (no run-grouping at all) $80/mo

Confidence: 65% · Rule: gha_missing_concurrency_group
MEDIUM

Where: .github/workflows/upload_pr_documentation.yml:12

What we found: This workflow has no `concurrency:` block. Beyond `cancel-in-progress` (covered by the gha_no_concurrency_cancel_in_progress rule), a `group:` declaration prevents two unrelated invocations of the same workflow from racing each other in cases like rapid-fire reruns or webhook duplicates. Adding a concurrency group is also a prerequisite for `cancel-in-progress: true` to have any effect. Best practice: add a workflow-scope group keyed on github.workflow + github.ref.

Before (.github/workflows/upload_pr_documentation.yml:12)

contents: read

jobs:
  build:
    uses: huggingface/doc-builder/.github/workflows/upload_pr_documentation.yml@9ad2de8582b56c017cb530c1165116d40433f1c6  # main
    with:
      package_name: transformers

After

# Add above `jobs:`:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Opportunity #102 — Job `run_models_gpu` uses fetch-depth: 0 (full history clone) $60/mo

Confidence: 75% · Rule: gha_fetch_depth_zero
MEDIUM

Where: .github/workflows/model_jobs_intel_gaudi.yml:78

What we found: Job `run_models_gpu` clones the full repository history (fetch-depth: 0). On a large or long-lived repo, this can add 60-180s per job vs the default shallow clone (fetch-depth: 1). Full history is only needed for specific tasks: semver detection from tags, release-please, conventional-commits changelog generation, or `git log`-based diff analysis. If your workflow doesn't do any of those, set fetch-depth: 1 (or remove the `with:` block to use the default).

Before (.github/workflows/model_jobs_intel_gaudi.yml:78)

uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: Install dependencies
        run: |

After

- uses: actions/checkout@v4
  with:
    fetch-depth: 1    # default — was: 0

Opportunity #103 — Job `notify_new_model` uses fetch-depth: 0 (full history clone) $60/mo

Confidence: 75% · Rule: gha_fetch_depth_zero
MEDIUM

Where: .github/workflows/new_model_pr_merged_notification.yml:21

What we found: Job `notify_new_model` clones the full repository history (fetch-depth: 0). On a large or long-lived repo, this can add 60-180s per job vs the default shallow clone (fetch-depth: 1). Full history is only needed for specific tasks: semver detection from tags, release-please, conventional-commits changelog generation, or `git log`-based diff analysis. If your workflow doesn't do any of those, set fetch-depth: 1 (or remove the `with:` block to use the default).

Before (.github/workflows/new_model_pr_merged_notification.yml:21)

- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
        with:
          fetch-depth: 0
          persist-credentials: false
      - name: Check new model
        shell: bash
        run: |

After

- uses: actions/checkout@v4
  with:
    fetch-depth: 1    # default — was: 0

Opportunity #104 — Job `get-jobs` uses fetch-depth: 0 (full history clone) $60/mo

Confidence: 75% · Rule: gha_fetch_depth_zero
MEDIUM

Where: .github/workflows/pr_slow_ci_suggestion.yml:32

What we found: Job `get-jobs` clones the full repository history (fetch-depth: 0). On a large or long-lived repo, this can add 60-180s per job vs the default shallow clone (fetch-depth: 1). Full history is only needed for specific tasks: semver detection from tags, release-please, conventional-commits changelog generation, or `git log`-based diff analysis. If your workflow doesn't do any of those, set fetch-depth: 1 (or remove the `with:` block to use the default).

Before (.github/workflows/pr_slow_ci_suggestion.yml:32)

- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
        with:
          fetch-depth: "0"
          persist-credentials: false

      # Refetch the PR file list from the API instead of receiving it as an
      # input from `get-pr-info.yml`. The previous approaches either expanded

After

- uses: actions/checkout@v4
  with:
    fetch-depth: 1    # default — was: 0

Opportunity #105 — Job `get-tests` uses fetch-depth: 0 (full history clone) $60/mo

Confidence: 75% · Rule: gha_fetch_depth_zero
MEDIUM

Where: .github/workflows/self-comment-ci.yml:73

What we found: Job `get-tests` clones the full repository history (fetch-depth: 0). On a large or long-lived repo, this can add 60-180s per job vs the default shallow clone (fetch-depth: 1). Full history is only needed for specific tasks: semver detection from tags, release-please, conventional-commits changelog generation, or `git log`-based diff analysis. If your workflow doesn't do any of those, set fetch-depth: 1 (or remove the `with:` block to use the default).

Before (.github/workflows/self-comment-ci.yml:73)

- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
        with:
          fetch-depth: "0"
          ref: "refs/pull/${{ needs.get-pr-number.outputs.PR_NUMBER }}/merge"
          persist-credentials: false

      - name: Verify merge commit SHA

After

- uses: actions/checkout@v4
  with:
    fetch-depth: 1    # default — was: 0

Opportunity #106 — Job `setup` uses fetch-depth: 0 (full history clone) $60/mo

Confidence: 75% · Rule: gha_fetch_depth_zero
MEDIUM

Where: .github/workflows/self-scheduled-intel-gaudi.yml:47

What we found: Job `setup` clones the full repository history (fetch-depth: 0). On a large or long-lived repo, this can add 60-180s per job vs the default shallow clone (fetch-depth: 1). Full history is only needed for specific tasks: semver detection from tags, release-please, conventional-commits changelog generation, or `git log`-based diff analysis. If your workflow doesn't do any of those, set fetch-depth: 1 (or remove the `with:` block to use the default).

Before (.github/workflows/self-scheduled-intel-gaudi.yml:47)

uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: Set up Python
        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0

After

- uses: actions/checkout@v4
  with:
    fetch-depth: 1    # default — was: 0

Opportunity #107 — Job `run_pipelines_torch_gpu` uses fetch-depth: 0 (full history clone) $60/mo

Confidence: 75% · Rule: gha_fetch_depth_zero
MEDIUM

Where: .github/workflows/self-scheduled-intel-gaudi.yml:47

What we found: Job `run_pipelines_torch_gpu` clones the full repository history (fetch-depth: 0). On a large or long-lived repo, this can add 60-180s per job vs the default shallow clone (fetch-depth: 1). Full history is only needed for specific tasks: semver detection from tags, release-please, conventional-commits changelog generation, or `git log`-based diff analysis. If your workflow doesn't do any of those, set fetch-depth: 1 (or remove the `with:` block to use the default).

Before (.github/workflows/self-scheduled-intel-gaudi.yml:47)

uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: Set up Python
        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0

After

- uses: actions/checkout@v4
  with:
    fetch-depth: 1    # default — was: 0

Opportunity #108 — Job `run_examples_gpu` uses fetch-depth: 0 (full history clone) $60/mo

Confidence: 75% · Rule: gha_fetch_depth_zero
MEDIUM

Where: .github/workflows/self-scheduled-intel-gaudi.yml:47

What we found: Job `run_examples_gpu` clones the full repository history (fetch-depth: 0). On a large or long-lived repo, this can add 60-180s per job vs the default shallow clone (fetch-depth: 1). Full history is only needed for specific tasks: semver detection from tags, release-please, conventional-commits changelog generation, or `git log`-based diff analysis. If your workflow doesn't do any of those, set fetch-depth: 1 (or remove the `with:` block to use the default).

Before (.github/workflows/self-scheduled-intel-gaudi.yml:47)

uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: Set up Python
        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0

After

- uses: actions/checkout@v4
  with:
    fetch-depth: 1    # default — was: 0

Opportunity #109 — Job `run_torch_cuda_extensions_gpu` uses fetch-depth: 0 (full history clone) $60/mo

Confidence: 75% · Rule: gha_fetch_depth_zero
MEDIUM

Where: .github/workflows/self-scheduled-intel-gaudi.yml:47

What we found: Job `run_torch_cuda_extensions_gpu` clones the full repository history (fetch-depth: 0). On a large or long-lived repo, this can add 60-180s per job vs the default shallow clone (fetch-depth: 1). Full history is only needed for specific tasks: semver detection from tags, release-please, conventional-commits changelog generation, or `git log`-based diff analysis. If your workflow doesn't do any of those, set fetch-depth: 1 (or remove the `with:` block to use the default).

Before (.github/workflows/self-scheduled-intel-gaudi.yml:47)

uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: Set up Python
        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0

After

- uses: actions/checkout@v4
  with:
    fetch-depth: 1    # default — was: 0

Opportunity #110 — Job `trufflehog` uses fetch-depth: 0 (full history clone) $60/mo

Confidence: 75% · Rule: gha_fetch_depth_zero
MEDIUM

Where: .github/workflows/trufflehog.yml:16

What we found: Job `trufflehog` clones the full repository history (fetch-depth: 0). On a large or long-lived repo, this can add 60-180s per job vs the default shallow clone (fetch-depth: 1). Full history is only needed for specific tasks: semver detection from tags, release-please, conventional-commits changelog generation, or `git log`-based diff analysis. If your workflow doesn't do any of those, set fetch-depth: 1 (or remove the `with:` block to use the default).

Before (.github/workflows/trufflehog.yml:16)

uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
        with:
          fetch-depth: 0
          persist-credentials: false
      - name: Secret Scanning
        uses: trufflesecurity/trufflehog@6bd2d14f7a4bc1e569fa3550efa7ec632a4fa67b  # main
        with:

After

- uses: actions/checkout@v4
  with:
    fetch-depth: 1    # default — was: 0

Opportunity #111 — Job `build_and_test` uploads artifact containing `build/` (likely bloated) $40/mo

Confidence: 60% · Rule: gha_artifact_upload_bloat
MEDIUM

Where: .github/workflows/release.yml:42

What we found: Artifact upload in job `build_and_test` includes `build/` — a directory that is typically large and easily regenerated. Artifact storage is billed at $0.25/GB/mo above the free tier, and the upload step itself slows the workflow linearly with size. node_modules / target / __pycache__ / dist/coverage / .next/cache should generally NOT be uploaded — they're derivable from source + lockfiles. If you need to share build output, upload the final dist/, .next/standalone, or compiled binaries — not the cache or intermediate trees.

Before (.github/workflows/release.yml:42)

- name: Upload build artifacts
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4.6.2
        with:
          name: python-dist
          path: |
            dist/**

After

- uses: actions/upload-artifact@v4
  with:
    name: build-output
    path: |
      dist/
      !dist/coverage    # exclude bloat
      build/release/    # final artifacts only

Opportunity #112 — Job `benchmark` runs `pip install` 2 times in the same job $25/mo

Confidence: 55% · Rule: gha_redundant_dependency_install
LOW

Where: .github/workflows/benchmark.yml:1

What we found: Job `benchmark` runs `pip install` 2 times across its steps. Almost always the second + third invocations are redundant — the first install already populated node_modules / .venv / vendor/. Each redundant install is 30-60 seconds of compounded waste, billed to your account on every workflow run. Consolidate to a single install step near the top of the job, then reference the installed deps in downstream steps.

Before (.github/workflows/benchmark.yml:1)

name: Self-hosted runner (benchmark)

on:
  push:
    branches: [main]

After

# Single install step at top of job:
- name: Install dependencies
  run: pip install

# Downstream steps use the already-installed deps:
- name: Lint
  run: npm run lint
- name: Test
  run: npm test

Opportunity #113 — Job `benchmark-v2` runs `pip install` 2 times in the same job $25/mo

Confidence: 55% · Rule: gha_redundant_dependency_install
LOW

Where: .github/workflows/benchmark_v2.yml:43

What we found: Job `benchmark-v2` runs `pip install` 2 times across its steps. Almost always the second + third invocations are redundant — the first install already populated node_modules / .venv / vendor/. Each redundant install is 30-60 seconds of compounded waste, billed to your account on every workflow run. Consolidate to a single install step near the top of the job, then reference the installed deps in downstream steps.

Before (.github/workflows/benchmark_v2.yml:43)

jobs:
  benchmark-v2:
    name: Benchmark v2
    runs-on: ${{ inputs.runner }}
    if: |
      (github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'run-benchmark')) ||

After

# Single install step at top of job:
- name: Install dependencies
  run: pip install

# Downstream steps use the already-installed deps:
- name: Lint
  run: npm run lint
- name: Test
  run: npm test

Opportunity #114 — Job `check_new_failures` runs `pip install` 2 times in the same job $25/mo

Confidence: 55% · Rule: gha_redundant_dependency_install
LOW

Where: .github/workflows/check_failed_tests.yml:34

What we found: Job `check_new_failures` runs `pip install` 2 times across its steps. Almost always the second + third invocations are redundant — the first install already populated node_modules / .venv / vendor/. Each redundant install is 30-60 seconds of compounded waste, billed to your account on every workflow run. Consolidate to a single install step near the top of the job, then reference the installed deps in downstream steps.

Before (.github/workflows/check_failed_tests.yml:34)

is_check_failures_ok:
        description: "Whether the failure checking infrastructure succeeded"
        value: ${{ jobs.check_new_failures.result != 'failure' && jobs.process_new_failures_with_commit_info.result != 'failure' }}

env:
  HF_HOME: /mnt/cache
  TRANSFORMERS_IS_CI: yes

After

# Single install step at top of job:
- name: Install dependencies
  run: pip install

# Downstream steps use the already-installed deps:
- name: Lint
  run: npm run lint
- name: Test
  run: npm test

Opportunity #115 — Job `test-extras` runs `pip install` 3 times in the same job $25/mo

Confidence: 55% · Rule: gha_redundant_dependency_install
LOW

Where: .github/workflows/extras-smoke-test.yml:37

What we found: Job `test-extras` runs `pip install` 3 times across its steps. Almost always the second + third invocations are redundant — the first install already populated node_modules / .venv / vendor/. Each redundant install is 30-60 seconds of compounded waste, billed to your account on every workflow run. Consolidate to a single install step near the top of the job, then reference the installed deps in downstream steps.

Before (.github/workflows/extras-smoke-test.yml:37)

echo "versions=$VERSIONS" >> $GITHUB_OUTPUT

  test-extras:
    name: Test extras on Python ${{ matrix.python-version }}
    needs: get-python-versions
    runs-on: ubuntu-latest
    strategy:

After

# Single install step at top of job:
- name: Install dependencies
  run: pip install

# Downstream steps use the already-installed deps:
- name: Lint
  run: npm run lint
- name: Test
  run: npm test

Opportunity #116 — Job `run_models_gpu` runs `pip install` 3 times in the same job $25/mo

Confidence: 55% · Rule: gha_redundant_dependency_install
LOW

Where: .github/workflows/model_jobs.yml:23

What we found: Job `run_models_gpu` runs `pip install` 3 times across its steps. Almost always the second + third invocations are redundant — the first install already populated node_modules / .venv / vendor/. Each redundant install is 30-60 seconds of compounded waste, billed to your account on every workflow run. Consolidate to a single install step near the top of the job, then reference the installed deps in downstream steps.

Before (.github/workflows/model_jobs.yml:23)

report_name_prefix:
        required: false
        default: run_models_gpu
        type: string
      runner_type:
        required: false
        type: string

After

# Single install step at top of job:
- name: Install dependencies
  run: pip install

# Downstream steps use the already-installed deps:
- name: Lint
  run: npm run lint
- name: Test
  run: npm test

Opportunity #117 — Job `run-repo-consistency-checks` runs `pip install` 2 times in the same job $25/mo

Confidence: 55% · Rule: gha_redundant_dependency_install
LOW

Where: .github/workflows/pr-repo-consistency-bot.yml:117

What we found: Job `run-repo-consistency-checks` runs `pip install` 2 times across its steps. Almost always the second + third invocations are redundant — the first install already populated node_modules / .venv / vendor/. Each redundant install is 30-60 seconds of compounded waste, billed to your account on every workflow run. Consolidate to a single install step near the top of the job, then reference the installed deps in downstream steps.

Before (.github/workflows/pr-repo-consistency-bot.yml:117)

core.setOutput('comment_id', botComment.id);

  run-repo-consistency-checks:
    runs-on: ubuntu-22.04
    needs: [get-pr-info, check-timestamps, init_comment_with_url]
    outputs:
      changes_detected: ${{ steps.run_repo_checks.outputs.changes_detected || steps.run_style_checks.outputs.changes_detected }}

After

# Single install step at top of job:
- name: Install dependencies
  run: pip install

# Downstream steps use the already-installed deps:
- name: Lint
  run: npm run lint
- name: Test
  run: npm test

Opportunity #118 — Job `build_and_test` runs `pip install` 5 times in the same job $25/mo

Confidence: 55% · Rule: gha_redundant_dependency_install
LOW

Where: .github/workflows/release.yml:13

What we found: Job `build_and_test` runs `pip install` 5 times across its steps. Almost always the second + third invocations are redundant — the first install already populated node_modules / .venv / vendor/. Each redundant install is 30-60 seconds of compounded waste, billed to your account on every workflow run. Consolidate to a single install step near the top of the job, then reference the installed deps in downstream steps.

Before (.github/workflows/release.yml:13)

jobs:
  build_and_test:
    name: build release
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2

After

# Single install step at top of job:
- name: Install dependencies
  run: pip install

# Downstream steps use the already-installed deps:
- name: Lint
  run: npm run lint
- name: Test
  run: npm test

Opportunity #119 — Job `run_examples_gpu` runs `pip install` 2 times in the same job $25/mo

Confidence: 55% · Rule: gha_redundant_dependency_install
LOW

Where: .github/workflows/self-scheduled-intel-gaudi.yml:182

What we found: Job `run_examples_gpu` runs `pip install` 2 times across its steps. Almost always the second + third invocations are redundant — the first install already populated node_modules / .venv / vendor/. Each redundant install is 30-60 seconds of compounded waste, billed to your account on every workflow run. Consolidate to a single install step near the top of the job, then reference the installed deps in downstream steps.

Before (.github/workflows/self-scheduled-intel-gaudi.yml:182)

path: reports/${{ env.machine_type }}_run_pipelines_torch_gpu_test_reports

  run_examples_gpu:
    if: ${{ inputs.job == 'run_examples_gpu' }}
    name: Examples directory
    strategy:
      fail-fast: false

After

# Single install step at top of job:
- name: Install dependencies
  run: pip install

# Downstream steps use the already-installed deps:
- name: Lint
  run: npm run lint
- name: Test
  run: npm test

Opportunity #120 — Job `run_torch_cuda_extensions_gpu` runs `pip install` 4 times in the same job $25/mo

Confidence: 55% · Rule: gha_redundant_dependency_install
LOW

Where: .github/workflows/self-scheduled.yml:5

What we found: Job `run_torch_cuda_extensions_gpu` runs `pip install` 4 times across its steps. Almost always the second + third invocations are redundant — the first install already populated node_modules / .venv / vendor/. Each redundant install is 30-60 seconds of compounded waste, billed to your account on every workflow run. Consolidate to a single install step near the top of the job, then reference the installed deps in downstream steps.

Before (.github/workflows/self-scheduled.yml:5)

# Note that each job's dependencies go into a corresponding docker file.
#
# For example for `run_torch_cuda_extensions_gpu` the docker image is
# `huggingface/transformers-pytorch-deepspeed-latest-gpu`, which can be found at
# `docker/transformers-pytorch-deepspeed-latest-gpu/Dockerfile`

on:

After

# Single install step at top of job:
- name: Install dependencies
  run: pip install

# Downstream steps use the already-installed deps:
- name: Lint
  run: npm run lint
- name: Test
  run: npm test

Opportunity #121 — Job `run_examples_gpu` runs `pip install` 2 times in the same job $25/mo

Confidence: 55% · Rule: gha_redundant_dependency_install
LOW

Where: .github/workflows/self-scheduled.yml:250

What we found: Job `run_examples_gpu` runs `pip install` 2 times across its steps. Almost always the second + third invocations are redundant — the first install already populated node_modules / .venv / vendor/. Each redundant install is 30-60 seconds of compounded waste, billed to your account on every workflow run. Consolidate to a single install step near the top of the job, then reference the installed deps in downstream steps.

Before (.github/workflows/self-scheduled.yml:250)

path: /transformers/reports/${{ env.machine_type }}_run_pipelines_torch_gpu_test_reports

  run_examples_gpu:
    if: ${{ inputs.job == 'run_examples_gpu' }}
    name: Examples directory
    strategy:
      fail-fast: false

After

# Single install step at top of job:
- name: Install dependencies
  run: pip install

# Downstream steps use the already-installed deps:
- name: Lint
  run: npm run lint
- name: Test
  run: npm test

Opportunity #122 — Job `run_kernels_gpu` runs `pip install` 2 times in the same job $25/mo

Confidence: 55% · Rule: gha_redundant_dependency_install
LOW

Where: .github/workflows/self-scheduled.yml:512

What we found: Job `run_kernels_gpu` runs `pip install` 2 times across its steps. Almost always the second + third invocations are redundant — the first install already populated node_modules / .venv / vendor/. Each redundant install is 30-60 seconds of compounded waste, billed to your account on every workflow run. Consolidate to a single install step near the top of the job, then reference the installed deps in downstream steps.

Before (.github/workflows/self-scheduled.yml:512)

path: /transformers/reports/${{ env.machine_type }}_run_quantization_torch_gpu_${{ env.matrix_folders }}_test_reports

  run_kernels_gpu:
    if: ${{ inputs.job == 'run_kernels_gpu' }}
    name: Kernel tests
    strategy:
      fail-fast: false

After

# Single install step at top of job:
- name: Install dependencies
  run: pip install

# Downstream steps use the already-installed deps:
- name: Lint
  run: npm run lint
- name: Test
  run: npm test

How GitHub Actions billing works

GitHub bills runner usage per-minute, scoped to the account or organization that owns the repo. For private repos beyond the included free minutes:

Public repos get unlimited free minutes on GitHub-hosted runners, but private repos and self-hosted-fallback setups still benefit from these fixes because every wasted minute is either billed or competing for runner capacity.

The fastest single-fix wins (in dollar order): cut macOS matrix axes that don't need them, cache package-manager installs, enable concurrency.cancel-in-progress on push/PR triggers, and add GHA cache to Docker builds. Verify each fix's impact in github.com/<org>/settings/billing on the next billing cycle — the line item is itemized by runner OS.

30-day re-audit voucher

Included with your $79 audit: a voucher for a free re-audit 30 days after delivery. Implement the recommended workflow changes, then re-submit the same repo URL via reply email — we re-run the analysis and confirm the cost-leak patterns are resolved. If we still flag any of the CRITICAL findings from this report, refund issued automatically.

Why this matters: GitHub Actions savings only materialize once the workflow YAML changes ship to main. The re-audit voucher creates an accountability loop — we can't claim "issue resolved" unless the v1 ruleset agrees on re-scan. Same deterministic engine, same file paths, same line numbers. No moving goalposts.