ci(checks): publish quoter-bot image to docker hub on release - #158
Conversation
A release-quoter-bot production run now also pushes the bot image to Docker Hub as morphoorg/quoter, tagged with the release commit hash and latest, in parallel with the Railway deploy and gating neither the deploy nor the GitHub release. Auth exchanges the run's GitHub OIDC token through the Docker org's OIDC connection (docker/login-action v4.5+), scoped by the quoter-bot-dockerhub GitHub Environment, so CI stores no static Docker Hub credential. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@codex review |
Address Codex review on #158: - Split the Dockerfile into build + runtime stages so the published image ships only the bot's self-contained esbuild bundle — no other bot's code, workspace source, node_modules, or pnpm. Verified locally: entrypoint --version runs through setpriv, /repo holds only bots/quoter-bot/{dist,package.json}, image is 347MB. - Document that the OIDC token's sub claim is environment-based (repo:...:environment:quoter-bot-dockerhub) because the job references an environment; a branch-style Docker ruleset would reject every exchange. - Clarify sha-tag semantics: the tag names the commit; reruns rebuild with current base layers. Point at Docker Hub immutable tags for byte-level freezing instead of a skip-if-exists guard, which would break reruns after transient push failures. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. Can't wait for the next one! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
The privileged-startup test encoded the single-stage Dockerfile shape (USER node then USER root) and crashed on the new two-stage split. It now asserts the build stage runs all workspace installs/builds after USER node, and the runtime stage equals exactly the eight instructions that ship the bot bundle behind the root-owned setpriv entrypoint — so any attempt to COPY workspace source or add a package manager to the public image fails the suite. Verified: injecting a workspace COPY fails the test; the committed Dockerfile passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fail closed when the Docker Hub commit-SHA tag already exists and document the immutable publish contract.
|
@codex review |
1 similar comment
|
@codex review |
Codex flagged that rerunning an older release's publish job (one that failed before pushing its commit tag) passes the new SHA-existence guard and would drag Docker Hub latest backward. Gate latest on the pipeline's own release record: skip it whenever a quoter-bot-* release tag descends from the built commit. Release runs are serialized, so the newest release cannot change mid-run. Verified against real repo data: branch HEAD yields sha+latest; a commit behind quoter-bot-2026.08.14-1 yields sha only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@codex review |
|
@codex review |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
Authenticate before checking immutable Docker Hub tags so first publication can proceed, and force runtime bundle files to remain root-owned and non-writable.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3bed72e359
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Reuse an existing immutable SHA image when recovering the latest tag, and publish Docker Hub tags only after the Railway deployment succeeds.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4b0c2a764e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Wait for the quoter GitHub release record before publishing Docker image tags, while keeping the release independent from Docker Hub.
|
@codex review |
|
Codex Review: Didn't find any major issues. 🚀 Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
|
@codex review |
The caller job now needs both the deploy and release-tag jobs; the TIB diagram still drew the image push parallel to the release. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep it up! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
|
@prd-carapulse[bot] review and approve if ok |
|
❌ Not approved. Requested changes on • Blocker: • Code/CI: Clean. Lint, Typecheck, Test, and Dead-Code green. Targeted suite passes locally: 18/18. • Review: #158 (review) |
There was a problem hiding this comment.
Blocking operational security gap: the live quoter-bot-dockerhub environment currently reports deployment_branch_policy: null and no protection rules, so it is not restricted to main. Because the Docker OIDC trust subject is environment-based (repo:morpho-org/morpho-bots:environment:quoter-bot-dockerhub) rather than ref-based, the documented main-only environment policy is the control preventing another branch workflow from minting an accepted token and pushing morphoorg/quoter.
Please restrict the environment deployment branches to main, then re-request approval. Code review otherwise clean: current-head CI is green and the targeted Railway/Dockerfile contract suite passes locally (18/18).
|
@prd-carapulse re-requesting approval: the 🤖 Addressed by Claude Code |
|
@prd-carapulse[bot] and now |
|
❌ Still not approved. • Blocker: • Required fix: Remove • Code/CI: Head |
There was a problem hiding this comment.
Still blocked: live quoter-bot-dockerhub policy is not main-only. The API currently returns two allow rules: branch main and tag quoter-bot-* (total_count: 2). By contrast, quoter-bot-production has exactly one rule: branch main.
Because deploy-production.yml supports workflow_dispatch, a run can be dispatched against an allowed quoter-bot-* tag. The publish job then receives the same environment-based OIDC subject, so the tag rule keeps Docker Hub token exchange reachable outside refs/heads/main.
Please remove the quoter-bot-* tag policy from quoter-bot-dockerhub, leaving only branch main, then re-request approval. Current head 51d84c4cde and all checks remain green.
|
@prd-carapulse[bot] now |
|
✅ Approved • Live environment policy now allows exactly branch |
|
@prd-carapulse re-requesting approval: the 🤖 Addressed by Claude Code |
Fixes MKT-1846
Why
quoter-bot is the public reference maker bot, but no public artifact of a release exists today: Railway builds the image internally from uploaded source, so third-party operators must build from source and there is no image record of what a release shipped. This PR publishes
morphoorg/quoterto Docker Hub on every quoter-bot production release — tagged with the release commit hash (a stable, greppable mapping from image to source, also stamped as OCIrevision/sourcelabels) pluslatest.Four properties drove the design, recorded in TIB-2026-08-14-quoter-bot-dockerhub-publishing:
docker/login-actionv4.5+):id-token: write, username-only login, connection selected byDOCKERHUB_OIDC_CONNECTIONID. The trust binding (which claims may push) lives in Docker-side rulesets, not in a long-lived secret. The exchanged token's expiry is raised to 1800s because the default 300s is shorter than the workspace build that runs between login and push.buildstage and a runtime stage that receives nothing but the bot's self-contained esbuild bundle and manifest, root-owned and non-writable to the runtime user — publishing publicly must not leak the liquidators' or crossed-books source, workspace internals, or a package manager. Railway builds the same final stage, so the deployed image slims down identically (verified locally: the setpriv entrypoint runs cleanly,/repoholds onlybots/quoter-bot/{dist,package.json}atroot root 555, and a write attempt as the runtime user is denied). The privileged-startup guard test encodes this contract — adding a workspace COPY or a package manager to the runtime stage fails the suite.Quoter-bot-imageneeds the Railway deploy and the release-tag job, so no image tag can publish for a failed deployment — whileRelease-quoter-botstill depends only on the deploy, so a Docker Hub outage cannot block a production release. The samerelease-quoter-botselector (including theworkflow_dispatchpath) remains the single entry point, and the GitHub release stays the source of truth for what runs in production.latestby manifest retag.latestonly moves forward — a rerun of an older release backfills its commit tag but skipslatestwhenever aquoter-bot-*release tag descends from the built commit (the pipeline's own release record decides "newest", and release runs are serialized). Hardening contributed together withprd-carapulse[bot].The publish job is a reusable
workflow_callworkflow scoped by thequoter-bot-dockerhubGitHub Environment, mirroring the existing per-concern environment pattern (deploy-quoter-bot-production.yml/quoter-bot-production).Operator checklist (environment assumptions)
quoter-bot-dockerhubenvironment holds secretDOCKERHUB_OIDC_CONNECTIONIDand variablesDOCKER_USERNAME(morphoorg) /DOCKER_REPOSITORY(quoter) — a fail-loud preflight step reports exactly which value is missing if that split differs.repo:morpho-org/morpho-bots:environment:quoter-bot-dockerhub— because the job references a GitHub Environment, GitHub mints the token with an environmentsubclaim, and aref:refs/heads/main-style ruleset would reject every exchange.main; that is where branch enforcement lives.morphoorg/quoteris optional belt-and-braces: the workflow already never rebuilds an existing commit tag and never moveslatestbackward.🤖 Generated with Claude Code