From e589f06fadd3887bcb967f36cf7ea94103bc13d8 Mon Sep 17 00:00:00 2001 From: Luke Parke <5702154+LukasParke@users.noreply.github.com> Date: Mon, 10 Aug 2026 12:29:31 -0500 Subject: [PATCH] fix(release): unblock the release train's scope gate for mcp version PRs Two latent breakages that would make the train refuse every Version PR bumping @openrouter/mcp: 1. verify-version-pr-scope.sh rejected packages/mcp/src/version.ts, the committed gen:version output that pnpm run version regenerates in every Version PR (see publish.yaml). Allowlist it and content-vet its diff against the fixed gen-version.mjs output shape, same as package.json. 2. packages/agent/package.json carried a literal \u2014 escape in its description; changeset version re-serializes with JSON.stringify and normalizes it to the literal em-dash, so every Version PR showed a non-version diff line and failed the content vet. The parsed string is identical, so package metadata is unchanged. --- .github/scripts/verify-version-pr-scope.sh | 26 +++++++++++++++++----- packages/agent/package.json | 2 +- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/.github/scripts/verify-version-pr-scope.sh b/.github/scripts/verify-version-pr-scope.sh index 5ee26e75..38e3882a 100755 --- a/.github/scripts/verify-version-pr-scope.sh +++ b/.github/scripts/verify-version-pr-scope.sh @@ -5,8 +5,11 @@ # # Two layers, both fail-closed: # 1. Path allowlist: consumed changesets (.changeset/*.md) and per-package -# package.json / CHANGELOG.md. No root package.json (private, -# unversioned), no lockfile (workspace:* deps don't touch it). +# package.json / CHANGELOG.md / src/version.ts. No root package.json +# (private, unversioned), no lockfile (workspace:* deps don't touch it). +# src/version.ts is the committed gen:version output (see publish.yaml's +# `pnpm run version` note) — a Version PR bumping @openrouter/mcp always +# carries it, so excluding it would fail every such train run. # 2. Content vet for package.json: paths alone are not enough — a smuggled # `"postinstall"` script in packages/*/package.json passes a path check, # survives `pnpm install --frozen-lockfile` (script-only edits don't @@ -14,6 +17,9 @@ # npm OIDC id-token is in scope. So every changed line in a package.json # must be a version bump or an internal @openrouter/* dependency range # bump — exactly what `changeset version` emits (cf. Version PR #57). +# src/version.ts gets the same treatment: every changed line must match +# the fixed gen-version.mjs output shape (comments or the PACKAGE_VERSION +# constant), so a smuggled statement can't ride the auto-merge either. # # File list is paginated via the REST API: `gh pr view --json files` caps at # 100 entries and sorts .changeset/ first, so a padded PR could hide an @@ -64,12 +70,19 @@ fi printf '%s\n' "$FILES_NDJSON" | python3 -c ' import json, re, sys -ALLOW = re.compile(r"^(\.changeset/[^/]+\.md|packages/[^/]+/(package\.json|CHANGELOG\.md))$") +ALLOW = re.compile(r"^(\.changeset/[^/]+\.md|packages/[^/]+/(package\.json|CHANGELOG\.md|src/version\.ts))$") # The only lines `changeset version` changes in a package.json: the version # field, and internal dependency ranges when updateInternalDependencies fires. OK_LINE = re.compile( r"^[+-]\s*\"(version|@openrouter/[A-Za-z0-9._-]+)\":\s*\"[^\"]*\",?\s*$" ) +# gen-version.mjs emits a fixed 5-line file; a version bump only rewrites the +# string literal in the constant. Allow comment lines, the blank line, and the +# constant itself. \x27 is a single quote (this code lives inside a +# shell-single-quoted string, so literal apostrophes are unusable here). +OK_VERSION_TS_LINE = re.compile( + r"^[+-]\s*(//.*|/\*\*.*\*/|export const PACKAGE_VERSION = \x27[^\x27]+\x27;)?\s*$" +) bad = [] for raw in sys.stdin: @@ -81,16 +94,17 @@ for raw in sys.stdin: if not ALLOW.match(name): bad.append(f"path outside allowlist: {name}") continue - if name.endswith("package.json"): + if name.endswith("package.json") or name.endswith("src/version.ts"): + ok_line = OK_VERSION_TS_LINE if name.endswith(".ts") else OK_LINE patch = f.get("patch") if patch is None: # No inline patch (file too large / binary flag) — cannot vet. - bad.append(f"unvettable package.json diff: {name}") + bad.append(f"unvettable diff: {name}") continue for line in patch.splitlines(): if line.startswith(("+++", "---")) or not line.startswith(("+", "-")): continue - if not OK_LINE.match(line): + if not ok_line.match(line): bad.append(f"non-version change in {name}: {line[:100]}") break diff --git a/packages/agent/package.json b/packages/agent/package.json index 195e651f..e9dd569b 100644 --- a/packages/agent/package.json +++ b/packages/agent/package.json @@ -2,7 +2,7 @@ "name": "@openrouter/agent", "version": "0.8.0", "author": "OpenRouter", - "description": "Agent toolkit for building AI applications with OpenRouter \u2014 tool orchestration, streaming, multi-turn conversations, and format compatibility.", + "description": "Agent toolkit for building AI applications with OpenRouter — tool orchestration, streaming, multi-turn conversations, and format compatibility.", "keywords": [ "openrouter", "agent",