diff --git a/.github/workflows/maven-publish.yaml b/.github/workflows/maven-publish.yaml index ac3a688c..9588e08b 100644 --- a/.github/workflows/maven-publish.yaml +++ b/.github/workflows/maven-publish.yaml @@ -5,7 +5,7 @@ # file is GPG-signed. The destination is chosen inside this workflow with # `rapids-is-release-build`: # - release build (vYY.MM.PP tag) -> Maven Central via the Sonatype Central -# Publisher Portal (OSSRH staging + validation, human-gated publish). +# Publisher Portal API (validation, human-gated publish). # - non-release build (nightly, branch push) -> Sonatype snapshot repository # (direct HTTP PUT, immediately available, no staging or portal step). name: Maven publish @@ -36,15 +36,6 @@ on: required: false type: string default: '' - profile-id: - description: | - Sonatype staging profile to search, if different from the Maven groupId read from - the POM (e.g. a verified parent namespace like com.nvidia for a com.nvidia.cuopt - groupId). Defaults to the groupId when not set. Only applies to the Maven Central - path (release builds); ignored on the snapshot path. - required: false - type: string - default: '' secrets: GPG_PRIVATE_KEY: description: Armored GPG private key used to sign every artifact at upload. @@ -124,13 +115,9 @@ jobs: --output-bundle central-bundle.zip --auto-drop "${AUTO_DROP}" ) - if [[ -n ${PROFILE_ID} ]]; then - args+=(--profile-id "${PROFILE_ID}") - fi shared-workflows/ci/maven-publish/maven_central_publish.sh "${args[@]}" env: GROUP_ID: ${{ steps.prepare.outputs.GROUP_ID }} - PROFILE_ID: ${{ inputs.profile-id }} ARTIFACT_ID: ${{ steps.prepare.outputs.ARTIFACT_ID }} VERSION: ${{ steps.prepare.outputs.VERSION }} # Invert: stage-for-...=true means don't auto-drop. diff --git a/ci/maven-publish/maven_central_publish.sh b/ci/maven-publish/maven_central_publish.sh index ab6f357a..e8fa4fa5 100755 --- a/ci/maven-publish/maven_central_publish.sh +++ b/ci/maven-publish/maven_central_publish.sh @@ -2,10 +2,10 @@ # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -# Creates a deployment bundle from a signed Maven repository tree, uploads its -# files through Sonatype's OSSRH staging compatibility API, and polls the -# Publisher Portal until the deployment passes validation. -# Never calls the /publish endpoint: publication always requires a human click. +# Creates a deployment bundle from a signed Maven repository tree, uploads it to +# the Central Publisher Portal with the Publisher API, and polls until the +# deployment passes validation. +# Never calls the publish endpoint: publication always requires a human click. set -euo pipefail @@ -19,7 +19,6 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" . "${SCRIPT_DIR}/maven_central_publish_steps.sh" CENTRAL_PORTAL_URL="https://central.sonatype.com" -OSSRH_STAGING_API_URL="https://ossrh-staging-api.central.sonatype.com" # Used by wait_for_validated in the sourced step library. # shellcheck disable=SC2034 POLL_INTERVAL_SEC=15 @@ -28,7 +27,6 @@ POLL_TIMEOUT_SEC=900 INPUT_DIR="" GROUP_ID="" -PROFILE_ID="" ARTIFACT_ID="" VERSION="" OUTPUT_BUNDLE="" @@ -42,9 +40,9 @@ Usage: maven_central_publish.sh --input --group-id \\ --output-bundle [OPTIONS] Copies a signed Maven repository tree into scratch space, generates .md5 and -.sha1 sidecars, and creates a retained ZIP. It uploads the repository files -individually through Sonatype's OSSRH staging compatibility API, then hands the -repository to the Central Publisher Portal without publishing it. +.sha1 sidecars, and creates a retained ZIP. It uploads the ZIP to the Central +Publisher Portal with the Publisher API as a USER_MANAGED deployment, so it is +never published without a human click. REQUIRED: -i, --input Signed Maven repository directory. @@ -54,18 +52,13 @@ REQUIRED: -o, --output-bundle Path for the retained deployment ZIP. OPTIONS: - --profile-id

