headroom/scripts/version-sync.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

205 lines
6.8 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
"""Synchronize version across all headroom packages."""
from __future__ import annotations
import argparse
import json
import re
from pathlib import Path
try:
import tomllib
except ImportError: # pragma: no cover - Python 3.10 fallback
import tomli as tomllib
def get_version_from_pyproject(root: Path) -> str:
"""Read version from pyproject.toml."""
pyproject_path = root / "pyproject.toml"
with open(pyproject_path, "rb") as f:
data = tomllib.load(f)
return data["project"]["version"]
def bump_version(version: str, bump_type: str) -> str:
"""Bump version according to bump_type (major, minor, patch)."""
major, minor, patch = map(int, version.split("."))
if bump_type == "major":
major += 1
minor = 0
patch = 0
elif bump_type == "minor":
minor += 1
patch = 0
elif bump_type == "patch":
patch += 1
return f"{major}.{minor}.{patch}"
def update_package_json(file_path: Path, version: str) -> None:
"""Update a package.json version field."""
with open(file_path, encoding="utf-8") as f:
data = json.load(f)
data["version"] = version
with open(file_path, "w", encoding="utf-8") as f:
chore(release): harden local artifact smokes (#1824) ## Description Harden the release artifact workflow so maintainers can reproduce npm and Python release checks locally and so OpenClaw packaging does not depend on a not-yet-published SDK version. This follow-up also keeps the OpenClaw loader export contract explicit and updates the PR after the branch was merged with current `headroomlabs/main`. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [x] Documentation update ## Changes Made - Added reusable local release smoke scripts for npm assets, Python wheel/sdist artifacts, and the combined release gate. - Switched the release workflow npm asset build to the reusable npm builder. - Made OpenClaw release asset building install against the just-built local SDK tarball before rewriting packed metadata to the release dependency range. - Kept the OpenClaw source dependency registry-installable at `headroom-ai@^0.22.3` while the packed artifact still ships `^<release-version>`. - Added `registerHeadroomPlugin` as a named export while preserving the default `{ register }` OpenClaw loader contract. - Added Windows development bootstrap docs/script and regression tests for version sync, npm asset ordering, OpenClaw source installability, and Python wheel smoke import isolation. ## Testing - [x] Unit tests pass (`pytest`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text uv run --with pytest python -m pytest tests/test_release_workflows.py scripts/tests/test_version_sync.py -q 44 passed, 1 warning node --check scripts/build_npm_release_assets.mjs node --check scripts/verify_npm_release_assets.mjs python -m py_compile scripts/build_python_release_smoke.py scripts/release_smoke_all.py scripts/version-sync.py python scripts/verify-versions.py All versions aligned at 0.31.0 npm ci (plugins/openclaw) added 88 packages, audited 89 packages, found 0 vulnerabilities python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739 Verified npm release assets for 0.31.0 wheel metadata OK: headroom_ai-0.31.0-cp310-abi3-win_amd64.whl contains headroom/_core.pyd sdist License-File metadata OK: ['LICENSE', 'NOTICE'] smoke-import OK: version=0.31.0 hello=headroom-core ``` ## Real Behavior Proof - Environment: Windows 11, Python 3.14.3, Node v24.14.0, npm 11.9.0, uv 0.11.15, Rust/Cargo already installed in the local development environment. - Exact command / steps: Ran `python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739` after syncing this branch with current `headroomlabs/main`. - Observed result: The command built `headroom-ai-0.31.0.tgz`, `headroom-openclaw-0.31.0.tgz`, `headroom_ai-0.31.0-cp310-abi3-win_amd64.whl`, and `headroom_ai-0.31.0.tar.gz`; npm verifier passed; the wheel installed into a fresh venv and imported `headroom._core`. - Not tested: Full GitHub Actions release matrix and publish jobs with real PyPI/npm/GitHub Packages credentials. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A. ## Additional Notes The post-merge full smoke initially failed because the OpenClaw source package depended on `headroom-ai@^0.31.0`, which is not available on public npm yet. The builder now installs OpenClaw against the just-built local SDK tarball before build/pack, and then rewrites packed metadata to `^0.31.0`. --------- Co-authored-by: JerrettDavis <mxjerrett@gmail.com> Co-authored-by: Tejas Chopra <chopratejas@gmail.com>
2026-07-14 22:07:34 +02:00
json.dump(data, f, indent=2, ensure_ascii=False)
f.write("\n")
def update_plugin_manifest(file_path: Path, version: str) -> None:
"""Update a plugin.json version field."""
with open(file_path, encoding="utf-8") as f:
data = json.load(f)
data["version"] = version
with open(file_path, "w", encoding="utf-8") as f:
chore(release): harden local artifact smokes (#1824) ## Description Harden the release artifact workflow so maintainers can reproduce npm and Python release checks locally and so OpenClaw packaging does not depend on a not-yet-published SDK version. This follow-up also keeps the OpenClaw loader export contract explicit and updates the PR after the branch was merged with current `headroomlabs/main`. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [x] Documentation update ## Changes Made - Added reusable local release smoke scripts for npm assets, Python wheel/sdist artifacts, and the combined release gate. - Switched the release workflow npm asset build to the reusable npm builder. - Made OpenClaw release asset building install against the just-built local SDK tarball before rewriting packed metadata to the release dependency range. - Kept the OpenClaw source dependency registry-installable at `headroom-ai@^0.22.3` while the packed artifact still ships `^<release-version>`. - Added `registerHeadroomPlugin` as a named export while preserving the default `{ register }` OpenClaw loader contract. - Added Windows development bootstrap docs/script and regression tests for version sync, npm asset ordering, OpenClaw source installability, and Python wheel smoke import isolation. ## Testing - [x] Unit tests pass (`pytest`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text uv run --with pytest python -m pytest tests/test_release_workflows.py scripts/tests/test_version_sync.py -q 44 passed, 1 warning node --check scripts/build_npm_release_assets.mjs node --check scripts/verify_npm_release_assets.mjs python -m py_compile scripts/build_python_release_smoke.py scripts/release_smoke_all.py scripts/version-sync.py python scripts/verify-versions.py All versions aligned at 0.31.0 npm ci (plugins/openclaw) added 88 packages, audited 89 packages, found 0 vulnerabilities python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739 Verified npm release assets for 0.31.0 wheel metadata OK: headroom_ai-0.31.0-cp310-abi3-win_amd64.whl contains headroom/_core.pyd sdist License-File metadata OK: ['LICENSE', 'NOTICE'] smoke-import OK: version=0.31.0 hello=headroom-core ``` ## Real Behavior Proof - Environment: Windows 11, Python 3.14.3, Node v24.14.0, npm 11.9.0, uv 0.11.15, Rust/Cargo already installed in the local development environment. - Exact command / steps: Ran `python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739` after syncing this branch with current `headroomlabs/main`. - Observed result: The command built `headroom-ai-0.31.0.tgz`, `headroom-openclaw-0.31.0.tgz`, `headroom_ai-0.31.0-cp310-abi3-win_amd64.whl`, and `headroom_ai-0.31.0.tar.gz`; npm verifier passed; the wheel installed into a fresh venv and imported `headroom._core`. - Not tested: Full GitHub Actions release matrix and publish jobs with real PyPI/npm/GitHub Packages credentials. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A. ## Additional Notes The post-merge full smoke initially failed because the OpenClaw source package depended on `headroom-ai@^0.31.0`, which is not available on public npm yet. The builder now installs OpenClaw against the just-built local SDK tarball before build/pack, and then rewrites packed metadata to `^0.31.0`. --------- Co-authored-by: JerrettDavis <mxjerrett@gmail.com> Co-authored-by: Tejas Chopra <chopratejas@gmail.com>
2026-07-14 22:07:34 +02:00
json.dump(data, f, indent=2, ensure_ascii=False)
f.write("\n")
def update_marketplace_manifest(file_path: Path, version: str) -> None:
"""Update marketplace metadata and plugin entry versions."""
with open(file_path, encoding="utf-8") as f:
data = json.load(f)
metadata = data.get("metadata")
if isinstance(metadata, dict):
metadata["version"] = version
plugins = data.get("plugins")
if isinstance(plugins, list):
for plugin in plugins:
if isinstance(plugin, dict):
plugin["version"] = version
with open(file_path, "w", encoding="utf-8") as f:
chore(release): harden local artifact smokes (#1824) ## Description Harden the release artifact workflow so maintainers can reproduce npm and Python release checks locally and so OpenClaw packaging does not depend on a not-yet-published SDK version. This follow-up also keeps the OpenClaw loader export contract explicit and updates the PR after the branch was merged with current `headroomlabs/main`. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [x] Documentation update ## Changes Made - Added reusable local release smoke scripts for npm assets, Python wheel/sdist artifacts, and the combined release gate. - Switched the release workflow npm asset build to the reusable npm builder. - Made OpenClaw release asset building install against the just-built local SDK tarball before rewriting packed metadata to the release dependency range. - Kept the OpenClaw source dependency registry-installable at `headroom-ai@^0.22.3` while the packed artifact still ships `^<release-version>`. - Added `registerHeadroomPlugin` as a named export while preserving the default `{ register }` OpenClaw loader contract. - Added Windows development bootstrap docs/script and regression tests for version sync, npm asset ordering, OpenClaw source installability, and Python wheel smoke import isolation. ## Testing - [x] Unit tests pass (`pytest`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text uv run --with pytest python -m pytest tests/test_release_workflows.py scripts/tests/test_version_sync.py -q 44 passed, 1 warning node --check scripts/build_npm_release_assets.mjs node --check scripts/verify_npm_release_assets.mjs python -m py_compile scripts/build_python_release_smoke.py scripts/release_smoke_all.py scripts/version-sync.py python scripts/verify-versions.py All versions aligned at 0.31.0 npm ci (plugins/openclaw) added 88 packages, audited 89 packages, found 0 vulnerabilities python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739 Verified npm release assets for 0.31.0 wheel metadata OK: headroom_ai-0.31.0-cp310-abi3-win_amd64.whl contains headroom/_core.pyd sdist License-File metadata OK: ['LICENSE', 'NOTICE'] smoke-import OK: version=0.31.0 hello=headroom-core ``` ## Real Behavior Proof - Environment: Windows 11, Python 3.14.3, Node v24.14.0, npm 11.9.0, uv 0.11.15, Rust/Cargo already installed in the local development environment. - Exact command / steps: Ran `python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739` after syncing this branch with current `headroomlabs/main`. - Observed result: The command built `headroom-ai-0.31.0.tgz`, `headroom-openclaw-0.31.0.tgz`, `headroom_ai-0.31.0-cp310-abi3-win_amd64.whl`, and `headroom_ai-0.31.0.tar.gz`; npm verifier passed; the wheel installed into a fresh venv and imported `headroom._core`. - Not tested: Full GitHub Actions release matrix and publish jobs with real PyPI/npm/GitHub Packages credentials. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A. ## Additional Notes The post-merge full smoke initially failed because the OpenClaw source package depended on `headroom-ai@^0.31.0`, which is not available on public npm yet. The builder now installs OpenClaw against the just-built local SDK tarball before build/pack, and then rewrites packed metadata to `^0.31.0`. --------- Co-authored-by: JerrettDavis <mxjerrett@gmail.com> Co-authored-by: Tejas Chopra <chopratejas@gmail.com>
2026-07-14 22:07:34 +02:00
json.dump(data, f, indent=2, ensure_ascii=False)
f.write("\n")
fix(release): sync generated version metadata on the release branch The 0.33.0 release PR (#2339) has been blocked since 2026-07-17 in changes-requested, because release-please only rewrites `pyproject.toml` and its configured `extra-files`. `server.json` is asserted byte-for-byte against `render_server_json()`, which reads the version from `pyproject.toml`, so the bump alone fails `test_root_server_json_matches_builder` on the release PR — the `test (2)` shard. Nothing in the repo regenerated `server.json` at all. `release.yml` already runs `version-sync.py` before its own `verify-versions.py` gate (lines 145/278), which is why `build` and `build-wheels` pass on the release PR despite the drift — it syncs in the workspace, uncommitted. The regular CI test job does not sync, so the fix has to be committed to the branch. - `scripts/version-sync.py`: also write `server.json`. It was the one version-carrying file with no writer anywhere, so it fell behind every release. Values are rewritten in place so key order and formatting keep matching the builder's byte-for-byte output. - `.github/workflows/release-metadata-sync.yml` (new): on a push to `release-please--branches--**`, run version-sync, gate on verify-versions, and commit if anything changed. Keyed off the branch push because release-please force-regenerates that branch on every merge to main — that is what repeatedly wiped the hand-pushed metadata fixes on #2339. Uses the same PAT as release-please.yml, since a GITHUB_TOKEN push would not re-trigger the release PR's checks. Idempotent, so the self-triggered rerun no-ops instead of looping. - Corrected the pre-existing drift on main: the agent-hooks plugin manifests, both marketplace manifests, and `.releasemetadata` were stranded at 0.31.0 and were never bumped for 0.32.0 either. `verify-versions.py` now passes on main. Chose running the script over adding ~13 `extra-files` jsonpath entries: the script is the single place that knows these locations, and a jsonpath that fails to match is silent — the same class of failure this removes. There is also no precedent for nested jsonpath in the config today. Tests: `test_server_json_version_is_synchronized`, `test_release_metadata_sync_runs_on_release_please_branch`, and `test_version_sync_covers_every_file_the_verifier_gates` (guards the two scripts against drifting apart again). Not addressed: PyPI is at 9.69GB of its 10GB project cap; the 0.21.x series alone holds 6.58GB across 31 releases. Roughly 4 more releases fit before that blocks.
2026-07-29 14:57:39 -07:00
def update_server_json(file_path: Path, version: str) -> None:
"""Update the MCP registry descriptor's version fields.
``server.json`` is asserted byte-for-byte against ``render_server_json()``
(tests/test_mcp_registry/test_server_json.py), which derives the version from
``pyproject.toml``. Nothing regenerated this file, so it silently fell behind
every release and failed that test on the release PR. Values are rewritten in
place so key order and formatting keep matching the builder's output.
"""
with open(file_path, encoding="utf-8") as f:
data = json.load(f)
data["version"] = version
packages = data.get("packages")
if isinstance(packages, list):
for package in packages:
if isinstance(package, dict):
package["version"] = version
with open(file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
f.write("\n")
def update_plugin_versions(root: Path, version: str) -> None:
"""Update marketplace and plugin manifest versions."""
update_marketplace_manifest(root / ".claude-plugin" / "marketplace.json", version)
update_marketplace_manifest(root / ".github" / "plugin" / "marketplace.json", version)
update_plugin_manifest(
root / "plugins" / "headroom-agent-hooks" / ".claude-plugin" / "plugin.json", version
)
update_plugin_manifest(
root / "plugins" / "headroom-agent-hooks" / ".github" / "plugin" / "plugin.json",
version,
)
chore(release): harden local artifact smokes (#1824) ## Description Harden the release artifact workflow so maintainers can reproduce npm and Python release checks locally and so OpenClaw packaging does not depend on a not-yet-published SDK version. This follow-up also keeps the OpenClaw loader export contract explicit and updates the PR after the branch was merged with current `headroomlabs/main`. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [x] Documentation update ## Changes Made - Added reusable local release smoke scripts for npm assets, Python wheel/sdist artifacts, and the combined release gate. - Switched the release workflow npm asset build to the reusable npm builder. - Made OpenClaw release asset building install against the just-built local SDK tarball before rewriting packed metadata to the release dependency range. - Kept the OpenClaw source dependency registry-installable at `headroom-ai@^0.22.3` while the packed artifact still ships `^<release-version>`. - Added `registerHeadroomPlugin` as a named export while preserving the default `{ register }` OpenClaw loader contract. - Added Windows development bootstrap docs/script and regression tests for version sync, npm asset ordering, OpenClaw source installability, and Python wheel smoke import isolation. ## Testing - [x] Unit tests pass (`pytest`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text uv run --with pytest python -m pytest tests/test_release_workflows.py scripts/tests/test_version_sync.py -q 44 passed, 1 warning node --check scripts/build_npm_release_assets.mjs node --check scripts/verify_npm_release_assets.mjs python -m py_compile scripts/build_python_release_smoke.py scripts/release_smoke_all.py scripts/version-sync.py python scripts/verify-versions.py All versions aligned at 0.31.0 npm ci (plugins/openclaw) added 88 packages, audited 89 packages, found 0 vulnerabilities python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739 Verified npm release assets for 0.31.0 wheel metadata OK: headroom_ai-0.31.0-cp310-abi3-win_amd64.whl contains headroom/_core.pyd sdist License-File metadata OK: ['LICENSE', 'NOTICE'] smoke-import OK: version=0.31.0 hello=headroom-core ``` ## Real Behavior Proof - Environment: Windows 11, Python 3.14.3, Node v24.14.0, npm 11.9.0, uv 0.11.15, Rust/Cargo already installed in the local development environment. - Exact command / steps: Ran `python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739` after syncing this branch with current `headroomlabs/main`. - Observed result: The command built `headroom-ai-0.31.0.tgz`, `headroom-openclaw-0.31.0.tgz`, `headroom_ai-0.31.0-cp310-abi3-win_amd64.whl`, and `headroom_ai-0.31.0.tar.gz`; npm verifier passed; the wheel installed into a fresh venv and imported `headroom._core`. - Not tested: Full GitHub Actions release matrix and publish jobs with real PyPI/npm/GitHub Packages credentials. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A. ## Additional Notes The post-merge full smoke initially failed because the OpenClaw source package depended on `headroom-ai@^0.31.0`, which is not available on public npm yet. The builder now installs OpenClaw against the just-built local SDK tarball before build/pack, and then rewrites packed metadata to `^0.31.0`. --------- Co-authored-by: JerrettDavis <mxjerrett@gmail.com> Co-authored-by: Tejas Chopra <chopratejas@gmail.com>
2026-07-14 22:07:34 +02:00
def update_openclaw_package_json(file_path: Path, version: str) -> None:
"""Update openclaw package.json version.
Keep the source `headroom-ai` dependency registry-installable. The release
workflow rewrites the packed tgz dependency to the exact release range after
the local SDK tarball is available.
"""
with open(file_path, encoding="utf-8") as f:
data = json.load(f)
data["version"] = version
with open(file_path, "w", encoding="utf-8") as f:
chore(release): harden local artifact smokes (#1824) ## Description Harden the release artifact workflow so maintainers can reproduce npm and Python release checks locally and so OpenClaw packaging does not depend on a not-yet-published SDK version. This follow-up also keeps the OpenClaw loader export contract explicit and updates the PR after the branch was merged with current `headroomlabs/main`. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [x] Documentation update ## Changes Made - Added reusable local release smoke scripts for npm assets, Python wheel/sdist artifacts, and the combined release gate. - Switched the release workflow npm asset build to the reusable npm builder. - Made OpenClaw release asset building install against the just-built local SDK tarball before rewriting packed metadata to the release dependency range. - Kept the OpenClaw source dependency registry-installable at `headroom-ai@^0.22.3` while the packed artifact still ships `^<release-version>`. - Added `registerHeadroomPlugin` as a named export while preserving the default `{ register }` OpenClaw loader contract. - Added Windows development bootstrap docs/script and regression tests for version sync, npm asset ordering, OpenClaw source installability, and Python wheel smoke import isolation. ## Testing - [x] Unit tests pass (`pytest`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text uv run --with pytest python -m pytest tests/test_release_workflows.py scripts/tests/test_version_sync.py -q 44 passed, 1 warning node --check scripts/build_npm_release_assets.mjs node --check scripts/verify_npm_release_assets.mjs python -m py_compile scripts/build_python_release_smoke.py scripts/release_smoke_all.py scripts/version-sync.py python scripts/verify-versions.py All versions aligned at 0.31.0 npm ci (plugins/openclaw) added 88 packages, audited 89 packages, found 0 vulnerabilities python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739 Verified npm release assets for 0.31.0 wheel metadata OK: headroom_ai-0.31.0-cp310-abi3-win_amd64.whl contains headroom/_core.pyd sdist License-File metadata OK: ['LICENSE', 'NOTICE'] smoke-import OK: version=0.31.0 hello=headroom-core ``` ## Real Behavior Proof - Environment: Windows 11, Python 3.14.3, Node v24.14.0, npm 11.9.0, uv 0.11.15, Rust/Cargo already installed in the local development environment. - Exact command / steps: Ran `python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739` after syncing this branch with current `headroomlabs/main`. - Observed result: The command built `headroom-ai-0.31.0.tgz`, `headroom-openclaw-0.31.0.tgz`, `headroom_ai-0.31.0-cp310-abi3-win_amd64.whl`, and `headroom_ai-0.31.0.tar.gz`; npm verifier passed; the wheel installed into a fresh venv and imported `headroom._core`. - Not tested: Full GitHub Actions release matrix and publish jobs with real PyPI/npm/GitHub Packages credentials. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A. ## Additional Notes The post-merge full smoke initially failed because the OpenClaw source package depended on `headroom-ai@^0.31.0`, which is not available on public npm yet. The builder now installs OpenClaw against the just-built local SDK tarball before build/pack, and then rewrites packed metadata to `^0.31.0`. --------- Co-authored-by: JerrettDavis <mxjerrett@gmail.com> Co-authored-by: Tejas Chopra <chopratejas@gmail.com>
2026-07-14 22:07:34 +02:00
json.dump(data, f, indent=2, ensure_ascii=False)
f.write("\n")
def update_pyproject_version(root: Path, version: str) -> None:
"""Update pyproject.toml version."""
pyproject_path = root / "pyproject.toml"
content = pyproject_path.read_text(encoding="utf-8")
updated = re.sub(
r'^version = "[^"]+"',
f'version = "{version}"',
content,
flags=re.MULTILINE,
)
pyproject_path.write_text(updated, encoding="utf-8")
def write_release_metadata(root: Path, version: str) -> None:
fix(scripts): rename .releaseetadata to .releasemetadata (#1246) ## Description Fixes a typo in the release metadata filename written by `scripts/version-sync.py`. The file was being created as `.releaseetadata` (double `e`) instead of `.releasemetadata`. Any downstream tooling or developer looking for the artifact by its correct name would not find it. Closes # ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - `scripts/version-sync.py`: corrected the filename in `write_release_metadata()` — both the docstring and the `metadata_path` assignment. - `scripts/tests/test_version_sync.py`: updated 3 test assertions to reference `.releasemetadata`. ## Testing - [x] Unit tests pass (`pytest`) - [ ] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) - [ ] New tests added for new functionality - [ ] Manual testing performed ### Test Output ```text $ uv run python -m pytest scripts/tests/test_version_sync.py -q ============================= test session starts ============================== platform linux -- Python 3.14.0, pytest-9.1.1, pluggy-1.6.0 rootdir: /home/sepurisaikrishna/Documents/calude-here/headroom configfile: pyproject.toml collected 6 items scripts/tests/test_version_sync.py ...... [100%] =============================== warnings summary =============================== PytestConfigWarning: Unknown config option: asyncio_mode -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html ========================= 6 passed, 1 warning in 1.00s ========================= $ git diff --check origin/main..HEAD # no output; command exited 0 ``` ## Real Behavior Proof - Environment: Linux, Python 3.14.0, uv-managed .venv, branch based on current origin/main. - Exact command / steps: grep -r "releaseetadata" scripts/ before the fix returns hits; after the fix returns nothing. Confirmed .releasemetadata is written correctly by test_release_metadata_written. - Observed result: all 6 test_version_sync.py tests pass with the corrected filename. - Not tested: full repository pytest, ruff, and mypy — this is a one-line spelling fix with no logic changes. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A. ## Additional Notes - The typo was consistent across implementation and tests, so all tests passed before this fix with the wrong name. The fix corrects both the code and the test expectations together. - No production behaviour changes the file is written but not yet consumed by any workflow step.
2026-07-10 03:59:17 +05:30
"""Write .releasemetadata JSON file."""
metadata = {
"version": version,
"packages": {
"pypi": version,
"npm-sdk": version,
"npm-openclaw": version,
"agent-hooks-plugin": version,
},
}
fix(scripts): rename .releaseetadata to .releasemetadata (#1246) ## Description Fixes a typo in the release metadata filename written by `scripts/version-sync.py`. The file was being created as `.releaseetadata` (double `e`) instead of `.releasemetadata`. Any downstream tooling or developer looking for the artifact by its correct name would not find it. Closes # ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - `scripts/version-sync.py`: corrected the filename in `write_release_metadata()` — both the docstring and the `metadata_path` assignment. - `scripts/tests/test_version_sync.py`: updated 3 test assertions to reference `.releasemetadata`. ## Testing - [x] Unit tests pass (`pytest`) - [ ] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) - [ ] New tests added for new functionality - [ ] Manual testing performed ### Test Output ```text $ uv run python -m pytest scripts/tests/test_version_sync.py -q ============================= test session starts ============================== platform linux -- Python 3.14.0, pytest-9.1.1, pluggy-1.6.0 rootdir: /home/sepurisaikrishna/Documents/calude-here/headroom configfile: pyproject.toml collected 6 items scripts/tests/test_version_sync.py ...... [100%] =============================== warnings summary =============================== PytestConfigWarning: Unknown config option: asyncio_mode -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html ========================= 6 passed, 1 warning in 1.00s ========================= $ git diff --check origin/main..HEAD # no output; command exited 0 ``` ## Real Behavior Proof - Environment: Linux, Python 3.14.0, uv-managed .venv, branch based on current origin/main. - Exact command / steps: grep -r "releaseetadata" scripts/ before the fix returns hits; after the fix returns nothing. Confirmed .releasemetadata is written correctly by test_release_metadata_written. - Observed result: all 6 test_version_sync.py tests pass with the corrected filename. - Not tested: full repository pytest, ruff, and mypy — this is a one-line spelling fix with no logic changes. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A. ## Additional Notes - The typo was consistent across implementation and tests, so all tests passed before this fix with the wrong name. The fix corrects both the code and the test expectations together. - No production behaviour changes the file is written but not yet consumed by any workflow step.
2026-07-10 03:59:17 +05:30
metadata_path = root / ".releasemetadata"
with open(metadata_path, "w", encoding="utf-8") as f:
chore(release): harden local artifact smokes (#1824) ## Description Harden the release artifact workflow so maintainers can reproduce npm and Python release checks locally and so OpenClaw packaging does not depend on a not-yet-published SDK version. This follow-up also keeps the OpenClaw loader export contract explicit and updates the PR after the branch was merged with current `headroomlabs/main`. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [x] Documentation update ## Changes Made - Added reusable local release smoke scripts for npm assets, Python wheel/sdist artifacts, and the combined release gate. - Switched the release workflow npm asset build to the reusable npm builder. - Made OpenClaw release asset building install against the just-built local SDK tarball before rewriting packed metadata to the release dependency range. - Kept the OpenClaw source dependency registry-installable at `headroom-ai@^0.22.3` while the packed artifact still ships `^<release-version>`. - Added `registerHeadroomPlugin` as a named export while preserving the default `{ register }` OpenClaw loader contract. - Added Windows development bootstrap docs/script and regression tests for version sync, npm asset ordering, OpenClaw source installability, and Python wheel smoke import isolation. ## Testing - [x] Unit tests pass (`pytest`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text uv run --with pytest python -m pytest tests/test_release_workflows.py scripts/tests/test_version_sync.py -q 44 passed, 1 warning node --check scripts/build_npm_release_assets.mjs node --check scripts/verify_npm_release_assets.mjs python -m py_compile scripts/build_python_release_smoke.py scripts/release_smoke_all.py scripts/version-sync.py python scripts/verify-versions.py All versions aligned at 0.31.0 npm ci (plugins/openclaw) added 88 packages, audited 89 packages, found 0 vulnerabilities python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739 Verified npm release assets for 0.31.0 wheel metadata OK: headroom_ai-0.31.0-cp310-abi3-win_amd64.whl contains headroom/_core.pyd sdist License-File metadata OK: ['LICENSE', 'NOTICE'] smoke-import OK: version=0.31.0 hello=headroom-core ``` ## Real Behavior Proof - Environment: Windows 11, Python 3.14.3, Node v24.14.0, npm 11.9.0, uv 0.11.15, Rust/Cargo already installed in the local development environment. - Exact command / steps: Ran `python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739` after syncing this branch with current `headroomlabs/main`. - Observed result: The command built `headroom-ai-0.31.0.tgz`, `headroom-openclaw-0.31.0.tgz`, `headroom_ai-0.31.0-cp310-abi3-win_amd64.whl`, and `headroom_ai-0.31.0.tar.gz`; npm verifier passed; the wheel installed into a fresh venv and imported `headroom._core`. - Not tested: Full GitHub Actions release matrix and publish jobs with real PyPI/npm/GitHub Packages credentials. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A. ## Additional Notes The post-merge full smoke initially failed because the OpenClaw source package depended on `headroom-ai@^0.31.0`, which is not available on public npm yet. The builder now installs OpenClaw against the just-built local SDK tarball before build/pack, and then rewrites packed metadata to `^0.31.0`. --------- Co-authored-by: JerrettDavis <mxjerrett@gmail.com> Co-authored-by: Tejas Chopra <chopratejas@gmail.com>
2026-07-14 22:07:34 +02:00
json.dump(metadata, f, indent=2, ensure_ascii=False)
f.write("\n")
def main() -> None:
parser = argparse.ArgumentParser(description="Synchronize version across headroom packages")
parser.add_argument(
"--root",
type=Path,
default=Path(__file__).parent.parent,
help="Root directory of the project",
)
group = parser.add_mutually_exclusive_group()
group.add_argument("--version", help="Explicit version to set (e.g., 0.6.0)")
group.add_argument(
"--bump",
choices=["major", "minor", "patch"],
help="Bump version from pyproject.toml",
)
parser.add_argument(
"--plugin-manifests-only",
action="store_true",
help="Only update marketplace/plugin manifest versions",
)
args = parser.parse_args()
if args.version:
version = args.version
elif args.bump:
base_version = get_version_from_pyproject(args.root)
version = bump_version(base_version, args.bump)
else:
version = get_version_from_pyproject(args.root)
if args.plugin_manifests_only:
update_plugin_versions(args.root, version)
print(f"Plugin versions synchronized to {version}")
return
# Update all versioned files
update_pyproject_version(args.root, version)
chore(release): harden local artifact smokes (#1824) ## Description Harden the release artifact workflow so maintainers can reproduce npm and Python release checks locally and so OpenClaw packaging does not depend on a not-yet-published SDK version. This follow-up also keeps the OpenClaw loader export contract explicit and updates the PR after the branch was merged with current `headroomlabs/main`. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [x] Documentation update ## Changes Made - Added reusable local release smoke scripts for npm assets, Python wheel/sdist artifacts, and the combined release gate. - Switched the release workflow npm asset build to the reusable npm builder. - Made OpenClaw release asset building install against the just-built local SDK tarball before rewriting packed metadata to the release dependency range. - Kept the OpenClaw source dependency registry-installable at `headroom-ai@^0.22.3` while the packed artifact still ships `^<release-version>`. - Added `registerHeadroomPlugin` as a named export while preserving the default `{ register }` OpenClaw loader contract. - Added Windows development bootstrap docs/script and regression tests for version sync, npm asset ordering, OpenClaw source installability, and Python wheel smoke import isolation. ## Testing - [x] Unit tests pass (`pytest`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text uv run --with pytest python -m pytest tests/test_release_workflows.py scripts/tests/test_version_sync.py -q 44 passed, 1 warning node --check scripts/build_npm_release_assets.mjs node --check scripts/verify_npm_release_assets.mjs python -m py_compile scripts/build_python_release_smoke.py scripts/release_smoke_all.py scripts/version-sync.py python scripts/verify-versions.py All versions aligned at 0.31.0 npm ci (plugins/openclaw) added 88 packages, audited 89 packages, found 0 vulnerabilities python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739 Verified npm release assets for 0.31.0 wheel metadata OK: headroom_ai-0.31.0-cp310-abi3-win_amd64.whl contains headroom/_core.pyd sdist License-File metadata OK: ['LICENSE', 'NOTICE'] smoke-import OK: version=0.31.0 hello=headroom-core ``` ## Real Behavior Proof - Environment: Windows 11, Python 3.14.3, Node v24.14.0, npm 11.9.0, uv 0.11.15, Rust/Cargo already installed in the local development environment. - Exact command / steps: Ran `python scripts/release_smoke_all.py --out release-assets-local/all-pr1824-postmerge-fixed-20260710-104739` after syncing this branch with current `headroomlabs/main`. - Observed result: The command built `headroom-ai-0.31.0.tgz`, `headroom-openclaw-0.31.0.tgz`, `headroom_ai-0.31.0-cp310-abi3-win_amd64.whl`, and `headroom_ai-0.31.0.tar.gz`; npm verifier passed; the wheel installed into a fresh venv and imported `headroom._core`. - Not tested: Full GitHub Actions release matrix and publish jobs with real PyPI/npm/GitHub Packages credentials. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A. ## Additional Notes The post-merge full smoke initially failed because the OpenClaw source package depended on `headroom-ai@^0.31.0`, which is not available on public npm yet. The builder now installs OpenClaw against the just-built local SDK tarball before build/pack, and then rewrites packed metadata to `^0.31.0`. --------- Co-authored-by: JerrettDavis <mxjerrett@gmail.com> Co-authored-by: Tejas Chopra <chopratejas@gmail.com>
2026-07-14 22:07:34 +02:00
update_openclaw_package_json(args.root / "plugins" / "openclaw" / "package.json", version)
update_package_json(args.root / "sdk" / "typescript" / "package.json", version)
update_plugin_versions(args.root, version)
fix(release): sync generated version metadata on the release branch The 0.33.0 release PR (#2339) has been blocked since 2026-07-17 in changes-requested, because release-please only rewrites `pyproject.toml` and its configured `extra-files`. `server.json` is asserted byte-for-byte against `render_server_json()`, which reads the version from `pyproject.toml`, so the bump alone fails `test_root_server_json_matches_builder` on the release PR — the `test (2)` shard. Nothing in the repo regenerated `server.json` at all. `release.yml` already runs `version-sync.py` before its own `verify-versions.py` gate (lines 145/278), which is why `build` and `build-wheels` pass on the release PR despite the drift — it syncs in the workspace, uncommitted. The regular CI test job does not sync, so the fix has to be committed to the branch. - `scripts/version-sync.py`: also write `server.json`. It was the one version-carrying file with no writer anywhere, so it fell behind every release. Values are rewritten in place so key order and formatting keep matching the builder's byte-for-byte output. - `.github/workflows/release-metadata-sync.yml` (new): on a push to `release-please--branches--**`, run version-sync, gate on verify-versions, and commit if anything changed. Keyed off the branch push because release-please force-regenerates that branch on every merge to main — that is what repeatedly wiped the hand-pushed metadata fixes on #2339. Uses the same PAT as release-please.yml, since a GITHUB_TOKEN push would not re-trigger the release PR's checks. Idempotent, so the self-triggered rerun no-ops instead of looping. - Corrected the pre-existing drift on main: the agent-hooks plugin manifests, both marketplace manifests, and `.releasemetadata` were stranded at 0.31.0 and were never bumped for 0.32.0 either. `verify-versions.py` now passes on main. Chose running the script over adding ~13 `extra-files` jsonpath entries: the script is the single place that knows these locations, and a jsonpath that fails to match is silent — the same class of failure this removes. There is also no precedent for nested jsonpath in the config today. Tests: `test_server_json_version_is_synchronized`, `test_release_metadata_sync_runs_on_release_please_branch`, and `test_version_sync_covers_every_file_the_verifier_gates` (guards the two scripts against drifting apart again). Not addressed: PyPI is at 9.69GB of its 10GB project cap; the 0.21.x series alone holds 6.58GB across 31 releases. Roughly 4 more releases fit before that blocks.
2026-07-29 14:57:39 -07:00
update_server_json(args.root / "server.json", version)
write_release_metadata(args.root, version)
print(f"Version synchronized to {version}")
if __name__ == "__main__":
main()