Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions utils/tests/verify_action_build/test_diff_node_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,69 @@ def test_noisy_files_ignored(self, tmp_path):
)
assert result is True

def test_ide_config_dirs_ignored(self, tmp_path):
# Some upstream npm packages ship author IDE config trees
# (``node_modules/tunnel/.idea/*`` was the case-in-point in
# benchmark-action's vendored deps). These are not runtime code
# and shouldn't break verification when they leak into one side
# of the comparison and not the other.
orig = tmp_path / "original"
rebuilt = tmp_path / "rebuilt"
orig.mkdir()
rebuilt.mkdir()

(orig / "tunnel").mkdir()
(rebuilt / "tunnel").mkdir()
(orig / "tunnel" / "index.js").write_text("code")
(rebuilt / "tunnel" / "index.js").write_text("code")

# Only the rebuilt tree carries IDE files (the upstream package
# tarball includes them; the published vendored copy was scrubbed).
(rebuilt / "tunnel" / ".idea").mkdir()
(rebuilt / "tunnel" / ".idea" / "encodings.xml").write_text("<noise/>")
(rebuilt / "tunnel" / ".idea" / "modules.xml").write_text("<noise/>")
(rebuilt / "tunnel" / ".idea" / "node-tunnel.iml").write_text("<noise/>")
(rebuilt / "tunnel" / ".idea" / "workspace.xml").write_text("<noise/>")

# Mirror the same noise on the original side under a different
# package, just to be sure we filter symmetrically.
(orig / "lodash").mkdir()
(rebuilt / "lodash").mkdir()
(orig / "lodash" / "index.js").write_text("code")
(rebuilt / "lodash" / "index.js").write_text("code")
(orig / "lodash" / ".vscode").mkdir()
(orig / "lodash" / ".vscode" / "settings.json").write_text("{}")

result = diff_node_modules(
orig, rebuilt, "test", "repo", "a" * 40,
)
assert result is True

def test_other_dotdirs_in_packages_still_compared(self, tmp_path):
# Defensive: a non-IDE dot-directory inside a package that DOES
# carry meaningful content (``.bin``, ``.eslintrc``, etc.) must
# still be compared, not silently skipped. Use ``.bin`` here
# since that's a real npm convention for package executables.
orig = tmp_path / "original"
rebuilt = tmp_path / "rebuilt"
orig.mkdir()
rebuilt.mkdir()

(orig / "pkg").mkdir()
(rebuilt / "pkg").mkdir()
(orig / "pkg" / "index.js").write_text("orig")
(rebuilt / "pkg" / "index.js").write_text("orig")
(orig / "pkg" / ".bin").mkdir()
(rebuilt / "pkg" / ".bin").mkdir()
(orig / "pkg" / ".bin" / "tool").write_text("ORIGINAL BINARY")
(rebuilt / "pkg" / ".bin" / "tool").write_text("DIFFERENT BINARY")

result = diff_node_modules(
orig, rebuilt, "test", "repo", "a" * 40,
)
# Content differs in .bin/tool — diff must still flag it.
assert result is False

def test_package_json_install_fields_ignored(self, tmp_path):
import json
orig = tmp_path / "original"
Expand Down
13 changes: 11 additions & 2 deletions utils/verify_action_build/diff_node_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,18 @@ def diff_node_modules(
"""Compare original vs rebuilt node_modules. Return True if they match."""
blob_url = f"https://github.com/{org}/{repo}/blob/{commit_hash}/node_modules"

# Metadata files that legitimately differ between installs
# Metadata files that legitimately differ between installs.
noisy_files = {".package-lock.json", ".yarn-integrity"}
noisy_dirs = {".cache", ".package-lock.json"}
# Directories that occasionally leak into a vendored ``node_modules`` (or
# into a fresh ``npm ci``) but are not meaningful for verification:
# npm's per-install ``.cache``/lock metadata, plus IDE config trees that
# some upstream npm packages ship — see
# ``node_modules/tunnel/.idea/*`` in benchmark-action's vendored deps —
# which are author tooling artifacts, not runtime code.
noisy_dirs = {
".cache", ".package-lock.json",
".idea", ".vscode", ".vs", ".fleet", ".zed",
}

def collect_files(base: Path) -> dict[Path, str]:
"""Collect all files under base with their SHA256 hashes."""
Expand Down
Loading