This is an automated email from the ASF dual-hosted git repository.
jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new a4d720d38 [#4417] feat(build): Add release script to automate the
release process (#4518)
a4d720d38 is described below
commit a4d720d38df21f2d5f692caabacaba15d29d830d
Author: Jerry Shao <[email protected]>
AuthorDate: Wed Aug 21 16:13:10 2024 +0800
[#4417] feat(build): Add release script to automate the release process
(#4518)
### What changes were proposed in this pull request?
This PR proposes to add several release script to automate the release
process.
### Why are the changes needed?
Fix: #4417
### Does this PR introduce _any_ user-facing change?
No.
### How was this patch tested?
Local test.
---
LICENSE | 4 +
dev/release/do-release.sh | 106 +++++++++++++
dev/release/release-build.sh | 357 +++++++++++++++++++++++++++++++++++++++++++
dev/release/release-tag.sh | 116 ++++++++++++++
dev/release/release-util.sh | 229 +++++++++++++++++++++++++++
5 files changed, 812 insertions(+)
diff --git a/LICENSE b/LICENSE
index 2d4b82eb2..32b71f314 100644
--- a/LICENSE
+++ b/LICENSE
@@ -220,6 +220,10 @@
./api/src/main/java/org/apache/gravitino/rel/expressions/Expression.java
./api/src/main/java/org/apache/gravitino/rel/expressions/NamedReference.java
./spark-connector/spark-connector/src/test/java/org/apache/gravitino/spark/connector/integration/test/util/SparkUtilIT.java
+ ./dev/release/do-release.sh
+ ./dev/release/release-build.sh
+ ./dev/release/release-tag.sh
+ ./dev/release/release-util.sh
Apache Iceberg
./api/src/main/java/org/apache/gravitino/exceptions/RESTException.java
diff --git a/dev/release/do-release.sh b/dev/release/do-release.sh
new file mode 100755
index 000000000..8f0fc7f08
--- /dev/null
+++ b/dev/release/do-release.sh
@@ -0,0 +1,106 @@
+#!/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.
+#
+
+# Referred from Apache Spark's release script
+# dev/create-release/do-release.sh
+
+SELF=$(cd $(dirname $0) && pwd)
+
+while getopts ":b:n" opt; do
+ case $opt in
+ b) GIT_BRANCH=$OPTARG ;;
+ n) DRY_RUN=1 ;;
+ \?) error "Invalid option: $OPTARG" ;;
+ esac
+done
+
+DRY_RUN=${DRY_RUN:-0}
+export DRY_RUN
+
+cmds=("git" "gpg" "svn" "twine" "shasum" "sha1sum" "jq")
+for cmd in "${cmds[@]}"; do
+ if ! command -v $cmd &> /dev/null; then
+ echo "$cmd is required to run this script."
+ exit 1
+ fi
+done
+
+if ! command -v md5 &> /dev/null && ! command -v md5sum &> /dev/null; then
+ echo "md5 or md5sum is required to run this script."
+ exit 1
+fi
+
+. "$SELF/release-util.sh"
+
+if [ "$RUNNING_IN_DOCKER" = "1" ]; then
+ # Inside docker, need to import the GPG key stored in the current directory.
+ echo $GPG_PASSPHRASE | $GPG --passphrase-fd 0 --import "$SELF/gpg.key"
+
+ # We may need to adjust the path since JAVA_HOME may be overridden by the
driver script.
+ if [ -n "$JAVA_HOME" ]; then
+ export PATH="$JAVA_HOME/bin:$PATH"
+ else
+ # JAVA_HOME for the openjdk package.
+ export JAVA_HOME=/usr
+ fi
+else
+ # Outside docker, need to ask for information about the release.
+ get_release_info
+fi
+
+function should_build {
+ local WHAT=$1
+ [ -z "$RELEASE_STEP" ] || [ "$WHAT" = "$RELEASE_STEP" ]
+}
+
+if should_build "tag" && [ $SKIP_TAG = 0 ]; then
+ run_silent "Creating release tag $RELEASE_TAG..." "tag.log" \
+ "$SELF/release-tag.sh"
+ echo "It may take some time for the tag to be synchronized to github."
+ echo "Press enter when you've verified that the new tag ($RELEASE_TAG) is
available."
+ read
+else
+ echo "Skipping tag creation for $RELEASE_TAG."
+fi
+
+if should_build "build"; then
+ run_silent "Building Gravitino..." "build.log" \
+ "$SELF/release-build.sh" package
+else
+ echo "Skipping build step."
+fi
+
+if should_build "docs"; then
+ run_silent "Building documentation..." "docs.log" \
+ "$SELF/release-build.sh" docs
+else
+ echo "Skipping docs step."
+fi
+
+if should_build "publish"; then
+ run_silent "Publishing release" "publish.log" \
+ "$SELF/release-build.sh" publish-release
+else
+ echo "Skipping publish step."
+fi
+
+if [ ! -z "$RELEASE_STEP" ] && [ "$RELEASE_STEP" = "finalize" ]; then
+ run_silent "Finalizing release" "finalize.log" \
+ "$SELF/release-build.sh" finalize
+fi
diff --git a/dev/release/release-build.sh b/dev/release/release-build.sh
new file mode 100755
index 000000000..d6d4ca5d4
--- /dev/null
+++ b/dev/release/release-build.sh
@@ -0,0 +1,357 @@
+#!/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.
+#
+
+# Referred from Apache Spark's release script
+# dev/create-release/release-build.sh
+
+SELF=$(cd $(dirname $0) && pwd)
+. "$SELF/release-util.sh"
+
+function exit_with_usage {
+ cat << EOF
+usage: release-build.sh <package|docs|publish-release|finalize>
+Creates build deliverables from a Apache Gravitino commit.
+
+Top level targets are
+ package: Create binary packages and commit them to
dist.apache.org/repos/dist/dev/incubator/gravitino/
+ docs: Build the Java and Python docs, and copy them to a local path.
+ publish-release: Publish a release to Apache release repo
+ finalize: Finalize the release after an RC passes vote
+
+All other inputs are environment variables
+
+GIT_REF - Release tag or commit to build from
+GRAVITINO_PACKAGE_VERSION - Release identifier in top level package directory
(e.g. 0.6.0-incubating-rc1)
+GRAVITINO_VERSION - (optional) Version of Gravitino being built (e.g.
0.6.0-incubating)
+
+ASF_USERNAME - Username of ASF committer account
+ASF_PASSWORD - Password of ASF committer account
+
+GPG_KEY - GPG key used to sign release artifacts
+GPG_PASSPHRASE - Passphrase for GPG key
+EOF
+ exit 1
+}
+
+set -e
+
+if [ $# -eq 0 ]; then
+ exit_with_usage
+fi
+
+if [[ $@ == *"help"* ]]; then
+ exit_with_usage
+fi
+
+if [[ -z "$ASF_PASSWORD" ]]; then
+ echo 'The environment variable ASF_PASSWORD is not set. Enter the password.'
+ echo
+ stty -echo && printf "ASF password: " && read ASF_PASSWORD && printf '\n' &&
stty echo
+fi
+
+if [[ -z "$GPG_PASSPHRASE" ]]; then
+ echo 'The environment variable GPG_PASSPHRASE is not set. Enter the
passphrase to'
+ echo 'unlock the GPG signing key that will be used to sign the release!'
+ echo
+ stty -echo && printf "GPG passphrase: " && read GPG_PASSPHRASE && printf
'\n' && stty echo
+fi
+
+for env in ASF_USERNAME GPG_PASSPHRASE GPG_KEY; do
+ if [ -z "${!env}" ]; then
+ echo "ERROR: $env must be set to run this script"
+ exit_with_usage
+ fi
+done
+
+export LC_ALL=C.UTF-8
+export LANG=C.UTF-8
+
+# Commit ref to checkout when building
+GIT_REF=${GIT_REF:-main}
+
+RELEASE_STAGING_LOCATION="https://dist.apache.org/repos/dist/dev/incubator/gravitino"
+RELEASE_LOCATION="https://dist.apache.org/repos/dist/release/incubator/gravitino"
+
+GPG="gpg -u $GPG_KEY --no-tty --batch --pinentry-mode loopback"
+NEXUS_ROOT=https://repository.apache.org/service/local/staging
+NEXUS_PROFILE=170bb01395e84a # Profile for Gravitino staging uploads
+BASE_DIR=$(pwd)
+
+init_java
+init_gradle
+
+if [[ "$1" == "finalize" ]]; then
+ if [[ -z "$PYPI_API_TOKEN" ]]; then
+ error 'The environment variable PYPI_API_TOKEN is not set. Exiting.'
+ fi
+
+ git config --global user.name "$GIT_NAME"
+ git config --global user.email "$GIT_EMAIL"
+
+ # Create the git tag for the new release
+ echo "Creating the git tag for the new release"
+ if check_for_tag "v$RELEASE_VERSION"; then
+ echo "v$RELEASE_VERSION already exists. Skip creating it."
+ else
+ rm -rf gravitino
+ git clone "https://$ASF_USERNAME:$ASF_PASSWORD@$ASF_GRAVITINO_REPO" -b main
+ cd gravitino
+ git tag "v$RELEASE_VERSION" "$RELEASE_TAG"
+ git push origin "v$RELEASE_VERSION"
+ cd ..
+ rm -rf gravitino
+ echo "git tag v$RELEASE_VERSION created"
+ fi
+
+ # download Gravitino Python binary from the dev directory and upload to PyPi.
+ echo "Uploading Gravitino to PyPi"
+ svn co --depth=empty "$RELEASE_STAGING_LOCATION/$RELEASE_TAG" svn-gravitino
+ cd svn-gravitino
+ PYGRAVITINO_VERSION=`echo "$RELEASE_VERSION" | sed -e "s/-/./" -e
"s/preview/dev/"`
+ svn update "apache_gravitino-$PYGRAVITINO_VERSION.tar.gz"
+ svn update "apache_gravitino-$PYGRAVITINO_VERSION.tar.gz.asc"
+ twine upload -u __token__ -p $PYPI_API_TOKEN \
+ --repository-url https://upload.pypi.org/legacy/ \
+ "apache_gravitino-$PYGRAVITINO_VERSION.tar.gz" \
+ "apache_gravitino-$PYGRAVITINO_VERSION.tar.gz.asc"
+ cd ..
+ rm -rf svn-gravitino
+ echo "Python Gravitino package uploaded"
+
+ # Moves the binaries from dev directory to release directory.
+ echo "Moving Gravitino binaries to the release directory"
+ svn mv --username "$ASF_USERNAME" --password "$ASF_PASSWORD" -m"Apache
Gravitino $RELEASE_VERSION" \
+ --no-auth-cache "$RELEASE_STAGING_LOCATION/$RELEASE_TAG"
"$RELEASE_LOCATION/$RELEASE_VERSION"
+ echo "Gravitino binaries moved"
+
+ # Update the KEYS file.
+ echo "Sync'ing KEYS"
+ svn co --depth=files "$RELEASE_LOCATION" svn-gravitino
+ curl "$RELEASE_STAGING_LOCATION/KEYS" > svn-gravitino/KEYS
+ (cd svn-gravitino && svn ci --username $ASF_USERNAME --password
"$ASF_PASSWORD" -m"Update KEYS")
+ echo "KEYS sync'ed"
+ rm -rf svn-gravitino
+
+ exit 0
+fi
+
+rm -rf gravitino
+git clone "$ASF_REPO"
+cd gravitino
+git checkout $GIT_REF
+git_hash=`git rev-parse --short HEAD`
+export GIT_HASH=$git_hash
+echo "Checked out Gravitino git hash $git_hash"
+
+if [ -z "$GRAVITINO_VERSION" ]; then
+ GRAVITINO_VERSION=$(cat gradle.properties | parse_version)
+fi
+
+if [ -z "$PYGRAVITINO_VERSION"]; then
+ PYGRAVITINO_VERSION=$(cat clients/client-python/setup.py | grep "version=" |
awk -F"\"" '{print $2}')
+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.
+LSOF=lsof
+if ! hash $LSOF 2>/dev/null; then
+ LSOF=/usr/sbin/lsof
+fi
+
+if [ -z "$GRAVITINO_PACKAGE_VERSION" ]; then
+ GRAVITINO_PACKAGE_VERSION="${GRAVITINO_VERSION}-$(date
+%Y_%m_%d_%H_%M)-${git_hash}"
+fi
+
+DEST_DIR_NAME="$GRAVITINO_PACKAGE_VERSION"
+
+git clean -d -f -x
+cd ..
+
+if [[ "$1" == "package" ]]; then
+ # Source and binary tarballs
+ echo "Packaging release source tarballs"
+ cp -r gravitino gravitino-$GRAVITINO_VERSION-src
+
+ rm -f gravitino-$GRAVITINO_VERSION-src/LICENSE.bin
+ rm -f gravitino-$GRAVITINO_VERSION-src/NOTICE.bin
+ rm -f gravitino-$GRAVITINO_VERSION-src/web/LICENSE.bin
+ rm -f gravitino-$GRAVITINO_VERSION-src/web/NOTICE.bin
+
+ tar cvzf gravitino-$GRAVITINO_VERSION-src.tar.gz --exclude
gravitino-$GRAVITINO_VERSION-src/.git gravitino-$GRAVITINO_VERSION-src
+ echo $GPG_PASSPHRASE | $GPG --passphrase-fd 0 --armour --output
gravitino-$GRAVITINO_VERSION-src.tar.gz.asc \
+ --detach-sig gravitino-$GRAVITINO_VERSION-src.tar.gz
+ shasum -a 512 gravitino-$GRAVITINO_VERSION-src.tar.gz >
gravitino-$GRAVITINO_VERSION-src.tar.gz.sha512
+ rm -rf gravitino-$GRAVITINO_VERSION-src
+
+ # Updated for each binary build
+ make_binary_release() {
+ echo "Building Gravitino binary dist"
+ cp -r gravitino gravitino-$GRAVITINO_VERSION-bin
+ cd gravitino-$GRAVITINO_VERSION-bin
+
+ echo "Creating distribution"
+
+ $GRADLE assembleDistribution -x test
+ $GRADLE :clients:client-python:distribution -x test
+ cd ..
+
+ echo "Copying and signing Gravitino server binary distribution"
+ cp
gravitino-$GRAVITINO_VERSION-bin/distribution/gravitino-$GRAVITINO_VERSION-bin.tar.gz
.
+ echo $GPG_PASSPHRASE | $GPG --passphrase-fd 0 --armour \
+ --output gravitino-$GRAVITINO_VERSION-bin.tar.gz.asc \
+ --detach-sig gravitino-$GRAVITINO_VERSION-bin.tar.gz
+ shasum -a 512 gravitino-$GRAVITINO_VERSION-bin.tar.gz >
gravitino-$GRAVITINO_VERSION-bin.tar.gz.sha512
+
+ echo "Copying and signing Gravitino Iceberg REST server binary
distribution"
+ cp
gravitino-$GRAVITINO_VERSION-bin/distribution/gravitino-iceberg-rest-server-$GRAVITINO_VERSION-bin.tar.gz
.
+ echo $GPG_PASSPHRASE | $GPG --passphrase-fd 0 --armour \
+ --output gravitino-iceberg-rest-server-$GRAVITINO_VERSION-bin.tar.gz.asc
\
+ --detach-sig gravitino-iceberg-rest-server-$GRAVITINO_VERSION-bin.tar.gz
+ shasum -a 512 gravitino-iceberg-rest-server-$GRAVITINO_VERSION-bin.tar.gz
> gravitino-iceberg-rest-server-$GRAVITINO_VERSION-bin.tar.gz.sha512
+
+ echo "Copying and signing Gravitino Trino connector binary distribution"
+ cp
gravitino-$GRAVITINO_VERSION-bin/distribution/gravitino-trino-connector-$GRAVITINO_VERSION.tar.gz
.
+ echo $GPG_PASSPHRASE | $GPG --passphrase-fd 0 --armour \
+ --output gravitino-trino-connector-$GRAVITINO_VERSION.tar.gz.asc \
+ --detach-sig gravitino-trino-connector-$GRAVITINO_VERSION.tar.gz
+ shasum -a 512 gravitino-trino-connector-$GRAVITINO_VERSION.tar.gz >
gravitino-trino-connector-$GRAVITINO_VERSION.tar.gz.sha512
+
+ echo "Copying and signing Gravitino Python client binary distribution"
+ cp
gravitino-$GRAVITINO_VERSION-bin/clients/client-python/dist/apache_gravitino-$PYGRAVITINO_VERSION.tar.gz
.
+ echo $GPG_PASSPHRASE | $GPG --passphrase-fd 0 --armour \
+ --output apache_gravitino-$PYGRAVITINO_VERSION.tar.gz.asc \
+ --detach-sig apache_gravitino-$PYGRAVITINO_VERSION.tar.gz
+ shasum -a 512 apache_gravitino-$PYGRAVITINO_VERSION.tar.gz >
apache_gravitino-$PYGRAVITINO_VERSION.tar.gz.sha512
+ }
+
+ make_binary_release
+ rm -rf gravitino-$GRAVITINO_VERSION-bin/
+
+ if ! is_dry_run; then
+ svn co --depth=empty $RELEASE_STAGING_LOCATION svn-gravitino
+ rm -rf "svn-gravitino/${DEST_DIR_NAME}"
+ mkdir -p "svn-gravitino/${DEST_DIR_NAME}"
+
+ echo "Copying release tarballs"
+ cp gravitino-* "svn-gravitino/${DEST_DIR_NAME}/"
+ svn add "svn-gravitino/${DEST_DIR_NAME}"
+
+ cd svn-gravitino
+ svn ci --username $ASF_USERNAME --password "$ASF_PASSWORD" -m"Apache
Gravitino $GRAVITINO_PACKAGE_VERSION" --no-auth-cache
+ cd ..
+ rm -rf svn-gravitino
+ fi
+
+ exit 0
+fi
+
+if [[ "$1" == "docs" ]]; then
+ # Documentation
+ cp -r gravitino gravitino-$GRAVITINO_VERSION-docs
+ cd gravitino-$GRAVITINO_VERSION-docs
+ echo "Building Gravitino Java and Python docs"
+ $GRADLE :clients:client-java:build -x test
+ $GRADLE :clients:client-python:pydoc
+ cd ..
+
+ cp -r
gravitino-$GRAVITINO_VERSION-docs/clients/client-java/build/docs/javadoc
gravitino-$GRAVITINO_VERSION-javadoc
+ cp -r gravitino-$GRAVITINO_VERSION-docs/clients/client-python/docs
gravitino-$PYGRAVITINO_VERSION-pydoc
+
+ rm -fr gravitino-$GRAVITINO_VERSION-docs
+fi
+
+if [[ "$1" == "publish-release" ]]; then
+ # Publish Gravitino to Maven release repo
+ echo "Publishing Gravitino checkout at '$GIT_REF' ($git_hash)"
+ echo "Publish version is $GRAVITINO_VERSION"
+
+ cp -r gravitino gravitino-$GRAVITINO_VERSION-publish
+ cd gravitino-$GRAVITINO_VERSION-publish
+
+ # Using Nexus API documented here:
+ #
https://support.sonatype.com/entries/39720203-Uploading-to-a-Staging-Repository-via-REST-API
+ if ! is_dry_run; then
+ echo "Creating Nexus staging repository"
+ repo_request="<promoteRequest><data><description>Apache Gravitino
$GRAVITINO_VERSION (commit $git_hash)</description></data></promoteRequest>"
+ out=$(curl -X POST -d "$repo_request" -u $ASF_USERNAME:$ASF_PASSWORD \
+ -H "Content-Type:application/xml" -v \
+ $NEXUS_ROOT/profiles/$NEXUS_PROFILE/start)
+ staged_repo_id=$(echo $out | sed -e
"s/.*\(orgapachegravitino-[0-9]\{4\}\).*/\1/")
+ echo "Created Nexus staging repository: $staged_repo_id"
+ fi
+
+ tmp_dir=$(mktemp -d gravitino-repo-XXXXX)
+ # the following recreates `readlink -f "$tmp_dir"` since readlink -f is
unsupported on MacOS
+ cd $tmp_dir
+ tmp_repo=$(pwd)
+ cd ..
+
+ $GRADLE clean
+ $GRADLE build -x test -PdefaultScalaVersion=2.12
+ $GRADLE build -x test -PdefaultScalaVersion=2.13
+
+ $GRADLE -Dmaven.repo.local=$tmp_repo publishToMavenLocal
-PdefaultScalaVersion=2.12
+ $GRADLE -Dmaven.repo.local=$tmp_repo publishToMavenLocal
-PdefaultScalaVersion=2.13
+
+ pushd $tmp_repo/org/apache/gravitino
+
+ # Remove any extra files generated during install
+ find . -type f |grep -v \.jar |grep -v \.pom |grep -v cyclonedx | xargs rm
+
+ echo "Creating hash and signature files"
+ # this must have .asc, .md5 and .sha1 - it really doesn't like anything else
there
+ for file in $(find . -type f)
+ do
+ echo $GPG_PASSPHRASE | $GPG --passphrase-fd 0 --output $file.asc \
+ --detach-sig --armour $file;
+ if [ $(command -v md5) ]; then
+ # Available on OS X; -q to keep only hash
+ md5 -q $file > $file.md5
+ else
+ # Available on Linux; cut to keep only hash
+ md5sum $file | cut -f1 -d' ' > $file.md5
+ fi
+ sha1sum $file | cut -f1 -d' ' > $file.sha1
+ done
+
+ if ! is_dry_run; then
+ nexus_upload=$NEXUS_ROOT/deployByRepositoryId/$staged_repo_id
+ echo "Uploading files to $nexus_upload"
+ for file in $(find . -type f)
+ do
+ # strip leading ./
+ file_short=$(echo $file | sed -e "s/\.\///")
+ dest_url="$nexus_upload/org/apache/gravitino/$file_short"
+ echo " Uploading $file_short"
+ curl --retry 3 --retry-all-errors -u $ASF_USERNAME:$ASF_PASSWORD
--upload-file $file_short $dest_url
+ done
+
+ echo "Closing nexus staging repository"
+
repo_request="<promoteRequest><data><stagedRepositoryId>$staged_repo_id</stagedRepositoryId><description>Apache
Gravitino $GRAVITINO_VERSION (commit
$git_hash)</description></data></promoteRequest>"
+ out=$(curl -X POST -d "$repo_request" -u $ASF_USERNAME:$ASF_PASSWORD \
+ -H "Content-Type:application/xml" -v \
+ $NEXUS_ROOT/profiles/$NEXUS_PROFILE/finish)
+ echo "Closed Nexus staging repository: $staged_repo_id"
+ fi
+
+ popd
+ rm -fr $tmp_repo
+ cd ..
+ rm -rf gravitino-$GRAVITINO_VERSION-publish
+fi
diff --git a/dev/release/release-tag.sh b/dev/release/release-tag.sh
new file mode 100755
index 000000000..a6ae3cea3
--- /dev/null
+++ b/dev/release/release-tag.sh
@@ -0,0 +1,116 @@
+#!/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.
+#
+
+# Referred from Apache Spark's release script
+# dev/create-release/release-tag.sh
+
+SELF=$(cd $(dirname $0) && pwd)
+. "$SELF/release-util.sh"
+
+function exit_with_usage {
+ local NAME=$(basename $0)
+ cat << EOF
+usage: $NAME
+Tags a Gravitino release on a particular branch.
+
+Inputs are specified with the following environment variables:
+ASF_USERNAME - Apache Username
+ASF_PASSWORD - Apache Password
+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
+RELEASE_VERSION - Version used in pom files for release
+RELEASE_TAG - Name of release tag
+NEXT_VERSION - Development version after release
+EOF
+ exit 1
+}
+
+set -e
+set -o pipefail
+
+if [[ $@ == *"help"* ]]; then
+ exit_with_usage
+fi
+
+if [[ -z "$ASF_PASSWORD" ]]; then
+ echo 'The environment variable ASF_PASSWORD is not set. Enter the password.'
+ echo
+ stty -echo && printf "ASF password: " && read ASF_PASSWORD && printf '\n' &&
stty echo
+fi
+
+for env in ASF_USERNAME ASF_PASSWORD RELEASE_VERSION RELEASE_TAG NEXT_VERSION
GIT_EMAIL GIT_NAME GIT_BRANCH; do
+ if [ -z "${!env}" ]; then
+ echo "$env must be set to run this script"
+ exit 1
+ fi
+done
+
+init_java
+init_gradle
+
+function uriencode { jq -nSRr --arg v "$1" '$v|@uri'; }
+
+declare -r ENCODED_ASF_PASSWORD=$(uriencode "$ASF_PASSWORD")
+
+rm -rf gravitino
+git clone "https://$ASF_USERNAME:$ENCODED_ASF_PASSWORD@$ASF_GRAVITINO_REPO" -b
$GIT_BRANCH
+cd gravitino
+
+git config user.name "$GIT_NAME"
+git config user.email "$GIT_EMAIL"
+
+PYGRAVITINO_RELEASE_VERSION="${RELEASE_VERSION/-incubating}"
+PYGRAVITINO_NEXT_VERSION=$(echo $NEXT_VERSION | sed
's/-incubating-SNAPSHOT/.dev0/')
+
+# Create release version for Java and Python
+sed -i".tmp1" 's/version = .*$/version = '"$RELEASE_VERSION"'/g'
gradle.properties
+sed -i".tmp2" 's/ version=.*$/
version="'"$PYGRAVITINO_RELEASE_VERSION"'",/g' clients/client-python/setup.py
+
+git commit -a -m "Preparing Gravitino release $RELEASE_TAG"
+echo "Creating tag $RELEASE_TAG at the head of $GIT_BRANCH"
+git tag $RELEASE_TAG
+
+# Create next version
+sed -i".tmp3" 's/version = .*$/version = '"$NEXT_VERSION"'/g' gradle.properties
+sed -i".tmp4" 's/ version=.*$/
version="'"$PYGRAVITINO_NEXT_VERSION"'",/g' clients/client-python/setup.py
+git commit -a -m "Preparing development version $NEXT_VERSION"
+
+if ! is_dry_run; then
+ # Push changes
+ git push origin $RELEASE_TAG
+ if [[ $RELEASE_VERSION != *"preview"* ]]; then
+ git push origin HEAD:$GIT_BRANCH
+ if git branch -r --contains tags/$RELEASE_TAG | grep origin; then
+ echo "Pushed $RELEASE_TAG to $GIT_BRANCH."
+ else
+ echo "Failed to push $RELEASE_TAG to $GIT_BRANCH. Please start over."
+ exit 1
+ fi
+ else
+ echo "It's preview release. We only push $RELEASE_TAG to remote."
+ fi
+
+ cd ..
+ rm -fr gravitino
+else
+ cd ..
+ mv gravitino gravitino-tag
+ echo "Clone with version changes and tag available as gravitino-tag in the
output directory."
+fi
diff --git a/dev/release/release-util.sh b/dev/release/release-util.sh
new file mode 100755
index 000000000..aa3913dad
--- /dev/null
+++ b/dev/release/release-util.sh
@@ -0,0 +1,229 @@
+#!/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.
+#
+
+# Referred from Apache Spark's release script
+# dev/create-release/release-util.sh
+
+DRY_RUN=${DRY_RUN:-0}
+GPG="gpg --no-tty --batch"
+ASF_REPO="https://github.com/apache/gravitino"
+ASF_REPO_WEBUI="https://raw.githubusercontent.com/apache/gravitino"
+ASF_GRAVITINO_REPO="gitbox.apache.org/repos/asf/gravitino.git"
+
+function error {
+ echo "$*"
+ exit 1
+}
+
+function read_config {
+ local PROMPT="$1"
+ local DEFAULT="$2"
+ local REPLY=
+
+ read -p "$PROMPT [$DEFAULT]: " REPLY
+ local RETVAL="${REPLY:-$DEFAULT}"
+ if [ -z "$RETVAL" ]; then
+ error "$PROMPT is must be provided."
+ fi
+ echo "$RETVAL"
+}
+
+function parse_version {
+ grep -e 'version = .*' | cut -d'=' -f2 | sed 's/^ *//;s/ *$//'
+}
+
+function run_silent {
+ local BANNER="$1"
+ local LOG_FILE="$2"
+ shift 2
+
+ echo "========================"
+ echo "= $BANNER"
+ echo "Command: $@"
+ echo "Log file: $LOG_FILE"
+
+ "$@" 1>"$LOG_FILE" 2>&1
+
+ local EC=$?
+ if [ $EC != 0 ]; then
+ echo "Command FAILED. Check full logs for details."
+ tail "$LOG_FILE"
+ exit $EC
+ fi
+}
+
+function fcreate_secure {
+ local FPATH="$1"
+ rm -f "$FPATH"
+ touch "$FPATH"
+ chmod 600 "$FPATH"
+}
+
+function check_for_tag {
+ curl -s --head --fail "$ASF_REPO/releases/tag/$1" > /dev/null
+}
+
+function get_release_info {
+ if [ -z "$GIT_BRANCH" ]; then
+ # If no branch is specified, found out the latest branch from the repo.
+ GIT_BRANCH=$(git ls-remote --heads "$ASF_REPO" |
+ grep -e "refs/heads/branch-.*" |
+ awk '{print $2}' |
+ sort -r |
+ head -n 1 |
+ cut -d/ -f3)
+ fi
+
+ export GIT_BRANCH=$(read_config "Branch" "$GIT_BRANCH")
+
+ # Find the current version for the branch.
+ local VERSION=$(curl -s "$ASF_REPO_WEBUI/$GIT_BRANCH/gradle.properties" |
+ parse_version)
+ echo "Current branch version is $VERSION."
+
+ if [[ ! $VERSION =~ .*-SNAPSHOT ]]; then
+ error "Not a SNAPSHOT version: $VERSION"
+ fi
+
+ NEXT_VERSION="$VERSION"
+ RELEASE_VERSION="${VERSION/-SNAPSHOT/}"
+ SHORT_VERSION=$(echo "$VERSION" | cut -d . -f 1-2)
+ local REV=$(echo "$RELEASE_VERSION" | cut -d . -f 3 | cut -d '-' -f 1)
+
+ # Find out what rc is being prepared.
+ # - If the current version is "x.y.0", then this is rc1 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 rc1 of the current version.
+ # - If it has not, we're building the next RC of the previous version.
+ local RC_COUNT
+ if [ $REV != 0 ]; then
+ local PREV_REL_REV=$((REV - 1))
+ local PREV_REL_TAG="v${SHORT_VERSION}.${PREV_REL_REV}-incubating"
+ if check_for_tag "$PREV_REL_TAG"; then
+ RC_COUNT=1
+ REV=$((REV + 1))
+ NEXT_VERSION="${SHORT_VERSION}.${REV}-incubating-SNAPSHOT"
+ else
+ RELEASE_VERSION="${SHORT_VERSION}.${PREV_REL_REV}-incubating"
+ RC_COUNT=$(git ls-remote --tags "$ASF_REPO" "v${RELEASE_VERSION}-rc*" |
wc -l)
+ RC_COUNT=$((RC_COUNT + 1))
+ fi
+ else
+ REV=$((REV + 1))
+ NEXT_VERSION="${SHORT_VERSION}.${REV}-incubating-SNAPSHOT"
+ RC_COUNT=1
+ fi
+
+ export NEXT_VERSION
+ export RELEASE_VERSION=$(read_config "Release" "$RELEASE_VERSION")
+
+ RC_COUNT=$(read_config "RC #" "$RC_COUNT")
+
+ # Check if the RC already exists, and if re-creating the RC, skip tag
creation.
+ RELEASE_TAG="v${RELEASE_VERSION}-rc${RC_COUNT}"
+ SKIP_TAG=0
+ if check_for_tag "$RELEASE_TAG"; then
+ read -p "$RELEASE_TAG already exists. Continue anyway [y/n]? " ANSWER
+ if [ "$ANSWER" != "y" ]; then
+ error "Exiting."
+ fi
+ SKIP_TAG=1
+ fi
+
+
+ export RELEASE_TAG
+
+ GIT_REF="$RELEASE_TAG"
+ if is_dry_run; then
+ echo "This is a dry run. Please confirm the ref that will be built for
testing."
+ if [[ $SKIP_TAG = 0 ]]; then
+ GIT_REF="$GIT_BRANCH"
+ fi
+ GIT_REF=$(read_config "Ref" "$GIT_REF")
+ fi
+ export GIT_REF
+ export GRAVITINO_PACKAGE_VERSION="$RELEASE_TAG"
+
+ # Gather some user information.
+ if [ -z "$ASF_USERNAME" ]; then
+ export ASF_USERNAME=$(read_config "ASF user" "$LOGNAME")
+ fi
+
+ if [ -z "$GIT_NAME" ]; then
+ GIT_NAME=$(git config user.name || echo "")
+ export GIT_NAME=$(read_config "Full name" "$GIT_NAME")
+ fi
+
+ export GIT_EMAIL="[email protected]"
+ export GPG_KEY=$(read_config "GPG key" "$GIT_EMAIL")
+
+ cat <<EOF
+================
+Release details:
+BRANCH: $GIT_BRANCH
+VERSION: $RELEASE_VERSION
+TAG: $RELEASE_TAG
+NEXT: $NEXT_VERSION
+
+ASF USER: $ASF_USERNAME
+GPG KEY: $GPG_KEY
+FULL NAME: $GIT_NAME
+E-MAIL: $GIT_EMAIL
+================
+EOF
+
+ read -p "Is this info correct [y/n]? " ANSWER
+ if [ "$ANSWER" != "y" ]; then
+ echo "Exiting."
+ exit 1
+ fi
+
+ if ! is_dry_run; then
+ if [ -z "$ASF_PASSWORD" ]; then
+ stty -echo && printf "ASF password: " && read ASF_PASSWORD && printf
'\n' && stty echo
+ fi
+ else
+ ASF_PASSWORD="***INVALID***"
+ fi
+
+ if [ -z "$GPG_PASSPHRASE" ]; then
+ stty -echo && printf "GPG passphrase: " && read GPG_PASSPHRASE && printf
'\n' && stty echo
+ fi
+
+ export ASF_PASSWORD
+ export GPG_PASSPHRASE
+}
+
+function is_dry_run {
+ [[ $DRY_RUN = 1 ]]
+}
+
+# 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)
+ export JAVA_VERSION
+}
+
+function init_gradle {
+ GRADLE="./gradlew"
+ export GRADLE
+}