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
release.yml: once a version's fixed group is on npm, the push-lane Releases backfill races the publish job's own Releases step — 17.6.0 got 9 × 422 already_exists, 5 duplicate GitHub Releases and two red runs #21313
Filed by the domain:cli seat (session_01VvcEokUG1tvVxkceYfR5XB) on the maintainer's direct instruction in that session on 2026-10-02: 「这次 Release 任务的结论是 failure,失败在 "Create GitHub Releases" 这一步。 报 issue」. ⛔ Not a claim, not a dispatch. Triage sets domain:* and the grade.
What happened (measured from the run logs and the Releases API)
The 17.6.0 release, cut from the version commit 617f25f8a4 (#20639), went to npm and pushed its tags cleanly. Two red runs followed, and they wrote to the same GitHub Releases at the same time:
Writer
Run / job
Script window
Result
Publish job, step "Create GitHub Releases"
run 36955885276, job 110678824190
03:03:47Z → 03:05:42Z
65 created, 1 updated, 3 failed (422)
Push-lane release-integrity, step "Backfill GitHub Releases" (the landing push 4e530568a2)
run 36958423332, job 110686494582
03:04:37Z → 03:05:42Z
9 created, 54 updated, 6 failed (422)
Both run scripts/release-github-releases.mjs for RELEASE_VERSION: 17.6.0. They walk the package list in the same order, about 50 s apart, and catch up with each other near the tail of the list.
The 9 failures: every one is 422 {"code":"already_exists","field":"tag_name"}.
The publish job failed on service-messaging, trigger-record-change and trigger-schedule.
The backfill failed on service-job, service-package, service-queue, service-settings, service-sms and verify.
Duplicates: where both writers' check-then-create landed inside the same second, both POSTs succeeded. 69 tags now carry 74 Release objects. Five tags have two releases each, published within a second of each other:
The ADR-0087 D4 asset: the publish job then ran release-spec-changes.sh --attach ("Attached spec-changes.json to release @objectstack/spec@17.6.0"). It landed on 401511580, and the other spec release, 401511585, carries no asset.
It works for the group. But the publish job's own npm read-back only settled at 03:03:47Z ("all 69 published package(s) are readable on npm — settled after 795s"). The publish job then still had its Releases step to run.
The landing 4e530568a2 arrived at 03:03:12Z. Its release-integrity read the group as complete and started its own backfill of the same Releases while the publish job was creating them.
the publish job uses group: release-publish-${{ github.ref }} (:1287-1288).
release-github-releases.mjs is not safe under a concurrent writer. It decides create-or-update from a read, then POSTs; a 422 already_exists fails the release rather than re-reading and updating. And the Releases API accepted two creates for one tag inside the same second.
npm: all 69 packages are published at 17.6.0, and every tag is pushed.
GitHub Releases: every tag has at least one release.
Five tags have a duplicate.
The spec duplicate pair carries the D4 asset on only one of the two.
The releases/latest pointer reads @objectstack/verify@17.6.0.
Runs: both are red with no missing artifact.
Out of scope: the seat did not touch any release object. ⛔ Deleting the duplicate releases and re-running either job are release-surface actions, and they stay with the maintainer or the release lane.
Direction (for triage; not a ruling)
Exclusion: make the backfill and the publish job's Releases step mutually exclusive for one version. Either they share a concurrency group keyed on the version, or the push lane skips the Releases backfill while a publish run for that version has not concluded.
Idempotent script: make release-github-releases.mjs idempotent under a racing writer. On a 422 already_exists, re-read the tag's release and update it instead of failing.
Duplicates: decide whether the script also has to detect and report duplicate releases for a tag. The five above say the platform will not prevent them.
One-time cleanup: delete one release from each duplicate pair, keeping 401511580 for spec because it carries the D4 asset. This is the maintainer's call.
Filed by the
domain:cliseat (session_01VvcEokUG1tvVxkceYfR5XB) on the maintainer's direct instruction in that session on 2026-10-02: 「这次 Release 任务的结论是 failure,失败在 "Create GitHub Releases" 这一步。 报 issue」. ⛔ Not a claim, not a dispatch. Triage setsdomain:*and the grade.What happened (measured from the run logs and the Releases API)
The 17.6.0 release, cut from the version commit
617f25f8a4(#20639), went to npm and pushed its tags cleanly. Two red runs followed, and they wrote to the same GitHub Releases at the same time:36955885276, job110678824190release-integrity, step "Backfill GitHub Releases" (the landing push4e530568a2)36958423332, job110686494582scripts/release-github-releases.mjsforRELEASE_VERSION: 17.6.0. They walk the package list in the same order, about 50 s apart, and catch up with each other near the tail of the list.422 {"code":"already_exists","field":"tag_name"}.service-messaging,trigger-record-changeandtrigger-schedule.service-job,service-package,service-queue,service-settings,service-smsandverify.@objectstack/service-knowledge@17.6.0:401511494,401511496@objectstack/service-realtime@17.6.0:401511528,401511529@objectstack/service-storage@17.6.0:401511561,401511562@objectstack/spec@17.6.0:401511580,401511585@objectstack/types@17.6.0:401511638,401511640release-spec-changes.sh --attach("Attached spec-changes.json to release @objectstack/spec@17.6.0"). It landed on401511580, and the otherspecrelease,401511585, carries no asset.Why (read from
release.ymlatorigin/main)4e530568a2arrived at 03:03:12Z. Itsrelease-integrityread the group as complete and started its own backfill of the same Releases while the publish job was creating them.release-integrityusesgroup: release-integrity-${{ github.ref }}(:783-784);group: release-publish-${{ github.ref }}(:1287-1288).release-github-releases.mjsis not safe under a concurrent writer. It decides create-or-update from a read, then POSTs; a 422already_existsfails the release rather than re-reading and updating. And the Releases API accepted two creates for one tag inside the same second.github.sha), not the version commit the publish built from #20982, also closed, covered the same backfill's build source and is not this.Current state
specduplicate pair carries the D4 asset on only one of the two.releases/latestpointer reads@objectstack/verify@17.6.0.Direction (for triage; not a ruling)
release-github-releases.mjsidempotent under a racing writer. On a 422already_exists, re-read the tag's release and update it instead of failing.401511580forspecbecause it carries the D4 asset. This is the maintainer's call.