feat(ci): auto-mirror each cut to Codeberg via reusable workflow #318

Closed
opened 2026-07-03 12:18:55 +02:00 by quartermaster · 1 comment

Motivation

Set I Track A (per Bosun 312c). Forward-going automation for the Codeberg mirror.

After #308's one-shot migration backfills the 38 historical releases, every subsequent cut needs to auto-mirror to codeberg.org/FrankenBit/release-toolkit so the Codeberg-side stays in-sync with substrate-of-record. Without automation, the mirror drifts and #308's migration script would have to re-run manually after every cut — high toil.

Reusable-workflow shape (per Bosun ratify): isolate mirror from cut so mirror-failure doesn't cascade from cut-failure and external adopters can opt-in independently.

What ships

  • .forgejo/workflows/reusable-mirror-to-codeberg.yml (new) — reusable workflow that takes forgejo_owner/repo, codeberg_owner/repo, tag_name, and runs_on as inputs. Reads release-body from Forgejo (source of truth) + POSTs to Codeberg. Idempotent (GET-before-POST) + warn-not-fail on Codeberg errors.
  • .forgejo/workflows/release.yml — adds a mirror job to toolkit-self's consumer wrapper. Depends on release, gated on mode == 'cut' (skips update + noop). Uses ./.forgejo/workflows/reusable-mirror-to-codeberg.yml (local ref) to sidestep the bootstrap-lag pattern; external adopters use the tagged form.

Secret

  • CODEBERG_MIRROR_PAT — Codeberg PAT with write:repository on the mirror repo. Provisioned to release-toolkit's Actions secrets. Missing secret → workflow warns + exits 0 (external adopters aren't forced to provision).

Design decisions

  • Local ref (./.forgejo/workflows/...) not tagged ref: sidesteps the bootstrap-lag class where a newly-added reusable workflow doesn't yet exist at the tag the toolkit is pinned to. External adopters use the tagged form once released.
  • Warn-not-fail: cut is the canonical event on Forgejo; mirror failure shouldn't block or fail-alert the cut. Emits GitHub-Actions-style ::warning:: on skip so operator sees it in workflow summary.
  • Reads release-body from Forgejo API at mirror-time: race-free because the cut path completes release publishing BEFORE the mirror job kicks in (via needs: release).
  • #308 — Track B one-shot migration (fills the historical gap this workflow closes forward-going)
  • Set I dispatch (Bosun 312c) — sequence: automation (this) + migration (#308) → v0.24.1 patch cut → v1.0.0

Priority

priority/medium size/S — modest workflow addition; no risk of substrate-of-record failure due to warn-not-fail. Blocks v1.0.0's clean-mirror stability-signal readiness.

## Motivation Set I Track A (per Bosun 312c). Forward-going automation for the Codeberg mirror. After #308's one-shot migration backfills the 38 historical releases, every subsequent cut needs to auto-mirror to `codeberg.org/FrankenBit/release-toolkit` so the Codeberg-side stays in-sync with substrate-of-record. Without automation, the mirror drifts and #308's migration script would have to re-run manually after every cut — high toil. Reusable-workflow shape (per Bosun ratify): isolate mirror from cut so mirror-failure doesn't cascade from cut-failure and external adopters can opt-in independently. ## What ships - **`.forgejo/workflows/reusable-mirror-to-codeberg.yml`** (new) — reusable workflow that takes `forgejo_owner/repo`, `codeberg_owner/repo`, `tag_name`, and `runs_on` as inputs. Reads release-body from Forgejo (source of truth) + POSTs to Codeberg. Idempotent (GET-before-POST) + warn-not-fail on Codeberg errors. - **`.forgejo/workflows/release.yml`** — adds a `mirror` job to toolkit-self's consumer wrapper. Depends on `release`, gated on `mode == 'cut'` (skips update + noop). Uses `./.forgejo/workflows/reusable-mirror-to-codeberg.yml` (local ref) to sidestep the bootstrap-lag pattern; external adopters use the tagged form. ## Secret - **`CODEBERG_MIRROR_PAT`** — Codeberg PAT with write:repository on the mirror repo. Provisioned to release-toolkit's Actions secrets. Missing secret → workflow warns + exits 0 (external adopters aren't forced to provision). ## Design decisions - **Local ref (`./.forgejo/workflows/...`) not tagged ref**: sidesteps the bootstrap-lag class where a newly-added reusable workflow doesn't yet exist at the tag the toolkit is pinned to. External adopters use the tagged form once released. - **Warn-not-fail**: cut is the canonical event on Forgejo; mirror failure shouldn't block or fail-alert the cut. Emits GitHub-Actions-style `::warning::` on skip so operator sees it in workflow summary. - **Reads release-body from Forgejo API at mirror-time**: race-free because the cut path completes release publishing BEFORE the mirror job kicks in (via `needs: release`). ## Related - #308 — Track B one-shot migration (fills the historical gap this workflow closes forward-going) - Set I dispatch (Bosun 312c) — sequence: automation (this) + migration (#308) → v0.24.1 patch cut → v1.0.0 ## Priority `priority/medium` `size/S` — modest workflow addition; no risk of substrate-of-record failure due to warn-not-fail. Blocks v1.0.0's clean-mirror stability-signal readiness.
Author
Owner

Closing as duplicate of #309 (Bosun's superseding tracker, same scope). Number-collision from parallel filing during Set I kickoff. All work continues in #309.

Closing as duplicate of #309 (Bosun's superseding tracker, same scope). Number-collision from parallel filing during Set I kickoff. All work continues in #309.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
frankenbit/release-toolkit#318
No description provided.