From 4668a0b59347b073c40de7036a8e3992e28f0c72 Mon Sep 17 00:00:00 2001 From: pwilkins Date: Wed, 10 Feb 2016 16:57:05 -0500 Subject: [PATCH 01/18] Added initial version This version automates the steps through the creation of a pull request on the ``release`` branch. It has little error checking at this point. --- README.md | 19 ++++++++++ release.sh | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100755 release.sh diff --git a/README.md b/README.md index 5cf3f21..85121d2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,21 @@ # release-script Scripts to automate the release process. + +These scripts automate the release process which to-date has been +an intricate manual process. These are the steps: + +1. Check-out a current master branch +2. Create a release candidate branch +3. Generate release notes +3. Update version numbers and RELEASE.rst +4. Commit updates and push branch +6. Open PR against ``release candidate`` branch +7. Merge PR once ``travis-ci`` build succeeds +8. Generate release notes with checkboxes +8. Open PR against ``release`` branch +10. Open PR against ``master`` branch +11. Merge PRs once developers verify their commits +12. Send email notifications + +## Notes +1. diff --git a/release.sh b/release.sh new file mode 100755 index 0000000..23c0130 --- /dev/null +++ b/release.sh @@ -0,0 +1,100 @@ +#!/bin/bash -x + +# A script to automate the release process + +# Usage +# release working_dir version_num + +set -euf -o pipefail + +# SCRIPT_DIR via http://www.ostricher.com/2014/10/the-right-way-to-get-the-directory-of-a-bash-script/ +SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +WORKING_DIR=$1 +VERSION=$2 +OLD_VERSION=$(find . -name 'settings.py' -maxdepth 2 | xargs grep VERSION | tr '"' ' ' | awk '{print $3}') + +# Check that programs are available +EXIT_TO_INSTALL_APPS=false + +if hash hub 2>/dev/null; then + # continue +else + EXIT_TO_INSTALL_APPS=true + echo 'Please install hub https://hub.github.com/' +fi +if hash git 2>/dev/null; then + @ continue +else + EXIT_TO_INSTALL_APPS=true + echo 'Please install git https://git-scm.com/downloads' +fi +if hash perl 2>/dev/null; then + @ continue +else + EXIT_TO_INSTALL_APPS=true + echo 'Please install perl https://www.perl.org/get.html' +fi +if EXIT_TO_INSTALL_APPS=true then + exit() +fi + +cd $WORKING_DIR # change to repository working directory +git checkout master +git pull + +# Create the branch if it doesn't exist. If it does, just check it out +git checkout -b release-candidate || (git checkout release-candidate && git merge master) + +# maxdepth, so we don't pull things from .tox, etc +find $WORKING_DIR -name 'settings.py' -maxdepth 2 | xargs perl -pi -e "s/VERSION = .*/VERSION = \"$VERSION\"/g" +find $WORKING_DIR -name 'setup.py' -maxdepth 2 | xargs perl -pi -e "s/version=.*/version='$VERSION',/g" + +# Create/Update RELEASE.rst +# +4 is to offset the header of the template we don't want yet. +IFS=$'\n' # sets separator to only newlines. see http://askubuntu.com/a/344418 +NEW_RELEASE_NOTES=$(git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes_rst.ejs | tail +4) + +echo 'Release Notes' > releases_rst.new +echo '=============' >> releases_rst.new +echo '' >> releases_rst.new +echo "Version $VERSION" >> releases_rst.new +echo '-------------' >> releases_rst.new +echo '' >> releases_rst.new + +# we do this because, without it, bash ignores newlines in between the bullets. +for line in $NEW_RELEASE_NOTES; do + echo $line >> releases_rst.new +done; +echo '' >> releases_rst.new +echo RELEASE.rst | tail +4 >> releases_rst.new + +mv releases_rst.new RELEASE.rst +# explicit add, because we know the location & we will need it for the first release +git add RELEASE.rst +git commit --all --message "Release $VERSION" + +# git push origin release-candidate:release-candidate +# hub pull-request -b master -h "release-candidate" -m "Update version to $VERSION" +# +git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes.ejs > release-notes-checklist +# hub pull-request -b release -h "release-candidate" -F release-notes-checklist + +echo "Go tell engineers to check their work. PR is on the repo." +echo "After they are done, run the next script." + +# Next Steps +# - make pr from rc/0.2.0 to release with git-release-notes as the PR description (the non-rst one) +# ... then instruct humans to QA +# ... when they are done, we "finish". Brandon has opinions about what this means w/r/t which branch gets merged where. +# ... we certainly tag builds and push tags up and delete some branches. +# ... What should it be doing something with PRs? *shrug* + +# QUESTIONS: +# Does pushing to rc/0.2.0 create a thing on teachersportal-rc.herokuapp.com? +# +# Can we just make a PR from this new rc/0.2.0 branch to release now using hub? Or do we have to wait for the build to pass on this branch? +# +# +# + + From 1dfbe87100ea1276717893431e42f0fca6773196 Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Wed, 17 Feb 2016 12:50:54 -0500 Subject: [PATCH 02/18] Move to functions. --- release.sh | 180 +++++++++++++++++++++++++++++------------------------ 1 file changed, 97 insertions(+), 83 deletions(-) diff --git a/release.sh b/release.sh index 23c0130..d895090 100755 --- a/release.sh +++ b/release.sh @@ -14,87 +14,101 @@ VERSION=$2 OLD_VERSION=$(find . -name 'settings.py' -maxdepth 2 | xargs grep VERSION | tr '"' ' ' | awk '{print $3}') # Check that programs are available -EXIT_TO_INSTALL_APPS=false - -if hash hub 2>/dev/null; then - # continue -else - EXIT_TO_INSTALL_APPS=true - echo 'Please install hub https://hub.github.com/' -fi -if hash git 2>/dev/null; then - @ continue -else - EXIT_TO_INSTALL_APPS=true - echo 'Please install git https://git-scm.com/downloads' -fi -if hash perl 2>/dev/null; then - @ continue -else - EXIT_TO_INSTALL_APPS=true - echo 'Please install perl https://www.perl.org/get.html' -fi -if EXIT_TO_INSTALL_APPS=true then - exit() -fi - -cd $WORKING_DIR # change to repository working directory -git checkout master -git pull - -# Create the branch if it doesn't exist. If it does, just check it out -git checkout -b release-candidate || (git checkout release-candidate && git merge master) - -# maxdepth, so we don't pull things from .tox, etc -find $WORKING_DIR -name 'settings.py' -maxdepth 2 | xargs perl -pi -e "s/VERSION = .*/VERSION = \"$VERSION\"/g" -find $WORKING_DIR -name 'setup.py' -maxdepth 2 | xargs perl -pi -e "s/version=.*/version='$VERSION',/g" - -# Create/Update RELEASE.rst -# +4 is to offset the header of the template we don't want yet. -IFS=$'\n' # sets separator to only newlines. see http://askubuntu.com/a/344418 -NEW_RELEASE_NOTES=$(git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes_rst.ejs | tail +4) - -echo 'Release Notes' > releases_rst.new -echo '=============' >> releases_rst.new -echo '' >> releases_rst.new -echo "Version $VERSION" >> releases_rst.new -echo '-------------' >> releases_rst.new -echo '' >> releases_rst.new - -# we do this because, without it, bash ignores newlines in between the bullets. -for line in $NEW_RELEASE_NOTES; do - echo $line >> releases_rst.new -done; -echo '' >> releases_rst.new -echo RELEASE.rst | tail +4 >> releases_rst.new - -mv releases_rst.new RELEASE.rst -# explicit add, because we know the location & we will need it for the first release -git add RELEASE.rst -git commit --all --message "Release $VERSION" - -# git push origin release-candidate:release-candidate -# hub pull-request -b master -h "release-candidate" -m "Update version to $VERSION" -# -git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes.ejs > release-notes-checklist -# hub pull-request -b release -h "release-candidate" -F release-notes-checklist - -echo "Go tell engineers to check their work. PR is on the repo." -echo "After they are done, run the next script." - -# Next Steps -# - make pr from rc/0.2.0 to release with git-release-notes as the PR description (the non-rst one) -# ... then instruct humans to QA -# ... when they are done, we "finish". Brandon has opinions about what this means w/r/t which branch gets merged where. -# ... we certainly tag builds and push tags up and delete some branches. -# ... What should it be doing something with PRs? *shrug* - -# QUESTIONS: -# Does pushing to rc/0.2.0 create a thing on teachersportal-rc.herokuapp.com? -# -# Can we just make a PR from this new rc/0.2.0 branch to release now using hub? Or do we have to wait for the build to pass on this branch? -# -# -# - +validate_dependencies () { + EXIT_TO_INSTALL_APPS=false + + if hash hub 2>/dev/null; then + # continue + else + EXIT_TO_INSTALL_APPS=true + echo 'Please install hub https://hub.github.com/' + fi + if hash git 2>/dev/null; then + @ continue + else + EXIT_TO_INSTALL_APPS=true + echo 'Please install git https://git-scm.com/downloads' + fi + if hash perl 2>/dev/null; then + @ continue + else + EXIT_TO_INSTALL_APPS=true + echo 'Please install perl https://www.perl.org/get.html' + fi + if EXIT_TO_INSTALL_APPS=true then + exit() + fi +} + +update_copy () { + cd $WORKING_DIR # change to repository working directory + git checkout master + git pull + +} + +checkout_release () { + # Create the branch if it doesn't exist. If it does, just check it out + git checkout -b release-candidate || (git checkout release-candidate && git merge master) +} + +update_versions () { + # maxdepth, so we don't pull things from .tox, etc + find $WORKING_DIR -name 'settings.py' -maxdepth 2 | xargs perl -pi -e "s/VERSION = .*/VERSION = \"$VERSION\"/g" + find $WORKING_DIR -name 'setup.py' -maxdepth 2 | xargs perl -pi -e "s/version=.*/version='$VERSION',/g" +} + +update_release_notes () { + # Create/Update RELEASE.rst + # +4 is to offset the header of the template we don't want yet. + IFS=$'\n' # sets separator to only newlines. see http://askubuntu.com/a/344418 + NEW_RELEASE_NOTES=$(git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes_rst.ejs | tail +4) + + echo 'Release Notes' > releases_rst.new + echo '=============' >> releases_rst.new + echo '' >> releases_rst.new + echo "Version $VERSION" >> releases_rst.new + echo '-------------' >> releases_rst.new + echo '' >> releases_rst.new + + # we do this because, without it, bash ignores newlines in between the bullets. + for line in $NEW_RELEASE_NOTES; do + echo $line >> releases_rst.new + done; + echo '' >> releases_rst.new + echo RELEASE.rst | tail +4 >> releases_rst.new + mv releases_rst.new RELEASE.rst + # explicit add, because we know the location & we will need it for the first release + git add RELEASE.rst + git commit --all --message "Release $VERSION" +} + + +build_release () { + # git push origin release-candidate:release-candidate +} + +generate_prs () { + # hub pull-request -b master -h "release-candidate" -m "Update version to $VERSION" + # + git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes.ejs > release-notes-checklist + # hub pull-request -b release -h "release-candidate" -F release-notes-checklist +} + +main () { + validate_dependencies + update_copy + checkout_release + update_versions + update_release_notes + build_release + generate_prs + echo "Go tell engineers to check their work. PR is on the repo." + echo "After they are done, run the next script." +} + + +# Next script: +# - tag build +# - push tags From e16b5cc06247e340358cc9963987c0bde5f96d25 Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Wed, 17 Feb 2016 13:21:53 -0500 Subject: [PATCH 03/18] useful error function. it writes to stderr. --- release.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/release.sh b/release.sh index d895090..ac29b50 100755 --- a/release.sh +++ b/release.sh @@ -7,6 +7,10 @@ set -euf -o pipefail +error () { # error that writes to stderr, not stdout. + >&2 echo $@ +} + # SCRIPT_DIR via http://www.ostricher.com/2014/10/the-right-way-to-get-the-directory-of-a-bash-script/ SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) WORKING_DIR=$1 From 9e4edb27886a976e6c5006be68c1090bc5707b94 Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Wed, 17 Feb 2016 13:22:24 -0500 Subject: [PATCH 04/18] Quote variable usage. --- release.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/release.sh b/release.sh index ac29b50..d542a48 100755 --- a/release.sh +++ b/release.sh @@ -11,11 +11,15 @@ error () { # error that writes to stderr, not stdout. >&2 echo $@ } +# Quote nesting works as described here: http://stackoverflow.com/a/6612417/4972 # SCRIPT_DIR via http://www.ostricher.com/2014/10/the-right-way-to-get-the-directory-of-a-bash-script/ -SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -WORKING_DIR=$1 -VERSION=$2 -OLD_VERSION=$(find . -name 'settings.py' -maxdepth 2 | xargs grep VERSION | tr '"' ' ' | awk '{print $3}') +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Default variables to empty if not present. Necessary due to the -u option specified above. +# For more information on this, look here: +# http://redsymbol.net/articles/unofficial-bash-strict-mode/#solution-positional-parameters +WORKING_DIR="${1:-}" # default $1 to empty if it's not supplied +VERSION="${2:-}" # Check that programs are available validate_dependencies () { From 51d4417a08d37bef4069fbd9375f606ae7862ade Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Wed, 17 Feb 2016 13:22:37 -0500 Subject: [PATCH 05/18] Check args are defined. --- release.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/release.sh b/release.sh index d542a48..9f251e6 100755 --- a/release.sh +++ b/release.sh @@ -21,6 +21,16 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" WORKING_DIR="${1:-}" # default $1 to empty if it's not supplied VERSION="${2:-}" +if [[ -z "$WORKING_DIR" ]]; then + error "You must specify a working directory as the first argument." + exit 1 +fi + +if [[ -z "$VERSION" ]]; then + error "You must specify a version as the second argument." + exit 1 +fi + # Check that programs are available validate_dependencies () { EXIT_TO_INSTALL_APPS=false From 0424d6c79377d7b1b4adcb65b434e171fa93630f Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Wed, 17 Feb 2016 13:22:48 -0500 Subject: [PATCH 06/18] Negate dependency check This allows us to not do the "it exists" case. Also, use bash integers `local -i $var` so addition is correct. Exit code communicates the number of missing dependencies. --- release.sh | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/release.sh b/release.sh index 9f251e6..c01dc9c 100755 --- a/release.sh +++ b/release.sh @@ -33,28 +33,22 @@ fi # Check that programs are available validate_dependencies () { - EXIT_TO_INSTALL_APPS=false - - if hash hub 2>/dev/null; then - # continue - else - EXIT_TO_INSTALL_APPS=true - echo 'Please install hub https://hub.github.com/' + local -i missing=0 + if ! hash hub 2>/dev/null; then + missing=$missing+1 + error 'Please install hub https://hub.github.com/' fi - if hash git 2>/dev/null; then - @ continue - else - EXIT_TO_INSTALL_APPS=true - echo 'Please install git https://git-scm.com/downloads' + if ! hash git 2>/dev/null; then + missing=$missing+1 + error 'Please install git https://git-scm.com/downloads' fi - if hash perl 2>/dev/null; then - @ continue - else - EXIT_TO_INSTALL_APPS=true - echo 'Please install perl https://www.perl.org/get.html' + if ! hash perl 2>/dev/null; then + missing=$missing+1 + error 'Please install perl https://www.perl.org/get.html' fi - if EXIT_TO_INSTALL_APPS=true then - exit() + + if [[ 0 -ne $missing ]]; then + exit $missing fi } From fde29b97d99f044938c089b27636dfd058256d5f Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Wed, 17 Feb 2016 13:23:48 -0500 Subject: [PATCH 07/18] Remove invalid bash function by giving it some content. --- release.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/release.sh b/release.sh index c01dc9c..d1bd272 100755 --- a/release.sh +++ b/release.sh @@ -98,6 +98,7 @@ update_release_notes () { build_release () { # git push origin release-candidate:release-candidate + echo "Building release" } generate_prs () { From 4879a605b1ef22499142fd93306ada184548b23b Mon Sep 17 00:00:00 2001 From: pwilkins Date: Wed, 10 Feb 2016 16:57:05 -0500 Subject: [PATCH 08/18] Added initial version This version automates the steps through the creation of a pull request on the ``release`` branch. It has little error checking at this point. --- README.md | 19 +++++++ release.sh | 100 +++++++++++++++++++++++++++++++++++++ util/release_notes.ejs | 3 ++ util/release_notes_rst.ejs | 5 ++ 4 files changed, 127 insertions(+) create mode 100755 release.sh create mode 100644 util/release_notes.ejs create mode 100644 util/release_notes_rst.ejs diff --git a/README.md b/README.md index 5cf3f21..85121d2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,21 @@ # release-script Scripts to automate the release process. + +These scripts automate the release process which to-date has been +an intricate manual process. These are the steps: + +1. Check-out a current master branch +2. Create a release candidate branch +3. Generate release notes +3. Update version numbers and RELEASE.rst +4. Commit updates and push branch +6. Open PR against ``release candidate`` branch +7. Merge PR once ``travis-ci`` build succeeds +8. Generate release notes with checkboxes +8. Open PR against ``release`` branch +10. Open PR against ``master`` branch +11. Merge PRs once developers verify their commits +12. Send email notifications + +## Notes +1. diff --git a/release.sh b/release.sh new file mode 100755 index 0000000..23c0130 --- /dev/null +++ b/release.sh @@ -0,0 +1,100 @@ +#!/bin/bash -x + +# A script to automate the release process + +# Usage +# release working_dir version_num + +set -euf -o pipefail + +# SCRIPT_DIR via http://www.ostricher.com/2014/10/the-right-way-to-get-the-directory-of-a-bash-script/ +SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +WORKING_DIR=$1 +VERSION=$2 +OLD_VERSION=$(find . -name 'settings.py' -maxdepth 2 | xargs grep VERSION | tr '"' ' ' | awk '{print $3}') + +# Check that programs are available +EXIT_TO_INSTALL_APPS=false + +if hash hub 2>/dev/null; then + # continue +else + EXIT_TO_INSTALL_APPS=true + echo 'Please install hub https://hub.github.com/' +fi +if hash git 2>/dev/null; then + @ continue +else + EXIT_TO_INSTALL_APPS=true + echo 'Please install git https://git-scm.com/downloads' +fi +if hash perl 2>/dev/null; then + @ continue +else + EXIT_TO_INSTALL_APPS=true + echo 'Please install perl https://www.perl.org/get.html' +fi +if EXIT_TO_INSTALL_APPS=true then + exit() +fi + +cd $WORKING_DIR # change to repository working directory +git checkout master +git pull + +# Create the branch if it doesn't exist. If it does, just check it out +git checkout -b release-candidate || (git checkout release-candidate && git merge master) + +# maxdepth, so we don't pull things from .tox, etc +find $WORKING_DIR -name 'settings.py' -maxdepth 2 | xargs perl -pi -e "s/VERSION = .*/VERSION = \"$VERSION\"/g" +find $WORKING_DIR -name 'setup.py' -maxdepth 2 | xargs perl -pi -e "s/version=.*/version='$VERSION',/g" + +# Create/Update RELEASE.rst +# +4 is to offset the header of the template we don't want yet. +IFS=$'\n' # sets separator to only newlines. see http://askubuntu.com/a/344418 +NEW_RELEASE_NOTES=$(git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes_rst.ejs | tail +4) + +echo 'Release Notes' > releases_rst.new +echo '=============' >> releases_rst.new +echo '' >> releases_rst.new +echo "Version $VERSION" >> releases_rst.new +echo '-------------' >> releases_rst.new +echo '' >> releases_rst.new + +# we do this because, without it, bash ignores newlines in between the bullets. +for line in $NEW_RELEASE_NOTES; do + echo $line >> releases_rst.new +done; +echo '' >> releases_rst.new +echo RELEASE.rst | tail +4 >> releases_rst.new + +mv releases_rst.new RELEASE.rst +# explicit add, because we know the location & we will need it for the first release +git add RELEASE.rst +git commit --all --message "Release $VERSION" + +# git push origin release-candidate:release-candidate +# hub pull-request -b master -h "release-candidate" -m "Update version to $VERSION" +# +git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes.ejs > release-notes-checklist +# hub pull-request -b release -h "release-candidate" -F release-notes-checklist + +echo "Go tell engineers to check their work. PR is on the repo." +echo "After they are done, run the next script." + +# Next Steps +# - make pr from rc/0.2.0 to release with git-release-notes as the PR description (the non-rst one) +# ... then instruct humans to QA +# ... when they are done, we "finish". Brandon has opinions about what this means w/r/t which branch gets merged where. +# ... we certainly tag builds and push tags up and delete some branches. +# ... What should it be doing something with PRs? *shrug* + +# QUESTIONS: +# Does pushing to rc/0.2.0 create a thing on teachersportal-rc.herokuapp.com? +# +# Can we just make a PR from this new rc/0.2.0 branch to release now using hub? Or do we have to wait for the build to pass on this branch? +# +# +# + + diff --git a/util/release_notes.ejs b/util/release_notes.ejs new file mode 100644 index 0000000..79ebd96 --- /dev/null +++ b/util/release_notes.ejs @@ -0,0 +1,3 @@ +<% commits.forEach(function (commit) { %>- [ ] <%= commit.title %> + [<%= commit.authorName %>](<%= commit.authorEmail %>) +<% }) %> diff --git a/util/release_notes_rst.ejs b/util/release_notes_rst.ejs new file mode 100644 index 0000000..15dd536 --- /dev/null +++ b/util/release_notes_rst.ejs @@ -0,0 +1,5 @@ +Version n.n.n +=============== + +<% commits.forEach(function (commit) { %>- <%= commit.title %> +<% }) %> From ee296e9a836e0d0f4a13550f52a4f69f0b796017 Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Wed, 17 Feb 2016 13:46:19 -0500 Subject: [PATCH 09/18] Call the main method on invocation. --- release.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/release.sh b/release.sh index d1bd272..4c66c2b 100755 --- a/release.sh +++ b/release.sh @@ -125,3 +125,4 @@ main () { # - tag build # - push tags +main From bc077d68df23f43b1bff7691442a7d06b8e20e7d Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Wed, 17 Feb 2016 13:46:34 -0500 Subject: [PATCH 10/18] change placement of -maxdepth --- release.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release.sh b/release.sh index 4c66c2b..39da0dd 100755 --- a/release.sh +++ b/release.sh @@ -66,8 +66,8 @@ checkout_release () { update_versions () { # maxdepth, so we don't pull things from .tox, etc - find $WORKING_DIR -name 'settings.py' -maxdepth 2 | xargs perl -pi -e "s/VERSION = .*/VERSION = \"$VERSION\"/g" - find $WORKING_DIR -name 'setup.py' -maxdepth 2 | xargs perl -pi -e "s/version=.*/version='$VERSION',/g" + find $WORKING_DIR -maxdepth 2 -name 'settings.py' | xargs perl -pi -e "s/VERSION = .*/VERSION = \"$VERSION\"/g" + find $WORKING_DIR -maxdepth 2 -name 'setup.py' | xargs perl -pi -e "s/version=.*/version='$VERSION',/g" } update_release_notes () { From 482583676013ce083c11eed33194c3afc8e3d7d9 Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Wed, 17 Feb 2016 13:52:36 -0500 Subject: [PATCH 11/18] Only trace the program if the TRACE envvar is set --- release.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/release.sh b/release.sh index 39da0dd..e857c9e 100755 --- a/release.sh +++ b/release.sh @@ -1,4 +1,4 @@ -#!/bin/bash -x +#!/bin/bash # A script to automate the release process @@ -7,6 +7,8 @@ set -euf -o pipefail +[[ "${TRACE:-}" ]] && set -x + error () { # error that writes to stderr, not stdout. >&2 echo $@ } From afccde0bd92a07eae6320ef9285d90a949aa0f0d Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Wed, 17 Feb 2016 13:53:01 -0500 Subject: [PATCH 12/18] helper function to validate cwd is clean. --- release.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/release.sh b/release.sh index e857c9e..4a78c72 100755 --- a/release.sh +++ b/release.sh @@ -34,6 +34,14 @@ if [[ -z "$VERSION" ]]; then fi # Check that programs are available +# Ensures the current working directory doesn't have tracked but uncommitted files in git. +clean_working_dir () { + if [[ "$(git status -s | grep -m1 "^ ")" ]]; then + error "Not checking out release. You have uncommitted files in your working directory." + exit 1 + fi +} + validate_dependencies () { local -i missing=0 if ! hash hub 2>/dev/null; then From 4b2a785d04a681a75c1d8372135eb1aaa603f9c7 Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Wed, 17 Feb 2016 13:53:26 -0500 Subject: [PATCH 13/18] Ensure git-release-notes is available. --- release.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/release.sh b/release.sh index 4a78c72..f4de136 100755 --- a/release.sh +++ b/release.sh @@ -33,7 +33,6 @@ if [[ -z "$VERSION" ]]; then exit 1 fi -# Check that programs are available # Ensures the current working directory doesn't have tracked but uncommitted files in git. clean_working_dir () { if [[ "$(git status -s | grep -m1 "^ ")" ]]; then @@ -42,6 +41,7 @@ clean_working_dir () { fi } +# Check that requisite programs are available validate_dependencies () { local -i missing=0 if ! hash hub 2>/dev/null; then @@ -57,6 +57,11 @@ validate_dependencies () { error 'Please install perl https://www.perl.org/get.html' fi + if ! hash git-release-notes 2>/dev/null; then + missing=$missing+1 + error 'Please install git-release-notes https://www.npmjs.com/package/git-release-notes' + fi + if [[ 0 -ne $missing ]]; then exit $missing fi From 4c5d4ce9dba7efd72eeea691db0b146c64a937fa Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Wed, 17 Feb 2016 13:53:55 -0500 Subject: [PATCH 14/18] Remove tail command for portability. Also adjust the template accordingly. --- release.sh | 33 +++++++++++++++++++++++++-------- util/release_notes_rst.ejs | 3 --- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/release.sh b/release.sh index f4de136..e04c6f5 100755 --- a/release.sh +++ b/release.sh @@ -22,6 +22,7 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # http://redsymbol.net/articles/unofficial-bash-strict-mode/#solution-positional-parameters WORKING_DIR="${1:-}" # default $1 to empty if it's not supplied VERSION="${2:-}" +OLD_VERSION= # set later. if [[ -z "$WORKING_DIR" ]]; then error "You must specify a working directory as the first argument." @@ -67,18 +68,32 @@ validate_dependencies () { fi } +# Updates the local repo update_copy () { cd $WORKING_DIR # change to repository working directory - git checkout master - git pull + clean_working_dir + git checkout master -q + git pull -q +} +set_old_version () { + cd $WORKING_DIR + OLD_VERSION="$(find . -maxdepth 2 -name 'settings.py' | xargs grep VERSION | tr "\"" ' ' | awk '{print $3}')" + if [[ -z "$OLD_VERSION" ]]; then + error "Could not determine the old version." + exit 1 + fi } +# Checks out the release-candidate branch checkout_release () { + cd $WORKING_DIR + clean_working_dir # Create the branch if it doesn't exist. If it does, just check it out - git checkout -b release-candidate || (git checkout release-candidate && git merge master) + git checkout -qb release-candidate 2>/dev/null || (git checkout -q release-candidate && git merge -q master) } + update_versions () { # maxdepth, so we don't pull things from .tox, etc find $WORKING_DIR -maxdepth 2 -name 'settings.py' | xargs perl -pi -e "s/VERSION = .*/VERSION = \"$VERSION\"/g" @@ -86,10 +101,11 @@ update_versions () { } update_release_notes () { + cd $WORKING_DIR # Create/Update RELEASE.rst # +4 is to offset the header of the template we don't want yet. IFS=$'\n' # sets separator to only newlines. see http://askubuntu.com/a/344418 - NEW_RELEASE_NOTES=$(git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes_rst.ejs | tail +4) + NEW_RELEASE_NOTES=$(git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes_rst.ejs) echo 'Release Notes' > releases_rst.new echo '=============' >> releases_rst.new @@ -103,17 +119,17 @@ update_release_notes () { echo $line >> releases_rst.new done; echo '' >> releases_rst.new - echo RELEASE.rst | tail +4 >> releases_rst.new + echo RELEASE.rst >> releases_rst.new mv releases_rst.new RELEASE.rst # explicit add, because we know the location & we will need it for the first release git add RELEASE.rst - git commit --all --message "Release $VERSION" + git commit -q --all --message "Release $VERSION" } build_release () { - # git push origin release-candidate:release-candidate - echo "Building release" + # git push -q origin release-candidate:release-candidate + echo "Building release..." } generate_prs () { @@ -127,6 +143,7 @@ main () { validate_dependencies update_copy checkout_release + set_old_version update_versions update_release_notes build_release diff --git a/util/release_notes_rst.ejs b/util/release_notes_rst.ejs index 15dd536..08ce531 100644 --- a/util/release_notes_rst.ejs +++ b/util/release_notes_rst.ejs @@ -1,5 +1,2 @@ -Version n.n.n -=============== - <% commits.forEach(function (commit) { %>- <%= commit.title %> <% }) %> From f56017811f0bf05511a93c3fbcec5b86fadff084 Mon Sep 17 00:00:00 2001 From: pwilkins Date: Wed, 2 Mar 2016 11:52:30 -0500 Subject: [PATCH 15/18] No dry run, per-author template, general fixes. --- release.sh | 12 +++++++----- util/release_notes.ejs | 23 ++++++++++++++++++++--- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/release.sh b/release.sh index e04c6f5..bfd7111 100755 --- a/release.sh +++ b/release.sh @@ -90,7 +90,7 @@ checkout_release () { cd $WORKING_DIR clean_working_dir # Create the branch if it doesn't exist. If it does, just check it out - git checkout -qb release-candidate 2>/dev/null || (git checkout -q release-candidate && git merge -q master) + git checkout -qb release-candidate 2>/dev/null || (git checkout -q release-candidate && git merge -q -m "Release $VERSION" master) } @@ -128,15 +128,17 @@ update_release_notes () { build_release () { - # git push -q origin release-candidate:release-candidate + git push -q origin release-candidate:release-candidate echo "Building release..." } generate_prs () { - # hub pull-request -b master -h "release-candidate" -m "Update version to $VERSION" + hub pull-request -b master -h "release-candidate" -m "Update version to $VERSION" # - git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes.ejs > release-notes-checklist - # hub pull-request -b release -h "release-candidate" -F release-notes-checklist + echo "Release $VERSION" >> release-notes-checklist + echo "" >> release-notes-checklist + git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes.ejs >> release-notes-checklist + hub pull-request -b release -h "release-candidate" -F release-notes-checklist } main () { diff --git a/util/release_notes.ejs b/util/release_notes.ejs index 79ebd96..ebbcacc 100644 --- a/util/release_notes.ejs +++ b/util/release_notes.ejs @@ -1,3 +1,20 @@ -<% commits.forEach(function (commit) { %>- [ ] <%= commit.title %> - [<%= commit.authorName %>](<%= commit.authorEmail %>) -<% }) %> +<% +by_author = {}; + +commits.forEach(function (commit) { + var author = commit.authorName; + by_author[author] = by_author[author] || []; + by_author[author].push(commit); +}) + +Object.keys(by_author).forEach(function (author) { + %>## <%= author %> +<% + by_author[author].forEach(function (commit) { + %> - [ ] <%= commit.title %> ([<%= commit.sha1.substring(0,8) %>](../commit/<%= commit.sha1 %>)) +<% + }); + %> +<% +}); +%> From 820155120208690d74bbb5931e848cffef4be8dd Mon Sep 17 00:00:00 2001 From: pwilkins Date: Wed, 2 Mar 2016 12:32:46 -0500 Subject: [PATCH 16/18] Release script should be catted, not echoed --- release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release.sh b/release.sh index bfd7111..f11d147 100755 --- a/release.sh +++ b/release.sh @@ -119,7 +119,7 @@ update_release_notes () { echo $line >> releases_rst.new done; echo '' >> releases_rst.new - echo RELEASE.rst >> releases_rst.new + cat RELEASE.rst >> releases_rst.new mv releases_rst.new RELEASE.rst # explicit add, because we know the location & we will need it for the first release git add RELEASE.rst From 313c2e0af9f726602a57a135cc6047c6a68e9d23 Mon Sep 17 00:00:00 2001 From: pwilkins Date: Thu, 3 Mar 2016 14:37:16 -0500 Subject: [PATCH 17/18] Fixed creation of release-notes-checklist ``release-notes-checklist`` should be created fresh each time the script is run. --- release.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/release.sh b/release.sh index f11d147..247f0da 100755 --- a/release.sh +++ b/release.sh @@ -135,7 +135,7 @@ build_release () { generate_prs () { hub pull-request -b master -h "release-candidate" -m "Update version to $VERSION" # - echo "Release $VERSION" >> release-notes-checklist + echo "Release $VERSION" > release-notes-checklist echo "" >> release-notes-checklist git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes.ejs >> release-notes-checklist hub pull-request -b release -h "release-candidate" -F release-notes-checklist @@ -150,6 +150,7 @@ main () { update_release_notes build_release generate_prs + echo "version $OLD_VERSION has been updated to $VERSION" echo "Go tell engineers to check their work. PR is on the repo." echo "After they are done, run the next script." } @@ -158,5 +159,7 @@ main () { # Next script: # - tag build # - push tags +# - merge release-candidate to release +# - merge release to master main From 16273e38b414a6d5df70a9c56b8b637705e3600c Mon Sep 17 00:00:00 2001 From: pwilkins Date: Fri, 4 Mar 2016 12:53:20 -0500 Subject: [PATCH 18/18] Removed PR from release-candidate to master This PR adds no useful information to the history and is unnecessary. --- release.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/release.sh b/release.sh index 247f0da..3d1e5b0 100755 --- a/release.sh +++ b/release.sh @@ -133,8 +133,6 @@ build_release () { } generate_prs () { - hub pull-request -b master -h "release-candidate" -m "Update version to $VERSION" - # echo "Release $VERSION" > release-notes-checklist echo "" >> release-notes-checklist git-release-notes v$OLD_VERSION..master $SCRIPT_DIR/util/release_notes.ejs >> release-notes-checklist