ci: add GHCR release workflow using the TES/RAG BuildKit-secret pattern - #11
Merged
Conversation
HIPAA PR3b GHCR follow-up: closes the API Gateway release-mechanism gap
identified in the prior read-only investigation. This repo's Dockerfile
previously required the *parent* directory as its build context (COPY
omnibioai-iam-client /tmp/...), which no GitHub Actions workflow in this
org has ever been able to do for a private sibling repository -- exactly
why this repo had zero working publish automation despite one image
having been pushed manually, once, over a month ago.
Dockerfile: adopts the exact pattern already proven in production by
omnibioai-tes and omnibioai-rag instead of inventing a new one.
omnibioai-iam-client is now a pinned git+https dependency declared in
pyproject.toml, installed via `pip install .` inside a
`RUN --mount=type=secret,id=github_token` layer -- never ARG/ENV, which
would leak the token into BuildKit's build-log output for that layer; a
secret mount is never printed and never persists in any image layer,
confirmed directly (docker history + an in-container filesystem search
for both the secret mount path and any leftover git-config rewrite found
neither). Build context is now `.` alone. git added to apt-get (required
for pip's own git+https clone; the old raw-COPY approach never needed
it).
pyproject.toml: omnibioai-iam-client @ git+https://.../omnibioai-iam-client.git@v0.1.3,
same pinned-tag convention and version as TES/RAG's own entries for this
exact dependency. Additionally required: [tool.hatch.metadata]
allow-direct-references = true -- hatchling's own metadata validation
otherwise rejects any `name @ <url>` dependency outright ("cannot be a
direct reference unless..."). TES and RAG never needed this because both
are setuptools-backed, not hatchling; this repo's own [build-system]
already was, so this is a required fix, not a style choice -- discovered
by an actual failing local build before it was added, not assumed.
requirements.txt is intentionally left untouched (unrelated to this
build's dependency resolution now, but not removed without being asked).
.github/workflows/ci.yml (new): single docker-publish job, modeled on
omnibioai-security-audit's own tag-gated `docker` job. Triggers on push
to main, v*.*.* tags, and workflow_dispatch; the job itself only runs for
a real tag or an explicit manual dispatch (matches that repo's own
tag-gating, so an ordinary push to main never publishes). Least-privilege
permissions (contents: read, packages: write) -- nothing else. Publishes
ghcr.io/omnibioai/omnibioai-api-gateway with three tags: latest, the
semver from the pushed tag, and an immutable short commit SHA
(sha-<short>) -- this org's convention has never included the SHA tag
before; added because every prior GHCR-content-verification step in this
whole workstream had to fall back to manual docker-cp archaeology for
lack of one. IAM_CLIENT_READ_TOKEN is referenced as a BuildKit secret
(never a build arg/env var) but is NOT created, assumed present, or
guessed at here -- if missing, the workflow will fail cleanly at the
Dockerfile's private-dependency install step, which is an intentional,
visible configuration gap, not something this change works around.
Validation performed (local only, nothing pushed):
- YAML parses cleanly.
- Full local BuildKit build using GHCR_PULL_TOKEN, already present in
omnibioai-studio's .env for this exact purpose (the same credential
omnibioai-tes/omnibioai-rag's own local dev builds already use) --
passed via --secret id=github_token,env=GHCR_PULL_TOKEN (never on the
command line, never in argv, never printed). First attempt failed on
the hatchling allow-direct-references gap above; fixed; second and
third builds (after a later comment-only Dockerfile edit) both
succeeded, producing a working image. Container boot-tested:
GET /health -> 200 {"status":"ok"}. Local image and container removed
after validation.
- git diff --check clean; docker history and an in-image filesystem
search both confirm no credential value anywhere in the built image.
- Full existing test suite: 199 passed, 4 pre-existing failures
(test_iam_client.py cache-key-prefix bug, unrelated, reproduced
identically on main before this branch).
Not done here, deliberately: no tag pushed, no image published, no
secret created, no other repository touched.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Blocked by #12 — API Gateway GHCR publish is blocked because
IAM_CLIENT_READ_TOKENis not currently available to the GitHub Actions workflow.Problem
This repo has never had working GHCR publish automation. Its Dockerfile required the parent directory as build context (
COPY omnibioai-iam-client /tmp/...) — a private sibling repo — and no GitHub Actions workflow anywhere in this org has ever solved cross-repo private checkout. The one published image (latest, 2026-07-10) was pushed manually, once, and now predates the merged PR3b signing code (#10) by over a month.Fix
Adopts the exact pattern already proven in production by
omnibioai-tesandomnibioai-rag— no new mechanism invented:omnibioai-iam-clientis now a pinnedgit+httpsdependency (pyproject.toml), installed viapip install .inside aRUN --mount=type=secret,id=github_tokenlayer. Build context is.alone. NeverARG/ENV(those leak into build logs).omnibioai-iam-client@v0.1.3, matching TES/RAG's own entries. Also adds[tool.hatch.metadata] allow-direct-references = true— required because this repo (unlike TES/RAG, both setuptools-backed) useshatchling, which otherwise rejects direct-reference dependencies outright. Discovered by an actual failing local build, not assumed..github/workflows/ci.yml(new): single docker-publish job modeled onomnibioai-security-audit's own tag-gated job. Triggers on push tomain,v*.*.*tags, andworkflow_dispatch; the job itself only runs for a real tag or manual dispatch.contents: read+packages: writeonly. Publisheslatest, the semver tag, and (new to this org) an immutablesha-<short>tag.IAM_CLIENT_READ_TOKENis referenced as a BuildKit secret but not created, assumed present, or guessed at. If missing, the workflow fails cleanly at the private-dependency install step — an intentional, visible gap, not something worked around here.Validation (local only — nothing pushed)
GHCR_PULL_TOKENalready inomnibioai-studio/.envfor this exact purpose (same credential TES/RAG's own local builds use), passed via--secret id=github_token,env=GHCR_PULL_TOKEN— never on the command line. First attempt failed on the hatchling gap above; fixed; rebuild succeeded. Container boot-tested:GET /health→200 {"status":"ok"}. Local image/container removed after.docker history+ an in-image filesystem search both confirm no credential value anywhere in the built image.test_iam_client.pycache-key-prefix bug, unrelated, reproduced identically onmain).Not done here
No tag pushed, no image published, no secret created/modified, no other repository touched.
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com