headroom/scripts/tests/test_version_sync.py

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

417 lines
15 KiB
Python
Raw Permalink Normal View History

"""Tests for version-sync.py."""
import json
import subprocess
import sys
from pathlib import Path
import pytest
@pytest.fixture
def temp_project(tmp_path: Path) -> dict[str, Path]:
"""Create a temporary project with all versioned files."""
# Create directory structure
root = tmp_path / "project"
headroom = root / "headroom"
headroom.mkdir(parents=True)
repo_claude_plugin = root / ".claude-plugin"
repo_claude_plugin.mkdir(parents=True)
repo_github_plugin = root / ".github" / "plugin"
repo_github_plugin.mkdir(parents=True)
plugins = root / "plugins"
openclaw = plugins / "openclaw"
openclaw.mkdir(parents=True)
fix: publish headroom-opencode in release workflow (#2372) ## Description `headroom-opencode` is documented as an npm package, but the release workflow never published it, so installs failed with a registry 404 even though the plugin source already lived under `plugins/opencode`. This wires the existing package into the npm release path, keeps its version synced with root releases, and adds release guards for the new package. Closes #76. ## 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) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - added `headroom-opencode` to the npm release workflow, including release-version stamping and `headroom-ai` dependency rewrite before publish - added `plugins/opencode/package.json` to release-please and local version-sync guards - synced the source opencode package version to the current release line and documented the new npm package in the release docs - added focused release workflow and version-sync tests for the opencode package - aligned the two failing dashboard Playwright tests with the current Session/Lifetime split and `/stats-lifetime` fixture contract ## Testing - [x] Unit tests pass (`uv run pytest scripts/tests/test_version_sync.py -q`, `uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency'`) - [x] Unit tests pass (`uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q`) - [x] Linting passes (`uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py`) - [ ] Type checking passes (`uv run mypy headroom`) - [x] New tests added for new functionality when applicable - [x] Manual testing performed ### Test Output ```text $ uv run pytest scripts/tests/test_version_sync.py -q 8 passed, 1 warning in 0.51s $ uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency' 2 passed, 38 deselected, 1 warning in 0.07s $ uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q 4 passed, 1 warning in 4.04s $ uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ npm ci && npm run build (plugins/opencode) Build success; dist/index.js, dist/entry.opencode.js, and DTS outputs emitted ``` ## Real Behavior Proof - Environment: Windows, Python 3.11.15, Node v24.15.0, npm 11.16.0 - Exact command / steps: inspected `.github/workflows/release.yml`, updated the npm publish path for `plugins/opencode`, aligned the two failing dashboard Playwright tests with the current Session/Lifetime split, then ran the focused pytest commands above plus `npm ci && npm run build` in `plugins/opencode` - Observed result: the release workflow now versions and publishes `headroom-opencode`, release-please and version-sync track `plugins/opencode/package.json`, the dashboard tests now fetch durable cache and setup-url data from the Lifetime view, and the opencode package still builds locally from source - Not tested: GitHub Package Registry publish ## 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 - [x] 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 - [x] I have updated the CHANGELOG.md if applicable ## Additional Notes `CHANGELOG.md` is unchanged because release-please owns changelog generation here. --------- Co-authored-by: JD Davis <mxjerrett@gmail.com>
2026-08-12 00:56:40 -04:00
opencode = plugins / "opencode"
opencode.mkdir(parents=True)
agent_hooks_claude = plugins / "headroom-agent-hooks" / ".claude-plugin"
agent_hooks_claude.mkdir(parents=True)
agent_hooks_github = plugins / "headroom-agent-hooks" / ".github" / "plugin"
agent_hooks_github.mkdir(parents=True)
sdk = root / "sdk"
typescript = sdk / "typescript"
typescript.mkdir(parents=True)
# pyproject.toml
pyproject = root / "pyproject.toml"
pyproject.write_text('[project]\nversion = "0.5.25"\n')
# headroom/_version.py is runtime-derived and must not be rewritten by version-sync.
version_py = headroom / "_version.py"
version_py.write_text('"""Package version metadata."""\n\n__version__ = "0.5.25"\n')
# plugins/openclaw/package.json
openclaw_pkg = openclaw / "package.json"
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
openclaw_pkg.write_text(
json.dumps(
{
"name": "test",
"version": "0.5.25",
"dependencies": {"headroom-ai": "^0.22.3"},
}
)
)
fix: publish headroom-opencode in release workflow (#2372) ## Description `headroom-opencode` is documented as an npm package, but the release workflow never published it, so installs failed with a registry 404 even though the plugin source already lived under `plugins/opencode`. This wires the existing package into the npm release path, keeps its version synced with root releases, and adds release guards for the new package. Closes #76. ## 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) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - added `headroom-opencode` to the npm release workflow, including release-version stamping and `headroom-ai` dependency rewrite before publish - added `plugins/opencode/package.json` to release-please and local version-sync guards - synced the source opencode package version to the current release line and documented the new npm package in the release docs - added focused release workflow and version-sync tests for the opencode package - aligned the two failing dashboard Playwright tests with the current Session/Lifetime split and `/stats-lifetime` fixture contract ## Testing - [x] Unit tests pass (`uv run pytest scripts/tests/test_version_sync.py -q`, `uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency'`) - [x] Unit tests pass (`uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q`) - [x] Linting passes (`uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py`) - [ ] Type checking passes (`uv run mypy headroom`) - [x] New tests added for new functionality when applicable - [x] Manual testing performed ### Test Output ```text $ uv run pytest scripts/tests/test_version_sync.py -q 8 passed, 1 warning in 0.51s $ uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency' 2 passed, 38 deselected, 1 warning in 0.07s $ uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q 4 passed, 1 warning in 4.04s $ uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ npm ci && npm run build (plugins/opencode) Build success; dist/index.js, dist/entry.opencode.js, and DTS outputs emitted ``` ## Real Behavior Proof - Environment: Windows, Python 3.11.15, Node v24.15.0, npm 11.16.0 - Exact command / steps: inspected `.github/workflows/release.yml`, updated the npm publish path for `plugins/opencode`, aligned the two failing dashboard Playwright tests with the current Session/Lifetime split, then ran the focused pytest commands above plus `npm ci && npm run build` in `plugins/opencode` - Observed result: the release workflow now versions and publishes `headroom-opencode`, release-please and version-sync track `plugins/opencode/package.json`, the dashboard tests now fetch durable cache and setup-url data from the Lifetime view, and the opencode package still builds locally from source - Not tested: GitHub Package Registry publish ## 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 - [x] 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 - [x] I have updated the CHANGELOG.md if applicable ## Additional Notes `CHANGELOG.md` is unchanged because release-please owns changelog generation here. --------- Co-authored-by: JD Davis <mxjerrett@gmail.com>
2026-08-12 00:56:40 -04:00
opencode_pkg = opencode / "package.json"
opencode_pkg.write_text(
json.dumps(
{
"name": "test-opencode",
"version": "0.5.25",
"dependencies": {"headroom-ai": "^0.22.3"},
}
)
)
repo_claude_marketplace = repo_claude_plugin / "marketplace.json"
repo_claude_marketplace.write_text(
json.dumps(
{
"metadata": {"name": "claude-marketplace", "version": "0.1.0"},
"plugins": [{"name": "headroom-agent-hooks", "version": "0.1.0"}],
}
)
)
repo_github_marketplace = repo_github_plugin / "marketplace.json"
repo_github_marketplace.write_text(
json.dumps(
{
"metadata": {"name": "copilot-marketplace", "version": "0.1.0"},
"plugins": [{"name": "headroom-agent-hooks", "version": "0.1.0"}],
}
)
)
claude_plugin = agent_hooks_claude / "plugin.json"
claude_plugin.write_text(json.dumps({"name": "headroom-agent-hooks", "version": "0.1.0"}))
github_plugin = agent_hooks_github / "plugin.json"
github_plugin.write_text(json.dumps({"name": "headroom-agent-hooks", "version": "0.1.0"}))
# sdk/typescript/package.json
typescript_pkg = typescript / "package.json"
typescript_pkg.write_text(json.dumps({"name": "test", "version": "0.5.25"}))
fix(release): sync generated version metadata on the release branch (#2659) ## Description The 0.33.0 release PR (#2339) has sat in `changes-requested` since 2026-07-17. Root cause: **release-please only rewrites `pyproject.toml` and its configured `extra-files`**, but other tracked files also carry the version — and `server.json` is asserted byte-for-byte against `render_server_json()`, which derives its version from `pyproject.toml`. So the bump alone fails `tests/test_mcp_registry/test_server_json.py::test_root_server_json_matches_builder` (the `test (2)` shard) on every regenerated release PR. Nothing in the repo regenerated `server.json` at all, so it fell behind every release. Unblocks #2339. ### Why the release *build* passes but the release PR does not `release.yml` already runs `scripts/version-sync.py` immediately before its own `verify-versions.py` gate (lines 145 and 278). That is why `build` and `build-wheels` are green on #2339 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. This also explains why reviewers kept seeing `verify-versions.py` fail locally while CI's build jobs passed: the verifier is never run un-synced inside `release.yml`. ## 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`**: also write `server.json`. It was the one version-carrying file with no writer anywhere. Values are rewritten in place so key order and formatting keep matching the builder's byte-for-byte output (verified: the file is pure ASCII and round-trips exactly through `json.dumps(..., indent=2) + "\n"`). - **`.github/workflows/release-metadata-sync.yml`** (new): on a push to `release-please--branches--**`, run version-sync → gate on verify-versions → commit if changed. - **Keyed off the branch push** because release-please force-regenerates that branch on every merge to main. That is precisely what wiped the hand-pushed metadata fixes on #2339 (`2a86c8ff`, `d5ea4dc5`) — a push trigger re-heals after every regeneration instead of being lost. - **Uses the same PAT as `release-please.yml`**: a `GITHUB_TOKEN` push does not trigger workflows, so the release PR's checks would never re-run against the synced commit and would stay red. - **Idempotent**: the self-triggered rerun finds no diff and exits before pushing, so the loop terminates after one no-op run. - **Corrected pre-existing drift on `main`**: the agent-hooks plugin manifests, both marketplace manifests, and `.releasemetadata` were stranded at **0.31.0** — never bumped for 0.32.0 either. `verify-versions.py` now passes on `main`. ### Why not more `extra-files` entries That would need ~13 jsonpath entries restating what `version-sync.py` already knows, and a jsonpath that fails to match **fails silently** — the same class of failure this PR removes, discoverable only after a real release PR regenerates. There is also no precedent for nested jsonpath (`$.packages[0].version`, `$.metadata.version`) in the config today; both existing entries are plain `$.version`. Running the script keeps one source of truth, and files added to it later are covered with no change here. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) — no `headroom/` sources touched - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text $ python -m pytest scripts/tests/ tests/test_release_workflows.py tests/test_mcp_registry/ -q 207 passed in 2.69s $ ruff check scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ ruff format --check <same> 3 files already formatted $ actionlint .github/workflows/release-metadata-sync.yml (clean) ``` New tests: - `test_server_json_version_is_synchronized` — version-sync moves both `server.json` version fields and preserves the other keys. - `test_release_metadata_sync_runs_on_release_please_branch` — asserts the trigger, the sync→verify→commit ordering, the no-op guard, and the PAT. - `test_version_sync_covers_every_file_the_verifier_gates` — guards `version-sync.py` and `verify-versions.py` against drifting apart again, which is the root cause here. ## Real Behavior Proof - **Environment:** macOS (Darwin arm64), Python 3.12, repo venv. - **Exact command / steps:** reproduced the CI failure locally by simulating release-please's partial bump, then applying the fix. **Reproducing the exact `test (2)` failure** — set `pyproject` to 0.33.0 while `server.json` stays at 0.32.0, as release-please leaves it: ```text $ python -m pytest tests/test_mcp_registry/test_server_json.py -q FAILED tests/test_mcp_registry/test_server_json.py::test_root_server_json_matches_builder 1 failed, 3 passed ``` **After `version-sync.py`:** ```text $ python scripts/version-sync.py && python -m pytest tests/test_mcp_registry/test_server_json.py -q 4 passed ``` **Both gates green on a simulated 0.33.0 bump:** ```text $ python scripts/version-sync.py --version 0.33.0 Version synchronized to 0.33.0 $ python scripts/verify-versions.py All versions aligned at 0.33.0 $ python -m pytest tests/test_mcp_registry/test_server_json.py -q 4 passed ``` **Idempotency** (the property the workflow's loop-termination relies on): re-running against an already-synced tree leaves `pyproject.toml`, `server.json`, `openclaw`, and `sdk/typescript` untouched. - **Not tested:** the workflow has not executed on a real release-please branch regeneration — that can only be exercised once this is on `main` and release-please next updates #2339. The PAT push path and the self-trigger no-op are reasoned from `release-please.yml`'s existing token comment and from local idempotency, not observed in CI. ## 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 - [x] 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 - [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 - [x] I did **not** edit `CHANGELOG.md` ## Additional Notes **Context on the v0.32.0 release failure, since it is easy to misread as "images never build".** Every artifact built for v0.32.0 — all 5 wheel platforms including Windows, all 16 Docker builds + 8 manifests + `promote-latest`, npm, and GitHub Packages. Only `publish-pypi` failed (PyPI attestations, already fixed by `f9cbdd6e` / #2405), and `create-release` was skipped because it depends on it. That is why the release looked like it produced nothing. **Separate, approaching blocker — not addressed here.** PyPI is at **9.69 GB of its 10 GB project cap (96.9%)**, leaving ~305 MB against ~68 MB per release, so roughly 4 more releases fit. The `0.21.x` series alone holds **6.58 GB across 31 releases**, from the old every-push-is-a-release era; pruning it would reclaim two thirds of the quota. Worth a separate issue. **`.releasemetadata` is written but never read** by anything outside `version-sync.py` and its test. It is kept in sync here for internal consistency, but it may be a deletion candidate.
2026-07-29 15:12:04 -07:00
# server.json — the MCP registry descriptor. Asserted byte-for-byte against
# render_server_json(), which reads the version from pyproject.toml, so it has
# to move with every bump or the release PR's test job fails.
server_json = root / "server.json"
server_json.write_text(
json.dumps(
{
"name": "io.github.headroomlabs-ai/headroom",
"version": "0.5.25",
"packages": [{"registryType": "pypi", "version": "0.5.25"}],
}
)
)
return {
"root": root,
"pyproject": pyproject,
"version_py": version_py,
"openclaw_pkg": openclaw_pkg,
fix: publish headroom-opencode in release workflow (#2372) ## Description `headroom-opencode` is documented as an npm package, but the release workflow never published it, so installs failed with a registry 404 even though the plugin source already lived under `plugins/opencode`. This wires the existing package into the npm release path, keeps its version synced with root releases, and adds release guards for the new package. Closes #76. ## 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) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - added `headroom-opencode` to the npm release workflow, including release-version stamping and `headroom-ai` dependency rewrite before publish - added `plugins/opencode/package.json` to release-please and local version-sync guards - synced the source opencode package version to the current release line and documented the new npm package in the release docs - added focused release workflow and version-sync tests for the opencode package - aligned the two failing dashboard Playwright tests with the current Session/Lifetime split and `/stats-lifetime` fixture contract ## Testing - [x] Unit tests pass (`uv run pytest scripts/tests/test_version_sync.py -q`, `uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency'`) - [x] Unit tests pass (`uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q`) - [x] Linting passes (`uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py`) - [ ] Type checking passes (`uv run mypy headroom`) - [x] New tests added for new functionality when applicable - [x] Manual testing performed ### Test Output ```text $ uv run pytest scripts/tests/test_version_sync.py -q 8 passed, 1 warning in 0.51s $ uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency' 2 passed, 38 deselected, 1 warning in 0.07s $ uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q 4 passed, 1 warning in 4.04s $ uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ npm ci && npm run build (plugins/opencode) Build success; dist/index.js, dist/entry.opencode.js, and DTS outputs emitted ``` ## Real Behavior Proof - Environment: Windows, Python 3.11.15, Node v24.15.0, npm 11.16.0 - Exact command / steps: inspected `.github/workflows/release.yml`, updated the npm publish path for `plugins/opencode`, aligned the two failing dashboard Playwright tests with the current Session/Lifetime split, then ran the focused pytest commands above plus `npm ci && npm run build` in `plugins/opencode` - Observed result: the release workflow now versions and publishes `headroom-opencode`, release-please and version-sync track `plugins/opencode/package.json`, the dashboard tests now fetch durable cache and setup-url data from the Lifetime view, and the opencode package still builds locally from source - Not tested: GitHub Package Registry publish ## 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 - [x] 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 - [x] I have updated the CHANGELOG.md if applicable ## Additional Notes `CHANGELOG.md` is unchanged because release-please owns changelog generation here. --------- Co-authored-by: JD Davis <mxjerrett@gmail.com>
2026-08-12 00:56:40 -04:00
"opencode_pkg": opencode_pkg,
"repo_claude_marketplace": repo_claude_marketplace,
"repo_github_marketplace": repo_github_marketplace,
"claude_plugin": claude_plugin,
"github_plugin": github_plugin,
"typescript_pkg": typescript_pkg,
fix(release): sync generated version metadata on the release branch (#2659) ## Description The 0.33.0 release PR (#2339) has sat in `changes-requested` since 2026-07-17. Root cause: **release-please only rewrites `pyproject.toml` and its configured `extra-files`**, but other tracked files also carry the version — and `server.json` is asserted byte-for-byte against `render_server_json()`, which derives its version from `pyproject.toml`. So the bump alone fails `tests/test_mcp_registry/test_server_json.py::test_root_server_json_matches_builder` (the `test (2)` shard) on every regenerated release PR. Nothing in the repo regenerated `server.json` at all, so it fell behind every release. Unblocks #2339. ### Why the release *build* passes but the release PR does not `release.yml` already runs `scripts/version-sync.py` immediately before its own `verify-versions.py` gate (lines 145 and 278). That is why `build` and `build-wheels` are green on #2339 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. This also explains why reviewers kept seeing `verify-versions.py` fail locally while CI's build jobs passed: the verifier is never run un-synced inside `release.yml`. ## 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`**: also write `server.json`. It was the one version-carrying file with no writer anywhere. Values are rewritten in place so key order and formatting keep matching the builder's byte-for-byte output (verified: the file is pure ASCII and round-trips exactly through `json.dumps(..., indent=2) + "\n"`). - **`.github/workflows/release-metadata-sync.yml`** (new): on a push to `release-please--branches--**`, run version-sync → gate on verify-versions → commit if changed. - **Keyed off the branch push** because release-please force-regenerates that branch on every merge to main. That is precisely what wiped the hand-pushed metadata fixes on #2339 (`2a86c8ff`, `d5ea4dc5`) — a push trigger re-heals after every regeneration instead of being lost. - **Uses the same PAT as `release-please.yml`**: a `GITHUB_TOKEN` push does not trigger workflows, so the release PR's checks would never re-run against the synced commit and would stay red. - **Idempotent**: the self-triggered rerun finds no diff and exits before pushing, so the loop terminates after one no-op run. - **Corrected pre-existing drift on `main`**: the agent-hooks plugin manifests, both marketplace manifests, and `.releasemetadata` were stranded at **0.31.0** — never bumped for 0.32.0 either. `verify-versions.py` now passes on `main`. ### Why not more `extra-files` entries That would need ~13 jsonpath entries restating what `version-sync.py` already knows, and a jsonpath that fails to match **fails silently** — the same class of failure this PR removes, discoverable only after a real release PR regenerates. There is also no precedent for nested jsonpath (`$.packages[0].version`, `$.metadata.version`) in the config today; both existing entries are plain `$.version`. Running the script keeps one source of truth, and files added to it later are covered with no change here. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) — no `headroom/` sources touched - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text $ python -m pytest scripts/tests/ tests/test_release_workflows.py tests/test_mcp_registry/ -q 207 passed in 2.69s $ ruff check scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ ruff format --check <same> 3 files already formatted $ actionlint .github/workflows/release-metadata-sync.yml (clean) ``` New tests: - `test_server_json_version_is_synchronized` — version-sync moves both `server.json` version fields and preserves the other keys. - `test_release_metadata_sync_runs_on_release_please_branch` — asserts the trigger, the sync→verify→commit ordering, the no-op guard, and the PAT. - `test_version_sync_covers_every_file_the_verifier_gates` — guards `version-sync.py` and `verify-versions.py` against drifting apart again, which is the root cause here. ## Real Behavior Proof - **Environment:** macOS (Darwin arm64), Python 3.12, repo venv. - **Exact command / steps:** reproduced the CI failure locally by simulating release-please's partial bump, then applying the fix. **Reproducing the exact `test (2)` failure** — set `pyproject` to 0.33.0 while `server.json` stays at 0.32.0, as release-please leaves it: ```text $ python -m pytest tests/test_mcp_registry/test_server_json.py -q FAILED tests/test_mcp_registry/test_server_json.py::test_root_server_json_matches_builder 1 failed, 3 passed ``` **After `version-sync.py`:** ```text $ python scripts/version-sync.py && python -m pytest tests/test_mcp_registry/test_server_json.py -q 4 passed ``` **Both gates green on a simulated 0.33.0 bump:** ```text $ python scripts/version-sync.py --version 0.33.0 Version synchronized to 0.33.0 $ python scripts/verify-versions.py All versions aligned at 0.33.0 $ python -m pytest tests/test_mcp_registry/test_server_json.py -q 4 passed ``` **Idempotency** (the property the workflow's loop-termination relies on): re-running against an already-synced tree leaves `pyproject.toml`, `server.json`, `openclaw`, and `sdk/typescript` untouched. - **Not tested:** the workflow has not executed on a real release-please branch regeneration — that can only be exercised once this is on `main` and release-please next updates #2339. The PAT push path and the self-trigger no-op are reasoned from `release-please.yml`'s existing token comment and from local idempotency, not observed in CI. ## 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 - [x] 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 - [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 - [x] I did **not** edit `CHANGELOG.md` ## Additional Notes **Context on the v0.32.0 release failure, since it is easy to misread as "images never build".** Every artifact built for v0.32.0 — all 5 wheel platforms including Windows, all 16 Docker builds + 8 manifests + `promote-latest`, npm, and GitHub Packages. Only `publish-pypi` failed (PyPI attestations, already fixed by `f9cbdd6e` / #2405), and `create-release` was skipped because it depends on it. That is why the release looked like it produced nothing. **Separate, approaching blocker — not addressed here.** PyPI is at **9.69 GB of its 10 GB project cap (96.9%)**, leaving ~305 MB against ~68 MB per release, so roughly 4 more releases fit. The `0.21.x` series alone holds **6.58 GB across 31 releases**, from the old every-push-is-a-release era; pruning it would reclaim two thirds of the quota. Worth a separate issue. **`.releasemetadata` is written but never read** by anything outside `version-sync.py` and its test. It is kept in sync here for internal consistency, but it may be a deletion candidate.
2026-07-29 15:12:04 -07:00
"server_json": server_json,
}
def test_version_sync_explicit_version(temp_project: dict[str, Path]) -> None:
"""Test --version flag updates all files."""
root = temp_project["root"]
script = Path(__file__).parent.parent / "version-sync.py"
result = subprocess.run(
[sys.executable, str(script), "--root", str(root), "--version", "0.7.0"],
capture_output=True,
text=True,
)
assert result.returncode == 0, f"Script failed: {result.stderr}"
# Verify pyproject.toml
pyproject_content = temp_project["pyproject"].read_text()
assert 'version = "0.7.0"' in pyproject_content
# Verify headroom/_version.py is not a synced manifest.
version_py_content = temp_project["version_py"].read_text()
assert '__version__ = "0.5.25"' in version_py_content
# Verify plugins/openclaw/package.json
openclaw_pkg = json.loads(temp_project["openclaw_pkg"].read_text())
assert openclaw_pkg["version"] == "0.7.0"
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
assert openclaw_pkg["dependencies"]["headroom-ai"] == "^0.22.3"
fix: publish headroom-opencode in release workflow (#2372) ## Description `headroom-opencode` is documented as an npm package, but the release workflow never published it, so installs failed with a registry 404 even though the plugin source already lived under `plugins/opencode`. This wires the existing package into the npm release path, keeps its version synced with root releases, and adds release guards for the new package. Closes #76. ## 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) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - added `headroom-opencode` to the npm release workflow, including release-version stamping and `headroom-ai` dependency rewrite before publish - added `plugins/opencode/package.json` to release-please and local version-sync guards - synced the source opencode package version to the current release line and documented the new npm package in the release docs - added focused release workflow and version-sync tests for the opencode package - aligned the two failing dashboard Playwright tests with the current Session/Lifetime split and `/stats-lifetime` fixture contract ## Testing - [x] Unit tests pass (`uv run pytest scripts/tests/test_version_sync.py -q`, `uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency'`) - [x] Unit tests pass (`uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q`) - [x] Linting passes (`uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py`) - [ ] Type checking passes (`uv run mypy headroom`) - [x] New tests added for new functionality when applicable - [x] Manual testing performed ### Test Output ```text $ uv run pytest scripts/tests/test_version_sync.py -q 8 passed, 1 warning in 0.51s $ uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency' 2 passed, 38 deselected, 1 warning in 0.07s $ uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q 4 passed, 1 warning in 4.04s $ uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ npm ci && npm run build (plugins/opencode) Build success; dist/index.js, dist/entry.opencode.js, and DTS outputs emitted ``` ## Real Behavior Proof - Environment: Windows, Python 3.11.15, Node v24.15.0, npm 11.16.0 - Exact command / steps: inspected `.github/workflows/release.yml`, updated the npm publish path for `plugins/opencode`, aligned the two failing dashboard Playwright tests with the current Session/Lifetime split, then ran the focused pytest commands above plus `npm ci && npm run build` in `plugins/opencode` - Observed result: the release workflow now versions and publishes `headroom-opencode`, release-please and version-sync track `plugins/opencode/package.json`, the dashboard tests now fetch durable cache and setup-url data from the Lifetime view, and the opencode package still builds locally from source - Not tested: GitHub Package Registry publish ## 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 - [x] 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 - [x] I have updated the CHANGELOG.md if applicable ## Additional Notes `CHANGELOG.md` is unchanged because release-please owns changelog generation here. --------- Co-authored-by: JD Davis <mxjerrett@gmail.com>
2026-08-12 00:56:40 -04:00
opencode_pkg = json.loads(temp_project["opencode_pkg"].read_text())
assert opencode_pkg["version"] == "0.7.0"
assert opencode_pkg["dependencies"]["headroom-ai"] == "^0.22.3"
# Verify sdk/typescript/package.json
typescript_pkg = json.loads(temp_project["typescript_pkg"].read_text())
assert typescript_pkg["version"] == "0.7.0"
repo_claude_marketplace = json.loads(temp_project["repo_claude_marketplace"].read_text())
assert repo_claude_marketplace["metadata"]["version"] == "0.7.0"
assert repo_claude_marketplace["plugins"][0]["version"] == "0.7.0"
repo_github_marketplace = json.loads(temp_project["repo_github_marketplace"].read_text())
assert repo_github_marketplace["metadata"]["version"] == "0.7.0"
assert repo_github_marketplace["plugins"][0]["version"] == "0.7.0"
claude_plugin = json.loads(temp_project["claude_plugin"].read_text())
assert claude_plugin["version"] == "0.7.0"
github_plugin = json.loads(temp_project["github_plugin"].read_text())
assert github_plugin["version"] == "0.7.0"
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
# Verify .releasemetadata was created
release_metadata = root / ".releasemetadata"
assert release_metadata.exists()
metadata = json.loads(release_metadata.read_text())
assert metadata["version"] == "0.7.0"
assert metadata["packages"]["pypi"] == "0.7.0"
assert metadata["packages"]["npm-sdk"] == "0.7.0"
assert metadata["packages"]["npm-openclaw"] == "0.7.0"
fix: publish headroom-opencode in release workflow (#2372) ## Description `headroom-opencode` is documented as an npm package, but the release workflow never published it, so installs failed with a registry 404 even though the plugin source already lived under `plugins/opencode`. This wires the existing package into the npm release path, keeps its version synced with root releases, and adds release guards for the new package. Closes #76. ## 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) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - added `headroom-opencode` to the npm release workflow, including release-version stamping and `headroom-ai` dependency rewrite before publish - added `plugins/opencode/package.json` to release-please and local version-sync guards - synced the source opencode package version to the current release line and documented the new npm package in the release docs - added focused release workflow and version-sync tests for the opencode package - aligned the two failing dashboard Playwright tests with the current Session/Lifetime split and `/stats-lifetime` fixture contract ## Testing - [x] Unit tests pass (`uv run pytest scripts/tests/test_version_sync.py -q`, `uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency'`) - [x] Unit tests pass (`uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q`) - [x] Linting passes (`uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py`) - [ ] Type checking passes (`uv run mypy headroom`) - [x] New tests added for new functionality when applicable - [x] Manual testing performed ### Test Output ```text $ uv run pytest scripts/tests/test_version_sync.py -q 8 passed, 1 warning in 0.51s $ uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency' 2 passed, 38 deselected, 1 warning in 0.07s $ uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q 4 passed, 1 warning in 4.04s $ uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ npm ci && npm run build (plugins/opencode) Build success; dist/index.js, dist/entry.opencode.js, and DTS outputs emitted ``` ## Real Behavior Proof - Environment: Windows, Python 3.11.15, Node v24.15.0, npm 11.16.0 - Exact command / steps: inspected `.github/workflows/release.yml`, updated the npm publish path for `plugins/opencode`, aligned the two failing dashboard Playwright tests with the current Session/Lifetime split, then ran the focused pytest commands above plus `npm ci && npm run build` in `plugins/opencode` - Observed result: the release workflow now versions and publishes `headroom-opencode`, release-please and version-sync track `plugins/opencode/package.json`, the dashboard tests now fetch durable cache and setup-url data from the Lifetime view, and the opencode package still builds locally from source - Not tested: GitHub Package Registry publish ## 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 - [x] 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 - [x] I have updated the CHANGELOG.md if applicable ## Additional Notes `CHANGELOG.md` is unchanged because release-please owns changelog generation here. --------- Co-authored-by: JD Davis <mxjerrett@gmail.com>
2026-08-12 00:56:40 -04:00
assert metadata["packages"]["npm-opencode"] == "0.7.0"
assert metadata["packages"]["agent-hooks-plugin"] == "0.7.0"
def test_bump_patch(temp_project: dict[str, Path]) -> None:
"""Test --bump patch bumps 0.5.25 to 0.5.26."""
root = temp_project["root"]
script = Path(__file__).parent.parent / "version-sync.py"
result = subprocess.run(
[sys.executable, str(script), "--root", str(root), "--bump", "patch"],
capture_output=True,
text=True,
)
assert result.returncode == 0, f"Script failed: {result.stderr}"
# Verify all files updated to 0.5.26
pyproject_content = temp_project["pyproject"].read_text()
assert 'version = "0.5.26"' in pyproject_content
version_py_content = temp_project["version_py"].read_text()
assert '__version__ = "0.5.25"' in version_py_content
openclaw_pkg = json.loads(temp_project["openclaw_pkg"].read_text())
assert openclaw_pkg["version"] == "0.5.26"
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
assert openclaw_pkg["dependencies"]["headroom-ai"] == "^0.22.3"
fix: publish headroom-opencode in release workflow (#2372) ## Description `headroom-opencode` is documented as an npm package, but the release workflow never published it, so installs failed with a registry 404 even though the plugin source already lived under `plugins/opencode`. This wires the existing package into the npm release path, keeps its version synced with root releases, and adds release guards for the new package. Closes #76. ## 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) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - added `headroom-opencode` to the npm release workflow, including release-version stamping and `headroom-ai` dependency rewrite before publish - added `plugins/opencode/package.json` to release-please and local version-sync guards - synced the source opencode package version to the current release line and documented the new npm package in the release docs - added focused release workflow and version-sync tests for the opencode package - aligned the two failing dashboard Playwright tests with the current Session/Lifetime split and `/stats-lifetime` fixture contract ## Testing - [x] Unit tests pass (`uv run pytest scripts/tests/test_version_sync.py -q`, `uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency'`) - [x] Unit tests pass (`uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q`) - [x] Linting passes (`uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py`) - [ ] Type checking passes (`uv run mypy headroom`) - [x] New tests added for new functionality when applicable - [x] Manual testing performed ### Test Output ```text $ uv run pytest scripts/tests/test_version_sync.py -q 8 passed, 1 warning in 0.51s $ uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency' 2 passed, 38 deselected, 1 warning in 0.07s $ uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q 4 passed, 1 warning in 4.04s $ uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ npm ci && npm run build (plugins/opencode) Build success; dist/index.js, dist/entry.opencode.js, and DTS outputs emitted ``` ## Real Behavior Proof - Environment: Windows, Python 3.11.15, Node v24.15.0, npm 11.16.0 - Exact command / steps: inspected `.github/workflows/release.yml`, updated the npm publish path for `plugins/opencode`, aligned the two failing dashboard Playwright tests with the current Session/Lifetime split, then ran the focused pytest commands above plus `npm ci && npm run build` in `plugins/opencode` - Observed result: the release workflow now versions and publishes `headroom-opencode`, release-please and version-sync track `plugins/opencode/package.json`, the dashboard tests now fetch durable cache and setup-url data from the Lifetime view, and the opencode package still builds locally from source - Not tested: GitHub Package Registry publish ## 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 - [x] 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 - [x] I have updated the CHANGELOG.md if applicable ## Additional Notes `CHANGELOG.md` is unchanged because release-please owns changelog generation here. --------- Co-authored-by: JD Davis <mxjerrett@gmail.com>
2026-08-12 00:56:40 -04:00
opencode_pkg = json.loads(temp_project["opencode_pkg"].read_text())
assert opencode_pkg["version"] == "0.5.26"
assert opencode_pkg["dependencies"]["headroom-ai"] == "^0.22.3"
typescript_pkg = json.loads(temp_project["typescript_pkg"].read_text())
assert typescript_pkg["version"] == "0.5.26"
claude_plugin = json.loads(temp_project["claude_plugin"].read_text())
assert claude_plugin["version"] == "0.5.26"
def test_bump_minor(temp_project: dict[str, Path]) -> None:
"""Test --bump minor bumps 0.5.25 to 0.6.0."""
root = temp_project["root"]
script = Path(__file__).parent.parent / "version-sync.py"
result = subprocess.run(
[sys.executable, str(script), "--root", str(root), "--bump", "minor"],
capture_output=True,
text=True,
)
assert result.returncode == 0, f"Script failed: {result.stderr}"
# Verify all files updated to 0.6.0
pyproject_content = temp_project["pyproject"].read_text()
assert 'version = "0.6.0"' in pyproject_content
version_py_content = temp_project["version_py"].read_text()
assert '__version__ = "0.5.25"' in version_py_content
openclaw_pkg = json.loads(temp_project["openclaw_pkg"].read_text())
assert openclaw_pkg["version"] == "0.6.0"
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
assert openclaw_pkg["dependencies"]["headroom-ai"] == "^0.22.3"
fix: publish headroom-opencode in release workflow (#2372) ## Description `headroom-opencode` is documented as an npm package, but the release workflow never published it, so installs failed with a registry 404 even though the plugin source already lived under `plugins/opencode`. This wires the existing package into the npm release path, keeps its version synced with root releases, and adds release guards for the new package. Closes #76. ## 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) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - added `headroom-opencode` to the npm release workflow, including release-version stamping and `headroom-ai` dependency rewrite before publish - added `plugins/opencode/package.json` to release-please and local version-sync guards - synced the source opencode package version to the current release line and documented the new npm package in the release docs - added focused release workflow and version-sync tests for the opencode package - aligned the two failing dashboard Playwright tests with the current Session/Lifetime split and `/stats-lifetime` fixture contract ## Testing - [x] Unit tests pass (`uv run pytest scripts/tests/test_version_sync.py -q`, `uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency'`) - [x] Unit tests pass (`uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q`) - [x] Linting passes (`uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py`) - [ ] Type checking passes (`uv run mypy headroom`) - [x] New tests added for new functionality when applicable - [x] Manual testing performed ### Test Output ```text $ uv run pytest scripts/tests/test_version_sync.py -q 8 passed, 1 warning in 0.51s $ uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency' 2 passed, 38 deselected, 1 warning in 0.07s $ uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q 4 passed, 1 warning in 4.04s $ uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ npm ci && npm run build (plugins/opencode) Build success; dist/index.js, dist/entry.opencode.js, and DTS outputs emitted ``` ## Real Behavior Proof - Environment: Windows, Python 3.11.15, Node v24.15.0, npm 11.16.0 - Exact command / steps: inspected `.github/workflows/release.yml`, updated the npm publish path for `plugins/opencode`, aligned the two failing dashboard Playwright tests with the current Session/Lifetime split, then ran the focused pytest commands above plus `npm ci && npm run build` in `plugins/opencode` - Observed result: the release workflow now versions and publishes `headroom-opencode`, release-please and version-sync track `plugins/opencode/package.json`, the dashboard tests now fetch durable cache and setup-url data from the Lifetime view, and the opencode package still builds locally from source - Not tested: GitHub Package Registry publish ## 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 - [x] 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 - [x] I have updated the CHANGELOG.md if applicable ## Additional Notes `CHANGELOG.md` is unchanged because release-please owns changelog generation here. --------- Co-authored-by: JD Davis <mxjerrett@gmail.com>
2026-08-12 00:56:40 -04:00
opencode_pkg = json.loads(temp_project["opencode_pkg"].read_text())
assert opencode_pkg["version"] == "0.6.0"
assert opencode_pkg["dependencies"]["headroom-ai"] == "^0.22.3"
typescript_pkg = json.loads(temp_project["typescript_pkg"].read_text())
assert typescript_pkg["version"] == "0.6.0"
github_plugin = json.loads(temp_project["github_plugin"].read_text())
assert github_plugin["version"] == "0.6.0"
def test_bump_major(temp_project: dict[str, Path]) -> None:
"""Test --bump major bumps 0.5.25 to 1.0.0."""
root = temp_project["root"]
script = Path(__file__).parent.parent / "version-sync.py"
result = subprocess.run(
[sys.executable, str(script), "--root", str(root), "--bump", "major"],
capture_output=True,
text=True,
)
assert result.returncode == 0, f"Script failed: {result.stderr}"
# Verify all files updated to 1.0.0
pyproject_content = temp_project["pyproject"].read_text()
assert 'version = "1.0.0"' in pyproject_content
version_py_content = temp_project["version_py"].read_text()
assert '__version__ = "0.5.25"' in version_py_content
openclaw_pkg = json.loads(temp_project["openclaw_pkg"].read_text())
assert openclaw_pkg["version"] == "1.0.0"
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
assert openclaw_pkg["dependencies"]["headroom-ai"] == "^0.22.3"
fix: publish headroom-opencode in release workflow (#2372) ## Description `headroom-opencode` is documented as an npm package, but the release workflow never published it, so installs failed with a registry 404 even though the plugin source already lived under `plugins/opencode`. This wires the existing package into the npm release path, keeps its version synced with root releases, and adds release guards for the new package. Closes #76. ## 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) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - added `headroom-opencode` to the npm release workflow, including release-version stamping and `headroom-ai` dependency rewrite before publish - added `plugins/opencode/package.json` to release-please and local version-sync guards - synced the source opencode package version to the current release line and documented the new npm package in the release docs - added focused release workflow and version-sync tests for the opencode package - aligned the two failing dashboard Playwright tests with the current Session/Lifetime split and `/stats-lifetime` fixture contract ## Testing - [x] Unit tests pass (`uv run pytest scripts/tests/test_version_sync.py -q`, `uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency'`) - [x] Unit tests pass (`uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q`) - [x] Linting passes (`uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py`) - [ ] Type checking passes (`uv run mypy headroom`) - [x] New tests added for new functionality when applicable - [x] Manual testing performed ### Test Output ```text $ uv run pytest scripts/tests/test_version_sync.py -q 8 passed, 1 warning in 0.51s $ uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency' 2 passed, 38 deselected, 1 warning in 0.07s $ uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q 4 passed, 1 warning in 4.04s $ uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ npm ci && npm run build (plugins/opencode) Build success; dist/index.js, dist/entry.opencode.js, and DTS outputs emitted ``` ## Real Behavior Proof - Environment: Windows, Python 3.11.15, Node v24.15.0, npm 11.16.0 - Exact command / steps: inspected `.github/workflows/release.yml`, updated the npm publish path for `plugins/opencode`, aligned the two failing dashboard Playwright tests with the current Session/Lifetime split, then ran the focused pytest commands above plus `npm ci && npm run build` in `plugins/opencode` - Observed result: the release workflow now versions and publishes `headroom-opencode`, release-please and version-sync track `plugins/opencode/package.json`, the dashboard tests now fetch durable cache and setup-url data from the Lifetime view, and the opencode package still builds locally from source - Not tested: GitHub Package Registry publish ## 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 - [x] 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 - [x] I have updated the CHANGELOG.md if applicable ## Additional Notes `CHANGELOG.md` is unchanged because release-please owns changelog generation here. --------- Co-authored-by: JD Davis <mxjerrett@gmail.com>
2026-08-12 00:56:40 -04:00
opencode_pkg = json.loads(temp_project["opencode_pkg"].read_text())
assert opencode_pkg["version"] == "1.0.0"
assert opencode_pkg["dependencies"]["headroom-ai"] == "^0.22.3"
typescript_pkg = json.loads(temp_project["typescript_pkg"].read_text())
assert typescript_pkg["version"] == "1.0.0"
repo_claude_marketplace = json.loads(temp_project["repo_claude_marketplace"].read_text())
assert repo_claude_marketplace["metadata"]["version"] == "1.0.0"
def test_release_metadata_written(temp_project: dict[str, Path]) -> 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
"""Test .releasemetadata is written correctly."""
root = temp_project["root"]
script = Path(__file__).parent.parent / "version-sync.py"
result = subprocess.run(
[sys.executable, str(script), "--root", str(root), "--version", "0.6.0"],
capture_output=True,
text=True,
)
assert result.returncode == 0, f"Script failed: {result.stderr}"
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
release_metadata = root / ".releasemetadata"
assert release_metadata.exists()
metadata = json.loads(release_metadata.read_text())
assert metadata == {
"version": "0.6.0",
"packages": {
"pypi": "0.6.0",
"npm-sdk": "0.6.0",
"npm-openclaw": "0.6.0",
fix: publish headroom-opencode in release workflow (#2372) ## Description `headroom-opencode` is documented as an npm package, but the release workflow never published it, so installs failed with a registry 404 even though the plugin source already lived under `plugins/opencode`. This wires the existing package into the npm release path, keeps its version synced with root releases, and adds release guards for the new package. Closes #76. ## 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) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - added `headroom-opencode` to the npm release workflow, including release-version stamping and `headroom-ai` dependency rewrite before publish - added `plugins/opencode/package.json` to release-please and local version-sync guards - synced the source opencode package version to the current release line and documented the new npm package in the release docs - added focused release workflow and version-sync tests for the opencode package - aligned the two failing dashboard Playwright tests with the current Session/Lifetime split and `/stats-lifetime` fixture contract ## Testing - [x] Unit tests pass (`uv run pytest scripts/tests/test_version_sync.py -q`, `uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency'`) - [x] Unit tests pass (`uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q`) - [x] Linting passes (`uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py`) - [ ] Type checking passes (`uv run mypy headroom`) - [x] New tests added for new functionality when applicable - [x] Manual testing performed ### Test Output ```text $ uv run pytest scripts/tests/test_version_sync.py -q 8 passed, 1 warning in 0.51s $ uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency' 2 passed, 38 deselected, 1 warning in 0.07s $ uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q 4 passed, 1 warning in 4.04s $ uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ npm ci && npm run build (plugins/opencode) Build success; dist/index.js, dist/entry.opencode.js, and DTS outputs emitted ``` ## Real Behavior Proof - Environment: Windows, Python 3.11.15, Node v24.15.0, npm 11.16.0 - Exact command / steps: inspected `.github/workflows/release.yml`, updated the npm publish path for `plugins/opencode`, aligned the two failing dashboard Playwright tests with the current Session/Lifetime split, then ran the focused pytest commands above plus `npm ci && npm run build` in `plugins/opencode` - Observed result: the release workflow now versions and publishes `headroom-opencode`, release-please and version-sync track `plugins/opencode/package.json`, the dashboard tests now fetch durable cache and setup-url data from the Lifetime view, and the opencode package still builds locally from source - Not tested: GitHub Package Registry publish ## 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 - [x] 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 - [x] I have updated the CHANGELOG.md if applicable ## Additional Notes `CHANGELOG.md` is unchanged because release-please owns changelog generation here. --------- Co-authored-by: JD Davis <mxjerrett@gmail.com>
2026-08-12 00:56:40 -04:00
"npm-opencode": "0.6.0",
"agent-hooks-plugin": "0.6.0",
},
}
def test_plugin_manifests_only_leaves_package_versions_unchanged(
temp_project: dict[str, Path],
) -> None:
"""Test plugin-only sync leaves canonical package versions alone."""
root = temp_project["root"]
script = Path(__file__).parent.parent / "version-sync.py"
result = subprocess.run(
[
sys.executable,
str(script),
"--root",
str(root),
"--version",
"0.8.0",
"--plugin-manifests-only",
],
capture_output=True,
text=True,
)
assert result.returncode == 0, f"Script failed: {result.stderr}"
assert 'version = "0.5.25"' in temp_project["pyproject"].read_text()
assert '__version__ = "0.5.25"' in temp_project["version_py"].read_text()
assert json.loads(temp_project["openclaw_pkg"].read_text())["version"] == "0.5.25"
fix: publish headroom-opencode in release workflow (#2372) ## Description `headroom-opencode` is documented as an npm package, but the release workflow never published it, so installs failed with a registry 404 even though the plugin source already lived under `plugins/opencode`. This wires the existing package into the npm release path, keeps its version synced with root releases, and adds release guards for the new package. Closes #76. ## 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) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - added `headroom-opencode` to the npm release workflow, including release-version stamping and `headroom-ai` dependency rewrite before publish - added `plugins/opencode/package.json` to release-please and local version-sync guards - synced the source opencode package version to the current release line and documented the new npm package in the release docs - added focused release workflow and version-sync tests for the opencode package - aligned the two failing dashboard Playwright tests with the current Session/Lifetime split and `/stats-lifetime` fixture contract ## Testing - [x] Unit tests pass (`uv run pytest scripts/tests/test_version_sync.py -q`, `uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency'`) - [x] Unit tests pass (`uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q`) - [x] Linting passes (`uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py`) - [ ] Type checking passes (`uv run mypy headroom`) - [x] New tests added for new functionality when applicable - [x] Manual testing performed ### Test Output ```text $ uv run pytest scripts/tests/test_version_sync.py -q 8 passed, 1 warning in 0.51s $ uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency' 2 passed, 38 deselected, 1 warning in 0.07s $ uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q 4 passed, 1 warning in 4.04s $ uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ npm ci && npm run build (plugins/opencode) Build success; dist/index.js, dist/entry.opencode.js, and DTS outputs emitted ``` ## Real Behavior Proof - Environment: Windows, Python 3.11.15, Node v24.15.0, npm 11.16.0 - Exact command / steps: inspected `.github/workflows/release.yml`, updated the npm publish path for `plugins/opencode`, aligned the two failing dashboard Playwright tests with the current Session/Lifetime split, then ran the focused pytest commands above plus `npm ci && npm run build` in `plugins/opencode` - Observed result: the release workflow now versions and publishes `headroom-opencode`, release-please and version-sync track `plugins/opencode/package.json`, the dashboard tests now fetch durable cache and setup-url data from the Lifetime view, and the opencode package still builds locally from source - Not tested: GitHub Package Registry publish ## 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 - [x] 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 - [x] I have updated the CHANGELOG.md if applicable ## Additional Notes `CHANGELOG.md` is unchanged because release-please owns changelog generation here. --------- Co-authored-by: JD Davis <mxjerrett@gmail.com>
2026-08-12 00:56:40 -04:00
assert json.loads(temp_project["opencode_pkg"].read_text())["version"] == "0.5.25"
assert json.loads(temp_project["typescript_pkg"].read_text())["version"] == "0.5.25"
assert json.loads(temp_project["claude_plugin"].read_text())["version"] == "0.8.0"
assert (
json.loads(temp_project["repo_github_marketplace"].read_text())["metadata"]["version"]
== "0.8.0"
)
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
assert not (root / ".releasemetadata").exists()
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 test_openclaw_headroom_dependency_is_preserved_for_registry_installability(
temp_project: dict[str, Path],
) -> None:
"""Source package stays installable even when the next SDK is not on npm yet."""
root = temp_project["root"]
script = Path(__file__).parent.parent / "version-sync.py"
result = subprocess.run(
[sys.executable, str(script), "--root", str(root), "--version", "0.28.0"],
capture_output=True,
text=True,
)
assert result.returncode == 0, f"Script failed: {result.stderr}"
openclaw_pkg = json.loads(temp_project["openclaw_pkg"].read_text())
assert openclaw_pkg["version"] == "0.28.0"
assert openclaw_pkg["dependencies"]["headroom-ai"] == "^0.22.3"
fix(release): sync generated version metadata on the release branch (#2659) ## Description The 0.33.0 release PR (#2339) has sat in `changes-requested` since 2026-07-17. Root cause: **release-please only rewrites `pyproject.toml` and its configured `extra-files`**, but other tracked files also carry the version — and `server.json` is asserted byte-for-byte against `render_server_json()`, which derives its version from `pyproject.toml`. So the bump alone fails `tests/test_mcp_registry/test_server_json.py::test_root_server_json_matches_builder` (the `test (2)` shard) on every regenerated release PR. Nothing in the repo regenerated `server.json` at all, so it fell behind every release. Unblocks #2339. ### Why the release *build* passes but the release PR does not `release.yml` already runs `scripts/version-sync.py` immediately before its own `verify-versions.py` gate (lines 145 and 278). That is why `build` and `build-wheels` are green on #2339 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. This also explains why reviewers kept seeing `verify-versions.py` fail locally while CI's build jobs passed: the verifier is never run un-synced inside `release.yml`. ## 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`**: also write `server.json`. It was the one version-carrying file with no writer anywhere. Values are rewritten in place so key order and formatting keep matching the builder's byte-for-byte output (verified: the file is pure ASCII and round-trips exactly through `json.dumps(..., indent=2) + "\n"`). - **`.github/workflows/release-metadata-sync.yml`** (new): on a push to `release-please--branches--**`, run version-sync → gate on verify-versions → commit if changed. - **Keyed off the branch push** because release-please force-regenerates that branch on every merge to main. That is precisely what wiped the hand-pushed metadata fixes on #2339 (`2a86c8ff`, `d5ea4dc5`) — a push trigger re-heals after every regeneration instead of being lost. - **Uses the same PAT as `release-please.yml`**: a `GITHUB_TOKEN` push does not trigger workflows, so the release PR's checks would never re-run against the synced commit and would stay red. - **Idempotent**: the self-triggered rerun finds no diff and exits before pushing, so the loop terminates after one no-op run. - **Corrected pre-existing drift on `main`**: the agent-hooks plugin manifests, both marketplace manifests, and `.releasemetadata` were stranded at **0.31.0** — never bumped for 0.32.0 either. `verify-versions.py` now passes on `main`. ### Why not more `extra-files` entries That would need ~13 jsonpath entries restating what `version-sync.py` already knows, and a jsonpath that fails to match **fails silently** — the same class of failure this PR removes, discoverable only after a real release PR regenerates. There is also no precedent for nested jsonpath (`$.packages[0].version`, `$.metadata.version`) in the config today; both existing entries are plain `$.version`. Running the script keeps one source of truth, and files added to it later are covered with no change here. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) — no `headroom/` sources touched - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text $ python -m pytest scripts/tests/ tests/test_release_workflows.py tests/test_mcp_registry/ -q 207 passed in 2.69s $ ruff check scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ ruff format --check <same> 3 files already formatted $ actionlint .github/workflows/release-metadata-sync.yml (clean) ``` New tests: - `test_server_json_version_is_synchronized` — version-sync moves both `server.json` version fields and preserves the other keys. - `test_release_metadata_sync_runs_on_release_please_branch` — asserts the trigger, the sync→verify→commit ordering, the no-op guard, and the PAT. - `test_version_sync_covers_every_file_the_verifier_gates` — guards `version-sync.py` and `verify-versions.py` against drifting apart again, which is the root cause here. ## Real Behavior Proof - **Environment:** macOS (Darwin arm64), Python 3.12, repo venv. - **Exact command / steps:** reproduced the CI failure locally by simulating release-please's partial bump, then applying the fix. **Reproducing the exact `test (2)` failure** — set `pyproject` to 0.33.0 while `server.json` stays at 0.32.0, as release-please leaves it: ```text $ python -m pytest tests/test_mcp_registry/test_server_json.py -q FAILED tests/test_mcp_registry/test_server_json.py::test_root_server_json_matches_builder 1 failed, 3 passed ``` **After `version-sync.py`:** ```text $ python scripts/version-sync.py && python -m pytest tests/test_mcp_registry/test_server_json.py -q 4 passed ``` **Both gates green on a simulated 0.33.0 bump:** ```text $ python scripts/version-sync.py --version 0.33.0 Version synchronized to 0.33.0 $ python scripts/verify-versions.py All versions aligned at 0.33.0 $ python -m pytest tests/test_mcp_registry/test_server_json.py -q 4 passed ``` **Idempotency** (the property the workflow's loop-termination relies on): re-running against an already-synced tree leaves `pyproject.toml`, `server.json`, `openclaw`, and `sdk/typescript` untouched. - **Not tested:** the workflow has not executed on a real release-please branch regeneration — that can only be exercised once this is on `main` and release-please next updates #2339. The PAT push path and the self-trigger no-op are reasoned from `release-please.yml`'s existing token comment and from local idempotency, not observed in CI. ## 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 - [x] 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 - [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 - [x] I did **not** edit `CHANGELOG.md` ## Additional Notes **Context on the v0.32.0 release failure, since it is easy to misread as "images never build".** Every artifact built for v0.32.0 — all 5 wheel platforms including Windows, all 16 Docker builds + 8 manifests + `promote-latest`, npm, and GitHub Packages. Only `publish-pypi` failed (PyPI attestations, already fixed by `f9cbdd6e` / #2405), and `create-release` was skipped because it depends on it. That is why the release looked like it produced nothing. **Separate, approaching blocker — not addressed here.** PyPI is at **9.69 GB of its 10 GB project cap (96.9%)**, leaving ~305 MB against ~68 MB per release, so roughly 4 more releases fit. The `0.21.x` series alone holds **6.58 GB across 31 releases**, from the old every-push-is-a-release era; pruning it would reclaim two thirds of the quota. Worth a separate issue. **`.releasemetadata` is written but never read** by anything outside `version-sync.py` and its test. It is kept in sync here for internal consistency, but it may be a deletion candidate.
2026-07-29 15:12:04 -07:00
def test_server_json_version_is_synchronized(temp_project: dict[str, Path]) -> None:
"""server.json must track the bump or the release PR's test job fails.
``tests/test_mcp_registry/test_server_json.py::test_root_server_json_matches_builder``
asserts the tracked file equals ``render_server_json()``, which reads the version
from ``pyproject.toml``. Nothing regenerated server.json, so it fell behind every
release and blocked v0.33.0 (PR #2339).
"""
root = temp_project["root"]
script = Path(__file__).parent.parent / "version-sync.py"
result = subprocess.run(
[sys.executable, str(script), "--root", str(root), "--version", "0.33.0"],
capture_output=True,
text=True,
)
assert result.returncode == 0, f"Script failed: {result.stderr}"
server_json = json.loads(temp_project["server_json"].read_text())
assert server_json["version"] == "0.33.0"
# The packages[] entry carries its own version and is checked by the builder too.
assert [p["version"] for p in server_json["packages"]] == ["0.33.0"]
# Untouched keys must survive so the file still matches the builder's output.
assert server_json["name"] == "io.github.headroomlabs-ai/headroom"
assert server_json["packages"][0]["registryType"] == "pypi"
fix: publish headroom-opencode in release workflow (#2372) ## Description `headroom-opencode` is documented as an npm package, but the release workflow never published it, so installs failed with a registry 404 even though the plugin source already lived under `plugins/opencode`. This wires the existing package into the npm release path, keeps its version synced with root releases, and adds release guards for the new package. Closes #76. ## 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) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - added `headroom-opencode` to the npm release workflow, including release-version stamping and `headroom-ai` dependency rewrite before publish - added `plugins/opencode/package.json` to release-please and local version-sync guards - synced the source opencode package version to the current release line and documented the new npm package in the release docs - added focused release workflow and version-sync tests for the opencode package - aligned the two failing dashboard Playwright tests with the current Session/Lifetime split and `/stats-lifetime` fixture contract ## Testing - [x] Unit tests pass (`uv run pytest scripts/tests/test_version_sync.py -q`, `uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency'`) - [x] Unit tests pass (`uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q`) - [x] Linting passes (`uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py`) - [ ] Type checking passes (`uv run mypy headroom`) - [x] New tests added for new functionality when applicable - [x] Manual testing performed ### Test Output ```text $ uv run pytest scripts/tests/test_version_sync.py -q 8 passed, 1 warning in 0.51s $ uv run pytest tests/test_release_workflows.py -q -k 'publish_npm_rewrites_opencode_dependency_after_version_and_before_publish or opencode_source_dependency_matches_lockfile_registry_range or release_please_manifest_config_consistency' 2 passed, 38 deselected, 1 warning in 0.07s $ uv run pytest tests/test_dashboard_cache_lifetime_playwright.py tests/test_dashboard_cache_ttl_playwright.py -q 4 passed, 1 warning in 4.04s $ uv run ruff check scripts/verify-versions.py scripts/version-sync.py scripts/tests/test_version_sync.py tests/test_release_workflows.py All checks passed! $ npm ci && npm run build (plugins/opencode) Build success; dist/index.js, dist/entry.opencode.js, and DTS outputs emitted ``` ## Real Behavior Proof - Environment: Windows, Python 3.11.15, Node v24.15.0, npm 11.16.0 - Exact command / steps: inspected `.github/workflows/release.yml`, updated the npm publish path for `plugins/opencode`, aligned the two failing dashboard Playwright tests with the current Session/Lifetime split, then ran the focused pytest commands above plus `npm ci && npm run build` in `plugins/opencode` - Observed result: the release workflow now versions and publishes `headroom-opencode`, release-please and version-sync track `plugins/opencode/package.json`, the dashboard tests now fetch durable cache and setup-url data from the Lifetime view, and the opencode package still builds locally from source - Not tested: GitHub Package Registry publish ## 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 - [x] 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 - [x] I have updated the CHANGELOG.md if applicable ## Additional Notes `CHANGELOG.md` is unchanged because release-please owns changelog generation here. --------- Co-authored-by: JD Davis <mxjerrett@gmail.com>
2026-08-12 00:56:40 -04:00
def test_opencode_headroom_dependency_is_preserved_for_registry_installability(
temp_project: dict[str, Path],
) -> None:
"""Source package stays installable even when the next SDK is not on npm yet."""
root = temp_project["root"]
script = Path(__file__).parent.parent / "version-sync.py"
result = subprocess.run(
[sys.executable, str(script), "--root", str(root), "--version", "0.28.0"],
capture_output=True,
text=True,
)
assert result.returncode == 0, f"Script failed: {result.stderr}"
opencode_pkg = json.loads(temp_project["opencode_pkg"].read_text())
assert opencode_pkg["version"] == "0.28.0"
assert opencode_pkg["dependencies"]["headroom-ai"] == "^0.22.3"