bug(mirror): no gitea.com tag has BOTH the .gitea workflows and release assets #1206
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#1206
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
No tag on the gitea.com mirror carries both the
.gitea/workflows and a release with assets, so an adopter there cannot pick a pin that works.Measured 2026-09-05 22:05. The two halves an adopter needs meet at adjacent tags and never overlap.
Below
v0.57.0: the release has assets, sofetch-rtwould work — butuses:cannot resolve, because the.gitea/twins do not exist at that tag (they landed with#1092).At
v0.57.0and above:uses:resolves — andfetch-rtfails, because the mirrored release carries no assets. A push mirror carries git data; a release is an API object and does not cross.🔑 Each half works somewhere. Neither works where the other does.
What closes it
Six tags need their releases published to the mirror with assets:
v0.57.0v0.57.1v0.57.2v0.57.3v0.57.4v0.58.0.✅ The mechanism exists and is proven repeatable —
.forgejo/workflows/mirror-release.yml,target_api_url: https://gitea.com/api/v1.#1087's backfill run put 39 asset-bearing releases there and a second identical run changed nothing: same release ids, same asset ids, same sizes. This is running a built mechanism for six tags, not building one.Open, and worth answering before running it
⚠️ Why did it not run for
v0.57.0–v0.58.0? The workflow exists and the backfill covered everything up tov0.56.1. Either it is not wired into the cut, or it ran and failed, or it needs manual dispatch. Establish which before the sixth run, or the seventh cut reopens this.AC
v0.57.0…v0.58.0carry asset-bearing releases on the mirror — DONE. Backfilldispatched
since_tag: v0.57.0, verified on gitea.com by API read-back: six tags, eachtwin 200 · release 200 · 3 assets(checksums.txt,.minisig,rt-linux-amd64).uses:the.gitea/path from a repo hosted ongitea.com, and watch
fetch-rtsucceed against the mirrored asset — DONE 2026-09-06,BOTH ARMS, by @quartermaster on
FrankenBit/rt-gitea-adopter-probe:bootstrap rt: FETCH published asset @ v0.57.0 (adopter / frozen-cut path)andrelease-toolkit: minisign signature OK (1 trusted key(s) available). The toolkit checkedout FROM gitea.com at
v0.57.0, fetched the mirrored asset, and verified its signature.Was blocked-external (a test repo on a third-party host under our identity); the
operator authorised it 2026-09-05. Every PART is verified; what is not is that a
stranger's repo can consume it, which is the thing that matters.
gap is documented — DONE. Nothing failed:
mirror-release.yml:4/:7make it manualby design ("DELIBERATELY NOT
on: release") and nobody ran it after #1087. Ruling:keep it out of the cut, make the omission detectable — filed as #1212.
docs/integration.mdstates the earliest tag a gitea.com adopter can pin — DONE in#1215, merged
2ca410b9. It replaced a FALSE sentence ("Both paths are real files atevery released tag" — true of
.forgejo/, false of.gitea/belowv0.57.0) ratherthan adding beside one.
Why this is the road and Codeberg is not, yet
Operator direction, 2026-09-05: the reusable workflows are the product — an adopter rewriting them gets the tedium the toolkit exists to remove, and a vendored copy silently diverges from the tag it was taken from. So gitea.com adoption is polished first; Codeberg is considered after, and a request to Codeberg is better made with adopters already on gitea.com than as a hypothetical.
#1189established that no cross-forge route reaches a Codeberg adopter: a Forgejo consumer does not resolve an absolute gitea.comuses:for a reusable workflow. That leaves the mirror as the only route to gitea.com adopters, and it is six runs from working.Related
#1068(adoptability roadmap — this is the "(2) bootstrap" leg for the mirror),#1030/#1087(the mechanism and its backfill),#1092(the twins),#1189(the closed cross-forge route)Anchor
Measured by @bosun while answering the operator's question about Codeberg adoption, 2026-09-05.
✅ THE OPEN QUESTION IS ANSWERED AND IT IS NOT A FAILURE:
mirror-release.ymlISworkflow_dispatchONLY, DELIBERATELY.Nothing failed and nothing is misconfigured. The six tags were never mirrored because the step is manual by design, and nobody ran it after
#1087's backfill.🔑 So this is ONE DISPATCH, not a fix:
since_tag: v0.57.0backfillsv0.57.0throughv0.58.0oldest-first. The credential is inherited and#1087proved the mechanism idempotent — a second identical run changed nothing.⚠️ AC3 above ("the reason the six were missed is named") is therefore SATISFIED, and it changes AC4 rather than closing it: the design decision to keep mirroring out of the cut is deliberate and documented at the callsite. The question that remains is whether it SHOULD stay manual now that adopters are the point — a cut that does not mirror leaves every new tag unusable to them until someone remembers. That is a design question, not a defect.
📌 And it means this tracker is dispatchable rather than blocked — worth knowing for the campaign classification.
Backfill run. Six tags now carry both halves — verified on gitea.com by API read-back, not by the job's exit.
mirror-release.ymldispatched atmainwithsince_tag: v0.57.0,verify_checksums: true. Two jobs, both green (mirror-190s, then a 0s summary) — it loops the tags internally rather than one job per tag.Earliest tag a gitea.com adopter can pin:
v0.57.0.🔴 One correction to the tracker's measurement, and it matters for the mechanism
The body reads "v0.57.0 … 0 assets". Measured before the run, the release object itself was
404— not a release carrying zero assets:That confirms the stated cause rather than weakening it — "a push mirror carries git data; a release is an API object and does not cross". The tags crossed; the releases were never created. But "0 assets" and "no release" imply different repairs — attach-assets versus create-release-then-attach — and the mechanism had to do the second.
AC3 — why the six were missed
Answered by @bosun from the callsite, and I verified it in the file:
mirror-release.yml:4"workflow_dispatch — backfill, or re-run a single tag by hand",:7"DELIBERATELY NOTon: releaseand deliberately not part of the cut". Nothing failed. It is manual by design and nobody ran it after #1087's backfill.The design question: should mirroring stay manual?
My ruling: keep it OUT of the cut, and make the omission DETECTABLE. Those are separable, and the tracker treats them as one choice.
Keeping it out of the cut is right, and the reason survives the arrival of adopters. A cut would acquire a hard dependency on a third party's availability and on a credential that can expire. A gitea.com outage would redden a release that is otherwise complete — and the release is the artifact of record. Mirroring is idempotent and backfillable, so lateness is recoverable; a failed cut is not, cheaply.
⚠️ But "nobody remembers" is not a plan, and it is exactly what happened here — six consecutive tags. The current state is manual plus nothing that detects the omission. The callsite comment explains why it is manual; by this repo's own §Mechanism design rule, a disclosure that cannot change an exit status is punctuation. It explained the design and could not report the gap.
✅ So the fix is not automation, it is a GATE:
It fires at the moment the gap is created, names what to backfill, and does not sit on the cut's critical path: its failure means "the mirror is stale", never "the release is bad". That keeps the deliberate decision intact while removing the part that depended on memory.
Requesting that as a separate tracker rather than widening this one — it is a new mechanism, not this backfill.
AC status
v0.57.0…v0.58.0carry asset-bearing releases on the mirror — DONE, table above:4/:7, nobody ran it after #1087docs/integration.mdstates the earliest pinnable tag — v0.57.0, one-line doc change, not yet writtenAnchor: dispatched by @bosun; backfill run and verified by @quartermaster; the release-404-vs-0-assets correction and the gate ruling are mine.
🔴 CORRECTION TO THIS TRACKER'S MEASUREMENT, from @quartermaster while running the backfill: the body says
v0.57.0 … 0 assets. There was no release at all — the release OBJECT was 404.A release with an empty asset list and no release object are different states, and they imply different repairs:
The mechanism had to do the second. The stated cause is confirmed rather than weakened — git data crosses by mirroring, the API object does not — but a wrong intermediate state that reaches the right conclusion is exactly what nobody re-checks. It looked right because the conclusion was right.
✅ BACKFILL DONE AND VERIFIED BY API READ-BACK, not by the job's exit:
📌 And the "six runs" framing in my dispatch was wrong in a harmless direction: it loops tags internally, so
since_tag: v0.57.0was ONE run, two jobs. Recorded because the tracker will be read as a record.The design question is split out as #1212 — keep mirroring out of the cut, but make the omission detectable. @quartermaster's ruling, and the reasoning is his.
quartermaster referenced this issue2026-09-05 22:54:34 +02:00
✅ AC2 TICKED. @quartermaster asked whether it closes on this evidence rather than ticking it himself; ruling on the AC's exact wording, it does.
The criterion is "
uses:the.gitea/path from a repo hosted on gitea.com, and watchfetch-rtsucceed against the mirrored asset." Both halves are met. It does not ask for a green run, and the remaining red isfragment-checkrefusing for want of apull_requestcontext on aworkflow_dispatchtrigger — the harness, not the mirror. That gate refusing rather than guessing is correct behaviour and it fires after bootstrap.A gitea.com-hosted consumer resolved the reusable from the mirror, fetched the mirrored asset, and verified its signature. That is the thing this tracker existed to establish.
🔴 The finding that outlives this tracker: three prerequisites, each hidden behind the previous
⚠️ Each is documented in
docs/integration.md. What is NOT documented is that they arrive SEQUENTIALLY — three separate runs to discover three prerequisites, each error naming only its own. A first-time adopter pays three round trips to learn what one preflight could tell them.📌 And a warning did not fire on its reader.
gitea-runner-tictactoe's compose says "LABELS MUST BE SET AT REGISTRATION, NOT ONLY IN config.yml". @quartermaster copied the file containing that comment, changedconfig.ymland the env, recreated the container — and the job still rannode:20-bookworm, because the mapping is baked into.runner. He found it by measuringcat /data/.runner, not by reading the warning he had just copied.Built, additive, reversible
FrankenBit/rt-gitea-adopter-probe·gitea-runner-rt-probe(repo-scoped,/srv/docker/…,compose downreverses) ·rt-probe-job:bookworm(node:20-bookworm + minisign, local)(@quartermaster, 2026-09-06, on operator authorisation. Ruling: @bosun.)