nodejs/node GitHub Actions scorecard

Public GitHub Actions data, last 30 days. Updated .

Data sourced from public GitHub. GitSpider is not affiliated with or endorsed by this repository's owners. Request removal.

427 min/mo
recoverable (~4% of CI time) · across 29 patterns · ≈$3/mo
Estimated from wall-clock time · public repos pay $0, $ = private-repo equivalent
See all 29 fixes, each with the exact YAML ↓
1.8%
failure rate, 30d
3m
avg time to recover from a failure
Since : findings 31 → 29 · recoverable ~501 → ~427 min/mo
55 workflows · 500 runs (16.7/day) · 10,540 CI-min (wall-clock) · ≈$63 at private-repo rates (30d)

Where the minutes go (30d)

Test Shared libraries~1,979 min · 24 runs
Coverage Linux~1,803 min · 22 runs
Test Linux~1,660 min · 31 runs
or track on every push →

Waste detected

Biggest wins first, each with the exact config fix.

Missing dependency cache · Test macOS

~402 min/mo · ≈$2/mo

Set `cache: 'pip'` on your `actions/setup-python` step, or add an `actions/cache@v4` step keyed on your requirements/lock file.

- uses: actions/setup-python@v5
  with:
    python-version: '3.12'
    cache: 'pip'

Full guide: how to fix this →

Missing dependency cache · Commit Queue

~19 min/mo

Set `cache: 'npm'` on your `actions/setup-node` step, or add an `actions/cache@v4` step keyed on your lockfile.

- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'

Full guide: how to fix this →

Concurrency without cancel-in-progress · Commit Queue

~6 min/mo

Concurrency group has no `cancel-in-progress: true`, so superseded runs queue instead of cancelling. Add it to supersede stale runs.

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

Full guide: how to fix this →

Also found: 26 more config fixes with negligible recoverable minutes: timeouts, retention, path filters

No job timeout · First commit message adheres to guidelines

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

No job timeout · Linters

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

No path filters on triggers · Linters

~0 min/mo

Runs on every push/PR with no `paths:` filter, so docs-only changes still trigger full CI. Add a `paths:` filter if that's common.

on:
  pull_request:
    paths:
      - 'src/**'
      - 'package.json'

Full guide: how to fix this →

No job timeout · Test Linux

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

No job timeout · Test macOS

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

Premium runners (macOS / Windows) · Test macOS

~0 min/mo

macOS bills ~10x and Windows ~2x a Linux minute. The cost estimate above assumes Linux, so your real spend is higher. Move any job that doesn't need them to `ubuntu-latest`.

jobs:
  build:
    runs-on: ubuntu-latest  # ~10x cheaper than macos-latest

Full guide: how to fix this →

No job timeout · Build from tarball

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

Artifacts at default retention · Build from tarball

~0 min/mo

`upload-artifact` has no `retention-days`, so artifacts keep up to 90 days (storage cost). Set e.g. `retention-days: 7`.

- uses: actions/upload-artifact@v4
  with:
    name: build
    path: dist/
    retention-days: 7

Full guide: how to fix this →

No job timeout · Commit Queue

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

No job timeout · Coverage Linux

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

No job timeout · Coverage Windows

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

Premium runners (macOS / Windows) · Coverage Windows

~0 min/mo

macOS bills ~10x and Windows ~2x a Linux minute. The cost estimate above assumes Linux, so your real spend is higher. Move any job that doesn't need them to `ubuntu-latest`.

jobs:
  build:
    runs-on: ubuntu-latest  # ~10x cheaper than macos-latest

Full guide: how to fix this →

No job timeout · Label PRs

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

No concurrency control · Comment on issues and PRs when labeled

~0 min/mo

Add a `concurrency:` block keyed on branch to cancel superseded runs when devs push twice quickly.

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

Full guide: how to fix this →

No job timeout · Comment on issues and PRs when labeled

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

No job timeout · Test and upload documentation to artifacts

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

Artifacts at default retention · Test and upload documentation to artifacts

~0 min/mo

