This is an automated email from the ASF dual-hosted git repository.

Apache9 pushed a commit to branch branch-3
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-3 by this push:
     new f8259f6601c HBASE-30272 Compatiblity checker can not compile rel/2.0.0 
when releasing 3.0.0-beta-2 (#8451)
f8259f6601c is described below

commit f8259f6601c76c810b648453802bbda2c57d8dd2
Author: Duo Zhang <[email protected]>
AuthorDate: Fri Jul 3 17:13:07 2026 +0800

    HBASE-30272 Compatiblity checker can not compile rel/2.0.0 when releasing 
3.0.0-beta-2 (#8451)
    
    Signed-off-by: Xiao Liu <[email protected]>
    (cherry picked from commit 448bd2486f26db2b3732386c04ef3057efb4cf5a)
---
 dev-support/checkcompatibility.py                  |  46 +-
 dev-support/create-release/README.txt              | 130 ---
 dev-support/create-release/do-release-docker.sh    | 342 --------
 dev-support/create-release/do-release.sh           | 159 ----
 dev-support/create-release/hbase-rm/Dockerfile     |  82 --
 .../create-release/mac-sshd-gpg-agent/Dockerfile   | 102 ---
 dev-support/create-release/prepend_changes.py      |  39 -
 dev-support/create-release/prepend_releasenotes.py |  40 -
 dev-support/create-release/release-build.sh        | 345 --------
 dev-support/create-release/release-util.sh         | 873 ---------------------
 dev-support/create-release/vote.tmpl               |  39 -
 11 files changed, 42 insertions(+), 2155 deletions(-)

diff --git a/dev-support/checkcompatibility.py 
b/dev-support/checkcompatibility.py
index 914f8dd42f1..6460411799b 100755
--- a/dev-support/checkcompatibility.py
+++ b/dev-support/checkcompatibility.py
@@ -44,6 +44,7 @@ import sys
 import urllib.request
 import urllib.error
 import urllib.parse
+import xml.etree.ElementTree as xml
 from collections import namedtuple
 try:
     import argparse
@@ -135,7 +136,33 @@ def get_repo_name(remote_name="origin"):
     return remote[:-4] if remote.endswith(".git") else remote
 
 
-def build_tree(java_path, verbose):
+def select_java_home(java_path, java8_home, java17_home):
+    pom = xml.parse(os.path.join(java_path, "pom.xml"))
+    root = pom.getroot()
+    ns = ""
+    if root.tag.startswith("{"):
+        ns = root.tag.split("}")[0] + "}"   # e.g. 
"{http://maven.apache.org/POM/4.0.0}";
+    version_elem = root.find(f"{ns}version")
+    if version_elem is not None and version_elem.text:
+        version = version_elem.text.strip()
+    else:
+        raise ValueError("Could not find project version")
+    if version == "${revision}":
+        properties_elem = root.find(f"{ns}properties")
+        if properties_elem is None:
+            raise ValueError("Could not find properties")
+        revision_elem = properties_elem.find(f"{ns}revision")
+        if revision_elem is not None and revision_elem.text:
+            version = revision_elem.text.strip()
+        else:
+            raise ValueError("Could not find project revision")
+    if version.startswith("3."):
+        return java17_home
+    else:
+        return java8_home
+
+
+def build_tree(java_path, verbose, java8_home, java17_home):
     """ Run the Java build within 'path'. """
     logging.info("Building in %s ", java_path)
     # special hack for comparing with rel/2.0.0, see HBASE-26063 for more 
details
@@ -144,7 +171,10 @@ def build_tree(java_path, verbose):
                "-Dmaven.javadoc.skip=true", "package"]
     if not verbose:
         mvn_cmd.insert(-1, "--quiet")
-    subprocess.check_call(mvn_cmd, cwd=java_path)
+    env = os.environ.copy()
+    if java8_home and java17_home:
+        env["JAVA_HOME"] = select_java_home(java_path, java8_home, java17_home)
+    subprocess.check_call(mvn_cmd, cwd=java_path, env=env)
 
 
 def checkout_java_acc(force):
@@ -444,6 +474,14 @@ def main():
     parser.add_argument("--skip-build",
                         action="store_true",
                         help="Skip building the projects.")
+    parser.add_argument("--java8_home",
+                        default=None,
+                        help="Path to Java 8 installation. "
+                        "Used for building projects with version < 3.0.")
+    parser.add_argument("--java17_home",
+                        default=None,
+                        help="Path to Java 17 installation. "
+                        "Used for building projects with version >= 3.0.")
     parser.add_argument("--verbose",
                         action="store_true",
                         help="more output")
@@ -516,8 +554,8 @@ def main():
     if args.skip_build:
         logging.info("Skipping the build")
     else:
-        build_tree(src_dir, args.verbose)
-        build_tree(dst_dir, args.verbose)
+        build_tree(src_dir, args.verbose, args.java8_home, args.java17_home)
+        build_tree(dst_dir, args.verbose, args.java8_home, args.java17_home)
 
     # Find the JARs.
     src_jars = find_jars(src_dir)
diff --git a/dev-support/create-release/README.txt 
b/dev-support/create-release/README.txt
deleted file mode 100644
index 14c2b7d458d..00000000000
--- a/dev-support/create-release/README.txt
+++ /dev/null
@@ -1,130 +0,0 @@
-Creates an HBase release candidate.
-
-The scripts in this directory came originally from spark
-(https://github.com/apache/spark/tree/master/dev/create-release). They were
-then modified to suit the hbase context. These scripts supercede the old
-_../make_rc.sh_ script for making release candidates because what is here is
-more comprehensive doing more steps of the RM process as well as running in a
-container so the RM build environment can be a constant.
-
-It:
-
- * Tags release
- * Sets version to the release version
- * Sets version to next SNAPSHOT version.
- * Builds, signs, and hashes all artifacts.
- * Pushes release tgzs to the dev dir in a apache dist.
- * Pushes to repository.apache.org staging.
-
-The entry point is the do-release-docker.sh script. It requires a local
-docker; for example, on mac os x, a Docker for Desktop installed and running.
-
-(To run a build w/o invoking docker (not recommended!), use _do_release.sh_.)
-
-The scripts will query interactively for needed parameters and passphrases.
-For explanation of the parameters, execute:
-
- $ release-build.sh --help
-
-The scripts run in dry-run mode by default where only local builds are
-performed and nothing is uploaded to the ASF repos. Pass the '-f' flag
-to remove dry-run mode.
-
-Before starting the RC build, run a reconciliation of what is in JIRA with
-what is in the commit log. Make sure they align and that anomalies are
-explained up in JIRA.
-See 
https://hbase.apache.org/docs/building-and-developing/releasing#making-a-release-candidate
-for how.
-
-Regardless of where your release build will run (locally, locally in docker,
-on a remote machine, etc) you will need a local gpg-agent with access to your
-secret keys. Before starting an RC build, make sure your local gpg-agent has
-configs to properly handle your credentials, especially if you want to avoid
-typing the passphrase to your secret key: e.g. if you are going to run
-and step away (the RC creation takes ~5 hours), best to increase the TTL on
-caching the unlocked secret by setting the following into local your
-~/.gnupg/gpg-agent.conf file:
-  # in seconds, e.g. a day
-  default-cache-ttl 86400
-  max-cache-ttl 86400
-
-A quick way to tell gpg to clear out state, re-read the gpg-agent.conf file
-and start a new gpg-agent is via the following command phrase:
-
- $ gpgconf --kill all && gpg-connect-agent /bye
-
-You can verify options took hold with '$ gpg --list-options gpg-agent'.
-
-Similarly, run ssh-agent with your ssh key added if building with docker.
-
-Running a build on GCE is easy enough. Here are some notes if of use.
-Create an instance. 4CPU/15G/20G disk seems to work well enough.
-Once up, run the below to make your machine fit for RC building:
-
-# Presuming debian-compatible OS, do these steps on the VM.
-# Your VM username should be your ASF id, because it will show up in build 
artifacts.
-# Follow the docker install guide: 
https://docs.docker.com/engine/install/debian/
-$ sudo apt-get install -y \
-    apt-transport-https \
-    ca-certificates \
-    curl \
-    gnupg2 \
-    software-properties-common
-$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
-$ sudo add-apt-repository -y \
-   "deb [arch=amd64] https://download.docker.com/linux/debian \
-   $(lsb_release -cs) \
-   stable"
-$ sudo apt-get update
-$ sudo apt-get install -y docker-ce docker-ce-cli containerd.io
-# Follow the post installation steps: 
https://docs.docker.com/engine/install/linux-postinstall/
-$ sudo usermod -aG docker $USER
-# LOGOUT and then LOGIN again so $USERID shows as part of docker group
-# Test here by running docker's hello world as your build user
-$ docker run hello-world
-
-# Follow the GPG guide for forwarding your gpg-agent from your local machine 
to the VM
-#   https://wiki.gnupg.org/AgentForwarding
-# On the VM find out the location of the gpg agent socket and extra socket
-$ gpgconf --list-dir agent-socket
-/run/user/1000/gnupg/S.gpg-agent
-$ gpgconf --list-dir agent-extra-socket
-/run/user/1000/gnupg/S.gpg-agent.extra
-# On the VM configure sshd to remove stale sockets
-$ sudo bash -c 'echo "StreamLocalBindUnlink yes" >> /etc/ssh/sshd_config'
-$ sudo systemctl restart ssh
-# logout of the VM
-
-# Do these steps on your local machine.
-# make sure gpg-agent is running
-$ gpg-connect-agent /bye
-# Export your public key and copy it to the VM.
-# Assuming 'example.gce.host' maps to your VM's external IP (or use the IP)
-$ gpg --export [email protected] > ~/gpg.example.apache.pub
-$ scp ~/gpg.example.apache.pub example.gce.host:
-# ssh into the VM while forwarding the remote gpg socket locations found above 
to your local
-#   gpg-agent's extra socket (this will restrict what commands the remote node 
is allowed to have
-#   your agent handle. Note that the gpg guide above can help you set this up 
in your ssh config
-#   rather than typing it in ssh like this every time.
-# Note that as of maven-gpg-plugin 3.0.1, with gnupg >= 2.1, the plugin uses
-#   `--pinentry-mode error`, which is apparently not supported over the 
`extra` socket. These
-#   instructions may require tweaking.
-$ ssh -i ~/.ssh/my_id \
-    -R "/run/user/1000/gnupg/S.gpg-agent:$(gpgconf --list-dir 
agent-extra-socket)" \
-    -R "/run/user/1000/gnupg/S.gpg-agent.extra:$(gpgconf --list-dir 
agent-extra-socket)" \
-    example.gce.host
-
-# now in an SSH session on the VM with the socket forwarding
-# import your public key and test signing with the forwarding to your local 
agent.
-$ gpg --no-autostart --import gpg.example.apache.pub
-$ echo "foo" > foo.txt
-$ gpg --no-autostart --detach --armor --sign foo.txt
-$ gpg --no-autostart --verify foo.txt.asc
-
-# install git and clone the main project on the build machine
-$ sudo apt-get install -y git
-$ git clone https://github.com/apache/hbase.git
-# finally set up an output folder and launch a dry run.
-$ mkdir ~/build
-$ cd hbase
-$ ./dev-support/create-release/do-release-docker.sh -d ~/build
diff --git a/dev-support/create-release/do-release-docker.sh 
b/dev-support/create-release/do-release-docker.sh
deleted file mode 100755
index 804661945e0..00000000000
--- a/dev-support/create-release/do-release-docker.sh
+++ /dev/null
@@ -1,342 +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.
-#
-
-#
-# Creates a HBase release candidate. The script will update versions, tag the 
branch,
-# build HBase binary packages and documentation, and upload maven artifacts to 
a staging
-# repository. There is also a dry run mode where only local builds are 
performed, and
-# nothing is uploaded to the ASF repos.
-#
-# Run with "-h" for options. For example, running below will do all
-# steps above using the 'rm' dir under Downloads as workspace:
-#
-# $ ./do-release-docker.sh  -d ~/Downloads/rm
-#
-# The scripts in this directory came originally from spark [1]. They were then
-# modified to suite the hbase context. These scripts supercedes the old
-# ../make_rc.sh script for making release candidates because what is here is 
more
-# comprehensive doing more steps of the RM process as well as running in a
-# container so the RM build environment can be a constant.
-#
-# It:
-#  * Tags release
-#  * Sets version to the release version
-#  * Sets version to next SNAPSHOT version.
-#  * Builds, signs, and hashes all artifacts.
-#  * Pushes release tgzs to the dev dir in a apache dist.
-#  * Pushes to repository.apache.org staging.
-#
-# The entry point is here, in the do-release-docker.sh script.
-#
-# 1. https://github.com/apache/spark/tree/master/dev/create-release
-#
-set -e
-
-# Set this to build other hbase repos: e.g. PROJECT=hbase-operator-tools
-export PROJECT="${PROJECT:-hbase}"
-
-SELF="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-# shellcheck source=SCRIPTDIR/release-util.sh
-. "$SELF/release-util.sh"
-ORIG_PWD="$(pwd)"
-
-function usage {
-  local NAME
-  NAME="$(basename "${BASH_SOURCE[0]}")"
-  cat <<EOF
-Usage: $NAME [OPTIONS]
-Runs release scripts inside a docker image.
-Options:
-  -d [path]    Required. Working directory. Output will be written to "output" 
in here.
-  -f           "force" -- actually publish this release. Unless you specify 
'-f', it will
-               default to dry run mode, which checks and does local builds, 
but does not
-               upload anything.
-  -t [tag]     Tag for the hbase-rm docker image to use for building (default: 
"latest").
-  -j [path]    Path to local JDK installation to use building. By default the 
script will
-               use openjdk8 installed in the docker image.
-  -p [project] Project to build: e.g. 'hbase' or 'hbase-thirdparty'; defaults 
to PROJECT env var
-  -r [repo]    Git repo to use for remote git operations. defaults to ASF 
gitbox for project.
-  -s [step]    Runs a single step of the process; valid steps: 
tag|publish-dist|publish-release.
-               If none specified, runs tag, then publish-dist, and then 
publish-release.
-               'publish-snapshot' is also an allowed, less used, option.
-  -x           Debug. Does less clean up (env file, gpg forwarding on mac)
-EOF
-  exit 1
-}
-
-WORKDIR=
-IMGTAG=latest
-JAVA=
-RELEASE_STEP=
-GIT_REPO=
-while getopts "d:fhj:p:r:s:t:x" opt; do
-  case $opt in
-    d) WORKDIR="$OPTARG" ;;
-    f) DRY_RUN=0 ;;
-    t) IMGTAG="$OPTARG" ;;
-    j) JAVA="$OPTARG" ;;
-    p) PROJECT="$OPTARG" ;;
-    r) GIT_REPO="$OPTARG" ;;
-    s) RELEASE_STEP="$OPTARG" ;;
-    x) DEBUG=1 ;;
-    h) usage ;;
-    ?) error "Invalid option. Run with -h for help." ;;
-  esac
-done
-shift $((OPTIND-1))
-if (( $# > 0 )); then
-  error "Arguments can only be provided with option flags, invalid args: $*"
-fi
-export DEBUG
-
-if [ -z "$WORKDIR" ] || [ ! -d "$WORKDIR" ]; then
-  error "Work directory (-d) must be defined and exist. Run with -h for help."
-fi
-
-if [ -d "$WORKDIR/output" ]; then
-  read -r -p "Output directory already exists. Overwrite and continue? [y/n] " 
ANSWER
-  if [ "$ANSWER" != "y" ]; then
-    error "Exiting."
-  fi
-fi
-
-if [ -f "${WORKDIR}/gpg-proxy.ssh.pid" ] || \
-   [ -f "${WORKDIR}/gpg-proxy.cid" ] || \
-   [ -f "${WORKDIR}/release.cid" ]; then
-  read -r -p "container/pid files from prior run exists. Overwrite and 
continue? [y/n] " ANSWER
-  if [ "$ANSWER" != "y" ]; then
-    error "Exiting."
-  fi
-fi
-
-cd "$WORKDIR"
-rm -rf "$WORKDIR/output"
-rm -rf "${WORKDIR}/gpg-proxy.ssh.pid" "${WORKDIR}/gpg-proxy.cid" 
"${WORKDIR}/release.cid"
-mkdir "$WORKDIR/output"
-
-banner "Gathering release details."
-HOST_OS="$(get_host_os)"
-get_release_info
-
-banner "Setup"
-
-# Place all RM scripts and necessary data in a local directory that must be 
defined in the command
-# line. This directory is mounted into the image. Its WORKDIR, the arg passed 
with -d.
-for f in "$SELF"/*; do
-  if [ -f "$f" ]; then
-    cp "$f" "$WORKDIR"
-  fi
-done
-
-# We need to import that public key in the container in order to use the 
private key via the agent.
-GPG_KEY_FILE="$WORKDIR/gpg.key.public"
-log "Exporting public key for ${GPG_KEY}"
-fcreate_secure "$GPG_KEY_FILE"
-$GPG "${GPG_ARGS[@]}" --export "${GPG_KEY}" > "${GPG_KEY_FILE}"
-
-function cleanup {
-  local id
-  banner "Release Cleanup"
-  if is_debug; then
-    log "skipping due to debug run"
-    return 0
-  fi
-  log "details in cleanup.log"
-  if [ -f "${ENVFILE}" ]; then
-    rm -f "$ENVFILE"
-  fi
-  rm -f "$GPG_KEY_FILE"
-  if [ -f "${WORKDIR}/gpg-proxy.ssh.pid" ]; then
-    id=$(cat "${WORKDIR}/gpg-proxy.ssh.pid")
-    echo "Stopping ssh tunnel for gpg-agent at PID ${id}" | tee -a cleanup.log
-    kill -9 "${id}" >>cleanup.log 2>&1 || true
-    rm -f "${WORKDIR}/gpg-proxy.ssh.pid" >>cleanup.log 2>&1
-  fi
-  if [ -f "${WORKDIR}/gpg-proxy.cid" ]; then
-    id=$(cat "${WORKDIR}/gpg-proxy.cid")
-    echo "Stopping gpg-proxy container with ID ${id}" | tee -a cleanup.log
-    docker kill "${id}" >>cleanup.log 2>&1 || true
-    rm -f "${WORKDIR}/gpg-proxy.cid" >>cleanup.log 2>&1
-    # TODO we should remove the gpgagent volume?
-  fi
-  if [ -f "${WORKDIR}/release.cid" ]; then
-    id=$(cat "${WORKDIR}/release.cid")
-    echo "Stopping release container with ID ${id}" | tee -a cleanup.log
-    docker kill "${id}" >>cleanup.log 2>&1 || true
-    rm -f "${WORKDIR}/release.cid" >>cleanup.log 2>&1
-  fi
-}
-
-trap cleanup EXIT
-
-log "Host OS: ${HOST_OS}"
-if [ "${HOST_OS}" == "DARWIN" ]; then
-  run_silent "Building gpg-agent-proxy image with tag ${IMGTAG}..." 
"docker-proxy-build.log" \
-    docker build --build-arg "UID=${UID}" --build-arg "RM_USER=${USER}" \
-        --tag "org.apache.hbase/gpg-agent-proxy:${IMGTAG}" 
"${SELF}/mac-sshd-gpg-agent"
-fi
-
-run_silent "Building hbase-rm image with tag $IMGTAG..." "docker-build.log" \
-  docker build --tag "org.apache.hbase/hbase-rm:$IMGTAG" --build-arg 
"UID=$UID" \
-      --build-arg "RM_USER=${USER}" "$SELF/hbase-rm"
-
-banner "Final prep for container launch."
-log "Writing out environment for container."
-# Write the release information to a file with environment variables to be 
used when running the
-# image.
-ENVFILE="$WORKDIR/env.list"
-fcreate_secure "$ENVFILE"
-
-cat > "$ENVFILE" <<EOF
-PROJECT=$PROJECT
-DRY_RUN=$DRY_RUN
-SKIP_TAG=$SKIP_TAG
-RUNNING_IN_DOCKER=1
-GIT_BRANCH=$GIT_BRANCH
-NEXT_VERSION=$NEXT_VERSION
-PREV_VERSION=$PREV_VERSION
-RELEASE_VERSION=$RELEASE_VERSION
-RELEASE_TAG=$RELEASE_TAG
-GIT_REF=$GIT_REF
-ASF_USERNAME=$ASF_USERNAME
-GIT_NAME=$GIT_NAME
-GIT_EMAIL=$GIT_EMAIL
-GPG_KEY=$GPG_KEY
-ASF_PASSWORD=$ASF_PASSWORD
-RELEASE_STEP=$RELEASE_STEP
-API_DIFF_TAG=$API_DIFF_TAG
-HOST_OS=$HOST_OS
-EOF
-
-JAVA_MOUNT=()
-if [ -n "$JAVA" ]; then
-  echo "JAVA_HOME=/opt/hbase-java" >> "$ENVFILE"
-  JAVA_MOUNT=(--mount "type=bind,src=${JAVA},dst=/opt/hbase-java,readonly")
-fi
-
-#TODO some debug output would be good here
-GIT_REPO_MOUNT=()
-if [ -n "${GIT_REPO}" ]; then
-  case "${GIT_REPO}" in
-    # skip the easy to identify remote protocols
-    ssh://*|git://*|http://*|https://*|ftp://*|ftps://*) ;;
-    # for sure local
-    /*)
-      GIT_REPO_MOUNT=(--mount 
"type=bind,src=${GIT_REPO},dst=/opt/hbase-repo,consistency=delegated")
-      echo "HOST_GIT_REPO=${GIT_REPO}" >> "${ENVFILE}"
-      GIT_REPO="/opt/hbase-repo"
-      ;;
-    # on the host but normally git wouldn't use the local optimization
-    file://*)
-      log "Converted file:// git repo to a local path, which changes git to 
assume --local."
-      GIT_REPO_MOUNT=(--mount 
"type=bind,src=${GIT_REPO#file://},dst=/opt/hbase-repo,consistency=delegated")
-      echo "HOST_GIT_REPO=${GIT_REPO}" >> "${ENVFILE}"
-      GIT_REPO="/opt/hbase-repo"
-      ;;
-    # have to decide if it's a local path or the "scp-ish" remote
-    *)
-      declare colon_remove_prefix;
-      declare slash_remove_prefix;
-      declare local_path;
-      colon_remove_prefix="${GIT_REPO#*:}"
-      slash_remove_prefix="${GIT_REPO#*/}"
-      if [ "${GIT_REPO}" = "${colon_remove_prefix}" ]; then
-        # if there was no colon at all, we assume this must be a local path
-        local_path="no colon at all"
-      elif [ "${GIT_REPO}" != "${slash_remove_prefix}" ]; then
-        # if there was a colon and there is no slash, then we assume it must 
be scp-style host
-        # and a relative path
-
-        if [ "${#colon_remove_prefix}" -lt "${#slash_remove_prefix}" ]; then
-          # Given the substrings made by removing everything up to the first 
colon and slash
-          # we can determine which comes first based on the longer substring 
length.
-          # if the slash is first, then we assume the colon is part of a path 
name and if the colon
-          # is first then it is the seperator between a scp-style host name 
and the path.
-          local_path="slash happened before a colon"
-        fi
-      fi
-      if [ -n "${local_path}" ]; then
-        # convert to an absolute path
-        GIT_REPO="$(cd "$(dirname "${ORIG_PWD}/${GIT_REPO}")"; pwd)/$(basename 
"${ORIG_PWD}/${GIT_REPO}")"
-        GIT_REPO_MOUNT=(--mount 
"type=bind,src=${GIT_REPO},dst=/opt/hbase-repo,consistency=delegated")
-        echo "HOST_GIT_REPO=${GIT_REPO}" >> "${ENVFILE}"
-        GIT_REPO="/opt/hbase-repo"
-      fi
-      ;;
-  esac
-  echo "GIT_REPO=${GIT_REPO}" >> "${ENVFILE}"
-fi
-
-GPG_PROXY_MOUNT=()
-if [ "${HOST_OS}" == "DARWIN" ]; then
-  GPG_PROXY_MOUNT=(--mount 
"type=volume,src=gpgagent,dst=/home/${USER}/.gnupg/")
-  log "Setting up GPG agent proxy container needed on OS X."
-  log "    we should clean this up for you. If that fails the container ID is 
below and in " \
-      "gpg-proxy.cid"
-  #TODO the key pair used should be configurable
-  docker run --rm -p 62222:22 \
-     --detach --cidfile "${WORKDIR}/gpg-proxy.cid" \
-     --mount \
-     
"type=bind,src=${HOME}/.ssh/id_rsa.pub,dst=/home/${USER}/.ssh/authorized_keys,readonly"
 \
