diff --git a/.gitea/scripts/ci.Dockerfile b/.gitea/scripts/ci.Dockerfile new file mode 100644 index 0000000..15a6f27 --- /dev/null +++ b/.gitea/scripts/ci.Dockerfile @@ -0,0 +1,21 @@ +# CI-only image for the dependency check. +# +# The report is a Node script because it has to compare semantic versions and +# read four different HTTP APIs, and the official `rust` image ships no Node — +# while the `node` image ships no cargo, which `cargo metadata` needs to resolve +# the workspace graph. Rather than maintain the parsing twice in two languages, +# this layers the two together. +# +# Node is copied from the official image rather than installed from a +# third-party apt repository: no extra signing key, no extra network +# dependency at build time, and the same binaries everyone else runs. +ARG RUST_VERSION=1.95 +ARG NODE_VERSION=22-bookworm-slim + +FROM node:${NODE_VERSION} AS node + +FROM rust:${RUST_VERSION}-bookworm +COPY --from=node /usr/local/bin/node /usr/local/bin/node +COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules +RUN ln -sf /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \ + && node --version diff --git a/.gitea/workflows/dependency-check.yml b/.gitea/workflows/dependency-check.yml index 3dec59e..ff4d733 100644 --- a/.gitea/workflows/dependency-check.yml +++ b/.gitea/workflows/dependency-check.yml @@ -53,8 +53,11 @@ jobs: # The workspace is streamed into the container over stdin rather than # bind-mounted, so this works whether the runner shares a filesystem with - # the daemon or not. The official rust image already carries the - # toolchain, so nothing is downloaded inside. + # the daemon or not. + # + # The image is rust + node, built from .gitea/scripts/ci.Dockerfile: the + # report needs cargo to resolve the workspace graph and Node to read the + # registries, and neither official image has both. # # RUSTUP_TOOLCHAIN overrides rust-toolchain.toml: the image's own # toolchain is enough to read Cargo.lock, and honouring the file would @@ -66,10 +69,17 @@ jobs: - name: Generate report run: | set -eu + VERSION="${{ steps.rust.outputs.version }}" + docker build \ + --build-arg "RUST_VERSION=${VERSION}" \ + --tag "dep-check:${VERSION}" \ + --file .gitea/scripts/ci.Dockerfile \ + .gitea/scripts > /dev/null + tar cf - --exclude=./.git --exclude=./target . | docker run --rm -i \ - -e RUSTUP_TOOLCHAIN="${{ steps.rust.outputs.version }}" \ + -e RUSTUP_TOOLCHAIN="${VERSION}" \ -e CARGO_TERM_COLOR=never \ - "rust:${{ steps.rust.outputs.version }}-bookworm" \ + "dep-check:${VERSION}" \ sh -ec 'mkdir -p /work && cd /work && tar xf - && exec node .gitea/scripts/dependency-report.mjs' \ > /tmp/report.md 2> /tmp/report.err || { echo "::error::the dependency report failed to generate"