diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f22fef3682..f39add67ac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -670,7 +670,7 @@ jobs: - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: - node-version: "26.12.0" + node-version: "26.12.1" - name: Install reviewed npm run: npm install -g npm@12.2.0 @@ -703,8 +703,8 @@ jobs: run: | set -euo pipefail json="$(npm pack --json --ignore-scripts)" - filename="$(node -e 'console.log(JSON.parse(process.argv[1])[0].filename)' "$json")" - test -f "$filename" + filename="$(printf '%s' "$json" | python3 ../../scripts/extract-npm-pack-filename.py)" + test -s "$filename" echo "filename=$filename" >> "$GITHUB_OUTPUT" - name: Stage the reviewed npm publish tool @@ -768,7 +768,7 @@ jobs: - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: - node-version: "26.12.0" + node-version: "26.12.1" # Prerelease SDK versions mirror the beta release convention: they take # the beta dist-tag and never take latest. Recovery re-runs are diff --git a/.github/workflows/sdk-conformance.yml b/.github/workflows/sdk-conformance.yml index 2f4c82b6e0..eb1847ef5d 100644 --- a/.github/workflows/sdk-conformance.yml +++ b/.github/workflows/sdk-conformance.yml @@ -20,6 +20,7 @@ on: - "pnpm-workspace.yaml" - "scripts/check-sdk-publish-workflow.py" - "scripts/test-check-sdk-publish-workflow.py" + - "scripts/extract-npm-pack-filename.py" - "scripts/check-github-hosted-runners.py" - "scripts/test-check-github-hosted-runners.py" - "scripts/package-release-archive.py" diff --git a/scripts/extract-npm-pack-filename.py b/scripts/extract-npm-pack-filename.py new file mode 100644 index 0000000000..677fbfea8b --- /dev/null +++ b/scripts/extract-npm-pack-filename.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import json +import sys + +try: + output = json.load(sys.stdin) +except json.JSONDecodeError as error: + print(f"npm pack returned invalid JSON: {error}", file=sys.stderr) + raise SystemExit(1) from error + +if not isinstance(output, dict) or len(output) != 1: + print("npm pack must return one package-name-keyed record", file=sys.stderr) + raise SystemExit(1) + +metadata = next(iter(output.values())) +filename = metadata.get("filename") if isinstance(metadata, dict) else None +if not isinstance(filename, str) or not filename: + print("npm pack record must contain a filename", file=sys.stderr) + raise SystemExit(1) + +print(filename) diff --git a/scripts/test-check-sdk-publish-workflow.py b/scripts/test-check-sdk-publish-workflow.py index 555a495a0c..cd931f2051 100755 --- a/scripts/test-check-sdk-publish-workflow.py +++ b/scripts/test-check-sdk-publish-workflow.py @@ -5,6 +5,9 @@ import copy import importlib.util +import json +import subprocess +import sys import tempfile import unittest from pathlib import Path @@ -38,6 +41,23 @@ def test_command_refactoring_does_not_require_a_policy_inventory_update(self) -> step["run"] = "./scripts/check-and-pack-sdk.sh" CHECKER.validate(self.workflow) + def test_npm_pack_object_output_yields_the_package_filename(self) -> None: + pack_output = json.dumps({ + "@tracedecay/sdk": { + "id": "@tracedecay/sdk@0.15.0", + "filename": "tracedecay-sdk-0.15.0.tgz", + }, + }) + result = subprocess.run( + [sys.executable, str(ROOT / "scripts/extract-npm-pack-filename.py")], + input=pack_output, + text=True, + capture_output=True, + check=False, + ) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(result.stdout.strip(), "tracedecay-sdk-0.15.0.tgz") + def test_dispatch_requires_an_explicit_string_release_tag(self) -> None: triggers = self.workflow.get("on", self.workflow.get(True)) inputs = triggers["workflow_dispatch"]["inputs"]