From a8629a6fb6fb6b43cea895d054da03e9df68cb29 Mon Sep 17 00:00:00 2001 From: Dylan Dreyer Date: Mon, 17 Aug 2026 18:30:20 -0700 Subject: [PATCH 1/2] fix(ci): build both triples on amd64; cross-rs images are amd64-only The aarch64 leg failed immediately: #2 [internal] load metadata for ghcr.io/cross-rs/aarch64-unknown-linux-musl:0.2.5 #2 ERROR: no match for platform in manifest: not found scripts/cross/aarch64-unknown-linux-musl.dockerfile builds FROM ghcr.io/cross-rs/aarch64-unknown-linux-musl:0.2.5, which is published for linux/amd64 only -- confirmed via `docker manifest inspect` on both cross-rs images. That is by design: a cross-rs "aarch64" image is an amd64 container carrying a toolchain that targets aarch64, not an arm64 image. It cannot run on ubuntu-24.04-arm. The earlier comment claiming cross uses a same-arch container was wrong. Both legs now run on ubuntu-24.04, matching how upstream's publish.yml builds these targets. This is still real cross-compilation rather than emulation: cross only needs QEMU to *run* target binaries, which `cross build` does not do. Also switches the static-linking assertion from `ldd` to `file`. ldd cannot inspect a foreign-architecture binary, which the aarch64 artifact now is on an amd64 host. The old `ldd ... | grep -qv 'not a dynamic executable'` was fragile regardless -- grep -qv succeeds whenever any single line fails to match, so incidental extra output would have tripped it. Co-Authored-By: Claude Opus 5 (1M context) --- .../workflows/startree-distroless-build.yml | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/.github/workflows/startree-distroless-build.yml b/.github/workflows/startree-distroless-build.yml index 2015400b9bd9d..fbfa39ecfcb8c 100644 --- a/.github/workflows/startree-distroless-build.yml +++ b/.github/workflows/startree-distroless-build.yml @@ -92,18 +92,22 @@ jobs: build: name: Build ${{ matrix.triple }} needs: metadata - runs-on: ${{ matrix.runner }} + runs-on: ubuntu-24.04 timeout-minutes: 180 strategy: fail-fast: false matrix: - include: - # Native builds -- `cross` uses a same-arch container carrying the musl - # toolchain, so there is no QEMU emulation on either leg. - - triple: x86_64-unknown-linux-musl - runner: ubuntu-24.04 - - triple: aarch64-unknown-linux-musl - runner: ubuntu-24.04-arm + # Both legs run on amd64. The cross-rs base images the Makefile builds + # FROM (scripts/cross/*.dockerfile) are published for linux/amd64 only -- + # the aarch64 one is an amd64 container holding a cross-toolchain, not an + # arm64 image. On an arm64 runner it fails with "no match for platform in + # manifest". This is also how upstream's publish.yml builds it. + # + # This is real cross-compilation, not emulation: cross only needs QEMU to + # *run* target binaries (tests), which `cross build` does not do. + triple: + - x86_64-unknown-linux-musl + - aarch64-unknown-linux-musl env: # Makefile does `export VERSION ?= $(shell cargo vdev version)`, which would # build vdev just to name a file. Set it directly instead. @@ -145,14 +149,17 @@ jobs: set -euo pipefail mkdir -p /tmp/verify && tar -xzf target/artifacts/vector-*.tar.gz \ -C /tmp/verify --strip-components=2 - file /tmp/verify/bin/vector + DESC="$(file -b /tmp/verify/bin/vector)" + echo "$DESC" # The old EC2 flow produced a glibc binary named "-musl". Catch that here - # rather than in a CrashLoopBackOff on distroless/static. - if ldd /tmp/verify/bin/vector 2>&1 | grep -qv 'not a dynamic executable'; then - echo "::error::binary is dynamically linked; it will not run on distroless/static" - ldd /tmp/verify/bin/vector || true - exit 1 - fi + # rather than in a CrashLoopBackOff on distroless/static. `file` is used + # rather than `ldd` because the aarch64 binary is cross-compiled on an + # amd64 host, where ldd cannot inspect a foreign-architecture binary. + case "$DESC" in + *"statically linked"*) echo "OK: statically linked" ;; + *) echo "::error::binary is not statically linked; it will not run on distroless/static" + exit 1 ;; + esac - uses: actions/upload-artifact@v4 with: From ccfe5eeafbfd850a4cb5d411659b587e34f8d2c3 Mon Sep 17 00:00:00 2001 From: Dylan Dreyer Date: Mon, 17 Aug 2026 19:23:59 -0700 Subject: [PATCH 2/2] fix(ci): accept static-pie in the static-linking assertion The x86_64 leg built fine and then failed the assertion on a binary that is static: /tmp/verify/bin/vector: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), static-pie linked, not stripped ##[error]binary is dynamically linked Two separate bugs, both false positives: 1. The `ldd` form. On this runner ldd prints "\tstatically linked" for a static binary, not "not a dynamic executable", so `grep -qv` matched and the check failed. The assumed output string was simply wrong. 2. The `file` replacement in the previous commit matched only "statically linked". Rust's musl targets emit a static-PIE, which file(1) reports as "static-pie linked" -- so it would have failed the same way. Now accepts both spellings. Verified against real file(1) output for static-pie (x86-64 and aarch64), plain static, and both dynamic forms. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/startree-distroless-build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/startree-distroless-build.yml b/.github/workflows/startree-distroless-build.yml index fbfa39ecfcb8c..aefec535eabdf 100644 --- a/.github/workflows/startree-distroless-build.yml +++ b/.github/workflows/startree-distroless-build.yml @@ -155,8 +155,10 @@ jobs: # rather than in a CrashLoopBackOff on distroless/static. `file` is used # rather than `ldd` because the aarch64 binary is cross-compiled on an # amd64 host, where ldd cannot inspect a foreign-architecture binary. + # Rust's musl targets emit a static-PIE, which `file` reports as + # "static-pie linked" rather than "statically linked". Both are static. case "$DESC" in - *"statically linked"*) echo "OK: statically linked" ;; + *"statically linked"*|*"static-pie linked"*) echo "OK: statically linked" ;; *) echo "::error::binary is not statically linked; it will not run on distroless/static" exit 1 ;; esac