alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Akka/Scala example source code file (release)

This example Akka source code file (release) is included in my "Source Code Warehouse" project. The intent of this project is to help you more easily find Akka and Scala source code examples by using tags.

All credit for the original source code belongs to akka.io; I'm just trying to make examples easier to find. (For my Scala work, see my Scala examples and tutorials.)

Akka tags/keywords

ask, eom, from, not, p, pgp, release_opt, sonatype, successfully, you

The release Akka example source code

#!/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 <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:
#        http://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 --dry-run <version>
#  And if all goes well a real run:
#    shell> project/scripts/release <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}
declare -r unzipped_dir="target/dist/unzipped"

# flags
unset run_tests dry_run no_mima no_revert

# 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
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})
  -n | --dry-run         Build everything but do not 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 ;;
    -n | --dry-run) dry_run=true; 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 "java version" | cut -d ' ' -f3 | cut -d '.' -f2` -eq 6 ]] || fail "Java version is not 1.6"

# 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"
}

(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 "Creating gzipped tar download..."
try tar -cz -C ${unzipped_dir} -f ${release_dir}/downloads/akka-${version}.tgz akka-${version}
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 <<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 ${release_branch}"
  echodry "  git push origin --tags"
else
  important git push origin ${release_branch}
  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 ${release_dir}/ ${publish_path}/"
  echodry "  sbt upload-release"
else
  important rsync -rlpvz --chmod=Dg+ws,Fg+w --exclude ${release_dir}/downloads ${release_dir}/ ${publish_path}/
  important sbt upload-release
fi

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

Other Akka source code examples

Here is a short list of links related to this Akka release source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.