feat(ci): semantic package-lock.json diff as an upserted PR comment - #65206
Merged
Merged
Conversation
ethernet8023
force-pushed
the
ethie/package-lock-compare
branch
from
July 15, 2026 21:03
fcb3a76 to
c709d13
Compare
Contributor
✅ CI-sensitive file review passedThe |
git diff on a lockfile is unreadable: npm reorders entries, rewrites
integrity hashes, and moves packages between nesting levels, so a
one-line package.json bump produces a thousand-line textual diff.
scripts/ci/lockfile_diff.py instead parses the `packages` map out of
both versions of every tracked package-lock.json (via `git show`),
reduces each to {install path: version}, and set-diffs the maps —
reorder/hash churn vanishes, leaving only actual version movement
(added / removed / updated, with nested dedup copies tracked
separately).
The lockfile-diff workflow posts the result as a Markdown table in a
PR comment gated behind a hidden marker: subsequent pushes PATCH the
existing comment instead of stacking new ones, and a push that reverts
all lockfile changes updates the comment to say so. Advisory only —
never fails on findings; fork PRs (read-only token) degrade to a
warning.
Wired through the ci.yml orchestrator with a new npm_lock lane in
classify_changes.py (fails open on .github/ changes per the existing
contract).
ethernet8023
force-pushed
the
ethie/package-lock-compare
branch
from
July 16, 2026 03:13
c709d13 to
08270cf
Compare
Closed
ethernet8023
enabled auto-merge (squash)
July 16, 2026 03:17
Gravezzz
pushed a commit
to Gravezzz/hermes-agent
that referenced
this pull request
Jul 21, 2026
…ousResearch#65206) git diff on a lockfile is unreadable: npm reorders entries, rewrites integrity hashes, and moves packages between nesting levels, so a one-line package.json bump produces a thousand-line textual diff. scripts/ci/lockfile_diff.py instead parses the `packages` map out of both versions of every tracked package-lock.json (via `git show`), reduces each to {install path: version}, and set-diffs the maps — reorder/hash churn vanishes, leaving only actual version movement (added / removed / updated, with nested dedup copies tracked separately). The lockfile-diff workflow posts the result as a Markdown table in a PR comment gated behind a hidden marker: subsequent pushes PATCH the existing comment instead of stacking new ones, and a push that reverts all lockfile changes updates the comment to say so. Advisory only — never fails on findings; fork PRs (read-only token) degrade to a warning. Wired through the ci.yml orchestrator with a new npm_lock lane in classify_changes.py (fails open on .github/ changes per the existing contract).
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
…ousResearch#65206) git diff on a lockfile is unreadable: npm reorders entries, rewrites integrity hashes, and moves packages between nesting levels, so a one-line package.json bump produces a thousand-line textual diff. scripts/ci/lockfile_diff.py instead parses the `packages` map out of both versions of every tracked package-lock.json (via `git show`), reduces each to {install path: version}, and set-diffs the maps — reorder/hash churn vanishes, leaving only actual version movement (added / removed / updated, with nested dedup copies tracked separately). The lockfile-diff workflow posts the result as a Markdown table in a PR comment gated behind a hidden marker: subsequent pushes PATCH the existing comment instead of stacking new ones, and a push that reverts all lockfile changes updates the comment to say so. Advisory only — never fails on findings; fork PRs (read-only token) degrade to a warning. Wired through the ci.yml orchestrator with a new npm_lock lane in classify_changes.py (fails open on .github/ changes per the existing contract).
33hodl
pushed a commit
to 33hodl/hermes-agent
that referenced
this pull request
Aug 12, 2026
…ousResearch#65206) git diff on a lockfile is unreadable: npm reorders entries, rewrites integrity hashes, and moves packages between nesting levels, so a one-line package.json bump produces a thousand-line textual diff. scripts/ci/lockfile_diff.py instead parses the `packages` map out of both versions of every tracked package-lock.json (via `git show`), reduces each to {install path: version}, and set-diffs the maps — reorder/hash churn vanishes, leaving only actual version movement (added / removed / updated, with nested dedup copies tracked separately). The lockfile-diff workflow posts the result as a Markdown table in a PR comment gated behind a hidden marker: subsequent pushes PATCH the existing comment instead of stacking new ones, and a push that reverts all lockfile changes updates the comment to say so. Advisory only — never fails on findings; fork PRs (read-only token) degrade to a warning. Wired through the ci.yml orchestrator with a new npm_lock lane in classify_changes.py (fails open on .github/ changes per the existing contract).
prmartinow
pushed a commit
to prmartinow/hermes-agent
that referenced
this pull request
Aug 26, 2026
…ousResearch#65206) git diff on a lockfile is unreadable: npm reorders entries, rewrites integrity hashes, and moves packages between nesting levels, so a one-line package.json bump produces a thousand-line textual diff. scripts/ci/lockfile_diff.py instead parses the `packages` map out of both versions of every tracked package-lock.json (via `git show`), reduces each to {install path: version}, and set-diffs the maps — reorder/hash churn vanishes, leaving only actual version movement (added / removed / updated, with nested dedup copies tracked separately). The lockfile-diff workflow posts the result as a Markdown table in a PR comment gated behind a hidden marker: subsequent pushes PATCH the existing comment instead of stacking new ones, and a push that reverts all lockfile changes updates the comment to say so. Advisory only — never fails on findings; fork PRs (read-only token) degrade to a warning. Wired through the ci.yml orchestrator with a new npm_lock lane in classify_changes.py (fails open on .github/ changes per the existing contract).
melon-xf
added a commit
to melon-xf/hermes-agent
that referenced
this pull request
Sep 3, 2026
…ousResearch#65206) git diff on a lockfile is unreadable: npm reorders entries, rewrites integrity hashes, and moves packages between nesting levels, so a one-line package.json bump produces a thousand-line textual diff. scripts/ci/lockfile_diff.py instead parses the `packages` map out of both versions of every tracked package-lock.json (via `git show`), reduces each to {install path: version}, and set-diffs the maps — reorder/hash churn vanishes, leaving only actual version movement (added / removed / updated, with nested dedup copies tracked separately). The lockfile-diff workflow posts the result as a Markdown table in a PR comment gated behind a hidden marker: subsequent pushes PATCH the existing comment instead of stacking new ones, and a push that reverts all lockfile changes updates the comment to say so. Advisory only — never fails on findings; fork PRs (read-only token) degrade to a warning. Wired through the ci.yml orchestrator with a new npm_lock lane in classify_changes.py (fails open on .github/ changes per the existing contract).
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 does this PR do?
Adds an advisory CI job that posts (and updates in place) a PR comment showing the semantic diff of
package-lock.jsonchanges — which packages were added, removed, or version-bumped.The raw textual diff of a lockfile is noise: npm reorders entries, rewrites integrity hashes, and moves packages between nesting levels, so a one-line
package.jsonbump can produce a thousand-line diff nobody reads. Instead of diffing text,scripts/ci/lockfile_diff.pyparses thepackagesmap out of both versions of every tracked lockfile (viagit show <ref>:<path>, merge base → HEAD), reduces each to{install path: version}, and set-diffs the maps. Reordering and hash churn produce a literally empty diff; what's left is the actual dependency change. Keying on the fullnode_modules/...path means the same package deduped at two versions shows as two entries (rendered asreact *(nested under foo)*).The comment is upserted: the body starts with a hidden
<!-- hermes-lockfile-diff -->marker, and the workflow finds its previous comment by that prefix (paginated) and PATCHes it, so a PR gets exactly one comment tracking the latest push. If a later push reverts all lockfile changes, the comment is updated to say so rather than left stale or deleted.Example comment body:
see #65316
Why in-house instead of a marketplace action: the existing lockfile-diff actions are unpinned third-party JS that would run with
pull-requests: write— exactly what our supply-chain policy exists to avoid. The differ is ~200 lines of stdlib Python with tests.The job is advisory: it never fails on findings, and fork PRs (read-only
GITHUB_TOKEN) degrade to a::warning::. It's in theall-checks-passgate only so a crash of the script itself is caught (skipped counts as success).closes #65316
^ that's just a demo
Related Issue
N/A — direct request.
Type of Change
Changes Made
scripts/ci/lockfile_diff.py— new semantic differ:parse_lockfile()/diff_locks()/render_markdown()pure functions +git show-based ref comparison across all trackedpackage-lock.jsonfiles (lockfileVersion 2/3).github/workflows/lockfile-diff.yml— newworkflow_calljob: diffs merge base → HEAD, writes the table to the step summary, upserts the PR comment viagh api(create or PATCH by marker).github/workflows/ci.yml— wires thelockfile-diffjob through the orchestrator, gated on PR events + the newnpm_locklane; added to theall-checks-passgate.github/actions/detect-changes/action.yml— exposes the newnpm_lockoutputscripts/ci/classify_changes.py— newnpm_locklane (any**/package-lock.json; fails open on.github/changes per the existing contract)tests/ci/test_lockfile_diff.py— new: reorder/hash-churn ⇒ empty diff, add/remove/update detection, nested-dedup tracking, root/link-entry skipping, markdown marker + renderingtests/ci/test_classify_changes.py—npm_locklane cases (root + nested lockfile, fail-open default)How to Test
scripts/run_tests.sh tests/ci/— 28 tests pass (differ + classifier)python3 scripts/ci/lockfile_diff.py --base HEAD --head HEAD --output /tmp/d.md⇒ empty report; committing a simulated version bump + package removal in the root lockfile and diffingHEAD~1..HEADproduces the two-row table abovepackage-lock.json: thepackage-lock.json diffjob posts the comment; push again and the same comment updates in placeChecklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests pass (viascripts/run_tests.sh tests/ci/)Documentation & Housekeeping
docs/, docstrings) — module docstrings in the new script; no user-facing docs affectedcli-config.yaml.exampleif I added/changed config keys — N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/A (follows the existing orchestrator/lane pattern)encoding="utf-8"explicitlyScreenshots / Logs
Simulated bump e2e output: