feat(ci): publish the ward-mcp runtime image to the in-cluster registry on push (the chart's image.tag prerequisite) #9

Closed
opened 2026-07-07 10:04:22 +00:00 by coilysiren · 2 comments
Owner

Why

The runtime (#7) and chart (#8) landed, but ward-mcp's CI (.forgejo/workflows/ci.yml) only builds / vets / tests - it does not publish the runtime image. The chart's values.yaml expects image.repository: forgejo.coilysiren.me/coilyco-flight-deck/ward-mcp with image.tag supplied at rollout (the skillsmp example: --set image.tag=<built-runtime-sha>). Nothing produces that image today, which blocks the deploy configs (deploy#61 skillsmp, deploy#46 forgejo) from actually standing a live MCP up.

There is one generic runtime image (mount-not-bake, ward-mcp#6), so it publishes when the runtime source changes - a push to ward-mcp main - not per guardfile. This is the fleet's source-repo → in-cluster-registry pattern.

What

  • Add a publish job/step (extend .forgejo/workflows/ci.yml or a sibling release workflow): on push to main, build the ward-mcp Dockerfile and push to the in-cluster registry as .../ward-mcp:<sha> (plus :latest if the fleet convention does).
  • Mirror the exact registry host, auth, and tag scheme the existing MCP source repos already use (reddit-mcp / node-stats-mcp / steam-mcp source CI). Do not invent a new one - lunch-money-k8s#23 is the "build on Forgejo CI to the in-cluster registry" convention, and the deploy CD resolves the sha into the chart's image.tag.

Possible infra prerequisite - surface it, do not guess

The other MCP source repos carry a Forgejo CI secret for registry push. ward-mcp is new and may not have it configured yet. If the runner is credential-less (the deploy#38 / #26 "CD cannot resolve a sha for private source repos" class), the workflow is authorable but wiring the registry-push secret is an ops step (configure the Forgejo repo/org secret). If you hit that wall, author the workflow and flag the missing secret in the WARD-OUTCOME rather than working around it.

Done

  • A push to ward-mcp main builds + pushes the runtime image to the in-cluster registry, tagged by sha.
  • The chart's image.repository / image.tag resolve to a real, pullable image.
  • deploy#61 / deploy#46 can then roll a live MCP.

ward-mcp#7 (runtime), #8 (chart), #6 (mount-not-bake - one runtime image), deploy#61 / #46 (the consumers this unblocks), lunch-money-k8s#23 + deploy#38 / #26 (the fleet publish + sha-resolution pattern to mirror).

## Why The runtime (#7) and chart (#8) landed, but ward-mcp's CI (`.forgejo/workflows/ci.yml`) only builds / vets / tests - it does **not** publish the runtime image. The chart's `values.yaml` expects `image.repository: forgejo.coilysiren.me/coilyco-flight-deck/ward-mcp` with `image.tag` supplied at rollout (the skillsmp example: `--set image.tag=<built-runtime-sha>`). Nothing produces that image today, which blocks the deploy configs (deploy#61 skillsmp, deploy#46 forgejo) from actually standing a live MCP up. There is **one** generic runtime image (mount-not-bake, ward-mcp#6), so it publishes when the runtime **source** changes - a push to ward-mcp main - not per guardfile. This is the fleet's source-repo → in-cluster-registry pattern. ## What - Add a publish job/step (extend `.forgejo/workflows/ci.yml` or a sibling release workflow): on push to main, build the ward-mcp `Dockerfile` and push to the in-cluster registry as `.../ward-mcp:<sha>` (plus `:latest` if the fleet convention does). - **Mirror the exact registry host, auth, and tag scheme the existing MCP source repos already use** (reddit-mcp / node-stats-mcp / steam-mcp source CI). Do not invent a new one - lunch-money-k8s#23 is the "build on Forgejo CI to the in-cluster registry" convention, and the deploy CD resolves the sha into the chart's `image.tag`. ## Possible infra prerequisite - surface it, do not guess The other MCP source repos carry a Forgejo CI secret for registry push. ward-mcp is new and may not have it configured yet. If the runner is credential-less (the deploy#38 / #26 "CD cannot resolve a sha for private source repos" class), the workflow is authorable but wiring the registry-push secret is an **ops step** (configure the Forgejo repo/org secret). If you hit that wall, author the workflow and **flag the missing secret in the WARD-OUTCOME** rather than working around it. ## Done - A push to ward-mcp main builds + pushes the runtime image to the in-cluster registry, tagged by sha. - The chart's `image.repository` / `image.tag` resolve to a real, pullable image. - deploy#61 / deploy#46 can then roll a live MCP. ## Related ward-mcp#7 (runtime), #8 (chart), #6 (mount-not-bake - one runtime image), deploy#61 / #46 (the consumers this unblocks), lunch-money-k8s#23 + deploy#38 / #26 (the fleet publish + sha-resolution pattern to mirror).
Member

🔒 Reserved by ward agent --driver claude — container engineer-claude-ward-mcp-9 on host KAI-DESKTOP-TOWER is carrying this issue (reserved 2026-07-07T10:04:27Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).

run seed context — what this run is carrying (ward#609)
  • Resolved: coilyco-flight-deck/ward-mcp#9 · branch issue-9 · driver claude · workflow direct-main
  • Run: engineer-claude-ward-mcp-9 · ward v0.419.0 · dispatched 2026-07-07T10:04:27Z
  • Comment thread: 0 included in the pre-flight read, 0 stripped (ward's own automated comments).

Issue body as seeded:

## Why

The runtime (#7) and chart (#8) landed, but ward-mcp's CI (`.forgejo/workflows/ci.yml`) only builds / vets / tests - it does **not** publish the runtime image. The chart's `values.yaml` expects `image.repository: forgejo.coilysiren.me/coilyco-flight-deck/ward-mcp` with `image.tag` supplied at rollout (the skillsmp example: `--set image.tag=<built-runtime-sha>`). Nothing produces that image today, which blocks the deploy configs (deploy#61 skillsmp, deploy#46 forgejo) from actually standing a live MCP up.

There is **one** generic runtime image (mount-not-bake, ward-mcp#6), so it publishes when the runtime **source** changes - a push to ward-mcp main - not per guardfile. This is the fleet's source-repo → in-cluster-registry pattern.

## What

- Add a publish job/step (extend `.forgejo/workflows/ci.yml` or a sibling release workflow): on push to main, build the ward-mcp `Dockerfile` and push to the in-cluster registry as `.../ward-mcp:<sha>` (plus `:latest` if the fleet convention does).
- **Mirror the exact registry host, auth, and tag scheme the existing MCP source repos already use** (reddit-mcp / node-stats-mcp / steam-mcp source CI). Do not invent a new one - lunch-money-k8s#23 is the "build on Forgejo CI to the in-cluster registry" convention, and the deploy CD resolves the sha into the chart's `image.tag`.

## Possible infra prerequisite - surface it, do not guess

The other MCP source repos carry a Forgejo CI secret for registry push. ward-mcp is new and may not have it configured yet. If the runner is credential-less (the deploy#38 / #26 "CD cannot resolve a sha for private source repos" class), the workflow is authorable but wiring the registry-push secret is an **ops step** (configure the Forgejo repo/org secret). If you hit that wall, author the workflow and **flag the missing secret in the WARD-OUTCOME** rather than working around it.

## Done

- A push to ward-mcp main builds + pushes the runtime image to the in-cluster registry, tagged by sha.

… (truncated to 2000 chars; full body is on this issue)

Static container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.419.0).

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `engineer-claude-ward-mcp-9` on host `KAI-DESKTOP-TOWER` is carrying this issue (reserved 2026-07-07T10:04:27Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. **Do not comment on or edit this issue to steer the run while it is reserved.** The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a **new issue, dispatched fresh** — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494). <details><summary>run seed context — what this run is carrying (ward#609)</summary> - **Resolved:** `coilyco-flight-deck/ward-mcp#9` · branch `issue-9` · driver `claude` · workflow `direct-main` - **Run:** `engineer-claude-ward-mcp-9` · ward `v0.419.0` · dispatched `2026-07-07T10:04:27Z` - **Comment thread:** 0 included in the pre-flight read, 0 stripped (ward's own automated comments). **Issue body as seeded:** ``` ## Why The runtime (#7) and chart (#8) landed, but ward-mcp's CI (`.forgejo/workflows/ci.yml`) only builds / vets / tests - it does **not** publish the runtime image. The chart's `values.yaml` expects `image.repository: forgejo.coilysiren.me/coilyco-flight-deck/ward-mcp` with `image.tag` supplied at rollout (the skillsmp example: `--set image.tag=<built-runtime-sha>`). Nothing produces that image today, which blocks the deploy configs (deploy#61 skillsmp, deploy#46 forgejo) from actually standing a live MCP up. There is **one** generic runtime image (mount-not-bake, ward-mcp#6), so it publishes when the runtime **source** changes - a push to ward-mcp main - not per guardfile. This is the fleet's source-repo → in-cluster-registry pattern. ## What - Add a publish job/step (extend `.forgejo/workflows/ci.yml` or a sibling release workflow): on push to main, build the ward-mcp `Dockerfile` and push to the in-cluster registry as `.../ward-mcp:<sha>` (plus `:latest` if the fleet convention does). - **Mirror the exact registry host, auth, and tag scheme the existing MCP source repos already use** (reddit-mcp / node-stats-mcp / steam-mcp source CI). Do not invent a new one - lunch-money-k8s#23 is the "build on Forgejo CI to the in-cluster registry" convention, and the deploy CD resolves the sha into the chart's `image.tag`. ## Possible infra prerequisite - surface it, do not guess The other MCP source repos carry a Forgejo CI secret for registry push. ward-mcp is new and may not have it configured yet. If the runner is credential-less (the deploy#38 / #26 "CD cannot resolve a sha for private source repos" class), the workflow is authorable but wiring the registry-push secret is an **ops step** (configure the Forgejo repo/org secret). If you hit that wall, author the workflow and **flag the missing secret in the WARD-OUTCOME** rather than working around it. ## Done - A push to ward-mcp main builds + pushes the runtime image to the in-cluster registry, tagged by sha. ``` … (truncated to 2000 chars; full body is on this issue) Static container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.419.0). </details> <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Owner

WARD-OUTCOME: done - CI now builds the ward-mcp Dockerfile on push-to-main and pushes 192.168.0.194:30500/ward-mcp: to the in-cluster registry.

Retro: this one turned out cleaner than the issue's framing feared. The "possible infra prerequisite" (a registry-push secret) is a non-issue for this pattern - I pulled the actual reddit-mcp build-publish.yml off Forgejo and it pushes plain-http to the insecure in-cluster registry (--insecure-registry on the DinD sidecar), so there's no docker login and no secret to provision. The agentic-os publish-image job was a red herring: it pushes to the Forgejo OCI registry with a REGISTRY_TOKEN, which is a different registry than the 192.168.0.194:30500 one the deploy rollout.sh actually checks. Reading rollout.sh nailed down the tag scheme: sha only, no :latest (rollouts key by sha).

The one thing that fought back was finding the reference: reddit-mcp/node-stats-mcp aren't in /substrate, so I had to hit the Forgejo API to locate the workflow (build-publish.yml, not ci.yml) and read it raw. Mirrored it verbatim onto ward-mcp's existing go gate, scoped to push-to-main.

Confidence is high on structure since it's a byte-level copy of a known-green fleet workflow, adjusted only for the image name and the go/GOPRIVATE build. The unproven bit is the first live run - I couldn't exercise the DinD-host probe or the actual registry push from here. Worth a glance at the first main-push Actions run to confirm the image lands; if the runner env differs from reddit-mcp's, the host-probe step is where it'd show. No follow-ups needed unless that first run surfaces something.

WARD-OUTCOME: done - CI now builds the ward-mcp Dockerfile on push-to-main and pushes 192.168.0.194:30500/ward-mcp:<sha> to the in-cluster registry. Retro: this one turned out cleaner than the issue's framing feared. The "possible infra prerequisite" (a registry-push secret) is a non-issue for this pattern - I pulled the actual reddit-mcp `build-publish.yml` off Forgejo and it pushes plain-http to the insecure in-cluster registry (`--insecure-registry` on the DinD sidecar), so there's no `docker login` and no secret to provision. The agentic-os `publish-image` job was a red herring: it pushes to the Forgejo OCI registry with a REGISTRY_TOKEN, which is a different registry than the `192.168.0.194:30500` one the deploy `rollout.sh` actually checks. Reading rollout.sh nailed down the tag scheme: sha only, no `:latest` (rollouts key by sha). The one thing that fought back was finding the reference: reddit-mcp/node-stats-mcp aren't in /substrate, so I had to hit the Forgejo API to locate the workflow (`build-publish.yml`, not `ci.yml`) and read it raw. Mirrored it verbatim onto ward-mcp's existing go gate, scoped to push-to-main. Confidence is high on structure since it's a byte-level copy of a known-green fleet workflow, adjusted only for the image name and the go/GOPRIVATE build. The unproven bit is the first live run - I couldn't exercise the DinD-host probe or the actual registry push from here. Worth a glance at the first main-push Actions run to confirm the image lands; if the runner env differs from reddit-mcp's, the host-probe step is where it'd show. No follow-ups needed unless that first run surfaces something.
Sign in to join this conversation.
No description provided.