diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index b7d1053..b9af025 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -262,7 +262,13 @@ jobs: _ "$RENDEZVOUS_RELEASE_DIR" "$RENDEZVOUS_VERSION" "$GITHUB_SHA" "$source_date_epoch" - name: Preserve verified candidate artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + # upload-artifact@v4 speaks the v2 artifacts API, which this Gitea only + # answers at its v3-era shape, so v4 aborts before uploading anything. + # Keeping the candidate is a pre-publish debugging backstop, not a + # release gate: publish-release.sh attaches the same files as Gitea + # release assets, so a failure here must never block a release. + continue-on-error: true + uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 with: name: rendezvous-${{ env.RENDEZVOUS_VERSION }} path: ${{ env.RENDEZVOUS_RELEASE_DIR }} @@ -270,9 +276,29 @@ jobs: retention-days: 30 - name: Install pinned signing client - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - with: - cosign-release: v3.0.6 + shell: bash + run: | + set -euo pipefail + # cosign-installer issues no API call on the pinned path, but it is a + # composite action resting on `envsubst` and a resolved runner.arch, + # neither of which this runner has ever exercised. Asked for the same + # version it bootstraps, the action downloads exactly this asset and + # checks it against exactly this digest before declaring itself done, + # so fetching it directly verifies identically with nothing unproven + # left in the path. The digest is pinned inline for the reason the + # scanner's is: a checksums file fetched at run time only proves the + # asset matches whatever the release currently serves. + cosign_bin_dir="$RENDEZVOUS_WORK_DIR/bin" + mkdir -p "$cosign_bin_dir" + curl --fail --location --silent --show-error --output "$cosign_bin_dir/cosign" \ + https://github.com/sigstore/cosign/releases/download/v3.0.6/cosign-linux-amd64 + echo "c956e5dfcac53d52bcf058360d579472f0c1d2d9b69f55209e256fe7783f4c74 $cosign_bin_dir/cosign" \ + | sha256sum --check --strict - + chmod +x "$cosign_bin_dir/cosign" + # publish-release.sh resolves cosign through `command -v`, so the + # directory joins the PATH the same way the action would have added it. + echo "$cosign_bin_dir" >>"$GITHUB_PATH" + "$cosign_bin_dir/cosign" version - name: Publish once, sign, attest, and create release shell: bash diff --git a/tests/FinalFactory.Rendezvous.Tests/Release/ReleaseCompatibilityTests.cs b/tests/FinalFactory.Rendezvous.Tests/Release/ReleaseCompatibilityTests.cs index 1ef3656..41dc24b 100644 --- a/tests/FinalFactory.Rendezvous.Tests/Release/ReleaseCompatibilityTests.cs +++ b/tests/FinalFactory.Rendezvous.Tests/Release/ReleaseCompatibilityTests.cs @@ -97,6 +97,31 @@ public sealed class ReleaseCompatibilityTests StringComparison.Ordinal); Assert.Contains("sha256sum --check --strict", workflow, StringComparison.Ordinal); Assert.Contains("TRIVY_CACHE_DIR=$RENDEZVOUS_WORK_DIR/trivy-cache", workflow, StringComparison.Ordinal); + + // Gitea answers the v3-era artifacts API only, so upload-artifact stays on + // v3 and never gates the release it is only meant to help debug. + Assert.DoesNotContain( + "actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02", + workflow, + StringComparison.Ordinal); + Assert.Contains( + "actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1", + workflow, + StringComparison.Ordinal); + Assert.Contains("continue-on-error: true", workflow, StringComparison.Ordinal); + + // The signing client is fetched the way the scanner is: a pinned asset + // checked against a pinned digest, with no action resolved off github.com. + Assert.DoesNotContain("sigstore/cosign-installer", workflow, StringComparison.Ordinal); + Assert.Contains( + "https://github.com/sigstore/cosign/releases/download/v3.0.6/cosign-linux-amd64", + workflow, + StringComparison.Ordinal); + Assert.Contains( + "c956e5dfcac53d52bcf058360d579472f0c1d2d9b69f55209e256fe7783f4c74", + workflow, + StringComparison.Ordinal); + Assert.Contains("echo \"$cosign_bin_dir\" >>\"$GITHUB_PATH\"", workflow, StringComparison.Ordinal); Assert.Contains("--exit-code 1", workflow, StringComparison.Ordinal); Assert.Contains("--severity HIGH,CRITICAL", workflow, StringComparison.Ordinal); Assert.DoesNotContain("--ignore-unfixed", workflow, StringComparison.Ordinal);