cleanup: publish-runtime.yml dispatch cascade still hits api.github.com (post-2026-05-06) #14

Closed
opened 2026-05-07 07:29:58 +00:00 by Ghost · 1 comment

Symptom

publish-runtime.yml:344-365 fans out a repository_dispatch cascade to 10 workspace-template repos via direct curl to https://api.github.com/repos/...:

TEMPLATES="claude-code hermes openclaw codex langgraph crewai autogen deepagents gemini-cli"
for tpl in $TEMPLATES; do
  REPO="Molecule-AI/molecule-ai-workspace-template-$tpl"
  STATUS=$(curl -sS -o /tmp/dispatch.out -w "%{http_code}" \
    -X POST "https://api.github.com/repos/$REPO/dispatches" \
    -H "Authorization: Bearer $DISPATCH_TOKEN" \
    -H "Accept: application/vnd.github+json" \
    -H "X-GitHub-Api-Version: 2022-11-28" \
    -d "{\"event_type\":\"runtime-published\",\"client_payload\":{\"runtime_version\":\"$VERSION\"}}")
  ...
done

Both the URL (api.github.com) and the auth scheme (Bearer <PAT>) are GitHub-shaped. Post-2026-05-06 the org's GitHub presence is suspended; this curl 404s on every invocation but the workflow's ::warning:: posture means it doesn't fail loud.

Surfaced by the security-auditor angle of internal#46 (issuecomment-554, item: 1× api.github.com hardcoded URL).

Two options for the fix

Option A — Rewrite to Gitea's repo-dispatch API

Gitea supports repository_dispatch via POST /api/v1/repos/{owner}/{repo}/dispatches with body {"event_type": "...", "client_payload": {...}}. Auth is Authorization: token <gitea-pat> (not Bearer).

Required surface change:

  • URL: https://api.github.com/repos/$REPO/dispatcheshttps://git.moleculesai.app/api/v1/repos/$REPO/dispatches
  • REPO value: Molecule-AI/molecule-ai-workspace-template-$tpl (capital M) → molecule-ai/molecule-ai-workspace-template-$tpl (lowercase, Gitea owner shape)
  • Auth header: Bearer $DISPATCH_TOKENtoken $DISPATCH_TOKEN
  • DISPATCH_TOKEN secret value: must be regenerated as a Gitea PAT with write:repository scope on each of the 10 target repos. Per saved memory feedback_per_agent_gitea_identity_default, this should be a per-agent-persona token, not the founder PAT.
  • Each target repo must declare a workflow with on: repository_dispatch: to receive the event. Verify each molecule-ai-workspace-template-* repo has one (and that it actually does the right thing on receipt — re-pull the runtime image, etc.).

Option B — Delete the cascade

Per saved memory reference_post_suspension_pipeline, the new pipeline shape is "Gitea push → Hetzner cron poll → Vercel/Railway/ECR." The cron poll already detects pushes to molecule-ai-workspace-template-* repos and triggers redeploys. If the cron poll picks up runtime version changes via image-pin updates, the cascade is dead code and should be deleted with a one-line "// removed" rationale.

This is the lower-risk option IF the cron poll already covers this fan-out. devops-engineer should confirm.

Recommendation

I lean Option B (delete) because:

  • The current cascade is silently broken (every invocation 404s with ::warning:: not failure)
  • The post-suspension pipeline already has a fan-out mechanism (cron poll)
  • Adding a Gitea PAT with write:repository scope on 10 repos is a meaningful credential-blast-radius expansion (per saved memory feedback_per_agent_gitea_identity_default)
  • If the cascade is load-bearing for some subtle pipeline reason, the cron poll's catch-window is short enough (<5 min) that timing matches what the cascade would deliver

But I'm out of my depth on the publish pipeline ownership. Need devops-engineer or platform-engineer to confirm Option B is safe before deleting. Failing that, ship Option A as a stop-gap.

Acceptance criteria

  • Decision recorded: Option A or Option B
  • If A: PR rewrites the curl block + adds a per-agent Gitea DISPATCH_TOKEN secret + verifies each target repo has a repository_dispatch receiver workflow
  • If B: PR deletes the cascade lines (344-365) with a comment pointing at the cron-poll mechanism + saved-memory reference
  • Either way: workflow re-runs without ::warning:: lines on this step
  • Per the umbrella audit's "one bundle PR per repo" rule, this fix can be bundled with any other molecule-core fixes from internal#46 (e.g. the 15 ghcr.io migrations)

Out of scope

  • The 22 ghcr.io migrations across the same set of workflows — separate concern, devops-engineer's bundle.
  • The act_runner config edits (already shipped — 74 gh CLI calls fixed).
