#! /bin/bash set -e SUDO=${SUDO-sudo} GITHUB_USER=${GITHUB_USER:-weaveworks} DOCKERHUB_USER=${DOCKERHUB_USER:-weaveworks} RELEASE_NAME=${RELEASE_NAME:-"Weave Scope"} RELEASE_DESCRIPTION=${RELEASE_DESCRIPTION:-"Container Visibility"} PWD=$(pwd) infer_release_type() { if echo "$1" | grep -qE '^v[0-9]+\.[0-9]+\.0+$'; then echo MAINLINE elif echo "$1" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then echo BRANCH else echo PRERELEASE fi } setup() { # Ensure we have exactly one annotated tag pointing at HEAD HEAD_TAGS=$(git tag --points-at HEAD) # shellcheck disable=SC2116 # shellcheck disable=SC2005 TAG_COUNT=$(echo "$(echo "$HEAD_TAGS" | wc -w)") # mac hack if [ "$TAG_COUNT" -eq 1 ]; then if [ "$HEAD_TAGS" != "latest_release" ]; then LATEST_TAG=$HEAD_TAGS else echo "Cannot determine version - latest_release points at HEAD" >&2 exit 1 fi elif [ "$TAG_COUNT" -eq 0 ]; then echo "Cannot determine version - no tags point at HEAD" >&2 exit 1 else echo "Cannot determine version - multiple tags point at HEAD:" >&2 for TAG in $HEAD_TAGS; do echo -e "\t$TAG" >&2 done exit 1 fi RELEASE_TYPE=$(infer_release_type "$LATEST_TAG") echo "== Inferred release type $RELEASE_TYPE from tag $LATEST_TAG" LATEST_TAG_SHA=$(git rev-parse "$LATEST_TAG") LATEST_TAG_COMMIT_SHA=$(git rev-list -1 "$LATEST_TAG") LATEST_RELEASE_SHA=$(git rev-parse latest_release) LATEST_RELEASE_COMMIT_SHA=$(git rev-list -1 latest_release) if [ "$RELEASE_TYPE" != 'PRERELEASE' ]; then VERSION=${LATEST_TAG#v} else VERSION=${LATEST_TAG} fi # NB does not check that this tag is on master RELEASE_DIR=./releases/$LATEST_TAG } build() { setup echo "== Clone repo at $LATEST_TAG for version $VERSION" if [ -d "$RELEASE_DIR" ]; then echo -e "\u2757 Release directory $RELEASE_DIR already exists, you may want to" >&2 echo -e "\trm -rf $RELEASE_DIR" >&2 exit 1 fi ## Clone the repo at the tag and go there mkdir -p releases git clone -q -b "$LATEST_TAG" . "$RELEASE_DIR" 2>/dev/null cd "$RELEASE_DIR" ## Check that the top changelog entry is this version if ! latest_changelog=$(perl -nle'print $& if m{(?<=^## Release ).*}' ./CHANGELOG.md | head -1) \ || ! [ "$latest_changelog" = "$VERSION" ]; then echo -e "\u2757 Latest changelog entry \"$latest_changelog\" does not match the release version $VERSION" >&2 exit 1 fi echo echo "== Build and test" ## Inject the version numbers and build the distributables ## (library versions?) sed -i.tmp "s/SCRIPT_VERSION=\"[^\"]*\"/SCRIPT_VERSION=\"$VERSION\"/" ./scope make SUDO="$SUDO" SCOPE_VERSION="$VERSION" DOCKERHUB_USER="$DOCKERHUB_USER" realclean all if make tests SUDO="$SUDO"; then echo -e '\u2713 Tests pass' else echo -e "\u2757 Tests failed, probably best not publish this one" >&2 exit 1 fi ## Run tests with the distributables, including version check #v=$(./scope version | grep -o '[0-9].*') #if ! [ "$v" == "$VERSION" ]; then # echo "Version of distributable "$v" does not match release version $VERSION" >&2 # exit 1 #fi echo -e '\u2713 Build OK' echo '** Release artefacts in' "$RELEASE_DIR" } draft() { setup cd "$PWD"/"$RELEASE_DIR" echo "== Sanity checks" ## Check that the tag exists by looking at github if ! curl -sSf "https://api.github.com/repos/$GITHUB_USER/scope/git/tags/$LATEST_TAG_SHA" >/dev/null 2>&1; then echo -e "\u2757 Tag $LATEST_TAG is not on GitHub, or is not the same as the local tag" >&2 echo -e "\thttps://github.com/$GITHUB_USER/scope/tags" >&2 echo "You may need to" >&2 echo -e "\tgit push git@github.com:$GITHUB_USER/scope $LATEST_TAG" exit 1 fi echo -e "\u2713 Tag $LATEST_TAG exists in GitHub repo $GITHUB_USER/scope" ## Check that the version does not already exist by looking at github ## releases if github-release info --user "$GITHUB_USER" --repo scope --tag "$LATEST_TAG" >/dev/null 2>&1; then echo -e "\u2757 Release $LATEST_TAG already exists on GitHub" >&2 echo -e "\thttps://github.com/$GITHUB_USER/scope/releases/$LATEST_TAG" >&2 exit 1 fi echo '** Sanity checks OK for publishing tag' "$LATEST_TAG" as "$DOCKERHUB_USER/scope:$VERSION" RELEASE_ARGS="--draft" if [ "$RELEASE_TYPE" = 'PRERELEASE' ]; then RELEASE_ARGS="$RELEASE_ARGS --pre-release" fi echo "== Creating GitHub release $RELEASE_ARGS $RELEASE_NAME $VERSION" github-release release "$RELEASE_ARGS" \ --user "$GITHUB_USER" \ --repo scope \ --tag "$LATEST_TAG" \ --name "$RELEASE_NAME $VERSION" \ --description "$RELEASE_DESCRIPTION" github-release upload \ --user "$GITHUB_USER" \ --repo scope \ --tag "$LATEST_TAG" \ --name "scope" \ --file "./scope" echo "** Draft $TYPE $RELEASE_NAME $VERSION created at" echo -e "\thttps://github.com/$GITHUB_USER/scope/releases/$LATEST_TAG" } publish() { setup cd "$PWD"/"$RELEASE_DIR" if [ "$RELEASE_TYPE" = 'PRERELEASE' ]; then push_images echo "== Publishing pre-release on GitHub" github-release publish \ --user "$GITHUB_USER" \ --repo scope \ --tag "$LATEST_TAG" echo "** Pre-release $RELEASE_NAME $VERSION published at" echo -e "\thttps://github.com/$GITHUB_USER/scope/releases/$LATEST_TAG" else echo "== Sanity checks" if ! [ "$LATEST_TAG_COMMIT_SHA" == "$LATEST_RELEASE_COMMIT_SHA" ]; then echo -e "\u2757 The tag latest_release does not point to the same commit as $LATEST_TAG" >&2 echo "You may need to" >&2 echo -e "\tgit tag -af latest_release $LATEST_TAG" >&2 exit 1 fi ## Check that the 'latest_release' tag exists by looking at github if ! curl -sSf "https://api.github.com/repos/$GITHUB_USER/scope/git/tags/$LATEST_RELEASE_SHA" >/dev/null 2>&1; then echo -e "\u2757 Tag latest_release is not on GitHub, or is not the same as the local tag" >&2 echo -e "\thttps://github.com/$GITHUB_USER/scope/tags" >&2 echo "You may need to" >&2 echo -e "\tgit push -f git@github.com:$GITHUB_USER/scope latest_release" >&2 exit 1 fi echo '** Sanity checks OK for publishing tag' "$LATEST_TAG" as "$DOCKERHUB_USER/scope:$VERSION" push_images echo "== Publishing release on GitHub" github-release publish \ --user "$GITHUB_USER" \ --repo scope \ --tag "$LATEST_TAG" if github-release info --user "$GITHUB_USER" --repo scope \ --tag latest_release >/dev/null 2>&1; then github-release delete \ --user "$GITHUB_USER" \ --repo scope \ --tag latest_release fi github-release release \ --user "$GITHUB_USER" \ --repo scope \ --tag latest_release \ --name "$RELEASE_NAME latest ($VERSION)" \ --description "[Release Notes](https://github.com/$GITHUB_USER/scope/releases/$LATEST_TAG)" github-release upload \ --user "$GITHUB_USER" \ --repo scope \ --tag latest_release \ --name "scope" \ --file "./scope" echo "** Release $RELEASE_NAME $VERSION published at" echo -e "\thttps://github.com/$GITHUB_USER/scope/releases/$LATEST_TAG" echo -e "\thttps://github.com/$GITHUB_USER/scope/releases/latest_release" fi } push_images() { echo "== Tagging and pushing images on docker hub and quay.io as user $DOCKERHUB_USER" for IMAGE in "scope" "cloud-agent"; do $SUDO docker tag "$DOCKERHUB_USER/$IMAGE" "$DOCKERHUB_USER/$IMAGE:$VERSION" $SUDO docker push "$DOCKERHUB_USER/$IMAGE:$VERSION" $SUDO docker tag "$DOCKERHUB_USER/$IMAGE:$VERSION" "$DOCKERHUB_USER/$IMAGE:latest_release" $SUDO docker push "$DOCKERHUB_USER/$IMAGE:latest_release" $SUDO docker tag "$DOCKERHUB_USER/$IMAGE:$VERSION" "quay.io/$DOCKERHUB_USER/$IMAGE:$VERSION" $SUDO docker push "quay.io/$DOCKERHUB_USER/$IMAGE:$VERSION" done echo "** Docker images tagged and pushed" } usage() { echo "Usage:" echo -e "\t./bin/release build" echo "-- Build artefacts for the latest version tag" echo -e "\t./bin/release draft" echo "-- Create draft release with artefacts in GitHub" echo -e "\t./bin/release publish" echo "-- Publish the GitHub release and update DockerHub" exit 1 } # Ensure required tooling is installed if ! which github-release >/dev/null; then echo "Please install git-release:" >&2 echo -e "\tgo get github.com/weaveworks/github-release" >&2 echo "and create a git token per https://github.com/weaveworks/github-release" >&2 exit 1 fi [ $# -eq 0 ] && usage COMMAND=$1 shift case "$COMMAND" in build) build "$@" ;; draft) draft "$@" ;; publish) publish "$@" ;; *) echo "Unknown command \"$COMMAND\"" usage ;; esac