diff --git a/build.gradle b/build.gradle index ab4b16a146..2f86927075 100644 --- a/build.gradle +++ b/build.gradle @@ -200,7 +200,10 @@ subprojects { // But since the dependsOn is within the conditional, the dependency is not created for release versions // so the publish in that case is never executed. if (version.toString().endsWith('SNAPSHOT')) { - dependsOn tasks.publish + exec { + workingDir project.projectDir + commandLine 'bash', "${project.rootDir}/scripts/snapshot_management.sh", project.name, project.version + } } doFirst { if (!version.toString().endsWith('SNAPSHOT')) { diff --git a/scripts/publish_to_maven_central.sh b/scripts/publish_to_maven_central.sh index 76157c5e13..ac7ba9cc87 100644 --- a/scripts/publish_to_maven_central.sh +++ b/scripts/publish_to_maven_central.sh @@ -12,11 +12,25 @@ echo "Executing in directory = $(pwd)" zipfile=${subproject}.${version}.zip -pushd build/local-repo -zip -qr ${zipfile} * - -bearer_token=$(echo "$MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME:$MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD" | base64) - +# Ensure jq is available if later used by callers; not strictly required here but helpful to surface missing deps early. +if ! command -v jq >/dev/null 2>&1; then + echo "Warning: jq not found. Some scripts expect jq for JSON parsing. Continue if you're sure it's not needed." +fi + +pushd build/local-repo >/dev/null +zip -qr "${zipfile}" * + +# Build Authorization header: prefer an explicit bearer token, otherwise fall back to Basic auth built from username/password +if [ -n "${MAVEN_CENTRAL_PORTAL_BEARER_TOKEN:-}" ]; then + auth_header="Authorization: Bearer ${MAVEN_CENTRAL_PORTAL_BEARER_TOKEN}" +elif [ -n "${MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME:-}" ] && [ -n "${MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD:-}" ]; then + basic_token=$(echo -n "${MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME}:${MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD}" | base64 | tr -d '\n') + auth_header="Authorization: Basic ${basic_token}" +else + echo "Error: No credentials found. Set MAVEN_CENTRAL_PORTAL_BEARER_TOKEN or MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME and MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD." + popd >/dev/null || true + exit 1 +fi # Upload to maven central. # publishingType=USER_MANAGED means that the artefacts will be uploaded and verified, but not yet published. @@ -24,12 +38,8 @@ bearer_token=$(echo "$MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME:$MAVEN_CENTRAL_PORTAL_ # From this page you can examine the list of artefacts, and either drop them or release them. # If you want to remove that step, use publishingType=AUTOMATIC below, that will publish directly. # Note that once published you cannot remove or alter the artifacts. -answer=$(curl --request POST \ - --verbose \ - --header "Authorization: Bearer ${bearer_token}" \ - --form bundle="@${zipfile}" \ - 'https://central.sonatype.com/api/v1/publisher/upload?publishingType=USER_MANAGED') +answer=$(curl --request POST --silent --show-error --header "${auth_header}" --form bundle="@${zipfile}" 'https://central.sonatype.com/api/v1/publisher/upload?publishingType=USER_MANAGED') echo "curl request answer: $answer" -popd \ No newline at end of file +popd >/dev/null \ No newline at end of file diff --git a/scripts/snapshot_management.sh b/scripts/snapshot_management.sh new file mode 100644 index 0000000000..237dedd334 --- /dev/null +++ b/scripts/snapshot_management.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# This script manages the uploading of snapshots to the Maven Central snapshot repository, and deletion of the associated snapshots after a set retention time. +set -e + +subproject=$1 +version=$2 + +echo "Running $(basename $0) for subproject \"$subproject\" and version \"$version\"" +echo "Executing in directory = $(pwd)" + +zipfile=${subproject}.${version}.zip + +# Ensure jq is available for JSON parsing +if ! command -v jq >/dev/null 2>&1; then + echo "Error: jq is required but not installed. Please install jq and retry." + exit 1 +fi + +pushd build/local-repo >/dev/null +zip -qr "${zipfile}" * + +# Build Authorization header: prefer an explicit bearer token, otherwise fall back to Basic auth built from username/password +if [ -n "${MAVEN_CENTRAL_PORTAL_BEARER_TOKEN:-}" ]; then + auth_header="Authorization: Bearer ${MAVEN_CENTRAL_PORTAL_BEARER_TOKEN}" +elif [ -n "${MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME:-}" ] && [ -n "${MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD:-}" ]; then + basic_token=$(echo -n "${MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME}:${MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD}" | base64 | tr -d '\n') + auth_header="Authorization: Basic ${basic_token}" +else + echo "Error: No credentials found. Set MAVEN_CENTRAL_PORTAL_BEARER_TOKEN or MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME and MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD." + popd >/dev/null || true + exit 1 +fi + +# Delete older snapshots before uploading the newest one to the project's snapshot repository on Maven Central. +# Query the deployments/files endpoint and delete each returned deployment id. +response=$(curl -s --request POST --header "${auth_header}" 'https://central.sonatype.com/api/v1/publisher/deployments/files') +if [ -z "${response}" ]; then + echo "No response from Sonatype when listing deployments." +else + staleIds=$(echo "${response}" | jq -r '.deploymentIds[]?') + if [ -z "${staleIds}" ]; then + echo "No stale deployment ids found." + else + for id in ${staleIds}; do + echo "Deleting stale deployment id: ${id}" + curl -s --request DELETE --header "${auth_header}" "https://central.sonatype.com/api/v1/publisher/deployments/${id}" || echo "Warning: failed to delete deployment ${id}" + done + fi +fi + +# Publish to the snapshot repository automatically (no manual intervention). +answer=$(curl --request POST --silent --show-error --header "${auth_header}" --form bundle="@${zipfile}" 'https://central.sonatype.com/api/v1/publisher/upload?publishingType=AUTOMATIC') + +echo "curl request answer: $answer" + +popd >/dev/null