`upload-artifact` has no `retention-days`, so artifacts keep up to 90 days (storage cost). Set e.g. `retention-days: 7`.

- uses: actions/upload-artifact@v4
  with:
    name: build
    path: dist/
    retention-days: 7

Full guide: how to fix this →

No path filters on triggers · Test and upload documentation to artifacts

~0 min/mo

Runs on every push/PR with no `paths:` filter, so docs-only changes still trigger full CI. Add a `paths:` filter if that's common.

on:
  pull_request:
    paths:
      - 'src/**'
      - 'package.json'

Full guide: how to fix this →

No job timeout · Notify on Push

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

No job timeout · Scorecard supply-chain security

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

No concurrency control · Notify on Review Wanted

~0 min/mo

Add a `concurrency:` block keyed on branch to cancel superseded runs when devs push twice quickly.

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

Full guide: how to fix this →

No job timeout · Notify on Review Wanted

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

No job timeout · Test Shared libraries

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

Artifacts at default retention · Test Shared libraries

~0 min/mo

`upload-artifact` has no `retention-days`, so artifacts keep up to 90 days (storage cost). Set e.g. `retention-days: 7`.

- uses: actions/upload-artifact@v4
  with:
    name: build
    path: dist/
    retention-days: 7

Full guide: how to fix this →

Premium runners (macOS / Windows) · Test Shared libraries

~0 min/mo

macOS bills ~10x and Windows ~2x a Linux minute. The cost estimate above assumes Linux, so your real spend is higher. Move any job that doesn't need them to `ubuntu-latest`.

jobs:
  build:
    runs-on: ubuntu-latest  # ~10x cheaper than macos-latest

Full guide: how to fix this →

No job timeout · Contributor guidance

~0 min/mo

No job sets `timeout-minutes`, so a hung step can run to GitHub's 6-hour default. Add `timeout-minutes` to each job.

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

Full guide: how to fix this →

Copy every fix as one block (8 snippets, annotated per workflow)
# Missing dependency cache (pip) (applies to: Test macOS)
- uses: actions/setup-python@v5
  with:
    python-version: '3.12'
    cache: 'pip'

# Missing dependency cache (npm) (applies to: Commit Queue)
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'

# Concurrency without cancel-in-progress (applies to: Commit Queue)
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

# No job timeout (applies to: First commit message adheres to guidelines, Linters, Test Linux, Test macOS, Build from tarball, Commit Queue, Coverage Linux, Coverage Windows, Label PRs, Comment on issues and PRs when labeled, Test and upload documentation to artifacts, Notify on Push, Scorecard supply-chain security, Notify on Review Wanted, Test Shared libraries, Contributor guidance)
jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15

# No path filters on triggers (applies to: Linters, Test and upload documentation to artifacts)
on:
  pull_request:
    paths:
      - 'src/**'
      - 'package.json'

# Premium runners (macOS / Windows) (applies to: Test macOS, Coverage Windows, Test Shared libraries)
jobs:
  build:
    runs-on: ubuntu-latest  # ~10x cheaper than macos-latest

# Artifacts at default retention (applies to: Build from tarball, Test and upload documentation to artifacts, Test Shared libraries)
- uses: actions/upload-artifact@v4
  with:
    name: build
    path: dist/
    retention-days: 7

# No concurrency control (applies to: Comment on issues and PRs when labeled, Notify on Review Wanted)
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Each snippet is representative. Merge into the named workflow files rather than pasting wholesale.

Add the badge to your README

Live CI-health badge → GitSpider badge

[![GitSpider](https://gitspider.com/badge/nodejs/node.svg)](https://gitspider.com/scan/nodejs/node)

Want this on every push?

This scorecard is a one-time snapshot. Install the free GitHub App to track this repo continuously: new regressions caught as they land, trends over time, on your public and private repos. Team adds the offending commit on the PR + Slack alerts.

Install & monitor this repo →

💬 On Team, every PR gets an automatic comment when its CI run fails or runs slow, right where your team already looks. See plans →

Not ready to install? Get this report by email. No spam, unsubscribe anytime.

Share this scorecard: https://gitspider.com/scan/nodejs/node