Repository navigation
ci: publish cbioportal/mcp:beta on pushes to beta (main) - #157
Merged
Merged
Conversation
Add `beta` to the push trigger and tag images built from a beta push as `beta` in both the build and merge jobs, so a beta push never produces or overwrites `latest`. main pushes still publish `latest` and workflow_dispatch still tags with the provided ref. Any other trigger now fails the tag step instead of silently defaulting to `latest`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: omnigent <noreply@omnigent.ai>
Stop interpolating github.event.inputs.ref / event_name / ref_name into the tag-step run scripts; pass them as INPUT_REF / EVENT_NAME / REF_NAME env vars instead. Validate a dispatched ref as a Docker tag before writing it to $GITHUB_ENV (rejects newlines and shell metacharacters), and quote $IMAGE_TAG in the imagetools create/inspect commands instead of interpolating env.IMAGE_TAG. Scope the GHA build cache per image tag so beta and main builds don't evict each other. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: omnigent <noreply@omnigent.ai>
The grep -Eqx guard anchored per line, so a ref like "v1<newline>IMAGE_TAG=latest" passed (first line is tag-shaped) and the extra line was written into $GITHUB_ENV, publishing :latest or injecting arbitrary env vars. Replace it in both tag steps with a bash [[ =~ ]] whole-string match, pin those steps to `shell: bash`, and set LC_ALL=C so the [A-Za-z] ranges are ASCII-only. Also clarify the dispatch input description (Docker tag / ref, no slashes) and drop the unreferenced `id: set-tag`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: omnigent <noreply@omnigent.ai>
Collaborator
Author
|
@inodb how have you been publishing to beta chat? wanted to make sure that I'm not doing something redundant. |
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.
What changed
.github/workflows/docker_ci.ymlonly. #157 (basemain) and #158 (basebeta) contain the same change from the same head branch.Beta tag
betatoon.push.branches.buildmatrix job and themergejob), apushtobetasetsIMAGE_TAG=beta.pushtomainstill setsIMAGE_TAG=latest.workflow_dispatchwith a validrefstill tags with that ref.exit 1) instead of falling back tolatest. That includes aworkflow_dispatchwith an emptyref, which used to publish:latestand now errors.refisrequired: truein the dispatch UI, so this only matters for API or CLI dispatches that pass an empty string.Script-injection hardening (the first sink predates this PR)
github.event.inputs.ref,github.event_nameandgithub.ref_nameare no longer interpolated with${{ }}insiderun:scripts. They're passed asINPUT_REF/EVENT_NAME/REF_NAMEenv vars and used as quoted"$VAR". This closes the pre-existing sink, where a dispatcher could inject shell viarefon a runner that holdsDOCKER_PASSWORD.refmust match^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$as one whole string, using bash[[ =~ ]], before it's written to$GITHUB_ENV. Both tag steps are pinned toshell: bashand setLC_ALL=C, so the character ranges are ASCII-only.grep -Eqxguard from an earlier commit on this branch (4a6d2c1). That guard was bypassable:grep -xanchors each line, sov1<newline>IMAGE_TAG=latestpassed and published:latest, andv1<newline>INJECTED=1wroteINJECTED=1into$GITHUB_ENV. The whole-string match rejects both (see the table below)./(e.g.feature/foo) were never valid Docker tags. Before, they failed late atimagetools create; now they fail at the tag step. The input description now says "Docker tag / ref (no slashes)".imagetools createandinspectcommands use a quoted"$IMAGE_TAG"instead of interpolating${{ env.IMAGE_TAG }}.id: set-tag.Build cache
${PLATFORM_PAIR}-${IMAGE_TAG}, so beta and main builds don't evict each other's cache. The first build on each tag after merge will be a cold build.Why
#151–#156 now target
betaso they can roll out to beta only. A push tobetahas to publishcbioportal/mcp:betaand must never produce or overwritecbioportal/mcp:latest. A push tobetaruns the workflow file on thebetabranch, so the change is needed on bothmainandbeta.Prod impact (read before merging)
main, so it rebuilds and republishescbioportal/mcp:latestwith a new digest.docker/DockerfilerunsCOPY . /appand the repo has no.dockerignore, so this workflow file is part of the build context and the image changes. The server code in the image is byte-identical, but Keel will see the new:latestdigest and roll the prod MCP pods. Merge when a routine pod restart is acceptable.beta. It publishes:betaonly and never touches:latest.mainpushes publish:latestas before and laterbetapushes publish:betaonly.Verification
python3 -c "import yaml; yaml.safe_load(open('.github/workflows/docker_ci.yml'))"parses.docker run --rm -v "$PWD":/repo -w /repo rhysd/actionlint:1.7.12 -no-color -oneline .github/workflows/docker_ci.yml(with shellcheck 0.11.0) reports two issues, both in lines this PR doesn't touch:actions/checkout@v3is too old$(printf 'cbioportal/mcp@sha256:%s ' *). The word splitting there is intentional.shell: bashand no${{in the body. Each body is written to a file and run the way GHA runsshell: bash, i.e.bash --noprofile --norc -eo pipefail <file>, withINPUT_REF/EVENT_NAME/REF_NAME/LC_ALL=Cset and a temporary$GITHUB_ENV.IMAGE_TAG=line (plusPLATFORM_PAIRinbuild) and rejected cases exit non-zero and write nothing.python:3.12) and macOS bash 3.2.57: 34/34 pass (17 cases × 2 jobs).latestIMAGE_TAG=latestbetaIMAGE_TAG=betav1IMAGE_TAG=v1v1.2.3IMAGE_TAG=v1.2.3feature-mcp-appsmainIMAGE_TAG=main$GITHUB_ENVemptyv1\nINJECTED=1$GITHUB_ENVemptyv1\nIMAGE_TAG=latest$GITHUB_ENVemptyv1\n(trailing newline)$GITHUB_ENVemptyfeature/foo$GITHUB_ENVempty$(id)$GITHUB_ENVempty`id`$GITHUB_ENVemptyx"; echo PWNED; "$GITHUB_ENVempty, noPWNEDoutput$GITHUB_ENVemptyRegression check: the same harness run against the previous
grep -Eqxguard (4a6d2c1) fails 6 checks: the three newline cases × 2 jobs. For example,v1\nIMAGE_TAG=latestexits 0 and writes['IMAGE_TAG=v1', 'IMAGE_TAG=latest'], which confirms the bypass and shows the harness catches it.Open follow-ups (not in this PR)
latestas a dispatch ref. A dispatcher can still passref=latestand overwrite:latestfrom any branch. That was already true before this PR and is left as-is here.concurrencygroup. Two quick pushes to the same branch can race in the merge job, and the older run could tag last.🤖 Generated with Claude Code