-     "${GPG_PROXY_MOUNT[@]}" \
-     "org.apache.hbase/gpg-agent-proxy:${IMGTAG}"
-  # gotta trust the container host
-  ssh-keyscan -p 62222 localhost 2>/dev/null | sort > 
"${WORKDIR}/gpg-agent-proxy.ssh-keyscan"
-  sort "${HOME}/.ssh/known_hosts" | comm -1 -3 - 
"${WORKDIR}/gpg-agent-proxy.ssh-keyscan" \
-      > "${WORKDIR}/gpg-agent-proxy.known_hosts"
-  if [ -s "${WORKDIR}/gpg-agent-proxy.known_hosts" ]; then
-    log "Your ssh known_hosts does not include the entries for the gpg-agent 
proxy container."
-    log "The following entry(ies) are missing:"
-    sed -e 's/^/    /' "${WORKDIR}/gpg-agent-proxy.known_hosts"
-    read -r -p "Okay to add these entries to ${HOME}/.ssh/known_hosts? [y/n] " 
ANSWER
-    if [ "$ANSWER" != "y" ]; then
-      error "Exiting."
-    fi
-    cat "${WORKDIR}/gpg-agent-proxy.known_hosts" >> "${HOME}/.ssh/known_hosts"
-  fi
-  log "Launching ssh reverse tunnel from the container to gpg agent."
-  log "    we should clean this up for you. If that fails the PID is in 
gpg-proxy.ssh.pid"
-  ssh -p 62222 -R "/home/${USER}/.gnupg/S.gpg-agent:$(gpgconf --list-dir 
agent-socket)" \
-      -i "${HOME}/.ssh/id_rsa" -N -n localhost >gpg-proxy.ssh.log 2>&1 &
-  echo $! > "${WORKDIR}/gpg-proxy.ssh.pid"
-else
-  # Note that on linux we always directly mount the gpg agent's extra socket 
to limit what the
-  # container can ask the gpg-agent to do.
-  # When working on a remote linux machine you should be sure to forward both 
the remote machine's
-  # agent socket and agent extra socket to your local gpg-agent's extra 
socket. See the README.txt
-  # for an example.
-  GPG_PROXY_MOUNT=(--mount \
-      "type=bind,src=$(gpgconf --list-dir 
agent-socket),dst=/home/${USER}/.gnupg/S.gpg-agent")
-fi
-
-banner "Building $RELEASE_TAG; output will be at $WORKDIR/output"
-log "We should clean the container up when we are done. If that fails then the 
container ID " \
-    "is in release.cid"
-echo
-# Where possible we specify "consistency=delegated" when we do not need host 
access during the
-# build run. On Mac OS X specifically this gets us a big perf improvement.
-cmd=(docker run --rm -ti \
-  --env-file "$ENVFILE" \
-  --cidfile "${WORKDIR}/release.cid" \
-  --mount 
"type=bind,src=${WORKDIR},dst=/home/${USER}/hbase-rm,consistency=delegated" \
-  "${JAVA_MOUNT[@]}" \
-  "${GIT_REPO_MOUNT[@]}" \
-  "${GPG_PROXY_MOUNT[@]}" \
-  "org.apache.hbase/hbase-rm:$IMGTAG")
-echo "${cmd[*]}"
-"${cmd[@]}"
diff --git a/dev-support/create-release/do-release.sh 
b/dev-support/create-release/do-release.sh
deleted file mode 100755
index 904d813fc3c..00000000000
--- a/dev-support/create-release/do-release.sh
+++ /dev/null
@@ -1,159 +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.
-#
-
-# Make a tmp dir into which we put files cleaned-up on exit.
-TMPDIR=$(mktemp -d)
-trap "rm -rf $TMPDIR" EXIT
-
-set -e
-# Use the adjacent do-release-docker.sh instead, if you can.
-# Otherwise, this runs core of the release creation.
-# Will ask you questions on what to build and for logins
-# and passwords to use building.
-export PROJECT="${PROJECT:-hbase}"
-
-SELF="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-# shellcheck source=SCRIPTDIR/release-util.sh
-. "$SELF/release-util.sh"
-
-while getopts "b:fs:" opt; do
-  case $opt in
-    b) export GIT_BRANCH=$OPTARG ;;
-    f) export DRY_RUN=0 ;;  # "force", ie actually publish this release 
(otherwise defaults to dry run)
-    s) RELEASE_STEP="$OPTARG" ;;
-    ?) error "Invalid option: $OPTARG" ;;
-  esac
-done
-shift $((OPTIND-1))
-if (( $# > 0 )); then
-  error "Arguments can only be provided with option flags, invalid args: $*"
-fi
-
-function gpg_agent_help {
-  cat <<EOF
-Trying to sign a test file using your GPG setup failed.
-
-Please make sure you have a local gpg-agent running with access to your secret 
keys prior to
-starting a release build. If you are creating release artifacts on a remote 
machine please check
-that you have set up ssh forwarding to the gpg-agent extra socket.
-
-For help on how to do this please see the README file in the create-release 
directory.
-EOF
-  exit 1
-}
-
-# If running in docker, import and then cache keys.
-if [ "$RUNNING_IN_DOCKER" = "1" ]; then
-  # when Docker Desktop for mac is running under load there is a delay before 
the mounted volume
-  # becomes available. if we do not pause then we may try to use the gpg-agent 
socket before docker
-  # has got it ready and we will not think there is a gpg-agent.
-  if [ "${HOST_OS}" == "DARWIN" ]; then
-    sleep 5
-  fi
-  # in docker our working dir is set to where all of our scripts are held
-  # and we want default output to go into the "output" directory that should 
be in there.
-  if [ -d "output" ]; then
-    cd output
-  fi
-  echo "GPG Version: $("${GPG}" "${GPG_ARGS[@]}" --version)"
-  # Inside docker, need to import the GPG key stored in the current directory.
-  if ! $GPG "${GPG_ARGS[@]}" --import "$SELF/gpg.key.public" ; then
-    gpg_agent_help
-  fi
-
-  # We may need to adjust the path since JAVA_HOME may be overridden by the 
driver script.
-  if [ -n "$JAVA_HOME" ]; then
-    echo "Using JAVA_HOME from host."
-    export PATH="$JAVA_HOME/bin:$PATH"
-  else
-    # JAVA_HOME for the openjdk package.
-    export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
-  fi
-else
-  # Outside docker, need to ask for information about the release.
-  get_release_info
-fi
-
-# Check GPG
-gpg_test_file="${TMPDIR}/gpg_test.$$.txt"
-echo "Testing gpg signing ${GPG} ${GPG_ARGS[@]} --detach --armor --sign 
${gpg_test_file}"
-echo "foo" > "${gpg_test_file}"
-if ! "${GPG}" "${GPG_ARGS[@]}" --detach --armor --sign "${gpg_test_file}" ; 
then
-  gpg_agent_help
-fi
-# In --batch mode we have to be explicit about what we are verifying
-if ! "${GPG}" "${GPG_ARGS[@]}" --verify "${gpg_test_file}.asc" 
"${gpg_test_file}" ; then
-  gpg_agent_help
-fi
-GPG_TTY="$(tty)"
-export GPG_TTY
-
-if [[ -z "$RELEASE_STEP" ]]; then
-  # If doing all stages, leave out 'publish-snapshot'
-  RELEASE_STEP="tag_publish-dist_publish-release"
-  # and use shared maven local repo for efficiency
-  export REPO="${REPO:-$(pwd)/$(mktemp -d hbase-repo-XXXXX)}"
-fi
-
-function should_build {
-  local WHAT=$1
-  if [[ -z "$RELEASE_STEP" ]]; then
-    return 0
-  elif [[ "$RELEASE_STEP" == *"$WHAT"* ]]; then
-    return 0
-  else
-    return 1
-  fi
-}
-
-if should_build "tag" && [ "$SKIP_TAG" = 0 ]; then
-  if [ -z "${YETUS_HOME}" ] && [ "${RUNNING_IN_DOCKER}" != "1" ]; then
-    declare local_yetus="/opt/apache-yetus/0.12.0/"
-    if [ "$(get_host_os)" = "DARWIN" ]; then
-      local_yetus="/usr/local/Cellar/yetus/0.12.0/"
-    fi
-    YETUS_HOME="$(read_config "YETUS_HOME not defined. Absolute path to local 
install of Apache Yetus" "${local_yetus}")"
-    export YETUS_HOME
-  fi
-  run_silent "Creating release tag $RELEASE_TAG..." "tag.log" \
-    "$SELF/release-build.sh" tag
-  if is_dry_run; then
-    export TAG_SAME_DRY_RUN="true";
-  fi
-else
-  echo "Skipping tag creation for $RELEASE_TAG."
-fi
-
-if should_build "publish-dist"; then
-  run_silent "Publishing distribution packages (tarballs)" "publish-dist.log" \
-    "$SELF/release-build.sh" publish-dist
-else
-  echo "Skipping publish-dist step."
-fi
-
-if should_build "publish-snapshot"; then
-  run_silent "Publishing snapshot" "publish-snapshot.log" \
-    "$SELF/release-build.sh" publish-snapshot
-
-elif should_build "publish-release"; then
-  run_silent "Publishing release" "publish-release.log" \
-    "$SELF/release-build.sh" publish-release
-else
-  echo "Skipping publish-release step."
-fi
diff --git a/dev-support/create-release/hbase-rm/Dockerfile 
b/dev-support/create-release/hbase-rm/Dockerfile
deleted file mode 100644
index 4f1d238d775..00000000000
--- a/dev-support/create-release/hbase-rm/Dockerfile
+++ /dev/null
@@ -1,82 +0,0 @@
-#
-# 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.
-#
-
-# Image for building HBase releases. Based on Ubuntu 22.04.
-#
-# Includes:
-# * Java 8
-FROM ubuntu:22.04
-
-# Install extra needed repos and refresh.
-#
-# This is all in a single "RUN" command so that if anything changes, "apt 
update" is run to fetch
-# the most current package versions (instead of potentially using old versions 
cached by docker).
-RUN DEBIAN_FRONTEND=noninteractive apt-get -qq -y update \
-  && DEBIAN_FRONTEND=noninteractive apt-get -qq -y install 
--no-install-recommends \
-    curl='7.81.0-*' \
-    git='1:2.34.1-*' \
-    gnupg='2.2.27-*' \
-    libcurl4-openssl-dev='7.81.0-*' \
-    libxml2-dev='2.9.13+dfsg-*' \
-    libxml2-utils='2.9.13+dfsg-*' \
-    lsof='4.93.2+dfsg-*' \
-    openjdk-8-jdk='8u*' \
-    python3-pip='22.0.2+dfsg-*' \
-    subversion='1.14.1-*' \
-    wget='1.21.2-*' \
-    patch='2.7.6-*' \
-  && apt-get clean \
-  && rm -rf /var/lib/apt/lists/* \
-  && update-alternatives --set java 
/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java \
-  && pip3 install --no-cache-dir python-dateutil==2.8.2
-
-SHELL ["/bin/bash", "-o", "pipefail", "-c"]
-
-# Install maven
-ENV MAVEN_VERSION=3.8.6
-ARG 
MAVEN_URL="https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz";
-ARG 
MAVEN_SHA512="f790857f3b1f90ae8d16281f902c689e4f136ebe584aba45e4b1fa66c80cba826d3e0e52fdd04ed44b4c66f6d3fe3584a057c26dfcac544a60b301e6d0f91c26"
-RUN mkdir -p /opt/maven \
-  && curl -fsSL -o /tmp/apache-maven.tar.gz "${MAVEN_URL}" \
-  && echo "${MAVEN_SHA512}  /tmp/apache-maven.tar.gz" | sha512sum -c - \
-  && tar -xzf /tmp/apache-maven.tar.gz -C /opt/maven --strip-components=1 \
-  && rm -f /tmp/apache-maven.tar.gz \
-  && ln -s /opt/maven/bin/mvn /usr/bin/mvn
-
-# Install Apache Yetus
-ENV YETUS_VERSION 0.14.1
-ARG 
YETUS_URL="https://archive.apache.org/dist/yetus/${YETUS_VERSION}/apache-yetus-${YETUS_VERSION}-bin.tar.gz";
-ARG 
YETUS_SHA512="068c8426a5c7ecc9281b988123d223a3d772fd725365303bde8287ae1515e623764b89f09a4a9cdc01e7f30631814086b71408b625025a51bdb3c58b213b4109"
-RUN mkdir -p /opt/yetus \
-  && curl -fsSL -o /tmp/apache-yetus.tar.gz "${YETUS_URL}" \
-  && echo "${YETUS_SHA512} */tmp/apache-yetus.tar.gz" | sha512sum -c - \
-  && tar -xzf /tmp/apache-yetus.tar.gz -C /opt/yetus --strip-components=1 \
-  && rm -f /tmp/apache-yetus.tar.gz
-ENV YETUS_HOME /opt/yetus
-
-ARG UID
-ARG RM_USER
-RUN groupadd hbase-rm && \
-    useradd --create-home -l --shell /bin/bash -p hbase-rm -u $UID $RM_USER && 
\
-    mkdir /home/$RM_USER/.gnupg && \
-    chown -R $RM_USER:hbase-rm /home/$RM_USER && \
-    chmod -R 700 /home/$RM_USER
-
-USER $RM_USER:hbase-rm
-WORKDIR /home/$RM_USER/hbase-rm/
-
-ENTRYPOINT [ "./do-release.sh" ]
diff --git a/dev-support/create-release/mac-sshd-gpg-agent/Dockerfile 
b/dev-support/create-release/mac-sshd-gpg-agent/Dockerfile
deleted file mode 100644
index d27285f2e39..00000000000
--- a/dev-support/create-release/mac-sshd-gpg-agent/Dockerfile
+++ /dev/null
@@ -1,102 +0,0 @@
-#
-# 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.
-#
-
-# Image for use on Mac boxes to get a gpg agent socket available
-# within transient release building ocntainers.
-#
-# build like:
-#
-# docker build --build-arg "UID=$UID" --build-arg "RM_USER=$USER" \
-#     --tag org.apache.hbase/gpg-agent-proxy mac-sshd-gpg-agent
-#
-# run like:
-#
-# docker run --rm -p 62222:22 \
-#     --mount 
"type=bind,src=${HOME}/.ssh/id_rsa.pub,dst=/home/${USER}/.ssh/authorized_keys,readonly"
 \
-#     --mount "type=volume,src=gpgagent,dst=/home/${USER}/.gnupg/" \
-#     org.apache.hbase/gpg-agent-proxy:latest
-#
-# test like:
-#
-# ssh -p 62222 -R "/home/${USER}/.gnupg/S.gpg-agent:$(gpgconf --list-dir 
agent-socket)" \
-#     -i "${HOME}/.ssh/id_rsa" -N -n localhost
-#
-# launch a docker container to do work that shares the mount for the gpg agent
-# expressly does not need to be this same image, but needs to have defined the 
same user
-#
-# docker run --rm -it \
-#     --mount "type=volume,src=gpgagent,dst=/home/${USER}/.gnupg/" \
-#     --mount 
"type=bind,src=${HOME}/projects/hbase-releases/KEYS,dst=/home/${USER}/KEYS,readonly"
 \
