feat: add unnecessary-release-age-exclude rule - #162
Open
maastrich wants to merge 2 commits into
Open
Conversation
Reports minimum release age exclusions that don't unblock anything anymore, for pnpm (`pnpm-workspace.yaml`), Yarn (`.yarnrc.yml`) and Bun (`bunfig.toml`). Two cases are reported: exclusions pinning versions that are already past the gate, and exclusions without a version whose package has been silent for at least ten times the gate. Patterns and version ranges are skipped, as they can match versions that aren't published yet. Publish dates aren't available on disk - lockfiles only store resolved versions and integrity hashes, and metadata caches strip the `time` field - so this rule fetches the registry document of the excluded packages. It only runs when such a configuration exists, never queries a custom registry, and reports nothing if the registry is unreachable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The rule queries the npm registry, so it now requires the `--check-release-age` flag (or the `checkReleaseAge` config field). A plain `sherif` run stays fully offline. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
New warning rule
unnecessary-release-age-exclude: reports minimum release age exclusions that don't unblock anything anymore. These are usually added to unblock one urgent upgrade, then forgotten - and they permanently disable the cooldown that protects against compromised releases.pnpm-workspace.yamlminimumReleaseAge(minutes)minimumReleaseAgeExclude.yarnrc.ymlnpmMinimalAgeGate(minutes)npmPreapprovedPackagesbunfig.tomlminimumReleaseAge(seconds)minimumReleaseAgeExcludesTwo cases are reported:
typescript@5.4.5) - those versions are published, so they will never be gated again;Patterns (
@myorg/*) and ranges (nx@^21.0.0) are skipped - they can match versions that aren't published yet. npm isn't supported (no exclusion list), nor is the pnpm 10.x.npmrcform.This needs network access, and I know that's a paradigm change
Every other rule is a pure function of files on disk. This one queries the npm registry, because publish dates exist nowhere locally:
pnpm-lock.yaml,yarn.lock,package-lock.json,bun.lock) only store resolved versions and integrity hashes;timefield;application/vnd.npm.install-v1+json) doesn't include it either.So the rule fetches the full registry document, which is what package managers themselves do to enforce the gate.
Because of that, the rule is opt-in: it only runs with
--check-release-age(or"checkReleaseAge": truein the config). A plainsherifrun stays fully offline, and existing users see no change. The GitHub Action needs no new input - the flag goes through the existingargs.Further guards, on top of the flag:
-r unnecessary-release-age-excludeshort-circuits before any request;registry=in the root.npmrcdisables the rule,@scope:registry=excludes that scope - nothing is ever sent to a private registry;Cost:
ureq(rustls/webpki-roots) +toml, binary goes from 1.9M to 3.1M. The musl cross-build was verified locally.If this isn't wanted behaviour for Sherif, say so and I'll close the PR - no hard feelings.
Tests
Fixtures for each config format, unit tests for parsing/date/verdict logic, a test asserting the rule stays off without the flag, and snapshot tests for the message.
cargo fmt,cargo clippy --tests -- -D warningsandcargo test -- --test-threads=1(60 tests) all pass. README documents the rule, the flag and the network requirement.🤖 Generated with Claude Code