You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ci: fix release push race and hotfix mirror tagging (#1781)
* ci: serialize master writers and retry release pushes to fix hotfix race
The Hotfix Release run for PR #1780 (run 28998970128) aborted inside
python-semantic-release with "Upstream branch 'origin/master' has
changed!": sync-tool-docs.yml pushed its doc-sync commit while the
release was mid-run, and the action's pre-push freshness check is not
retryable from inside the workflow. Because the job checked out the
event's frozen merge_commit_sha, re-runs re-fetched an already-advanced
master and were doomed to the same abort.
- Put every workflow that pushes to master (hotfix-release,
semver-release, sync-tool-docs, addon-publish-dev via
_update-addon-config) in one master-write concurrency group with
cancel-in-progress: false, so no bot push can land while a release's
semantic-release is running.
- hotfix-release now checks out master by name instead of the pinned
merge_commit_sha: still an attached branch (the PR #1090 constraint),
but re-runs recover and post-merge bot commits are already in the
base. The redundant manual attach step is dropped.
- The plain changelog/config pushes we own get the sync-tool-docs
rebase-and-retry loop as defense in depth (covers manual dispatches
that bypass the group).
Known tradeoff, documented in the workflow comments: GitHub queues only
one pending run per group, so a three-way coincidence (hotfix merge
touching tools) can cancel one queued bot run; both bot workflows are
workflow_dispatch-recoverable and self-heal on the next merge.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: tag integration mirror on hotfix releases too
sync-integration-mirror.yml only tagged the HACS mirror after a
"SemVer Release" workflow_run, so a hotfix that bumps the component
version copied the code to the mirror's main but never created the
version tag - HACS users stayed pinned to the previous release (bit
component 1.0.1 after PR #1780). The tag step is already idempotent
(skips when the manifest version is tagged), so hotfixes without a
component change are a no-op.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(internal): drop dead version_variables from semantic-release config
src/ha_mcp/__init__.py assigns __version__ = get_version() (resolved at
runtime from package metadata), so the version_variables pattern has
matched nothing since that change (num_matches=0 in release logs).
version_toml on pyproject.toml is the single bump source.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: queue master-write runs FIFO and guard retry rebases
Review follow-up (Patch76 on #1781).
Concern 1: with the default single-slot concurrency queue, a newly queued
run EVICTS the older pending one — so a queued release sitting behind an
in-progress bot writer could be silently dropped when a later bot run
queues. Add queue: max (GA 2026-05-07, valid because cancel-in-progress
is false) to all four master-write blocks: up to 100 pending runs wait
FIFO, no eviction. This also corrects the sync-tool-docs comment that
described the opposite eviction direction.
Minor: the retry-rebase loops now abort a conflicted/failed rebase and
surface the real error instead of leaving rebase-in-progress state for
the remaining attempts to trip over. Also refreshed the stale
sync-tool-docs loop comment (the mechanism is now the shared group, not
cancel-in-progress).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: skip mirror sync on non-success release runs; serialize pushes
Review follow-up (Patch76 on #1781).
Concern 2: adding Hotfix Release to the workflow_run trigger means the
mirror sync now fires on a completed run of a workflow that is skipped on
every non-hotfix PR merge (the release job is if-guarded). Without a
job-level guard the clone/snapshot/push stages ran on effectively every
merge, and a real hotfix produced two near-simultaneous mirror pushes
(push leg + workflow_run leg) with no serialization -- the second a
non-fast-forward rejection that fails the job before it can tag.
Guard the job with "event_name != 'workflow_run' || workflow_run
conclusion == 'success'" (also fixes the pre-existing odd-week/no-change
SemVer case), and add a mirror-sync concurrency group
(cancel-in-progress: false, queue: max) so the two legs of a real hotfix
serialize instead of racing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: replace vacuous hotfix origin check with a stable-tag existence guard
Review follow-up (Patch76 on #1781).
The "Validate hotfix is based on stable" step ran post-merge, where HEAD is
master's tip. Because master is never rewritten, the stable tag is always an
ancestor of HEAD, so `git merge-base --is-ancestor stable HEAD` can never
fail -- the ancestor logic (both exit-1 fallbacks) was unreachable dead code.
Verified against git-scm merge-base exit semantics and actions/checkout ref
behavior. It was equally vacuous under the previous merge_commit_sha checkout.
Real hotfix-origin validation already happens PRE-merge in
pr-validate-hotfix.yml, which checks out the unmerged branch head. Rather than
delete the whole step (which would silently drop its one reachable behavior --
the missing-stable-tag hard-fail, which pr-validate-hotfix.yml does NOT cover:
it only warns-and-skips), replace the dead ancestor logic with a one-line
stable-tag existence guard and keep the hard-fail.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: kingpanther13 <kingpanther13@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
0 commit comments