mirror of
https://github.com/block/buzz.git
synced 2026-11-10 11:21:05 +00:00
ci(docker): skip relay image publishes for main pushes outside the build context (#9310)
## Summary Every push to `main` published a new relay and push gateway image, even when it only changed `desktop/`, `mobile/`, `docs/` or other paths `.dockerignore` keeps out of the Docker build context. Deployments that track the sortable `main-<commit UTC>-<7>` tag then rolled their relays onto an image built from identical inputs. The `push` trigger now skips the directories excluded from the build context (`desktop/`, `mobile/`, `docs/`, `bin/`, `sidecars/`, `.github/`) and re-includes `.github/workflows/docker.yml`, which defines the build. Tag pushes (`relay-v*`) still always publish, because GitHub does not evaluate path filters for tag pushes. Pull request builds keep their existing allowlist. ## Guard `scripts/test-relay-image-eligibility-workflow.sh`, which `ci.yml` runs, now requires the push filter to be exactly, in order: 1. `"**"`, 2. only `"!<dir>/**"` exclusions, each also listed in `.dockerignore`, 3. the `.github/workflows/docker.yml` re-inclusion. Comment and blank lines inside the list are skipped rather than ending it. So nobody can add a file exclusion, exclude a directory Docker sees, or reorder the re-inclusion in a way that hides a change to the image. ## Testing - `scripts/test-relay-image-eligibility-workflow.sh` passes. - The guard fails with a specific message for each of these: `"!crates/**"` added, `"!Cargo.lock"` added, single-quoted `'!Cargo.lock'`, the re-inclusion moved before `"!.github/**"`, `"**"` removed, and `"!crates/**"` appended after a comment or a blank line. - `actionlint` passes on `docker.yml`. ## Simpler The image is published only when its inputs can change. This removes no-op staging rollouts, plus the cancelled or queued Docker runs that each merge to main caused. No new concepts: the filter reuses `.dockerignore` as the only definition of what the image sees. Identified follow-up: root-level Markdown (for example `README.md`) is in the build context, so root-docs-only merges still publish. Skipping them would need a `.dockerignore` entry and a file-level filter rule, which the guard currently rejects on purpose. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Luke Tornquist <tornquist@squareup.com> Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
19
.github/workflows/docker.yml
vendored
19
.github/workflows/docker.yml
vendored
@@ -17,7 +17,8 @@ name: Docker image
|
||||
#
|
||||
# Triggers:
|
||||
# - push to main → :main + :sha-<7> + :main-<commit UTC>-<7>
|
||||
# + the matching :debug-* tags
|
||||
# + the matching :debug-* tags, only when the
|
||||
# push touches the image build context (below)
|
||||
# - push tags relay-v*.*.* → :{version} + :{major}.{minor} + :{major}
|
||||
# + matching :debug-* tags
|
||||
# (+ :latest/:debug-latest for stable releases)
|
||||
@@ -49,10 +50,26 @@ name: Docker image
|
||||
# semver, so relay-v0.3.0-rc.1 publishes :0.3.0-rc.1 without moving :latest,
|
||||
# and main pushes (no semver tag) never produce :latest.
|
||||
|
||||
# Main pushes skip paths that .dockerignore keeps out of the build context:
|
||||
# they cannot change either image, and every published :main-<commit UTC>-<7>
|
||||
# tag rolls staging through Kargo. .github/ is ignored by Docker too, but this
|
||||
# workflow defines the build, so it is re-included. GitHub does not evaluate
|
||||
# path filters for tag pushes, so relay-v* tags always publish.
|
||||
# scripts/test-relay-image-eligibility-workflow.sh checks every exclusion
|
||||
# against .dockerignore.
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
tags: ["relay-v[0-9]*"]
|
||||
paths:
|
||||
- "**"
|
||||
- "!desktop/**"
|
||||
- "!mobile/**"
|
||||
- "!docs/**"
|
||||
- "!bin/**"
|
||||
- "!sidecars/**"
|
||||
- "!.github/**"
|
||||
- ".github/workflows/docker.yml"
|
||||
pull_request:
|
||||
paths:
|
||||
- "Dockerfile"
|
||||
|
||||
@@ -104,8 +104,11 @@ prior release's recorded squash commit; tag ancestry is deliberately irrelevant.
|
||||
`debug-0.3.0` and `debug-latest`) for native profiling. The ordinary tags
|
||||
remain stripped and are the default for deployments that do not need it.
|
||||
|
||||
Every push to `main` continues to publish the rolling relay `:main` and
|
||||
`:sha-<7>` tags, plus matching `:debug-main` and `:debug-sha-<7>` variants.
|
||||
Every push to `main` that changes the image build context continues to
|
||||
publish the rolling relay `:main` and `:sha-<7>` tags, plus matching
|
||||
`:debug-main` and `:debug-sha-<7>` variants. Pushes that only touch paths
|
||||
`.dockerignore` excludes (such as `desktop/`, `mobile/` and `docs/`) publish
|
||||
nothing.
|
||||
|
||||
### Mobile
|
||||
|
||||
|
||||
@@ -30,6 +30,32 @@ require_literal '- "scripts/create-deployment-eligibility-predicate.jq"'
|
||||
require_literal '- "scripts/select-qualified-ci-run.jq"'
|
||||
require_literal '- "scripts/test-relay-image-eligibility-workflow.sh"'
|
||||
|
||||
# Main pushes may skip only paths Docker never sees. The push filter must be, in
|
||||
# order: "**", then directory exclusions that .dockerignore also excludes, then
|
||||
# the re-included image workflow. Any other entry, or another order, could stop
|
||||
# a change that alters the published image from publishing it.
|
||||
push_trigger=$(awk '/^ push:$/{f=1;next} f&&/^ [a-z_]+:/{exit} f' "$workflow")
|
||||
push_paths=()
|
||||
while IFS= read -r entry; do
|
||||
push_paths+=("$entry")
|
||||
done < <(awk '/^ paths:$/{f=1;next} f&&/^[[:space:]]*(#.*)?$/{next} f&&/^ - /{print;next} f{exit}' <<<"$push_trigger")
|
||||
fail_push_paths() {
|
||||
echo "main push path filter: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
(( ${#push_paths[@]} >= 3 )) || fail_push_paths "expected \"**\", directory exclusions, then the workflow"
|
||||
[[ "${push_paths[0]}" == ' - "**"' ]] || fail_push_paths 'first entry must be "**"'
|
||||
last=$(( ${#push_paths[@]} - 1 ))
|
||||
[[ "${push_paths[$last]}" == ' - ".github/workflows/docker.yml"' ]] ||
|
||||
fail_push_paths "last entry must re-include .github/workflows/docker.yml"
|
||||
for entry in "${push_paths[@]:1:last-1}"; do
|
||||
[[ "$entry" =~ ^\ {6}-\ \"!([A-Za-z0-9._-]+)/\*\*\"$ ]] ||
|
||||
fail_push_paths "only \"!<dir>/**\" exclusions may sit between \"**\" and the workflow, found: ${entry# - }"
|
||||
excluded=${BASH_REMATCH[1]}
|
||||
grep -Fxq "$excluded/" "$repo_root/.dockerignore" ||
|
||||
fail_push_paths "skips $excluded/, which .dockerignore keeps in the image build context"
|
||||
done
|
||||
|
||||
if grep -Fq "buzz-staging-dev" "$workflow"; then
|
||||
echo "canonical relay image workflow references the preview-only image package" >&2
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user