#!/usr/bin/env bash
# Merges the current branch into master and tags a release. Run
# deploy/prepare-release.sh on this branch first - this script does not
# build anything itself, it only bumps VERSION, merges, tags, and pushes.
set -euo pipefail

if [ $# -ne 1 ]; then
    echo "Usage: deploy/publish-release.sh <version>   e.g. deploy/publish-release.sh 1.1.0" >&2
    exit 1
fi

VERSION="$1"
cd "$(dirname "$0")/.."

if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    echo "Version must be plain SemVer (MAJOR.MINOR.PATCH), got: $VERSION" >&2
    exit 1
fi

CURRENT_BRANCH="$(git branch --show-current)"

if [ "$CURRENT_BRANCH" = "master" ]; then
    echo "Run this from the branch you want to release (e.g. develop), not from master itself." >&2
    exit 1
fi

# CHANGELOG.md's top entry must already exist as "## [$VERSION] —
# Unreleased" (this project's standing habit: start that section as
# soon as work begins, not just before a release) - stamping today's
# date here removes the one manual step that kept getting forgotten
# (an already-released version sitting there still labeled
# "Unreleased" until someone noticed). Checked before touching
# anything, so a failure here leaves a completely clean working tree.
if ! grep -q "^## \[$VERSION\] — Unreleased\$" CHANGELOG.md; then
    echo "CHANGELOG.md has no '## [$VERSION] — Unreleased' heading to stamp - add one before publishing." >&2
    exit 1
fi

echo "==> Bumping VERSION to $VERSION on $CURRENT_BRANCH..."
echo "$VERSION" > VERSION

DATE="$(date +%Y-%m-%d)"
sed -i "s/^## \[$VERSION\] — Unreleased\$/## [$VERSION] — $DATE/" CHANGELOG.md
sed -i "s/^\*\*Current version: [0-9]\+\.[0-9]\+\.[0-9]\+\*\*/**Current version: $VERSION**/" README.md

git add VERSION CHANGELOG.md README.md
git commit -m "Release v$VERSION" --allow-empty

# Push the version-bump commit back to its own branch immediately -
# otherwise it only ever exists locally and inside the master merge
# below, leaving origin/$CURRENT_BRANCH permanently stuck behind by
# however many commits this release added (a real gap that shipped
# once: origin/develop sat 5 commits behind origin/master because this
# push was simply missing).
echo "==> Pushing $CURRENT_BRANCH..."
git push origin "$CURRENT_BRANCH"

# Merge into master via a scratch worktree instead of `git checkout
# master` in this working directory - this repo's checked-out branch
# never changes, even transiently, and a failure here (bad merge,
# push rejected, etc.) can never strand you on master.
echo "==> Merging $CURRENT_BRANCH into master (in a scratch worktree)..."
git worktree prune
git fetch origin master:master
WORKTREE_DIR="$(mktemp -d)"
git worktree add --quiet "$WORKTREE_DIR" master

cleanup() {
    git worktree remove "$WORKTREE_DIR" --force >/dev/null 2>&1 || true
}
trap cleanup EXIT

(
    cd "$WORKTREE_DIR"
    git merge --no-ff "$CURRENT_BRANCH" -m "Merge $CURRENT_BRANCH into master for v$VERSION"
    echo "==> Tagging v$VERSION..."
    git tag -a "v$VERSION" -m "v$VERSION"
    echo "==> Pushing master and the tag..."
    git push origin master
    git push origin "v$VERSION"
)

cat <<EOF

Done. master is now at v$VERSION and pushed.

Tonight's 2am cron on the server (deploy/update.php) will pick this up
on its own. To deploy right now instead of waiting, visit or trigger
deploy/update.php on the server directly.
EOF
