pekko/project/scripts/release
Roland Kuhn 0acf03f528 update warnOldDocs.js and symlink for release
This will also git commit before and after the upload of the docs, so as
to make sure that changes to warnOldDocs.js are recoverable.
2016-03-08 19:46:46 +01:00

387 lines
12 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Release script for Akka.
#
# ATTENTION: This script involves calling `git clean -fxd` which will remove all untracked
# files from your working directory (including IDE settings).
#
# Prerequisites and Installation Instructions
#
# 1) You must be able to sign the artifacts with PGP
#
# 1.1) If you don't have PGP and a PGP key
# On OS X from othe command line:
# shell> brew install gnupg
# shell> gpg --gen-key
#
# Default values for the key type and 2048 bits is OK.
# Make sure to use the email address that you will use later to register
# with Sonatype.
#
# 1.2) Check that signing works
# From inside sbt do the following
# sbt> publishLocalSigned
# It should should ask you for your pass phrase, and create .asc files for
# all artifacts
#
# 1.3) Publish your key to a server that Sonatype use
# From the command line:
# shell> gpg --keyserver hkp://pool.sks-keyservers.net/ --send-keys <your key id>
# To find out your key id do this from the command line:
# shell> gpg --list-keys
# pub 2048/<your key id> ...
# You can verify the existence of your key here, if you don't trust your tool:
# https://sks-keyservers.net/i/#extract
#
# 2) You must have publishing rights to oss.sonatype.org
#
# 2.1) Register with oss.sonatype.org by only following the instructions under
# sign up here https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide
# Use the same email address as you used for the pgp key.
#
# 2.2) Ask Jonas who is the original creator of this ticket https://issues.sonatype.org/browse/OSSRH-3097
# to add a comment that says that your username (not your full name) should
# have publish access to that project. There is manual administration of
# the ticket at Sonatype, so it could take a little while.
#
# 2.3) Add your credentials to sbt by adding a global.sbt file in your sbt home
# directory containing the following.
# credentials += Credentials("Sonatype Nexus Repository Manager",
# "oss.sonatype.org",
# "<your username>",
# "<your password>")
#
# 3) You must have access to repo.akka.io
#
# 3.1) Ask someone in the team for login information for the akkarepo user.
#
# 3.2) Install your public ssh key to avoid typing in your password.
# From the command line:
# shell> cat ~/.ssh/id_rsa.pub | ssh akkarepo@repo.akka.io "cat >> ~/.ssh/authorized_keys"
#
# 4) You must have upload access to S3 bucket "downloads.typesafe.com"
#
# 4.1) Ask Akka team member for the AWS access key for 'akka.team' user.
#
# 4.2) Add your credentials to sbt by adding this to your global.sbt file
# credentials += Credentials("Amazon S3",
# "downloads.typesafe.com.s3.amazonaws.com",
# "<Access Key Id>",
# "<Secret Access Key>")
#
# 5) Have access to github.com/akka/akka. This should be a given.
#
# Now you should be all set to run the script
#
# Run the script in two stages.
# First a dry run:
# shell> project/scripts/release <version>
# And if all goes well a real run:
# shell> project/scripts/release --real-run <version>
#
# The artifacts published to oss.sonatype.org needs to be released by following the
# instructions under release here
# https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide
# defaults
declare -r default_server="akkarepo@repo.akka.io"
declare -r default_path="www"
# settings
declare -r release_dir="target/release"
declare release_server=${default_server}
declare release_path=${default_path}
# flags
unset run_tests dry_run no_mima no_revert
# dry-run is the default
dry_run=true
# get the source location for this script; handles symlinks
function get_script_path {
local source="${BASH_SOURCE[0]}"
while [ -h "${source}" ] ; do
source="$(readlink "${source}")";
done
echo ${source}
}
# path, name, and dir for this script
declare -r script_path=$(get_script_path)
declare -r script_name=$(basename "${script_path}")
declare -r script_dir="$(cd -P "$(dirname "${script_path}")" && pwd)"
# print usage info
function usage {
cat <<EOM
Dry run is be default.
Usage: ${script_name} [options] VERSION
-h | --help Print this usage message
-t | --run-tests Run all tests before releasing
-s | --server SERVER Set the release server (default ${default_server})
-p | --path PATH Set the path on the release server (default ${default_path})
-e | --real-run Build everything and push the release
-m | --no-mima Skip binary compatibility check in dry-run
-r | --no-revert On dry-run don't revert git commits and tags
EOM
}
# echo a log message
function echolog {
echo "[${script_name}] $@"
}
# echo an error message
function echoerr {
echo "[${script_name}] $@" 1>&2
}
# echo a dry run log message
function echodry {
echolog "(dry run) $@"
}
# fail the script with an error message
function fail {
echoerr "$@"
exit 1
}
# process options and set flags
while true; do
case "$1" in
-h | --help ) usage; exit 1 ;;
-t | --run-tests ) run_tests=true; shift ;;
-s | --server ) release_server=$2; shift 2 ;;
-p | --path ) release_path=$2; shift 2 ;;
-e | --real-run) unset dry_run; shift ;;
-m | --no-mima) no_mima=true; shift ;;
-r | --no-revert) no_revert=true; shift ;;
* ) break ;;
esac
done
if [ $# != "1" ]; then
usage
fail "A release version must be specified"
fi
declare -r version=$1
declare -r publish_path="${release_server}:${release_path}"
[[ `java -version 2>&1 | grep -E "java version|openjdk version" | cut -d ' ' -f3 | cut -d '.' -f2` -eq 8 ]] || fail "Java version is not 1.8"
# check for a git command
type -P git &> /dev/null || fail "git command not found"
# check for an sbt command
type -P sbt &> /dev/null || fail "sbt command not found"
# check for an rsync command
type -P rsync &> /dev/null || fail "rsync command not found"
# check for a tar command
type -P tar &> /dev/null || fail "tar command not found"
# get the current git branch
function get_current_branch {
local ref=$(git symbolic-ref HEAD 2> /dev/null)
local branch=${ref#refs/heads/}
echo "${branch}"
}
# get the current project version from sbt
# a little messy as the ansi escape codes are included
function get_current_version {
local result=$(sbt version | grep -v warn | tail -1 | cut -f2)
# remove ansi escape code from end
local code0=$(echo -e "\033[0m")
echo ${result%$code0}
}
# store the current git branch for cleaning up
declare -r initial_branch=$(get_current_branch)
# check we have an initial branch
[[ "${initial_branch}" ]] || fail "Not on a git branch"
# check that we have a clean status
[[ -z "$(git status --porcelain)" ]] || {
git status
fail "There are uncommitted changes - please commit before releasing"
}
(read -p "The working directory will now be cleaned from all non-tracked files. Are you sure you want this? " x; test "$x" = yes) || fail "bailing out"
git clean -fxd || fail "cannot git clean -fxd"
# the branch we'll release on
declare -r release_branch="releasing-${version}"
# try to run a cleanup command - these shouldn't actually fail
function safely {
"$@" || fail "Failed to clean up release - please check current state"
}
# perform a clean up when a failure has occurred
function git_cleanup {
echoerr "Cleaning up..."
local branch=$(get_current_branch)
safely git reset --hard
safely git clean -f
if [ "${branch}" == "${release_branch}" ]; then
safely git checkout ${initial_branch}
safely git branch -D ${release_branch}
local tags=$(git tag -l)
[[ "${tags}" == *v${version}* ]] && safely git tag -d v${version}
fi
}
# clean up and fail the script with an error message
function bail_out {
echoerr "Bailing out!"
git_cleanup
echoerr "Cleaned up failed release"
fail "$@"
}
# bail out for signals
function signal_bail_out {
echoerr "Interrupted by signal"
bail_out "Received signal to stop release"
}
# bail out on signals
trap signal_bail_out SIGHUP SIGINT SIGTERM
# try to run a command or otherwise bail out
function try {
"$@" || bail_out "Failed to create release"
}
echolog "Creating release ${version} ..."
if [ $dry_run ]; then
echodry "Building everything but not pushing release"
else
echolog "Publishing to ${publish_path}"
fi
[[ $run_tests ]] && echolog "All tests will be run"
# try ssh'ing to the release server
echolog "Checking ssh connection to ${release_server}"
try ssh -t ${release_server} echo "Successfully contacted release server."
echolog "Getting current project version from sbt..."
declare -r current_version=$(get_current_version)
echolog "Current version is ${current_version}"
# check out a release branch
try git checkout -b ${release_branch}
# find and replace the version
try ${script_dir}/find-replace ${current_version} ${version}
# start clean
try sbt clean
# run the tests if specified
if [ $run_tests ]; then
echolog "Running all tests..."
try sbt test
echolog "All tests are green"
fi
# build the release
echolog "Building the release..."
if [ ! $dry_run ]; then
RELEASE_OPT="-Dakka.genjavadoc.enabled=true -Dpublish.maven.central=true"
else
RELEASE_OPT="-Dakka.genjavadoc.enabled=true"
fi
try sbt $RELEASE_OPT +buildRelease
echolog "Successfully created local release"
# check binary compatibility for dry run
if [ ! $no_mima ] && [ $dry_run ]; then
echodry "Running migration manager report..."
sbt mimaReportBinaryIssues
echodry "Finished migration manager report"
fi
# commit and tag this release
echolog "Committing and tagging..."
try git add .
try git commit -am "Update version for release ${version}"
try git tag -am "Version ${version}" v${version}
# the point of no return... we're now pushing out to servers
# use a special failure from now on
function arrgh {
cat 1>&2 <<EOM
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Release failed while pushing to servers!
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
EOM
fail "Could not complete release - please check current state"
}
# try running a pushing command or otherwise fail
function important {
"$@" || arrgh
}
# new interrupted bail out for signals
function arrgh_interrupt {
echoerr "Interrupted by signal"
arrgh
}
# new exit on signals
trap arrgh_interrupt SIGHUP SIGINT SIGTERM
# push the commits and tags to git origin
echolog "Pushing to git origin..."
if [ $dry_run ]; then
echodry "Not actually pushing to git origin. Commands:"
echodry " git push origin --tags"
else
important git push origin --tags
fi
# push the release to the server
echolog "Pushing ${release_dir} to ${publish_path} ..."
if [ $dry_run ]; then
echodry "Not actually pushing to server. Command:"
echodry " rsync -rlpvz --chmod=Dg+ws,Fg+w --exclude ${release_dir}/downloads ${release_dir}/ ${publish_path}/"
echodry " sbt uploadRelease"
else
important ssh ${release_server} "cd ${release_path}/docs/akka; git add .; git commit -m 'before publishing version $version'; true"
important rsync -rlpvz --chmod=Dg+ws,Fg+w --exclude ${release_dir}/downloads ${release_dir}/ ${publish_path}/
important sbt uploadRelease
important ssh ${release_server} cp -v ${release_path}/docs/akka/${version}/_static/warnOldDocs.js ${release_path}/docs/akka
important ssh ${release_server} ln -snvf ../../warnOldDocs.js ${release_path}/docs/akka/${version}/_static/warnOldDocs.js
important ssh ${release_server} "cd ${release_path}/docs/akka; git add .; git commit -m 'publish version $version'"
fi
echolog "*****"
echolog "Do not forget to update versions.json on akka.github.com!"
echolog "*****"
if [ $dry_run ]; then
if [ $no_revert ]; then
echodry "No revert: git branch ${release_branch} and git tag v${version} remain"
else
git_cleanup
fi
echodry "Successfully created release ${version}"
echodry "See ${release_dir}"
else
echolog "Switching back to initial branch"
git checkout ${initial_branch}
echolog "Successfully created release ${version}"
fi