name: immutable-release on: push: tags: - "v*.*.*" concurrency: group: release-${{ gitea.ref_name }} cancel-in-progress: false jobs: release: runs-on: ubuntu-latest timeout-minutes: 45 environment: production steps: - name: Check out immutable tag uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 - name: Install pinned .NET SDK uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 with: dotnet-version: 10.0.301 - name: Install pinned Buildx and BuildKit uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 with: version: v0.35.0 install: true driver-opts: image=moby/buildkit:v0.25.2@sha256:0f63d66f8d2de0bd16438284831a3e9ee6ca7cd57b6eb3ed6e38a7a456590fa7 - name: Validate tag and produce reproducible artifacts shell: bash run: | set -euo pipefail version="${GITHUB_REF_NAME#v}" ./scripts/check-release-tag.sh "$GITHUB_REF_NAME" previous_tag="$(git tag --merged HEAD^ --list 'v*.*.*' --sort=-version:refname | sed -n '1p')" if [[ -n "$previous_tag" ]]; then ./scripts/check-compatibility.sh "$previous_tag" elif [[ -n "$(git tag --list 'v*.*.*' | sed -n '1p')" ]]; then echo "No prior release tag is an ancestor of $GITHUB_REF_NAME." >&2 exit 1 else ./scripts/check-compatibility.sh __initial_release_without_base__ fi release_builder="rendezvous-release-builder:${GITHUB_SHA}" docker buildx build \ --platform linux/amd64 \ --file eng/release-builder.Dockerfile \ --target release-builder \ --load \ --tag "$release_builder" . mkdir -p "${RUNNER_TEMP}/release-home" "${RUNNER_TEMP}/nuget" docker run --rm \ --user "$(id -u):$(id -g)" \ --env HOME="${RUNNER_TEMP}/release-home" \ --env NUGET_PACKAGES="${RUNNER_TEMP}/nuget" \ --volume "$GITHUB_WORKSPACE:/source" \ --volume "${RUNNER_TEMP}:${RUNNER_TEMP}" \ --workdir /source \ "$release_builder" \ ./scripts/build-release.sh "$version" "${RUNNER_TEMP}/release/$version" ./scripts/verify-real-consumers.sh "$version" "${RUNNER_TEMP}/release/$version" echo "RENDEZVOUS_VERSION=$version" >>"$GITHUB_ENV" echo "RENDEZVOUS_RELEASE_DIR=${RUNNER_TEMP}/release/$version" >>"$GITHUB_ENV" echo "RENDEZVOUS_RELEASE_BUILDER=$release_builder" >>"$GITHUB_ENV" - name: Build exact container candidate shell: bash run: | set -euo pipefail export SOURCE_DATE_EPOCH="$(git show -s --format=%ct HEAD)" common=( --no-cache --pull=false --provenance=false --platform linux/amd64 --build-arg SOURCE_DATE_EPOCH="$SOURCE_DATE_EPOCH" --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" docker buildx build "${common[@]}" --tag "$release_tag" \ --output "type=docker,dest=$image_one,rewrite-timestamp=true" . docker buildx build "${common[@]}" --tag "$release_tag" \ --output "type=docker,dest=$image_two,rewrite-timestamp=true" . cmp --silent "$image_one" "$image_two" docker load --input "$image_one" candidate_id="$(docker image inspect --format '{{.Id}}' "$release_tag")" buildkit_version="$(docker buildx inspect --bootstrap | sed -n 's/.*BuildKit version: *//p' | sed -n '1p')" docker run --rm \ --user "$(id -u):$(id -g)" \ --volume "$GITHUB_WORKSPACE:/source" \ --volume "${RUNNER_TEMP}:${RUNNER_TEMP}" \ --workdir /source \ "$RENDEZVOUS_RELEASE_BUILDER" \ python3 eng/release_artifacts.py record-container-build \ --provenance "$RENDEZVOUS_RELEASE_DIR/release-provenance.json" \ --buildx-version "$(docker buildx version)" \ --buildkit-version "$buildkit_version" \ --image-id "$candidate_id" - name: Stage HTTP registration, browse, and authenticated UDP traversal shell: bash run: | set -euo pipefail secret="deploy/compose/secrets/signing-key" cleanup() { RENDEZVOUS_UID=1654 RENDEZVOUS_GID=1654 RENDEZVOUS_IMAGE="git.finalfactory.de/heikyu/rendezvous:${RENDEZVOUS_VERSION}" \ docker compose -f deploy/compose/compose.yaml down --volumes >/dev/null 2>&1 || true rm -f "$secret" } trap cleanup EXIT install -d -m 0700 deploy/compose/secrets openssl rand -out "$secret" 32 chmod 0444 "$secret" export RENDEZVOUS_UID=1654 export RENDEZVOUS_GID=1654 export RENDEZVOUS_IMAGE="git.finalfactory.de/heikyu/rendezvous:${RENDEZVOUS_VERSION}" docker compose -f deploy/compose/compose.yaml up --detach --no-build for attempt in {1..100}; do curl --fail --silent http://127.0.0.1:8080/health/ready >/dev/null 2>&1 && break if (( attempt == 100 )); then docker compose -f deploy/compose/compose.yaml logs rendezvous exit 1 fi sleep 0.1 done ./scripts/smoke-deployment.sh - name: Scan candidate for high and critical vulnerabilities uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0, post-incident safe SHA with: image-ref: git.finalfactory.de/heikyu/rendezvous:${{ env.RENDEZVOUS_VERSION }} version: v0.69.3 format: table exit-code: "1" ignore-unfixed: false severity: HIGH,CRITICAL - name: Generate container SPDX inventory uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0, post-incident safe SHA with: image-ref: git.finalfactory.de/heikyu/rendezvous:${{ env.RENDEZVOUS_VERSION }} version: v0.69.3 format: spdx-json output: ${{ env.RENDEZVOUS_RELEASE_DIR }}/FinalFactory.Rendezvous.Container.${{ env.RENDEZVOUS_VERSION }}.spdx.json - name: Finalize checksums over the publish-ready candidate shell: bash run: | set -euo pipefail source_date_epoch="$(git show -s --format=%ct HEAD)" docker run --rm \ --user "$(id -u):$(id -g)" \ --volume "$GITHUB_WORKSPACE:/source" \ --volume "${RUNNER_TEMP}:${RUNNER_TEMP}" \ --workdir /source \ "$RENDEZVOUS_RELEASE_BUILDER" \ bash -c 'python3 eng/release_artifacts.py normalize-container-sbom \ --file "$1/FinalFactory.Rendezvous.Container.$2.spdx.json" \ --version "$2" \ --commit "$3" \ --source-date-epoch "$4" \ && ./scripts/finalize-release-candidate.sh "$2" "$1"' \ _ "$RENDEZVOUS_RELEASE_DIR" "$RENDEZVOUS_VERSION" "$GITHUB_SHA" "$source_date_epoch" - name: Preserve verified candidate artifacts uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: rendezvous-${{ env.RENDEZVOUS_VERSION }} path: ${{ env.RENDEZVOUS_RELEASE_DIR }} if-no-files-found: error retention-days: 30 - name: Install pinned signing client uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 with: cosign-release: v3.0.6 - name: Publish once, sign, attest, and create release shell: bash env: RENDEZVOUS_RELEASE_USERNAME: ${{ secrets.RELEASE_USERNAME }} RENDEZVOUS_RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }} COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} run: ./scripts/publish-release.sh "$RENDEZVOUS_VERSION" "$RENDEZVOUS_RELEASE_DIR"