Files
yvgude--lean-ctx/scripts/check-package-versions.py
T
wehub-resource-sync 26382a7ac6
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
JetBrains Plugin / Actionlint (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (rust) (push) Waiting to run
JetBrains Plugin / Validation (push) Waiting to run
JetBrains Plugin / Build (push) Waiting to run
JetBrains Plugin / Test (push) Blocked by required conditions
Security Check / Security Scan (push) Waiting to run
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:30 +08:00

96 lines
3.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""Engine <-> npm package version-coupling gate.
Every npm package that *ships the engine* (as opposed to an independently
versioned SDK, or the decoupled editor extension) MUST carry the exact engine
version. Otherwise a release silently skips publishing the stale package (npm
"already exists" -> continue-on-error) and `npx`/Pi users quietly fall a version
behind — the exact drift GH issue reports about the Pi extension came from.
This gate is the *enforced* counterpart of the DEPLOY_CHECKLIST "Version bumped
in ALL locations" step: it fails on every push/PR (CI) and blocks the release
build, so the engine and its wrapper packages can never diverge.
Source of truth:
* engine version: rust/Cargo.toml [package] version (first `^version =`)
Coupled packages (must equal the engine version):
* packages/pi-lean-ctx/package.json — Pi Coding Agent extension
* packages/lean-ctx-bin/package.json — npx/npm binary wrapper
Deliberately excluded:
* vscode-extension — decoupled cadence (vscode-v* tags, own workflow)
* packages/node-lean-ctx and the cookbook SDKs — own semver, guarded by
scripts/check-sdk-versions.py
No third-party dependencies — standard library only.
"""
from __future__ import annotations
import json
import pathlib
import re
import sys
ROOT = pathlib.Path(__file__).resolve().parent.parent
# npm packages whose version must match the engine, relative to the repo root.
COUPLED_PACKAGES = [
"packages/pi-lean-ctx/package.json",
"packages/lean-ctx-bin/package.json",
]
FAILURES: list[str] = []
def read(path: str) -> str:
return (ROOT / path).read_text(encoding="utf-8")
def engine_version() -> str:
"""The [package] version from the workspace root Cargo.toml (first `^version =`)."""
m = re.search(r'^version\s*=\s*"([^"]+)"', read("rust/Cargo.toml"), re.M)
if not m:
sys.exit("FATAL: [package] version not found in rust/Cargo.toml")
return m.group(1)
def package_version(rel: str) -> str:
return json.loads(read(rel))["version"]
def main() -> int:
engine = engine_version()
print(f"engine version (rust/Cargo.toml): {engine}")
for rel in COUPLED_PACKAGES:
try:
got = package_version(rel)
except (OSError, KeyError, json.JSONDecodeError) as e:
FAILURES.append(f"{rel}: could not read version ({e})")
continue
status = "ok" if got == engine else "DRIFT"
print(f" {rel:<38} {got:<12} {status}")
if got != engine:
FAILURES.append(
f"{rel} is {got} but the engine ships {engine} — bump it to {engine}"
)
for f in FAILURES:
print(f"::error title=Package version drift::{f}")
if FAILURES:
print(
f"\n{len(FAILURES)} package(s) out of sync with engine {engine}. "
"Bump every coupled package.json to the engine version before releasing."
)
return 1
print(f"\nOK: all {len(COUPLED_PACKAGES)} coupled packages match engine {engine}")
return 0
if __name__ == "__main__":
sys.exit(main())