#!/bin/bash
#
# ci/scripts/shipit
#
# Script for generating Github release / tag assets
# and managing release notes for a BOSH Release pipeline
#
# author:  James Hunt <james@niftylogic.com>
# created: 2016-03-30

set -eu

header() {
	echo
	echo "###############################################"
	echo
	echo "$*"
	echo
}

: "${REPO_ROOT:?required}" # Contains the Git repo
: "${RELEASE_ROOT:?required}" # Contains any information that is passed on to subsequent steps, e.g. GitHub publish
: "${REPO_OUT:?required}" # Resulting repo state for subsequent steps
: "${BRANCH:?required}" # The branch name, from which to build the release
: "${GITHUB_OWNER:?required}" # The github organization / owner of the repo
: "${GIT_USER_NAME:?required}" # The user name for GIT commits is mandatory. This should be a user that is allowed to push to master.
: "${GIT_USER_EMAIL:?required}" # The e-mail address for GIT commits is mandatory. This should be a user that is allowed to push to master.
: "${VERSION_FROM:?required}" # The path to the Version file
: "${GCP_SERVICE_KEY:?required}" # The GCP service key for accessing the blobstore, written to a temporary private.yml.

if [[ ! -f "${VERSION_FROM}" ]]; then
  echo >&2 "Version file (${VERSION_FROM}) not found.  Did you misconfigure Concourse?"
  exit 2
fi
VERSION_TO_CREATE=$(cat "${VERSION_FROM}")
if [[ -z "${VERSION_TO_CREATE}" ]]; then
  echo >&2 "Version file (${VERSION_FROM}) was empty.  Did you misconfigure Concourse?"
  exit 2
fi

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

###############################################################

cd "${REPO_ROOT}"
RELEASE_NAME=$(bosh int config/final.yml --path /name)

# YAML needs to be indented. The GCP service key is a multiline YAML and needs to be indented uniformly.
# Bash does not allow variables in a sequence literal. $PAD is a 6 spaces indent.
PAD=$(printf ' %.0s' {1..6})
PADDED_GCP_SERVICE_KEY=$(sed -E 's/^(.*)$/'"${PAD}"'\1/g' <<<"${GCP_SERVICE_KEY}")

cat > config/private.yml <<YAML
---
blobstore:
  options:
    credentials_source: static
    json_key: |
${PADDED_GCP_SERVICE_KEY}
YAML

header "Pulling in any git submodules..."
git submodule update --init --recursive --force
cd -

version() {
  # extract the version variable $1 from the packaging script $2 (default 'haproxy')
  pattern='s/VERSION=(.*)(\s?#.*)/\1/p'
  package=${2:-haproxy}
  # extract version and remove all spaces
  sed -n -E "${pattern//VERSION/${1:?}}" "${REPO_ROOT}/packages/${package}/packaging" | sed 's/ *//g'
}

HAPROXY_VERSION=$(version HAPROXY_VERSION)
LUA_VERSION=$(version LUA_VERSION)
SOCAT_VERSION=$(version SOCAT_VERSION)
PCRE_VERSION=$(version PCRE_VERSION)
KEEPALIVED_VERSION=$(version KEEPALIVED_VERSION keepalived)

VERSION="${VERSION_TO_CREATE}+${HAPROXY_VERSION}"

cd "${REPO_ROOT}"
header "Create final release..."
bosh -n create-release --final --version "${VERSION}"
bosh -n create-release "releases/${RELEASE_NAME}/${RELEASE_NAME}-${VERSION}.yml" \
              --tarball "releases/${RELEASE_NAME}/${RELEASE_NAME}-${VERSION}.tgz"
cd -

# SC2155 discourages variable assignment and export in the same line.
RELEASE_TGZ=${REPO_ROOT}/releases/${RELEASE_NAME}/${RELEASE_NAME}-${VERSION}.tgz
# shellcheck disable=SC2155
export SHA1=$(sha1sum "${RELEASE_TGZ}" | head -n1 | awk '{print $1}')
echo "SHA1=${SHA1}"
# shellcheck disable=SC2155
export SHA256=$(sha256sum "${RELEASE_TGZ}" | head -n1 | awk '{print $1}')
echo "SHA256=${SHA256}"



