Files
Rendezvous/scripts/verify-real-consumers.sh
KyuubiYoru d41fa0c7e9 fix(release): repair tag gate and sibling-container publication (#1)
The release workflow could not complete on the self-hosted sibling-container
runner. Four defects are corrected together because three of them share the
same release.yml plumbing.

Exclude the tag under release from the prior-tag probe. check-release-tag.sh
already requires the tag to point at HEAD, so the unfiltered listing always
matched itself and rejected every first release before the initial baseline
branch could run.

Resolve host bind sources once per job. Steps run inside the runner container
while docker run starts siblings on the host daemon, so GITHUB_WORKSPACE and
RUNNER_TEMP are not usable as bind sources. A new step maps both to host paths
through the runner's own mounts and exports them; the build, provenance, smoke,
finalize, and publish steps reuse them, and publish-release.sh receives them by
environment instead of repeating the inspection. Bind destinations stay at the
container-internal paths so runner-side reads keep working unchanged.

Prove the signing material before the first push. Gitea package versions are
immutable, so a missing or undecryptable cosign key must abort ahead of the
require_absent gate rather than after packages and the image are published.

Authenticate the pinned consumer fetches. Both consumer repositories are
private, so anonymous fetches fail; the release token is passed to the
verification step and applied as a URL-scoped extra header through git's
config environment, keeping it out of argv, remotes, and on-disk config.
Anonymous fetch remains the fallback for local runs.
2026-08-22 19:47:57 +02:00

100 lines
3.7 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
version="${1:?usage: verify-real-consumers.sh VERSION RELEASE_DIRECTORY}"
release_dir="${2:?usage: verify-real-consumers.sh VERSION RELEASE_DIRECTORY}"
manifest="$root/eng/consumer-revisions.json"
# The pinned consumers live in private repositories, so release automation must
# authenticate. Keep the token in the environment git reads config from: it must
# never reach argv, the remote URL, or on-disk repository configuration.
token="${RENDEZVOUS_CONSUMER_TOKEN:-${RENDEZVOUS_RELEASE_TOKEN:-}}"
export GIT_TERMINAL_PROMPT=0
work="$(mktemp -d "${TMPDIR:-/tmp}/rendezvous-consumers.XXXXXX")"
cleanup() {
rm -rf "$work"
}
trap cleanup EXIT
for command in dotnet git jq python3; do
command -v "$command" >/dev/null || {
echo "Required consumer verification command is unavailable: $command" >&2
exit 1
}
done
fetch_consumer_revision() {
local checkout="$1"
local repository="$2"
local revision="$3"
if [[ -z "$token" ]]; then
git -C "$checkout" fetch --quiet --depth 1 origin "$revision"
return
fi
GIT_CONFIG_COUNT=1 \
GIT_CONFIG_KEY_0="http.${repository}.extraHeader" \
GIT_CONFIG_VALUE_0="Authorization: token ${token}" \
git -C "$checkout" fetch --quiet --depth 1 origin "$revision"
}
python3 "$root/eng/release_artifacts.py" consumer-config \
--local-source "$release_dir" \
--output "$work/NuGet.config"
count="$(jq '.consumers | length' "$manifest")"
for ((index = 0; index < count; index++)); do
name="$(jq -r ".consumers[$index].name" "$manifest")"
repository="$(jq -r ".consumers[$index].repository" "$manifest")"
revision="$(jq -r ".consumers[$index].revision" "$manifest")"
project_relative="$(jq -r ".consumers[$index].project" "$manifest")"
checkout="$work/$name"
git -c init.defaultBranch=main init --quiet "$checkout"
git -C "$checkout" remote add origin "$repository"
fetch_consumer_revision "$checkout" "$repository" "$revision"
GIT_LFS_SKIP_SMUDGE=1 git -C "$checkout" checkout --quiet --detach FETCH_HEAD
[[ "$(git -C "$checkout" rev-parse HEAD)" == "$revision" ]] || {
echo "$name did not resolve the pinned consumer revision." >&2
exit 1
}
project="$checkout/$project_relative"
[[ -f "$project" ]] || {
echo "$name consumer project does not exist at $project_relative." >&2
exit 1
}
targets="$work/$name.Rendezvous.Consumer.targets"
cat >"$targets" <<EOF
<Project>
<ItemGroup Condition="'\$(MSBuildProjectFullPath)' == '$project'">
<PackageReference Remove="FinalFactory.Rendezvous.Client" />
<PackageReference Remove="FinalFactory.Rendezvous.Contracts" />
<PackageReference Include="FinalFactory.Rendezvous.Client" Version="[$version]" />
<PackageReference Include="FinalFactory.Rendezvous.Contracts" Version="[$version]" />
</ItemGroup>
</Project>
EOF
packages="$work/packages-$name"
dotnet restore "$project" \
-p:CustomAfterMicrosoftCommonTargets="$targets" \
-p:RestorePackagesWithLockFile=false \
-p:RestoreLockedMode=false \
--packages "$packages" \
--configfile "$work/NuGet.config" \
--force-evaluate
assets=""
while IFS= read -r candidate_assets; do
if grep -Fq "FinalFactory.Rendezvous.Client/$version" "$candidate_assets"; then
assets="$candidate_assets"
break
fi
done < <(find "$checkout" -path '*/obj/project.assets.json' -type f -print)
[[ -n "$assets" ]] || {
echo "$name restore did not produce assets for the injected Rendezvous references." >&2
exit 1
}
python3 "$root/eng/release_artifacts.py" consumer \
--assets "$assets" \
--version "$version"
echo "Verified $name at $revision can pin and restore Rendezvous $version."
done