From 015cd524c368a353e149fc6b3adeb0f9391af2fd Mon Sep 17 00:00:00 2001 From: Warren Lee <5959690+wrn14897@users.noreply.github.com> Date: Fri, 18 Sep 2026 14:01:25 -0700 Subject: [PATCH 1/5] fix(docker): stop clobbering the base image's /usr/lib with node's The all-in-one and local images copied the whole /usr/lib out of node:22.22-alpine on top of the ClickHouse base image, overwriting libapk.so, libssl, libcrypto and libz. That only worked while both images happened to sit on the same Alpine point release. Bumping CLICKHOUSE_VERSION to 26.8 (#3142) moved the base to Alpine 3.24.2 / apk-tools 3.0.8 while node:22.22-alpine is still on 3.24.1 / 3.0.6, so the copy left a 3.0.6 libapk.so under a 3.0.8 /sbin/apk and the next apk call died with exit 127: Error relocating /sbin/apk: apk_fs_is_malicious_filename: symbol not found Node only needs libstdc++ and libgcc from that directory, so install those with apk from the image's own Alpine release and drop the blanket copy. They go in before the v3.9 mongodb repositories are appended so they resolve against 3.24 rather than 3.9. Verified by building all-in-one-noauth (amd64) and all-in-one-auth (arm64): apk, node, clickhouse-server and mongod all run, libapk and OpenSSL are owned by the base image's packages again, and scripts/ci/smoke-all-in-one.sh gets a canary log end-to-end through the collector into ClickHouse. --- .changeset/fix-alpine-libapk-clobber.md | 9 +++++++++ docker/hyperdx/Dockerfile | 15 +++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 .changeset/fix-alpine-libapk-clobber.md diff --git a/.changeset/fix-alpine-libapk-clobber.md b/.changeset/fix-alpine-libapk-clobber.md new file mode 100644 index 0000000000..bda197bad2 --- /dev/null +++ b/.changeset/fix-alpine-libapk-clobber.md @@ -0,0 +1,9 @@ +--- +'@hyperdx/app': patch +--- + +fix: stop the all-in-one image copying node's /usr/lib over the base image + +The all-in-one and local images copied the whole `/usr/lib` out of `node:22.22-alpine`, overwriting the ClickHouse base image's `libapk.so`, `libssl`, `libcrypto` and `libz`. Once the two images landed on different Alpine point releases (3.24.1 vs 3.24.2), the older `libapk.so` no longer satisfied the newer `/sbin/apk`, and every image build failed with `Error relocating /sbin/apk: apk_fs_is_malicious_filename: symbol not found`. + +Node only needed `libstdc++`/`libgcc` from that copy, so those are now installed with apk from the image's own Alpine release and the blanket copy is gone. This also stops ClickHouse's OpenSSL being silently swapped for node's. diff --git a/docker/hyperdx/Dockerfile b/docker/hyperdx/Dockerfile index d13edc5d21..74f3cc7c77 100644 --- a/docker/hyperdx/Dockerfile +++ b/docker/hyperdx/Dockerfile @@ -159,10 +159,14 @@ ENV OTEL_RESOURCE_ATTRIBUTES="service.version=$CODE_VERSION" COPY --from=ocb-builder --chmod=755 /build/output/otelcol-hyperdx /otelcontribcol COPY --from=otel_collector_opampsupervisor_base --chmod=755 /usr/local/bin/opampsupervisor /usr/local/bin/opampsupervisor -# Copy Node.js runtime from node base +# Copy Node.js runtime from node base. +# Deliberately NOT copying node's /usr/lib: it overwrites this image's +# libapk.so, libssl, libcrypto and libz with whatever Alpine point release the +# node image happens to be built on. When the two drift, apk stops linking +# ("Error relocating /sbin/apk: ... symbol not found") and the build dies. +# Node only needs libstdc++/libgcc from there; those are installed via apk below. COPY --from=node_base --link /usr/local/bin /usr/local/bin COPY --from=node_base --link /usr/local/lib /usr/local/lib -COPY --from=node_base /usr/lib /usr/lib COPY --from=node_base /usr/local/include /usr/local/include # Set up Clickhouse @@ -186,8 +190,11 @@ COPY --from=goose /bin/goose /usr/local/bin/goose # Copy migrate binary (Go-based goose migration tool with full TLS support) COPY --from=migrate-builder /migrate /usr/local/bin/migrate -# Install MongoDB and other dependencies (consolidated into a single RUN command) -RUN echo 'http://dl-cdn.alpinelinux.org/alpine/v3.9/main' >> /etc/apk/repositories && \ +# Install MongoDB and other dependencies (consolidated into a single RUN command). +# libstdc++/libgcc are the Node.js runtime deps, installed before the v3.9 +# repositories are appended so they resolve from this image's own Alpine release. +RUN apk add --no-cache libstdc++ libgcc && \ + echo 'http://dl-cdn.alpinelinux.org/alpine/v3.9/main' >> /etc/apk/repositories && \ echo 'http://dl-cdn.alpinelinux.org/alpine/v3.9/community' >> /etc/apk/repositories && \ apk update && \ apk add --no-cache mongodb yaml-cpp=0.6.2-r2 ca-certificates && \ From 3dc71d8ce1b8e3a1530a0f8e4849da9302ceae05 Mon Sep 17 00:00:00 2001 From: Warren Lee <5959690+wrn14897@users.noreply.github.com> Date: Fri, 18 Sep 2026 14:55:54 -0700 Subject: [PATCH 2/5] ci: build the release images on every push to main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The apk break that killed the last release came in from outside the repo. The Dockerfile pins floating upstream tags, and Docker Hub re-pointed clickhouse-server:26.8-alpine from ClickHouse 26.8.6 to 26.8.7 around 15:00 UTC, taking apk-tools from 3.0.6 to 3.0.8 with it. Nothing we had would catch that: 21:22 (D-1) PR #3142 Docker Build -> passes, base @9f10a193 (3.0.6) 00:36 nightly -> passes, base @9f10a193 (3.0.6) ~15:01 upstream re-tags 26.8-alpine -> @2bece7c6 (3.0.8) 16:17 merge to main -> no image build 17:48 merge to main -> no image build 19:31 Release -> fails Both gates were green because both ran before the re-tag, and the two merges that followed it built no images: Docker Build only ran on pull requests, and its path filter would have skipped those diffs anyway. The next thing to touch the new base was the release itself. So run Docker Build on pushes to main too, and ignore the path filter there. The filter is right for pull requests, where the question is "did this diff break the image" and staying fast matters; it is the wrong instrument on main, where the question is "does the image still build today". Both all-in-one targets and the end-to-end smoke test run as they already do on pull requests, so a drifted base now shows up as a red build on the next merge rather than in a release hours later. The twelve copies of the changed-files condition collapse into one `gate` step per job, since the condition now has two variables rather than one. Pull-request and workflow_dispatch behaviour is unchanged. Concurrency is keyed on the event as well as the ref: `github.ref` is the same for every push to main, and the existing cancel-in-progress group would have each merge cancel the one before it and leave that commit unverified. Pull requests keep cancel-on-new-push. Also set `pull: true` on the nightly's three image builds and on the all-in-one PR build, so the floating tags are re-resolved against the registry instead of whatever the runner happens to hold. Fresh runners already re-resolve, so this is hygiene rather than the fix — it keeps holding if these ever move to a persistent builder. --- .github/workflows/docker-build.yml | 109 ++++++++++++++++++-------- .github/workflows/release-nightly.yml | 15 ++++ 2 files changed, 91 insertions(+), 33 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index f301a338b9..49264cb68c 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -1,16 +1,36 @@ name: Docker Build -# Verifies the release Docker images actually build on PRs, without pushing. +# Verifies the release Docker images actually build, without pushing. # A source-level type check (`make ci-lint`) cannot catch build failures that # only surface inside the image — e.g. a declaration file that exists in the -# repo but was never COPYed into the Docker build stage. Each image is built -# only when files that affect it change, so unrelated PRs stay fast. +# repo but was never COPYed into the Docker build stage. +# +# On pull requests each image is built only when files that affect it change, +# so unrelated PRs stay fast. +# +# On pushes to main every image is built regardless of what changed. The path +# filter is the wrong instrument there, because these builds can break with no +# repo change at all: the Dockerfile pins floating upstream tags +# (`node:${NODE_VERSION}-alpine`, `clickhouse-server:${CLICKHOUSE_VERSION}-alpine`) +# and the registry re-points them whenever upstream publishes a patch. That is +# exactly how the 26.8-alpine break reached a release: the tag moved from +# ClickHouse 26.8.6 to 26.8.7 mid-afternoon, upgrading apk-tools 3.0.6 -> 3.0.8 +# underneath us. The PR check and the nightly had both already passed against +# the older digest, two commits then merged to main with no image build between +# them, and the failure only appeared in the release run hours later. Building +# unconditionally on main turns that into a red build on the next merge. on: pull_request: branches: [main] + push: + branches: [main] workflow_dispatch: concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + # Keyed on the event as well as the ref: on main `github.ref` is identical for + # every push, so a shared group with cancel-in-progress would let each merge + # cancel the previous one and leave that commit unverified. PRs keep + # cancel-on-new-push; pushes to main queue instead. + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} permissions: contents: read jobs: @@ -24,20 +44,27 @@ jobs: uses: actions/checkout@v6 - name: Get changed files id: changed-files + if: github.event_name == 'pull_request' uses: tj-actions/changed-files@v47.0.6 with: files: | docker/otel-collector/** packages/otel-collector/** + # Path filtering applies to pull requests only; see the header comment. + - name: Decide whether to build + id: gate + env: + EVENT_NAME: ${{ github.event_name }} + ANY_CHANGED: ${{ steps.changed-files.outputs.any_changed }} + run: | + if [ "$EVENT_NAME" != "pull_request" ] || [ "$ANY_CHANGED" = "true" ]; then + echo "run=true" >> "$GITHUB_OUTPUT" + fi - name: Setup Docker Buildx - if: - steps.changed-files.outputs.any_changed == 'true' || github.event_name - == 'workflow_dispatch' + if: steps.gate.outputs.run == 'true' uses: docker/setup-buildx-action@v3 - name: Build (no push) - if: - steps.changed-files.outputs.any_changed == 'true' || github.event_name - == 'workflow_dispatch' + if: steps.gate.outputs.run == 'true' uses: docker/build-push-action@v6 with: context: . @@ -62,6 +89,7 @@ jobs: uses: actions/checkout@v6 - name: Get changed files id: changed-files + if: github.event_name == 'pull_request' uses: tj-actions/changed-files@v47.0.6 with: files: | @@ -77,15 +105,21 @@ jobs: .prettierignore tsconfig.base.json nx.json + # Path filtering applies to pull requests only; see the header comment. + - name: Decide whether to build + id: gate + env: + EVENT_NAME: ${{ github.event_name }} + ANY_CHANGED: ${{ steps.changed-files.outputs.any_changed }} + run: | + if [ "$EVENT_NAME" != "pull_request" ] || [ "$ANY_CHANGED" = "true" ]; then + echo "run=true" >> "$GITHUB_OUTPUT" + fi - name: Setup Docker Buildx - if: - steps.changed-files.outputs.any_changed == 'true' || github.event_name - == 'workflow_dispatch' + if: steps.gate.outputs.run == 'true' uses: docker/setup-buildx-action@v3 - name: Build (no push) - if: - steps.changed-files.outputs.any_changed == 'true' || github.event_name - == 'workflow_dispatch' + if: steps.gate.outputs.run == 'true' uses: docker/build-push-action@v6 with: context: . @@ -115,10 +149,11 @@ jobs: # # This target's base does `COPY --from=prod /app /app`, so it already # rebuilds the entire App/prod image. To avoid duplicating that ~8-minute - # Node build on every app change, this job is gated ONLY on the incremental - # bundling inputs (ClickHouse / OTel / the shared Dockerfile) — NOT on - # api/app/common-utils/deps. Those are covered by the App Image job above, - # and they can't break the bundling layers, which only COPY the prod output. + # Node build on every app change, the pull-request path filter below is + # scoped ONLY to the incremental bundling inputs (ClickHouse / OTel / the + # shared Dockerfile) — NOT api/app/common-utils/deps. Those are covered by + # the App Image job above, and they can't break the bundling layers, which + # only COPY the prod output. Pushes to main ignore the filter entirely. all-in-one-image: name: Build All-in-One Image runs-on: ubuntu-24.04 @@ -128,6 +163,7 @@ jobs: uses: actions/checkout@v6 - name: Get changed files id: changed-files + if: github.event_name == 'pull_request' uses: tj-actions/changed-files@v47.0.6 with: files: | @@ -136,15 +172,23 @@ jobs: docker/clickhouse/** docker/otel-collector/** .vex/** + # Path filtering applies to pull requests only; see the header comment. + # This is the job that guards against upstream base-image drift, so on + # main it must run even when the diff touches nothing it lists. + - name: Decide whether to build + id: gate + env: + EVENT_NAME: ${{ github.event_name }} + ANY_CHANGED: ${{ steps.changed-files.outputs.any_changed }} + run: | + if [ "$EVENT_NAME" != "pull_request" ] || [ "$ANY_CHANGED" = "true" ]; then + echo "run=true" >> "$GITHUB_OUTPUT" + fi - name: Setup Docker Buildx - if: - steps.changed-files.outputs.any_changed == 'true' || github.event_name - == 'workflow_dispatch' + if: steps.gate.outputs.run == 'true' uses: docker/setup-buildx-action@v3 - name: Build all-in-one-auth (no push) - if: - steps.changed-files.outputs.any_changed == 'true' || github.event_name - == 'workflow_dispatch' + if: steps.gate.outputs.run == 'true' uses: docker/build-push-action@v6 with: context: . @@ -152,6 +196,9 @@ jobs: target: all-in-one-auth platforms: linux/amd64 push: false + # Re-resolve the floating upstream tags rather than trusting whatever + # the runner happens to have; this job exists to notice when they move. + pull: true build-contexts: | clickhouse=./docker/clickhouse otel-collector=./docker/otel-collector @@ -168,9 +215,7 @@ jobs: # already in buildx's local cache from the step above, so this only builds # the final noauth COPY layer. - name: Build all-in-one-noauth / Local (no push) - if: - steps.changed-files.outputs.any_changed == 'true' || github.event_name - == 'workflow_dispatch' + if: steps.gate.outputs.run == 'true' uses: docker/build-push-action@v6 with: context: . @@ -194,8 +239,6 @@ jobs: # Boot the freshly built Local image and push one OTLP log end-to-end into # ClickHouse. Proves the artefact we ship actually runs, not just builds. - name: Smoke test the built image - if: - steps.changed-files.outputs.any_changed == 'true' || github.event_name - == 'workflow_dispatch' + if: steps.gate.outputs.run == 'true' timeout-minutes: 10 run: scripts/ci/smoke-all-in-one.sh hyperdx-aio-smoke:pr diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml index 6b967dffcf..c9b47f6456 100644 --- a/.github/workflows/release-nightly.yml +++ b/.github/workflows/release-nightly.yml @@ -136,6 +136,11 @@ jobs: CODE_VERSION=${{ env.IMAGE_NIGHTLY_TAG }} tags: | ${{ env.IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_NIGHTLY_TAG }}-${{ matrix.arch }} + # Re-resolve the floating upstream base tags (node:*-alpine, + # clickhouse-server:*-alpine) instead of reusing whatever the runner + # already has. Those tags get re-pointed on upstream patch releases, + # and this nightly is the first thing that should notice. + pull: true push: true sbom: true provenance: true @@ -218,6 +223,11 @@ jobs: tags: | ${{ env.LOCAL_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_NIGHTLY_TAG }}-${{ matrix.arch }} ${{ env.NEXT_LOCAL_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_NIGHTLY_TAG }}-${{ matrix.arch }} + # Re-resolve the floating upstream base tags (node:*-alpine, + # clickhouse-server:*-alpine) instead of reusing whatever the runner + # already has. Those tags get re-pointed on upstream patch releases, + # and this nightly is the first thing that should notice. + pull: true push: true sbom: true provenance: true @@ -301,6 +311,11 @@ jobs: tags: | ${{ env.ALL_IN_ONE_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_NIGHTLY_TAG }}-${{ matrix.arch }} ${{ env.NEXT_ALL_IN_ONE_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_NIGHTLY_TAG }}-${{ matrix.arch }} + # Re-resolve the floating upstream base tags (node:*-alpine, + # clickhouse-server:*-alpine) instead of reusing whatever the runner + # already has. Those tags get re-pointed on upstream patch releases, + # and this nightly is the first thing that should notice. + pull: true push: true sbom: true provenance: true From 85e50b283316487479a247c8d94b89bf2c79c1e3 Mon Sep 17 00:00:00 2001 From: Warren Lee <5959690+wrn14897@users.noreply.github.com> Date: Fri, 18 Sep 2026 15:18:07 -0700 Subject: [PATCH 3/5] ci: correct what the concurrency group actually guarantees MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review caught that the comment overclaimed. GitHub holds at most one pending run per concurrency group, so a third merge arriving during a long build supersedes the queued one rather than joining a queue — the middle commit is not built. Say that plainly, and say why it is acceptable here: base-image drift affects every commit equally and a Dockerfile break in a superseded commit is still there at the tip, so building the tip is what this job needs. Per-commit attribution comes from the pull request run. Also drops the claim that the event key exists to stop merges cancelling each other; cancel-in-progress already does that. It is there to keep push and pull_request runs in separate groups. --- .github/workflows/docker-build.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 49264cb68c..21f68f999c 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -25,10 +25,18 @@ on: branches: [main] workflow_dispatch: concurrency: - # Keyed on the event as well as the ref: on main `github.ref` is identical for - # every push, so a shared group with cancel-in-progress would let each merge - # cancel the previous one and leave that commit unverified. PRs keep - # cancel-on-new-push; pushes to main queue instead. + # Keyed on the event as well as the ref so that pushes to main and pull + # request runs never share a group: `github.ref` alone would let a merge + # cancel an in-flight PR run, or vice versa. + # + # Pushes to main do not cancel in progress, so a merge cannot kill the build + # verifying the commit before it. This guarantees the tip of main gets built, + # not that every individual commit does: GitHub holds only one pending run per + # group, so a third merge arriving during a long build supersedes the queued + # one. That is fine for what this job is for — an upstream base-image move + # affects every commit equally, and a Dockerfile break in a superseded commit + # is still present at the tip. Per-commit attribution comes from the pull + # request run, not from here. group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} permissions: From 47e95ac697fc0d17c9429eb63c75d98b558f11a7 Mon Sep 17 00:00:00 2001 From: Warren Lee <5959690+wrn14897@users.noreply.github.com> Date: Fri, 18 Sep 2026 15:29:54 -0700 Subject: [PATCH 4/5] ci: state the real reason the concurrency group keys on the event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pull request run and a merge could never have shared a group — `github.ref` is `refs/pull//merge` on one and `refs/heads/main` on the other. The event key earns its place elsewhere: a manual run on main carries `refs/heads/main` too, and without it would contend with a merge. --- .github/workflows/docker-build.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 21f68f999c..236b7ea2a2 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -25,9 +25,10 @@ on: branches: [main] workflow_dispatch: concurrency: - # Keyed on the event as well as the ref so that pushes to main and pull - # request runs never share a group: `github.ref` alone would let a merge - # cancel an in-flight PR run, or vice versa. + # Keyed on the event as well as the ref to separate a manual run on main from + # a merge: both carry `refs/heads/main`, so they would otherwise contend for + # one group. (A pull request run never collides with either — its ref is + # `refs/pull//merge`.) # # Pushes to main do not cancel in progress, so a merge cannot kill the build # verifying the commit before it. This guarantees the tip of main gets built, From 8af13902a809ba50c86e46b45a938c1273a849ec Mon Sep 17 00:00:00 2001 From: Warren Lee <5959690+wrn14897@users.noreply.github.com> Date: Fri, 18 Sep 2026 15:40:38 -0700 Subject: [PATCH 5/5] ci: inline the build condition and drop the unproven pull: true MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review was right on both counts. The gate step did not do what I claimed. The `if:` lines never collapsed — there are eight of them and there still were, just shorter — so the step bought three copies of a nine-line shell block and nothing else. The condition goes back inline, one expression, no extra steps. A skipped `changed-files` leaves `any_changed` empty, so the second clause is false on push and dispatch and the first carries it; behaviour is identical to the gate for all four event/filter combinations. (Eight, not the twelve the earlier commit message asserted. That was wrong too.) `pull: true` is gone. On docker-build.yml it was provably dead: these jobs run on ephemeral ubuntu-24.04 with a fresh buildx, which always re-resolves the tag. On the nightly it was unproven, and adding it there while leaving release.yml — same runner labels, and the path that actually ships — without it made the fleet less consistent, not more. It was never part of the fix; the release failed precisely because its runner *did* re-resolve to the new digest. Dropping it reverts release-nightly.yml entirely, leaving this PR one workflow file. Whether these builds should pin tag resolution at all is a real question, but it belongs in a change that can touch release.yml. --- .github/workflows/docker-build.yml | 67 ++++++++++----------------- .github/workflows/release-nightly.yml | 15 ------ 2 files changed, 24 insertions(+), 58 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 236b7ea2a2..513261b0d1 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -59,21 +59,15 @@ jobs: files: | docker/otel-collector/** packages/otel-collector/** - # Path filtering applies to pull requests only; see the header comment. - - name: Decide whether to build - id: gate - env: - EVENT_NAME: ${{ github.event_name }} - ANY_CHANGED: ${{ steps.changed-files.outputs.any_changed }} - run: | - if [ "$EVENT_NAME" != "pull_request" ] || [ "$ANY_CHANGED" = "true" ]; then - echo "run=true" >> "$GITHUB_OUTPUT" - fi - name: Setup Docker Buildx - if: steps.gate.outputs.run == 'true' + if: + github.event_name != 'pull_request' || + steps.changed-files.outputs.any_changed == 'true' uses: docker/setup-buildx-action@v3 - name: Build (no push) - if: steps.gate.outputs.run == 'true' + if: + github.event_name != 'pull_request' || + steps.changed-files.outputs.any_changed == 'true' uses: docker/build-push-action@v6 with: context: . @@ -114,21 +108,15 @@ jobs: .prettierignore tsconfig.base.json nx.json - # Path filtering applies to pull requests only; see the header comment. - - name: Decide whether to build - id: gate - env: - EVENT_NAME: ${{ github.event_name }} - ANY_CHANGED: ${{ steps.changed-files.outputs.any_changed }} - run: | - if [ "$EVENT_NAME" != "pull_request" ] || [ "$ANY_CHANGED" = "true" ]; then - echo "run=true" >> "$GITHUB_OUTPUT" - fi - name: Setup Docker Buildx - if: steps.gate.outputs.run == 'true' + if: + github.event_name != 'pull_request' || + steps.changed-files.outputs.any_changed == 'true' uses: docker/setup-buildx-action@v3 - name: Build (no push) - if: steps.gate.outputs.run == 'true' + if: + github.event_name != 'pull_request' || + steps.changed-files.outputs.any_changed == 'true' uses: docker/build-push-action@v6 with: context: . @@ -181,23 +169,15 @@ jobs: docker/clickhouse/** docker/otel-collector/** .vex/** - # Path filtering applies to pull requests only; see the header comment. - # This is the job that guards against upstream base-image drift, so on - # main it must run even when the diff touches nothing it lists. - - name: Decide whether to build - id: gate - env: - EVENT_NAME: ${{ github.event_name }} - ANY_CHANGED: ${{ steps.changed-files.outputs.any_changed }} - run: | - if [ "$EVENT_NAME" != "pull_request" ] || [ "$ANY_CHANGED" = "true" ]; then - echo "run=true" >> "$GITHUB_OUTPUT" - fi - name: Setup Docker Buildx - if: steps.gate.outputs.run == 'true' + if: + github.event_name != 'pull_request' || + steps.changed-files.outputs.any_changed == 'true' uses: docker/setup-buildx-action@v3 - name: Build all-in-one-auth (no push) - if: steps.gate.outputs.run == 'true' + if: + github.event_name != 'pull_request' || + steps.changed-files.outputs.any_changed == 'true' uses: docker/build-push-action@v6 with: context: . @@ -205,9 +185,6 @@ jobs: target: all-in-one-auth platforms: linux/amd64 push: false - # Re-resolve the floating upstream tags rather than trusting whatever - # the runner happens to have; this job exists to notice when they move. - pull: true build-contexts: | clickhouse=./docker/clickhouse otel-collector=./docker/otel-collector @@ -224,7 +201,9 @@ jobs: # already in buildx's local cache from the step above, so this only builds # the final noauth COPY layer. - name: Build all-in-one-noauth / Local (no push) - if: steps.gate.outputs.run == 'true' + if: + github.event_name != 'pull_request' || + steps.changed-files.outputs.any_changed == 'true' uses: docker/build-push-action@v6 with: context: . @@ -248,6 +227,8 @@ jobs: # Boot the freshly built Local image and push one OTLP log end-to-end into # ClickHouse. Proves the artefact we ship actually runs, not just builds. - name: Smoke test the built image - if: steps.gate.outputs.run == 'true' + if: + github.event_name != 'pull_request' || + steps.changed-files.outputs.any_changed == 'true' timeout-minutes: 10 run: scripts/ci/smoke-all-in-one.sh hyperdx-aio-smoke:pr diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml index c9b47f6456..6b967dffcf 100644 --- a/.github/workflows/release-nightly.yml +++ b/.github/workflows/release-nightly.yml @@ -136,11 +136,6 @@ jobs: CODE_VERSION=${{ env.IMAGE_NIGHTLY_TAG }} tags: | ${{ env.IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_NIGHTLY_TAG }}-${{ matrix.arch }} - # Re-resolve the floating upstream base tags (node:*-alpine, - # clickhouse-server:*-alpine) instead of reusing whatever the runner - # already has. Those tags get re-pointed on upstream patch releases, - # and this nightly is the first thing that should notice. - pull: true push: true sbom: true provenance: true @@ -223,11 +218,6 @@ jobs: tags: | ${{ env.LOCAL_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_NIGHTLY_TAG }}-${{ matrix.arch }} ${{ env.NEXT_LOCAL_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_NIGHTLY_TAG }}-${{ matrix.arch }} - # Re-resolve the floating upstream base tags (node:*-alpine, - # clickhouse-server:*-alpine) instead of reusing whatever the runner - # already has. Those tags get re-pointed on upstream patch releases, - # and this nightly is the first thing that should notice. - pull: true push: true sbom: true provenance: true @@ -311,11 +301,6 @@ jobs: tags: | ${{ env.ALL_IN_ONE_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_NIGHTLY_TAG }}-${{ matrix.arch }} ${{ env.NEXT_ALL_IN_ONE_IMAGE_NAME_DOCKERHUB }}:${{ env.IMAGE_NIGHTLY_TAG }}-${{ matrix.arch }} - # Re-resolve the floating upstream base tags (node:*-alpine, - # clickhouse-server:*-alpine) instead of reusing whatever the runner - # already has. Those tags get re-pointed on upstream patch releases, - # and this nightly is the first thing that should notice. - pull: true push: true sbom: true provenance: true