#!/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> publish-local-signed # 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 # To find out your key id do this from the command line: # shell> gpg --list-keys # pub 2048/ ... # 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", # "", # "") # # 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", # "", # "") # # 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 # And if all goes well a real run: # shell> project/scripts/release --real-run # # 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 <&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 +build-release echolog "Successfully created local release" # check binary compatibility for dry run if [ ! $no_mima ] && [ $dry_run ]; then echodry "Running migration manager report..." sbt mima-report-binary-issues 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 <