Static-analysis CI/CD cost audit · https://github.com/huggingface/transformers · Generated 2026-05-16 22:49 UTC
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).
| # | Opportunity | Severity | $/mo saved |
|---|---|---|---|
| 1 | Job `assign_reviewers` installs pip deps without caching | CRITICAL | $250 |
| 2 | Job `benchmark` installs pip deps without caching | CRITICAL | $250 |
| 3 | Job `benchmark-v2` installs pip deps without caching | CRITICAL | $250 |
| 4 | Job `check_new_failures` installs pip deps without caching | CRITICAL | $250 |
| 5 | Job `process_new_failures_with_commit_info` installs pip deps without caching | CRITICAL | $250 |
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.
jobs:
assign_reviewers:
permissions:
pull-requests: write
runs-on: ubuntu-22.04
steps:
# 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') }}
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.
name: Self-hosted runner (benchmark)
on:
push:
branches: [main]
# 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') }}
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.
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')) ||
# 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') }}
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.
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
# 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') }}
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.
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
# 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') }}
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.
push:
branches:
- check_tiny_models*
repository_dispatch:
schedule:
- cron: "0 2 * * *"
# 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') }}
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.
jobs:
comment:
runs-on: ubuntu-22.04
permissions:
pull-requests: write
env:
# 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') }}
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.
jobs:
collated_reports:
name: Collated reports
runs-on: ubuntu-22.04
if: always()
steps:
# 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') }}
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.
jobs:
run_doctests:
name: " "
strategy:
max-parallel: 8 # 8 jobs at a time
fail-fast: false
# 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') }}
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.
jobs:
setup:
name: Setup
runs-on:
group: aws-g5-4xlarge-cache
container:
# 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') }}
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.
secrets: inherit
send_results:
name: Send results to webhook
runs-on: ubuntu-22.04
if: always()
needs: [call_doctest_job]
# 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') }}
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.
jobs:
get-python-versions:
name: Get supported Python versions
runs-on: ubuntu-latest
outputs:
versions: ${{ steps.extract-versions.outputs.versions }}
# 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') }}
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.
echo "versions=$VERSIONS" >> $GITHUB_OUTPUT
test-extras:
name: Test extras on Python ${{ matrix.python-version }}
needs: get-python-versions
runs-on: ubuntu-latest
strategy:
# 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') }}
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.
report_name_prefix:
required: false
default: run_models_gpu
type: string
runner_type:
required: false
type: string
# 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') }}
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.
report_name_prefix:
required: false
default: run_models_gpu
type: string
env:
RUN_SLOW: yes
# 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') }}
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.
jobs:
notify_new_model:
name: Notify new model
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
# 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') }}
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.
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 }}
# 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') }}
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.
jobs:
build_and_test:
name: build release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# 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') }}
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.
# 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 }}
# 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') }}
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.
secrets: inherit
run_pipelines_torch_gpu:
if: ${{ inputs.job == 'run_pipelines_torch_gpu' }}
name: Pipelines
strategy:
fail-fast: false
# 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') }}
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.
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
# 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') }}
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.
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
# 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') }}
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.
# 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:
# 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') }}
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.
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:
# 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') }}
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.
secrets: inherit
run_pipelines_torch_gpu:
if: ${{ inputs.job == 'run_pipelines_torch_gpu' }}
name: PyTorch pipelines
strategy:
fail-fast: false
# 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') }}
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.
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
# 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') }}
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.
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
# 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') }}
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.
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
# 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') }}
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.
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 }}
# 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') }}
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.
echo "RUNNER=$RUNNER" >> $GITHUB_OUTPUT
ssh_runner:
name: "SSH"
needs: get_runner
runs-on:
group: ${{ needs.get_runner.outputs.RUNNER }}
# 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') }}
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.
jobs:
close_stale_issues:
name: Close Stale Issues
if: github.repository == 'huggingface/transformers'
runs-on: ubuntu-22.04
permissions:
# 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') }}
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.
jobs:
build_and_package:
runs-on: ubuntu-22.04
defaults:
run:
shell: bash -l {0}
# 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') }}
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.
name: Add model like runner
on:
push:
branches:
- none # put main here when this is fixed
#pull_request:
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Build docker images (scheduled)
on:
push:
branches:
- build_ci_docker_image*
repository_dispatch:
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Build docker images (Nightly CI)
on:
workflow_call:
inputs:
job:
required: true
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Build docker images (Past CI)
on:
push:
branches:
- build_past_ci_docker_image*
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Build documentation
on:
workflow_dispatch:
push:
branches:
- main
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Check Tiny Models
on:
push:
branches:
- check_tiny_models*
repository_dispatch:
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: CodeQL Security Analysis
on:
push:
branches: ["main", "fix_security_issue_*"]
# pull_request:
# branches: ["main"]
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Doctests
on:
push:
branches:
- run_doctest*
repository_dispatch:
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: New model PR merged notification
on:
push:
branches:
- main
paths:
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Slow tests on important models (on Push - A10)
on:
push:
branches: [ main ]
permissions:
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Release - Conda
on:
push:
tags:
- v*
branches:
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Release
on:
push:
tags:
- v*
branches:
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
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:
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Self-hosted runner (nightly-past-ci-caller)
on:
schedule:
- cron: "17 2,14 * * *"
push:
branches:
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Self-hosted runner (AMD mi250 scheduled CI caller)
on:
workflow_run:
workflows: ["Self-hosted runner (AMD scheduled CI caller)"]
branches: ["main"]
types: [completed]
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
# 2gpu scale set: amd-mi325-ci-2gpu
on:
workflow_run:
workflows: ["Self-hosted runner (AMD scheduled CI caller)"]
branches: ["main"]
types: [completed]
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
# 2gpu : amd-mi355-ci-2gpu
on:
workflow_run:
workflows: ["Self-hosted runner (AMD scheduled CI caller)"]
branches: ["main"]
types: [completed]
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Nvidia CI
on:
repository_dispatch:
schedule:
- cron: "17 2 * * *"
push:
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Nvidia CI - Flash Attn
on:
repository_dispatch:
schedule:
- cron: "17 2 * * *"
push:
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
on: push: name: Secret Leaks
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
name: Update Transformers metadata
on:
push:
branches:
- main
- update_transformers_metadata*
# Add at workflow root (above `jobs:`):
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
-
name: Build and push
uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1
with:
context: ./docker/transformers-all-latest-gpu
build-args: |
REF=main
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myimage:latest
cache-from: type=gha
cache-to: type=gha,mode=max
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.
-
name: Build and push
uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1
with:
context: ./docker/transformers-all-latest-gpu
build-args: |
REF=main
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myimage:latest
cache-from: type=gha
cache-to: type=gha,mode=max
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.
-
name: Build and push
uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1
with:
context: ./docker/transformers-past-gpu
build-args: |
REF=main
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myimage:latest
cache-from: type=gha
cache-to: type=gha,mode=max
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.
-
name: Build and push
uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1
with:
context: ./docker/transformers-past-gpu
build-args: |
REF=main
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myimage:latest
cache-from: type=gha
cache-to: type=gha,mode=max
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.
contents: read
jobs:
run_tests_templates_like:
name: "Add new model like template tests"
runs-on: ubuntu-22.04
steps:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
types: [opened, reopened]
jobs:
anti-slop:
runs-on: ubuntu-latest
steps:
- uses: peakoss/anti-slop@85daca1880e9e1af197fc06ea03349daf08f4202 # v0.2.1
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
assign_reviewers:
permissions:
pull-requests: write
runs-on: ubuntu-22.04
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
benchmark-v2:
name: Benchmark v2
runs-on: ${{ inputs.runner }}
if: |
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
benchmark-v2-default:
name: Benchmark v2 - Default Models
uses: ./.github/workflows/benchmark_v2.yml
with:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
benchmark-v2-default:
name: Benchmark v2 - Default Models
uses: ./.github/workflows/benchmark_v2.yml
with:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
build:
uses: huggingface/doc-builder/.github/workflows/build_main_documentation.yml@2430c1ec91d04667414e2fa31ecfc36c153ea391 # main
with:
commit_sha: ${{ github.sha }}
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
advisor:
uses: huggingface/security-workflows/.github/workflows/permissions-advisor-reusable.yml@1b6a139c28db347498b30338da6a602e0a06f56c # main
permissions:
actions: read
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
setup_check_new_failures:
name: "Setup matrix for finding commits"
runs-on: ubuntu-22.04
outputs:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
check_tiny_models:
name: Check tiny models
runs-on: ubuntu-22.04
steps:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
comment:
runs-on: ubuntu-22.04
permissions:
pull-requests: write
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
codeql:
name: CodeQL Analysis
uses: huggingface/security-workflows/.github/workflows/codeql-reusable.yml@1b6a139c28db347498b30338da6a602e0a06f56c # main
permissions:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
collated_reports:
name: Collated reports
runs-on: ubuntu-22.04
if: always()
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
run_doctests:
name: " "
strategy:
max-parallel: 8 # 8 jobs at a time
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
setup:
name: Setup
runs-on:
group: aws-g5-4xlarge-cache
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
get-python-versions:
name: Get supported Python versions
runs-on: ubuntu-latest
outputs:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
get-pr-info:
runs-on: ubuntu-22.04
name: Get PR commit SHA better
outputs:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
get-pr-number:
runs-on: ubuntu-22.04
name: Get PR number
outputs:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
run_models_gpu:
name: " "
strategy:
max-parallel: 8
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
run_models_gpu:
name: " "
strategy:
max-parallel: 8
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
notify_new_model:
name: Notify new model
runs-on: ubuntu-22.04
steps:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
get-pr-number:
name: Get PR number
uses: ./.github/workflows/get-pr-number.yml
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
get_modified_models:
name: "Get all modified files"
runs-on: ubuntu-latest
outputs:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
build_and_package:
runs-on: ubuntu-22.04
defaults:
run:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
build_and_test:
name: build release
runs-on: ubuntu-latest
steps:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
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:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
get_number:
name: Get number
runs-on: ubuntu-22.04
outputs:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
model-ci:
name: Model CI
uses: ./.github/workflows/self-scheduled.yml
with:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
run_scheduled_amd_ci:
name: Trigger Scheduled AMD CI
runs-on: ubuntu-22.04
if: ${{ always() }}
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
model-ci:
name: Model CI
uses: huggingface/hf-workflows/.github/workflows/transformers_amd_ci_scheduled.yaml@63657f571a92cc9759159442936061c51d6d9ae4 # main
with:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
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:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
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:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
setup:
name: Setup
runs-on: ubuntu-22.04
steps:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
setup:
name: Setup
runs-on: ubuntu-22.04
steps:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
setup:
if: contains(fromJSON('["run_models_gpu", "run_trainer_and_fsdp_gpu"]'), inputs.job)
name: Setup
runs-on: ubuntu-latest
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
model-ci:
name: Model CI
uses: ./.github/workflows/self-scheduled-intel-gaudi.yml
with:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
setup:
name: Setup
if: contains(fromJSON('["run_models_gpu", "run_trainer_and_fsdp_gpu", "run_quantization_torch_gpu"]'), inputs.job)
strategy:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
send_results:
name: Send results to webhook
runs-on: ubuntu-22.04
if: always() && !cancelled()
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
get_runner:
name: "Get runner to use"
runs-on: ubuntu-22.04
outputs:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
close_stale_issues:
name: Close Stale Issues
if: github.repository == 'huggingface/transformers'
runs-on: ubuntu-22.04
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
issues: read
jobs:
dispatch:
if: >
github.event.issue.pull_request &&
contains(github.event.comment.body, '/trl-ci')
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
trufflehog:
runs-on: ubuntu-latest
steps:
- name: Checkout code
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
build_and_package:
runs-on: ubuntu-22.04
defaults:
run:
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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.
contents: read
jobs:
build:
uses: huggingface/doc-builder/.github/workflows/upload_pr_documentation.yml@9ad2de8582b56c017cb530c1165116d40433f1c6 # main
with:
package_name: transformers
# Add above `jobs:`:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
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).
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
fetch-depth: 0
persist-credentials: false
- name: Install dependencies
run: |
- uses: actions/checkout@v4
with:
fetch-depth: 1 # default — was: 0
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).
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
fetch-depth: 0
persist-credentials: false
- name: Check new model
shell: bash
run: |
- uses: actions/checkout@v4
with:
fetch-depth: 1 # default — was: 0
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).
- 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
- uses: actions/checkout@v4
with:
fetch-depth: 1 # default — was: 0
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).
- 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
- uses: actions/checkout@v4
with:
fetch-depth: 1 # default — was: 0
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).
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
- uses: actions/checkout@v4
with:
fetch-depth: 1 # default — was: 0
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).
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
- uses: actions/checkout@v4
with:
fetch-depth: 1 # default — was: 0
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).
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
- uses: actions/checkout@v4
with:
fetch-depth: 1 # default — was: 0
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).
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
- uses: actions/checkout@v4
with:
fetch-depth: 1 # default — was: 0
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).
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: Secret Scanning
uses: trufflesecurity/trufflehog@6bd2d14f7a4bc1e569fa3550efa7ec632a4fa67b # main
with:
- uses: actions/checkout@v4
with:
fetch-depth: 1 # default — was: 0
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.
- name: Upload build artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: python-dist
path: |
dist/**
- uses: actions/upload-artifact@v4
with:
name: build-output
path: |
dist/
!dist/coverage # exclude bloat
build/release/ # final artifacts only
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.
name: Self-hosted runner (benchmark)
on:
push:
branches: [main]
# 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
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.
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')) ||
# 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
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.
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
# 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
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.
echo "versions=$VERSIONS" >> $GITHUB_OUTPUT
test-extras:
name: Test extras on Python ${{ matrix.python-version }}
needs: get-python-versions
runs-on: ubuntu-latest
strategy:
# 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
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.
report_name_prefix:
required: false
default: run_models_gpu
type: string
runner_type:
required: false
type: string
# 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
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.
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 }}
# 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
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.
jobs:
build_and_test:
name: build release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# 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
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.
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
# 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
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.
# 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:
# 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
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.
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
# 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
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.
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
# 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
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.
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.