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
1 change: 0 additions & 1 deletion .github/scripts/test_app_answer_release_release_prep.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ def test_prep_packet_does_not_itself_perform_release_actions(self) -> None:
self.assertIn(required, record)

def test_current_public_install_surfaces_remain_on_published_baseline(self) -> None:
self.assertIn('"version": "0.2.1"', read(NPM_PACKAGE))
self.assertIn("cargo add ethos-doc-core@0.2.0", read(README))
self.assertIn("python3 -m pip install ethos-pdf==0.2.0", read(README))
self.assertIn("npm install -g @docushell/ethos-pdf@0.2.1", read(README))
Expand Down
10 changes: 6 additions & 4 deletions .github/scripts/test_npm_binary_package_scaffold.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@
"darwin:arm64": {
"binary": "ethos-darwin-arm64",
"release_asset": "ethos-macos-arm64.tar.gz",
"release_asset_sha256": "c588ee77bbaf99a7d933673e6cd9db190f5992e47d40955def803435a9f9fc5a",
"release_asset_sha256": "efb163f140bf4afffd1caeb396f79e42f484591c3e90a86810ca6c0f0c209c96",
},
"linux:x64": {
"binary": "ethos-linux-x64",
"release_asset": "ethos-linux-x64.tar.gz",
"release_asset_sha256": "00137b20ca2c2a2d2089df1d135920b021b0905d779b1347d134e8a2fb7bfa23",
"release_asset_sha256": "b549ba5968e04b7679a8d3e879cd45d27f3e9a6fd226eee5c270a4e4f5c01405",
},
}

Expand Down Expand Up @@ -101,9 +101,11 @@ def test_package_docs_keep_pdfium_and_publication_boundaries(self) -> None:
self.assertIn("does not bundle PDFium", text)
self.assertIn("ETHOS_PDFIUM_LIBRARY_PATH", text)
self.assertIn("QUICKSTART.md", text)
self.assertIn("current npm package is `@docushell/ethos-pdf@0.2.1`", text)
self.assertIn("source package candidate is `@docushell/ethos-pdf@0.3.0`", text)
self.assertIn("current published npm package remains `@docushell/ethos-pdf@0.2.1`", text)
self.assertIn("Version `0.2.0` is deprecated", text)
self.assertIn("`ethos 0.2.0`", text)
self.assertIn("`ethos 0.3.0`", text)
self.assertIn("npm publication and public `0.3.0` install wording remain blocked", text)
self.assertIn("does not include public benchmark reports or claims", normalized)

quickstart = read(QUICKSTART)
Expand Down
40 changes: 20 additions & 20 deletions .github/scripts/test_npm_tarball_candidate_evidence.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@

