e93507a09c
Lockfile supply-chain audit / lockfile supply-chain audit (push) Has been cancelled
Windows Studio GGUF CI / GPU prebuilt resolves without Visual Studio (push) Has been cancelled
Windows Studio GGUF CI / setup.ps1 unit tests (VS 2026 / CMake guard) (push) Has been cancelled
Windows Studio GGUF CI / real-VS detection (VS 2022) (push) Has been cancelled
Windows Studio GGUF CI / real-VS detection (VS 2026) (push) Has been cancelled
Windows Studio GGUF CI / VC++ runtime detect + install round-trip (windows-2025-vs2026) (push) Has been cancelled
Windows Studio GGUF CI / VC++ runtime detect + install round-trip (windows-latest) (push) Has been cancelled
Windows Studio Update CI / Studio Updating Tests (push) Has been cancelled
Wheel CI / Wheel build + content sanity + import smoke (push) Has been cancelled
Lint CI / Source lint (Python + shell + YAML + JSON + safety nets) (push) Has been cancelled
MLX CI on Mac M1 / dispatch (push) Has been cancelled
Security audit / advisory audit (pip + npm + cargo) (push) Has been cancelled
Security audit / pip scan-packages :: extras (push) Has been cancelled
Security audit / pip scan-packages :: studio (push) Has been cancelled
Security audit / pip scan-packages :: hf-stack (push) Has been cancelled
Security audit / npm scan-packages (Studio frontend tarballs) (push) Has been cancelled
Security audit / workflow-trigger lint (pull_request_target / cache-poisoning) (push) Has been cancelled
Security audit / pytest tests/security (push) Has been cancelled
Security audit / npm provenance + new install-script diff (push) Has been cancelled
Studio API CI / Studio API & Auth Tests (push) Has been cancelled
Backend CI / (Python 3.10) (push) Has been cancelled
Backend CI / (Python 3.11) (push) Has been cancelled
Backend CI / (Python 3.12) (push) Has been cancelled
Backend CI / (Python 3.13) (push) Has been cancelled
Backend CI / Repo tests (CPU) (push) Has been cancelled
Frontend CI / Frontend build + bundle sanity (push) Has been cancelled
Studio GGUF CI / OpenAI, Anthropic API tests (push) Has been cancelled
Studio GGUF CI / Tool calling Tests (push) Has been cancelled
Studio GGUF CI / JSON, images (push) Has been cancelled
Mac Studio GGUF CI / OpenAI, Anthropic API tests (push) Has been cancelled
Mac Studio GGUF CI / Tool calling Tests (push) Has been cancelled
Mac Studio GGUF CI / JSON, images (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-14) (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-15) (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-26) (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-15-intel) (push) Has been cancelled
Mac Studio API CI / Studio API & Auth Tests (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-26-intel) (push) Has been cancelled
Mac Studio UI CI / Chat UI Tests (push) Has been cancelled
Studio Tauri CI / Tauri Linux debug build (no codesign) (push) Has been cancelled
Mac Studio Update CI / Studio Updating Tests (push) Has been cancelled
Studio UI CI / Chat UI Tests (push) Has been cancelled
Windows Studio API CI / Studio API & Auth Tests (push) Has been cancelled
Windows Studio UI CI / Chat UI Tests (push) Has been cancelled
Studio Update CI / Studio Updating Tests (push) Has been cancelled
Core / Core (HF=default + TRL=default) (push) Has been cancelled
Core / Core (HF=4.57.6 + TRL<1) (push) Has been cancelled
Core / Core (HF=latest + TRL=latest) (push) Has been cancelled
Core / llama.cpp build + smoke (push) Has been cancelled
Windows Studio GGUF CI / OpenAI, Anthropic API tests (push) Has been cancelled
Windows Studio GGUF CI / Tool calling Tests (push) Has been cancelled
Windows Studio GGUF CI / JSON, images (push) Has been cancelled
Windows Studio GGUF CI / Studio install + inference without Visual Studio (push) Has been cancelled
Studio export capability / capability (macos-latest) (push) Has been cancelled
Studio export capability / capability (ubuntu-latest) (push) Has been cancelled
Studio export capability / capability (windows-latest) (push) Has been cancelled
Cross-platform parity / parity (macos-latest) (push) Has been cancelled
Cross-platform parity / parity (windows-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
Studio load-orchestrator CI / test (push) Has been cancelled
193 lines
6.4 KiB
Python
193 lines
6.4 KiB
Python
"""Regression tests for `scripts/check_new_install_scripts.py`.
|
|
|
|
Lockfiles are tiny dicts in tmp_path; the network_blocker fixture forces the
|
|
scanner's offline path (registry unreachable -> emit finding anyway).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
SCRIPT = REPO_ROOT / "scripts" / "check_new_install_scripts.py"
|
|
|
|
|
|
def _run(
|
|
base: Path,
|
|
head: Path,
|
|
*,
|
|
timeout: int = 30,
|
|
) -> subprocess.CompletedProcess:
|
|
return subprocess.run(
|
|
[
|
|
sys.executable,
|
|
str(SCRIPT),
|
|
"--base",
|
|
str(base),
|
|
"--head",
|
|
str(head),
|
|
],
|
|
capture_output = True,
|
|
text = True,
|
|
timeout = timeout,
|
|
)
|
|
|
|
|
|
def _write(path: Path, content: dict) -> Path:
|
|
path.write_text(json.dumps(content), encoding = "utf-8")
|
|
return path
|
|
|
|
|
|
# Lockfile fixtures
|
|
def _v3_lockfile(packages: dict) -> dict:
|
|
return {
|
|
"name": "unsloth-theme",
|
|
"version": "0.0.0",
|
|
"lockfileVersion": 3,
|
|
"requires": True,
|
|
"packages": packages,
|
|
}
|
|
|
|
|
|
def _v2_lockfile(packages: dict, dependencies: dict) -> dict:
|
|
return {
|
|
"name": "unsloth-theme",
|
|
"version": "0.0.0",
|
|
"lockfileVersion": 2,
|
|
"requires": True,
|
|
"packages": packages,
|
|
"dependencies": dependencies,
|
|
}
|
|
|
|
|
|
# Tests
|
|
def test_no_new_install_scripts_exit_0(tmp_path: Path):
|
|
"""If base == head, nothing new can have been added."""
|
|
same = _v3_lockfile(
|
|
{
|
|
"": {"name": "unsloth-theme", "version": "0.0.0"},
|
|
"node_modules/node-gyp": {
|
|
"version": "10.0.1",
|
|
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz",
|
|
"integrity": "sha512-fake",
|
|
"hasInstallScript": True,
|
|
},
|
|
}
|
|
)
|
|
base = _write(tmp_path / "base.json", same)
|
|
head = _write(tmp_path / "head.json", same)
|
|
result = _run(base, head)
|
|
assert result.returncode == 0, result.stderr
|
|
assert "no newly-added install-script" in result.stdout.lower()
|
|
|
|
|
|
def test_new_dep_with_postinstall_exits_1(tmp_path: Path):
|
|
"""A NEW dep in head with `hasInstallScript: true` must exit 1."""
|
|
base_pkgs = {
|
|
"": {"name": "unsloth-theme", "version": "0.0.0"},
|
|
"node_modules/react": {
|
|
"version": "19.2.4",
|
|
"resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
|
|
"integrity": "sha512-fake",
|
|
},
|
|
}
|
|
head_pkgs = dict(base_pkgs)
|
|
head_pkgs["node_modules/evil-postinstall"] = {
|
|
"version": "1.0.0",
|
|
"resolved": ("https://registry.npmjs.org/evil-postinstall/-/evil-postinstall-1.0.0.tgz"),
|
|
"integrity": "sha512-fake",
|
|
"hasInstallScript": True,
|
|
}
|
|
base = _write(tmp_path / "base.json", _v3_lockfile(base_pkgs))
|
|
head = _write(tmp_path / "head.json", _v3_lockfile(head_pkgs))
|
|
result = _run(base, head)
|
|
assert (
|
|
result.returncode == 1
|
|
), f"expected exit 1, got {result.returncode}; stderr:\n{result.stderr}"
|
|
assert "evil-postinstall" in result.stderr
|
|
assert "1.0.0" in result.stderr
|
|
|
|
|
|
def test_existing_dep_with_postinstall_ignored(tmp_path: Path):
|
|
"""An install-script dep present in BOTH base and head is not new."""
|
|
base_pkgs = {
|
|
"": {"name": "unsloth-theme", "version": "0.0.0"},
|
|
"node_modules/node-gyp": {
|
|
"version": "10.0.1",
|
|
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz",
|
|
"integrity": "sha512-fake",
|
|
"hasInstallScript": True,
|
|
},
|
|
# Transitive install-script copy, nested under another dep.
|
|
"node_modules/some-build-pkg/node_modules/node-gyp": {
|
|
"version": "10.0.1",
|
|
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz",
|
|
"integrity": "sha512-fake",
|
|
"hasInstallScript": True,
|
|
},
|
|
}
|
|
head_pkgs = dict(base_pkgs)
|
|
# Add an unrelated non-install-script dep in head.
|
|
head_pkgs["node_modules/lodash"] = {
|
|
"version": "4.17.21",
|
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
|
"integrity": "sha512-fake",
|
|
}
|
|
base = _write(tmp_path / "base.json", _v3_lockfile(base_pkgs))
|
|
head = _write(tmp_path / "head.json", _v3_lockfile(head_pkgs))
|
|
result = _run(base, head)
|
|
assert result.returncode == 0, (
|
|
f"expected exit 0, got {result.returncode}; stderr:\n{result.stderr}\n"
|
|
f"stdout:\n{result.stdout}"
|
|
)
|
|
# Sanity: the existing node-gyp must NOT be reported.
|
|
assert "node-gyp" not in result.stderr
|
|
|
|
|
|
def test_v2_v3_lockfile_format_support(tmp_path: Path):
|
|
"""A lockfileVersion 2 lockfile with the same shape parses the same."""
|
|
base_pkgs = {
|
|
"": {"name": "unsloth-theme", "version": "0.0.0"},
|
|
}
|
|
base_deps = {} # v2 carries both; empty deps OK
|
|
head_pkgs = {
|
|
"": {"name": "unsloth-theme", "version": "0.0.0"},
|
|
"node_modules/v2-postinstall-dep": {
|
|
"version": "2.0.0",
|
|
"resolved": (
|
|
"https://registry.npmjs.org/v2-postinstall-dep/-/v2-postinstall-dep-2.0.0.tgz"
|
|
),
|
|
"integrity": "sha512-fake",
|
|
"hasInstallScript": True,
|
|
},
|
|
}
|
|
head_deps = {
|
|
"v2-postinstall-dep": {
|
|
"version": "2.0.0",
|
|
"resolved": (
|
|
"https://registry.npmjs.org/v2-postinstall-dep/-/v2-postinstall-dep-2.0.0.tgz"
|
|
),
|
|
"integrity": "sha512-fake",
|
|
},
|
|
}
|
|
base = _write(tmp_path / "base.json", _v2_lockfile(base_pkgs, base_deps))
|
|
head = _write(tmp_path / "head.json", _v2_lockfile(head_pkgs, head_deps))
|
|
result = _run(base, head)
|
|
assert result.returncode == 1, (
|
|
f"expected exit 1 for v2 lockfile, got {result.returncode}; " f"stderr:\n{result.stderr}"
|
|
)
|
|
assert "v2-postinstall-dep" in result.stderr
|
|
|
|
# Same packages as lockfileVersion 3 must give the same finding.
|
|
base_v3 = _write(tmp_path / "base_v3.json", _v3_lockfile(base_pkgs))
|
|
head_v3 = _write(tmp_path / "head_v3.json", _v3_lockfile(head_pkgs))
|
|
result_v3 = _run(base_v3, head_v3)
|
|
assert result_v3.returncode == 1, (
|
|
f"expected exit 1 for v3 lockfile, got {result_v3.returncode}; "
|
|
f"stderr:\n{result_v3.stderr}"
|
|
)
|
|
assert "v2-postinstall-dep" in result_v3.stderr
|