Skip to content

Commit 44454b6

Browse files
author
Marcelo Vanzin
committed
[SPARK-24372][build] Add scripts to help with preparing releases.
The "do-release.sh" script asks questions about the RC being prepared, trying to find out as much as possible automatically, and then executes the existing scripts with proper arguments to prepare the release. This script was used to prepare the 2.3.1 release candidates, so was tested in that context. The docker version runs that same script inside a docker image especially crafted for building Spark releases. That image is based on the work by Felix C. linked in the bug. At this point is has been only midly tested. I also added a template for the vote e-mail, with placeholders for things that need to be replaced, although there is no automation around that for the moment. It shouldn't be hard to hook up certain things like version and tags to this, or to figure out certain things like the repo URL from the output of the release scripts.
1 parent a53ea70 commit 44454b6

File tree

5 files changed

+501
-0
lines changed

5 files changed

+501
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/usr/bin/env bash
2+
3+
#
4+
# Licensed to the Apache Software Foundation (ASF) under one or more
5+
# contributor license agreements. See the NOTICE file distributed with
6+
# this work for additional information regarding copyright ownership.
7+
# The ASF licenses this file to You under the Apache License, Version 2.0
8+
# (the "License"); you may not use this file except in compliance with
9+
# the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
#
19+
20+
set -e
21+
SELF=$(cd $(dirname $0) && pwd)
22+
. "$SELF/release-util.sh"
23+
24+
WORKDIR=
25+
IMGTAG=latest
26+
while getopts "d:n:t:" opt; do
27+
case $opt in
28+
d) WORKDIR="$OPTARG" ;;
29+
n) DRY_RUN=1 ;;
30+
t) IMGTAG="$OPTARG" ;;
31+
?) error "Invalid option: $OPTARG" ;;
32+
esac
33+
done
34+
35+
if [ -z "$WORKDIR" ] || [ ! -d "$WORKDIR" ]; then
36+
error "Work directory (-d) must be defined and exist."
37+
fi
38+
39+
if [ -d "$WORKDIR/output" ]; then
40+
read -p "Output directory already exists. Overwrite and continue? [y/n] " ANSWER
41+
if [ "$ANSWER" != "y" ]; then
42+
error "Exiting."
43+
fi
44+
fi
45+
46+
cd "$WORKDIR"
47+
rm -rf "$WORKDIR/output"
48+
mkdir "$WORKDIR/output"
49+
50+
get_release_info
51+
52+
# Place all RM scripts and necessary data in a local directory that must be defined in the command
53+
# line. This directory is mounted into the image.
54+
for f in "$SELF"/*; do
55+
if [ -f "$f" ]; then
56+
cp "$f" "$WORKDIR"
57+
fi
58+
done
59+
GPG_KEY_FILE="$WORKDIR/gpg.key"
60+
fcreate_secure "$GPG_KEY_FILE"
61+
$GPG --export-secret-key --armor "$GPG_KEY" > "$GPG_KEY_FILE"
62+
63+
run_silent "Building spark-rm image with tag $IMGTAG..." "docker-build.log" \
64+
docker build -t "spark-rm:$IMGTAG" --build-arg UID=$UID "$SELF/spark-rm"
65+
66+
# Write the release information to a file with environment variables to be used when running the
67+
# image.
68+
ENVFILE="$WORKDIR/env.list"
69+
fcreate_secure "$ENVFILE"
70+
71+
function cleanup {
72+
rm -f "$ENVFILE"
73+
rm -f "$GPG_KEY_FILE"
74+
}
75+
76+
trap cleanup EXIT
77+
78+
cat > $ENVFILE <<EOF
79+
DRY_RUN=$DRY_RUN
80+
SKIP_TAG=$SKIP_TAG
81+
RUNNING_IN_DOCKER=1
82+
GIT_BRANCH=$GIT_BRANCH
83+
NEXT_VERSION=$NEXT_VERSION
84+
RELEASE_VERSION=$RELEASE_VERSION
85+
RELEASE_TAG=$RELEASE_TAG
86+
GIT_REF=$GIT_REF
87+
SPARK_PACKAGE_VERSION=$SPARK_PACKAGE_VERSION
88+
ASF_USERNAME=$ASF_USERNAME
89+
GIT_NAME=$GIT_NAME
90+
GIT_EMAIL=$GIT_EMAIL
91+
GPG_KEY=$GPG_KEY
92+
ASF_PASSWORD=$ASF_PASSWORD
93+
GPG_PASSPHRASE=$GPG_PASSPHRASE
94+
EOF
95+
96+
echo "Building $RELEASE_TAG; output will be at $WORKDIR/output"
97+
docker run \
98+
--env-file "$ENVFILE" \
99+
--volume "$WORKDIR":/opt/spark-rm \
100+
"spark-rm:$IMGTAG"

dev/create-release/do-release.sh

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env bash
2+
3+
#
4+
# Licensed to the Apache Software Foundation (ASF) under one or more
5+
# contributor license agreements. See the NOTICE file distributed with
6+
# this work for additional information regarding copyright ownership.
7+
# The ASF licenses this file to You under the Apache License, Version 2.0
8+
# (the "License"); you may not use this file except in compliance with
9+
# the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
#
19+
20+
SELF=$(cd $(dirname $0) && pwd)
21+
. "$SELF/release-util.sh"
22+
23+
while getopts "bn" opt; do
24+
case $opt in
25+
b) GIT_BRANCH=$OPTARG ;;
26+
n) DRY_RUN=1 ;;
27+
?) error "Invalid option: $OPTARG" ;;
28+
esac
29+
done
30+
31+
set -e
32+
33+
if [ "$RUNNING_IN_DOCKER" = "1" ]; then
34+
# Inside docker, need to import the GPG key stored in the current directory.
35+
echo $GPG_PASSPHRASE | $GPG --passphrase-fd 0 "$SELF/gpg.key"
36+
else
37+
# Outside docker, need to ask for information about the release.
38+
get_release_info
39+
fi
40+
41+
if [ $SKIP_TAG = 0 ]; then
42+
run_silent "Creating release tag $RELEASE_TAG..." "tag.log" \
43+
"$SELF/release-tag.sh"
44+
else
45+
echo "Skipping tag creation for $RELEASE_TAG."
46+
fi
47+
48+
run_silent "Building Spark..." "build.log" \
49+
"$SELF/release-build.sh" package
50+
run_silent "Building documentation..." "docs.log" \
51+
"$SELF/release-build.sh" docs
52+
run_silent "Publishing release" "publish.log" \
53+
"$SELF/release-build.sh" publish-release

dev/create-release/release-util.sh

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
#!/usr/bin/env bash
2+
3+
#
4+
# Licensed to the Apache Software Foundation (ASF) under one or more
5+
# contributor license agreements. See the NOTICE file distributed with
6+
# this work for additional information regarding copyright ownership.
7+
# The ASF licenses this file to You under the Apache License, Version 2.0
8+
# (the "License"); you may not use this file except in compliance with
9+
# the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
#
19+
20+
DRY_RUN=${DRY_RUN:-0}
21+
GPG="gpg --no-tty --batch"
22+
ASF_REPO="https://git-wip-us.apache.org/repos/asf/spark.git"
23+
ASF_REPO_WEBUI="https://git-wip-us.apache.org/repos/asf?p=spark.git"
24+
25+
function error {
26+
echo "$*"
27+
exit 1
28+
}
29+
30+
function read_config {
31+
local PROMPT="$1"
32+
local DEFAULT="$2"
33+
local REPLY=
34+
35+
read -p "$PROMPT [$DEFAULT]: " REPLY
36+
local RETVAL="${REPLY:-$DEFAULT}"
37+
if [ -z "$RETVAL" ]; then
38+
error "$PROMPT is must be provided."
39+
fi
40+
echo "$RETVAL"
41+
}
42+
43+
function parse_version {
44+
grep -e '<version>.*</version>' | \
45+
head -n 2 | tail -n 1 | cut -d'>' -f2 | cut -d '<' -f1
46+
}
47+
48+
function run_silent {
49+
local BANNER="$1"
50+
shift
51+
local LOG_FILE="$1"
52+
shift
53+
54+
echo "=================================="
55+
echo "= $BANNER"
56+
echo "Command: $@"
57+
echo "Log file: $LOG_FILE"
58+
59+
if [ $DRY_RUN = 0 ]; then
60+
"$@" 1>"$LOG_FILE" 2>&1
61+
else
62+
echo "$@"
63+
touch "$LOG_FILE"
64+
fi
65+
66+
local EC=$?
67+
if [ $EC != 0 ]; then
68+
echo "Command FAILED. Check full logs for details."
69+
tail "$LOG_FILE"
70+
return $EC
71+
fi
72+
}
73+
74+
function fcreate_secure {
75+
local FPATH="$1"
76+
rm -f "$FPATH"
77+
touch "$FPATH"
78+
chmod 600 "$FPATH"
79+
}
80+
81+
function check_for_tag {
82+
curl -s --head --fail "$ASF_REPO_WEBUI;a=commit;h=$1" >/dev/null
83+
}
84+
85+
function get_release_info {
86+
if [ -z "$GIT_BRANCH" ]; then
87+
# If no branch is specified, found out the latest branch from the repo.
88+
GIT_BRANCH=$(git ls-remote --heads "$ASF_REPO" |
89+
grep -v refs/heads/master |
90+
awk '{print $2}' |
91+
sort -r |
92+
head -n 1 |
93+
cut -d/ -f3)
94+
fi
95+
96+
export GIT_BRANCH=$(read_config "Branch" "$GIT_BRANCH")
97+
98+
# Find the current version for the branch.
99+
local VERSION=$(curl -s "$ASF_REPO_WEBUI;a=blob_plain;f=pom.xml;hb=refs/heads/$GIT_BRANCH" |
100+
parse_version)
101+
echo "Current branch version is $VERSION."
102+
103+
if [[ ! $VERSION =~ .*-SNAPSHOT ]]; then
104+
error "Not a SNAPSHOT version: $VERSION"
105+
fi
106+
107+
NEXT_VERSION="$VERSION"
108+
RELEASE_VERSION="${VERSION/-SNAPSHOT/}"
109+
SHORT_VERSION=$(echo "$VERSION" | cut -d . -f 1-2)
110+
local REV=$(echo "$VERSION" | cut -d . -f 3)
111+
112+
# Find out what rc is being prepared.
113+
# - If the current version is "x.y.0", then this is rc1 of the "x.y.0" release.
114+
# - If not, need to check whether the previous version has been already released or not.
115+
# - If it has, then we're building rc1 of the current version.
116+
# - If it has not, we're building the next RC of the previous version.
117+
local RC_COUNT
118+
if [ $REV != 0 ]; then
119+
local PREV_REL_REV=$((REV - 1))
120+
local PREV_REL_TAG="v${SHORT_VERSION}.${PREV_REL_REV}"
121+
if check_for_tag "$PREV_REL_TAG"; then
122+
RC_COUNT=1
123+
REV=$((REV + 1))
124+
NEXT_VERSION="${SHORT_VERSION}-${REV}-SNAPSHOT"
125+
else
126+
RELEASE_VERSION="${SHORT_VERSION}.${PREV_REL_REV}"
127+
RC_COUNT=$(git ls-remote --tags "$ASF_REPO" "v${RELEASE_VERSION}-rc*" | wc -l)
128+
RC_COUNT=$((RC_COUNT + 1))
129+
fi
130+
else
131+
REV=$((REV + 1))
132+
NEXT_VERSION="${SHORT_VERSION}-${REV}-SNAPSHOT"
133+
RC_COUNT=1
134+
fi
135+
136+
export NEXT_VERSION
137+
export RELEASE_VERSION=$(read_config "Release" "$RELEASE_VERSION")
138+
139+
RC_COUNT=$(read_config "RC #" "$RC_COUNT")
140+
141+
# Check if the RC already exists, and if re-creating the RC, skip tag creation.
142+
RELEASE_TAG="v${RELEASE_VERSION}-rc${RC_COUNT}"
143+
SKIP_TAG=0
144+
if check_for_tag "RELEASE_TAG"; then
145+
read -p "$RELEASE_TAG already exists. Continue anyway [y/n]? " ANSWER
146+
if [ "$ANSWER" != "y" ]; then
147+
error "Exiting."
148+
fi
149+
SKIP_TAG=1
150+
fi
151+
152+
export RELEASE_TAG
153+
export GIT_REF="$RELEASE_TAG"
154+
export SPARK_PACKAGE_VERSION="$RELEASE_TAG"
155+
156+
# Gather some user information.
157+
export ASF_USERNAME=$(read_config "ASF user" "$LOGNAME")
158+
159+
GIT_NAME=$(git config user.name)
160+
export GIT_NAME=$(read_config "Full name" "$GIT_NAME")
161+
162+
export GIT_EMAIL="$ASF_USERNAME@apache.org"
163+
export GPG_KEY=$(read_config "GPG key" "$GIT_EMAIL")
164+
165+
cat <<EOF
166+
================
167+
Release details:
168+
BRANCH: $GIT_BRANCH
169+
VERSION: $RELEASE_VERSION
170+
TAG: $RELEASE_TAG
171+
NEXT: $NEXT_VERSION
172+
173+
ASF USER: $ASF_USERNAME
174+
GPG KEY: $GPG_KEY
175+
FULL NAME: $GIT_NAME
176+
E-MAIL: $GIT_EMAIL
177+
================
178+
EOF
179+
180+
read -p "Is this info correct [y/n]? " ANSWER
181+
if [ "$ANSWER" != "y" ]; then
182+
echo "Exiting."
183+
exit 1
184+
fi
185+
186+
if [ -z "$ASF_PASSWORD" ]; then
187+
stty -echo && printf "ASF password: " && read ASF_PASSWORD && printf '\n' && stty echo
188+
export ASF_PASSWORD
189+
fi
190+
191+
if [ -z "$GPG_PASSPHRASE" ]; then
192+
stty -echo && printf "GPG passphrase: " && read GPG_PASSPHRASE && printf '\n' && stty echo
193+
export GPG_PASSPHRASE
194+
fi
195+
}

0 commit comments

Comments
 (0)