Skip to content

release-health re-folds and retries instead of losing a report - #43

Merged
bdbarnett merged 1 commit into
mainfrom
housekeeping/release-health-retry
Sep 22, 2026
Merged

bdbarnett merged 1 commit into
mainfrom
housekeeping/release-health-retry

Conversation

@bdbarnett

Copy link
Copy Markdown
Contributor

Fixes #34.

One release reports several distributions — audiocomponents publishes two
from one tag, audioif three — and each dispatches its own release-health
event. A repository_dispatch freezes github.sha at creation time, so the
second run checks out a tip that predates the first run's commit and its push
is rejected. The release-health concurrency group serializes the jobs; it
cannot fix the checkout.

A rebase-and-retry, as suggested on the issue, is not the right shape here.
reusable-synchronize-mip-package.yml can rebase because it edits a lockfile
entry. This step regenerates RELEASE_HEALTH.md whole and rewrites
release-health/data.json as one sorted object, so replaying our diff onto the
new tip either conflicts or drops the other distribution's row.

So the step re-folds instead: the Python moves into $RUNNER_TEMP/fold.py so it
can be run again, and on a rejection the loop discards the commit, takes the
branch tip, and folds the same payload in a second time. The fold is idempotent
— it sets one key by distribution name — so the result carries both rows.
Three attempts, then a hard error rather than a silent stale row.

While in there, the commit message takes distribution and version through
env: rather than interpolating the dispatch payload straight into the shell.

How it was proved

tests/test_release_health.py lifts the step's run: body out of the YAML and
runs it against real git repositories, staging the race as two clones of one
tip pushing to a bare origin.

$ python3 -m unittest discover -s tests
Ran 16 tests in 0.620s

OK

The race test asserts the retry path is actually taken (push rejected (attempt 1) in the output), that both keys are in the published
data.json, and that both rows are on the page. Two more cover an
uncontended report and a re-report of the same distribution.

The same race run against the pre-fix step, so the test is not passing
vacuously:

=== run 2 (audioeffects), same frozen tip ===
hint: Updates were rejected because the remote contains work that you do not
hint: have locally.
=== what the dashboard ended up with ===
{
 "pydevices-audioinstruments": { ... "version": "0.2.0" }
}

audioeffects is simply missing — the bug as filed.

actionlint clean, ruff check scripts/ tests/ clean.

Note the stale row the issue describes has since been overwritten by later
releases; RELEASE_HEALTH.md on main is current. This stops it recurring.

One release reports several distributions -- audiocomponents publishes two
from one tag, audioif three -- and each dispatches its own release-health
event. A repository_dispatch freezes github.sha at creation time, so the
second run checks out a tip that predates the first run's commit and its push
is rejected. The concurrency group serializes the jobs but cannot fix the
checkout. That is how pydevices-audioeffects' row sat stale at 0.1.1 while
pydevices-audioinstruments right above it read 0.2.0.

The sibling fix in reusable-synchronize-mip-package rebases and retries, but a
rebase is wrong here: RELEASE_HEALTH.md is regenerated whole and data.json is
one sorted object, so replaying our diff onto the new tip conflicts or drops
the other distribution's row. Instead the fold moves into a file and the step
loops: on a rejection, discard the commit, take the branch tip, and fold the
payload in again. The fold is idempotent, so the result carries both rows.

The commit message also takes the payload through env rather than
interpolating it into the shell.

tests/test_release_health.py lifts the step out of the YAML and runs it
against real repositories, staging the race with two clones of one tip.

Closes #34
@bdbarnett
bdbarnett merged commit d6c2831 into main Sep 22, 2026
5 checks passed
@bdbarnett
bdbarnett deleted the housekeeping/release-health-retry branch September 22, 2026 02:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

release-health.yml: second concurrent report from one release lost a git push, left a stale dashboard row

1 participant