Files
mc-webui/scripts/release.sh
T
MarekWo ed2cf07e73 fix(release): refuse to tag when main has not been pushed
Pushing the tag drags the commit objects to GitHub, so the release page
looks correct while the main branch still points at older code - exactly
what happened on the 2.1.0 release, where origin/main stayed on the
previous merge. The script now fetches origin/main and refuses unless the
local HEAD matches it, naming the push command.

Also spells out what to do when VERSION still carries a -dev suffix,
since the format check alone did not say which way to resolve it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 19:41:39 +02:00

101 lines
3.1 KiB
Bash
Executable File

#!/bin/bash
# Tag the current release and publish it on GitHub.
#
# Run on `main`, after merging `dev`. Reads the release number from VERSION
# and the release notes from the matching docs/whatsnew.md section, so there
# is exactly one place to edit each of them.
#
# ./scripts/release.sh # tag + GitHub release
# ./scripts/release.sh --dry-run # show what would happen, change nothing
set -e
DRY_RUN=false
[ "$1" = "--dry-run" ] && DRY_RUN=true
cd "$(dirname "$0")/.."
info() { echo -e "\033[0;34m[*]\033[0m $1"; }
success() { echo -e "\033[0;32m[+]\033[0m $1"; }
error() { echo -e "\033[0;31m[!]\033[0m $1" >&2; }
VERSION=$(tr -d ' \t\r\n' < VERSION)
TAG="v${VERSION}"
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
error "VERSION must be MAJOR.MINOR.PATCH, got '${VERSION}'"
case "$VERSION" in
*-dev|*-dev*)
error "This is still a development version. Drop the '-dev' suffix"
error "on dev, title the whatsnew section, then merge and release."
;;
esac
exit 1
fi
BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "$BRANCH" != "main" ]; then
error "Releases are cut from main, but you are on '${BRANCH}'"
exit 1
fi
if [ -n "$(git status --porcelain)" ]; then
error "Working tree is dirty - commit or stash first"
exit 1
fi
# The tag alone would drag the commit objects to GitHub, leaving the main
# branch pointing at older code while a release claims otherwise
info "Checking that main is pushed..."
git fetch origin main --quiet
LOCAL_HEAD=$(git rev-parse HEAD)
REMOTE_HEAD=$(git rev-parse origin/main 2>/dev/null || echo "")
if [ "$LOCAL_HEAD" != "$REMOTE_HEAD" ]; then
error "Local main ($(git rev-parse --short HEAD)) does not match origin/main (${REMOTE_HEAD:0:7})"
error "Push it first: git push origin main"
exit 1
fi
if git rev-parse "$TAG" >/dev/null 2>&1; then
error "Tag ${TAG} already exists - bump VERSION before releasing"
exit 1
fi
# Release notes: the whatsnew.md section headed "## <version> - <date>",
# up to the next "## " heading
NOTES=$(awk -v ver="$VERSION" '
$0 ~ "^## " ver "( |$|—)" { found = 1; next }
found && /^## / { exit }
found { print }
' docs/whatsnew.md | sed -e 's/^---$//' | awk 'NF || printed { print; printed = 1 }')
if [ -z "$(echo "$NOTES" | tr -d '[:space:]')" ]; then
error "No release notes for ${VERSION} in docs/whatsnew.md"
error "Expected a section headed: ## ${VERSION} - YYYY-MM-DD"
exit 1
fi
info "Release ${TAG} on $(git rev-parse --short HEAD)"
echo "----------------------------------------"
echo "$NOTES"
echo "----------------------------------------"
if [ "$DRY_RUN" = true ]; then
info "Dry run - no tag created, nothing published"
exit 0
fi
git tag -a "$TAG" -m "mc-webui ${VERSION}"
success "Tagged ${TAG}"
git push origin "$TAG"
success "Pushed ${TAG}"
if command -v gh >/dev/null 2>&1; then
echo "$NOTES" | gh release create "$TAG" --title "mc-webui ${VERSION}" --notes-file -
success "Published GitHub release ${TAG}"
else
info "gh CLI not found - create the release manually at:"
info " https://github.com/MarekWo/mc-webui/releases/new?tag=${TAG}"
fi