RussellSpitzer commented on code in PR #3548: URL: https://github.com/apache/parquet-java/pull/3548#discussion_r3221613321
########## release/bin/publish-release.sh: ########## @@ -0,0 +1,408 @@ +#!/bin/bash +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +LIBS_DIR="${SCRIPT_DIR}/../libs" + +source "${LIBS_DIR}/_constants.sh" +source "${LIBS_DIR}/_log.sh" +source "${LIBS_DIR}/_exec.sh" +source "${LIBS_DIR}/_version.sh" +source "${LIBS_DIR}/_nexus.sh" +source "${LIBS_DIR}/_svn.sh" + +# --------------------------------------------------------------------------- +# Usage +# --------------------------------------------------------------------------- +function usage { + cat <<EOF +Usage: $0 <version> <staging-repo-id> [--rc <num>] [--allow-description-mismatch] + +Publish a release after the vote passes. + +Arguments: + version Release version (e.g., 1.18.0) + staging-repo-id Nexus staging repository ID (e.g., orgapacheparquet-1234) + +Options: + --rc <num> RC number that passed the vote (default: auto-detect latest) + --allow-description-mismatch + Bypass the staging-repo description check (for recovery scenarios) + --help Show this help + +Before any destructive action, this script verifies that the staging repo +belongs to org.apache.parquet, is in 'closed' state, contains +${NEXUS_VERIFY_ARTIFACT_ID:-parquet-common}-<version>.pom, and has a +description matching "Apache Parquet <version> RC<num>". + +The next development version is auto-computed by incrementing the patch +version (e.g., 1.18.0 -> 1.18.1-SNAPSHOT). + +Environment variables: + DRY_RUN Set to 0 for real execution (default: 1) + NEXUS_USERNAME Apache Nexus username + NEXUS_PASSWORD Apache Nexus password + SVN_USERNAME SVN username for dist.apache.org + SVN_PASSWORD SVN password + GITHUB_TOKEN GitHub token for release creation + +Example: + DRY_RUN=1 $0 1.18.0 orgapacheparquet-1234 + DRY_RUN=1 $0 1.18.0 orgapacheparquet-1234 --rc 2 +EOF + exit "${1:-0}" +} + +# --------------------------------------------------------------------------- +# Parse arguments +# --------------------------------------------------------------------------- +version="" +staging_repo_id="" +rc_num="" +allow_description_mismatch=0 +positional=() + +while [[ $# -gt 0 ]]; do + case "$1" in + --rc) + if [[ -z "${2:-}" ]]; then + print_error "--rc requires a value" + usage 1 + fi + rc_num="$2" + shift 2 + ;; + --allow-description-mismatch) + allow_description_mismatch=1 + shift + ;; + --help|-h) + usage 0 + ;; + -*) + print_error "Unknown option: $1" + usage 1 + ;; + *) + positional+=("$1") + shift + ;; + esac +done + +if [[ ${#positional[@]} -lt 2 ]]; then + print_error "Expected 2 positional arguments (version, staging-repo-id), got ${#positional[@]}" + usage 1 +fi + +version="${positional[0]}" +staging_repo_id="${positional[1]}" + +# --------------------------------------------------------------------------- +# Validate inputs +# --------------------------------------------------------------------------- +step_summary "## Release Publication" +step_summary "" + +if [[ ${DRY_RUN:-1} -eq 1 ]]; then + step_summary "> **DRY RUN** -- no changes will be made" + step_summary "" +fi + +if ! validate_and_extract_version "${version}"; then + print_error "Invalid version format: '${version}'" + exit 1 +fi + +next_dev_version="${major}.${minor}.$(( patch + 1 ))" + +if ! [[ "${staging_repo_id}" =~ ^[a-zA-Z][a-zA-Z0-9._-]*$ ]]; then + print_error "Invalid staging repository ID: '${staging_repo_id}'. Expected alphanumeric with dots/hyphens (e.g., orgapacheparquet-1234)." + exit 1 +fi + +if [[ -z "${rc_num}" ]]; then + print_info "No RC number specified, auto-detecting latest RC for ${version}..." + if ! find_latest_rc_number "${version}"; then + exit 1 + fi + rc_num="${latest_rc_number}" + print_info "Auto-detected latest RC: rc${rc_num}" +else + if ! [[ "${rc_num}" =~ ^[0-9]+$ ]]; then + print_error "Invalid RC number: '${rc_num}'. Expected a non-negative integer." + exit 1 + fi + + if find_latest_rc_number "${version}" 2>/dev/null; then + if [[ "${rc_num}" -ne "${latest_rc_number}" ]]; then + print_error "RC${rc_num} is not the latest RC for ${version}. Latest is rc${latest_rc_number}." + print_error "Publishing an older RC is likely a mistake. If intentional, delete the newer RC tags first." + exit 1 + fi + fi +fi + +rc_tag="${TAG_PREFIX}${version}-rc${rc_num}" +final_tag="${TAG_PREFIX}${version}" + +if ! git rev-parse "${rc_tag}" >/dev/null 2>&1; then + print_error "RC tag ${rc_tag} does not exist" + exit 1 +fi + +rc_commit=$(git rev-list -1 "${rc_tag}") +current_commit=$(git rev-parse HEAD) + +if [[ "${current_commit}" != "${rc_commit}" ]]; then + print_error "Current HEAD (${current_commit}) does not match RC tag ${rc_tag} (${rc_commit})" + print_error "The release branch has commits beyond the voted RC. Either reset the branch or create a new RC." + exit 1 +fi + +if git rev-parse "${final_tag}" >/dev/null 2>&1; then + print_error "Final release tag ${final_tag} already exists" + exit 1 +fi + +step_summary "| Parameter | Value |" +step_summary "| --- | --- |" +step_summary "| Version | \`${version}\` |" +step_summary "| RC tag | \`${rc_tag}\` |" +step_summary "| Final tag | \`${final_tag}\` |" +step_summary "| Staging repo | \`${staging_repo_id}\` |" +step_summary "| Next dev version | \`${next_dev_version}-SNAPSHOT\` |" +step_summary "| Commit | \`${rc_commit}\` |" + +# --------------------------------------------------------------------------- +# Step 0: Verify staging repository before any destructive action +# --------------------------------------------------------------------------- +step_summary "" +step_summary "### Staging Repository Verification" + +if ! nexus_verify_staging_repo "${staging_repo_id}" "${version}" "${rc_num}" "${allow_description_mismatch}"; then + step_summary "Staging repository verification: **FAILED**" + exit 1 +fi +step_summary "Staging repository \`${staging_repo_id}\` verified" + +# --------------------------------------------------------------------------- +# Step 1: Move SVN artifacts from dist/dev to dist/release +# --------------------------------------------------------------------------- +step_summary "" +step_summary "### SVN Promotion" + +svn_promote_rc_to_release "${version}" "${rc_num}" + +step_summary "Promoted \`${rc_tag}\` -> \`${final_tag}\` on dist.apache.org" + +# --------------------------------------------------------------------------- +# Step 2: Clean up superseded patch releases on the same minor branch +# --------------------------------------------------------------------------- +# Policy: only patch releases of the *same* minor (parquet-${major}.${minor}.x) Review Comment: So heads up to reviewers, We currently do not have any instructions to remove old releases so this is new. Apache policy says we shouldn't keep *any* old releases here, they should just be in archives. Currently It looks like some Parquet releases were removed and some weren't. *This changes the behavior to only keep one patch per minor.* -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
