Docs / Integrations / GitHub Action
GitHub Action
Run kedgeway on every pull request and fail the build when a finding meets your threshold, or run it on a schedule and let it open the migration pull request.
Quick start
kedgeway initThis writes .github/workflows/kedgeway.yml, pinned to the installed version. Then add the secret: run kedgeway login --export and save its output as a repository secret named KEDGEWAY_AUTH. Use --print to preview the YAML and --force to overwrite an existing file. See Commands.
Use it
- uses: actions/checkout@v4
- uses: Klorenn/kedgeway@v0.1.0
with:
path: .
fail-on: warning
auth: ${{ secrets.KEDGEWAY_AUTH }} # live Raven data; or use fixture: for offlinePin a release tag as above. @main is unpinned and can change under you.
Inputs and outputs
| Input | Default | Meaning |
|---|---|---|
mode | diagnose | diagnose reports findings. pr opens or updates a pull request with the migration edits. See Open a migration PR. |
path | . | Directory to scan. |
repo | none | Repository URL or owner/repo to scan instead of path. It is shallow-cloned and deleted afterwards. Annotations are not emitted for it, because its paths are not in the checkout. |
fail-on | warning | Fail on any finding at or above this severity. Empty disables. |
fixture | none | Ecosystem snapshot JSON (offline). Set this or auth. |
auth | none | Raven credentials from kedgeway login --export, as a secret. Set this or fixture. |
json | false | Print JSON instead of text. |
sarif | false | Also write SARIF 2.1.0 to $RUNNER_TEMP/kedgeway.sarif. |
version | the pinned tag | kedgeway version to run. Accepts a semver such as 1.2.3, or source to force the source build. |
annotations | on in Actions | Emit a GitHub annotation, with file and line, for each finding. Set "false" to disable. |
pr-base | none | mode: pr only. Branch the pull request targets. Empty uses the repository's default branch. |
pr-branch | none | mode: pr only. Head branch to push. Empty uses kedgeway/migrate-<major>. Force-pushed with a lease; must start with kedgeway/. |
pr-draft | false | mode: pr only. Open the pull request as a draft. |
refresh-lockfiles | false | mode: pr only. Also refresh the lockfiles the plan touched, when the tool is installed on the runner. |
token | ${{ github.token }} | mode: pr only. GitHub token used to push and to call the API. Defaults to the workflow token. |
Outputs: summary (for example critical=0 warning=1 info=2), report-json (the path of the JSON report under RUNNER_TEMP) and sarif (the SARIF file path, only when sarif is on). With mode: pr, also pr-url and pr-action.
Auth or a fixture is required
The action needs one of two inputs, and names both if neither is set.
auth: yourKEDGEWAY_AUTHsecret, for live Raven data. Export it withkedgeway login --export.fixture: a committed snapshot (see Fixtures). Offline and deterministic; you refresh it.
Annotations
With annotations on, which is the default when the action runs on GitHub, each finding becomes a workflow command pointing at the dependency's line in its manifest. Critical is ::error, warning is ::warning, info is ::notice. On a pull request they show on the changed files in the diff. No extra permission or step is needed.
- GitHub caps annotations at 10 per type (error, warning, notice) per step and 50 per job. A large repo shows only the first ones; the full report is still printed in the log.
- Findings that are not about a file, such as
DATA_DEGRADEDandNO_SDK_FOUND, have no file and show on the run instead. - The line comes from a plain scan of the manifest (the first matching key), so it is best effort. Paths are relative to the directory the action runs from.
- Finding text is sanitised before it is printed, so a manifest cannot inject workflow commands.
Outside Actions, use kedgeway diagnose --format annotations or --annotations <file>. See Commands. SARIF below is separate and stays: it feeds code scanning, annotations feed the diff.
Open a migration PR
With mode: pr the action runs kedgeway pr: when your SDK versions are behind, it pushes the branch kedgeway/migrate-<major> and opens one pull request with the edits, the findings, the manual steps as a checklist and the migration guide. Later runs update the same pull request. When there is nothing to edit, the run is skipped. The repo input is not supported here, because a pull request needs the local checkout. See Commands for the full flow.
kedgeway init --mode prname: kedgeway-pr
on:
schedule:
- cron: "0 9 * * 1"
workflow_dispatch:
permissions:
contents: write
pull-requests: write
concurrency:
group: kedgeway-pr
cancel-in-progress: false
jobs:
kedgeway-pr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- uses: Klorenn/kedgeway@v0.3.0
with:
mode: pr
auth: ${{ secrets.KEDGEWAY_AUTH }}kedgeway init --mode pr writes this file as .github/workflows/kedgeway-pr.yml, pinned to the installed version. It runs every Monday at 09:00 UTC and on demand. Add the KEDGEWAY_AUTH secret as for diagnose.
It needs:
permissions: contents: writeandpull-requests: writeon the workflow or job. The generated file sets them.actions/checkoutwithfetch-depth: 0, so the base branch history is available to branch from.persist-credentials: falseon the checkout, so no token is left in.git/config. The generated workflow sets it.- A
concurrencygroup,kedgeway-pr, so two runs never overlap. The generated workflow sets it. - A push host of
github.com, or the host ofGITHUB_API_URLon GitHub Enterprise Server. Otherwise the run exits 2 and the token is never sent. - With
refresh-lockfiles, Yarn 1 is skipped and Yarn 2+ runs with scripts disabled. - The repository setting "Allow GitHub Actions to create and approve pull requests" (Settings, Actions, General, Workflow permissions). An organization must allow it first at the organization level. Without it GitHub answers
403; kedgeway prints GitHub's message with a hint pointing at this setting and exits 1.
In mode: pr the action also sets pr-url (the pull request that was created or updated, empty when skipped) and pr-action (create, update or skip).
SARIF and code scanning
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- id: kedgeway
uses: Klorenn/kedgeway@v0.1.0
with:
auth: ${{ secrets.KEDGEWAY_AUTH }}
sarif: "true"
fail-on: "" # let the upload step report instead of failing here
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: ${{ steps.kedgeway.outputs.sarif }}The log has one run for the tool kedgeway, a rule per finding code (18), and one result per finding with the repo-relative manifest path. Critical is an error, warning is a warning, info is a note. Findings that are not about a file, such as DATA_DEGRADED and NO_SDK_FOUND, have no location.
Exit codes and speed
The action runs diagnose once, always writes its outputs, then exits with the CLI's code: 0 when nothing met the threshold, 2 when a finding did, 1 on a tool error. Pinning a release tag (uses: Klorenn/kedgeway@v1.2.3) installs exactly that version from npm with no build step, and fails with a clear error if the version is not published. Any other ref (@main, a commit SHA, a branch) builds the checked-out source with npm ci && npm run build, which is slower, and @main is unpinned. The npm install path applies to tags cut after this change; v0.1.0 still builds from source.
With mode: pr it runs kedgeway pr instead: 0 when the pull request was created or updated, or the run was skipped; 1 on a git or API failure; 2 on a usage error.