Sonatype staging profile to search, if different from - --group-id (e.g. a verified parent namespace like - com.nvidia for a com.nvidia.cuopt groupId). Defaults to - --group-id. --auto-drop Drop after VALIDATED (default: true). -h, --help Show this help message. ENVIRONMENT VARIABLES: MAVEN_DEPLOY_USERNAME Publisher Portal user token username. MAVEN_DEPLOY_TOKEN Publisher Portal user token password. - GITHUB_OUTPUT If set, receives STAGING_REPOSITORY_KEY and - DEPLOYMENT_ID. + GITHUB_OUTPUT If set, receives DEPLOYMENT_ID. EOF } @@ -87,11 +80,6 @@ parse_args() { GROUP_ID=$2 shift 2 ;; - --profile-id) - require_value "$1" "${2:-}" - PROFILE_ID=$2 - shift 2 - ;; -a|--artifact-id) require_value "$1" "${2:-}" ARTIFACT_ID=$2 @@ -134,11 +122,6 @@ if [[ ${AUTO_DROP} != "true" && ${AUTO_DROP} != "false" ]]; then fi require_maven_coordinates "${GROUP_ID}" "${ARTIFACT_ID}" "${VERSION}" require_release_version "${VERSION}" -# A groupId nested under a verified parent namespace (e.g. com.nvidia.cuopt under the -# verified com.nvidia) still searches/creates its OSSRH staging repo under the parent's -# Sonatype profile, not the full groupId string -- so default to GROUP_ID, but let callers -# override it. -PROFILE_ID="${PROFILE_ID:-${GROUP_ID}}" if [[ ! -d ${INPUT_DIR} ]]; then fatal "--input '${INPUT_DIR}' does not exist or is not a directory" fi @@ -157,44 +140,18 @@ if [[ -e ${OUTPUT_BUNDLE} ]]; then fi echo "Maven Central upload" echo " coordinates: ${GROUP_ID}:${ARTIFACT_ID}:${VERSION}" -echo " profile: ${PROFILE_ID}" echo " auto-drop: ${AUTO_DROP}" echo " input dir: ${INPUT_DIR}" echo " output bundle: ${OUTPUT_BUNDLE}" -echo " staging API: ${OSSRH_STAGING_API_URL}" -echo " target portal: ${CENTRAL_PORTAL_URL}" +echo " portal: ${CENTRAL_PORTAL_URL}" WORK_DIR="$(mktemp -d)" -STAGING_REPOSITORY_KEY="" -STAGING_FILE_UPLOADED="false" -STAGING_HANDED_OFF="false" - -cleanup() { - local status=$? - if (( status != 0 )) \ - && [[ ${STAGING_FILE_UPLOADED} == "true" ]] \ - && [[ ${STAGING_HANDED_OFF} != "true" ]]; then - if [[ -z ${STAGING_REPOSITORY_KEY} ]]; then - STAGING_REPOSITORY_KEY=$(staging_search_repositories open 2>/dev/null \ - | jq -r 'if (.repositories | length) == 1 then .repositories[0].key else empty end' \ - 2>/dev/null) || true - fi - if [[ -n ${STAGING_REPOSITORY_KEY} ]]; then - echo "Cleaning up open OSSRH staging repository ${STAGING_REPOSITORY_KEY}" >&2 - staging_drop_repository "${STAGING_REPOSITORY_KEY}" \ - || echo "Warning: could not drop staging repository ${STAGING_REPOSITORY_KEY}; remove it before retrying" >&2 - fi - fi - rm -rf "${WORK_DIR}" - return "${status}" -} -trap cleanup EXIT +trap 'rm -rf "${WORK_DIR}"' EXIT BUNDLE_DIR="${WORK_DIR}/bundle" BUNDLE_ARTIFACT_DIR="${BUNDLE_DIR}/$(maven_group_path "${GROUP_ID}")/${ARTIFACT_ID}/${VERSION}" mkdir -p "${BUNDLE_DIR}" -require_no_open_staging_repository copy_bundle "${INPUT_DIR}" "${BUNDLE_DIR}" require_bundle_contents "${BUNDLE_ARTIFACT_DIR}" generate_bundle_checksums "${BUNDLE_ARTIFACT_DIR}" @@ -203,15 +160,14 @@ BUNDLE_ZIP="${WORK_DIR}/${ARTIFACT_ID}-${VERSION}.zip" create_bundle_zip "${BUNDLE_ZIP}" "${BUNDLE_DIR}" mv "${BUNDLE_ZIP}" "${OUTPUT_BUNDLE}" -DEPLOYMENT_ID="" -upload_tree_to_staging "${BUNDLE_DIR}" -find_open_staging_repository -echo "Handing staging repository to the Publisher Portal" -staging_handoff_repository "${STAGING_REPOSITORY_KEY}" -wait_for_portal_handoff "${STAGING_REPOSITORY_KEY}" -STAGING_HANDED_OFF="true" +PUBLISHING_TYPE="USER_MANAGED" +echo "Uploading bundle to the Publisher Portal" +DEPLOYMENT_ID=$(portal_upload_bundle "${OUTPUT_BUNDLE}" "${GROUP_ID}:${ARTIFACT_ID}:${VERSION}" "${PUBLISHING_TYPE}") +if [[ ! ${DEPLOYMENT_ID} =~ ^[A-Za-z0-9-]+$ ]]; then + fatal "Publisher Portal returned an invalid deployment id" +fi +echo " Portal deployment id: ${DEPLOYMENT_ID}" if [[ -n ${GITHUB_OUTPUT:-} ]]; then - echo "STAGING_REPOSITORY_KEY=${STAGING_REPOSITORY_KEY}" >> "${GITHUB_OUTPUT}" echo "DEPLOYMENT_ID=${DEPLOYMENT_ID}" >> "${GITHUB_OUTPUT}" fi diff --git a/ci/maven-publish/maven_central_publish_steps.sh b/ci/maven-publish/maven_central_publish_steps.sh index f803c62d..1d49f3f9 100644 --- a/ci/maven-publish/maven_central_publish_steps.sh +++ b/ci/maven-publish/maven_central_publish_steps.sh @@ -2,7 +2,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -# Sonatype HTTP wrappers and local bundle helpers for maven_central_publish.sh. +# Central Publisher Portal HTTP wrappers and local bundle helpers for maven_central_publish.sh. _portal_auth() { printf '%s:%s' "${MAVEN_DEPLOY_USERNAME}" "${MAVEN_DEPLOY_TOKEN}" \ @@ -38,58 +38,28 @@ _sonatype_call() { rm -f "${body_file}" } -# _sonatype_upload FILE URL -# Basic auth, PUT FILE. Logs failure and returns 1 on non-2xx. -_sonatype_upload() { - local upload_file=$1 url=$2 - local body_file status +# portal_upload_bundle ZIP NAME PUBLISHING_TYPE +# Bearer auth, multipart POST of the bundle. Prints the deployment id on 201; +# logs failure and returns 1 otherwise. +portal_upload_bundle() { + local zip_path=$1 name=$2 publishing_type=$3 + local body_file status url + url="${CENTRAL_PORTAL_URL}/api/v1/publisher/upload?publishingType=${publishing_type}&name=$(printf %s "${name}" | jq -sRr @uri)" body_file=$(mktemp) status=$(curl -sS --retry 3 --retry-delay 2 \ - --user "${MAVEN_DEPLOY_USERNAME}:${MAVEN_DEPLOY_TOKEN}" \ - --upload-file "${upload_file}" \ - -o "${body_file}" -w '%{http_code}' "${url}") \ + -H "Authorization: Bearer $(_portal_auth)" \ + --form "bundle=@${zip_path};type=application/octet-stream" \ + -X POST -o "${body_file}" -w '%{http_code}' "${url}") \ || status="transport-error" - if [[ ${status} != 2* ]]; then - _sonatype_error_log PUT "${url}" "${status}" "${body_file}" >&2 + if [[ ${status} != 201 ]]; then + _sonatype_error_log POST "${url}" "${status}" "${body_file}" >&2 rm -f "${body_file}" return 1 fi + tr -d '[:space:]' < "${body_file}" rm -f "${body_file}" } -staging_search_repositories() { - local state=${1:-} - local url - url="${OSSRH_STAGING_API_URL}/manual/search/repositories?ip=client&profile_id=$(printf %s "${PROFILE_ID}" | jq -sRr @uri)" - if [[ -n ${state} ]]; then - url+="&state=$(printf %s "${state}" | jq -sRr @uri)" - fi - _sonatype_call GET "${url}" -} - -staging_upload_file() { - local file_path=$1 repository_path=$2 - local encoded_path - encoded_path=$(jq -rn --arg path "${repository_path}" \ - '$path | split("/") | map(@uri) | join("/")') - _sonatype_upload "${file_path}" \ - "${OSSRH_STAGING_API_URL}/service/local/staging/deploy/maven2/${encoded_path}" -} - -staging_handoff_repository() { - local repository_key=$1 - _sonatype_call POST \ - "${OSSRH_STAGING_API_URL}/manual/upload/repository/${repository_key}?publishing_type=portal_api" \ - >/dev/null -} - -staging_drop_repository() { - local repository_key=$1 - _sonatype_call DELETE \ - "${OSSRH_STAGING_API_URL}/manual/drop/repository/${repository_key}" \ - >/dev/null -} - portal_get_status() { local deployment_id=$1 _sonatype_call POST \ @@ -149,76 +119,6 @@ create_bundle_zip() { (cd "${bundle_dir}" && zip -qr "${zip_path}" .) } -require_no_open_staging_repository() { - local response count - response=$(staging_search_repositories open) - count=$(jq -er '.repositories | length' <<< "${response}") \ - || fatal "OSSRH staging search returned an invalid response" - if (( count != 0 )); then - jq . <<< "${response}" >&2 || true - fatal "found ${count} open OSSRH staging repository/repositories for ${PROFILE_ID} from this IP; drop or hand them off before retrying" - fi -} - -upload_tree_to_staging() { - local root=$1 file repository_path count=0 - echo "Uploading Maven repository files to the OSSRH staging service" - while IFS= read -r -d '' file; do - repository_path=${file#"${root}/"} - staging_upload_file "${file}" "${repository_path}" - # Consumed by the EXIT cleanup trap in maven_central_publish.sh. - # shellcheck disable=SC2034 - STAGING_FILE_UPLOADED="true" - count=$((count + 1)) - done < <(find "${root}" -type f -print0) - echo " uploaded files: ${count}" -} - -find_open_staging_repository() { - local response count - response=$(staging_search_repositories open) - count=$(jq -er '.repositories | length' <<< "${response}") \ - || fatal "OSSRH staging search returned an invalid response" - if (( count != 1 )); then - jq . <<< "${response}" >&2 || true - fatal "expected exactly one open OSSRH staging repository after upload, found ${count}" - fi - STAGING_REPOSITORY_KEY=$(jq -er '.repositories[0].key | select(type == "string" and length > 0)' \ - <<< "${response}") || fatal "OSSRH staging response did not contain a repository key" - # Keys are composite paths of the form //--default-repository, - # so slashes are expected. Just guard against characters that would break URL path use. - if [[ ! ${STAGING_REPOSITORY_KEY} =~ ^[A-Za-z0-9._/-]+$ ]]; then - fatal "OSSRH staging service returned an invalid repository key: ${STAGING_REPOSITORY_KEY}" - fi - echo " staging repository: ${STAGING_REPOSITORY_KEY}" -} - -wait_for_portal_handoff() { - local repository_key=$1 - local response state elapsed=0 - echo "Polling OSSRH staging handoff (interval=${POLL_INTERVAL_SEC}s, timeout=${POLL_TIMEOUT_SEC}s)" - while (( elapsed < POLL_TIMEOUT_SEC )); do - response=$(staging_search_repositories) - state=$(jq -r --arg key "${repository_key}" \ - '.repositories[]? | select(.key == $key) | .state // "UNKNOWN"' \ - <<< "${response}") - DEPLOYMENT_ID=$(jq -r --arg key "${repository_key}" \ - '.repositories[]? | select(.key == $key) | .portal_deployment_id // empty' \ - <<< "${response}") - echo " [${elapsed}s] staging state=${state:-UNKNOWN}" - if [[ -n ${DEPLOYMENT_ID} ]]; then - if [[ ! ${DEPLOYMENT_ID} =~ ^[A-Za-z0-9-]+$ ]]; then - fatal "OSSRH staging service returned an invalid Portal deployment id" - fi - echo " Portal deployment id: ${DEPLOYMENT_ID}" - return 0 - fi - sleep "${POLL_INTERVAL_SEC}" - elapsed=$((elapsed + POLL_INTERVAL_SEC)) - done - fatal "timed out waiting for OSSRH staging repository '${repository_key}' to reach the Portal" -} - wait_for_validated() { local deployment_id=$1 local response state elapsed=0 diff --git a/ci/maven-publish/test_maven_central_publish_integration.sh b/ci/maven-publish/test_maven_central_publish_integration.sh index 53bb277c..62aa9b41 100755 --- a/ci/maven-publish/test_maven_central_publish_integration.sh +++ b/ci/maven-publish/test_maven_central_publish_integration.sh @@ -21,45 +21,48 @@ for suffix in \ printf 'content for %s\n' "${suffix}" > "${ARTIFACT_DIR}/example-26.08.0${suffix}" done -# This is the literal contents of the mock curl executable; its variables must -# expand only when that executable runs. -# shellcheck disable=SC2016 -MOCK_CURL='#!/bin/bash +cat > "${MOCK_BIN}/curl" <<'EOF' +#!/bin/bash set -euo pipefail -printf "%s\n" "$*" >> "${MOCK_STATE_DIR}/curl.log" +printf '%s\n' "$*" >> "${MOCK_STATE_DIR}/curl.log" +out=/dev/null +method=GET +args=("$@") +for ((i = 0; i < ${#args[@]}; i++)); do + case "${args[i]}" in + -o) out=${args[i + 1]} ;; + -X) method=${args[i + 1]} ;; + --form) + bundle=${args[i + 1]#bundle=@} + cp "${bundle%%;*}" "${MOCK_STATE_DIR}/uploaded.zip" + ;; + esac +done case "$*" in - *manual/search/repositories*state=open*) - if [[ ${PREEXISTING_OPEN:-false} == true || -f ${MOCK_STATE_DIR}/uploaded ]]; then - printf "%s\n" '\''{"repositories":[{"key":"repo-key","state":"open","portal_deployment_id":"","warnings":[]}]} '\'' + *publisher/upload*) + if [[ ${FAIL_UPLOAD:-false} == true ]]; then + echo '{"error":"bad bundle"}' > "${out}" + printf 400 else - printf "%s\n" '\''{"repositories":[]}'\'' + echo 00000000-0000-0000-0000-000000000001 > "${out}" + printf 201 fi ;; - *--upload-file*) - touch "${MOCK_STATE_DIR}/uploaded" - printf "%s\n" "$*" >> "${MOCK_STATE_DIR}/uploads.log" - upload_count=$(wc -l < "${MOCK_STATE_DIR}/uploads.log") - if [[ ${FAIL_UPLOAD:-false} == true && ${upload_count} -gt 1 ]]; then - exit 22 - fi + *publisher/status*) + echo "{\"deploymentState\":\"${DEPLOYMENT_STATE:-VALIDATED}\"}" > "${out}" + printf 200 ;; - *manual/upload/repository/repo-key*publishing_type=portal_api*) - touch "${MOCK_STATE_DIR}/handed-off" + *publisher/deployment/*) + [[ ${method} == DELETE ]] && touch "${MOCK_STATE_DIR}/dropped" + : > "${out}" + printf 204 ;; - *manual/search/repositories*) - if [[ -f ${MOCK_STATE_DIR}/handed-off ]]; then - printf "%s\n" '\''{"repositories":[{"key":"repo-key","state":"released","portal_deployment_id":"00000000-0000-0000-0000-000000000001","warnings":[]}]} '\'' - else - echo "repository searched before handoff" >&2 - exit 1 - fi + *) + echo "unexpected curl invocation: $*" >&2 + exit 1 ;; - *publisher/status*) printf "%s\n" '\''{"deploymentState":"VALIDATED"}'\'' ;; - *publisher/deployment/*) touch "${MOCK_STATE_DIR}/portal-dropped" ;; - *manual/drop/repository/*) touch "${MOCK_STATE_DIR}/staging-dropped" ;; - *) echo "unexpected curl invocation: $*" >&2; exit 1 ;; -esac' -printf '%s\n' "${MOCK_CURL}" > "${MOCK_BIN}/curl" +esac +EOF chmod +x "${MOCK_BIN}/curl" export PATH="${MOCK_BIN}:${PATH}" @@ -67,59 +70,56 @@ export GITHUB_OUTPUT MOCK_STATE_DIR export MAVEN_DEPLOY_USERNAME=test-user export MAVEN_DEPLOY_TOKEN=test-token -OUTPUT_BUNDLE="${TEST_ROOT}/central-bundle.zip" -"${SCRIPT_DIR}/maven_central_publish.sh" \ - --input "${TEST_ROOT}/signed" \ - --group-id ai.rapids \ - --artifact-id example \ - --version 26.08.0 \ - --output-bundle "${OUTPUT_BUNDLE}" \ - --auto-drop true +publish() { + "${SCRIPT_DIR}/maven_central_publish.sh" \ + --input "${TEST_ROOT}/signed" \ + --group-id ai.rapids \ + --artifact-id example \ + --version 26.08.0 \ + --output-bundle "${TEST_ROOT}/bundle-$1.zip" \ + --auto-drop "$2" +} + +reset_state() { + rm -rf "${MOCK_STATE_DIR:?}"/* + : > "${GITHUB_OUTPUT}" +} -unzip -tq "${OUTPUT_BUNDLE}" >/dev/null -unzip -l "${OUTPUT_BUNDLE}" | grep -F 'example-26.08.0.jar.asc.sha1' -grep -Fx 'STAGING_REPOSITORY_KEY=repo-key' "${GITHUB_OUTPUT}" +reset_state +publish drop true + +unzip -tq "${TEST_ROOT}/bundle-drop.zip" >/dev/null +unzip -l "${TEST_ROOT}/bundle-drop.zip" | grep -F 'example-26.08.0.jar.asc.sha1' grep -Fx 'DEPLOYMENT_ID=00000000-0000-0000-0000-000000000001' "${GITHUB_OUTPUT}" -[[ $(wc -l < "${MOCK_STATE_DIR}/uploads.log") -eq 24 ]] -grep -F -- '--upload-file' "${MOCK_STATE_DIR}/uploads.log" \ - | grep -F '/ai/rapids/example/26.08.0/example-26.08.0.jar.asc.sha1' -grep -F 'manual/upload/repository/repo-key?publishing_type=portal_api' \ - "${MOCK_STATE_DIR}/curl.log" -if grep -Fq 'api/v1/publisher/upload' "${MOCK_STATE_DIR}/curl.log"; then - echo "bundle upload endpoint must not be used" >&2 +grep -F 'api/v1/publisher/upload?publishingType=USER_MANAGED' "${MOCK_STATE_DIR}/curl.log" +grep -F 'Authorization: Bearer dGVzdC11c2VyOnRlc3QtdG9rZW4=' "${MOCK_STATE_DIR}/curl.log" +grep -F 'bundle=@' "${MOCK_STATE_DIR}/curl.log" +unzip -l "${MOCK_STATE_DIR}/uploaded.zip" | grep -F 'ai/rapids/example/26.08.0/example-26.08.0.jar' +if grep -Fq 'ossrh-staging-api' "${MOCK_STATE_DIR}/curl.log"; then + echo "the legacy OSSRH staging API must not be used" >&2 exit 1 fi -[[ -f ${MOCK_STATE_DIR}/portal-dropped ]] -[[ ! -f ${MOCK_STATE_DIR}/staging-dropped ]] +[[ -f ${MOCK_STATE_DIR}/dropped ]] -rm -f "${MOCK_STATE_DIR}"/* -export PREEXISTING_OPEN=true -if "${SCRIPT_DIR}/maven_central_publish.sh" \ - --input "${TEST_ROOT}/signed" \ - --group-id ai.rapids \ - --artifact-id example \ - --version 26.08.0 \ - --output-bundle "${TEST_ROOT}/blocked-bundle.zip" \ - --auto-drop true; then - echo "a pre-existing open staging repository must block publication" >&2 - exit 1 -fi -[[ ! -e ${MOCK_STATE_DIR}/uploads.log ]] -[[ ! -e ${MOCK_STATE_DIR}/staging-dropped ]] +reset_state +publish keep false +[[ ! -f ${MOCK_STATE_DIR}/dropped ]] -rm -f "${MOCK_STATE_DIR}"/* -export PREEXISTING_OPEN=false +reset_state export FAIL_UPLOAD=true -if "${SCRIPT_DIR}/maven_central_publish.sh" \ - --input "${TEST_ROOT}/signed" \ - --group-id ai.rapids \ - --artifact-id example \ - --version 26.08.0 \ - --output-bundle "${TEST_ROOT}/failed-upload-bundle.zip" \ - --auto-drop true; then +if publish failed-upload true; then echo "an upload failure must fail publication" >&2 exit 1 fi -[[ -f ${MOCK_STATE_DIR}/staging-dropped ]] +[[ ! -f ${MOCK_STATE_DIR}/dropped ]] +unset FAIL_UPLOAD + +reset_state +export DEPLOYMENT_STATE=FAILED +if publish failed-validation true; then + echo "a FAILED deployment must fail publication" >&2 + exit 1 +fi +[[ ! -f ${MOCK_STATE_DIR}/dropped ]] echo "Maven Central publish integration test passed"