From 7cc080dd5d8512420069f26bac0fb360cc5859ae Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 4 Jun 2026 10:30:29 +0000 Subject: [PATCH 1/3] ci: verify release secrets before deploy Replaces debug step with explicit checks for Sonatype token, GPG key import, and GPG passphrase. Each failure points at the matching RELEASING.md section so the fix is clear from the workflow log. Signed-off-by: Gregor Zeitlinger --- .github/workflows/release.yml | 46 ++++++++++++++++++++++++++++++++--- RELEASING.md | 21 ++++++++++++++++ 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2e0732b563..70bab54859 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,14 +18,52 @@ jobs: permissions: {} steps: - - name: Debug gpg key + - name: Verify release secrets env: + MAVEN_USERNAME: ${{ secrets.SONATYPE_MAVEN_REPOSITORY_USERNAME }} + MAVEN_CENTRAL_TOKEN: ${{ secrets.SONATYPE_MAVEN_REPOSITORY_PASSWORD }} GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} + GPG_SIGNING_PASSPHRASE: ${{ secrets.GPG_SIGNING_PASSPHRASE }} run: | - echo "${#GPG_SIGNING_KEY}" - echo "${GPG_SIGNING_KEY}" | gpg --batch --import-options import-show --import + fail() { + echo "::error::$1" + echo "::error::Fix: see '$2' in RELEASING.md" + exit 1 + } + + # Sonatype token + response=$(curl -s -u "${MAVEN_USERNAME}:${MAVEN_CENTRAL_TOKEN}" \ + "https://central.sonatype.com/api/v1/publisher/status?id=test") + echo "Sonatype response: ${response}" + if echo "${response}" | grep -q "Invalid token"; then + fail "Sonatype Central token is invalid." \ + "If the Sonatype Central Token is Invalid" + fi + + # GPG key import + if ! echo "${GPG_SIGNING_KEY}" | gpg --batch --import 2>&1 | \ + tee /tmp/gpg-import.log | grep -q "secret key imported\|secret keys read"; then + cat /tmp/gpg-import.log + fail "GPG_SIGNING_KEY did not import a secret key." \ + "If the GPG Key Expired" + fi + + # GPG passphrase + key_id=$(gpg --list-secret-keys --with-colons | \ + awk -F: '/^sec:/ { print $5; exit }') + if [ -z "${key_id}" ]; then + fail "No secret key available after import." \ + "If the GPG Key Expired" + fi + if ! echo "test" | gpg --batch --pinentry-mode loopback \ + --passphrase "${GPG_SIGNING_PASSPHRASE}" \ + -u "${key_id}" --clearsign >/dev/null 2>/tmp/gpg-sign.log; then + cat /tmp/gpg-sign.log + fail "GPG_SIGNING_PASSPHRASE does not match GPG_SIGNING_KEY." \ + "If the GPG Key Expired" + fi - name: Checkout Plugin Repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ inputs.tag }} persist-credentials: false diff --git a/RELEASING.md b/RELEASING.md index 25f2d59a54..c5ae0ed4b8 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -44,6 +44,27 @@ the benchmarks before merging the release PR: mise run update-benchmarks ``` +## If the Sonatype Central Token is Invalid + +The release workflow verifies the token before deploy. If it fails: + +1. Sign in at and open + View Account -> Generate User Token. +2. Copy the `username` and `password` values from the snippet. +3. Update the secrets: + - + - +4. Verify locally: + + ```shell + curl -i -u "$USER:$PASS" \ + "https://central.sonatype.com/api/v1/publisher/status?id=test" + ``` + + `{"error":{"message":"Invalid token"}}` means the token is still + wrong. Any other response (including 404 for the test id) means the + token works. + ## If the GPG Key Expired 1. Generate a new key: From 81f1aba201eabdf67030034b10d6743ebf389842 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 4 Jun 2026 13:58:50 +0200 Subject: [PATCH 2/3] fix zizmor Signed-off-by: Gregor Zeitlinger --- .github/workflows/acceptance-tests.yml | 2 +- .github/workflows/api-diff.yml | 2 +- .github/workflows/build.yml | 2 +- .github/workflows/codeql.yml | 2 +- .github/workflows/generate-api-diff-baseline.yml | 4 ++-- .github/workflows/generate-protobuf.yml | 4 ++-- .github/workflows/github-pages.yaml | 2 +- .github/workflows/jmx-exporter-compatibility.yml | 2 +- .github/workflows/multi-version-test.yml | 2 +- .github/workflows/native-tests.yml | 2 +- .github/workflows/scorecard.yml | 2 +- .github/workflows/test-release-build.yml | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/acceptance-tests.yml b/.github/workflows/acceptance-tests.yml index 0b3194e0cd..c846a0e452 100644 --- a/.github/workflows/acceptance-tests.yml +++ b/.github/workflows/acceptance-tests.yml @@ -12,7 +12,7 @@ jobs: - name: Check out with: persist-credentials: false - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1 with: version: v2026.5.18 diff --git a/.github/workflows/api-diff.yml b/.github/workflows/api-diff.yml index 99b7844ea7..d0e9c3e87f 100644 --- a/.github/workflows/api-diff.yml +++ b/.github/workflows/api-diff.yml @@ -32,7 +32,7 @@ jobs: ${{ contains(github.event.pull_request.labels.*.name, 'breaking-api-change-accepted') }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c6be7ed7b0..93520b8583 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ jobs: build: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 521dab4f43..625978ffbf 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -21,7 +21,7 @@ jobs: security-events: write # required for github/codeql-action/analyze to upload SARIF steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/generate-api-diff-baseline.yml b/.github/workflows/generate-api-diff-baseline.yml index aee2b4ee69..429a1367d1 100644 --- a/.github/workflows/generate-api-diff-baseline.yml +++ b/.github/workflows/generate-api-diff-baseline.yml @@ -29,7 +29,7 @@ jobs: permissions: contents: read # checkout + read-only `git fetch origin main` for the verify step steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.ref }} persist-credentials: false @@ -90,7 +90,7 @@ jobs: permissions: contents: write # push regenerated docs/apidiffs back to the renovate branch steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.ref }} # zizmor: ignore[artipacked] -- needs credentials to push diff --git a/.github/workflows/generate-protobuf.yml b/.github/workflows/generate-protobuf.yml index e096b58814..377c56d0bc 100644 --- a/.github/workflows/generate-protobuf.yml +++ b/.github/workflows/generate-protobuf.yml @@ -14,7 +14,7 @@ jobs: permissions: contents: read # checkout + read-only `git fetch origin main` for the verify step steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.ref }} persist-credentials: false @@ -66,7 +66,7 @@ jobs: permissions: contents: write # push regenerated sources back to the renovate branch steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.ref }} # zizmor: ignore[artipacked] -- needs credentials to push diff --git a/.github/workflows/github-pages.yaml b/.github/workflows/github-pages.yaml index bd1b58a470..576084a258 100644 --- a/.github/workflows/github-pages.yaml +++ b/.github/workflows/github-pages.yaml @@ -32,7 +32,7 @@ jobs: if: github.repository == 'prometheus/client_java' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false fetch-tags: "true" diff --git a/.github/workflows/jmx-exporter-compatibility.yml b/.github/workflows/jmx-exporter-compatibility.yml index afdaed42d4..c175fddbb4 100644 --- a/.github/workflows/jmx-exporter-compatibility.yml +++ b/.github/workflows/jmx-exporter-compatibility.yml @@ -19,7 +19,7 @@ jobs: jmx-exporter-compatibility: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1 diff --git a/.github/workflows/multi-version-test.yml b/.github/workflows/multi-version-test.yml index a0bfeef76d..8264392fbb 100644 --- a/.github/workflows/multi-version-test.yml +++ b/.github/workflows/multi-version-test.yml @@ -15,7 +15,7 @@ jobs: java: [17, 21, 25] steps: - name: Check out - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/native-tests.yml b/.github/workflows/native-tests.yml index 81e4ed9b98..41ed2a47a3 100644 --- a/.github/workflows/native-tests.yml +++ b/.github/workflows/native-tests.yml @@ -12,7 +12,7 @@ jobs: - name: Check out with: persist-credentials: false - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1 with: version: v2026.5.18 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 532a3787b8..87c9852a23 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -22,7 +22,7 @@ jobs: id-token: write # required by scorecard-action for OIDC token steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/test-release-build.yml b/.github/workflows/test-release-build.yml index 9e88dc4309..de22df7a58 100644 --- a/.github/workflows/test-release-build.yml +++ b/.github/workflows/test-release-build.yml @@ -13,7 +13,7 @@ jobs: build: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false fetch-tags: "true" From 77fc330cce26df40632a34a0cde152b9e8194e0f Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Fri, 5 Jun 2026 09:48:25 +0200 Subject: [PATCH 3/3] fix merge mistake Signed-off-by: Gregor Zeitlinger --- .github/workflows/release.yml | 46 ++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6ba78b44a1..70bab54859 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,14 +18,52 @@ jobs: permissions: {} steps: - - name: Debug gpg key + - name: Verify release secrets env: + MAVEN_USERNAME: ${{ secrets.SONATYPE_MAVEN_REPOSITORY_USERNAME }} + MAVEN_CENTRAL_TOKEN: ${{ secrets.SONATYPE_MAVEN_REPOSITORY_PASSWORD }} GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} + GPG_SIGNING_PASSPHRASE: ${{ secrets.GPG_SIGNING_PASSPHRASE }} run: | - echo "${#GPG_SIGNING_KEY}" - echo "${GPG_SIGNING_KEY}" | gpg --batch --import-options import-show --import + fail() { + echo "::error::$1" + echo "::error::Fix: see '$2' in RELEASING.md" + exit 1 + } + + # Sonatype token + response=$(curl -s -u "${MAVEN_USERNAME}:${MAVEN_CENTRAL_TOKEN}" \ + "https://central.sonatype.com/api/v1/publisher/status?id=test") + echo "Sonatype response: ${response}" + if echo "${response}" | grep -q "Invalid token"; then + fail "Sonatype Central token is invalid." \ + "If the Sonatype Central Token is Invalid" + fi + + # GPG key import + if ! echo "${GPG_SIGNING_KEY}" | gpg --batch --import 2>&1 | \ + tee /tmp/gpg-import.log | grep -q "secret key imported\|secret keys read"; then + cat /tmp/gpg-import.log + fail "GPG_SIGNING_KEY did not import a secret key." \ + "If the GPG Key Expired" + fi + + # GPG passphrase + key_id=$(gpg --list-secret-keys --with-colons | \ + awk -F: '/^sec:/ { print $5; exit }') + if [ -z "${key_id}" ]; then + fail "No secret key available after import." \ + "If the GPG Key Expired" + fi + if ! echo "test" | gpg --batch --pinentry-mode loopback \ + --passphrase "${GPG_SIGNING_PASSPHRASE}" \ + -u "${key_id}" --clearsign >/dev/null 2>/tmp/gpg-sign.log; then + cat /tmp/gpg-sign.log + fail "GPG_SIGNING_PASSPHRASE does not match GPG_SIGNING_KEY." \ + "If the GPG Key Expired" + fi - name: Checkout Plugin Repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ inputs.tag }} persist-credentials: false