From 5304c4a37aadc575c833509f3bcbe49d7e716a59 Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Sat, 25 Jul 2026 08:03:11 +0200 Subject: [PATCH 1/2] Pin reproducibility checks to the deployed snapshot `deploy-snapshot-reusable` now publishes the local staging directory of `nexus-staging-maven-plugin` (the exact bits uploaded to Nexus) as a run artifact. `verify-reproducibility-reusable` accepts a new `reference-artifact-name` input and, when set, uses that artifact as a `file://` reference repository instead of `nexus-url`. This prevents the comparison from picking up a newer snapshot deployed by a concurrent run. Assisted-By: Claude Fable 5 --- .../workflows/deploy-snapshot-reusable.yaml | 14 +++++++ .../verify-reproducibility-reusable.yaml | 41 +++++++++++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-snapshot-reusable.yaml b/.github/workflows/deploy-snapshot-reusable.yaml index 172620d2..29d0feef 100644 --- a/.github/workflows/deploy-snapshot-reusable.yaml +++ b/.github/workflows/deploy-snapshot-reusable.yaml @@ -28,6 +28,9 @@ on: project-version: description: The version of the project value: ${{ jobs.deploy.outputs.project-version }} + repository-artifact-name: + description: Name of the run artifact containing the deployed Maven repository + value: ${{ jobs.deploy.outputs.repository-artifact-name }} secrets: NEXUS_USERNAME: description: Nexus snapshot repository username for deploying artifacts @@ -45,6 +48,7 @@ jobs: runs-on: ubuntu-latest outputs: project-version: ${{ steps.version.outputs.project-version }} + repository-artifact-name: deploy-snapshot-repository steps: - name: Checkout repository @@ -83,3 +87,13 @@ jobs: ./mvnw \ --show-version --batch-mode --errors --no-transfer-progress \ -P deploy + + # `nexus-staging-maven-plugin` gathers the artifacts in this directory before uploading them. + # `verify-reproducibility-reusable` uses this artifact. + - name: Upload deployed repository + uses: actions/upload-artifact@v7 + with: + name: deploy-snapshot-repository + path: target/nexus-staging/deferred + if-no-files-found: error + retention-days: 1 diff --git a/.github/workflows/verify-reproducibility-reusable.yaml b/.github/workflows/verify-reproducibility-reusable.yaml index 99f791e6..825be5eb 100644 --- a/.github/workflows/verify-reproducibility-reusable.yaml +++ b/.github/workflows/verify-reproducibility-reusable.yaml @@ -28,7 +28,14 @@ on: description: Additional Maven arguments type: string nexus-url: - description: The URL of the reference Nexus repository + description: > + The URL of the reference Nexus repository. + Exactly one of `nexus-url` and `reference-artifact-name` must be provided. + type: string + reference-artifact-name: + description: > + Name of a run artifact containing the reference Maven repository. + Exactly one of `nexus-url` and `reference-artifact-name` must be provided. type: string runs-on: description: The type of runners to use as JSON array @@ -37,7 +44,6 @@ on: env: MAVEN_ARGS: ${{ inputs.maven-args }} - NEXUS_URL: ${{ inputs.nexus-url }} # Explicitly drop all permissions inherited from the caller for security. # Reference: https://docs.github.com/en/actions/sharing-automations/reusing-workflows#access-and-permissions @@ -90,15 +96,44 @@ jobs: restore-keys: | ${{ env.CACHE_KEY }}-${{ runner.os }}- + # Contains the exact artifacts deployed by `deploy-snapshot-reusable`. + - name: Download reference repository + if: inputs.reference-artifact-name + uses: actions/download-artifact@v8 + with: + name: ${{ inputs.reference-artifact-name }} + path: ${{ runner.temp }}/reference-repository + # `clean verify artifact:compare` is required to generate the build reproducibility report. # For details, see: https://maven.apache.org/guides/mini/guide-reproducible-builds.html#how-to-test-my-maven-build-reproducibility - name: Verify build reproducibility shell: bash + env: + NEXUS_URL: ${{ inputs.nexus-url }} + REFERENCE_ARTIFACT_NAME: ${{ inputs.reference-artifact-name }} run: | + REFERENCE_REPO="$NEXUS_URL" + + # Computes the URI of the local repository, if `reference-artifact-name` was given. + if [ -n "$REFERENCE_ARTIFACT_NAME" ]; then + TEMP_DIR="$RUNNER_TEMP" + # On Windows, convert `D:\a\_temp` to `D:/a/_temp` + if command -v cygpath > /dev/null; then + TEMP_DIR=$(cygpath -m "$TEMP_DIR") + fi + # Strip the leading `/`, if present, to form a valid `file:///` URL on all platforms + REFERENCE_REPO="file:///${TEMP_DIR#/}/reference-repository" + fi + + # Runs Maven + if [ -z "$REFERENCE_REPO" ]; then + echo '::error::Either `nexus-url` or `reference-artifact-name` must be provided.' + exit 1 + fi ./mvnw \ --show-version --batch-mode --errors --no-transfer-progress \ -DskipTests=true \ - -Dreference.repo="${NEXUS_URL}" \ + -Dreference.repo="${REFERENCE_REPO}" \ clean verify artifact:compare # Upload reproducibility results if the build fails. From 68992096c8ee58988c25716eb78dbdfe9e9c28b6 Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Sat, 25 Jul 2026 08:58:00 +0200 Subject: [PATCH 2/2] Enforce `nexus-url` or `reference-artifact-name`, never both Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../workflows/verify-reproducibility-reusable.yaml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/verify-reproducibility-reusable.yaml b/.github/workflows/verify-reproducibility-reusable.yaml index 825be5eb..63f0298d 100644 --- a/.github/workflows/verify-reproducibility-reusable.yaml +++ b/.github/workflows/verify-reproducibility-reusable.yaml @@ -112,7 +112,12 @@ jobs: NEXUS_URL: ${{ inputs.nexus-url }} REFERENCE_ARTIFACT_NAME: ${{ inputs.reference-artifact-name }} run: | - REFERENCE_REPO="$NEXUS_URL" + REFERENCE_REPO="" + + if [ -n "$NEXUS_URL" ] && [ -n "$REFERENCE_ARTIFACT_NAME" ]; then + echo '::error::Provide exactly one of `nexus-url` or `reference-artifact-name`, not both.' + exit 1 + fi # Computes the URI of the local repository, if `reference-artifact-name` was given. if [ -n "$REFERENCE_ARTIFACT_NAME" ]; then @@ -123,10 +128,9 @@ jobs: fi # Strip the leading `/`, if present, to form a valid `file:///` URL on all platforms REFERENCE_REPO="file:///${TEMP_DIR#/}/reference-repository" - fi - - # Runs Maven - if [ -z "$REFERENCE_REPO" ]; then + elif [ -n "$NEXUS_URL" ]; then + REFERENCE_REPO="$NEXUS_URL" + else echo '::error::Either `nexus-url` or `reference-artifact-name` must be provided.' exit 1 fi