@kenai-platform/check-exact-packages
v2.0.0
Published
Enforce exact dependency versions in package.json files — allow-list of exact semver, catalog: and workspace: specs
Readme
@kenai-platform/check-exact-packages
A CLI tool to enforce exact dependency versions in all package.json files across your repository. This helps ensure reproducible builds and prevents unexpected dependency updates.
What it does
- Scans all
package.jsonfiles in the repository (including nested ones) - Checks
dependencies,devDependenciesandoptionalDependencies, each section separately - Skips
peerDependencies, where ranges like>=5are correct - Fails the check if any spec is not pinned
- Provides detailed output naming the file, the section and the offending spec
What passes
| Spec | Example |
|---|---|
| Exact semver | 1.2.3 |
| Exact prerelease / build metadata | 10.0.0-preview.14, 1.0.0+build.1 |
| Catalog protocol | catalog:, catalog:react |
| Workspace protocol | workspace:*, workspace:1.0.0 |
Everything else fails — this is an allow-list, not a blocklist. That includes
^1.0.0, ~1.0.0, dist-tags (preview, latest, next, canary), wildcards
(*, ""), ranges (>=1.0.0, 1.x, 1 || 2), partial versions (8.5), and
git / URL / npm: alias specs.
Installation
Install the package from npm:
npm install --save-dev @kenai-platform/check-exact-packagesOr with bun:
bun add -d @kenai-platform/check-exact-packagesUsage
1. CLI Command
After installation, you can run the check from anywhere in your repository:
With npm/npx:
npx @kenai-platform/check-exact-packagesWith bun/bunx:
bunx @kenai-platform/check-exact-packagesIf installed globally:
npm install -g @kenai-platform/check-exact-packages
check-exact-packagesThe command will:
- Scan all
package.jsonfiles in your repository - Report any non-exact versions found
- Exit with code 1 if violations are found, 0 if all versions are exact
2. Preinstall Script (Run Without Installation)
You can run the check as a preinstall script without installing the package. This is useful for CI/CD pipelines or to enforce the check before dependencies are installed.
In your package.json:
{
"scripts": {
"preinstall": "npx @kenai-platform/check-exact-packages"
}
}Or with bun:
{
"scripts": {
"preinstall": "bunx @kenai-platform/check-exact-packages"
}
}Note: The preinstall script runs automatically before npm install or bun install. If non-exact versions are found, the installation will fail.
3. GitHub Actions Workflow
Add a GitHub Actions workflow to automatically check for exact versions on pull requests and pushes:
Create .github/workflows/check-exact-versions.yml:
name: Check Exact Versions
on:
pull_request:
paths:
- '**/package.json'
push:
branches: [main, master]
paths:
- '**/package.json'
jobs:
check-versions:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Run check-exact-packages
run: npx @kenai-platform/check-exact-packages4. Pre-commit Hook
Using pre-commit.com
Add this to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/kenai-platform/check-exact-packages
rev: v2.0.0 # Use the latest version tag
hooks:
- id: check-exact-packagesThen install and run:
pre-commit install
pre-commit run check-exact-packages --all-filesThe hook will automatically run before each commit.
Using Husky
If you're using Husky in your project:
Install the package:
npm install --save-dev @kenai-platform/check-exact-packagesAdd to your
.husky/pre-commitfile:#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" npx check-exact-packages || exit 1Or with bun:
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" bunx @kenai-platform/check-exact-packages || exit 1
The hook will automatically run before each commit.
Prerequisites
- jq: Required to parse JSON files
- Pre-installed on GitHub Actions
ubuntu-latestrunners - For local use, install via:
brew install jq(macOS) orapt-get install jq(Linux)
- Pre-installed on GitHub Actions
- git: Required to find
package.jsonfiles (usesgit ls-files) - bash: Required to run the script
Example Output
When non-exact versions are found:
package.json has packages with non-exact versions:
• express: ^4.18.0
• lodash: ~4.17.21
Error: Use exact versions (no ^ or ~) in package.json filesWhen all versions are exact:
✓ All package.json files use exact versionsReleasing
Releases are automated with release-please. Nobody edits the version by hand and nobody runs npm publish.
The loop:
- Land a Conventional Commit on
main—fix:,feat:, or anything with!/BREAKING CHANGE:for a major. - release-please opens (or updates) a release PR with the next version and a generated
CHANGELOG.md. - Merge that release PR when you want to ship. That tags the commit, cuts a GitHub Release, and publishes to npm.
Which commit prefix moves which number:
| Prefix | Bump | Example |
|---|---|---|
| fix: | patch | fix: handle empty dependency blocks |
| feat: | minor | feat: report the dependency section on failure |
| feat!: / BREAKING CHANGE: | major | feat!: reject dist-tags and ranges |
| chore:, docs:, ci:, refactor: | none | housekeeping, no release |
Commits that don't parse as Conventional Commits are ignored — no bump, silently. Squash-merge PRs so the PR title becomes the commit subject, and keep that title conventional.
Every published version carries npm provenance, so the tarball on npm is cryptographically linked to the commit and workflow run that built it.
One-time setup
Publishing uses npm trusted publishing (OIDC) rather than a long-lived token — there is no NPM_TOKEN secret to leak or rotate. On npmjs.com, under the package's Settings → Trusted Publisher, point it at:
| Field | Value |
|---|---|
| Repository | kenai-platform/check-exact-packages |
| Workflow | release.yml |
If you rename .github/workflows/release.yml, update it there too or publishing will start failing with an auth error.
Opening the release PR needs a second credential. The kenai-platform org forbids GitHub Actions from creating pull requests, so GITHUB_TOKEN cannot do it — release-please authenticates as a GitHub App instead. Two repository secrets:
| Secret | Source |
|---|---|
| RELEASE_APP_ID | The App's ID, on its settings page |
| RELEASE_APP_PRIVATE_KEY | A generated .pem, pasted whole |
The App needs Contents: read and write and Pull requests: read and write, no webhook, and should be installed on this repository only. The workflow mints a token per run that expires in an hour; the private key is the only long-lived secret.
There is a second reason for the App beyond permissions: a pull request opened with GITHUB_TOKEN does not trigger other workflows. The release PR would never report the test (…) checks that main's ruleset requires, and so could never be merged. An App token does trigger them.
Development
git clone https://github.com/kenai-platform/check-exact-packages.git
cd check-exact-packages
npm test # runs test/run.sh
./bin/check-exact-packages # run the checker against this repotest/run.sh builds a throwaway git repo per case (the tool scans git ls-files) and asserts the exit code. Add a case there for any spec form you change the handling of. CI runs it on Ubuntu and macOS — the stock bash on macOS is 3.2, so keep the script portable.
