Skip to content

chore: sync generated version metadata #152

chore: sync generated version metadata

chore: sync generated version metadata #152

name: Release Metadata Sync
# Keep generated version-carrying files in sync on release-please's branch.
#
# Why this exists
# ---------------
# release-please only rewrites `pyproject.toml` plus the `extra-files` listed in
# `.release-please-config.json` (currently the TypeScript SDK and OpenClaw
# package.json). Several 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 moment release-please bumps
# the version, `tests/test_mcp_registry/test_server_json.py::
# test_root_server_json_matches_builder` fails on the release PR, and the release
# cannot be merged. That is what blocked v0.33.0 (PR #2339).
#
# `release.yml` already runs `scripts/version-sync.py` before its own
# `verify-versions.py` gate, so the release *build* self-heals in the workspace.
# The regular CI test job does not, so the fix has to be committed.
#
# Why a workflow rather than more `extra-files` entries
# ----------------------------------------------------
# `scripts/version-sync.py` is the single place that knows every version-carrying
# file. Restating that list as per-file jsonpaths would duplicate it, and a
# jsonpath that silently fails to match produces exactly the failure we are trying
# to remove. Running the script instead means files added to it in future are
# covered with no change here.
#
# Why the push trigger
# --------------------
# release-please regenerates (force-pushes) its branch on every merge to main.
# That is what repeatedly wiped the hand-pushed metadata fixes on #2339. Keying
# off a push to the branch means the sync re-applies after every regeneration
# instead of being lost.
on:
push:
branches:
- "release-please--branches--**"
permissions:
contents: write
concurrency:
# Never cancel: a half-applied sync would leave the release PR inconsistent.
group: release-metadata-sync-${{ github.ref }}
cancel-in-progress: false
jobs:
sync:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
# Prefer a short-lived, repo-scoped GitHub App installation token over a
# personal PAT. Gated on the repo variable so an unconfigured app simply
# falls through to the existing chain instead of breaking the release.
- name: Mint installation token
id: app-token
if: ${{ vars.RELEASE_APP_ID != '' }}
continue-on-error: true
uses: actions/create-github-app-token@v3
with:
app-id: ${{ vars.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
- uses: actions/checkout@v7
with:
ref: ${{ github.ref_name }}
# Do NOT persist the credential into .git/config. The next step runs
# scripts/version-sync.py *from the checked-out branch*, and this job
# triggers on a push to the unprotected glob release-please--branches--**.
# A persisted token would be readable by that script.
persist-credentials: false
- uses: actions/setup-python@v6
with:
python-version: "3.12"
# version-sync.py is stdlib-only (json/re/tomllib), so no install step.
- name: Sync version-carrying files release-please does not bump
run: python scripts/version-sync.py
- name: Verify all versions agree
run: python scripts/verify-versions.py
- name: Commit and push if anything changed
env:
# An app installation token if one was minted, else the existing
# chain. A PAT (not GITHUB_TOKEN) is still preferred here for the same
# reason release-please.yml wants one: a push made with GITHUB_TOKEN
# does not trigger workflows, so the release PR's checks would never
# re-run against the synced commit and would stay red. Supplied only
# to this step, after the branch-supplied script has already run.
SYNC_TOKEN: ${{ steps.app-token.outputs.token || secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}
run: |
if git diff --quiet; then
echo "Already in sync — nothing to commit."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A
git commit -m "chore: sync generated version metadata"
# Push via an explicit remote URL because the checkout no longer
# persists credentials. Passed on stdin-free env expansion so the
# token is not written to the command line or into .git/config.
# This push re-triggers this workflow. version-sync.py is idempotent, so
# the next run finds no diff and exits above without pushing — the loop
# terminates after one no-op run.
git push \
"https://x-access-token:${SYNC_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" \
HEAD:"${GITHUB_REF_NAME}"