The Action is the second distribution channel for GhostDeps, after the GitHub
App (ADR-0003: the app is primary). It exists for teams that refuse external
services: nothing leaves the runner, no app installation, no webhook endpoint.
The CLI does the analysis; the action posts one ghostdeps check run with the
same conclusions, summaries and annotations the app would produce.
name: ghostdeps
on:
pull_request:
push:
branches: [main]
permissions:
contents: read # actions/checkout
checks: write # create the ghostdeps check run
pull-requests: read # added-line lookup for PR annotations
jobs:
ghostdeps:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: rowkavdev/ghostdeps/packages/action@main
with:
path: "."
# fail-on: high # opt in to gating; advisory by defaultThe check is advisory: conclusions are success (quiet) or neutral, never
failure. Annotations appear only on high-confidence findings whose evidence
points at a line the PR added, capped at 50 per run - identical to the app.
The --json output is never filtered, so there is no severity input: the
check renderer already groups findings by confidence.
The check run labels the commit the workflow analysed (GITHUB_SHA). With
the default actions/checkout on pull_request that is the merge ref, so
the run sits on the merge commit like any other CI check. To analyse the PR
head instead, check out ${{ github.event.pull_request.head.sha }}
explicitly.
The action is pre-release and has no version tags yet: @main follows the
latest main. Pin a full commit SHA (rowkavdev/ghostdeps/packages/action@<sha>)
for production workflows.
| Input | Default | Purpose |
|---|---|---|
path |
. |
Directory to scan |
fail-on |
(empty) | Fail the step when a finding reaches this severity; empty = advisory |
disable-rule |
(empty) | Comma-separated rule ids to turn off |
allowlist |
(empty) | Comma-separated ecosystem:name entries marked as expected tooling |
fixture-roots |
(empty) | Per-run fixture-scope override (#354): bounded schema-versioned JSON with the .ghostdeps.json grammar; replaces the committed roots for the run, '{"schemaVersion":1,"fixtureRoots":[]}' clears them. Unset = the committed file governs |
check-name |
ghostdeps |
Name of the check run |
node-version |
22 |
Node.js for the analysis (engine requires >= 22) |
github-token |
github.token |
Token used to create the check run |
Outputs: conclusion (the posted check conclusion), scan-exit (the CLI's
exit code).
Choosing the Action means accepting these. They are structural to running as a workflow, not bugs.
- Fork pull requests get no check run. On
pull_requestevents from a fork,GITHUB_TOKENis read-only and cannot create check runs. The action still reads the PR's added lines (read access works) and degrades to workflow-command annotations on those lines (at most 10 notices, GitHub's per-step cap) plus the job summary. Install the GitHub App for full fork-PR coverage. - No re-run button semantics. The app's check runs can be re-run in isolation. A workflow's "Re-run jobs" re-runs the whole workflow - checkout, build, scan and all - and the check run exists only as output of that run.
- No cross-run result cache. The app serves repeat analyses of an unchanged head SHA from a cache (#174). The action analyses on every run. The workspace build is cached per action commit + lockfile + runner OS + Node version (#347), so repeat runs skip the install and build; the first run on a cold cache still pays the full build.
- No installation model. There is nothing to install and nothing that watches your repo: no push handling outside the workflows you write, no org-wide rollout, no per-installation settings. Configuration is the action's inputs, per workflow.
- Actions minutes are yours. Every run consumes your repo's Actions minutes, billed on private repositories. The app absorbs that cost instead.
action.yml is a composite action: it installs pnpm and Node 22, builds
@ghostdeps/cli and @ghostdeps/action from the pinned ref, runs
ghostdeps scan --json against your checkout, and hands the result to a small
poster that creates one completed check run through the Checks API with the
workflow's GITHUB_TOKEN. Rendering comes from @ghostdeps/checks-renderer,
the same package the app uses, so conclusions and annotation text cannot drift
between the two channels.