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
68 changes: 27 additions & 41 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ jobs:
grep -Fq "## [${RELEASE_VERSION}] -" CHANGELOG.md
test -s ".github/release-notes/${RELEASE_VERSION}.md"
scripts/verify-revapi-allowlist.sh
./mvnw --quiet --batch-mode -N -Prelease \
-Dcentral.autoPublish=true -Dcentral.waitUntil=published \
help:effective-pom -Doutput="${RUNNER_TEMP}/effective-pom.xml"
grep -Fq "<autoPublish>true</autoPublish>" "${RUNNER_TEMP}/effective-pom.xml"
grep -Fq "<waitUntil>published</waitUntil>" "${RUNNER_TEMP}/effective-pom.xml"
test -n "${CENTRAL_USERNAME}"
test -n "${CENTRAL_TOKEN}"
test -n "${GPG_PASSPHRASE}"
Expand Down Expand Up @@ -131,65 +136,46 @@ jobs:
shell: bash
run: |
set -euo pipefail
base_url="https://repo1.maven.org/maven2/dev/juherr/datex4j"
missing=0
while read -r artifact_id _packaging; do
[[ -z "${artifact_id}" || "${artifact_id}" == \#* ]] && continue
pom_url="${base_url}/${artifact_id}/${RELEASE_VERSION}/${artifact_id}-${RELEASE_VERSION}.pom"
if ! curl \
--connect-timeout 5 \
--max-time 10 \
--fail \
--silent \
--show-error \
--head \
"${pom_url}" >/dev/null; then
missing=1
break
fi
done < config/release/public-artifacts.txt
if [[ "${missing}" -eq 0 ]]; then
status=0
scripts/check-central-release.sh "${RELEASE_VERSION}" || status=$?
if [[ "${status}" -eq 0 ]]; then
echo "Release ${RELEASE_VERSION} is already available from Maven Central; skipping deploy."
exit 0
fi
if [[ "${status}" -ne 1 ]]; then
echo "Could not determine whether ${RELEASE_VERSION} is published; refusing to deploy." >&2
exit "${status}"
fi
./mvnw --batch-mode --no-transfer-progress \
-Prelease -DskipTests -DautoPublish=true -DwaitUntil=published deploy
-Prelease -DskipTests \
-Dcentral.autoPublish=true -Dcentral.waitUntil=published deploy

- name: Wait for Maven Central resolution
shell: bash
run: |
set -euo pipefail
base_url="https://repo1.maven.org/maven2/dev/juherr/datex4j"
for attempt in $(seq 1 30); do
missing=0
while read -r artifact_id _packaging; do
[[ -z "${artifact_id}" || "${artifact_id}" == \#* ]] && continue
pom_url="${base_url}/${artifact_id}/${RELEASE_VERSION}/${artifact_id}-${RELEASE_VERSION}.pom"
if ! curl \
--connect-timeout 5 \
--max-time 10 \
--fail \
--silent \
--show-error \
--head \
"${pom_url}" >/dev/null; then
missing=1
break
fi
done < config/release/public-artifacts.txt
[[ "${missing}" -eq 0 ]] && break
if [[ "${attempt}" -eq 30 ]]; then
for attempt in $(seq 1 60); do
# Unlike the deploy guard, a transport failure is retried here: this
# loop only waits, so an unreachable Central is just another retry.
status=0
scripts/check-central-release.sh "${RELEASE_VERSION}" || status=$?
if [[ "${status}" -eq 0 ]]; then
break
fi
if [[ "${attempt}" -eq 60 ]]; then
echo "Release did not become resolvable from Maven Central in time." >&2
echo "Check the deployment state at https://central.sonatype.com/publishing/deployments" >&2
echo "Once it reports published, re-run this failed job to keep the released commit." >&2
exit 1
fi
sleep 20
sleep 30
Comment thread
coderabbitai[bot] marked this conversation as resolved.
done
consumer_repository=$(mktemp -d)
./mvnw --batch-mode --no-transfer-progress \
-f config/release-smoke/pom.xml \
-Dmaven.repo.local="${consumer_repository}" \
-Ddatex4j.version="${RELEASE_VERSION}" \
-Ddatex4j.repository="${base_url%/dev/juherr/datex4j}" \
-Ddatex4j.repository="https://repo1.maven.org/maven2" \
verify

finalize:
Expand Down
13 changes: 13 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,16 @@ Release steps:

The workflow safely resumes when its signed tag or GitHub Release already exists at the same
commit. It refuses conflicting tags or releases.

Resume a failed release with `gh run rerun <run-id> --failed` rather than a new dispatch. A re-run
keeps the original commit, so the signed tag still points at the code that produced the published
artifacts. The publishing job skips the deploy only when `scripts/check-central-release.sh` resolves
every published file — each POM plus the main, sources, and javadoc jars — so a partially propagated
release still redeploys instead of being frozen. The re-run then replays the remaining verification,
tag, and release steps.

The publishing job drives `central-publishing-maven-plugin` through the `central.autoPublish` and
`central.waitUntil` properties. The root POM binds them into an explicit plugin `<configuration>`,
which takes precedence over the plugin's own `autoPublish` and `waitUntil` user properties — those
`-D` flags are silently ignored. `Validate release inputs` asserts the effective POM resolves to
`true` and `published` before anything is uploaded.
69 changes: 69 additions & 0 deletions scripts/check-central-release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
set -euo pipefail

if [[ $# -ne 1 ]]; then
echo "Usage: $0 <version>" >&2
exit 2
fi

version=$1
project_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
inventory="${project_root}/config/release/public-artifacts.txt"
base_url=${CENTRAL_BASE_URL:-https://repo1.maven.org/maven2/dev/juherr/datex4j}

# Exit 0: every payload resolves. Exit 1: Central answered, something is absent.
# Exit 2: Central could not be questioned. Callers must not read 2 as "absent" —
# deploying on a transport failure would republish an already published version.
resolves() {
local url=$1
local http_code curl_status=0

http_code=$(curl \
--connect-timeout 5 \
--max-time 10 \
--silent \
--head \
--output /dev/null \
--write-out '%{http_code}' \
"${url}") || curl_status=$?

if [[ "${curl_status}" -ne 0 ]]; then
echo "Maven Central is unreachable (curl exit ${curl_status}): ${url}" >&2
exit 2
fi

case "${http_code}" in
200) return 0 ;;
404) return 1 ;;
*)
echo "Unexpected HTTP ${http_code} from Maven Central: ${url}" >&2
exit 2
;;
esac
}

# Mirrors the payload set asserted locally by verify-central-bundle.sh, so a
# release is only considered complete once every published file resolves.
while read -r artifact_id packaging; do
[[ -z "${artifact_id}" || "${artifact_id}" == \#* ]] && continue

base="${base_url}/${artifact_id}/${version}/${artifact_id}-${version}"
payloads=("${base}.pom")
case "${packaging}" in
jar)
payloads+=("${base}.jar" "${base}-sources.jar" "${base}-javadoc.jar")
;;
pom) ;;
*)
echo "Unsupported packaging '${packaging}' for ${artifact_id}" >&2
exit 2
;;
esac

for payload in "${payloads[@]}"; do
if ! resolves "${payload}"; then
echo "Not published to Maven Central: ${payload}" >&2
exit 1
fi
done
done < "${inventory}"
Loading