fix .bin scripts
This commit is contained in:
399
.config/yadm/alt/.bin/rtm##o.Linux
Executable file
399
.config/yadm/alt/.bin/rtm##o.Linux
Executable file
@@ -0,0 +1,399 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# rtm -- Release to Master
|
||||
# Implements the release process of Vincent Driessen's branching model:
|
||||
# http://nvie.com/posts/a-successful-git-branching-model/
|
||||
#
|
||||
# Since we use the model at Bol.com for puppet modules, this script
|
||||
# will also check for metadata.json and Modulefile but it only does
|
||||
# something with it if it actually finds it.
|
||||
#
|
||||
# If xclip is installed then the version number will be sent to the
|
||||
# clipboard. This is handy for if you want to add it to the annotated
|
||||
# tag during the gitflow release process.
|
||||
#
|
||||
# Author: Steven Meunier <smeunier@bol.com>
|
||||
# Version: 0.2.0
|
||||
|
||||
set -e
|
||||
script_abort() {
|
||||
echo
|
||||
echo "Oops, it looks like something went wrong that I can't recover from."
|
||||
echo "You now have two options:"
|
||||
echo " 1) Fix the problem and continue the release process manually."
|
||||
echo " 2) Rollback any part of the release already performed, fix what"
|
||||
echo " caused the issue and try running the script again."
|
||||
echo "Whatever you decide, please don't blindly re-run this script as the results"
|
||||
echo "could be unexpected."
|
||||
exit 1
|
||||
}
|
||||
trap script_abort ERR
|
||||
|
||||
commit_counts () {
|
||||
local SOURCE=${1:-"@{upstream}"}
|
||||
local TARGET=${2:-"HEAD"}
|
||||
|
||||
echo $(git rev-list --no-merges --count --left-right $SOURCE...$TARGET 2> /dev/null)
|
||||
}
|
||||
|
||||
commits_behind () {
|
||||
local SOURCE=${1:-"@{upstream}"}
|
||||
local TARGET=${2:-"HEAD"}
|
||||
|
||||
local counts=( $(commit_counts $SOURCE $TARGET) )
|
||||
echo ${counts[0]}
|
||||
}
|
||||
|
||||
commits_ahead () {
|
||||
local SOURCE=${1:-"@{upstream}"}
|
||||
local TARGET=${2:-"HEAD"}
|
||||
|
||||
local counts=( $(commit_counts $SOURCE $TARGET) )
|
||||
echo ${counts[1]}
|
||||
}
|
||||
|
||||
get_current_branch() {
|
||||
echo -n $(git describe --contains --all HEAD)
|
||||
}
|
||||
|
||||
get_git_release () {
|
||||
local BRANCH=${1:-"master"}
|
||||
|
||||
echo -n $(git describe $BRANCH 2> /dev/null | cut -d'-' -f 1)
|
||||
}
|
||||
|
||||
get_metadata_release () {
|
||||
if [[ -f "metadata.json" ]]
|
||||
then
|
||||
echo -n $(grep -E "\"version\"" metadata.json | sed -E "s/\"version\":\s*[\"\'](.*)[\"\']\,$/\1/")
|
||||
elif [[ -f "Modulefile" ]]
|
||||
then
|
||||
echo -n $(grep -E "^version" Modulefile | sed -E "s/^version '(.*)'$/\1/")
|
||||
fi
|
||||
}
|
||||
|
||||
get_git_dir () {
|
||||
echo $(git rev-parse --git-dir 2> /dev/null)
|
||||
}
|
||||
|
||||
get_remote_name () {
|
||||
local BRANCH=${1:-"master"}
|
||||
|
||||
echo $(git config --local --get "branch.${BRANCH}.remote" 2> /dev/null)
|
||||
}
|
||||
|
||||
git_push () {
|
||||
local BRANCH=$1
|
||||
local THROUGH_GERRIT=${2:-"true"}
|
||||
|
||||
git checkout -q $BRANCH
|
||||
if [[ "${THROUGH_GERRIT}" =~ ^[tT]{1}([rR]{1}[uU]{1}[eE]{1})*$ ]]
|
||||
then
|
||||
local GERRIT_PREFIX="HEAD:refs/for"
|
||||
else
|
||||
local GERRIT_PREFIX="HEAD:refs/heads"
|
||||
fi
|
||||
git push $(get_remote_name ${BRANCH}) ${GERRIT_PREFIX}/${BRANCH}
|
||||
}
|
||||
|
||||
git_push_tag () {
|
||||
local TAG=${1:-${VERSION}}
|
||||
|
||||
git push $(get_remote_name ${BRANCH}) ${TAG}
|
||||
}
|
||||
|
||||
increment_version () {
|
||||
# Taken from http://stackoverflow.com/questions/8653126/how-to-increment-version-number-in-a-shell-script
|
||||
local VERSION=${1:-$(get_git_release)}
|
||||
|
||||
echo $VERSION | awk -F. -v OFS=. 'NF==1{print ++$NF}; NF>1{if(length($NF+1)>length($NF))$(NF-1)++; $NF=sprintf("%0*d", length($NF), ($NF+1)%(10^length($NF))); print}'
|
||||
}
|
||||
|
||||
is_inside_work_tree () {
|
||||
[ $(git rev-parse --is-inside-work-tree 2> /dev/null) == "true" ]
|
||||
}
|
||||
|
||||
is_gitflow_installed () {
|
||||
local GITFLOW=$(git flow version > /dev/null 2>&1)
|
||||
|
||||
if [[ "$?" -ne "0" ]]; then
|
||||
false
|
||||
else
|
||||
true
|
||||
fi
|
||||
}
|
||||
|
||||
show_diff () {
|
||||
local SOURCE_BRANCH=${1:-"master"}
|
||||
local TARGET_BRANCH=${2:-$(get_remote_name ${SOURCE_BRANCH})/${SOURCE_BRANCH}}
|
||||
|
||||
git diff ${TARGET_BRANCH} ${SOURCE_BRANCH}
|
||||
}
|
||||
|
||||
show_commits_to_be_pushed () {
|
||||
local SOURCE_BRANCH=${1:-"master"}
|
||||
local TARGET_BRANCH=${2:-$(get_remote_name ${SOURCE_BRANCH})/${SOURCE_BRANCH}}
|
||||
local FORMAT=${3:-"format:%Cgreen%h%Creset %<(70)%s %<(25)%Cblue%an%Creset (%ai)"}
|
||||
|
||||
echo "The following commits will be pushed to ${TARGET_BRANCH}:"
|
||||
echo -e "$(git log --pretty="${FORMAT}" ${TARGET_BRANCH}..${SOURCE_BRANCH})"
|
||||
}
|
||||
|
||||
show_current_release () {
|
||||
local METADATA_RELEASE=$(get_metadata_release)
|
||||
local GIT_RELEASE=$(get_git_release)
|
||||
|
||||
if [[ $GIT_RELEASE != $METADATA_RELEASE && "x${METADATA_RELEASE}" != "x" ]]
|
||||
then
|
||||
local VERSION_SUFFIX=" (metadata.json/Modulefile has ${METADATA_RELEASE})"
|
||||
else
|
||||
local VERSION_SUFFIX=""
|
||||
fi
|
||||
echo $GIT_RELEASE $VERSION_SUFFIX
|
||||
}
|
||||
|
||||
yes_no_prompt () {
|
||||
local PROMPT=${1:-"Are you sure? [y/N] "}
|
||||
local CMD_WHEN_YES=${2:-"true"}
|
||||
local CMD_WHEN_NO=${3:-"false"}
|
||||
|
||||
read -p "$PROMPT" RESPONSE
|
||||
if [[ $RESPONSE =~ ^[yY]([eE]{1}[sS]{1})*$ ]]
|
||||
then
|
||||
$CMD_WHEN_YES
|
||||
elif [[ $RESPONSE =~ ^[nN][oO]*$ ]]
|
||||
then
|
||||
$CMD_WHEN_NO
|
||||
else
|
||||
echo "Please answer 'yes' or 'no'"
|
||||
yes_no_prompt "$PROMPT" "$CMD_WHEN_YES" "$CMD_WHEN_NO"
|
||||
fi
|
||||
}
|
||||
|
||||
convert_modulefile () {
|
||||
PUPPETBIN=$(which puppet 2> /dev/null)
|
||||
: ${EDITOR:=$(which vi 2> /dev/null)}
|
||||
|
||||
if [[ -z "${PUPPETBIN}" ]]
|
||||
then
|
||||
echo "Puppet is required to convert the Modulefile. Skipping conversion."
|
||||
else
|
||||
"${PUPPETBIN}" module build
|
||||
if [[ $? -eq 0 ]]
|
||||
then
|
||||
cp pkg/*/metadata.json ./
|
||||
yes_no_prompt "Edit metadata.json before commit? [y/N] " "${EDITOR} metadata.json" true
|
||||
if $(grep -q metadata.json .gitignore)
|
||||
then
|
||||
sed -i '/metadata.json/d' .gitignore
|
||||
git add .gitignore
|
||||
fi
|
||||
git add metadata.json
|
||||
git rm -f Modulefile
|
||||
rm -rf pkg
|
||||
git commit -m "Convert Modulefile to metadata.json"
|
||||
else
|
||||
echo "Converting Modulefile to metadata.json failed."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
update_metadata () {
|
||||
local VERSION=$1
|
||||
local UPDATE_FLAG=0
|
||||
if [[ -f "metadata.json" && "x${VERSION}" != "x" && $(get_metadata_release) != "${VERSION}" ]]
|
||||
then
|
||||
sed -i -e "s/\"version\":.*/\"version\": \"${VERSION}\"\,/" metadata.json
|
||||
git add metadata.json
|
||||
UPDATE_FLAG=1
|
||||
fi
|
||||
if [[ $UPDATE_FLAG != 0 ]]
|
||||
then
|
||||
git commit -m "Bumped version"
|
||||
fi
|
||||
}
|
||||
|
||||
send_version_to_clipboard () {
|
||||
local VERSION=${1}
|
||||
local XCLIP_BIN=$(which xclip 2> /dev/null)
|
||||
|
||||
if [[ "x$XCLIP_BIN" != "x" ]]
|
||||
then
|
||||
echo -n $VERSION | ${XCLIP_BIN} -in
|
||||
fi
|
||||
}
|
||||
|
||||
prompt_release_version () {
|
||||
local INPUT_VERSION
|
||||
local INCREMENT_VERSION=$(increment_version)
|
||||
echo "Current release is:" $(show_current_release)
|
||||
echo "Default version to release: $INCREMENT_VERSION"
|
||||
read -e -p "Version to Release: " INPUT_VERSION
|
||||
|
||||
if [ "x$INPUT_VERSION" != "x" ]
|
||||
then
|
||||
VERSION=$INPUT_VERSION
|
||||
else
|
||||
VERSION=$INCREMENT_VERSION
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_change_id () {
|
||||
# Gerrit is likely to be configured to require a change-id but
|
||||
# merge commits with gitflow don't add it so we need to do that
|
||||
# ourselves. We do that by amending the merge commit. If the
|
||||
# change-id hook is installed then a change-id will be added. If
|
||||
# not, then nothing will happen and presumably Gerrit is then not
|
||||
# configured to require it either.
|
||||
local LOG=$(git log -1)
|
||||
local VERSION=${1:-${VERSION}}
|
||||
|
||||
if $(echo ${LOG} | grep -q "Merge:") && [[ $(echo ${LOG} | grep -q "Change-Id:") != 0 ]]
|
||||
then
|
||||
COMMIT=$(echo ${LOG} | head -1 | awk '{print $2}')
|
||||
echo "Change-Id is missing. Adding it..."
|
||||
git commit --amend -C ${COMMIT}
|
||||
|
||||
# This will mess up our annotated tag so we need to move it to
|
||||
# our amended commit
|
||||
if [[ $(get_current_branch) == "master" ]]
|
||||
then
|
||||
TAG_MSG=$(git show --pretty="format:%b" ${VERSION} | tail -n +3)
|
||||
git tag -f -a ${VERSION} -m "${TAG_MSG}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_git_flow_enabled () {
|
||||
if ! [[ $(grep gitflow $(get_git_dir)/config) ]]
|
||||
then
|
||||
echo "Enabling gitflow"
|
||||
git flow init -d > /dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
gitflow_release () {
|
||||
local VERSION=${1}
|
||||
|
||||
# gitflow creates an annotated tag so the user will be prompted to
|
||||
# enter one. There is no way around that unless we perform the
|
||||
# steps ourselves rather than use gitflow.
|
||||
git flow release start $VERSION
|
||||
|
||||
# While we could have converted the Modulefile while checking for
|
||||
# the version, we wait until starting the release for so that we
|
||||
# can include the commit for it as part of the release.
|
||||
if [[ -f "Modulefile" ]] && [[ ! -f "metadata.json" ]]
|
||||
then
|
||||
echo "Modulefile is deprecated. Will attempt to convert it to metadata.json"
|
||||
convert_modulefile
|
||||
fi
|
||||
|
||||
update_metadata $VERSION
|
||||
git flow release finish $VERSION
|
||||
}
|
||||
|
||||
push_changes () {
|
||||
local BRANCH=${1:-"master"}
|
||||
|
||||
if [[ $(commits_ahead $(get_remote_name ${BRANCH})/${BRANCH} ${BRANCH}) -ne 0 ]]
|
||||
then
|
||||
yes_no_prompt "Push branch '${BRANCH}' to '$(get_remote_name ${BRANCH})' [y/N] " "git_push ${BRANCH}" true
|
||||
else
|
||||
echo "No changes to push for branch '${BRANCH}'"
|
||||
fi
|
||||
|
||||
}
|
||||
verify_changes () {
|
||||
local BRANCH=${1:-"master"}
|
||||
|
||||
if [[ $(commits_ahead $(get_remote_name ${BRANCH})/${BRANCH} ${BRANCH}) -ne 0 ]]
|
||||
then
|
||||
yes_no_prompt "Show commits to be pushed for '${BRANCH}'? [y/N] " "show_commits_to_be_pushed ${BRANCH}" true
|
||||
yes_no_prompt "Show diff for '${BRANCH}'? [y/N] " "show_diff ${BRANCH}" true
|
||||
else
|
||||
echo "Local and remote branch '${BRANCH}' are the same"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
### Preparation
|
||||
GIT_DIR=${1:-$(pwd)}
|
||||
cd $GIT_DIR
|
||||
if ! $(is_inside_work_tree)
|
||||
then
|
||||
echo "Error: ${GIT_DIR} is not a git repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for BRANCH in "develop" "master"
|
||||
do
|
||||
if [[ $(commits_ahead $(get_remote_name ${BRANCH})/${BRANCH} ${BRANCH}) -ne 0 ]]
|
||||
then
|
||||
echo "Error: Your local branch '${BRANCH}' is ahead of the remote branch"
|
||||
echo "It's not possible to perform a release."
|
||||
echo "I recommend creating a new branch, resetting to the remote branch and trying again:"
|
||||
echo " git checkout -b ${BRANCH}_ahead"
|
||||
echo " git checkout ${BRANCH}"
|
||||
echo " git reset --hard $(get_remote_name ${BRANCH})/${BRANCH}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if ! $(is_gitflow_installed)
|
||||
then
|
||||
echo "Error: Gitflow is required. It can be obtained from:"
|
||||
echo "https://github.com/nvie/gitflow"
|
||||
exit 1
|
||||
fi
|
||||
ensure_git_flow_enabled
|
||||
|
||||
git fetch > /dev/null
|
||||
for BRANCH in "develop" "master"
|
||||
do
|
||||
echo "Preparing ${BRANCH} for release:"
|
||||
git checkout -q ${BRANCH}
|
||||
# It's more efficient to only pull the branch if there are changes
|
||||
# but it doesn't hurt to explicitly pull either...just to be sure
|
||||
# we don't have any issues when pushing to Gerrit
|
||||
git pull --rebase
|
||||
echo
|
||||
done
|
||||
|
||||
if [[ $(commits_ahead master develop) -eq 0 ]]
|
||||
then
|
||||
echo "Nothing to merge to master for ${GIT_DIR}"
|
||||
echo "Current version is $(show_current_release)"
|
||||
send_version_to_clipboard $(get_git_release)
|
||||
exit 2
|
||||
fi
|
||||
|
||||
### End Preparation
|
||||
|
||||
### Before release to master
|
||||
# Exploit BASH's global variables so that the VERSION that is obtained
|
||||
# in the function is available outside of the function. Hence, no
|
||||
# explicit assignment to a variable here. If we did assign to a
|
||||
# variable, we wouldn't be able to echo the current version.
|
||||
prompt_release_version
|
||||
send_version_to_clipboard ${VERSION}
|
||||
gitflow_release ${VERSION}
|
||||
|
||||
### Give user a chance to see what will change before making any
|
||||
### changes on the remote server
|
||||
for BRANCH in "develop" "master"
|
||||
do
|
||||
git checkout -q ${BRANCH}
|
||||
ensure_change_id
|
||||
verify_changes ${BRANCH}
|
||||
done
|
||||
|
||||
### Now we're ready to push the changes
|
||||
for BRANCH in "develop" "master"
|
||||
do
|
||||
push_changes ${BRANCH}
|
||||
done
|
||||
|
||||
yes_no_prompt "Push tag '${VERSION}' to '$(get_remote_name master)' [y/N] " "git_push_tag ${VERSION}" true
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user