From 9c7327559361316672f46e196b918eeccce5df29 Mon Sep 17 00:00:00 2001 From: Huang Xiao Date: Sun, 2 Aug 2026 09:44:23 +0800 Subject: [PATCH] fix(release): parse Maven 4 project version --- .github/workflows/release.yml | 12 ++++- scripts/verify-release-workflow-test.sh | 64 ++++++++++++++++++++++++- scripts/verify-release-workflow.sh | 14 ++++++ 3 files changed, 86 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9367cd16..88050212 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,7 +43,11 @@ jobs: test "$(git rev-parse HEAD)" = "$(git rev-list -n 1 "${release_tag}")" test -z "$(git status --porcelain)" - version="$(./mvnw -q help:evaluate -Dexpression=project.version -DforceStdout | tail -n 1)" + version="$( + ./mvnw -q help:evaluate -Dexpression=project.version -DforceStdout | + sed -n 's/^\[INFO\] \[stdout\] //p' | + tail -n 1 + )" test "${{ inputs.release_tag }}" = "v${version}" case "${version}" in *-SNAPSHOT) @@ -122,7 +126,11 @@ jobs: ./mvnw -B -Prelease -DskipTests -Dmaven.repo.local="${consumer_pom_repository}" \ -Dgpg.passphrase="${GPG_PASSPHRASE}" install - version="$(./mvnw -q help:evaluate -Dexpression=project.version -DforceStdout | tail -n 1)" + version="$( + ./mvnw -q help:evaluate -Dexpression=project.version -DforceStdout | + sed -n 's/^\[INFO\] \[stdout\] //p' | + tail -n 1 + )" bash scripts/verify-consumer-pom.sh "${consumer_pom_repository}" "${version}" \ "$(command -v mvn)" "$(pwd)/mvnw" echo "CONSUMER_POM_REPOSITORY=${consumer_pom_repository}" >> "${GITHUB_ENV}" diff --git a/scripts/verify-release-workflow-test.sh b/scripts/verify-release-workflow-test.sh index 8ca52db1..132d8ac5 100644 --- a/scripts/verify-release-workflow-test.sh +++ b/scripts/verify-release-workflow-test.sh @@ -45,14 +45,24 @@ jobs: ref: ${{ inputs.release_tag }} - name: Verify immutable release source run: | - version="$(./mvnw -q help:evaluate -Dexpression=project.version -DforceStdout | tail -n 1)" + version="$( + ./mvnw -q help:evaluate -Dexpression=project.version -DforceStdout | + sed -n 's/^\[INFO\] \[stdout\] //p' | + tail -n 1 + )" test "${{ inputs.release_tag }}" = "v${version}" test -z "$(git status --porcelain)" - name: Verify complete CI run: gh run view 1 --json jobs - run: ./mvnw -B -Prelease -DskipTests verify - name: Verify Maven Central Consumer POMs - run: bash scripts/verify-consumer-pom.sh /tmp/repository 1.0.0 mvn ./mvnw + run: | + version="$( + ./mvnw -q help:evaluate -Dexpression=project.version -DforceStdout | + sed -n 's/^\[INFO\] \[stdout\] //p' | + tail -n 1 + )" + bash scripts/verify-consumer-pom.sh /tmp/repository "${version}" mvn ./mvnw - run: ./mvnw -B -Prelease -DskipTests deploy - name: Verify Dependabot security alerts run: gh api repos/${GITHUB_REPOSITORY}/dependabot/alerts @@ -91,6 +101,56 @@ cat >> "${complete_workflow}" <<'YAML' YAML assert_accepts "${complete_workflow}" +legacy_version_extraction_workflow="${temp_dir}/legacy-version-extraction-release.yml" +awk ' + / version="\$\(/ { + print " version=\"\$(./mvnw -q help:evaluate -Dexpression=project.version -DforceStdout | tail -n 1)\"" + skipping = 1 + next + } + skipping && / \)/ { + skipping = 0 + next + } + !skipping { print } +' "${complete_workflow}" > "${legacy_version_extraction_workflow}" +assert_rejects "${legacy_version_extraction_workflow}" + +partially_legacy_version_extraction_workflow="${temp_dir}/partially-legacy-version-extraction-release.yml" +awk ' + / version="\$\(/ { + version_extraction_count++ + if (version_extraction_count == 2) { + print " version=\"\$(./mvnw -q help:evaluate -Dexpression=project.version -DforceStdout | tail -n 1)\"" + skipping = 1 + next + } + } + skipping && / \)/ { + skipping = 0 + next + } + !skipping { print } +' "${complete_workflow}" > "${partially_legacy_version_extraction_workflow}" +assert_rejects "${partially_legacy_version_extraction_workflow}" + +missing_consumer_pom_version_extraction_workflow="${temp_dir}/missing-consumer-pom-version-extraction-release.yml" +awk ' + / version="\$\(/ { + version_extraction_count++ + if (version_extraction_count == 2) { + skipping = 1 + next + } + } + skipping && / \)/ { + skipping = 0 + next + } + !skipping { print } +' "${complete_workflow}" > "${missing_consumer_pom_version_extraction_workflow}" +assert_rejects "${missing_consumer_pom_version_extraction_workflow}" + missing_vulnerability_alerts_permission_workflow="${temp_dir}/missing-vulnerability-alerts-permission-release.yml" grep -v "vulnerability-alerts: read" "${complete_workflow}" > "${missing_vulnerability_alerts_permission_workflow}" assert_rejects "${missing_vulnerability_alerts_permission_workflow}" diff --git a/scripts/verify-release-workflow.sh b/scripts/verify-release-workflow.sh index 9666ac6e..234dbff3 100644 --- a/scripts/verify-release-workflow.sh +++ b/scripts/verify-release-workflow.sh @@ -17,6 +17,18 @@ require_text() { fi } +require_count() { + local text="$1" + local expected_count="$2" + local actual_count + + actual_count="$(grep -Fc -- "${text}" "${workflow_file}" || true)" + if [[ "${actual_count}" != "${expected_count}" ]]; then + echo "Release workflow must contain ${expected_count} occurrence(s) of: ${text}" >&2 + exit 1 + fi +} + forbid_text() { local text="$1" if grep -Fq -- "${text}" "${workflow_file}"; then @@ -32,6 +44,7 @@ require_text "Verify immutable release source" require_text "Verify complete CI" require_text 'test "${{ inputs.release_tag }}" = "v${version}"' require_text 'test -z "$(git status --porcelain)"' +require_count "sed -n 's/^\\[INFO\\] \\[stdout\\] //p'" 2 require_text "gh run view" require_text "actions: read" require_text "-Prelease -DskipTests verify" @@ -54,5 +67,6 @@ require_text "target/*.asc" forbid_text "versions-maven-plugin" forbid_text "versions:set" forbid_text "git push" +forbid_text "-DforceStdout | tail -n 1" echo "Release workflow verification passed: ${workflow_file}"