#!/bin/bash ##Always exit on $? -ne 0 set -e ## _cleanup() { rm $FILENAME_TMPCHANGELOG &>/dev/null } ##### Create a release for a project managed with a Git repository ##### ### Functions ### # Confirm dialog for user interactions # Usage: confirm "Question?" # Returns: 0 = true, 1 = false confirm() { read -r -p "$1 [y/n] " response case $response in [yY][eE][sS]|[yY]) return 0;; *) return 1;; esac } ### Display usage message usage () { echo "Usage: $0 [-v VERSION] [-r REMOTE] -s 'One line summary of changes for this release'" exit 0 } ### Initialize the variables and settings ### #Variables RELEASE_VERSION= REMOTE= SHORT_SUMMARY= while getopts v:r:s: OPT; do case $OPT in v) RELEASE_VERSION="${OPTARG}";; r) REMOTE="${OPTARG}";; s) SHORT_SUMMARY="${OPTARG}";; esac done shift $(( $OPTIND - 1 )); if [ -z "${SHORT_SUMMARY}" ]; then usage && exit 0 fi : ${REMOTE:=origin} FILENAME_TMPCHANGELOG="$( mktemp --suffix=ansible_role_release_changelog )" trap _cleanup ALRM HUP INT TERM EXIT # Fetch Git remote inormation git fetch $REMOTE --tags # Some information can be detected LAST_VERSION=$( git tag -l | tail -n 1 ) REPOSITORY_NAME=$( git remote show -n $REMOTE | grep Fetch | sed 's#.*/##' | sed 's/\.git//' ) EXISTING_TAGS=`git tag -l` # Detect version if not provided by user if [[ -z "${RELEASE_VERSION}" ]]; then RELEASE_VERSION=$(echo $LAST_VERSION|awk -F . '{print $1 "." $2 + 1 "." $3}') fi RELEASE_BRANCH="release/${RELEASE_VERSION}" # Check if there is already a tag named $RELEASE_VERSION ## Temporary disabling exit on $? -ne 0 to be able to display error message set +e if [[ $EXISTING_TAGS =~ "$RELEASE_VERSION" ]]; then >&2 echo "A tag $RELEASE_VERSION already exists!" >&2 echo "Aborting.." exit 1 fi set -e # Confirm or exit echo echo "Settings for the release to be created:" echo " Version of last release: ${LAST_VERSION}" echo " Version of new release: ${RELEASE_VERSION}" echo " Name of Git repository: ${REPOSITORY_NAME}" echo " Summary text for release: ${SHORT_SUMMARY}" if ! confirm "Continue with these settings?"; then exit 1 fi ### Perform release ### echo echo "Checkout and pull next branch" git checkout next git pull $REMOTE next echo echo "Checkout new release branch" git checkout -b ${RELEASE_BRANCH} echo echo "Write VERSION file" echo ${RELEASE_VERSION} > VERSION echo echo "Add release information to CHANGELOG.md file" cat CHANGELOG.md > $FILENAME_TMPCHANGELOG echo "# ${RELEASE_VERSION}" > CHANGELOG.md echo "" >> CHANGELOG.md if [[ -n ${LAST_VERSION} ]]; then git shortlog --no-merges next --not ${LAST_VERSION} | sed -e '/^[ \t]/s#^[ \t]*#* #' | perl -pe 's/:$/:\n/g' >> CHANGELOG.md cat $FILENAME_TMPCHANGELOG >> CHANGELOG.md else git shortlog --no-merges next | sed -e '/^[ \t]/s#^[ \t]*#* #' | perl -pe 's/:$/:\n/g' >> CHANGELOG.md cat $FILENAME_TMPCHANGELOG >> CHANGELOG.md fi echo "Please verify and adjust version information that was prepended to CHANGELOG.md file" echo "Diff looks like this:" echo echo '###### Diff start ######' ## Disable exit on $? -ne 0 for the diff command, since it returns $? == 1 if a diff was found set +e diff -u $FILENAME_TMPCHANGELOG CHANGELOG.md set -e echo '###### Diff end ######' echo echo "In case this is not correct, press ctrl+z to pause this script, adjust CHANGELOG.md and get back using the fg command" while ! confirm "Continue?"; do echo "And now?" done echo echo "Commit generated release information" rm -f $FILENAME_TMPCHANGELOG git add VERSION git add CHANGELOG.md git commit -m "${REPOSITORY_NAME} ${RELEASE_VERSION}: ${SHORT_SUMMARY}" echo echo "Checkout and pull master branch" git checkout master git pull $REMOTE master echo echo "Merge release branch to master branch" git merge --no-ff --log --no-edit ${RELEASE_BRANCH} echo echo "Create release tag ${RELEASE_VERSION}" git tag -a ${RELEASE_VERSION} -m "${REPOSITORY_NAME} ${RELEASE_VERSION}: ${SHORT_SUMMARY}" echo echo "Merge release branch to next branch" git checkout next git merge ${RELEASE_BRANCH} echo echo "Delete release branch - it's obsolete now" git branch -d ${RELEASE_BRANCH} echo echo "Push all changes to remote repository" git push $REMOTE master next ${RELEASE_VERSION} exit 0