fix: madtea's runtime GitHub calls speak the Gitea API - retool before the first GitHub release #421

Closed
opened 2026-08-17 15:50:47 +00:00 by hexajon · 1 comment
Owner

Problem

The madtea.lol migration (#420) repointed distribution config to the GitHub edge, which is correct and gate-green. But madtea itself is a Gitea/Forgejo API-v1 client, and several RUNTIME paths still speak the Gitea API against GitHub targets, which GitHub does not serve. GoReleaser publishes to GitHub natively, and that works; madtea's own code cannot. None of these paths fire until a release is cut, so the config merge is safe - but the first GitHub release is blocked until this lands. I found this reviewing the migration.

Broken paths

  1. Self-updater (blocker, shipped user-facing). madtea update / --check / --verify use the Gitea client, which builds https://github.com/api/v1/repos/sixfold-space/madtea/releases/latest. GitHub's REST API is api.github.com with no /api/v1 and a different schema, so it 404s. internal/cmd/update/update.go, client_release_ext.go, integrity.go. The gate misses it because the update tests mock the Gitea shape on a local server. This is the ADR 0012 headline feature - it cannot ship broken.
  2. release.sh token preflight (major). release.sh preflights and exports GITEA_TOKEN, but .goreleaser.yaml now uses the github provider (GITHUB_TOKEN). A missing GITHUB_TOKEN is not caught until after the tag is pushed - a half-published state. scripts/release.sh (~149-180).
  3. Satellite-readiness check (major). check-satellite-readiness.sh runs madtea api /repos/sixfold-space/homebrew-tap --jq .empty, which resolves against the cheshirecube origin, not GitHub; .empty is a Gitea field GitHub does not return. Likely aborts every release. scripts/check-satellite-readiness.sh:46, release.sh:200-208.
  4. Release-existence check (major). forge_release_exists() runs madtea release get <tag> --repo sixfold-space/madtea against cheshirecube; releases publish to GitHub, so it always 404s - re-runs goreleaser on resume and misreports failure. scripts/release.sh:314-322,356,374.
  5. Plugin vendor (major). assemble-plugin-artifact.sh runs madtea clone/finish (a Forgejo PR flow) against cheshirecube, but claude-plugins is a GitHub distribution repo, so the marketplace bump never lands. scripts/assemble-plugin-artifact.sh:364,403.

Open question I need to settle before building

Root cause: madtea is a standard Gitea API-v1 client (ADR 0017 - no per-platform branching). Reaching GitHub means madtea grows a GitHub REST path, in tension with ADR 0017. The options:

  • (a) Bounded GitHub REST helper for release metadata plus a plain-HTTPS asset download in the self-updater, and rework the release scripts to use gh/curl for GitHub state. Keeps the core forge client Gitea-only; the self-updater and release publishing are distribution concerns, arguably outside ADR 0017's scope.
  • (b) Dual-publish: GoReleaser also creates a Forgejo release on cheshirecube, so madtea's Gitea client keeps querying release state there while binaries download from GitHub.
  • (c) Self-updater stays on cheshirecube entirely (metadata and download), accepting the firewall cost on the update path only.

The second half of the same question: where is claude-plugins operatively homed for release-time commits - GitHub direct-commit with the release PAT (which matches the committed docs/contributing/release-credentials.md), or cheshirecube plus a sync? That determines how the vendor script is retooled.

Release gate

The first GitHub release must not be cut until (1) is fixed (a broken self-updater cannot ship, ADR 0012) and (2)-(5) are resolved. This issue blocks that release. Part of #420.

## Problem The madtea.lol migration (#420) repointed distribution config to the GitHub edge, which is correct and gate-green. But madtea itself is a Gitea/Forgejo API-v1 client, and several RUNTIME paths still speak the Gitea API against GitHub targets, which GitHub does not serve. GoReleaser publishes to GitHub natively, and that works; madtea's own code cannot. None of these paths fire until a release is cut, so the config merge is safe - but **the first GitHub release is blocked until this lands.** I found this reviewing the migration. ## Broken paths 1. **Self-updater (blocker, shipped user-facing).** `madtea update` / `--check` / `--verify` use the Gitea client, which builds `https://github.com/api/v1/repos/sixfold-space/madtea/releases/latest`. GitHub's REST API is `api.github.com` with no `/api/v1` and a different schema, so it 404s. `internal/cmd/update/update.go`, `client_release_ext.go`, `integrity.go`. The gate misses it because the update tests mock the Gitea shape on a local server. This is the ADR 0012 headline feature - it cannot ship broken. 2. **release.sh token preflight (major).** `release.sh` preflights and exports `GITEA_TOKEN`, but `.goreleaser.yaml` now uses the `github` provider (`GITHUB_TOKEN`). A missing `GITHUB_TOKEN` is not caught until after the tag is pushed - a half-published state. `scripts/release.sh` (~149-180). 3. **Satellite-readiness check (major).** `check-satellite-readiness.sh` runs `madtea api /repos/sixfold-space/homebrew-tap --jq .empty`, which resolves against the cheshirecube origin, not GitHub; `.empty` is a Gitea field GitHub does not return. Likely aborts every release. `scripts/check-satellite-readiness.sh:46`, `release.sh:200-208`. 4. **Release-existence check (major).** `forge_release_exists()` runs `madtea release get <tag> --repo sixfold-space/madtea` against cheshirecube; releases publish to GitHub, so it always 404s - re-runs goreleaser on resume and misreports failure. `scripts/release.sh:314-322,356,374`. 5. **Plugin vendor (major).** `assemble-plugin-artifact.sh` runs `madtea clone`/`finish` (a Forgejo PR flow) against cheshirecube, but claude-plugins is a GitHub distribution repo, so the marketplace bump never lands. `scripts/assemble-plugin-artifact.sh:364,403`. ## Open question I need to settle before building Root cause: madtea is a standard Gitea API-v1 client (ADR 0017 - no per-platform branching). Reaching GitHub means madtea grows a GitHub REST path, in tension with ADR 0017. The options: - **(a) Bounded GitHub REST helper** for release metadata plus a plain-HTTPS asset download in the self-updater, and rework the release scripts to use `gh`/curl for GitHub state. Keeps the core forge client Gitea-only; the self-updater and release publishing are distribution concerns, arguably outside ADR 0017's scope. - **(b) Dual-publish**: GoReleaser also creates a Forgejo release on cheshirecube, so madtea's Gitea client keeps querying release state there while binaries download from GitHub. - **(c) Self-updater stays on cheshirecube** entirely (metadata and download), accepting the firewall cost on the update path only. The second half of the same question: **where is claude-plugins operatively homed for release-time commits** - GitHub direct-commit with the release PAT (which matches the committed `docs/contributing/release-credentials.md`), or cheshirecube plus a sync? That determines how the vendor script is retooled. ## Release gate The first GitHub release must not be cut until (1) is fixed (a broken self-updater cannot ship, ADR 0012) and (2)-(5) are resolved. This issue blocks that release. Part of #420.
Author
Owner

My lean on the design fork is (a): a bounded GitHub REST helper for release metadata, plus a plain-HTTPS asset download in the self-updater, with the release scripts using gh/curl for GitHub state. It keeps the core forge client Gitea-only, so ADR 0017 stays intact, and it treats self-update and release publishing as the distribution concerns they are. For the claude-plugins home my lean is GitHub direct-commit with the release PAT, matching the committed release-credentials doc.

The tradeoff I am accepting with (a) is a second HTTP shape inside madtea, which is exactly what ADR 0017 was written to avoid. (b) avoids that at the cost of publishing every release twice; (c) avoids it entirely but leaves the update path behind the firewall that started this whole migration.

Still open, and I want it settled before the retool starts, because it blocks the first GitHub release and touches all five broken paths at once.

My lean on the design fork is (a): a bounded GitHub REST helper for release metadata, plus a plain-HTTPS asset download in the self-updater, with the release scripts using `gh`/curl for GitHub state. It keeps the core forge client Gitea-only, so ADR 0017 stays intact, and it treats self-update and release publishing as the distribution concerns they are. For the claude-plugins home my lean is GitHub direct-commit with the release PAT, matching the committed release-credentials doc. The tradeoff I am accepting with (a) is a second HTTP shape inside madtea, which is exactly what ADR 0017 was written to avoid. (b) avoids that at the cost of publishing every release twice; (c) avoids it entirely but leaves the update path behind the firewall that started this whole migration. Still open, and I want it settled before the retool starts, because it blocks the first GitHub release and touches all five broken paths at once.
hexajon self-assigned this 2026-08-17 17:45:48 +00:00
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.

Reference
sixfold-space/madtea#421
No description provided.