mkdir -p "${RELEASE_ROOT}/artifacts"
echo "v${VERSION}"                            > "${RELEASE_ROOT}/tag"
echo "v${VERSION}"                            > "${RELEASE_ROOT}/name"
mv "${REPO_ROOT}"/releases/*/*-"${VERSION}".tgz "${RELEASE_ROOT}/artifacts"

cat >> "${RELEASE_ROOT}/notes.md" <<EOF
# haproxy-boshrelease ${VERSION}

## Fixes
<!--
- fix a (@personA)
- fix b (@personB)
//-->

## New Features
<!--
- feature a (@personA)
- feature b (@personB)
//-->

## Upgrades
<!--
- `component` has been upgraded from v1.0.0 to v1.2.3
//-->

### Versions

The following versions of upstream components are included in this haproxy-boshrelease:

| Component   | Version |
| ----------- | ------- |
| HAProxy     | \`${HAPROXY_VERSION}\` |
| keepalived  | \`${KEEPALIVED_VERSION}\` |
| Lua         | \`${LUA_VERSION}\` |
| PCRE        | \`${PCRE_VERSION}\` |
| socat       | \`${SOCAT_VERSION}\` |

### Deployment
\`\`\`yaml
releases:
- name: "${RELEASE_NAME}"
  version: "${VERSION}"
  url: "https://github.com/${GITHUB_OWNER}/${RELEASE_NAME}-boshrelease/releases/download/v${VERSION}/${RELEASE_NAME}-${VERSION}.tgz"
  sha1: "${SHA1}"

# for deployments with sha256, use the following line instead:
# sha1: "sha256:${SHA256}"
\`\`\`
EOF

cat > "${RELEASE_ROOT}/notification" <<EOF
<!here> New ${RELEASE_NAME} v${VERSION} released!
EOF

header "Update git repo with final release..."
if [[ -z $(git config --global user.email) ]]; then
  git config --global user.email "$GIT_USER_EMAIL"
fi
if [[ -z $(git config --global user.name) ]]; then
  git config --global user.name "$GIT_USER_NAME"
fi

pushd "${REPO_ROOT}"
  for MANIFEST_PATH in manifests/*.yml; do
    "${DIR}/update-manifest" "${GITHUB_OWNER}" "${RELEASE_NAME}" "${VERSION}" "${SHA1}" "${MANIFEST_PATH}"
  done
  git merge --no-edit "${BRANCH}"
  git add -A
  git status
  git commit -m "release v${VERSION}"

  # After creating a final release we will also create a dev release patches from haproxy-patches directory
  echo "- haproxy/patches.tar.gz" >> packages/haproxy/spec
  tar -czvf haproxy-patches.tar.gz haproxy-patches
  bosh add-blob haproxy-patches.tar.gz haproxy/patches.tar.gz
  bosh upload-blobs

  bosh -n create-release --force --version "${VERSION}-patched" \
    --tarball "../${RELEASE_NAME}-${VERSION}-patched.tgz"

  # Undo changes to repo from creating dev release
  git clean -df
  git reset --hard
popd

mkdir -p "${RELEASE_ROOT}/artifacts-patched"
mv "${RELEASE_NAME}-${VERSION}-patched.tgz" "${RELEASE_ROOT}/artifacts-patched"

PATCHED_RELEASE_TGZ=${RELEASE_ROOT}/artifacts-patched/${RELEASE_NAME}-${VERSION}-patched.tgz
# shellcheck disable=SC2155
export PATCHED_SHA1=$(sha1sum "${PATCHED_RELEASE_TGZ}" | head -n1 | awk '{print $1}')
echo "PATCHED_SHA1=${PATCHED_SHA1}"
# shellcheck disable=SC2155
export PATCHED_SHA256=$(sha256sum "${PATCHED_RELEASE_TGZ}" | head -n1 | awk '{print $1}')
echo "PATCHED_SHA256=${PATCHED_SHA256}"

cat >> "${RELEASE_ROOT}/notes.md" <<EOF

### Deployment (patched)
\`\`\`yaml
releases:
- name: "${RELEASE_NAME}"
  version: "${VERSION}-patched"
  url: "https://github.com/${GITHUB_OWNER}/${RELEASE_NAME}-boshrelease/releases/download/v${VERSION}/${RELEASE_NAME}-${VERSION}-patched.tgz"
  sha1: "${PATCHED_SHA1}"

# for deployments with sha256, use the following line instead:
# sha1: "sha256:${PATCHED_SHA256}"
\`\`\`
EOF

# so that future steps in the pipeline can push our changes
cp -a "${REPO_ROOT}" "${REPO_OUT}"

cat > "${NOTIFICATION_OUT:-notifications}/message" <<EOS
New ${RELEASE_NAME} v${VERSION} release draft created. Please complete the <https://github.com/${GITHUB_OWNER}/${RELEASE_NAME}-boshrelease/releases/tag/v${VERSION}|Release notes> in GitHub and finalize the release.
EOS
