From 62d2ffd899265e75b8d3cc4bb12f21fc823a6344 Mon Sep 17 00:00:00 2001 From: Anubhav Date: Sun, 18 Jun 2017 00:50:54 -0700 Subject: [PATCH] Added versioning and merge-to-master scripts --- .gitignore | 1 + merge-to-master.sh | 238 +++++++++++++++++++++++++++++++++++++++++++++ versioning-acs.sh | 43 -------- versioning.sh | 28 ++++++ 4 files changed, 267 insertions(+), 43 deletions(-) create mode 100755 merge-to-master.sh delete mode 100755 versioning-acs.sh create mode 100755 versioning.sh diff --git a/.gitignore b/.gitignore index 40badad6..7224dcf6 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ commons/pom.xml.versionsBackup **/surefire~ **/gotty-client* .acs.* +xmlstarlet* diff --git a/merge-to-master.sh b/merge-to-master.sh new file mode 100755 index 00000000..a1a559f8 --- /dev/null +++ b/merge-to-master.sh @@ -0,0 +1,238 @@ +#!/usr/bin/env bash + +YES='yes' +SKIP='skip' +NO='n' +CONFIRMATION_MESSAGE="Type '${YES}' to continue, '${SKIP}' to skip or '${NO}' to abort" + +unset STEP_SKIPPED + +function prompt { + echo -e "\n\n${1}\n\n" + read -p "${CONFIRMATION_MESSAGE}. [${YES}/${SKIP}/${NO}]: " ANSWER + + if [[ "$ANSWER" == "$SKIP" ]]; then + STEP_SKIPPED='true' + elif [[ "$ANSWER" == "$YES" ]]; then + unset STEP_SKIPPED + else + echo -e '\nExiting...' + exit 1 + fi +} + +function set_proxies { + export http_proxy='http://proxy-src.research.ge.com:8080' + export HTTP_PROXY="$http_proxy" + export https_proxy="$http_proxy" + export HTTPS_PROXY="$https_proxy" +} + +function unset_proxies { + unset http_proxy + unset HTTP_PROXY + unset https_proxy + unset HTTPS_PROXY +} + +function run_versioning_script { + set_proxies + ./versioning.sh "$1" + unset_proxies +} + +function update_version { + if [[ -n "$1" ]]; then + local SNAPSHOT_VERSION="${1}-SNAPSHOT" + run_versioning_script "$SNAPSHOT_VERSION" + git commit -am "Bumped up the version to ${SNAPSHOT_VERSION}" + git push + RELEASE_VERSION="$1" + fi +} + +{ set -ex; } 2>/dev/null + +REPOSITORY_URI_PATH=$(git ls-remote --get-url | sed -n 's|.*[:/]\(.*\)/\(.*\)\.git|\1/\2|p') + +# Set the GitHub API domain/URI path and GE-specific proxies if the repository is hosted on github.com: +GIT_DOMAIN=$(git ls-remote --get-url | sed -n 's|\(.*\)[:/].*/.*\.git|\1|;s|.*[/@]\(.*\)|\1|p') +if [[ $(echo "$GIT_DOMAIN" | grep -q 'github\.com'; echo "$?") -eq 0 ]]; then + GIT_API_URI_PATH="api.${GIT_DOMAIN}" + set_proxies +else + GIT_API_URI_PATH="${GIT_DOMAIN}/api/v3" + unset_proxies +fi + +# Get the personal access token necessary for using the GitHub API: +{ set +x; } 2>/dev/null +read -p "Please go to https://${GIT_DOMAIN}/settings/tokens, click the 'Edit' button next to your personal access token, click the 'Regenerate token' button towards the top, and enter the token shown: " GIT_ACCESS_TOKEN + +if [[ -z "$GIT_ACCESS_TOKEN" ]]; then + echo -e '\nYour personal access token is required before running this script. Exiting...' + exit 1 +else + { set -x; } 2>/dev/null + PR_GET_ALL="$(curl "https://${GIT_API_URI_PATH}/repos/${REPOSITORY_URI_PATH}/pulls" -sI -X GET \ + -H "Authorization: token ${GIT_ACCESS_TOKEN}")" + { set +x; } 2>/dev/null + if [[ $(echo "$PR_GET_ALL" | grep -q '^HTTP.*200'; echo "$?") -ne 0 ]]; then + echo -e '\nYour personal access token is invalid. Please try again. Exiting...' + exit 1 + fi +fi + +prompt "About to merge changes from the develop to the master branch. Please stash any changes now via 'git stash save -u '." +{ set -x; } 2>/dev/null + +# Checkout the develop branch as follows (note that any local and untracked changes will be removed so they should be stashed prior to running these commands): +git clean -fd +git checkout -f develop +git pull --all --prune --tags --verbose + +# Cut a new release branch from develop, grabbing the current version from the top-level pom.xml file as follows: +RELEASE_VERSION=$(xmllint --xpath "//*[local-name()='project']/*[local-name()='version']/text()" pom.xml | sed 's/-SNAPSHOT//') + +if [[ -z "$RELEASE_VERSION" ]]; then + echo -e "\nThe release version can't be empty. Exiting..." + exit 1 +fi + +if [[ -z "$STEP_SKIPPED" ]]; then + { set +x; } 2>/dev/null + echo -e "\n\nThe current version that will be used in the 'release-${RELEASE_VERSION}' branch is '${RELEASE_VERSION}'.\n\n" + read -p "If you would like to update the version, please enter the new version (without the '-SNAPSHOT' suffix) or press Enter to continue using the existing version: " UPDATED_RELEASE_VERSION + { set -x; } 2>/dev/null + + update_version "$UPDATED_RELEASE_VERSION" + + if [[ $(git branch -a | grep -q "remotes/origin/release-${RELEASE_VERSION}"; echo "$?") -ne 0 ]]; then + git checkout -B "release-${RELEASE_VERSION}" develop + + # Remove the -SNAPSHOT suffix from all versions, verify the changes and commit them as follows: + run_versioning_script "$RELEASE_VERSION" + git commit -am "Changed the version to ${RELEASE_VERSION} (removes the '-SNAPSHOT' suffix)" + + # Merge the master branch into the release branch as follows: + git checkout -f master + git pull --all --prune --tags --verbose + git checkout - + { set +e; } 2>/dev/null + git merge -X ours --no-edit master + { set -e; } 2>/dev/null + + # Push the release branch upstream as follows: + git push -u origin "release-${RELEASE_VERSION}" + else + { set +x; } 2>/dev/null + echo -e '\nRelease branch has already been pushed.\n\n' + { set -x; } 2>/dev/null + fi +fi + +{ set +x; } 2>/dev/null +prompt "About to create a pull request from this release branch and merge it in." +{ set -x; } 2>/dev/null + +if [[ -z "$STEP_SKIPPED" ]]; then + PR_GET_RESPONSE="$(curl "https://${GIT_API_URI_PATH}/repos/${REPOSITORY_URI_PATH}/pulls?state=open" -s -X GET \ + -H "Authorization: token ${GIT_ACCESS_TOKEN}")" + + RELEASE_TITLE="Release ${RELEASE_VERSION}" + + if [[ -z $(echo "$PR_GET_RESPONSE" | python -c "import sys, json; pull_requests = json.load(sys.stdin); title = [pr['title'] for pr in pull_requests if pr['title'] == '${RELEASE_TITLE}']; print title[0] if title else '';") ]]; then + # Create a pull request for the release branch: + PR_CREATE_RESPONSE="$(curl "https://${GIT_API_URI_PATH}/repos/${REPOSITORY_URI_PATH}/pulls" -s -X POST \ + -H "Authorization: token ${GIT_ACCESS_TOKEN}" \ + -H 'Content-Type: application/json' \ + -d '{ "title": "'"${RELEASE_TITLE}"'", "head": "release-'"$RELEASE_VERSION"'", "base": "master" }')" + + PR_JSON_RESPONSE="$PR_CREATE_RESPONSE" + else + PR_JSON_RESPONSE="$PR_GET_RESPONSE" + + { set +x; } 2>/dev/null + echo -e '\nPull request was already created.\n\n' + { set -x; } 2>/dev/null + fi + + { set +x; } 2>/dev/null + PULL_REQUEST_NUMBER=$(echo "$PR_JSON_RESPONSE" | python -c "import sys, json; print json.load(sys.stdin)['number']") + PULL_REQUEST_TITLE=$(echo "$PR_JSON_RESPONSE" | python -c "import sys, json; print json.load(sys.stdin)['title']") + PULL_REQUEST_HEAD_LABEL=$(echo "$PR_JSON_RESPONSE" | python -c "import sys, json; print json.load(sys.stdin)['head']['label']" | tr ':' '/') + PULL_REQUEST_HEAD_SHA=$(echo "$PR_JSON_RESPONSE" | python -c "import sys, json; print json.load(sys.stdin)['head']['sha']") + PULL_REQUEST_URL=$(echo "$PR_JSON_RESPONSE" | python -c "import sys, json; print json.load(sys.stdin)['url']") + + prompt "About to merge the pull request located at '${PULL_REQUEST_URL}'." + { set -x; } 2>/dev/null + + if [[ -z "$STEP_SKIPPED" ]]; then + PR_GET_MERGE_RESPONSE="$(curl "${PULL_REQUEST_URL}/merge" -sI -X GET \ + -H "Authorization: token ${GIT_ACCESS_TOKEN}")" + + if [[ $(echo "$PR_GET_MERGE_RESPONSE" | grep -q '^HTTP.*204'; echo "$?") -ne 0 ]]; then + # Merge the pull request to master as follows: + PR_MERGE_RESPONSE="$(curl "${PULL_REQUEST_URL}/merge" -s -X PUT \ + -H "Authorization: token ${GIT_ACCESS_TOKEN}" \ + -H 'Content-Type: application/json' \ + -d '{ "commit_title": "Merge pull request #'"$PULL_REQUEST_NUMBER"' from '"$PULL_REQUEST_HEAD_LABEL"'", "commit_message": "'"$PULL_REQUEST_TITLE"'", "sha": "'"$PULL_REQUEST_HEAD_SHA"'", "merge_method": "merge" }')" + else + { set +x; } 2>/dev/null + echo -e '\nPull request was already merged.\n\n' + { set -x; } 2>/dev/null + fi + fi +fi + +{ set +x; } 2>/dev/null +prompt "About to delete the release branch remotely and locally." +{ set -x; } 2>/dev/null + +if [[ -z "$STEP_SKIPPED" ]]; then + # Delete the release branch remotely and locally as follows: + git checkout -f master + git pull --all --prune --tags --verbose + + if [[ $(git branch -a | grep -q "remotes/origin/release-${RELEASE_VERSION}"; echo "$?") -eq 0 ]]; then + git push --delete origin "release-${RELEASE_VERSION}" + git branch -D "release-${RELEASE_VERSION}" + else + { set +x; } 2>/dev/null + echo -e '\nRelease branch has already been deleted.\n\n' + { set -x; } 2>/dev/null + fi +fi + +{ set +x; } 2>/dev/null +prompt "About to tag the release." +{ set -x; } 2>/dev/null + +if [[ -z "$STEP_SKIPPED" ]]; then + # Pull the merged changes and tag the merge commit on master for future reference: + git checkout -f master + git pull --all --prune --tags --verbose + + if [[ $(git ls-remote --tags | grep -q "refs/tags/$RELEASE_VERSION"; echo "$?") -ne 0 ]]; then + { set +e; } 2>/dev/null + git tag -d "$RELEASE_VERSION" + { set -e; } 2>/dev/null + git tag "$RELEASE_VERSION" + git show "$RELEASE_VERSION" + git push origin "$RELEASE_VERSION" + else + { set +x; } 2>/dev/null + echo -e '\nRelease has already been tagged.\n\n' + { set -x; } 2>/dev/null + fi +fi + +git checkout -f develop +git pull --all --prune --tags --verbose + +{ set +x; } 2>/dev/null +echo -e "\n\nThe current version that will be used in the 'develop' branch is '${RELEASE_VERSION}-SNAPSHOT'.\n\n" +read -p "If you would like to update the version, please enter the new version (without the '-SNAPSHOT' suffix) or press Enter to continue using the existing version: " UPDATED_RELEASE_VERSION +{ set -x; } 2>/dev/null + +update_version "$UPDATED_RELEASE_VERSION" diff --git a/versioning-acs.sh b/versioning-acs.sh deleted file mode 100755 index 8a79c112..00000000 --- a/versioning-acs.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash - -#******************************************************************************* -# Copyright 2016 General Electric Company. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#******************************************************************************* - -# This convenience script updates POM versions for all ACS modules - -# Abort the script on failure of any command -set -ex - -# Abort the script if the ACS version wasn't passed in -if [ -z "$1" ]; then - echo "Please provide the ACS version." - exit 2 -fi - -# Remove older ACS artifacts from the local repository and re-install the current version of all artifacts -# so that versions are correctly set by the Maven Versions plugin -rm -rf ~/.m2/repository/com/ge/predix/acs* -mvn clean install -s ../acs-ci-config/mvn_settings.xml -DskipTests - -# Update the project versions in all POMs (main module and all submodules) -mvn versions:set -DallowSnapshots=true -DgenerateBackupPoms=false -DnewVersion=$1 -mvn clean install -s ../acs-ci-config/mvn_settings.xml -DskipTests - -# Update the project version of the parent POM in the acs-integration-tests POM -cd acs-integration-tests -mvn versions:update-parent -DallowSnapshots=true -DgenerateBackupPoms=false -DparentVersion=$1 -mvn versions:use-latest-versions -DallowSnapshots=true -DgenerateBackupPoms=false -Dincludes=com.ge.predix:acs-service -mvn clean install -s ../../acs-ci-config/mvn_settings.xml -Dmaven.test.skip diff --git a/versioning.sh b/versioning.sh new file mode 100755 index 00000000..5c3eafaa --- /dev/null +++ b/versioning.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +set -ex + +if [[ -z "$1" ]]; then + echo "Please provide the version to set in all POM files" + exit 2 +fi + +XMLSTARLET_VERSION='1.6.1' +XMLSTARLET_DIRNAME="xmlstarlet-${XMLSTARLET_VERSION}" +XMLSTARLET_ARCHIVE_NAME="${XMLSTARLET_DIRNAME}.tar.gz" +if [[ ! -f "${XMLSTARLET_DIRNAME}/xml" ]]; then + curl -OL "https://downloads.sourceforge.net/project/xmlstar/xmlstarlet/${XMLSTARLET_VERSION}/${XMLSTARLET_ARCHIVE_NAME}" + tar -xvzf "${XMLSTARLET_ARCHIVE_NAME}" + cd "$XMLSTARLET_DIRNAME" + ./configure && make +else + cd "$XMLSTARLET_DIRNAME" +fi + +./xml ed -P -L -N x='http://maven.apache.org/POM/4.0.0' -u '/x:project/x:version' -v "$1" '../pom.xml' + +for f in 'commons/pom.xml' 'model/pom.xml' 'service/pom.xml' 'acs-integration-tests/pom.xml'; do + ./xml ed -P -L -N x='http://maven.apache.org/POM/4.0.0' -u '/x:project/x:parent/x:version' -v "$1" "../${f}" +done + +./xml ed -P -L -N x='http://maven.apache.org/POM/4.0.0' -u '/x:project/x:dependencies/x:dependency[x:artifactId="acs-service"]/x:version' -v "$1" '../acs-integration-tests/pom.xml'