ROOT = Path(__file__).resolve().parents[2]
PACKAGE_DIR = ROOT / "packages/npm/ethos-pdf"
PACKAGE_TARBALL = PACKAGE_DIR / "docushell-ethos-pdf-0.1.2.tgz"
RECORD = ROOT / "docs/validation/patch-0-1-2-npm-vendor-refresh-validation-2026-06-24.md"
PACKAGE_TARBALL = PACKAGE_DIR / "docushell-ethos-pdf-0.3.0.tgz"
RECORD = ROOT / "docs/validation/v0-3-0-npm-vendor-refresh-validation-2026-07-02.md"
VALIDATION_README = ROOT / "docs/validation/README.md"
SOURCE_SHORT = "2323398"
SOURCE_COMMIT = "23233986035e0f4a20295b24a9cfafafe65aa117"
SOURCE_TREE = "750551f51094f0bc9625c781b8cc978431e431c3"
SOURCE_SHORT = "8e20db3"
SOURCE_COMMIT = "8e20db3c796f051925b059f62c294f41f981bcfa"
SOURCE_TREE = "7f528ace4993e21e457aefb5a0aa65ed40297c6c"
EXPECTED_FILES = {
"LICENSE",
"NOTICE",
Expand All @@ -49,14 +49,14 @@
"vendor/manifest.json",
}
EXPECTED_VENDOR_SHA256 = {
"vendor/ethos-darwin-arm64": "47c2f4aaac6cb6a1ca5cf1d9a0cc1f897ef00c48cdd8549455de70f0fbc6bcc1",
"vendor/ethos-linux-x64": "e75122f2954efbde6b8c07a98601b8d4a3b7a06647891a9e60d6aef4046649c3",
"vendor/manifest.json": "d557e081b946be0f839b17b8593027e31267b668498e202372026020f68a97a1",
"vendor/ethos-darwin-arm64": "777e1fb243425a46b83b63ed92fbf7cb810f59cfedd81cfe671cf791410c20dc",
"vendor/ethos-linux-x64": "b416993fc38e6f794611b8b71789ed85af18eb6aa63fef380d9ae7738661f154",
"vendor/manifest.json": "e313b42e49b258171611935455fd9e70bad7ce61c409df63ab90aaa2732a46af",
}
EXPECTED_PACK_SHASUM = "39b85d74f588666bfbf69e423a189c2039743de4"
EXPECTED_PACK_SHA256 = "77cbc9c79dd60cc16073690a186e149ecbaabacce035fb0bd3603b267ce64112"
EXPECTED_PACK_SHASUM = "1a90cebd8d52011ea5c41629becdfb37dec73ee7"
EXPECTED_PACK_SHA256 = "1b72ef2fd9415f9edff93319ee2763e8f67cd6168ea00cd64d89a3760101c5fa"
EXPECTED_PACK_INTEGRITY = (
"sha512-3loga13tnAkUkjuOrjKjpA0D3Cm5lW6Al8OwTyRx7NGMt6EB4gMpZOoaSCPjZWchYv7as1uPaEnZyOqrmFOPxg=="
"sha512-ZWoIY5BO7O8tzN88ICGvRasmOt7/RSN/xWFM2ONT8lavQqIOuCY/bQjvxnuK9vGpNeogh8X4UXHLLSRKqqHVOQ=="
)
EVIDENCE_PACK_SHASUM = EXPECTED_PACK_SHASUM
EVIDENCE_PACK_SHA256 = EXPECTED_PACK_SHA256
Expand Down Expand Up @@ -108,8 +108,8 @@ def test_npm_pack_candidate_contents_and_checksums(self) -> None:
files = {entry["path"]: entry for entry in pack["files"]}

self.assertEqual("@docushell/ethos-pdf", pack["name"])
self.assertEqual("0.1.2", pack["version"])
self.assertEqual("docushell-ethos-pdf-0.1.2.tgz", pack["filename"])
self.assertEqual("0.3.0", pack["version"])
self.assertEqual("docushell-ethos-pdf-0.3.0.tgz", pack["filename"])
self.assertEqual(EXPECTED_FILES, set(files))
self.assertEqual(493, files["vendor/ethos-darwin-arm64"]["mode"])
self.assertEqual(493, files["vendor/ethos-linux-x64"]["mode"])
Expand All @@ -127,22 +127,22 @@ def test_candidate_evidence_record_is_source_bound_and_indexed(self) -> None:
readme = normalized(VALIDATION_README)

self.assertIn(f"Validated source HEAD before this record: `{SOURCE_SHORT}`", read(RECORD))
self.assertIn(f"npm vendor refresh source commit: `{SOURCE_COMMIT}`", record)
self.assertIn(f"npm vendor refresh source tree: `{SOURCE_TREE}`", record)
self.assertIn(f"v0.3.0 npm vendor refresh source commit: `{SOURCE_COMMIT}`", record)
self.assertIn(f"v0.3.0 npm vendor refresh source tree: `{SOURCE_TREE}`", record)
self.assertIn(EVIDENCE_PACK_SHASUM, record)
self.assertIn(EVIDENCE_PACK_SHA256, record)
self.assertIn(EVIDENCE_PACK_INTEGRITY, record)
self.assertIn(f"Node.js: `{EXPECTED_NODE_VERSION}`", record)
self.assertIn(f"npm: `{EXPECTED_NPM_VERSION}`", record)
self.assertIn("durable package-content provenance", record)
self.assertIn("per-file vendor SHA256 values as the durable content binding", record)
self.assertIn("ethos 0.1.2", record)
self.assertIn("exit code `12`", record)
self.assertIn("ethos 0.3.0", record)
self.assertIn("exit code 12", record)
self.assertIn("npm publication remains blocked", record)
self.assertIn("Public installation wording remains blocked", record)
self.assertIn("Public `0.3.0` install wording remains blocked", record)
self.assertNotIn("npm publication approved", record.lower())
self.assertIn(RECORD.name, readme)
self.assertIn("patch 0.1.2 npm vendor refresh validation", readme)
self.assertIn("v0.3.0 npm vendor refresh", readme)