-#     --entrypoint /bin/bash --user "${USER}" --workdir "/home/${USER}/" \
-#     org.apache.hbase/gpg-agent-proxy:latest
-#
-#
-# Make sure to import the public keys
-#
-# gpg --no-autostart --import < ${HOME}/KEYS
-# Optional?
-# gpg --no-autostart --edit-key ${YOUR_KEY}
-# trust
-# 5
-# y
-# quit
-#
-# echo "foo" > foo
-# gpg --no-autostart --armor --detach --sign foo
-# gpg --no-autostart --verify foo.asc
-#
-# For more info see
-# * gpg forwarding over ssh: https://wiki.gnupg.org/AgentForwarding
-# * example docker for sshd: https://github.com/hotblac/nginx-ssh
-# * why we have to bother with this: 
https://github.com/docker/for-mac/issues/483
-#
-# If the docker image changes then the host key used by sshd will change and 
you will get a
-# nastygram when launching ssh about host identification changing. This is 
expected. you should
-# remove the previous host key.
-#
-# Tested with
-# * Docker Desktop 2.2.0.5
-# * gpg 2.2.20
-# * pinentry-mac 0.9.4
-# * yubikey 5
-#
-FROM ubuntu:18.04
-
-# This is all in a single "RUN" command so that if anything changes, "apt 
update" is run to fetch
-# the most current package versions (instead of potentially using old versions 
cached by docker).
-#
-# We only need gnupg2 here if we want the ability to test out the gpg-agent 
forwarding by sshing
-# into the container rather than launching a new docker container.
-RUN DEBIAN_FRONTEND=noninteractive apt-get -qq -y update \
-  && DEBIAN_FRONTEND=noninteractive apt-get -qq -y install 
--no-install-recommends \
-    openssh-server=1:7.6p1-* \
-    gnupg2=2.2.4-* \
-  && mkdir /run/sshd \
-  && echo "StreamLocalBindUnlink yes" >> /etc/ssh/sshd_config \
-  && apt-get clean \
-  && rm -rf /var/lib/apt/lists/*
-EXPOSE 22
-# Set up our ssh user
-ARG UID
-ARG RM_USER
-RUN groupadd sshgroup && \
-    useradd --create-home --shell /bin/bash --groups sshgroup --uid $UID 
$RM_USER && \
-    mkdir /home/$RM_USER/.ssh /home/$RM_USER/.gnupg && \
-    chown -R $RM_USER:sshgroup /home/$RM_USER/ && \
-    chmod -R 700 /home/$RM_USER/
-# When we run we run sshd
-ENTRYPOINT ["/usr/sbin/sshd", "-D"]
diff --git a/dev-support/create-release/prepend_changes.py 
b/dev-support/create-release/prepend_changes.py
deleted file mode 100755
index 7e9dfbb4e51..00000000000
--- a/dev-support/create-release/prepend_changes.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env python3
-##
-# 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.
-
-import sys
-import re
-import os
-
-if len(sys.argv) != 3:
-  print("usage: %s <NEW_CHANGES.md> <PREV_CHANGES.md>" % sys.argv[0])
-  sys.exit(1)
-
-pattern = re.compile(r'^## Release .+$')
-with open(sys.argv[1], 'r', errors = 'ignore') as new_r, open(sys.argv[2], 
'r', errors = 'ignore') as prev_r, open(sys.argv[2] + '.tmp', 'w') as w:
-  line = prev_r.readline()
-  while line:
-    if pattern.match(line):
-      break
-    line = prev_r.readline()
-  for newline in new_r:
-    w.writelines(newline)
-  while line:
-    w.writelines(line)
-    line = prev_r.readline()
-os.rename(sys.argv[2] + '.tmp', sys.argv[2])
diff --git a/dev-support/create-release/prepend_releasenotes.py 
b/dev-support/create-release/prepend_releasenotes.py
deleted file mode 100755
index 41be2c1c18a..00000000000
--- a/dev-support/create-release/prepend_releasenotes.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-##
-# 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.
-
-import sys
-import re
-import os
-
-if len(sys.argv) != 3:
-  print("usage: %s <NEW_RELEASENOTES.md> <PREV_RELEASENOTES.md>" % sys.argv[0])
-  sys.exit(1)
-
-pattern = re.compile(r'^# .+ Release Notes$')
-with open(sys.argv[1], 'r', errors = 'ignore') as new_r, open(sys.argv[2], 
'r', errors = 'ignore') as prev_r, open(sys.argv[2] + '.tmp', 'w') as w:
-  line = prev_r.readline()
-  while line:
-    if pattern.match(line):
-      break
-    line = prev_r.readline()
-  w.writelines('# RELEASENOTES')
-  for newline in new_r:
-    w.writelines(newline)
-  while line:
-    w.writelines(line)
-    line = prev_r.readline()
-os.rename(sys.argv[2] + '.tmp', sys.argv[2])
diff --git a/dev-support/create-release/release-build.sh 
b/dev-support/create-release/release-build.sh
deleted file mode 100755
index f3d8798be46..00000000000
--- a/dev-support/create-release/release-build.sh
+++ /dev/null
@@ -1,345 +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.
-#
-
-trap cleanup EXIT
-
-# Source in utils.
-SELF="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-# shellcheck source=SCRIPTDIR/release-util.sh
-. "$SELF/release-util.sh"
-
-# Print usage and exit.
-function exit_with_usage {
-  cat <<'EOF'
-Usage: release-build.sh <tag|publish-dist|publish-snapshot|publish-release>
-Creates release deliverables from a tag or commit.
-Argument: one of 'tag', 'publish-dist', 'publish-snapshot', or 
'publish-release'
-  tag               Prepares for release on specified git branch: Set release 
version,
-                    update CHANGES and RELEASENOTES, create release tag,
-                    increment version for ongoing dev, and publish to Apache 
git repo.
-  publish-dist      Build and publish distribution packages (tarballs) to 
Apache dist repo
-  publish-snapshot  Build and publish maven artifacts snapshot release to 
Apache snapshots repo
-  publish-release   Build and publish maven artifacts release to Apache 
release repo, and
-                    construct vote email from template
-
-All other inputs are environment variables.  Please use do-release-docker.sh or
-do-release.sh to set up the needed environment variables.  This script, 
release-build.sh,
-is not intended to be called stand-alone, and such use is untested.  The env 
variables used are:
-
-Used for 'tag' and 'publish' stages:
-  PROJECT - The project to build. No default.
-  RELEASE_VERSION - Version used in pom files for release (e.g. 2.1.2)
-    Required for 'tag'; defaults for 'publish' to the version in pom at GIT_REF
-  RELEASE_TAG - Name of release tag (e.g. 2.1.2RC0), also used by
-    publish-dist as package version name in dist directory path
-  ASF_USERNAME - Username of ASF committer account
-  ASF_PASSWORD - Password of ASF committer account
-  DRY_RUN - 1:true (default), 0:false. If "1", does almost all the work, but 
doesn't actually
-    publish anything to upstream source or object repositories. It defaults to 
"1", so if you want
-    to actually publish you have to set '-f' (force) flag in do-release.sh or 
do-release-docker.sh.
-
-Used only for 'tag':
-  YETUS_HOME - installation location for Apache Yetus
-  GIT_NAME - Name to use with git
-  GIT_EMAIL - E-mail address to use with git
-  GIT_BRANCH - Git branch on which to make release. Tag is always placed at 
HEAD of this branch.
-  NEXT_VERSION - Development version after release (e.g. 2.1.3-SNAPSHOT)
-
-Used only for 'publish':
-  GIT_REF - Release tag or commit to build from (defaults to $RELEASE_TAG; 
only need to
-    separately define GIT_REF if RELEASE_TAG is not actually present as a tag 
at publish time)
-    If both RELEASE_TAG and GIT_REF are undefined it will default to HEAD of 
master.
-  GPG_KEY - GPG key id (usually email addr) used to sign release artifacts
-  REPO - Set to full path of a directory to use as maven local repo 
(dependencies cache)
-    to avoid re-downloading dependencies for each stage.  It is automatically 
set if you
-    request full sequence of stages (tag, publish-dist, publish-release) in 
do-release.sh.
-
-For example:
- $ PROJECT="hbase-operator-tools" ASF_USERNAME=NAME ASF_PASSWORD=PASSWORD 
[email protected] ./release-build.sh publish-dist
-EOF
-  exit 1
-}
-
-set -e
-
-function cleanup {
-  # If REPO was set, then leave things be. Otherwise if we defined a repo 
clean it out.
-  if [[ -z "${REPO}" ]] && [[ -n "${MAVEN_LOCAL_REPO}" ]]; then
-    log "Cleaning up temp repo in '${MAVEN_LOCAL_REPO}'. Set REPO to reuse 
downloads." >&2
-    rm -f "${MAVEN_SETTINGS_FILE}" &> /dev/null || true
-    rm -rf "${MAVEN_LOCAL_REPO}" &> /dev/null || true
-  fi
-}
-
-if [ $# -ne 1 ]; then
-  exit_with_usage
-fi
-
-if [[ "$1" == "-h" ]]; then
-  exit_with_usage
-fi
-
-if [[ "$*" == *"help"* ]]; then
-  exit_with_usage
-fi
-
-init_locale
-init_java
-init_mvn
-init_python
-# Print out subset of perl version (used in git hooks and 
japi-compliance-checker)
-perl --version | grep 'This is'
-
-rm -rf "${PROJECT}"
-
-if is_debug; then
-  set -x  # detailed logging during action
-fi
-
-if [[ "$1" == "tag" ]]; then
-  init_yetus
-  # for 'tag' stage
-  set -o pipefail
-  check_get_passwords ASF_PASSWORD
-  check_needed_vars PROJECT RELEASE_VERSION RELEASE_TAG NEXT_VERSION GIT_EMAIL 
GIT_NAME GIT_BRANCH
-  if [ -z "${GIT_REPO}" ]; then
-    check_needed_vars ASF_USERNAME ASF_PASSWORD
-  fi
-  git_clone_overwrite
-
-  # 'update_releasenotes' searches the project's Jira for issues where 'Fix 
Version' matches specified
-  # $jira_fix_version. For most projects this is same as ${RELEASE_VERSION}. 
However, all the 'hbase-*'
-  # projects share the same HBASE jira name.  To make this work, by 
convention, the HBASE jira "Fix Version"
-  # field values have the sub-project name pre-pended, as in 
"hbase-operator-tools-1.0.0".
-  # So, here we prepend the project name to the version, but only for the 
hbase sub-projects.
-  jira_fix_version="${RELEASE_VERSION}"
-  shopt -s nocasematch
-  if [[ "${PROJECT}" == "hbase-thirdparty" ]]; then
-    jira_fix_version="thirdparty-${RELEASE_VERSION}"
-  elif [[ "${PROJECT}" =~ ^hbase- ]]; then
-    jira_fix_version="${PROJECT}-${RELEASE_VERSION}"
-  fi
-  shopt -u nocasematch
-  update_releasenotes "$(pwd)/${PROJECT}" "${jira_fix_version}"
-
-  cd "${PROJECT}"
-
-  git config user.name "$GIT_NAME"
-  git config user.email "$GIT_EMAIL"
-  git config user.signingkey "${GPG_KEY}"
-
-  # Create release version
-  maven_set_version "$RELEASE_VERSION"
-  find . -name pom.xml -exec git add {} \;
-  # Always put CHANGES.md and RELEASENOTES.md to parent directory, so later we 
do not need to
-  # check their position when generating release data. We can not put them 
under the source code
-  # directory because for 3.x+, CHANGES.md and RELEASENOTES.md are not tracked 
so later when
-  # generating src release tarball, we will reset the git repo
-  if is_tracked "CHANGES.md"; then
-    git add RELEASENOTES.md CHANGES.md
-    git commit -s -m "Preparing ${PROJECT} release $RELEASE_TAG; tagging and 
updates to CHANGES.md and RELEASENOTES.md"
-    cp CHANGES.md ../
-    cp RELEASENOTES.md ../
-  else
-    # CHANGES.md is not tracked, should 3.x+
-    git commit -s -m "Preparing ${PROJECT} release $RELEASE_TAG"
-    mv CHANGES.md ../
-    mv RELEASENOTES.md ../
-  fi
-
-  log "Creating tag $RELEASE_TAG at the head of $GIT_BRANCH"
-  git tag -s -m "Via create-release" "$RELEASE_TAG"
-
-  # Create next version
-  maven_set_version "$NEXT_VERSION"
-  find . -name pom.xml -exec git add {} \;
-  git commit -s -m "Preparing development version $NEXT_VERSION"
-
-  if ! is_dry_run; then
-    # Push changes
-    git push origin "$RELEASE_TAG"
-    git push origin "HEAD:$GIT_BRANCH"
-    cd ..
-    rm -rf "${PROJECT}"
-  else
-    cd ..
-    mv "${PROJECT}" "${PROJECT}.tag"
-    log "Dry run: Clone with version changes and tag available as 
${PROJECT}.tag in the output directory."
-  fi
-  exit 0
-fi
-
-### Below is for 'publish-*' stages ###
-check_get_passwords ASF_PASSWORD
-check_needed_vars PROJECT ASF_USERNAME ASF_PASSWORD GPG_KEY
-
-# Commit ref to checkout when building
-BASE_DIR=$(pwd)
-GIT_REF=${GIT_REF:-master}
-if [[ "$PROJECT" =~ ^hbase ]]; then
-  RELEASE_STAGING_LOCATION="https://dist.apache.org/repos/dist/dev/hbase";
-else
-  RELEASE_STAGING_LOCATION="https://dist.apache.org/repos/dist/dev/${PROJECT}";
-fi
-
-# in case of dry run, enable publish steps to chain from tag step
-if is_dry_run && [[ "${TAG_SAME_DRY_RUN:-}" == "true" && -d "${PROJECT}.tag" 
]]; then
-  ln -s "${PROJECT}.tag" "${PROJECT}"
-else
-  git_clone_overwrite
-fi
-cd "${PROJECT}"
-git checkout "$GIT_REF"
-git_hash="$(git rev-parse --short HEAD)"
-GIT_LONG_HASH="$(git rev-parse HEAD)"
-log "Checked out ${PROJECT} at ${GIT_REF} commit $git_hash"
-
-if [ -z "${RELEASE_VERSION}" ]; then
-  RELEASE_VERSION="$(maven_get_version)"
-fi
-
-# This is a band-aid fix to avoid the failure of Maven nightly snapshot in 
some Jenkins
-# machines by explicitly calling /usr/sbin/lsof. Please see SPARK-22377 and 
the discussion
-# in its pull request.
-LSOF=lsof
-if ! hash $LSOF 2>/dev/null; then
-  LSOF=/usr/sbin/lsof
-fi
-
-package_version_name="$RELEASE_TAG"
-if [ -z "$package_version_name" ]; then
-  package_version_name="${RELEASE_VERSION}-$(date +%Y_%m_%d_%H_%M)-${git_hash}"
-fi
-
-git clean -d -f -x
-cd ..
-if [[ "$PROJECT" =~ ^hbase- ]]; then
-  DEST_DIR_NAME="${PROJECT}-${package_version_name}"
-else
-  DEST_DIR_NAME="$package_version_name"
-fi
-
-if [[ "$1" == "publish-dist" ]]; then
-  # Source and binary tarballs
-  log "Packaging release source tarballs"
-  make_src_release "${PROJECT}" "${RELEASE_VERSION}"
-
-  # we do not have binary tarballs for hbase-thirdparty
-  if [[ "${PROJECT}" != "hbase-thirdparty" ]]; then
-    make_binary_release "${PROJECT}" "${RELEASE_VERSION}"
-  fi
-
-  svn_target="svn-${PROJECT}"
-  svn co --depth=empty "$RELEASE_STAGING_LOCATION" "$svn_target"
-  rm -rf "${svn_target:?}/${DEST_DIR_NAME}"
-  mkdir -p "$svn_target/${DEST_DIR_NAME}"
-
-  log "Copying release tarballs"
-  cp "${PROJECT}"-*.tar.* "$svn_target/${DEST_DIR_NAME}/"
-  cp "CHANGES.md" "$svn_target/${DEST_DIR_NAME}/"
-  cp "RELEASENOTES.md" "$svn_target/${DEST_DIR_NAME}/"
-
-  shopt -s nocasematch
-  # Generate api report only if project is hbase for now.
-  if [ "${PROJECT}" == "hbase" ]; then
-    # This script usually reports an errcode along w/ the report.
-    generate_api_report "./${PROJECT}" "${API_DIFF_TAG}" "${GIT_REF}" || true
-    cp api*.html "$svn_target/${DEST_DIR_NAME}/"
-  fi
-  shopt -u nocasematch
-
-  log "svn add"
-  svn add "$svn_target/${DEST_DIR_NAME}"
-
-  if ! is_dry_run; then
-    cd "$svn_target"
-    svn ci --username "$ASF_USERNAME" --password "$ASF_PASSWORD" -m"Apache 
${PROJECT} $package_version_name" --no-auth-cache
-    cd ..
-    rm -rf "$svn_target"
-  else
-    mv "$svn_target/${DEST_DIR_NAME}" "${svn_target}_${DEST_DIR_NAME}.dist"
-    log "Dry run: svn-managed 'dist' directory with release tarballs, 
CHANGES.md and RELEASENOTES.md available as 
$(pwd)/${svn_target}_${DEST_DIR_NAME}.dist"
-    rm -rf "$svn_target"
-  fi
-  log "svn ci done"
-
-  exit 0
-fi
-
-if [[ "$1" == "publish-snapshot" ]]; then
-  (
-  cd "${PROJECT}"
-  mvn_log="${BASE_DIR}/mvn_deploy_snapshot.log"
-  log "Publishing snapshot to nexus"
-  maven_deploy snapshot "$mvn_log"
-  if ! is_dry_run; then
-    log "Snapshot artifacts successfully published to repo."
-    rm "$mvn_log"
-  else
-    log "Dry run: Snapshot artifacts successfully built, but not published due 
to dry run."
-  fi
-  )
-  exit $?
-fi
-
-if [[ "$1" == "publish-release" ]]; then
-  (
-  cd "${PROJECT}"
-  mvn_log="${BASE_DIR}/mvn_deploy_release.log"
-  log "Staging release in nexus"
-  maven_deploy release "$mvn_log"
-  declare staged_repo_id
-  declare hadoop3_staged_repo_id
-  if ! is_dry_run; then
-    mapfile -t staged_repo_ids < <(grep -o "Closing staging repository with ID 
.*" "$mvn_log" \
-        | sed -e 's/Closing staging repository with ID "\([^"]*\)"./\1/')
-    log "Release artifacts successfully published to repo: " 
"${staged_repo_ids[@]}"
-    repo_count="${#staged_repo_ids[@]}"
-    if [[ "${repo_count}" == "2" ]]; then
-      staged_repo_id=${staged_repo_ids[0]}
-      hadoop3_staged_repo_id=${staged_repo_ids[1]}
-    elif [[ "${repo_count}" == "1" ]]; then
-      staged_repo_id=${staged_repo_ids[0]}
-      hadoop3_staged_repo_id="not-applicable"
-    else
-      staged_repo_id="not-applicable"
-      hadoop3_staged_repo_id="not-applicable"
-    fi
-    rm "$mvn_log"
-  else
-    log "Dry run: Release artifacts successfully built, but not published due 
to dry run."
-    staged_repo_id="dryrun-no-repo"
-    hadoop3_staged_repo_id="dryrun-no-repo"
-  fi
-  export staged_repo_id
-  export hadoop3_staged_repo_id
-  # Dump out email to send. Where we find vote.tmpl depends
-  # on where this script is run from
-  PROJECT_TEXT="${PROJECT//-/ }" #substitute like 's/-/ /g'
-  export PROJECT_TEXT
-  eval "echo \"$(< "${SELF}/vote.tmpl")\"" |tee "${BASE_DIR}/vote.txt"
-  )
-  exit $?
-fi
-
-set +x  # done with detailed logging
-cd ..
-rm -rf "${PROJECT}"
-log "ERROR: expects to be called with 'tag', 'publish-dist', 
'publish-release', or 'publish-snapshot'" >&2
-exit_with_usage
diff --git a/dev-support/create-release/release-util.sh 
b/dev-support/create-release/release-util.sh
deleted file mode 100755
index 787ec4dac18..00000000000
--- a/dev-support/create-release/release-util.sh
+++ /dev/null
@@ -1,873 +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.
-#
-
-# Source this file if you want to use any of its utiilty (also useful
-# testing the below functions). Do "$ . ./release-util.sh" and then
-# you can do stuff like call the CHANGES updating function
-# update_releasenotes:
-#
-#  $ update_releasenotes ~/checkouts/hbase.apache.git 2.3.4
-#
-# Just make sure any environment variables needed are predefined
-# in your context.
-#
-DRY_RUN=${DRY_RUN:-1} #default to dry run
-DEBUG=${DEBUG:-0}
-GPG=${GPG:-gpg}
-GPG_ARGS=(--no-autostart --batch --pinentry-mode error)
-if [ -n "${GPG_KEY}" ]; then
-  GPG_ARGS=("${GPG_ARGS[@]}" --local-user "${GPG_KEY}")
-fi
-# Maven Profiles for publishing snapshots and release to Maven Central and Dist
-PUBLISH_PROFILES=("-P" "apache-release,release")
-
-# get the current directory, we want to use some python scripts to generate
-# CHANGES.md and RELEASENOTES.md
-SELF="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-
-function error {
-  log "Error: $*" >&2
-  exit 1
-}
-
-function read_config {
-  local PROMPT="$1"
-  local DEFAULT="$2"
-  local REPLY=
-
-  read -r -p "$PROMPT [$DEFAULT]: " REPLY
-  local RETVAL="${REPLY:-$DEFAULT}"
-  if [ -z "$RETVAL" ]; then
-    error "$PROMPT must be provided."
-  fi
-  echo "$RETVAL"
-}
-
-function parse_version {
-  xmllint --xpath 
"//*[local-name()='project']/*[local-name()='version']/text()" -
-}
-
-function parse_revision {
-  xmllint --xpath 
"//*[local-name()='project']/*[local-name()='properties']/*[local-name()='revision']/text()"
 -
-}
-
-function banner {
-  local msg="$1"
-  echo "========================"
-  log "${msg}"
-  echo
-}
-
-function log {
-  echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") $*"
-}
-
-# current number of seconds since epoch
-function get_ctime {
-  date +"%s"
-}
-
-function run_silent {
-  local BANNER="$1"
-  local LOG_FILE="$2"
-  shift 2
-  local -i start_time
-  local -i stop_time
-
-  banner "${BANNER}"
-  log "Command: $*"
-  log "Log file: $LOG_FILE"
-  start_time="$(get_ctime)"
-
-  if ! "$@" 1>"$LOG_FILE" 2>&1; then
-    log "Command FAILED. Check full logs for details."
-    tail "$LOG_FILE"
-    exit 1
-  fi
-  stop_time="$(get_ctime)"
-  log "SUCCESS ($((stop_time - start_time)) seconds)"
-}
-
-function fcreate_secure {
-  local FPATH="$1"
-  rm -f "$FPATH"
-  touch "$FPATH"
-  chmod 600 "$FPATH"
-}
-
-# API compare version.
-function get_api_diff_version {
-  local version="$1"
-  local rev
-  local api_diff_tag
-  rev=$(echo "$version" | cut -d . -f 3)
-  if [ "$rev" != 0 ]; then
-    local short_version
-    short_version="$(echo "$version" | cut -d . -f 1-2)"
-    api_diff_tag="rel/${short_version}.$((rev - 1))"
-  else
-    local major minor
-    major="$(echo "$version" | cut -d . -f 1)"
-    minor="$(echo "$version" | cut -d . -f 2)"
-    if [ "$minor" != 0 ]; then
-      api_diff_tag="rel/${major}.$((minor - 1)).0"
-    else
-      api_diff_tag="rel/$((major - 1)).0.0"
-    fi
-  fi
-  api_diff_tag="$(read_config "api_diff_tag" "$api_diff_tag")"
-  echo "$api_diff_tag"
-}
-
-# Get all branches that begin with 'branch-', the hbase convention for
-# release branches, sort them and then pop off the most recent.
-function get_release_info {
-  init_xmllint
-
-  PROJECT="$(read_config "PROJECT" "$PROJECT")"
-  export PROJECT
-
-  if [[ -z "${ASF_REPO}" ]]; then
-    ASF_REPO="https://gitbox.apache.org/repos/asf/${PROJECT}.git";
-  fi
-  if [[ -z "${ASF_REPO_WEBUI}" ]]; then
-    ASF_REPO_WEBUI="https://gitbox.apache.org/repos/asf?p=${PROJECT}.git";
-  fi
-  if [[ -z "${ASF_GITHUB_REPO}" ]]; then
-    ASF_GITHUB_REPO="https://github.com/apache/${PROJECT}";
-  fi
-  if [ -z "$GIT_BRANCH" ]; then
-    # If no branch is specified, find out the latest branch from the repo.
-    GIT_BRANCH="$(git ls-remote --heads "$ASF_REPO" |
-      grep refs/heads/branch- |
-      awk '{print $2}' |
-      sort -r |
-      head -n 1 |
-      cut -d/ -f3)"
-  fi
-
-  GIT_BRANCH="$(read_config "GIT_BRANCH" "$GIT_BRANCH")"
-  export GIT_BRANCH
-
-  # Find the current version for the branch.
-  local version
-  version="$(curl -s 
"$ASF_REPO_WEBUI;a=blob_plain;f=pom.xml;hb=refs/heads/$GIT_BRANCH" |
-    parse_version)"
-  # We do not want to expand ${revision} here, see 
https://maven.apache.org/maven-ci-friendly.html
-  # If we use ${revision} as placeholder, we need to parse the revision 
property to
-  # get maven version
-  # shellcheck disable=SC2016
-  if [[ "${version}" == '${revision}' ]]; then
-    version="$(curl -s 
"$ASF_REPO_WEBUI;a=blob_plain;f=pom.xml;hb=refs/heads/$GIT_BRANCH" |
-      parse_revision)"
-  fi
-  log "Current branch VERSION is $version."
-
-  NEXT_VERSION="$version"
-  RELEASE_VERSION=""
-  SHORT_VERSION="$(echo "$version" | cut -d . -f 1-2)"
-  if [[ ! "$version" =~ .*-SNAPSHOT ]]; then
-    RELEASE_VERSION="$version"
-  else
-    RELEASE_VERSION="${version/-SNAPSHOT/}"
-  fi
-
-  local REV
-  REV="$(echo "${RELEASE_VERSION}" | cut -d . -f 3)"
-
-  # Find out what RC is being prepared.
-  # - If the current version is "x.y.0", then this is RC0 of the "x.y.0" 
release.
-  # - If not, need to check whether the previous version has been already 
released or not.
-  #   - If it has, then we're building RC0 of the current version.
-  #   - If it has not, we're building the next RC of the previous version.
-  if [[ -z "${RC_COUNT}" ]]; then
-    local RC_COUNT
-    if [ "$REV" != 0 ]; then
-      local PREV_REL_REV=$((REV - 1))
-      PREV_VERSION=${SHORT_VERSION}.${PREV_REL_REV}
-      PREV_REL_TAG="rel/${PREV_VERSION}"
-      if git ls-remote --tags "$ASF_REPO" "$PREV_REL_TAG" | grep -q 
"refs/tags/${PREV_REL_TAG}$" ; then
-        RC_COUNT=0
-        REV=$((REV + 1))
-        NEXT_VERSION="${SHORT_VERSION}.${REV}-SNAPSHOT"
-      else
-        RELEASE_VERSION="${SHORT_VERSION}.${PREV_REL_REV}"
-        RC_COUNT="$(git ls-remote --tags "$ASF_REPO" "${RELEASE_VERSION}RC*" | 
wc -l)"
-        # This makes a 'number' of it.
-        RC_COUNT=$((RC_COUNT))
-      fi
-    else
-      REV=$((REV + 1))
-      NEXT_VERSION="${SHORT_VERSION}.${REV}-SNAPSHOT"
-      # not easy to calculate it, just leave it as empty and let users provide 
it
-      PREV_VERSION=""
-      RC_COUNT=0
-    fi
-  fi
-
-  RELEASE_VERSION="$(read_config "RELEASE_VERSION" "$RELEASE_VERSION")"
-  NEXT_VERSION="$(read_config "NEXT_VERSION" "$NEXT_VERSION")"
-  PREV_VERSION="$(read_config "PREV_VERSION" "$PREV_VERSION")"
-  export RELEASE_VERSION NEXT_VERSION PREV_VERSION
-
-  RC_COUNT="$(read_config "RC_COUNT" "$RC_COUNT")"
-  if [[ -z "${RELEASE_TAG}" ]]; then
-    RELEASE_TAG="${RELEASE_VERSION}RC${RC_COUNT}"
-    RELEASE_TAG="$(read_config "RELEASE_TAG" "$RELEASE_TAG")"
-  fi
-
-  # Check if the RC already exists, and if re-creating the RC, skip tag 
creation.
-  SKIP_TAG=0
-  if git ls-remote --tags "$ASF_REPO" "$RELEASE_TAG" | grep -q 
"refs/tags/${RELEASE_TAG}$" ; then
-    read -r -p "$RELEASE_TAG already exists. Continue anyway [y/n]? " ANSWER
-    if [ "$ANSWER" != "y" ]; then
-      log "Exiting."
-      exit 1
-    fi
-    SKIP_TAG=1
-  fi
-
-  export RELEASE_TAG SKIP_TAG
-
-  GIT_REF="$RELEASE_TAG"
-  if is_dry_run; then
-    log "This is a dry run. If tag does not actually exist, please confirm the 
ref that will be built for testing."
-    GIT_REF="$(read_config "GIT_REF" "$GIT_REF")"
-  fi
-  export GIT_REF
-
-  API_DIFF_TAG="$(get_api_diff_version "$RELEASE_VERSION")"
-
-  # Gather some user information.
-  ASF_USERNAME="$(read_config "ASF_USERNAME" "$LOGNAME")"
-
-  GIT_NAME="$(git config user.name || echo "")"
-  GIT_NAME="$(read_config "GIT_NAME" "$GIT_NAME")"
-
-  GIT_EMAIL="[email protected]"
-  if [[ -z "${GPG_KEY}" ]]; then
-    GPG_KEY="$(read_config "GPG_KEY" "$GIT_EMAIL")"
-  fi
-  if ! GPG_KEY_ID=$("${GPG}" "${GPG_ARGS[@]}" --keyid-format 0xshort 
--list-public-key "${GPG_KEY}" | grep "\[S\]" | grep -o "0x[0-9A-F]*") ||
-      [ -z "${GPG_KEY_ID}" ] ; then
-    GPG_KEY_ID=$("${GPG}" "${GPG_ARGS[@]}" --keyid-format 0xshort 
--list-public-key "${GPG_KEY}" | head -n 1 | grep -o "0x[0-9A-F]*" || true)
-  fi
-  read -r -p "Does the GPG key '${GPG_KEY}' corresponds to the GPG key id 
'${GPG_KEY_ID}'. Is this correct [y/n]? " ANSWER
-  if [ "$ANSWER" = "y" ]; then
-    GPG_KEY="${GPG_KEY_ID}"
-  fi
-  export API_DIFF_TAG ASF_USERNAME GIT_NAME GIT_EMAIL GPG_KEY
-
-  cat <<EOF
-================
-Release details:
-GIT_BRANCH:      $GIT_BRANCH
-RELEASE_VERSION: $RELEASE_VERSION
-NEXT_VERSION:    $NEXT_VERSION
-PREV_VERSION:    $PREV_VERSION
-RELEASE_TAG:     $RELEASE_TAG $([[ "$GIT_REF" != "$RELEASE_TAG" ]] && printf 
"\n%s\n" "GIT_REF:         $GIT_REF")
-API_DIFF_TAG:    $API_DIFF_TAG
-ASF_USERNAME:    $ASF_USERNAME
-GPG_KEY:         $GPG_KEY
-GIT_NAME:        $GIT_NAME
-GIT_EMAIL:       $GIT_EMAIL
-DRY_RUN:         $(is_dry_run && echo "yes" || echo "NO, THIS BUILD WILL BE 
PUBLISHED!")
-================
-EOF
-
-  read -r -p "Is this info correct [y/n]? " ANSWER
-  if [ "$ANSWER" != "y" ]; then
-    log "Exiting."
-    exit 1
-  fi
-  GPG_ARGS=("${GPG_ARGS[@]}" --local-user "${GPG_KEY}")
-
-  # The nexus staging plugin needs the password to contact to remote server 
even if
-  # skipRemoteStaging is set to true, not sure why so here we need the 
password even
-  # if this is a dry run
-  if [ -z "$ASF_PASSWORD" ]; then
-    stty -echo && printf "ASF_PASSWORD: " && read -r ASF_PASSWORD && printf 
'\n' && stty echo
-  fi
-
-  export ASF_PASSWORD
-}
-
-function is_dry_run {
-  [[ "$DRY_RUN" = 1 ]]
-}
-
-function is_debug {
-  [[ "${DEBUG}" = 1 ]]
-}
-
-function check_get_passwords {
-  for env in "$@"; do
-    if [ -z "${!env}" ]; then
-      log "The environment variable $env is not set. Please enter the password 
or passphrase."
-      echo
-      # shellcheck disable=SC2229
-      stty -echo && printf "%s : " "$env" && read -r "$env" && printf '\n' && 
stty echo
-    fi
-    # shellcheck disable=SC2163
-    export "$env"
-  done
-}
-
-function check_needed_vars {
-  local missing=0
-  for env in "$@"; do
-    if [ -z "${!env}" ]; then
-      log "$env must be set to run this script"
-      (( missing++ ))
-    else
-      # shellcheck disable=SC2163
-      export "$env"
-    fi
-  done
-  (( missing > 0 )) && exit_with_usage
-  return 0
-}
-
-function init_locale {
-  local locale_value
-  OS="$(uname -s)"
-  case "${OS}" in
-    Darwin*)    locale_value="en_US.UTF-8";;
-    Linux*)     locale_value="C.UTF-8";;
-    *)          error "unknown OS";;
-  esac
-  export LC_ALL="$locale_value"
-  export LANG="$locale_value"
-}
-
-# Check whether xmllint is available
-function init_xmllint {
-  if ! [ -x "$(command -v xmllint)"  ]; then
-    log "Error: xmllint is not available, we need to use it for parsing 
pom.xml." >&2
-    log "Ubuntu: apt install libxml2-utils" >&2
-    log "CentOS: yum install xmlstarlet" >&2
-    log "Mac OS: brew install xmlstarlet" >&2
-    exit 1
-  fi
-}
-
-# Initializes JAVA_VERSION to the version of the JVM in use.
-function init_java {
-  if [ -z "$JAVA_HOME" ]; then
-    error "JAVA_HOME is not set."
-  fi
-  JAVA_VERSION=$("${JAVA_HOME}"/bin/javac -version 2>&1 | cut -d " " -f 2)
-  log "java version: $JAVA_VERSION"
-  export JAVA_VERSION
-}
-
-function init_python {
-  if ! [ -x "$(command -v python3)"  ]; then
-    error 'python3 needed by yetus and api report. Install or add link?'
-  fi
-  log "python3 version: $(python3 --version)"
-}
-
-# Set MVN
-function init_mvn {
-  if [ -n "$MAVEN_HOME" ]; then
-      MVN=("${MAVEN_HOME}/bin/mvn")
-  elif [ "$(type -P mvn)" ]; then
-      MVN=(mvn)
-  else
-    error "MAVEN_HOME is not set nor is mvn on the current path."
-  fi
-  # Add batch mode.
-  MVN=("${MVN[@]}" -B)
-  export MVN
-  echo -n "mvn version: "
-  "${MVN[@]}" --version
-  configure_maven
-}
-
-function init_yetus {
-  declare YETUS_VERSION
-  if [ -z "${YETUS_HOME}" ]; then
-    error "Missing Apache Yetus."
-  fi
-  # Work around yetus bug by asking test-patch for the version instead of rdm.
-  YETUS_VERSION=$("${YETUS_HOME}/bin/test-patch" --version)
-  log "Apache Yetus version ${YETUS_VERSION}"
-}
-
-function configure_maven {
-  # Add timestamps to mvn logs.
-  MAVEN_OPTS="-Dorg.slf4j.simpleLogger.showDateTime=true 
-Dorg.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss ${MAVEN_OPTS}"
-  # Suppress gobs of "Download from central:" messages
-  
MAVEN_OPTS="-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
 ${MAVEN_OPTS}"
-  MAVEN_LOCAL_REPO="${REPO:-$(pwd)/$(mktemp -d hbase-repo-XXXXX)}"
-  [[ -d "$MAVEN_LOCAL_REPO" ]] || mkdir -p "$MAVEN_LOCAL_REPO"
-  MAVEN_SETTINGS_FILE="${MAVEN_LOCAL_REPO}/tmp-settings.xml"
-  MVN=("${MVN[@]}" --settings "${MAVEN_SETTINGS_FILE}")
-  export MVN MAVEN_OPTS MAVEN_SETTINGS_FILE MAVEN_LOCAL_REPO
-  export ASF_USERNAME ASF_PASSWORD
-  # reference passwords from env rather than storing in the settings.xml file.
-  cat <<'EOF' > "$MAVEN_SETTINGS_FILE"
-<?xml version="1.0" encoding="UTF-8"?>
-<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0";
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 
http://maven.apache.org/xsd/settings-1.0.0.xsd";>
-  <localRepository>/${env.MAVEN_LOCAL_REPO}</localRepository>
-  <servers>
-    
<server><id>apache.snapshots.https</id><username>${env.ASF_USERNAME}</username>
-      <password>${env.ASF_PASSWORD}</password></server>
-    
<server><id>apache.releases.https</id><username>${env.ASF_USERNAME}</username>
-      <password>${env.ASF_PASSWORD}</password></server>
-  </servers>
-  <profiles>
-    <profile>
-      <activation>
-        <activeByDefault>true</activeByDefault>
-      </activation>
-      <properties>
-        <gpg.keyname>${env.GPG_KEY}</gpg.keyname>
-      </properties>
-    </profile>
-  </profiles>
-</settings>
-EOF
-}
-
-# clone of the repo, deleting anything that exists in the working directory 
named after the project.
-# optionally with auth details for pushing.
-function git_clone_overwrite {
-  local asf_repo
-  if [ -z "${PROJECT}" ] || [ "${PROJECT}" != "${PROJECT#/}" ]; then
-    error "Project name must be defined and not start with a '/'. 
PROJECT='${PROJECT}'"
-  fi
-  rm -rf "${PROJECT}"
-
-  if [[ -z "${GIT_REPO}" ]]; then
-    asf_repo="gitbox.apache.org/repos/asf/${PROJECT}.git"
-    log "Clone will be of the gitbox repo for ${PROJECT}."
-    if [ -n "${ASF_USERNAME}" ] && [ -n "${ASF_PASSWORD}" ]; then
-      # Ugly!
-      encoded_username=$(python3 -c "from urllib.parse import quote; 
print(quote('''$ASF_USERNAME''', ''))")
-      encoded_password=$(python3 -c "from urllib.parse import quote; 
print(quote('''$ASF_PASSWORD''', ''))")
-      GIT_REPO="https://$encoded_username:$encoded_password@${asf_repo}";
-    else
-      GIT_REPO="https://${asf_repo}";
-    fi
-  else
-    log "Clone will be of provided git repo."
-  fi
-  # N.B. we use the shared flag because the clone is short lived and if a 
local repo repo was
-  #      given this will let us refer to objects there directly instead of 
hardlinks or copying.
-  #      The option is silently ignored for non-local repositories. see the 
note on git help clone
-  #      for the --shared option for details.
-  git clone --shared -b "${GIT_BRANCH}" -- "${GIT_REPO}" "${PROJECT}"
-  # If this was a host local git repo then add in an alternates and remote 
that will
-  # work back on the host if the RM needs to do any post-processing steps, 
i.e. pushing the git tag
-  # for more info see 'git help remote' and 'git help repository-layout'.
-  if [ -n "$HOST_GIT_REPO" ]; then
-    echo "${HOST_GIT_REPO}/objects" >> 
"${PROJECT}/.git/objects/info/alternates"
-    (cd "${PROJECT}"; git remote add host "${HOST_GIT_REPO}")
-  fi
-}
-
-function start_step {
-  local name=$1
-  if [ -z "${name}" ]; then
-    name="${FUNCNAME[1]}"
-  fi
-  log "${name} start" >&2
-  get_ctime
-}
-
-function stop_step {
-  local name=$2
-  local start_time=$1
-  local stop_time
-  if [ -z "${name}" ]; then
-    name="${FUNCNAME[1]}"
-  fi
-  stop_time="$(get_ctime)"
-  log "${name} stop ($((stop_time - start_time)) seconds)"
-}
-
-# Writes report into cwd!
-# TODO should have option for maintenance release that include LimitedPrivate 
in report
-function generate_api_report {
-  local project="$1"
-  local previous_tag="$2"
-  local release_tag="$3"
-  local previous_version
-  local timing_token
-  timing_token="$(start_step)"
-  # Generate api report.
-  # Filter out some jar types. Filters are tricky. Python regex on
-  # file basename. Exclude the saved-aside original jars... they are
-  # not included in resulting artifact. Also, do not include the
-  # hbase-shaded-testing-util.*  jars. This jar is unzip'able on mac
-  # os x as is because has it a META_INF/LICENSE file and then a
-  # META_INF/license directory for the included jar's licenses;
-  # it fails to unjar on mac os x which this tool does making its checks
-  # (Its exclusion should be fine; it is just an aggregate of other jars).
-  "${project}"/dev-support/checkcompatibility.py --annotation \
-    org.apache.yetus.audience.InterfaceAudience.Public  \
-    -e "original-hbase.*.jar" \
-    -e "hbase-shaded-testing-util.*.jar" \
-    "$previous_tag" "$release_tag"
-  previous_version="$(echo "${previous_tag}" | sed -e 's/rel\///')"
-  cp "${project}/target/compat-check/report.html" 
"./api_compare_${previous_version}_to_${release_tag}.html"
-  stop_step "${timing_token}"
-}
-
-# Look up the Jira name associated with project.
-# Returns result on stdout.
-# Currently all the 'hbase-*' projects share the same HBASE jira name.  This 
works because,
-# by convention, the HBASE jira "Fix Version" field values have the 
sub-project name pre-pended,
-# as in "hbase-operator-tools-1.0.0".
-# TODO: For non-hbase-related projects, enhance this to use Jira API query 
instead of text lookup.
-function get_jira_name {
-  local project="$1"
-  local jira_name
-  case "${project}" in
-    hbase*) jira_name="HBASE";;
-    *)      jira_name="";;
-  esac
-  if [[ -z "$jira_name" ]]; then
-    error "Sorry, can't determine the Jira name for project $project"
-  fi
-  echo "$jira_name"
-}
-
-# Update the CHANGES.md
-# DOES NOT DO COMMITS! Caller should do that.
-# requires yetus to have a defined home already.
-# yetus requires python3 to be on the path.
-function update_releasenotes {
-  local project_dir="$1"
-  local jira_fix_version="$2"
-  local jira_project
-  local timing_token
-  timing_token="$(start_step)"
-  changelog="CHANGELOG.${jira_fix_version}.md"
-  releasenotes="RELEASENOTES.${jira_fix_version}.md"
-  if [ -f ${changelog} ]; then
-    rm ${changelog}
-  fi
-  if [ -f ${releasenotes} ]; then
-    rm ${releasenotes}
-  fi
-  jira_project="$(get_jira_name "$(basename "$project_dir")")"
-  "${YETUS_HOME}/bin/releasedocmaker" -p "${jira_project}" --fileversions -v 
"${jira_fix_version}" \
-      -l --sortorder=newer --skip-credits || true
-  # First clear out the changes written by previous RCs.
-  if [ -f "${project_dir}/CHANGES.md" ]; then
-    sed -i -e \
-        "/^## Release ${jira_fix_version}/,/^## Release/ {//!d; /^## Release 
${jira_fix_version}/d;}" \
-        "${project_dir}/CHANGES.md" || true
-  else
-    # should be hbase 3.x, will copy CHANGES.md from archive.a.o/dist
-    curl --location --fail --silent --show-error --output 
${project_dir}/CHANGES.md 
"https://archive.apache.org/dist/hbase/${PREV_VERSION}/CHANGES.md";
-  fi
-  if [ -f "${project_dir}/RELEASENOTES.md" ]; then
-    sed -i -e \
-        "/^# ${jira_project}  ${jira_fix_version} Release Notes/,/^# 
${jira_project}/{//!d; /^# ${jira_project}  ${jira_fix_version} Release 
Notes/d;}" \
-        "${project_dir}/RELEASENOTES.md" || true
-  else
-    # should be hbase 3.x, will copy CHANGES.md from archive.a.o/dist
-    curl --location --fail --silent --show-error --output 
${project_dir}/RELEASENOTES.md 
"https://archive.apache.org/dist/hbase/${PREV_VERSION}/RELEASENOTES.md";
-  fi
-
-  # Yetus will not generate CHANGES if no JIRAs fixed against the release 
version
-  # (Could happen if a release were bungled such that we had to make a new one
-  # without changes)
-  if [ ! -f "${changelog}" ]; then
-    echo -e "## Release ${jira_fix_version} - Unreleased (as of `date`)\nNo 
changes\n" > "${changelog}"
-  fi
-  if [ ! -f "${releasenotes}" ]; then
-    echo -e "# hbase ${jira_fix_version} Release Notes\nNo changes\n" > 
"${releasenotes}"
-  fi
-
-  # The releasedocmaker call above generates RELEASENOTES.X.X.X.md and 
CHANGELOG.X.X.X.md.
-  if [ -f "${project_dir}/CHANGES.md" ]; then
-    $SELF/prepend_changes.py "${changelog}" "${project_dir}/CHANGES.md"
-  else
-    mv "${changelog}" "${project_dir}/CHANGES.md"
-  fi
-  if [ -f "${project_dir}/RELEASENOTES.md" ]; then
-    $SELF/prepend_releasenotes.py "${releasenotes}" 
"${project_dir}/RELEASENOTES.md"
-  else
-    mv "${releasenotes}" "${project_dir}/RELEASENOTES.md"
-  fi
-  stop_step "${timing_token}"
-}
-
-# Make src release.
-# Takes as arguments first the project name -- e.g. hbase or 
hbase-operator-tools
-# -- and then the version string. Expects to find checkout adjacent to this 
script
-# named for 'project', the first arg passed.
-# Expects the following three defines in the environment:
-# - GPG needs to be defined, with the path to GPG: defaults 'gpg'.
-# - GIT_REF which is the tag to create the tgz from: defaults to 'master'.
-# For example:
-# $ GIT_REF="master" make_src_release hbase-operator-tools 1.0.0
-make_src_release() {
-  # Tar up the src and sign and hash it.
-  local project="${1}"
-  local version="${2}"
-  local base_name="${project}-${version}"
-  local timing_token
-  timing_token="$(start_step)"
-  rm -rf "${base_name}"-src*
-  tgz="${base_name}-src.tar.gz"
-  cd "${project}" || exit
-  git clean -d -f -x
-  git archive --format=tar.gz --output="../${tgz}" --prefix="${base_name}/" 
"${GIT_REF:-master}"
-  cd .. || exit
-  $GPG "${GPG_ARGS[@]}" --armor --output "${tgz}.asc" --detach-sig "${tgz}"
-  $GPG "${GPG_ARGS[@]}" --print-md SHA512 "${tgz}" > "${tgz}.sha512"
-  stop_step "${timing_token}"
-}
-
-build_release_binary() {
-  local project="${1}"
-  local version="${2}"
-  local base_name="${project}-${version}"
-  local extra_flags=()
-  if [[ "${version}" = *-hadoop3 ]] || [[ "${version}" = *-hadoop3-SNAPSHOT 
]]; then
-    extra_flags=("-Drevision=${version}" "-Dhadoop.profile=3.0")
-  fi
-
-  cd "$project" || exit
-  git clean -d -f -x
-  # Three invocations of maven. This seems to work. One to
-  # populate the repo, another to build the site, and then
-  # a third to assemble the binary artifact. Trying to do
-  # all in the one invocation fails; a problem in our
-  # assembly spec to in maven. TODO. Meantime, three invocations.
-  cmd=("${MVN[@]}" "${extra_flags[@]}" clean install -DskipTests)
-  echo "${cmd[*]}"
-  "${cmd[@]}"
-  cmd=("${MVN[@]}" "${extra_flags[@]}" site -DskipTests)
-  echo "${cmd[*]}"
-  "${cmd[@]}"
-  kick_gpg_agent
-  cmd=("${MVN[@]}" "${extra_flags[@]}" install assembly:single -DskipTests 
-Dcheckstyle.skip=true "${PUBLISH_PROFILES[@]}")
-  echo "${cmd[*]}"
-  "${cmd[@]}"
-
-  # Check there is a bin gz output. The build may not produce one: e.g. 
hbase-thirdparty.
-  local f_bin_prefix="./${PROJECT}-assembly/target/${base_name}"
-  if ls "${f_bin_prefix}"*-bin.tar.gz &>/dev/null; then
-    cp "${f_bin_prefix}"*-bin.tar.gz ..
-    cd .. || exit
-    for i in "${base_name}"*-bin.tar.gz; do
-      "${GPG}" "${GPG_ARGS[@]}" --armour --output "${i}.asc" --detach-sig 
"${i}"
-      "${GPG}" "${GPG_ARGS[@]}" --print-md SHA512 "${i}" > "${i}.sha512"
-    done
-  else
-    cd .. || exit
-    log "No ${f_bin_prefix}*-bin.tar.gz product; expected?"
-  fi
-}
-
-# Make binary release.
-# Takes as arguments first the project name -- e.g. hbase or 
hbase-operator-tools
-# -- and then the version string. Expects to find checkout adjacent to this 
script
-# named for 'project', the first arg passed.
-# Expects the following three defines in the environment:
-# - GPG needs to be defined, with the path to GPG: defaults 'gpg'.
-# - GIT_REF which is the tag to create the tgz from: defaults to 'master'.
-# - MVN Default is "mvn -B --settings $MAVEN_SETTINGS_FILE".
-# For example:
-# $ GIT_REF="master" make_src_release hbase-operator-tools 1.0.0
-make_binary_release() {
-  local project="${1}"
-  local version="${2}"
-  local base_name="${project}-${version}"
-  local timing_token
-  timing_token="$(start_step)"
-  rm -rf "${base_name}"-bin*
-
-  build_release_binary "${project}" "${version}"
-  if should_build_with_hadoop3 "$project/pom.xml"; then
-    build_release_binary "${project}" "$(get_hadoop3_version "${version}")"
-  fi
-
-  stop_step "${timing_token}"
-}
-
-# "Wake up" the gpg agent so it responds properly to maven-gpg-plugin, and 
doesn't cause timeout.
-# Specifically this is done between invocation of 'mvn site' and 'mvn 
assembly:single', because
-# the 'site' build takes long enough that the gpg-agent does become 
unresponsive and the following
-# 'assembly' build (where gpg signing occurs) experiences timeout, without 
this "kick".
-function kick_gpg_agent {
-  # All that's needed is to run gpg on a random file
-  # TODO could we just call gpg-connect-agent /bye
-  local i
-  i="$(mktemp)"
-  echo "This is a test file" > "$i"
-  "${GPG}" "${GPG_ARGS[@]}" --armour --output "${i}.asc" --detach-sig "${i}"
-  rm "$i" "$i.asc"
-}
-
-# Do maven command to set version into local pom
-function maven_set_version { #input: <version_to_set>
-  local this_version="$1"
-  local use_revision='false'
-  local maven_version
-  maven_version="$(parse_version < pom.xml)"
-  # We do not want to expand ${revision} here, see 
https://maven.apache.org/maven-ci-friendly.html
-  # If we use ${revision} as placeholder, the way to bump maven version will 
be different
-  # shellcheck disable=SC2016
-  if [[ "${maven_version}" == '${revision}' ]]; then
-    use_revision='true'
-  fi
-
-  if [ "${use_revision}" = 'false' ] ; then
-    log "${MVN[@]}" versions:set -DnewVersion="$this_version"
-    "${MVN[@]}" versions:set -DnewVersion="$this_version" | grep -v "no value" 
# silence logs
-  else
-    log "${MVN[@]}" versions:set-property -Dproperty=revision 
-DnewVersion="$this_version" -DgenerateBackupPoms=false
-    "${MVN[@]}" versions:set-property -Dproperty=revision 
-DnewVersion="$this_version" -DgenerateBackupPoms=false | grep -v "no value" # 
silence logs
-  fi
-}
-
-# Do maven command to read version from local pom
-function maven_get_version {
-  # shellcheck disable=SC2016
-  "${MVN[@]}" -q -N -Dexec.executable="echo" -Dexec.args='${project.version}' 
exec:exec
-}
-
-# Do maven deploy to snapshot or release artifact repository, with checks.
-function maven_deploy { #inputs: <snapshot|release> <log_file_path>
-  local timing_token
-  # Invoke with cwd=$PROJECT
-  local deploy_type="$1"
-  local mvn_log_file="$2" #secondary log file used later to extract 
staged_repo_id
-  local staging_dir
-  if [[ "$deploy_type" != "snapshot" && "$deploy_type" != "release" ]]; then
-    error "unrecognized deploy type, must be 'snapshot'|'release'"
-  fi
-  if [[ -z "$mvn_log_file" ]] || ! touch "$mvn_log_file"; then
-    error "must provide writable maven log output filepath"
-  fi
-  timing_token=$(start_step)
-  # shellcheck disable=SC2153
-  if [[ "$deploy_type" == "snapshot" ]] && ! [[ "$RELEASE_VERSION" =~ 
-SNAPSHOT$ ]]; then
-    error "Snapshots must have a version with suffix '-SNAPSHOT'; you gave 
version '$RELEASE_VERSION'"
-  elif [[ "$deploy_type" == "release" ]] && [[ "$RELEASE_VERSION" =~ SNAPSHOT 
]]; then
-    error "Non-snapshot release version must not include the word 'SNAPSHOT'; 
you gave version '$RELEASE_VERSION'"
-  fi
-  # Just output to parent directory, the staging directory has a staging 
prefix already
-  staging_dir="$(dirname "$(pwd)")/local-staged"
-  # Publish ${PROJECT} to Maven repo
-  # shellcheck disable=SC2154
-  log "Publishing ${PROJECT} checkout at '$GIT_REF' ($git_hash)"
-  log "Publish version is $RELEASE_VERSION"
-  # Coerce the requested version
-  maven_set_version "$RELEASE_VERSION"
-  # Prepare for signing
-  kick_gpg_agent
-  declare -a mvn_extra_flags=()
-  if is_dry_run; then
-    # In dry run mode, skip deploying to remote repo
-    mvn_extra_flags=("${mvn_extra_flags[@]}" -DskipRemoteStaging)
-  fi
-  log "${MVN[@]}" clean deploy -DskipTests -Dcheckstyle.skip=true \
-    -DaltStagingDirectory="${staging_dir}" "${PUBLISH_PROFILES[@]}" 
"${mvn_extra_flags[@]}"
-  log "Logging to ${mvn_log_file}.  This will take a while..."
-  rm -f "$mvn_log_file"
-  # The tortuous redirect in the next command allows mvn's stdout and stderr 
to go to mvn_log_file,
-  # while also sending stderr back to the caller.
-  # shellcheck disable=SC2094
-  if ! "${MVN[@]}" clean deploy -DskipTests -Dcheckstyle.skip=true 
"${PUBLISH_PROFILES[@]}" \
-      -DaltStagingDirectory="${staging_dir}" "${PUBLISH_PROFILES[@]}" 
"${mvn_extra_flags[@]}" \
-      1>> "$mvn_log_file" 2> >( tee -a "$mvn_log_file" >&2 ); then
-    error "Deploy build failed, for details see log at '$mvn_log_file'."
-  fi
-  local hadoop3_version
-  if should_build_with_hadoop3 pom.xml; then
-    hadoop3_version="$(get_hadoop3_version "${RELEASE_VERSION}")"
-    hadoop3_staging_dir="${staging_dir}-hadoop3"
-    log "Deploying artifacts for hadoop3..."
-    log "${MVN[@]}" clean deploy -DskipTests -Dcheckstyle.skip=true \
-      -Drevision="${hadoop3_version}" -Dhadoop.profile=3.0 \
-      -DaltStagingDirectory="${hadoop3_staging_dir}" "${PUBLISH_PROFILES[@]}" 
"${mvn_extra_flags[@]}"
-    {
-      echo 
"========================================================================"
-      echo "Deploy build for hadoop3"
-      echo 
"========================================================================"
-    } >> "$mvn_log_file"
-    # shellcheck disable=SC2094
-    if ! "${MVN[@]}" clean deploy -DskipTests -Dcheckstyle.skip=true 
"${PUBLISH_PROFILES[@]}" \
-        -Drevision="${hadoop3_version}" -Dhadoop.profile=3.0 \
-        -DaltStagingDirectory="${hadoop3_staging_dir}" 
"${PUBLISH_PROFILES[@]}" "${mvn_extra_flags[@]}" \
-        1>> "$mvn_log_file" 2> >( tee -a "$mvn_log_file" >&2 ); then
-      error "Deploy build failed, for details see log at '$mvn_log_file'."
-    fi
-  fi
-  log "BUILD SUCCESS."
-  stop_step "${timing_token}"
-  return 0
-}
-
-# guess the host os
-# * DARWIN
-# * LINUX
-function get_host_os() {
-  uname -s | tr '[:lower:]' '[:upper:]'
-}
-
-function is_tracked() {
-  local file=$1
-  git ls-files --error-unmatch "$file" &>/dev/null
-  return $?
-}
-
-# When we have all the below conditions matched, we will build hadoop3 binaries
-# 1. Use $revision place holder as version in pom
-# 2. Has a hadoop-2.0 profile
-# 3. Has a hadoop-3.0 profile
-function should_build_with_hadoop3() {
-  local pom="$1"
-  maven_version="$(parse_version < "${pom}")"
-  # We do not want to expand ${revision} here, see 
https://maven.apache.org/maven-ci-friendly.html
-  # If we use ${revision} as placeholder, the way to bump maven version will 
be different
-  # shellcheck disable=SC2016
-  if [[ "${maven_version}" != '${revision}' ]]; then
-    return 1
-  fi
-  if ! xmllint --xpath 
"//*[local-name()='project']/*[local-name()='profiles']/*[local-name()='profile']/*[local-name()='id']/text()"
 "${pom}" \
-    | grep -q ^hadoop-2.0$; then
-    return 1
-  fi
-  if ! xmllint --xpath 
"//*[local-name()='project']/*[local-name()='profiles']/*[local-name()='profile']/*[local-name()='id']/text()"
 "${pom}" \
-    | grep -q ^hadoop-3.0$; then
-    return 1
-  fi
-  return 0
-}
-
-function get_hadoop3_version() {
-  local version="$1"
-  if [[ "${version}" =~ -SNAPSHOT$ ]]; then
-    echo "${version/-SNAPSHOT/-hadoop3-SNAPSHOT}"
-  else
-    echo "${version}-hadoop3"
-  fi
-}
diff --git a/dev-support/create-release/vote.tmpl 
b/dev-support/create-release/vote.tmpl
deleted file mode 100644
index bdc7901f712..00000000000
--- a/dev-support/create-release/vote.tmpl
+++ /dev/null
@@ -1,39 +0,0 @@
-Please vote on this Apache ${PROJECT_TEXT} release candidate,
-${PROJECT}-${RELEASE_TAG}
-
-The VOTE will remain open for at least 72 hours.
-
-[ ] +1 Release this package as Apache ${PROJECT_TEXT} ${RELEASE_VERSION}
-[ ] -1 Do not release this package because ...
-
-The tag to be voted on is ${RELEASE_TAG}:
-
-  https://github.com/apache/${PROJECT}/tree/${RELEASE_TAG}
-
-This tag currently points to git reference
-
-  ${GIT_LONG_HASH}
-
-The release files, including signatures, digests, as well as CHANGES.md
-and RELEASENOTES.md included in this RC can be found at:
-
-  https://dist.apache.org/repos/dist/dev/hbase/${DEST_DIR_NAME}/
-
-Maven artifacts are available in a staging repository at:
-
-  https://repository.apache.org/content/repositories/${staged_repo_id}/
-
-Maven artifacts for hadoop3 are available in a staging repository at:
-
-  https://repository.apache.org/content/repositories/${hadoop3_staged_repo_id}/
-
-Artifacts were signed with the ${GPG_KEY} key which can be found in:
-
-  https://downloads.apache.org/hbase/KEYS
-
-To learn more about Apache ${PROJECT_TEXT}, please see
-
-  http://hbase.apache.org/
-
-Thanks,
-Your HBase Release Manager


Reply via email to