blob: e2daa4ddc2838037851a64e4e9ffa20d817f8da8 [file] [log] [blame]
#!/bin/bash
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Creates and sets up the actual release artifacts into dev
# See https://cwiki.apache.org/confluence/display/METRON/Release+Process
set -eo pipefail
# define constants
# Git repos
# To add a new submodule, add the repo name, upstream Git repo, and update the getrepo() selection function.
# if versioning of the submodule isn't x.y.z format, retrieval of the git tag must also be adjusted.
METRON_REPO_NAME="metron"
BRO_PLUGIN_REPO_NAME="metron-bro-plugin-kafka"
METRON_UPSTREAM="https://gitbox.apache.org/repos/asf/${METRON_REPO_NAME}.git"
BRO_PLUGIN_UPSTREAM="https://gitbox.apache.org/repos/asf/${BRO_PLUGIN_REPO_NAME}.git"
DEV_REPO="https://dist.apache.org/repos/dist/dev/metron"
RELEASE_REPO=" https://dist.apache.org/repos/dist/release/metron"
PLUGIN_GIT_REPO="https://gitbox.apache.org/repos/asf/${BRO_PLUGIN_REPO_NAME}.git"
RC_PREFIX=rc
UPPER_RC_PREFIX="$(tr '[:lower:]' '[:upper:]' <<< ${RC_PREFIX})"
TAG_POSTFIX="-release"
CONFIG_FILE=~/.metron-prepare-release-candidate
# does a config file already exist?
if [ -f $CONFIG_FILE ]; then
. $CONFIG_FILE
echo " ...using settings from $CONFIG_FILE"
fi
# apache id of committer (you)
if [ -z "${APACHE_NAME}" ]; then
read -p " your apache userid [${APACHE_NAME}]: " INPUT
[ -n "$INPUT" ] && APACHE_NAME=$INPUT
# write setting to config file
echo "APACHE_NAME=$APACHE_NAME" >> $CONFIG_FILE
fi
# apache email addr of committer (you)
if [ -z "${APACHE_EMAIL}" ]; then
APACHE_EMAIL=${APACHE_NAME}@apache.org
read -p " your apache email [${APACHE_EMAIL}]: " INPUT
[ -n "$INPUT" ] && APACHE_EMAIL=$INPUT
# write setting to config file, so it is not needed next time
echo "APACHE_EMAIL=$APACHE_EMAIL" >> $CONFIG_FILE
fi
# which repo? metron or metron-bro-plugin-kafka
getrepo() {
echo " [1] ${METRON_REPO_NAME}"
echo " [2] ${BRO_PLUGIN_REPO_NAME}"
read -p " which repo? [1]: " INPUT
case "${INPUT}" in
[Bb][Rr][Oo]|[Mm][Ee][Tt][Rr][Oo][Nn]-[Bb][Rr][Oo]-[Pp][Ll][Uu][Gg][Ii][Nn]-[Kk][Aa][Ff][Kk][Aa]|*metron-bro-plugin-kafka\.git|2)
INPUT="${BRO_PLUGIN_UPSTREAM}" ;;
[Mm][Ee][Tt][Rr][Oo][Nn]|*metron\.git|1|'')
INPUT="${METRON_UPSTREAM}" ;;
*)
echo "Invalid repo, provided \"${INPUT}\". Please choose between ${METRON_REPO_NAME} or ${BRO_PLUGIN_REPO_NAME}"
return 1
;;
esac
[ -n "$INPUT" ] && UPSTREAM=$INPUT
return 0
}
until getrepo; do :; done
CHOSEN_REPO=$(basename ${UPSTREAM%%.git})
# Need the capitalized version of the repos some naming
CAPITAL_REPO="$(tr '[:lower:]' '[:upper:]' <<< ${CHOSEN_REPO:0:1})${CHOSEN_REPO:1}"
getcurrentversion() {
# currently released version. Used for CHANGES file
read -p " current version: " CURRENT_VERSION
if ! [[ "${CURRENT_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
printf " Please enter a valid x.y.z version\n"
return 1
fi
return 0
}
until getcurrentversion; do : ; done
# version that we're building an RC for
getversion() {
read -p " version being built: " VERSION
if ! [[ "${VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
printf " Please enter a valid x.y.z version\n"
return 1
fi
return 0
}
until getversion; do : ; done
# RC number we're building
getrcnum() {
read -p " release candidate number: " RC_NUM
if [[ "${RC_NUM}" =~ ^[0-9]+$ ]]; then
RC="${RC_PREFIX}${RC_NUM}"
return 0
else
printf " Please enter an integer\n"
return 1
fi
}
until getrcnum; do : ; done
# define default values
TMPDIR="$HOME/tmp"
WORKDIR="$TMPDIR/${CHOSEN_REPO}-${VERSION}"
# warn the user if the working directory exists
if [ -d "$WORKDIR" ]; then
read -p " directory exists [$WORKDIR]. overwrite existing directory? [y/n] " -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
# Clear out the existing work directory
rm -rf "$WORKDIR"
mkdir "$WORKDIR"
getbaserev() {
read -p " base revision branch or hash for release candidate [master]: " GIT_REF
GIT_REF=${GIT_REF:-master}
# check to see if we were given branch
git rev-parse -q --verify ${GIT_REF} >> /dev/null
if [[ $? -ne 0 ]]; then
# check to see if we were given hash
git cat-file -e ${GIT_REF}
if [[ $? -ne 0 ]]; then
"Unable to find git revision"
return 1
fi
fi
return 0
}
until getbaserev; do : ; done
# Signing key
getkey() {
read -s -p " signing key id in 8-byte format (e.g. BADDCAFEDEADBEEF): " SIGNING_KEY
printf "\n"
if ! [[ "${SIGNING_KEY}" =~ ^[A-F0-9]{16}$ ]]; then
printf " Please enter a valid signing key\n"
return 1
fi
return 0
}
until getkey; do : ; done
# Determine if this is a practice run or not.
getpractice() {
read -p " do a live run (push to remote repositories?) [y/n] " INPUT
case "${INPUT}" in
y)
PRACTICE_RUN=false
return 0 ;;
n)
PRACTICE_RUN=true
return 0 ;;
*)
printf "Please enter 'y' or 'n'\n"
return 1
;;
esac
}
until getpractice; do : ; done
## Prepare everything for building the release artifacts
# Fetch the SVN repos. Always needed regardless of what's being released.
fetch_svn_repo () {
local SVN_REPO=$1
local SVN_DIR=$2
mkdir "$SVN_DIR"
cd "$SVN_DIR"
printf "Checking out repo: %s\n" "$SVN_REPO" "$(basename $SVN_DIR)"
svn co -q $SVN_REPO
cd "$(dirname $WORKDIR)"
}
fetch_svn_repo "$DEV_REPO" "$WORKDIR/dev"
fetch_svn_repo "$RELEASE_REPO" "$WORKDIR/release"
# Fetch the appropriate Git repo. Only need what we're releasing
GIT_DIR="$WORKDIR/${CHOSEN_REPO}"
printf "Checking out git repo: %s\n" "$UPSTREAM"
git clone $UPSTREAM "${GIT_DIR}"
cd "${GIT_DIR}"
git fetch --tags
# Create the release branch in the Git repo
printf "Creating branch: %s_%s\n" "${CAPITAL_REPO}" "$VERSION"
printf "Using git rev: %s\n" ${GIT_REF}
cd "$GIT_DIR"
git checkout ${GIT_REF}
git checkout -b "${CAPITAL_REPO}_${VERSION}"
if [ "${PRACTICE_RUN}" = true ]; then
printf "This is a practice run. Not running <git push --set-upstream origin %s_%s>\n" "${CAPITAL_REPO}" "$VERSION"
else
printf "Pushing branch %s_%s\n" "${CAPITAL_REPO}" "$VERSION"
git push --set-upstream origin "${CAPITAL_REPO}_${VERSION}"
fi
# Create directory for release artifacts
if [ "${CHOSEN_REPO}" = "${METRON_REPO_NAME}" ]; then
ART_DIR="$WORKDIR/dev/metron/${VERSION}-${UPPER_RC_PREFIX}${RC_NUM}"
else
# We're using a sub module, so put it in it's own directory.
ART_DIR="$WORKDIR/dev/metron/${CHOSEN_REPO}/${VERSION}-${UPPER_RC_PREFIX}${RC_NUM}"
fi
mkdir -p "$ART_DIR"
# Setup various parameters we need for the release artifacts
if [ "${CHOSEN_REPO}" = "${METRON_REPO_NAME}" ]; then
CORE_PREFIX="apache-metron_"
ARTIFACT_PREFIX="${CORE_PREFIX}"
TAG_VERSION="${CURRENT_VERSION}"
TAG="${CORE_PREFIX}${TAG_VERSION}${TAG_POSTFIX}"
elif [ "${CHOSEN_REPO}" = "${BRO_PLUGIN_REPO_NAME}" ]; then
BRO_PLUGIN_PREFIX="apache-metron-bro-plugin-kafka_"
ARTIFACT_PREFIX="${BRO_PLUGIN_PREFIX}"
TAG_VERSION="${CURRENT_VERSION}"
TAG="${BRO_PLUGIN_PREFIX}${TAG_VERSION}${TAG_POSTFIX}"
else
# If we ever add new modules, add them as needed.
printf "Unrecognized module: %s\n" "${CHOSEN_REPO}"
exit 1
fi
ARTIFACT="${ARTIFACT_PREFIX}${VERSION}-${RC}"
## Do the work of actually creating the release artifacts
printf "Creating tentative git tag <%s%s-%s>. Do not push this tag until RC is ready for community review.\n" "${TAG_PREFIX}" "$VERSION" "$RC"
cd "$GIT_DIR"
git checkout "${CAPITAL_REPO}_${VERSION}"
# The branch only exists if this is not a practice run
if [ "${PRACTICE_RUN}" = false ]; then
printf "Pulling latest state of branch\n"
git pull
fi
git tag "${ARTIFACT}"
# Create the rc tarball from the tag
printf "Creating the RC tarball for tag %s\n" "$ARTIFACT"
git archive "--prefix=${ARTIFACT}/" "${ARTIFACT}" | gzip > "${ARTIFACT}.tar.gz"
# Create signing hash files
printf "Creating the SHA hash files\n"
gpg --print-md SHA512 ${ARTIFACT}.tar.gz > ${ARTIFACT}.tar.gz.sha512
gpg --print-md SHA256 ${ARTIFACT}.tar.gz > ${ARTIFACT}.tar.gz.sha256
# Sign the release tarball
printf "Signing the release tarball\n"
gpg -u ${SIGNING_KEY} --armor --output ${ARTIFACT}.tar.gz.asc --detach-sig ${ARTIFACT}.tar.gz
if [[ $? -ne 0 ]]; then
# gpg will print out an error on its own
exit 1
fi
# Setup the release artifacts
printf "Copying release artifacts\n"
mv "${GIT_DIR}/${ARTIFACT}.tar.gz" "$ART_DIR"
mv "${ARTIFACT}.tar.gz.sha512" "$ART_DIR"
mv "${ARTIFACT}.tar.gz.sha256" "$ART_DIR"
mv "${ARTIFACT}.tar.gz.asc" "$ART_DIR"
# Create the CHANGES file
# Do this by getting all commits in current branch that aren't in current release. Filter out any merges by making sure lines start with blankspace followed by "METRON"
# i.e. make sure the lines starts with a ticket number to avoid merge commits into feature branches
printf "Creating CHANGES file\n"
git log "${CAPITAL_REPO}_${VERSION}" "^tags/${TAG}" --no-merges | grep -E "^[[:blank:]]+METRON" | sed 's/\[//g' | sed 's/\]//g' > "${ART_DIR}/CHANGES"
if [[ $? -ne 0 ]]; then
"Error creating CHANGES file"
exit 1
fi
printf "Extracting LICENSE and NOTICE from tarball\n" # Only pull from core
cd ${ART_DIR}
if [ "${CHOSEN_REPO}" = "${BRO_PLUGIN_REPO_NAME}" ]; then
# Bro's convention for the LICENSE is different, so the file is called COPYING
tar --strip-components=1 -zxvf "${ARTIFACT}.tar.gz" "${ARTIFACT}/COPYING"
else
tar --strip-components=1 -zxvf "${ARTIFACT}.tar.gz" "${ARTIFACT}/LICENSE"
fi
# TODO figure out what to do for bro repo here. The KEYS file only needs to live in the /dist root, rather than in each sub repo.
# Should we have a separate process for adding to the KEYS file without doing a Metron release?
tar --strip-components=1 -zxvf "${ARTIFACT}.tar.gz" "${ARTIFACT}/NOTICE"
# Add the directory and commit to subversion
COMMIT_DIR=$(basename ${ART_DIR})
if [ "${PRACTICE_RUN}" = true ]; then
printf "This is a practice run. Not running the following commands:\n"
printf "<svn add %s>\n" ${COMMIT_DIR}
printf "<svn commit -m \"Adding artifacts for %s %s\">\n" "${CHOSEN_REPO}" "${COMMIT_DIR}"
else
printf "Adding artifacts for Metron ${VERSION}-${UPPER_RC_PREFIX}${RC_NUM} to dev SVN\n"
# Metron goes in the root of the dir, submodules go in folder
if [ "${CHOSEN_REPO}" = "${METRON_REPO_NAME}" ]; then
cd "$WORKDIR/dev/metron/"
else
cd "$WORKDIR/dev/metron/${CHOSEN_REPO}"
fi
svn add ${COMMIT_DIR}
svn commit -m "Adding artifacts for ${CHOSEN_REPO} ${COMMIT_DIR}"
fi