Phase 3 step 4: build pipeline OCI labels + atomic pin update — internal#229 §X step 4 #554

Closed
opened 2026-05-11 19:33:25 +00:00 by hongming · 2 comments
Owner

Parent RFC: internal#229 §X amendment (Phase 2 design).

Implements step 4 of §6 sequencing — build pipeline produces images carrying full provenance + atomically updates the CP pin.

Parallelizable with steps 1 (molecule-controlplane#130) and 2 (operator-config issue). Becomes useful once step 1 ships in log-only mode — the new builds get a green verifier outcome immediately, and the dataset for step 3 (backfill) is bounded to pre-existing pins.

Scope (this tracker issue)

This is the umbrella; expect 2–4 sub-PRs touching workflow YAML in different repos. Each sub-PR is independently reviewable.

PR-1: molecule-ai/molecule-core.gitea/workflows/publish-workspace-server-image.yml + publish-runtime.yml

Add to the buildx step:

- name: build + label + push
  run: |
    docker buildx build \
      --tag "${REGISTRY}/${REPO}:staging-${GITHUB_SHA}" \                  # FULL 40-char SHA
      --tag "${REGISTRY}/${REPO}:staging-$(date -u +%Y%m%dT%H%M)" \
      --label "org.opencontainers.image.source=https://git.moleculesai.app/molecule-ai/${REPO}" \
      --label "org.opencontainers.image.revision=${GITHUB_SHA}" \
      --label "org.opencontainers.image.created=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
      --label "molecule.workflow.run_id=${GITHUB_RUN_ID}" \
      --push .

- name: capture digest + update CP pin atomically
  run: |
    DIGEST=$(docker buildx imagetools inspect "${REGISTRY}/${REPO}:staging-${GITHUB_SHA}" --format '{{.Manifest.Digest}}')
    echo "::notice::published digest=${DIGEST}"
    curl -fSs -X POST \
      -H "Authorization: Bearer ${{ secrets.CP_ADMIN_API_TOKEN }}" \
      -H "Content-Type: application/json" \
      -d "{\"runtime\":\"workspace-server\",\"digest\":\"${DIGEST}\",\"source_sha\":\"${GITHUB_SHA}\"}" \
      "${{ vars.CP_URL }}/cp/admin/runtime-image-pins"

Pre-req on CP side: POST /cp/admin/runtime-image-pins endpoint must accept this payload. Today the table is updated manually. File a sub-issue on molecule-controlplane for this endpoint if it doesn't exist yet.

PR-2: molecule-ai/molecule-ai-workspace-template-* (9 template repos) — .gitea/workflows/publish-image.yml

Same shape, adjusted for template image conventions. Coordinate as one PR per repo or bundle via mirror script. The 9 repos:

  • molecule-ai-workspace-template-claude-code
  • molecule-ai-workspace-template-hermes
  • molecule-ai-workspace-template-langgraph
  • molecule-ai-workspace-template-autogen
  • molecule-ai-workspace-template-codex
  • molecule-ai-workspace-template-crewai
  • molecule-ai-workspace-template-deepagents
  • molecule-ai-workspace-template-gemini-cli
  • molecule-ai-workspace-template-openclaw

PR-3 (sub-issue on molecule-controlplane): POST /cp/admin/runtime-image-pins endpoint that takes {runtime, digest, source_sha} and upserts the row.

Acceptance criteria (DoD)

  1. One full publish→pin cycle on staging:
    • Push a no-op commit to molecule-core/staging
    • Workflow fires, builds image with labels
    • docker buildx imagetools inspect <digest> shows all 4 labels
    • CP runtime_image_pins row updated with new digest + source_sha = commit SHA
    • Trigger redeploy on staging-cplead tenant — CP#130's verifier emits redeploy.verify.reachable (because new image has labels AND SHA resolves on Gitea)
  2. Five-Axis review (security lens: CP_ADMIN_API_TOKEN must come from Gitea secret, not be echoed; CP_URL is a non-secret repo variable)
  3. Per-repo PR template includes link back to this issue + RFC#229 §X

Out of scope

  • Removing :latest tag from publish step — that's step 6 of the RFC sequencing.
  • Backfilling existing pins with source_sha — that's step 3.
  • The CP enforcement-mode flip — that's step 5.

Five-Axis review lens (per sub-PR)

  • Correctness: GITHUB_SHA is the full 40-char from the workflow env (verify in YAML linter). docker buildx imagetools inspect digest format matches what CP stores (sha256:).
  • Security: CP_ADMIN_API_TOKEN exposure on failure logs — pipe through mask: if Gitea Actions supports it; otherwise scope the curl to a step with continue-on-error: false + no extra logging.
  • Architecture: Pipeline-writes-pin is the seam this RFC closes. If a publish succeeds but the pin update fails, the workflow should fail loudly (no silent drift). curl -fSs ensures non-2xx exits non-zero.
  • Performance: Pin update is a single POST; trivial.
  • Readability: The 4 OCI labels follow the OCI image-spec annotations — standard names, no proprietary fields except molecule.workflow.run_id.

DRI: core-devops. Effort estimate: ~1 day across all sub-PRs.

**Parent RFC:** [internal#229 §X amendment](https://git.moleculesai.app/molecule-ai/internal/issues/229#issuecomment-12538) (Phase 2 design). Implements **step 4 of §6 sequencing** — build pipeline produces images carrying full provenance + atomically updates the CP pin. Parallelizable with steps 1 ([molecule-controlplane#130](https://git.moleculesai.app/molecule-ai/molecule-controlplane/issues/130)) and 2 (operator-config issue). Becomes useful once step 1 ships in log-only mode — the new builds get a green verifier outcome immediately, and the dataset for step 3 (backfill) is bounded to pre-existing pins. ## Scope (this tracker issue) This is the umbrella; expect 2–4 sub-PRs touching workflow YAML in different repos. Each sub-PR is independently reviewable. **PR-1: `molecule-ai/molecule-core` — `.gitea/workflows/publish-workspace-server-image.yml` + `publish-runtime.yml`** Add to the `buildx` step: ```yaml - name: build + label + push run: | docker buildx build \ --tag "${REGISTRY}/${REPO}:staging-${GITHUB_SHA}" \ # FULL 40-char SHA --tag "${REGISTRY}/${REPO}:staging-$(date -u +%Y%m%dT%H%M)" \ --label "org.opencontainers.image.source=https://git.moleculesai.app/molecule-ai/${REPO}" \ --label "org.opencontainers.image.revision=${GITHUB_SHA}" \ --label "org.opencontainers.image.created=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ --label "molecule.workflow.run_id=${GITHUB_RUN_ID}" \ --push . - name: capture digest + update CP pin atomically run: | DIGEST=$(docker buildx imagetools inspect "${REGISTRY}/${REPO}:staging-${GITHUB_SHA}" --format '{{.Manifest.Digest}}') echo "::notice::published digest=${DIGEST}" curl -fSs -X POST \ -H "Authorization: Bearer ${{ secrets.CP_ADMIN_API_TOKEN }}" \ -H "Content-Type: application/json" \ -d "{\"runtime\":\"workspace-server\",\"digest\":\"${DIGEST}\",\"source_sha\":\"${GITHUB_SHA}\"}" \ "${{ vars.CP_URL }}/cp/admin/runtime-image-pins" ``` **Pre-req on CP side:** `POST /cp/admin/runtime-image-pins` endpoint must accept this payload. Today the table is updated manually. File a sub-issue on `molecule-controlplane` for this endpoint if it doesn't exist yet. **PR-2: `molecule-ai/molecule-ai-workspace-template-*` (9 template repos) — `.gitea/workflows/publish-image.yml`** Same shape, adjusted for template image conventions. Coordinate as one PR per repo or bundle via mirror script. The 9 repos: - `molecule-ai-workspace-template-claude-code` - `molecule-ai-workspace-template-hermes` - `molecule-ai-workspace-template-langgraph` - `molecule-ai-workspace-template-autogen` - `molecule-ai-workspace-template-codex` - `molecule-ai-workspace-template-crewai` - `molecule-ai-workspace-template-deepagents` - `molecule-ai-workspace-template-gemini-cli` - `molecule-ai-workspace-template-openclaw` **PR-3 (sub-issue on molecule-controlplane):** `POST /cp/admin/runtime-image-pins` endpoint that takes `{runtime, digest, source_sha}` and upserts the row. ## Acceptance criteria (DoD) 1. One full publish→pin cycle on staging: - Push a no-op commit to `molecule-core/staging` - Workflow fires, builds image with labels - `docker buildx imagetools inspect <digest>` shows all 4 labels - CP `runtime_image_pins` row updated with new digest + `source_sha` = commit SHA - Trigger redeploy on `staging-cplead` tenant — CP#130's verifier emits `redeploy.verify.reachable` (because new image has labels AND SHA resolves on Gitea) 2. Five-Axis review (security lens: `CP_ADMIN_API_TOKEN` must come from Gitea secret, not be echoed; `CP_URL` is a non-secret repo variable) 3. Per-repo PR template includes link back to this issue + RFC#229 §X ## Out of scope - Removing `:latest` tag from publish step — that's step 6 of the RFC sequencing. - Backfilling existing pins with `source_sha` — that's step 3. - The CP enforcement-mode flip — that's step 5. ## Five-Axis review lens (per sub-PR) - **Correctness:** `GITHUB_SHA` is the full 40-char from the workflow env (verify in YAML linter). `docker buildx imagetools inspect` digest format matches what CP stores (`sha256:`). - **Security:** `CP_ADMIN_API_TOKEN` exposure on failure logs — pipe through `mask:` if Gitea Actions supports it; otherwise scope the curl to a step with `continue-on-error: false` + no extra logging. - **Architecture:** Pipeline-writes-pin is the seam this RFC closes. If a publish succeeds but the pin update fails, the workflow should fail loudly (no silent drift). `curl -fSs` ensures non-2xx exits non-zero. - **Performance:** Pin update is a single POST; trivial. - **Readability:** The 4 OCI labels follow the [OCI image-spec annotations](https://github.com/opencontainers/image-spec/blob/main/annotations.md) — standard names, no proprietary fields except `molecule.workflow.run_id`. DRI: `core-devops`. Effort estimate: ~1 day across all sub-PRs.
core-devops was assigned by hongming 2026-05-11 19:33:32 +00:00
Member

PR #559 implements PR-1 (OCI labels + buildx) for both platform and tenant images. Part 2 (atomic CP pin update via POST /cp/admin/runtime-image-pins) remains open — depends on the CP endpoint being available (PR-3 sub-issue on molecule-controlplane).

PR #559 implements PR-1 (OCI labels + buildx) for both platform and tenant images. Part 2 (atomic CP pin update via POST /cp/admin/runtime-image-pins) remains open — depends on the CP endpoint being available (PR-3 sub-issue on molecule-controlplane).
triage-operator added the tier:medium label 2026-05-11 20:20:15 +00:00
Member

Phase 3 step 4 OCI labels merged in PR #559 (commit 815dc7e1). Closing.

Phase 3 step 4 OCI labels merged in PR #559 (commit 815dc7e1). Closing.
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-core#554