Created
August 13, 2018 22:30
-
-
Save matthewadams/de8b213bb18dac8a09e12269ab2102c9 to your computer and use it in GitHub Desktop.
release-docker-image-on-codefresh.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# This script implements the release branch workflow for docker images built by codefresh.io. | |
# | |
# Requirements: | |
# git | |
# docker | |
# TODO: port this from bash to plain ol' sh (regex matching needs to be ported) | |
usage() { | |
cat<<EOF | |
usage: | |
if on master branch: release pre|rc <chart> | |
if on release branch: release major|minor|patch|pre <chart> | |
where: | |
<chart> is the name of the chart | |
EOF | |
} | |
if [ -n "$TEST" ]; then ECHO=echo; fi | |
if [ -n "$DBG" ]; then set -x; fi | |
ORIGIN=${ORIGIN:-origin} | |
MASTER=${MASTER:-master} | |
RELEASE_LEVEL="$1" | |
case "$RELEASE_LEVEL" in | |
major|minor|patch|pre|rc) | |
# ok | |
;; | |
h|he|hel|help) | |
usage | |
exit 0 | |
;; | |
*) | |
echo "ERROR: Specify release level of 'pre', 'patch', 'minor', 'major', or 'rc'" >&2 | |
usage | |
exit 1 | |
;; | |
esac | |
CODEFRESH_YML=${CODEFRESH_YML:-codefresh.yml} | |
DOCKER_BUILD_STEP_NAME=${DOCKER_BUILD_STEP_NAME:-BuildingDockerImage} | |
DOCKER_PUSH_STEP_NAME=${DOCKER_PUSH_STEP_NAME:-PushingToDockerRegistry} | |
git pull > /dev/null 2>&1 | |
if ! git diff --exit-code --no-patch > /dev/null 2>&1; then | |
echo 'ERROR: You have modified tracked files; only release from clean directories!' >&2 | |
exit 3 | |
fi | |
if ! git diff --cached --exit-code --no-patch > /dev/null 2>&1; then | |
echo 'ERROR: You have cached modified tracked files; only release from clean directories!' >&2 | |
exit 3 | |
fi | |
if [ -n "$(git status -s)" ]; then | |
echo 'ERROR: You have unignored untracked files; only release from clean directories!' >&2 | |
exit 3 | |
fi | |
VERSION="$(cat "$CODEFRESH_YML" | docker run --rm -i matthewadams12/ymlx "this.steps['$DOCKER_PUSH_STEP_NAME'].tag")" | |
if [[ ! "$VERSION" =~ \-(pre|rc)\.[0-9]{1,}$ ]]; then | |
echo 'ERROR: repository is in an inconsistent state: version does NOT end in a prerelease suffix!' >&2 | |
exit 3 | |
fi | |
BRANCH="$(git status | head -n 1 | awk '{ print $3 }')" | |
if [[ ! "$BRANCH" =~ ^(master|v[0-9]{1,}\.[0-9]{1,})$ ]]; then # it is not a master or a release branch | |
echo 'ERROR: You can only release from the master branch or release branches (vmajor.minor)!' >&2 | |
exit 3 | |
fi | |
if ! git diff --exit-code -no-patch $BRANCH $ORIGIN/$BRANCH > /dev/null 2>&1; then | |
echo "ERROR: Local branch $BRANCH differs from remote branch $ORIGIN/$BRANCH" >&2 | |
exit 3 | |
fi | |
if [ "$BRANCH" == "$MASTER" ]; then | |
case "$RELEASE_LEVEL" in | |
pre|rc) | |
# ok | |
;; | |
*) | |
echo "ERROR: Only 'pre' or 'rc' releases are permitted from the $MASTER branch." >&2 | |
exit 6 | |
;; | |
esac | |
else # this is a release branch | |
case "$RELEASE_LEVEL" in | |
rc|patch|minor|major) | |
# ok | |
;; | |
*) | |
echo "ERROR: Only 'pre', 'patch', 'minor', or 'major' releases are permitted from a release branch." >&2 | |
exit 7 | |
;; | |
esac | |
fi | |
if [ "$BRANCH" == "$MASTER" ]; then | |
if [[ ! "$VERSION" =~ ^([0-9]{1,})\.([0-9]{1,})\.0\-pre\.([0-9]{1,})$ ]]; then | |
echo "ERROR: The version does not match the format of major.minor.0-pre.n required in the $MASTER branch." >&2 | |
exit 8 | |
fi | |
# create release branch | |
MAJOR=${BASH_REMATCH[1]} | |
MINOR=${BASH_REMATCH[2]} | |
PATCH=0 | |
PRE=${BASH_REMATCH[3]} | |
case "$RELEASE_LEVEL" in | |
rc) # then it's time to create a new release branch | |
NEW_RELEASE_BRANCH="v$MAJOR.$MINOR" | |
git checkout -b $NEW_RELEASE_BRANCH > /dev/null 2>&1 | |
NEW_RELEASE_BRANCH_VERSION="$MAJOR.$MINOR.0-rc.0" | |
CODEFRESH_YML_CONTENT="$(cat "$CODEFRESH_YML")" | |
echo -n "$CODEFRESH_YML_CONTENT" \ | |
| docker run --rm -i matthewadams12/ymlx "it => { it.steps['$DOCKER_PUSH_STEP_NAME'].tag = '$NEW_RELEASE_BRANCH_VERSION'; return it; }" \ | |
> "$CODEFRESH_YML" | |
git add . > /dev/null 2>&1 | |
git commit -m "release $NEW_RELEASE_BRANCH_VERSION" > /dev/null 2>&1 | |
git tag $NEW_RELEASE_BRANCH_VERSION > /dev/null 2>&1 | |
git push -u $ORIGIN $NEW_RELEASE_BRANCH > /dev/null 2>&1 | |
git push --tags > /dev/null 2>&1 | |
# return to master branch | |
git checkout $MASTER > /dev/null 2>&1 | |
git cherry-pick $NEW_RELEASE_BRANCH > /dev/null 2>&1 # cherry pick from release branch to get release candidate commit in master | |
# advance master version | |
NEXT_VERSION="$MAJOR.$(($MINOR+1)).0-pre.0" | |
CODEFRESH_YML_CONTENT="$(cat "$CODEFRESH_YML")" | |
echo -n "$CODEFRESH_YML_CONTENT" \ | |
| docker run --rm -i matthewadams12/ymlx "it => { it.steps['$DOCKER_PUSH_STEP_NAME'].tag = '$NEXT_VERSION'; return it; }" \ | |
> "$CODEFRESH_YML" | |
git add . > /dev/null 2>&1 | |
git commit -m "bump to $NEXT_VERSION [skip ci]" > /dev/null 2>&1 | |
git push > /dev/null 2>&1 | |
# return to release branch & prepare for next prerelease | |
git checkout $NEW_RELEASE_BRANCH > /dev/null 2>&1 | |
NEXT_RELEASE_BRANCH_VERSION="$MAJOR.$MINOR.0-rc.1" | |
CODEFRESH_YML_CONTENT="$(cat "$CODEFRESH_YML")" | |
echo -n "$CODEFRESH_YML_CONTENT" \ | |
| docker run --rm -i matthewadams12/ymlx "it => { it.steps['$DOCKER_PUSH_STEP_NAME'].tag = '$NEXT_RELEASE_BRANCH_VERSION'; return it; }" \ | |
> "$CODEFRESH_YML" | |
git add . > /dev/null 2>&1 | |
git commit -m "bump to $NEXT_RELEASE_BRANCH_VERSION [skip ci]" > /dev/null 2>&1 | |
git push > /dev/null 2>&1 | |
echo "created release branch $NEW_RELEASE_BRANCH and tagged $NEW_RELEASE_BRANCH_VERSION for release" | |
exit 0 | |
;; | |
pre) | |
git tag "v$VERSION" > /dev/null 2>&1 | |
RELEASED_VERSION="$VERSION" | |
NEXT_VERSION=$MAJOR.$MINOR.$PATCH-pre.$((PRE+1)) | |
CODEFRESH_YML_CONTENT="$(cat "$CODEFRESH_YML")" | |
echo -n "$CODEFRESH_YML_CONTENT" \ | |
| docker run --rm -i matthewadams12/ymlx "it => { it.steps['$DOCKER_PUSH_STEP_NAME'].tag = '$NEXT_VERSION'; return it; }" \ | |
> "$CODEFRESH_YML" | |
git add . > /dev/null 2>&1 | |
git commit -m "bump to $NEXT_VERSION [skip ci]" > /dev/null 2>&1 | |
git push > /dev/null 2>&1 | |
git push --tags > /dev/null 2>&1 | |
echo "tagged $RELEASED_VERSION for release" | |
exit 0 | |
;; | |
esac | |
fi | |
# If we get this far, we are releasing something from a release branch. | |
if [[ ! "$VERSION" =~ ^([0-9]{1,})\.([0-9]{1,})\.([0-9]{1,})\-rc\.([0-9]{1,})$ ]]; then | |
echo "ERROR: The version does not match the format of major.minor.patch-rc.n required in the release branch." >&2 | |
exit 8 | |
fi | |
MAJOR=${BASH_REMATCH[1]} | |
MINOR=${BASH_REMATCH[2]} | |
PATCH=${BASH_REMATCH[3]} | |
PRE=${BASH_REMATCH[4]} | |
case "$RELEASE_LEVEL" in | |
major|minor|patch) | |
# NOTE: if RELEASE_LEVEL is 'minor' & we're prepped for a major release, no harm, no foul. | |
# A major release is the same as a minor release, only that the minor version is 0. | |
if [ $RELEASE_LEVEL == major ] && [ $MINOR != 0 ]; then | |
echo "ERROR: This branch is not prepared for a major release because the minor version is $MINOR, not 0." >&2 | |
exit 10 | |
else | |
NEXT_RELEASE_BRANCH_VERSION="$MAJOR.$MINOR.1-rc.0" | |
fi | |
if [ $RELEASE_LEVEL == minor ] && [ $PATCH != 0 ]; then | |
echo "ERROR: A minor release has already been performed in this release branch; only patch releases are allowed here now." >&2 | |
exit 11 | |
else | |
NEXT_RELEASE_BRANCH_VERSION="$MAJOR.$MINOR.1-rc.0" | |
fi | |
if [ $RELEASE_LEVEL == patch ] && [ $PATCH == 0 ]; then | |
echo "ERROR: You must release a minor release before releasing a patch in this release branch." >&2 | |
exit 12 | |
else | |
NEXT_RELEASE_BRANCH_VERSION="$MAJOR.$MINOR.$((PATCH+1))-rc.0" | |
fi | |
RELEASE_VERSION="$MAJOR.$MINOR.$PATCH" | |
CODEFRESH_YML_CONTENT="$(cat "$CODEFRESH_YML")" | |
echo -n "$CODEFRESH_YML_CONTENT" \ | |
| docker run --rm -i matthewadams12/ymlx "it => { it.steps['$DOCKER_PUSH_STEP_NAME'].tag = '$RELEASE_VERSION'; return it; }" \ | |
> "$CODEFRESH_YML" | |
git add . > /dev/null 2>&1 | |
git commit -m "release $RELEASE_VERSION" > /dev/null 2>&1 | |
git tag "v$RELEASE_VERSION" > /dev/null 2>&1 | |
git push > /dev/null 2>&1 | |
git push --tags > /dev/null 2>&1 | |
CODEFRESH_YML_CONTENT="$(cat "$CODEFRESH_YML")" | |
echo -n "$CODEFRESH_YML_CONTENT" \ | |
| docker run --rm -i matthewadams12/ymlx "it => { it.steps['$DOCKER_PUSH_STEP_NAME'].tag = '$NEXT_RELEASE_BRANCH_VERSION'; return it; }" \ | |
> "$CODEFRESH_YML" | |
git add . > /dev/null 2>&1 | |
git commit -m "bump to $NEXT_RELEASE_BRANCH_VERSION [skip ci]" > /dev/null 2>&1 | |
git push > /dev/null 2>&1 | |
echo "tagged $RELEASE_VERSION" | |
exit 0 | |
;; | |
rc) | |
git tag "v$VERSION" > /dev/null 2>&1 | |
NEXT_RELEASE_BRANCH_VERSION="$MAJOR.$MINOR.$PATCH-rc.$((PRE+1))" | |
CODEFRESH_YML_CONTENT="$(cat "$CODEFRESH_YML")" | |
echo -n "$CODEFRESH_YML_CONTENT" \ | |
| docker run --rm -i matthewadams12/ymlx "it => { it.steps['$DOCKER_PUSH_STEP_NAME'].tag = '$NEXT_RELEASE_BRANCH_VERSION'; return it; }" \ | |
> "$CODEFRESH_YML" | |
git add . > /dev/null 2>&1 | |
git commit -m "bump to $NEXT_RELEASE_BRANCH_VERSION [skip ci]" > /dev/null 2>&1 | |
git push > /dev/null 2>&1 | |
git push --tags > /dev/null 2>&1 | |
echo "tagged v$VERSION" | |
exit 0 | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment