Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ jobs:
gpg-passphrase: MAVEN_GPG_PASSPHRASE

- name: Publish to Apache Maven Central
run: mvn deploy -P 'release,!default' -Dmaven.test.skip=true
run: >-
./mvnw -B deploy -P 'release,!default,!examples-and-integration-tests'
-Dmaven.test.skip=true
env:
MAVEN_USERNAME: ${{ secrets.SONATYPE_MAVEN_REPOSITORY_USERNAME }}
MAVEN_CENTRAL_TOKEN: ${{ secrets.SONATYPE_MAVEN_REPOSITORY_PASSWORD }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test-release-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ jobs:
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- name: Check release deployment configuration
run: python3 .mise/tasks/test_release_configuration.py
- name: Build GitHub Pages
run: mise run build-gh-pages
env:
Expand Down
2 changes: 1 addition & 1 deletion .mise/tasks/build-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

set -euo pipefail

mvn -B package -P 'release,!default,!examples-and-integration-tests' \
./mvnw -B package -P 'release,!default,!examples-and-integration-tests' \
-Dmaven.test.skip=true -Dgpg.skip=true
34 changes: 34 additions & 0 deletions .mise/tasks/test_release_configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Guard the release reactor configuration without credentials or publishing artifacts."""

import re
import shlex
import unittest
from pathlib import Path

ROOT = Path(__file__).resolve().parents[2]


def profiles(text):
"""Read the single explicit Maven profile selection in a release command."""
selections = re.findall(r"\s-P\s+('[^']*'|\"[^\"]*\"|[^\s]+)", text)
if len(selections) != 1:
raise AssertionError("Expected exactly one explicit Maven -P selection")
return set(shlex.split(selections[0])[0].split(","))


class ReleaseConfigurationTest(unittest.TestCase):
def test_build_and_deploy_use_the_same_release_reactor(self):
build = (ROOT / ".mise/tasks/build-release.sh").read_text()
deploy = (ROOT / ".github/workflows/release.yml").read_text()
expected = {"release", "!default", "!examples-and-integration-tests"}
self.assertEqual(profiles(build), expected)
self.assertEqual(profiles(deploy), profiles(build))

def test_regression_detects_the_failed_release_configuration(self):
build = (ROOT / ".mise/tasks/build-release.sh").read_text()
failed_command = "mvn deploy -P 'release,!default' -Dmaven.test.skip=true"
self.assertNotEqual(profiles(failed_command), profiles(build))


if __name__ == "__main__":
unittest.main()
30 changes: 30 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,36 @@ the benchmarks before merging the release PR:
mise run update-benchmarks
```

## Retrying a Failed Maven Central Deployment

A GitHub release and a Maven Central publication are separate operations.
An immutable GitHub release does not prevent publishing artifacts from its
existing tag. Do not move the tag or rebuild the release from newer source.

Before retrying, check the failed job's full log and the Sonatype Central
Deployments page. Maven reactor `SUCCESS` entries can mean artifacts were
only staged locally; look for an uploaded bundle and deployment ID. If a
deployment is already pending, inspect it before submitting another one.
Already published Maven Central versions cannot be overwritten.

For a workflow-only fix, merge the correction to `main`, then dispatch the
updated workflow with the original release tag:

```shell
gh workflow run release.yml --repo prometheus/client_java --ref main -f tag=v1.9.0
```

Replace `v1.9.0` with the tag being recovered. The workflow comes from `main`,
but its checkout uses the supplied tag. Rerunning the original failed job
instead uses its original workflow and repeats the same configuration error.
Changes to scripts or POMs on `main` are not picked up by that tagged checkout;
those require a separate recovery plan or a new release.

Keep the deployment profile selection aligned with `mise run build-release`:
examples, benchmarks, and integration tests must not enter the release reactor.
The Test Build Release workflow checks this configuration before building.
This check does not validate signing credentials or Sonatype availability.

## If the Sonatype Central Token is Invalid

The release workflow verifies the token before deploy. If it fails:
Expand Down
Loading