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 2e0732b56..70bab5485 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 25f2d59a5..c5ae0ed4b 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 0b3194e0c..c846a0e45 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 99b7844ea..d0e9c3e87 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 c6be7ed7b..93520b858 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 521dab4f4..625978ffb 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 aee2b4ee6..429a1367d 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 e096b5881..377c56d0b 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 bd1b58a47..576084a25 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 afdaed42d..c175fddbb 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 a0bfeef76..8264392fb 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 81e4ed9b9..41ed2a47a 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 532a3787b..87c9852a2 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 9e88dc430..de22df7a5 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 6ba78b44a..70bab5485 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