fix(release): share sibling paths through the workspace (#1)
quality-gate / quality (push) Successful in 2m42s
quality-gate / container (push) Successful in 2m9s
immutable-release / release (push) Failing after 6m7s

The release job stopped at the bind-source gate. RUNNER_TEMP is
container-internal on this runner and no runner mount exposes it on the Docker
host, so no sibling container could ever share it; only the workspace is
host-mounted.

Move every path shared between the runner's shell steps and its sibling
containers under $GITHUB_WORKSPACE/.release-work: the release directory, the
release builder's HOME and NuGet cache, both candidate image tars, and the
container SPDX inventory. Resolution now maps the workspace alone to its host
path, and each sibling binds that source at $GITHUB_WORKSPACE and works from
there instead of /source, so a shared path is the same string on both sides of
the boundary. publish-release.sh follows with a single bind and requires the
release directory to sit inside the workspace.

Ignore .release-work in Git so the tag gate's cleanliness check stays true while
artifacts accumulate, and in Docker so artifacts written between the two
candidate builds cannot alter the build context the byte-comparison gate
depends on. Skip it in the dependency inventory as well, keeping the restored
package cache out of the license policy scan.
This commit is contained in:
KyuubiYoru
2026-08-22 20:31:18 +02:00
parent c5bc9651e5
commit 4233f12368
5 changed files with 61 additions and 51 deletions
+39 -43
View File
@@ -20,38 +20,36 @@ jobs:
with:
fetch-depth: 0
- name: Resolve host bind sources for sibling containers
- name: Resolve the host bind source for sibling containers
shell: bash
run: |
set -euo pipefail
# This job's steps run inside the runner container while every
# `docker run` starts a sibling container on the host daemon, so bind
# sources must be host paths. Resolve them once from the runner's own
# mounts and reuse them in every later step.
# sources must be host paths. The workspace is the only runner mount
# backed by the host, so every path shared with a sibling lives under
# it and a single bind source is resolved once here. Siblings mount
# that source at $GITHUB_WORKSPACE, which keeps every shared path the
# same string on both sides of the boundary.
echo "RENDEZVOUS_WORK_DIR=$GITHUB_WORKSPACE/.release-work" >>"$GITHUB_ENV"
if ! mounts="$(docker inspect "$HOSTNAME" 2>/dev/null | jq -c '.[0].Mounts')"; then
echo "Runner is not containerized; using workspace and temp paths as host paths."
echo "Runner is not containerized; using the workspace path as its own host path."
echo "RENDEZVOUS_WORKSPACE_SOURCE=$GITHUB_WORKSPACE" >>"$GITHUB_ENV"
echo "RENDEZVOUS_TEMP_SOURCE=$RUNNER_TEMP" >>"$GITHUB_ENV"
exit 0
fi
resolve_host_path() {
jq -er --arg path "$1" '
[ .[]
| .Destination as $destination
| select($path == $destination
or ($path | startswith($destination + "/"))) ]
| if length == 0 then
error("No runner mount exposes \($path) on the Docker host.")
else
sort_by(.Destination | length) | last
end
| (.Destination | length) as $prefix
| .Source + $path[$prefix:]' <<<"$mounts"
}
workspace_source="$(resolve_host_path "$GITHUB_WORKSPACE")"
temp_source="$(resolve_host_path "$RUNNER_TEMP")"
workspace_source="$(jq -er --arg path "$GITHUB_WORKSPACE" '
[ .[]
| .Destination as $destination
| select($path == $destination
or ($path | startswith($destination + "/"))) ]
| if length == 0 then
error("No runner mount exposes \($path) on the Docker host.")
else
sort_by(.Destination | length) | last
end
| (.Destination | length) as $prefix
| .Source + $path[$prefix:]' <<<"$mounts")"
echo "RENDEZVOUS_WORKSPACE_SOURCE=$workspace_source" >>"$GITHUB_ENV"
echo "RENDEZVOUS_TEMP_SOURCE=$temp_source" >>"$GITHUB_ENV"
- name: Install pinned .NET SDKs
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
@@ -94,20 +92,19 @@ jobs:
--target release-builder \
--load \
--tag "$release_builder" .
mkdir -p "${RUNNER_TEMP}/release-home" "${RUNNER_TEMP}/nuget"
release_dir="$RENDEZVOUS_WORK_DIR/release/$version"
mkdir -p "$RENDEZVOUS_WORK_DIR/release-home" "$RENDEZVOUS_WORK_DIR/nuget"
docker run --rm \
--user "$(id -u):$(id -g)" \
--env HOME="${RUNNER_TEMP}/release-home" \
--env NUGET_PACKAGES="${RUNNER_TEMP}/nuget" \
--volume "$RENDEZVOUS_WORKSPACE_SOURCE:/source" \
--volume "$RENDEZVOUS_TEMP_SOURCE:${RUNNER_TEMP}" \
--workdir /source \
--env HOME="$RENDEZVOUS_WORK_DIR/release-home" \
--env NUGET_PACKAGES="$RENDEZVOUS_WORK_DIR/nuget" \
--volume "$RENDEZVOUS_WORKSPACE_SOURCE:$GITHUB_WORKSPACE" \
--workdir "$GITHUB_WORKSPACE" \
"$release_builder" \
./scripts/build-release.sh "$version" "${RUNNER_TEMP}/release/$version"
./scripts/verify-real-consumers.sh "$version" "${RUNNER_TEMP}/release/$version"
./scripts/build-release.sh "$version" "$release_dir"
./scripts/verify-real-consumers.sh "$version" "$release_dir"
echo "RENDEZVOUS_VERSION=$version" >>"$GITHUB_ENV"
echo "RENDEZVOUS_RELEASE_DIR=${RUNNER_TEMP}/release/$version" >>"$GITHUB_ENV"
echo "RENDEZVOUS_RELEASE_DIR_SOURCE=${RENDEZVOUS_TEMP_SOURCE}/release/$version" >>"$GITHUB_ENV"
echo "RENDEZVOUS_RELEASE_DIR=$release_dir" >>"$GITHUB_ENV"
echo "RENDEZVOUS_RELEASE_BUILDER=$release_builder" >>"$GITHUB_ENV"
- name: Build exact container candidate
@@ -124,8 +121,10 @@ jobs:
--build-arg SOURCE_REVISION_ID="$GITHUB_SHA"
)
release_tag="git.finalfactory.de/heikyu/rendezvous:${RENDEZVOUS_VERSION}"
image_one="${RUNNER_TEMP}/rendezvous-image-1.tar"
image_two="${RUNNER_TEMP}/rendezvous-image-2.tar"
# .release-work is excluded from the build context, so the tar written
# by the first build cannot change the context the second one sees.
image_one="$RENDEZVOUS_WORK_DIR/rendezvous-image-1.tar"
image_two="$RENDEZVOUS_WORK_DIR/rendezvous-image-2.tar"
docker buildx build "${common[@]}" --tag "$release_tag" \
--output "type=docker,dest=$image_one,rewrite-timestamp=true" .
docker buildx build "${common[@]}" --tag "$release_tag" \
@@ -136,9 +135,8 @@ jobs:
buildkit_version="$(docker buildx inspect --bootstrap | sed -n 's/.*BuildKit version: *//p' | sed -n '1p')"
docker run --rm \
--user "$(id -u):$(id -g)" \
--volume "$RENDEZVOUS_WORKSPACE_SOURCE:/source" \
--volume "$RENDEZVOUS_TEMP_SOURCE:${RUNNER_TEMP}" \
--workdir /source \
--volume "$RENDEZVOUS_WORKSPACE_SOURCE:$GITHUB_WORKSPACE" \
--workdir "$GITHUB_WORKSPACE" \
"$RENDEZVOUS_RELEASE_BUILDER" \
python3 eng/release_artifacts.py record-container-build \
--provenance "$RENDEZVOUS_RELEASE_DIR/release-provenance.json" \
@@ -184,8 +182,8 @@ jobs:
--env RENDEZVOUS_SMOKE_HTTP_URL=http://127.0.0.1:8080/ \
--env RENDEZVOUS_SMOKE_UDP_ENDPOINT=127.0.0.1:9050 \
--env RENDEZVOUS_PUBLISHER_CREDENTIAL \
--volume "$runner_workspace_source:/source:ro" \
--workdir /source \
--volume "$runner_workspace_source:$GITHUB_WORKSPACE:ro" \
--workdir "$GITHUB_WORKSPACE" \
"$RENDEZVOUS_RELEASE_BUILDER" \
bash -lc '
for attempt in {1..180}; do
@@ -223,9 +221,8 @@ jobs:
source_date_epoch="$(git show -s --format=%ct HEAD)"
docker run --rm \
--user "$(id -u):$(id -g)" \
--volume "$RENDEZVOUS_WORKSPACE_SOURCE:/source" \
--volume "$RENDEZVOUS_TEMP_SOURCE:${RUNNER_TEMP}" \
--workdir /source \
--volume "$RENDEZVOUS_WORKSPACE_SOURCE:$GITHUB_WORKSPACE" \
--workdir "$GITHUB_WORKSPACE" \
"$RENDEZVOUS_RELEASE_BUILDER" \
bash -c 'python3 eng/release_artifacts.py normalize-container-sbom \
--file "$1/FinalFactory.Rendezvous.Container.$2.spdx.json" \
@@ -256,5 +253,4 @@ jobs:
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
RENDEZVOUS_WORKSPACE_SOURCE: ${{ env.RENDEZVOUS_WORKSPACE_SOURCE }}
RENDEZVOUS_RELEASE_DIR_SOURCE: ${{ env.RENDEZVOUS_RELEASE_DIR_SOURCE }}
run: ./scripts/publish-release.sh "$RENDEZVOUS_VERSION" "$RENDEZVOUS_RELEASE_DIR"