gh-action-pulse
gh-action-pulse scans a repository for GitHub Actions uses: references, checks them against the GitHub API, and rewrites them to safer or more current references when a better upstream target exists.
It is aimed at repositories that want to keep GitHub Actions dependencies understandable, current, and pinned with more confidence.
Key Features
- Automatic scanning: Detects
uses:statements across workflow and reusable action files. - Reference classification: Distinguishes whether an action is currently pinned to a commit SHA, tag, or branch.
- Recommendation engine: Looks up upstream metadata and recommends an updated reference based on available SemVer tags and branch state.
- Repository redirect handling: Rewrites moved repositories to their canonical name when GitHub reports a redirect.
- Freshness checks: Warns or fails when the newest eligible SemVer tag is older than your configured threshold.
- Node.js runtime check: Recursively verifies that actions, including composite and local composite dependencies, run on at least a configurable minimum Node.js version (
--minimum-nodejs-version, default24), failing with a dedicated exit code (3) when an outdated runtime is detected. - Comment preservation: Keeps extra trailing comments on
uses:lines (for examplegh-action-pulse: ignore[max-days]) when rewriting references.
How It Works
For each detected uses: line, gh-action-pulse:
- Finds GitHub Actions references in the configured workflow and action directories.
- Queries the GitHub API for the referenced repository.
- Detects whether the current reference is a tag, branch, or SHA.
- Selects the newest SemVer tag that is at least
--min-agedays old. - Falls back to a branch recommendation when that is safer or newer than the eligible tag.
- Rewrites redirected repositories to their canonical upstream name.
In practice, this means the tool can:
- convert branch or tag references into pinned SHAs annotated with the matching tag,
- preserve branch intent when no suitable tag exists,
- keep extra trailing comments such as ignore hints,
- surface stale upstream action releases with a non-zero exit code.
Example
Before:
- uses: google-github-actions/auth@v2
After:
- uses: google-github-actions/auth@<commit-sha> # v2.1.10
If an action repository has moved, the repository name may also be rewritten to the canonical upstream location.
Setup
gh-action-pulse talks to the GitHub API.
Set a token explicitly:
export GITHUB_TOKEN=your_github_token_here
If GITHUB_TOKEN is not set, the tool can fall back to using the GitHub CLI authentication flow when gh is available.
The project currently requires Python >= 3.14.
Installation
Install from PyPI with uv
uv tool install gh-action-pulse
Install from PyPI with pipx
pipx install gh-action-pulse
Install the local checkout
uv tool install . --force --reinstall
CLI Usage
Run against the current repository:
gh-action-pulse
Preview changes without writing files:
gh-action-pulse --dry-run
Require action tags to be at least 14 days old before they can be selected:
gh-action-pulse --min-age 14
Fail when the newest eligible tag is older than 180 days:
gh-action-pulse --min-age 14 --max-age 180
Require actions to run on at least Node.js 20:
gh-action-pulse --minimum-nodejs-version 20
Show more detail while debugging:
gh-action-pulse --log-level DEBUG
Print the installed version:
gh-action-pulse --version
Output
The CLI uses Rich for progress and summaries on stderr:
- a progress bar while enriching actions from the GitHub API (and while checking Node.js runtimes);
- colored phase lines for scan, freshness, and Node.js checks;
- a table of proposed or applied
uses:rewrites (yellow header in--dry-run); - a closing summary panel with update counts, warnings, and the exit code.
Routine per-file and per-action chatter is logged at DEBUG. Use --log-level DEBUG (or WARNING / ERROR) when you need diagnostic detail; warnings and errors still use Rich-formatted logging without repeating the main user-facing summary.
CLI Options
--dry-run(GH_ACTION_PULSE_DRY_RUN): show the updates without writing files.--log-level(GH_ACTION_PULSE_LOG_LEVEL): set the logging level (DEBUG,INFO,WARNING,ERROR,CRITICAL).--min-age(GH_ACTION_PULSE_MIN_AGE): require tags to be at least this many days old before recommending them.--max-age(GH_ACTION_PULSE_MAX_AGE): fail when the chosen--min-age-eligible upstream tag is older than this many days. Use0to disable the check.--minimum-nodejs-version(GH_ACTION_PULSE_MINIMUM_NODEJS_VERSION): fail when an action, or any of its composite/local dependencies, runs on a Node.js major version below this value (default24). Use0to disable the check.--version: print the package version and exit.
CLI flags override the matching environment variables when both are set.
Exit Codes
gh-action-pulse uses its exit code to signal the outcome of a run:
0: the run completed and no failing condition was detected.2: GitHub authentication failed (GITHUB_TOKENcould not be resolved).3: a Node.js runtime problem was detected in the repository. When an action, or any of its composite/local composite dependencies, runs on a Node.js major version below--minimum-nodejs-version(default24), the tool logs an error and exits with status3. Set--minimum-nodejs-version 0to disable this check.4: a referenced upstream action repository is archived.5: a--max-agestaleness failure occurred.
When multiple failing conditions are detected in the same run, the exit code with the lowest number is returned: authentication (2) and archived repositories (4) stop the run early, and among end-of-run checks the Node.js exit code (3) takes precedence over stale tags (5).
Limitations
- Local actions such as
./.github/actions/my-actionare not part of the GitHub API lookup flow. - Recommendations depend on repositories exposing usable SemVer tags.
- The tool needs GitHub API access, so rate limits and authentication still apply.
Node.js version check (--minimum-nodejs-version)
The Node.js runtime check does not inspect every uses: line in the repository. In practice it:
- only starts from remote GitHub Actions referenced as
owner/repo@ref(orowner/repo/path@ref) in.github/workflowsand.github/actions; - skips local actions such as
uses: ./.github/actions/my-actionbecause they do not match thename@referencepattern used during scanning; - inspects the recommended upstream reference (the one the tool would update to), not the currently pinned reference when a recommendation exists;
- only flags JavaScript actions whose manifest declares
runs.using: nodeXX(for examplenode20,node24); - skips Docker actions (
docker://), unresolvable references, missing manifests, and other non-nodeXXruntimes; - walks composite actions recursively and checks nested
uses:dependencies, including relative./pathsteps inside a remote composite action (resolved within that upstream repository); - does not meaningfully check reusable workflows referenced as
uses: org/repo/.github/workflows/foo.yml@ref, because it looks foraction.yml/action.yamlmanifests rather than workflow files.
Set --minimum-nodejs-version 0 to disable this check entirely.
Roadmap
Possible future improvements:
- Maybe Separate unit tests with appropriate workflow (pytest) if checks takes times
- Add E2E tests with appropriate workflow (pytest and/or bats)
- Change to versioned version of tools in mise.toml when near stable version (could depend on tools)
Potential future CLI options (to get the idea):
--config-file: load configuration, including ignore parameters or specific rules for some workflows (needs thinking).--only-workflow: restrict scanning to a specific workflow.--workflow-omit: exclude specific workflows from scanning.--github-action-omit: exclude specific GitHub Actions from the checks.
Contributing
Contributions are welcome. See CONTRIBUTING.md for the code layout, local setup, and the full list of linters and checks run in CI.
Release files for gh-action-pulse 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gh_action_pulse-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Release files / gh_action_pulse-1.2.0-py3-none-any.whl
| Download URL | gh_action_pulse-1.2.0-py3-none-any.whl |
|---|---|
| Size | 40.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
59618a207e71e575bbfe361aa2dd4f64cd0987e9c2a8f403c0e851472cfcfcb4
|
|
BLAKE2b-256 checksum How to use checksums |
85e1722fba708e235c2b23480d355e7d93b5c7987803bad0ef825cb6d05bf237
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.
Transparency log