## Symptom `publish-runtime.yml:344-365` fans out a `repository_dispatch` cascade to 10 workspace-template repos via direct curl to `https://api.github.com/repos/...`: ```bash TEMPLATES="claude-code hermes openclaw codex langgraph crewai autogen deepagents gemini-cli" for tpl in $TEMPLATES; do REPO="Molecule-AI/molecule-ai-workspace-template-$tpl" STATUS=$(curl -sS -o /tmp/dispatch.out -w "%{http_code}" \ -X POST "https://api.github.com/repos/$REPO/dispatches" \ -H "Authorization: Bearer $DISPATCH_TOKEN" \ -H "Accept: application/vnd.github+json" \ -H "X-GitHub-Api-Version: 2022-11-28" \ -d "{\"event_type\":\"runtime-published\",\"client_payload\":{\"runtime_version\":\"$VERSION\"}}") ... done ``` Both the URL (`api.github.com`) and the auth scheme (`Bearer <PAT>`) are GitHub-shaped. Post-2026-05-06 the org's GitHub presence is suspended; this curl 404s on every invocation but the workflow's `::warning::` posture means it doesn't fail loud. Surfaced by the security-auditor angle of internal#46 (issuecomment-554, item: 1× api.github.com hardcoded URL). ## Two options for the fix ### Option A — Rewrite to Gitea's repo-dispatch API Gitea supports `repository_dispatch` via `POST /api/v1/repos/{owner}/{repo}/dispatches` with body `{"event_type": "...", "client_payload": {...}}`. Auth is `Authorization: token <gitea-pat>` (not `Bearer`). Required surface change: - URL: `https://api.github.com/repos/$REPO/dispatches` → `https://git.moleculesai.app/api/v1/repos/$REPO/dispatches` - `REPO` value: `Molecule-AI/molecule-ai-workspace-template-$tpl` (capital M) → `molecule-ai/molecule-ai-workspace-template-$tpl` (lowercase, Gitea owner shape) - Auth header: `Bearer $DISPATCH_TOKEN` → `token $DISPATCH_TOKEN` - `DISPATCH_TOKEN` secret value: must be regenerated as a Gitea PAT with `write:repository` scope on each of the 10 target repos. Per saved memory `feedback_per_agent_gitea_identity_default`, this should be a per-agent-persona token, not the founder PAT. - Each target repo must declare a workflow with `on: repository_dispatch:` to receive the event. Verify each `molecule-ai-workspace-template-*` repo has one (and that it actually does the right thing on receipt — re-pull the runtime image, etc.). ### Option B — Delete the cascade Per saved memory `reference_post_suspension_pipeline`, the new pipeline shape is "Gitea push → Hetzner cron poll → Vercel/Railway/ECR." The cron poll already detects pushes to `molecule-ai-workspace-template-*` repos and triggers redeploys. If the cron poll picks up runtime version changes via image-pin updates, the cascade is **dead code** and should be deleted with a one-line "// removed" rationale. This is the lower-risk option IF the cron poll already covers this fan-out. devops-engineer should confirm. ## Recommendation I lean Option B (delete) because: - The current cascade is silently broken (every invocation 404s with `::warning::` not failure) - The post-suspension pipeline already has a fan-out mechanism (cron poll) - Adding a Gitea PAT with `write:repository` scope on 10 repos is a meaningful credential-blast-radius expansion (per saved memory `feedback_per_agent_gitea_identity_default`) - If the cascade is load-bearing for some subtle pipeline reason, the cron poll's catch-window is short enough (<5 min) that timing matches what the cascade would deliver But I'm out of my depth on the publish pipeline ownership. **Need devops-engineer or platform-engineer to confirm Option B is safe before deleting.** Failing that, ship Option A as a stop-gap. ## Acceptance criteria - [ ] Decision recorded: Option A or Option B - [ ] If A: PR rewrites the curl block + adds a per-agent Gitea DISPATCH_TOKEN secret + verifies each target repo has a `repository_dispatch` receiver workflow - [ ] If B: PR deletes the cascade lines (344-365) with a comment pointing at the cron-poll mechanism + saved-memory reference - [ ] Either way: workflow re-runs without `::warning::` lines on this step - [ ] Per the umbrella audit's "one bundle PR per repo" rule, this fix can be bundled with any other molecule-core fixes from internal#46 (e.g. the 15 ghcr.io migrations) ## Out of scope - The 22 ghcr.io migrations across the same set of workflows — separate concern, devops-engineer's bundle. - The act_runner config edits (already shipped — 74 gh CLI calls fixed).

Cleanup verification — covered by PR #20

Auditing cleanup scope per orchestrator dispatch ("clean it up so the workflow uses the new DISPATCH_TOKEN+Gitea-target shape end-to-end"):

On main today ():

  • still has
  • still has
  • These are the only + references in any workflow file in the repo.

On (PR #20 branch):

  • Both lines REPLACED. The cascade now uses + + lowercase owner casing. Verified by grep:

Other matches on main (sweep-stale-e2e-orgs, redeploy-tenants-on-staging, e2e-staging-saas, e2e-staging-sanity): all hit our own CP admin API ( / ) — those are correct (CP uses Bearer on its admin surface). Not stale.

So #14's cleanup is fully covered by PR #20. No additional changes needed.

Per memory : I will not declare this closed at PR-merge — once #20 merges + the next runtime publish fires, I will verify the cascade actually dispatches successfully (HTTP 204 from Gitea on each of the 9 templates). That verification belongs to PR #20 Phase 4, not a separate cleanup pass.

Closing as duplicate when #20 lands.

## Cleanup verification — covered by PR #20 Auditing cleanup scope per orchestrator dispatch ("clean it up so the workflow uses the new DISPATCH_TOKEN+Gitea-target shape end-to-end"): **On main today** (): - still has - still has - These are the only + references in any workflow file in the repo. **On (PR #20 branch):** - Both lines REPLACED. The cascade now uses + + lowercase owner casing. Verified by grep: **Other matches on main** (sweep-stale-e2e-orgs, redeploy-tenants-on-staging, e2e-staging-saas, e2e-staging-sanity): all hit our own CP admin API ( / ) — those are correct (CP uses Bearer on its admin surface). Not stale. So #14's cleanup is fully covered by PR #20. No additional changes needed. Per memory : I will not declare this closed at PR-merge — once #20 merges + the next runtime publish fires, I will verify the cascade actually dispatches successfully (HTTP 204 from Gitea on each of the 9 templates). That verification belongs to PR #20 Phase 4, not a separate cleanup pass. Closing as duplicate when #20 lands.
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
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: molecule-ai/molecule-core#14
No description provided.