diff --git a/.github/workflows/publish-tool-images.yml b/.github/workflows/publish-tool-images.yml index a9f8fb65..888aae71 100644 --- a/.github/workflows/publish-tool-images.yml +++ b/.github/workflows/publish-tool-images.yml @@ -33,6 +33,7 @@ jobs: - {name: terraform, kind: toolcache} - {name: tflint, kind: toolcache} - {name: awscli, kind: toolcache} + - {name: strace, kind: toolcache} - {name: openmpi, kind: sysroot} - {name: highs, kind: sysroot} - {name: libpq, kind: sysroot} @@ -134,6 +135,7 @@ jobs: - {name: terraform, kind: toolcache} - {name: tflint, kind: toolcache} - {name: awscli, kind: toolcache} + - {name: strace, kind: toolcache} - {name: openmpi, kind: sysroot} - {name: highs, kind: sysroot} - {name: libpq, kind: sysroot} diff --git a/roles/github_runner_arc/README.md b/roles/github_runner_arc/README.md index 272c8a1e..f22c2522 100644 --- a/roles/github_runner_arc/README.md +++ b/roles/github_runner_arc/README.md @@ -253,7 +253,7 @@ A tool image is any image that has: `` and `` are what the consuming setup action looks up: `node` and the plain version (`24.21.0`, no leading `v`) for `actions/setup-node`, `tflint` and the version without its `v` for `setup-tflint`. `` is named the way that action names the architecture, and actions differ: `actions/setup-node` uses Node's `os.arch()` (`x64`, `arm64`), while `setup-tflint` maps `x64` to `amd64` (`amd64`, `arm64`). For a tool used only through `path` the name does not matter, since `path` finds whichever architecture is there; the reference images use `os.arch()` names, the tool cache's own default. A multi-architecture image holds, for each platform, only that platform's `` directory, so the tool cache in any one pod has one architecture per tool, which is what `path` relies on. `path` adds `//[/]` for the one `` with a `.complete` marker, and the job fails at its start if there is none or more than one. -`tool-images/` holds Dockerfiles for reference images following this contract: Node.js, Terraform, TFLint and the AWS CLI. Each downloads the official release for the target architecture in a first stage, verifies it (against the release's checksums, and for Terraform and the AWS CLI against the vendor's signing key, pinned by fingerprint), lays it out under `/toolcache`, and copies that into `busybox`, which supplies `sh`, `cp` and `rm`. To build one yourself, for both architectures: +`tool-images/` holds Dockerfiles for reference images following this contract: Node.js, Terraform, TFLint, the AWS CLI and strace. Each downloads the official release for the target architecture in a first stage (strace builds its source release into one static executable), verifies it (against the release's checksums, and for Terraform, the AWS CLI and strace against the vendor's signing key, pinned by fingerprint), lays it out under `/toolcache`, and copies that into `busybox`, which supplies `sh`, `cp` and `rm`. To build one yourself, for both architectures: ```sh docker buildx build --platform linux/amd64,linux/arm64 --build-arg NODE_VERSION=24.21.0 \ diff --git a/tool-images/strace/Dockerfile b/tool-images/strace/Dockerfile new file mode 100644 index 00000000..a0cbf022 --- /dev/null +++ b/tool-images/strace/Dockerfile @@ -0,0 +1,36 @@ +# Tool-cache capability image for strace, following the tool-image contract in roles/github_runner_arc/README.md (Capabilities): /toolcache/strace///strace is one statically linked executable, with .complete beside it, and is Node's os.arch() name (x64 or arm64), the tool cache's own default. No setup action looks strace up in the tool cache, so this capability is meant to be declared with path: strace/, which puts strace on PATH at job start. It is linked statically so it needs nothing of the runner image's libraries, and without a Linux capability: a runner pod's processes may trace their own descendants (ptrace_scope 1), which is all a job tracing its own test run needs. The final stage is busybox, which supplies the sh, cp, rm and chmod the role's init containers run. +# +# Build for both architectures: docker buildx build --platform linux/amd64,linux/arm64 --build-arg STRACE_VERSION= --build-arg STRACE_SHA256= -t /: tool-images/strace +FROM alpine:3.22 AS build +SHELL ["/bin/ash", "-eo", "pipefail", "-c"] +ARG STRACE_VERSION=7.2 +ARG TARGETARCH +# The SHA-256 of the release tarball, and the fingerprint of the key that signs the releases (the strace maintainer's primary key, whose signing subkey made this release's signature), both to be re-derived when the version is raised. +ARG STRACE_SHA256=4bde6246926890dcee824f6e6ac42a06752f47d77e5097d86e3c0d6d4b709fe5 +ARG STRACE_KEY_FINGERPRINT=7BECFE3AF7B280BB52FF77F104BA4521C996DDE1 +RUN apk add --no-cache build-base linux-headers curl gnupg xz +WORKDIR /build +# The tarball is checked against the digest above and its detached signature against the key with the fingerprint above, so neither a changed release asset nor a changed key alone can pass. +RUN release="https://github.com/strace/strace/releases/download/v${STRACE_VERSION}" \ + && curl -fsSLO "${release}/strace-${STRACE_VERSION}.tar.xz" \ + && curl -fsSLO "${release}/strace-${STRACE_VERSION}.tar.xz.asc" \ + && echo "${STRACE_SHA256} strace-${STRACE_VERSION}.tar.xz" | sha256sum -c - \ + && curl -fsSL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x${STRACE_KEY_FINGERPRINT}" | gpg --batch --import \ + && gpg --batch --with-colons --fingerprint | grep -q "^fpr:::::::::${STRACE_KEY_FINGERPRINT}:" \ + && gpg --batch --verify "strace-${STRACE_VERSION}.tar.xz.asc" "strace-${STRACE_VERSION}.tar.xz" +# One executable with no shared library and no personality (32-bit) support, which needs a multilib toolchain. +RUN case "${TARGETARCH}" in amd64) arch=x64 ;; arm64) arch=arm64 ;; *) echo "unsupported architecture: ${TARGETARCH}" >&2; exit 1 ;; esac \ + && tar -xJf "strace-${STRACE_VERSION}.tar.xz" \ + && cd "strace-${STRACE_VERSION}" \ + && ./configure --enable-mpers=no LDFLAGS=-static \ + && make -j"$(nproc)" \ + && strip src/strace \ + && ! ldd src/strace >/dev/null 2>&1 \ + && destination="/toolcache/strace/${STRACE_VERSION}/${arch}" \ + && mkdir -p "${destination}" \ + && cp src/strace "${destination}/strace" \ + && touch "${destination}.complete" \ + && chmod -R a+rX /toolcache + +FROM busybox:1.37 +COPY --from=build /toolcache /toolcache