diff --git a/linux/build/scripts/build.sh b/linux/build/scripts/build.sh index 0d4b3ec..686635d 100755 --- a/linux/build/scripts/build.sh +++ b/linux/build/scripts/build.sh @@ -76,26 +76,55 @@ mkdir -p "${BUILD_DIR}" echo "build.sh: commit=${COMMIT_SHA} epoch=${SOURCE_DATE_EPOCH} snapshot=${SNAPSHOT_TIMESTAMP}" echo "build.sh: output -> ${BUILD_DIR}" +# --- Mount strategy: local vs CI ------------------------------------------- +# Locally we bind-mount the repo into the build container at the *same* +# path (self-referential), so internal references work transparently and +# the inner script doesn't need to care which host it's on. +# +# In CI we can't do that. build.sh runs inside a Gitea Actions job +# container which talks to the *host's* docker daemon via /var/run/docker.sock. +# Bind-mounting REPO_ROOT (= /workspace//) would resolve +# against the host filesystem where that path doesn't exist; docker +# silently creates an empty dir on the host and mounts that, leaving the +# build container with an empty /work and a confusing "No such file or +# directory" error on the first config source. +# +# The standard fix for that DooD topology is --volumes-from of the parent +# job container, which inherits its /workspace mount intact. That keeps +# paths identical inside and outside, so the inner heredoc below is the +# same in both environments. +if [[ -n "${GITHUB_ACTIONS:-}" ]]; then + BIND_ARGS=(--volumes-from "$(hostname)") +else + BIND_ARGS=(-v "${REPO_ROOT}:${REPO_ROOT}:rw") + # If BUILD_DIR lives outside REPO_ROOT (uncommon, but the env-var + # override allows it), mount it explicitly too. + if [[ "${BUILD_DIR}" != "${REPO_ROOT}/"* && "${BUILD_DIR}" != "${REPO_ROOT}" ]]; then + BIND_ARGS+=(-v "${BUILD_DIR}:${BUILD_DIR}:rw") + fi +fi + # --- Run the build inside the container ------------------------------------ # --privileged is required because live-build mounts loop devices and chroots. # --network=host lets the container reach snapshot.debian.org without us # fighting CI proxy config; tighten if/when that becomes a concern. docker run --rm --privileged \ --network=host \ + "${BIND_ARGS[@]}" \ -e SOURCE_DATE_EPOCH \ -e SNAPSHOT_TIMESTAMP \ -e LC_ALL=C.UTF-8 \ -e LANG=C.UTF-8 \ -e TZ=UTC \ - -v "${REPO_ROOT}:/work:rw" \ - -v "${BUILD_DIR}:/out:rw" \ - -w /work \ + -e REPO_ROOT="${REPO_ROOT}" \ + -e BUILD_DIR="${BUILD_DIR}" \ + -w "${REPO_ROOT}" \ "${BUILDER_IMAGE}" \ bash -euo pipefail -c ' # shellcheck disable=SC1091 - source /work/linux/build/config/silvermetal-base.conf + source "${REPO_ROOT}/linux/build/config/silvermetal-base.conf" - cd /work/linux/build/derivative-maker + cd "${REPO_ROOT}/linux/build/derivative-maker" ./derivative-maker \ --build \ @@ -103,18 +132,19 @@ docker run --rm --privileged \ --flavour "${DERIVATIVE_FLAVOUR}" \ --arch "${DERIVATIVE_TARGET_ARCH}" \ --dist "${DERIVATIVE_DIST}" \ - --config /work/linux/build/config/silvermetal-base.conf + --config "${REPO_ROOT}/linux/build/config/silvermetal-base.conf" - # derivative-maker writes into its own build/ dir; collect into /out. - # Exact upstream output paths can shift between tags — keep this - # tolerant. Anything matching *.iso under the tree is what we want. + # derivative-maker writes into its own build/ dir; collect into + # BUILD_DIR. Exact upstream output paths can shift between tags — + # keep this tolerant. Anything matching *.iso under the tree is + # what we want. find . -maxdepth 6 -type f -name "*.iso" -print0 \ - | xargs -0 -I{} cp -av "{}" /out/ + | xargs -0 -I{} cp -av "{}" "${BUILD_DIR}/" # Manifest of file metadata that lives inside the ISO. Useful when # diagnosing reproducibility regressions without re-extracting. find . -maxdepth 6 -type f -name "*.manifest" -print0 \ - | xargs -0 -I{} cp -av "{}" /out/ 2>/dev/null || true + | xargs -0 -I{} cp -av "{}" "${BUILD_DIR}/" 2>/dev/null || true ' || { echo "build.sh: derivative-maker failed"; exit 3; } # --- Hash artefacts ---------------------------------------------------------