This is an automated email from the ASF dual-hosted git repository.
Aias00 pushed a commit to branch 2.7.1-release
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/2.7.1-release by this push:
new d4ff742225 Remove release.sh from source tree (moved to parent
directory)
d4ff742225 is described below
commit d4ff742225a276d1552bcc8cb761be8f7de924cc
Author: liuhy <[email protected]>
AuthorDate: Wed Jun 17 09:37:25 2026 +0800
Remove release.sh from source tree (moved to parent directory)
---
release.sh | 1115 ------------------------------------------------------------
1 file changed, 1115 deletions(-)
diff --git a/release.sh b/release.sh
deleted file mode 100755
index cca4c7e829..0000000000
--- a/release.sh
+++ /dev/null
@@ -1,1115 +0,0 @@
-#!/usr/bin/env 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.
-#
-# ----------------------------------------------------------------------------
-# Apache ShenYu Release Script
-# Version: 2.7.1
-#
-# Usage:
-# ./release.sh <step> [options]
-#
-# Steps:
-# 1 - Prerequisites check
-# 2 - Maven release:prepare dry-run
-# 3 - Maven release:prepare (actual)
-# 4 - Maven release:perform
-# 5 - Publish to SVN dev repository
-# 6 - Verify release artifacts
-# 7 - Print voting email templates
-# 8 - Final release (after vote passes)
-# all - Run steps 1-6 sequentially
-# clean - Rollback: delete branch, tags, and clean Maven release artifacts
-#
-# Environment variables (can also be passed via options):
-# RELEASE_VERSION - Version to release (default: 2.7.1)
-# NEXT_VERSION - Next SNAPSHOT version (default: 2.7.2-SNAPSHOT)
-# GPG_KEY - GPG key ID (default: auto-detect from git user)
-# APACHE_USER - Apache LDAP username
-# GPG_PASSPHRASE - GPG key passphrase
-# SHENYU_HOME - Path to shenyu source (default: script directory)
-# SVN_DEV_DIR - Local SVN dev checkout dir (default:
~/svn_release/dev/shenyu)
-# SVN_RELEASE_DIR - Local SVN release checkout dir (default:
~/svn_release/release/shenyu)
-# ----------------------------------------------------------------------------
-
-set -euo pipefail
-
-# ========================= Configuration =========================
-
-RELEASE_VERSION="${RELEASE_VERSION:-2.7.1}"
-NEXT_VERSION="${NEXT_VERSION:-2.7.2-SNAPSHOT}"
-APACHE_USER="${APACHE_USER:-liuhongyu}"
-GPG_KEY="${GPG_KEY:-}"
-GPG_PASSPHRASE="${GPG_PASSPHRASE:-}"
-SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
-SHENYU_HOME="${SHENYU_HOME:-${SCRIPT_DIR}}"
-SVN_DEV_DIR="${SVN_DEV_DIR:-${HOME}/svn_release/dev/shenyu}"
-SVN_RELEASE_DIR="${SVN_RELEASE_DIR:-${HOME}/svn_release/release/shenyu}"
-RELEASE_BRANCH="${RELEASE_VERSION}-release"
-GIT_TAG="v${RELEASE_VERSION}"
-
-# Colors
-RED='\033[0;31m'
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-BLUE='\033[0;34m'
-NC='\033[0m' # No Color
-
-# ========================= Helper Functions =========================
-
-log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
-log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
-log_error() { echo -e "${RED}[ERROR]${NC} $*"; }
-log_step() { echo -e "\n${BLUE}========== STEP $1: $2 ==========${NC}\n"; }
-
-confirm() {
- local prompt="$1"
- local default="${2:-n}"
- local answer
- if [[ "$default" == "y" ]]; then
- read -rp "$(echo -e "${YELLOW}${prompt} [Y/n]${NC} ")" answer
- [[ -z "$answer" || "$answer" =~ ^[Yy] ]]
- else
- read -rp "$(echo -e "${YELLOW}${prompt} [y/N]${NC} ")" answer
- [[ "$answer" =~ ^[Yy] ]]
- fi
-}
-
-require_var() {
- local name="$1"
- local value="$2"
- if [[ -z "$value" ]]; then
- log_error "Required variable $name is not set. Export it or pass it as
an option."
- exit 1
- fi
-}
-
-check_command() {
- if ! command -v "$1" &>/dev/null; then
- log_error "Command '$1' is required but not found. Please install it
first."
- exit 1
- fi
-}
-
-detect_gpg_key() {
- if [[ -z "$GPG_KEY" ]]; then
- # Try to find the key for the Apache user
- GPG_KEY=$(gpg --list-secret-keys --keyid-format long 2>/dev/null \
- | grep -A1 "uid.*${APACHE_USER}@apache.org" \
- | grep "sec" | awk '{print $2}' | cut -d'/' -f2 | head -1)
- if [[ -z "$GPG_KEY" ]]; then
- # Fallback: use the first secret key
- GPG_KEY=$(gpg --list-secret-keys --keyid-format long 2>/dev/null \
- | grep "sec" | awk '{print $2}' | cut -d'/' -f2 | head -1)
- fi
- fi
- echo "$GPG_KEY"
-}
-
-mvn_release_args() {
- local args="-DskipTests"
- if [[ -n "$GPG_PASSPHRASE" ]]; then
- args="$args -Dgpg.passphrase=${GPG_PASSPHRASE}"
- fi
- echo "$args"
-}
-
-# ========================= Step 1: Prerequisites Check
=========================
-
-step_1_prerequisites() {
- log_step "1" "Prerequisites Check"
-
- local ok=true
-
- # Check required commands
- for cmd in java mvn git gpg svn curl; do
- if check_command "$cmd" 2>/dev/null; then
- local version
- version=$("$cmd" --version 2>/dev/null | head -1 || echo "unknown")
- log_info "Found $cmd: $version"
- else
- log_error "Missing required command: $cmd"
- ok=false
- fi
- done
-
- # Check Java version (need Java 17+)
- local java_version
- java_version=$(java -version 2>&1 | head -1 | grep -oE '[0-9]+' | head -1)
- if [[ "$java_version" -lt 17 ]]; then
- log_error "Java 17+ is required, found Java $java_version"
- ok=false
- else
- log_info "Java version: $java_version (OK)"
- fi
-
- # Check Maven version
- local mvn_version
- mvn_version=$(mvn --version 2>/dev/null | head -1)
- log_info "Maven: $mvn_version"
-
- # Check GPG keys
- GPG_KEY=$(detect_gpg_key)
- if [[ -z "$GPG_KEY" ]]; then
- log_error "No GPG secret key found. Create one with: gpg
--full-gen-key"
- ok=false
- else
- log_info "GPG key: $GPG_KEY"
- fi
-
- # Check GPG key on keyserver
- log_info "Checking GPG key on keyserver..."
- if curl -s
"https://keyserver.ubuntu.com/pks/lookup?op=index&search=${GPG_KEY}" | grep -q
"pub"; then
- log_info "GPG key found on keyserver.ubuntu.com (OK)"
- else
- log_warn "GPG key NOT found on keyserver.ubuntu.com. Upload with: gpg
--send-key $GPG_KEY"
- fi
-
- # Check Maven settings.xml
- local settings_file="${HOME}/.m2/settings.xml"
- if [[ -f "$settings_file" ]]; then
- if grep -q "apache.releases.https" "$settings_file" && grep -q
"apache.snapshots.https" "$settings_file"; then
- log_info "Maven settings.xml has Apache repository credentials
(OK)"
- else
- log_error "Maven settings.xml missing Apache repository
credentials (apache.releases.https / apache.snapshots.https)"
- ok=false
- fi
- else
- log_error "Maven settings.xml not found at $settings_file"
- ok=false
- fi
-
- # Check git repository
- if [[ -d "${SHENYU_HOME}/.git" ]]; then
- local current_branch
- current_branch=$(cd "$SHENYU_HOME" && git branch --show-current)
- log_info "Git repo found, current branch: $current_branch"
- if [[ "$current_branch" != "$RELEASE_BRANCH" ]]; then
- log_warn "Current branch is '$current_branch', expected
'$RELEASE_BRANCH'"
- if confirm "Switch to branch $RELEASE_BRANCH?"; then
- (cd "$SHENYU_HOME" && git checkout "$RELEASE_BRANCH") || true
- fi
- fi
- else
- log_error "Not a git repository at $SHENYU_HOME"
- ok=false
- fi
-
- # Check for uncommitted changes
- local git_status
- git_status=$(cd "$SHENYU_HOME" && git status --porcelain)
- if [[ -n "$git_status" ]]; then
- log_warn "Uncommitted changes found:"
- echo "$git_status"
- if ! confirm "Continue with uncommitted changes?"; then
- exit 1
- fi
- else
- log_info "No uncommitted changes (OK)"
- fi
-
- # Prompt for GPG passphrase if not set
- if [[ -z "$GPG_PASSPHRASE" ]]; then
- log_warn "GPG_PASSPHRASE is not set."
- log_warn "You can either:"
- log_warn " 1. Export it: export GPG_PASSPHRASE='your-passphrase'"
- log_warn " 2. Ensure gpg-agent has it cached"
- log_warn " 3. Use --pinentry-mode loopback by adding to
~/.gnupg/gpg.conf"
- echo ""
- if confirm "Enter GPG passphrase now? (will be hidden)"; then
- read -rs -p "GPG Passphrase: " GPG_PASSPHRASE
- echo ""
- export GPG_PASSPHRASE
- fi
- fi
-
- # Check Apache user
- if [[ -z "$APACHE_USER" ]]; then
- log_error "APACHE_USER is not set"
- ok=false
- else
- log_info "Apache user: $APACHE_USER"
- fi
-
- echo ""
- if [[ "$ok" == true ]]; then
- log_info "✅ All prerequisites passed!"
- else
- log_error "❌ Some prerequisites failed. Please fix them before
proceeding."
- exit 1
- fi
-}
-
-# ========================= Step 2: Maven release:prepare dry-run
=========================
-
-step_2_dry_run() {
- log_step "2" "Maven release:prepare dry-run"
-
- require_var "RELEASE_VERSION" "$RELEASE_VERSION"
-
- cd "$SHENYU_HOME"
-
- log_info "Running Maven release:prepare dry-run for version
${RELEASE_VERSION}..."
- log_info "Next development version will be: ${NEXT_VERSION}"
-
- mvn release:prepare \
- -Prelease \
- -Darguments="$(mvn_release_args)" \
- -DautoVersionSubmodules=true \
- -DdryRun=true \
- -DreleaseVersion="${RELEASE_VERSION}" \
- -DdevelopmentVersion="${NEXT_VERSION}" \
- -Dusername="${APACHE_USER}"
-
- if [[ $? -eq 0 ]]; then
- log_info "✅ Dry-run succeeded! Cleaning up dry-run artifacts..."
- mvn release:clean -q
- log_info "Ready to proceed with actual release:prepare."
- else
- log_error "❌ Dry-run failed. Please fix the errors above before
proceeding."
- exit 1
- fi
-}
-
-# ========================= Step 3: Maven release:prepare (actual)
=========================
-
-step_3_prepare() {
- log_step "3" "Maven release:prepare (actual)"
-
- cd "$SHENYU_HOME"
-
- if ! confirm "This will modify pom.xml versions and create git tags.
Continue?"; then
- log_info "Aborted."
- exit 0
- fi
-
- log_info "Cleaning previous release artifacts..."
- mvn release:clean -q
-
- log_info "Running Maven release:prepare for version ${RELEASE_VERSION}..."
- log_info "Next development version: ${NEXT_VERSION}"
- log_info "pushChanges=false - you will push manually after review."
-
- mvn release:prepare \
- -Prelease \
- -Darguments="$(mvn_release_args)" \
- -DautoVersionSubmodules=true \
- -DpushChanges=false \
- -DreleaseVersion="${RELEASE_VERSION}" \
- -DdevelopmentVersion="${NEXT_VERSION}" \
- -Dusername="${APACHE_USER}"
-
- if [[ $? -ne 0 ]]; then
- log_error "❌ release:prepare failed. Rolling back..."
- mvn release:rollback -q 2>/dev/null || true
- exit 1
- fi
-
- log_info "✅ release:prepare succeeded!"
- log_info ""
- log_info "Review the changes:"
- log_info " git log --oneline -5"
- log_info " git tag -l 'v${RELEASE_VERSION}'"
- log_info ""
-
- if confirm "Push release branch and tags to origin?"; then
- git push origin "${RELEASE_BRANCH}"
- git push origin --tags
- log_info "✅ Branch and tags pushed."
- else
- log_warn "Branch and tags NOT pushed. Push manually with:"
- log_warn " git push origin ${RELEASE_BRANCH}"
- log_warn " git push origin --tags"
- fi
-}
-
-# ========================= Step 4: Maven release:perform
=========================
-
-step_4_perform() {
- log_step "4" "Maven release:perform"
-
- cd "$SHENYU_HOME"
-
- if ! confirm "This will deploy artifacts to Apache Nexus staging
repository. Continue?"; then
- log_info "Aborted."
- exit 0
- fi
-
- log_info "Running Maven release:perform for version ${RELEASE_VERSION}..."
-
- mvn release:perform \
- -Prelease \
- -Darguments="$(mvn_release_args)" \
- -DautoVersionSubmodules=true \
- -Dusername="${APACHE_USER}"
-
- if [[ $? -ne 0 ]]; then
- log_error "❌ release:perform failed."
- exit 1
- fi
-
- log_info "✅ release:perform succeeded!"
- log_info ""
- log_warn "⚠️ IMPORTANT: Go to Apache Nexus and Close the staging
repository:"
- log_warn " https://repository.apache.org/#stagingRepositories"
- log_warn " Find the staging repo for org.apache.shenyu, select it, and
click 'Close'."
- log_warn " Note the repository ID (e.g., orgapacheshenyu-XXXX) for the
vote email."
-}
-
-# ========================= Step 5: Publish to SVN dev repository
=========================
-
-step_5_svn_dev() {
- log_step "5" "Publish to SVN dev repository"
-
- require_var "RELEASE_VERSION" "$RELEASE_VERSION"
- require_var "APACHE_USER" "$APACHE_USER"
-
- # Step 5a: Update KEYS file
- log_info "--- Step 5a: Update KEYS file ---"
-
- GPG_KEY=$(detect_gpg_key)
-
- if [[ -d "${HOME}/svn_release/release/shenyu" ]]; then
- log_info "Updating existing KEYS checkout..."
- cd "${HOME}/svn_release/release/shenyu"
- svn update
- else
- log_info "Checking out SVN release directory..."
- mkdir -p "${HOME}/svn_release/release"
- cd "${HOME}/svn_release/release"
- svn --username="${APACHE_USER}" co
https://dist.apache.org/repos/dist/release/shenyu
- cd shenyu
- fi
-
- # Check if our key is already in KEYS
- if grep -q "$GPG_KEY" KEYS 2>/dev/null; then
- log_info "GPG key already in KEYS file (OK)"
- else
- log_info "Appending GPG public key to KEYS file..."
- gpg -a --export "${GPG_KEY}" >> KEYS
- if confirm "Commit KEYS update to SVN?"; then
- svn --username="${APACHE_USER}" commit -m "append to KEYS"
- fi
- fi
-
- # Step 5b: Copy distribution files to SVN dev
- log_info "--- Step 5b: Copy distribution files to SVN dev ---"
-
- if [[ -d "${SVN_DEV_DIR}" ]]; then
- log_info "Updating existing SVN dev checkout..."
- cd "${SVN_DEV_DIR}"
- svn update
- else
- log_info "Checking out SVN dev directory..."
- mkdir -p "$(dirname "${SVN_DEV_DIR}")"
- cd "$(dirname "${SVN_DEV_DIR}")"
- svn --username="${APACHE_USER}" co
https://dist.apache.org/repos/dist/dev/shenyu
- cd shenyu
- fi
-
- local version_dir="${SVN_DEV_DIR}/${RELEASE_VERSION}"
- if [[ -d "$version_dir" ]]; then
- log_warn "Version directory already exists: $version_dir"
- if ! confirm "Remove and recreate?"; then
- log_info "Keeping existing directory."
- else
- svn delete "$version_dir" -m "remove old ${RELEASE_VERSION}"
2>/dev/null || true
- rm -rf "$version_dir"
- fi
- fi
-
- mkdir -p "$version_dir"
-
- local dist_dir="${SHENYU_HOME}/shenyu-dist"
- log_info "Copying distribution files from ${dist_dir}..."
-
- # Source distribution
- if ls "${dist_dir}/shenyu-src-dist/target/"*.zip* 1>/dev/null 2>&1; then
- cp -f "${dist_dir}/shenyu-src-dist/target/"*.zip* "$version_dir/"
- log_info " ✅ Source distribution copied"
- else
- log_error " ❌ Source distribution not found at
${dist_dir}/shenyu-src-dist/target/"
- log_error " Make sure release:perform has been run and
distributions were built."
- fi
-
- # Bootstrap distribution
- if ls "${dist_dir}/shenyu-bootstrap-dist/target/"*.tar.gz* 1>/dev/null
2>&1; then
- cp -f "${dist_dir}/shenyu-bootstrap-dist/target/"*.tar.gz*
"$version_dir/"
- log_info " ✅ Bootstrap distribution copied"
- else
- log_error " ❌ Bootstrap distribution not found"
- fi
-
- # Admin distribution
- if ls "${dist_dir}/shenyu-admin-dist/target/"*.tar.gz* 1>/dev/null 2>&1;
then
- cp -f "${dist_dir}/shenyu-admin-dist/target/"*.tar.gz* "$version_dir/"
- log_info " ✅ Admin distribution copied"
- else
- log_error " ❌ Admin distribution not found"
- fi
-
- # List files in version directory
- log_info "Files to be committed:"
- ls -la "$version_dir/"
-
- # Step 5c: Commit to SVN
- log_info "--- Step 5c: Commit to SVN ---"
-
- cd "${SVN_DEV_DIR}"
- svn add "${RELEASE_VERSION}/" 2>/dev/null || true
-
- if confirm "Commit release ${RELEASE_VERSION} to SVN dev?"; then
- svn --username="${APACHE_USER}" commit -m "release ${RELEASE_VERSION}"
- log_info "✅ SVN dev commit done."
- else
- log_warn "SVN commit skipped. Commit manually:"
- log_warn " cd ${SVN_DEV_DIR} && svn --username=${APACHE_USER} commit
-m 'release ${RELEASE_VERSION}'"
- fi
-}
-
-# ========================= Step 6: Verify release artifacts
=========================
-
-step_6_verify() {
- log_step "6" "Verify release artifacts"
-
- require_var "RELEASE_VERSION" "$RELEASE_VERSION"
-
- local version_dir="${SVN_DEV_DIR}/${RELEASE_VERSION}"
- if [[ ! -d "$version_dir" ]]; then
- log_error "Version directory not found: $version_dir"
- log_error "Run step 5 first, or check SVN_DEV_DIR setting."
- exit 1
- fi
-
- cd "$version_dir"
-
- local all_ok=true
-
- # 6a: Verify sha512 checksums
- log_info "--- 6a: Verify SHA512 checksums ---"
- for sha_file in *.sha512; do
- if [[ -f "$sha_file" ]]; then
- if shasum -a 512 -c "$sha_file" 2>/dev/null; then
- log_info " ✅ $sha_file verified"
- else
- log_error " ❌ $sha_file FAILED"
- all_ok=false
- fi
- else
- log_warn " No .sha512 files found. Generating checksums..."
- for artifact in apache-shenyu-${RELEASE_VERSION}-src.zip \
-
apache-shenyu-${RELEASE_VERSION}-bootstrap-bin.tar.gz \
- apache-shenyu-${RELEASE_VERSION}-admin-bin.tar.gz;
do
- if [[ -f "$artifact" ]]; then
- shasum -a 512 "$artifact" > "${artifact}.sha512"
- log_info " Generated ${artifact}.sha512"
- fi
- done
- fi
- done
-
- # 6b: Verify GPG signatures
- log_info "--- 6b: Verify GPG signatures ---"
- if ! curl -sf https://downloads.apache.org/shenyu/KEYS -o KEYS.download
2>/dev/null; then
- log_warn "Could not download KEYS from Apache. Using local keys."
- fi
- gpg --import KEYS.download 2>/dev/null || true
- rm -f KEYS.download
-
- for asc_file in *.asc; do
- if [[ -f "$asc_file" ]]; then
- local artifact="${asc_file%.asc}"
- if [[ -f "$artifact" ]]; then
- if gpg --verify "$asc_file" "$artifact" 2>/dev/null; then
- log_info " ✅ $asc_file signature verified"
- else
- log_error " ❌ $asc_file signature FAILED"
- all_ok=false
- fi
- fi
- fi
- done
-
- # 6c: Verify source dist contains required files
- log_info "--- 6c: Verify source distribution contents ---"
- local src_zip="apache-shenyu-${RELEASE_VERSION}-src.zip"
- if [[ -f "$src_zip" ]]; then
- local tmp_dir
- tmp_dir=$(mktemp -d)
- unzip -q "$src_zip" -d "$tmp_dir"
-
- local src_dir="${tmp_dir}/apache-shenyu-${RELEASE_VERSION}-src"
-
- # Check LICENSE and NOTICE
- for file in LICENSE NOTICE; do
- if [[ -f "${src_dir}/${file}" ]]; then
- log_info " ✅ ${file} exists"
- else
- log_error " ❌ ${file} MISSING"
- all_ok=false
- fi
- done
-
- # Check year in NOTICE
- local current_year
- current_year=$(date +%Y)
- if grep -q "$current_year" "${src_dir}/NOTICE" 2>/dev/null; then
- log_info " ✅ NOTICE year is current ($current_year)"
- else
- log_warn " ⚠️ NOTICE year may need updating (expected
$current_year)"
- fi
-
- # Clean up
- rm -rf "$tmp_dir"
- else
- log_error "Source zip not found: $src_zip"
- all_ok=false
- fi
-
- # 6d: Verify binary distributions
- log_info "--- 6d: Verify binary distributions ---"
- for bin_file in apache-shenyu-${RELEASE_VERSION}-bootstrap-bin.tar.gz \
- apache-shenyu-${RELEASE_VERSION}-admin-bin.tar.gz; do
- if [[ -f "$bin_file" ]]; then
- local tmp_dir
- tmp_dir=$(mktemp -d)
- tar xzf "$bin_file" -C "$tmp_dir"
-
- for file in LICENSE NOTICE; do
- if find "$tmp_dir" -name "$file" | head -1 | grep -q .; then
- log_info " ✅ ${bin_file}: ${file} exists"
- else
- log_error " ❌ ${bin_file}: ${file} MISSING"
- all_ok=false
- fi
- done
-
- rm -rf "$tmp_dir"
- else
- log_warn " Binary not found: $bin_file"
- fi
- done
-
- # 6e: Compare SVN source with GitHub tag
- log_info "--- 6e: Verify SVN source matches GitHub tag ---"
- log_info "To manually verify, run:"
- echo ""
- echo " wget
https://github.com/apache/shenyu/archive/v${RELEASE_VERSION}.zip"
- echo " unzip v${RELEASE_VERSION}.zip"
- echo " unzip apache-shenyu-${RELEASE_VERSION}-src.zip"
- echo " diff -r -x 'shenyu-dashboard' -x 'shenyu-examples' -x
'shenyu-integrated-test' -x 'static' \\"
- echo " apache-shenyu-${RELEASE_VERSION}-src shenyu-${RELEASE_VERSION}"
- echo ""
-
- echo ""
- if [[ "$all_ok" == true ]]; then
- log_info "✅ All verification checks passed!"
- else
- log_warn "⚠️ Some verification checks failed. Review the output
above."
- fi
-}
-
-# ========================= Step 7: Print voting email templates
=========================
-
-step_7_vote_templates() {
- log_step "7" "Voting email templates"
-
- # Get the release commit ID
- local commit_id
- commit_id=$(cd "$SHENYU_HOME" && git rev-list -1 "v${RELEASE_VERSION}"
2>/dev/null || echo "COMMIT_ID_HERE")
-
- # Detect staging repo ID
- log_info "After closing the Nexus staging repository, find the repository
ID (e.g., orgapacheshenyu-XXXX)"
- log_info "and replace STAGING_REPO_ID below with it."
- echo ""
-
- local staging_repo_id="STAGING_REPO_ID"
-
- cat <<'VOTE_EMAIL'
-╔══════════════════════════════════════════════════════════════════╗
-║ VOTE EMAIL TEMPLATE ║
-╚══════════════════════════════════════════════════════════════════╝
-
-Send to: [email protected]
-Subject: [VOTE] Release Apache ShenYu RELEASE_VERSION
-
---- BEGIN EMAIL ---
-
-Hello ShenYu Community,
-
-This is a call for vote to release Apache ShenYu version RELEASE_VERSION
-
-Release notes:
-https://github.com/apache/shenyu/blob/master/RELEASE-NOTES.md
-
-The release candidates:
-https://dist.apache.org/repos/dist/dev/shenyu/RELEASE_VERSION/
-
-Maven 2 staging repository:
-https://repository.apache.org/content/repositories/STAGING_REPO_ID/org/apache/shenyu/shenyu/RELEASE_VERSION/
-
-Git tag for the release:
-https://github.com/apache/shenyu/tree/vRELEASE_VERSION/
-
-Release Commit ID:
-https://github.com/apache/shenyu/commit/COMMIT_ID
-
-Keys to verify the Release Candidate:
-https://downloads.apache.org/shenyu/KEYS
-
-Look at here for how to verify this release candidate:
-https://shenyu.apache.org/community/release-guide/#check-release
-
-The vote will be open for at least 72 hours or until necessary number of votes
is reached.
-
-Please vote accordingly:
-[ ] +1 approve
-[ ] +0 no opinion
-[ ] -1 disapprove with the reason
-
-Checklist for reference:
-[ ] Download links are valid.
-[ ] Checksums and PGP signatures are valid.
-[ ] Source code distributions have correct names matching the current release.
-[ ] LICENSE and NOTICE files are correct for each ShenYu repo.
-[ ] All files have license headers if necessary.
-[ ] No compiled archives bundled in source archive.
-
---- END EMAIL ---
-
-VOTE_EMAIL
-
- cat <<'RESULT_EMAIL'
-╔══════════════════════════════════════════════════════════════════╗
-║ VOTE RESULT EMAIL TEMPLATE ║
-╚══════════════════════════════════════════════════════════════════╝
-
-Send to: [email protected]
-Subject: [RESULT][VOTE] Release Apache ShenYu RELEASE_VERSION
-
---- BEGIN EMAIL ---
-
-We've received 3 +1 binding votes and X +1 non-binding votes:
-
-+1, (binding voter 1) (binding)
-+1, (binding voter 2) (binding)
-+1, (binding voter 3) (binding)
-+1, (non-binding voter 1) (non-binding)
-+1, (non-binding voter 2) (non-binding)
-
-Vote thread:
-https://lists.apache.org/thread/XXXXX
-
-Thanks everyone for taking the time to verify and vote for the release!
-
---- END EMAIL ---
-
-RESULT_EMAIL
-
- cat <<'ANNOUNCE_EMAIL'
-╔══════════════════════════════════════════════════════════════════╗
-║ ANNOUNCE EMAIL TEMPLATE ║
-╚══════════════════════════════════════════════════════════════════╝
-
-Send to: [email protected], [email protected]
-Subject: [ANNOUNCE] Apache ShenYu RELEASE_VERSION available
-
-NOTE: [email protected] requires plain text format only.
-
---- BEGIN EMAIL ---
-
-Hi,
-
-Apache ShenYu Team is glad to announce the new release of Apache ShenYu
RELEASE_VERSION.
-
-Apache ShenYu is an asynchronous, high-performance, cross-language, responsive
API gateway.
-
-Support various languages (http protocol), support Dubbo, Spring-Cloud, Grpc,
Motan, Sofa, Tars and other protocols.
-Plugin design idea, plugin hot swap, easy to expand.
-Flexible flow filtering to meet various flow control.
-Built-in rich plugin support, authentication, limiting, fuse, firewall, etc.
-Dynamic flow configuration, high performance.
-Support cluster deployment, A/B Test, blue-green release.
-
-Download Links: https://shenyu.apache.org/download/
-Release Notes: https://github.com/apache/shenyu/blob/master/RELEASE-NOTES.md
-Website: https://shenyu.apache.org/
-
-ShenYu Resources:
-- Issue: https://github.com/apache/shenyu/issues
-- Mailing list: [email protected]
-- Documents: https://shenyu.apache.org/docs/index/
-
-- Apache ShenYu Team
-
---- END EMAIL ---
-
-ANNOUNCE_EMAIL
-
- # Print with actual values
- log_info "Replace the following placeholders in the templates:"
- log_info " RELEASE_VERSION → ${RELEASE_VERSION}"
- log_info " STAGING_REPO_ID → (find at
https://repository.apache.org/#stagingRepositories after closing)"
- log_info " COMMIT_ID → ${commit_id}"
-}
-
-# ========================= Step 8: Final release (after vote passes)
=========================
-
-step_8_final_release() {
- log_step "8" "Final release (after vote passes)"
-
- require_var "RELEASE_VERSION" "$RELEASE_VERSION"
- require_var "APACHE_USER" "$APACHE_USER"
-
- local prev_version
- prev_version=$(echo "$RELEASE_VERSION" | awk -F. '{printf "%d.%d.%d", $1,
$2, $3-1}')
- # For 2.7.1, previous is 2.7.0
-
- if ! confirm "Has the vote passed with at least 3 +1 binding votes?"; then
- log_info "Cannot proceed with final release until vote passes."
- exit 0
- fi
-
- # 8a: SVN release
- log_info "--- 8a: Move artifacts from SVN dev to release ---"
- log_info "Running: svn mv
https://dist.apache.org/repos/dist/dev/shenyu/${RELEASE_VERSION}
https://dist.apache.org/repos/dist/release/shenyu/ -m 'transfer packages for
${RELEASE_VERSION}'"
- if confirm "Execute SVN move?"; then
- svn mv
"https://dist.apache.org/repos/dist/dev/shenyu/${RELEASE_VERSION}" \
- "https://dist.apache.org/repos/dist/release/shenyu/" \
- -m "transfer packages for ${RELEASE_VERSION}" \
- --username="${APACHE_USER}"
- log_info "✅ SVN move done."
- fi
-
- log_info "--- 8a2: Delete previous version from SVN release ---"
- log_info "Previous version: ${prev_version}"
- if confirm "Delete previous version ${prev_version} from SVN release?";
then
- svn delete
"https://dist.apache.org/repos/dist/release/shenyu/${prev_version}" \
- -m "remove ${prev_version}" \
- --username="${APACHE_USER}" 2>/dev/null || log_warn
"Previous version not found or already deleted."
- fi
-
- # 8b: Maven release
- log_info ""
- log_info "--- 8b: Release Maven staging repository ---"
- log_info "Go to https://repository.apache.org/#stagingRepositories"
- log_info "Find the staging repo for org.apache.shenyu, select it, and
click 'Release'."
- log_info ""
- log_info "Press Enter after you have released the staging repository..."
- read -r
-
- # 8c: GitHub release
- log_info "--- 8c: GitHub release ---"
- log_info "Go to https://github.com/apache/shenyu/releases"
- log_info "Edit the v${RELEASE_VERSION} release and click 'Publish'."
- log_info ""
- log_info "Press Enter after you have published the GitHub release..."
- read -r
-
- # 8d: Docker release (automatic via GitHub Actions)
- log_info "--- 8d: Docker release ---"
- log_info "Docker images are automatically published via GitHub Actions
workflow (docker-publish-dockerhub.yml)."
- log_info "Monitor: https://github.com/apache/shenyu/actions"
- log_info ""
- log_info "If the workflow fails, you can build manually:"
- echo ""
- echo " git checkout v${RELEASE_VERSION}"
- echo " cd shenyu-dist"
- echo " mvn clean package -Prelease"
- echo " docker buildx create --name shenyu"
- echo " docker buildx use shenyu"
- echo " docker login"
- echo " docker buildx build \\"
- echo " -t apache/shenyu-admin:latest \\"
- echo " -t apache/shenyu-admin:${RELEASE_VERSION} \\"
- echo " --build-arg APP_NAME=apache-shenyu-${RELEASE_VERSION}-admin-bin
\\"
- echo " --platform=linux/arm64,linux/amd64 \\"
- echo " -f ./shenyu-admin-dist/docker/Dockerfile --push
./shenyu-admin-dist"
- echo " docker buildx build \\"
- echo " -t apache/shenyu-bootstrap:latest \\"
- echo " -t apache/shenyu-bootstrap:${RELEASE_VERSION} \\"
- echo " --build-arg
APP_NAME=apache-shenyu-${RELEASE_VERSION}-bootstrap-bin \\"
- echo " --platform=linux/arm64,linux/amd64 \\"
- echo " -f ./shenyu-bootstrap-dist/docker/Dockerfile --push
./shenyu-bootstrap-dist"
- echo ""
-
- # 8e: Merge release branch back to master
- log_info "--- 8e: Merge release branch back to master ---"
- if confirm "Merge ${RELEASE_BRANCH} back to master?"; then
- (cd "$SHENYU_HOME" && \
- git checkout master && \
- git merge "origin/${RELEASE_BRANCH}" && \
- git pull && \
- git push origin master)
- log_info "✅ Merged and pushed to master."
-
- if confirm "Delete release branch ${RELEASE_BRANCH}?"; then
- (cd "$SHENYU_HOME" && \
- git push origin --delete "${RELEASE_BRANCH}" 2>/dev/null ||
true && \
- git branch -d "${RELEASE_BRANCH}" 2>/dev/null || true)
- log_info "✅ Release branch deleted."
- fi
- fi
-
- # 8f: Update download pages
- log_info "--- 8f: Update download pages ---"
- log_info "⚠️ Manual steps required:"
- log_info " 1. Update English download page:
https://shenyu.apache.org/download/"
- log_info " 2. Update Chinese download page:
https://shenyu.apache.org/zh/download/"
- log_info " - Use https://www.apache.org/dyn/closer.lua for download
links (NOT closer.cgi or mirrors.cgi)"
- log_info " - GPG signature and hash links must use:
https://downloads.apache.org/shenyu/"
- log_info " 3. Archive documentation for ${RELEASE_VERSION}"
- log_info " 4. Update version page"
- log_info " 5. Update events page with new release event"
- log_info " 6. Update news page with new release news"
- log_info ""
- log_info "Wait at least 1 hour for Apache mirror to sync before updating
download pages."
-
- # 8g: Send announce email
- log_info "--- 8g: Send announce email ---"
- log_info "Send the announce email (see template from step 7) to:"
- log_info " - [email protected]"
- log_info " - [email protected] (plain text format only!)"
-
- log_info ""
- log_info "🎉 Release ${RELEASE_VERSION} process complete!"
-}
-
-# ========================= Clean / Rollback =========================
-
-step_clean() {
- log_step "CLEAN" "Rollback release artifacts"
-
- require_var "RELEASE_VERSION" "$RELEASE_VERSION"
-
- cd "$SHENYU_HOME"
-
- log_warn "This will clean up Maven release artifacts and optionally delete
the release branch and tag."
-
- # Maven release:clean
- if confirm "Run mvn release:clean?"; then
- mvn release:clean -q
- log_info "✅ Maven release artifacts cleaned."
- fi
-
- # Delete local tag
- if git tag -l "v${RELEASE_VERSION}" | grep -q .; then
- if confirm "Delete local tag v${RELEASE_VERSION}?"; then
- git tag -d "v${RELEASE_VERSION}"
- log_info "✅ Local tag deleted."
- fi
- fi
-
- # Delete remote tag
- if git ls-remote --tags origin "v${RELEASE_VERSION}" | grep -q .; then
- if confirm "Delete remote tag v${RELEASE_VERSION}?"; then
- git push origin --delete tag "v${RELEASE_VERSION}"
- log_info "✅ Remote tag deleted."
- fi
- fi
-
- # Delete release branch
- if git branch --list "${RELEASE_BRANCH}" | grep -q .; then
- if confirm "Delete local branch ${RELEASE_BRANCH}?"; then
- git branch -D "${RELEASE_BRANCH}"
- log_info "✅ Local branch deleted."
- fi
- fi
-
- if git ls-remote --heads origin "${RELEASE_BRANCH}" | grep -q .; then
- if confirm "Delete remote branch ${RELEASE_BRANCH}?"; then
- git push origin --delete "${RELEASE_BRANCH}"
- log_info "✅ Remote branch deleted."
- fi
- fi
-
- # Drop Nexus staging repo
- log_warn "⚠️ Remember to drop the Nexus staging repository if it was
closed:"
- log_warn " https://repository.apache.org/#stagingRepositories"
-
- # Delete SVN dev artifacts
- if confirm "Delete SVN dev artifacts for ${RELEASE_VERSION}?"; then
- svn delete
"https://dist.apache.org/repos/dist/dev/shenyu/${RELEASE_VERSION}" \
- -m "delete ${RELEASE_VERSION}" \
- --username="${APACHE_USER}" 2>/dev/null || log_warn "SVN
delete failed or already deleted."
- fi
-
- log_info "✅ Cleanup complete."
-}
-
-# ========================= Usage =========================
-
-usage() {
- cat <<EOF
-Apache ShenYu Release Script - v${RELEASE_VERSION}
-
-Usage: $(basename "$0") <step> [options]
-
-Steps:
- 1 Prerequisites check
- 2 Maven release:prepare dry-run
- 3 Maven release:prepare (actual - modifies pom.xml and creates tags)
- 4 Maven release:perform (deploys to Apache Nexus staging)
- 5 Publish to SVN dev repository
- 6 Verify release artifacts
- 7 Print voting email templates
- 8 Final release (after vote passes)
- all Run steps 1-6 sequentially
- clean Rollback: delete branch, tags, and clean Maven release artifacts
-
-Options:
- -v, --version VERSION Release version (default: ${RELEASE_VERSION})
- -n, --next-version VERSION Next SNAPSHOT version (default: ${NEXT_VERSION})
- -u, --user USERNAME Apache LDAP username (default: ${APACHE_USER})
- -k, --gpg-key KEY_ID GPG key ID
- -p, --gpg-passphrase PASS GPG passphrase
- -d, --home DIR ShenYu source directory (default:
${SHENYU_HOME})
-
-Environment variables:
- RELEASE_VERSION, NEXT_VERSION, APACHE_USER, GPG_KEY, GPG_PASSPHRASE,
SHENYU_HOME
-
-Examples:
- # Check prerequisites
- $(basename "$0") 1
-
- # Dry run with GPG passphrase
- $(basename "$0") 2 -p 'my-passphrase'
-
- # Full release (steps 1-6)
- $(basename "$0") all -p 'my-passphrase'
-
- # Print vote email templates
- $(basename "$0") 7
-
- # Final release after vote
- $(basename "$0") 8
-
- # Rollback
- $(basename "$0") clean
-EOF
-}
-
-# ========================= Parse Arguments =========================
-
-parse_args() {
- while [[ $# -gt 0 ]]; do
- case "$1" in
- -v|--version)
- RELEASE_VERSION="$2"
- RELEASE_BRANCH="${RELEASE_VERSION}-release"
- GIT_TAG="v${RELEASE_VERSION}"
- shift 2
- ;;
- -n|--next-version)
- NEXT_VERSION="$2"
- shift 2
- ;;
- -u|--user)
- APACHE_USER="$2"
- shift 2
- ;;
- -k|--gpg-key)
- GPG_KEY="$2"
- shift 2
- ;;
- -p|--gpg-passphrase)
- GPG_PASSPHRASE="$2"
- shift 2
- ;;
- -d|--home)
- SHENYU_HOME="$2"
- shift 2
- ;;
- -h|--help)
- usage
- exit 0
- ;;
- *)
- echo "Unknown option: $1"
- usage
- exit 1
- ;;
- esac
- done
-}
-
-# ========================= Main =========================
-
-main() {
- # Handle help flag even as first arg
- if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
- usage
- exit 0
- fi
-
- if [[ $# -lt 1 ]]; then
- usage
- exit 1
- fi
-
- local step="$1"
- shift
- parse_args "$@"
-
- # Export GPG passphrase for subprocess
- export GPG_PASSPHRASE
-
- echo ""
- echo -e
"${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
- echo -e "${BLUE}║ Apache ShenYu ${RELEASE_VERSION} Release Script
║${NC}"
- echo -e
"${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
- echo ""
- log_info "Release version: ${RELEASE_VERSION}"
- log_info "Next version: ${NEXT_VERSION}"
- log_info "Apache user: ${APACHE_USER}"
- log_info "Source dir: ${SHENYU_HOME}"
- log_info "GPG key: $(detect_gpg_key)"
- echo ""
-
- case "$step" in
- 1) step_1_prerequisites ;;
- 2) step_2_dry_run ;;
- 3) step_3_prepare ;;
- 4) step_4_perform ;;
- 5) step_5_svn_dev ;;
- 6) step_6_verify ;;
- 7) step_7_vote_templates ;;
- 8) step_8_final_release ;;
- all)
- step_1_prerequisites
- step_2_dry_run
- step_3_prepare
- step_4_perform
- step_5_svn_dev
- step_6_verify
- echo ""
- log_info "✅ Steps 1-6 complete! Next steps:"
- log_info " 1. Close the Nexus staging repository at
https://repository.apache.org/#stagingRepositories"
- log_info " 2. Run './release.sh 7' to print voting email
templates"
- log_info " 3. Send vote email to [email protected]"
- log_info " 4. After vote passes, run './release.sh 8' to finalize
the release"
- ;;
- clean)
- step_clean ;;
- *)
- echo "Unknown step: $step"
- usage
- exit 1
- ;;
- esac
-}
-
-main "$@"