def test_candidate_tarball_installs_and_preserves_pdfium_boundary(self) -> None:
with tempfile.TemporaryDirectory(prefix="ethos-npm-install-") as temp:
Expand Down Expand Up @@ -178,7 +178,7 @@ def test_candidate_tarball_installs_and_preserves_pdfium_boundary(self) -> None:
stderr=subprocess.PIPE,
)
self.assertEqual(0, version.returncode, version.stderr)
self.assertEqual("ethos 0.1.2", version.stdout.strip())
self.assertEqual("ethos 0.3.0", version.stdout.strip())

dummy_pdf = Path(temp) / "dummy.pdf"
dummy_pdf.write_text("%PDF-1.4\n%%EOF\n", encoding="utf-8")
Expand Down
259 changes: 259 additions & 0 deletions .github/scripts/test_v0_3_0_npm_vendor_refresh.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
#!/usr/bin/env python3
#
# Copyright 2026 The Ethos maintainers
#
# Licensed under the Apache License, Version 2.0 (the "License");
#

from __future__ import annotations

import hashlib
import json
import os
import re
import subprocess
import tempfile
import unittest
from pathlib import Path

from makefile_guard import target_block
from validation_record_source import assert_record_source_binding


ROOT = Path(__file__).resolve().parents[2]
PACKAGE_DIR = ROOT / "packages/npm/ethos-pdf"
PACKAGE_JSON = PACKAGE_DIR / "package.json"
PACKAGE_TARBALL = PACKAGE_DIR / "docushell-ethos-pdf-0.3.0.tgz"
RECORD = ROOT / "docs/validation/v0-3-0-npm-vendor-refresh-validation-2026-07-02.md"
ARTIFACT_CLOSEOUT = ROOT / (
"docs/validation/v0-3-0-artifact-publication-closeout-validation-2026-07-02.md"
)
VALIDATION_README = ROOT / "docs/validation/README.md"
EXECUTION_STATUS = ROOT / "docs/execution-status.md"
PUBLIC_RELEASE_CHECKLIST = ROOT / "docs/public-release-checklist.md"
RELEASE_PREP = ROOT / "docs/v0-3-0-release-prep.md"
MAKEFILE = ROOT / "Makefile"

SOURCE_SHORT = "8e20db3"
SOURCE_COMMIT = "8e20db3c796f051925b059f62c294f41f981bcfa"
SOURCE_TREE = "7f528ace4993e21e457aefb5a0aa65ed40297c6c"
MACOS_ARTIFACT_SHA256 = "efb163f140bf4afffd1caeb396f79e42f484591c3e90a86810ca6c0f0c209c96"
LINUX_ARTIFACT_SHA256 = "b549ba5968e04b7679a8d3e879cd45d27f3e9a6fd226eee5c270a4e4f5c01405"
EXPECTED_FILES = {
"LICENSE",
"NOTICE",
"QUICKSTART.md",
"README.md",
"bin/ethos-pdf.js",
"package.json",
"scripts/postinstall.js",
"scripts/prepare-vendor.js",
"vendor/ethos-darwin-arm64",
"vendor/ethos-linux-x64",
"vendor/manifest.json",
}
EXPECTED_VENDOR_SHA256 = {
"vendor/ethos-darwin-arm64": "777e1fb243425a46b83b63ed92fbf7cb810f59cfedd81cfe671cf791410c20dc",
"vendor/ethos-linux-x64": "b416993fc38e6f794611b8b71789ed85af18eb6aa63fef380d9ae7738661f154",
"vendor/manifest.json": "e313b42e49b258171611935455fd9e70bad7ce61c409df63ab90aaa2732a46af",
}
EXPECTED_PACK_SHASUM = "1a90cebd8d52011ea5c41629becdfb37dec73ee7"
EXPECTED_PACK_SHA256 = "1b72ef2fd9415f9edff93319ee2763e8f67cd6168ea00cd64d89a3760101c5fa"
EXPECTED_PACK_INTEGRITY = (
"sha512-ZWoIY5BO7O8tzN88ICGvRasmOt7/RSN/xWFM2ONT8lavQqIOuCY/bQjvxnuK9vGpNeogh8X4UXHLLSRKqqHVOQ=="
)
EXPECTED_NODE_VERSION = "v23.11.1"
EXPECTED_NPM_VERSION = "10.9.2"
PRIVATE_PATH_MARKERS = (
"/" + "Users/",
"/" + "private/tmp",
"/" + "private/var",
"/" + "var/folders",
"saumil" + "diwaker",
"Desktop/" + "Stuff",
"project/repo/" + "ethos",
)
FORBIDDEN_APPROVALS = (
"npm publication approved",
"npm publish approved",
"github release artifact publication approved",
"registry publication approved",
"release tag creation approved",
"package tag creation approved",
"public installation wording approved",
"installable 0.3.0 wording approved",
"production-ready",
)


def sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()


def read(path: Path) -> str:
return path.read_text(encoding="utf-8")


def normalized(path: Path) -> str:
return re.sub(r"\s+", " ", read(path))


def pack_candidate(temp: str) -> dict[str, object]:
env = {**os.environ, "npm_config_cache": str(Path(temp) / "npm-cache")}
result = subprocess.run(
["npm", "pack", "--json"],
cwd=PACKAGE_DIR,
check=False,
encoding="utf-8",
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
if result.returncode != 0:
raise AssertionError(result.stderr)
return json.loads(result.stdout)[0]


class V030NpmVendorRefreshTests(unittest.TestCase):
def test_vendor_payload_files_are_exact_v0_3_release_derived_binaries(self) -> None:
self.assertEqual("0.3.0", json.loads(read(PACKAGE_JSON))["version"])
for relative_path, expected in EXPECTED_VENDOR_SHA256.items():
self.assertEqual(expected, sha256(PACKAGE_DIR / relative_path))

manifest = json.loads(read(PACKAGE_DIR / "vendor/manifest.json"))
self.assertEqual(MACOS_ARTIFACT_SHA256, manifest["targets"]["darwin:arm64"]["release_asset_sha256"])
self.assertEqual(LINUX_ARTIFACT_SHA256, manifest["targets"]["linux:x64"]["release_asset_sha256"])

def test_npm_pack_candidate_contents_and_checksums(self) -> None:
node_version = subprocess.check_output(["node", "--version"], encoding="utf-8").strip()
npm_version = subprocess.check_output(["npm", "--version"], encoding="utf-8").strip()
exact_pack_toolchain = (
node_version == EXPECTED_NODE_VERSION and npm_version == EXPECTED_NPM_VERSION
)

with tempfile.TemporaryDirectory(prefix="ethos-v0-3-npm-candidate-") as temp:
try:
pack = pack_candidate(temp)
files = {entry["path"]: entry for entry in pack["files"]}

self.assertEqual("@docushell/ethos-pdf", pack["name"])
self.assertEqual("0.3.0", pack["version"])
self.assertEqual("docushell-ethos-pdf-0.3.0.tgz", pack["filename"])
self.assertEqual(EXPECTED_FILES, set(files))
self.assertEqual(493, files["vendor/ethos-darwin-arm64"]["mode"])
self.assertEqual(493, files["vendor/ethos-linux-x64"]["mode"])
for relative_path, expected in EXPECTED_VENDOR_SHA256.items():
self.assertEqual(expected, sha256(PACKAGE_DIR / relative_path))
if exact_pack_toolchain:
self.assertEqual(EXPECTED_PACK_SHASUM, pack["shasum"])
self.assertEqual(EXPECTED_PACK_INTEGRITY, pack["integrity"])
self.assertEqual(EXPECTED_PACK_SHA256, sha256(PACKAGE_TARBALL))
finally:
PACKAGE_TARBALL.unlink(missing_ok=True)

def test_candidate_tarball_installs_and_preserves_pdfium_boundary(self) -> None:
with tempfile.TemporaryDirectory(prefix="ethos-v0-3-npm-install-") as temp:
try:
pack_candidate(temp)
env = {**os.environ, "npm_config_cache": str(Path(temp) / "npm-cache")}
install = subprocess.run(
["npm", "install", str(PACKAGE_TARBALL), "--prefix", temp],
cwd=ROOT,
check=False,
encoding="utf-8",
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
self.assertEqual(0, install.returncode, install.stderr)

ethos = Path(temp) / "node_modules/.bin/ethos"
version = subprocess.run(
[str(ethos), "--version"],
check=False,
encoding="utf-8",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
self.assertEqual(0, version.returncode, version.stderr)
self.assertEqual("ethos 0.3.0", version.stdout.strip())

missing_pdfium = subprocess.run(
[str(ethos), "doctor", "--require-pdfium"],
check=False,
encoding="utf-8",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
self.assertEqual(12, missing_pdfium.returncode)
combined = missing_pdfium.stdout + missing_pdfium.stderr
self.assertIn("ethos 0.3.0", combined)
self.assertIn("darwin:arm64", combined)
self.assertIn("approved npm vendor manifest", combined)
self.assertIn("ETHOS_PDFIUM_LIBRARY_PATH", combined)
finally:
PACKAGE_TARBALL.unlink(missing_ok=True)

def test_evidence_record_is_source_bound_indexed_and_blocked(self) -> None:
raw = read(RECORD)
record = normalized(RECORD)
readme = normalized(VALIDATION_README)
execution = normalized(EXECUTION_STATUS)
checklist = normalized(PUBLIC_RELEASE_CHECKLIST)
release_prep = normalized(RELEASE_PREP)
block = target_block("v0-3-release-prep")
artifact_closeout_guard = (
"$(PYTHON) .github/scripts/test_v0_3_0_artifact_publication_closeout.py"
)
scaffold_guard = "$(PYTHON) .github/scripts/test_npm_binary_package_scaffold.py"
vendor_guard = "$(PYTHON) .github/scripts/test_v0_3_0_npm_vendor_refresh.py"
public_surface_guard = "$(PYTHON) .github/scripts/test_public_surface_posture.py"

assert_record_source_binding(
self,
root=ROOT,
raw_record=raw,
normalized_record=record,
validated_head=SOURCE_SHORT,
source_label="v0.3.0 npm vendor refresh",
source_commit=SOURCE_COMMIT,
source_tree=SOURCE_TREE,
)
for expected in (
ARTIFACT_CLOSEOUT.name,
MACOS_ARTIFACT_SHA256,
LINUX_ARTIFACT_SHA256,
EXPECTED_PACK_SHASUM,
EXPECTED_PACK_SHA256,
EXPECTED_PACK_INTEGRITY,
f"Node.js: `{EXPECTED_NODE_VERSION}`",
f"npm: `{EXPECTED_NPM_VERSION}`",
"durable package-content provenance",
"per-file vendor SHA256 values as the durable content binding",
"@docushell/ethos-pdf@0.3.0",
"ethos 0.3.0",
"exit code 12",
"npm publication remains blocked",
"Public `0.3.0` install wording remains blocked",
"current published npm package remains `@docushell/ethos-pdf@0.2.1`",
):
self.assertIn(expected, record)
for text in (readme, execution, checklist, release_prep):
self.assertIn(RECORD.name, text)
self.assertIn("v0.3.0 npm vendor refresh", text.lower())
self.assertIn("npm publication", text)
self.assertIn("blocked", text.lower())
for forbidden in FORBIDDEN_APPROVALS:
self.assertNotIn(forbidden, record.lower())
for marker in PRIVATE_PATH_MARKERS:
self.assertNotIn(marker, raw)
self.assertIn(scaffold_guard, block)
self.assertIn(vendor_guard, block)
self.assertEqual(1, block.count(vendor_guard))
self.assertLess(block.index(artifact_closeout_guard), block.index(scaffold_guard))
self.assertLess(block.index(scaffold_guard), block.index(vendor_guard))
self.assertLess(block.index(vendor_guard), block.index(public_surface_guard))


if __name__ == "__main__":
unittest.main()
3 changes: 2 additions & 1 deletion .github/scripts/test_v0_3_0_package_build_evidence.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@ def test_python_wheel_candidate_is_0_3_0_and_helper_smoke_passes(self) -> None:
def test_source_metadata_and_public_install_baseline_remain_split(self) -> None:
self.assertIn('version = "0.3.0"', read(PYPROJECT))
self.assertIn('__version__ = "0.3.0"', read(PY_INIT))
self.assertEqual("0.2.1", json.loads(read(NPM_PACKAGE))["version"])
self.assertIn("- npm package metadata remains `@docushell/ethos-pdf@0.2.1`", read(RECORD))
self.assertIn(json.loads(read(NPM_PACKAGE))["version"], {"0.2.1", "0.3.0"})

def test_record_keeps_publication_artifact_npm_and_docushell_boundaries_blocked(self) -> None:
raw = read(RECORD)
Expand Down
Loading
Loading