#!/usr/bin/env bash # # Release script for Akka. # # To run this script you need a user account on akka.io and contributor access # to github.com/akka/akka. # # If your username on akka.io is different from your local username then you can # configure ssh to always associate a particular username with akka.io by adding # the following to .ssh/config: # Host akka.io # User # defaults declare -r default_server="akka.io" declare -r default_path="/akka/www" # settings declare -r release_dir="target/release" declare release_server=${default_server} declare release_path=${default_path} declare -r unzipped_dir="target/dist/unzipped" # flags unset run_tests dry_run # 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 ;; -n | --dry-run) dry_run=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}" # 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 | 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" } # 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..." try sbt build-release try cp akka-spring/src/main/resources/akka/spring/akka-*.xsd ${release_dir} echolog "Creating gzipped tar download..." try tar -cz -C ${unzipped_dir} -f ${release_dir}/downloads/akka-${version}.tgz akka-${version} echolog "Successfully created local release" # commit and tag this release echolog "Committing and tagging..." try git add . try git commit -am "Update version for release ${version}" try git tag -m "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 <