171 lines
6.7 KiB
Bash
Executable File
171 lines
6.7 KiB
Bash
Executable File
#!/bin/bash
|
|
# release.sh — build and publish a PhotoPhetch release to Gitea
|
|
#
|
|
# Usage:
|
|
# ./release.sh 1.0.0 "First release with Android and iPhone support"
|
|
# ./release.sh 1.1.0 # prompts for release notes
|
|
#
|
|
# Requires:
|
|
# - curl (built into macOS)
|
|
# - git
|
|
# - ./gradlew (Gradle wrapper in this directory)
|
|
# - GITEA_TOKEN environment variable, or it will prompt
|
|
# Get a token: https://git.bolenpad.com/user/settings/applications
|
|
|
|
set -euo pipefail
|
|
|
|
# ── Config ──────────────────────────────────────────────────────────────────
|
|
GITEA_URL="https://git.bolenpad.com"
|
|
GITEA_USER="kbolen"
|
|
GITEA_REPO="photophetch"
|
|
|
|
# ── Arguments ───────────────────────────────────────────────────────────────
|
|
if [ $# -lt 1 ]; then
|
|
echo "Usage: $0 <version> [release-notes]"
|
|
echo " Example: $0 1.0.0 'First stable release'"
|
|
exit 1
|
|
fi
|
|
|
|
VERSION="$1"
|
|
TAG="v${VERSION}"
|
|
|
|
# Release notes: from argument, or auto-generate from git log
|
|
if [ $# -ge 2 ]; then
|
|
NOTES="$2"
|
|
else
|
|
# Auto-generate from git log since last tag (or all commits if no tags yet)
|
|
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
|
|
if [ -n "$LAST_TAG" ]; then
|
|
RAW_LOG=$(git log "${LAST_TAG}..HEAD" --oneline --no-merges)
|
|
LOG_RANGE="since $LAST_TAG"
|
|
else
|
|
RAW_LOG=$(git log --oneline --no-merges | head -30)
|
|
LOG_RANGE="all commits"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Auto-generated release notes ($LOG_RANGE):"
|
|
echo "──────────────────────────────────────────"
|
|
echo "$RAW_LOG"
|
|
echo "──────────────────────────────────────────"
|
|
echo ""
|
|
echo "Accept these as release notes? [y=yes, e=edit, q=quit]"
|
|
read -r CHOICE
|
|
|
|
case "$CHOICE" in
|
|
y|Y)
|
|
NOTES="$RAW_LOG"
|
|
;;
|
|
e|E)
|
|
TMPFILE=$(mktemp /tmp/photophetch-release-notes.XXXXXX.md)
|
|
echo "$RAW_LOG" > "$TMPFILE"
|
|
${EDITOR:-nano} "$TMPFILE"
|
|
NOTES=$(cat "$TMPFILE")
|
|
rm -f "$TMPFILE"
|
|
;;
|
|
*)
|
|
echo "Aborted."
|
|
exit 1
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# Gitea token
|
|
if [ -z "${GITEA_TOKEN:-}" ]; then
|
|
echo "GITEA_TOKEN not set."
|
|
read -rsp "Enter Gitea API token: " GITEA_TOKEN
|
|
echo
|
|
fi
|
|
|
|
# ── Pre-flight checks ────────────────────────────────────────────────────────
|
|
echo "→ Checking for uncommitted changes..."
|
|
if ! git diff --quiet || ! git diff --cached --quiet; then
|
|
echo "ERROR: Uncommitted changes exist. Commit or stash them first."
|
|
exit 1
|
|
fi
|
|
|
|
echo "→ Checking we're on main..."
|
|
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
if [ "$BRANCH" != "main" ]; then
|
|
echo "ERROR: Not on main branch (currently on '$BRANCH'). Switch to main first."
|
|
exit 1
|
|
fi
|
|
|
|
echo "→ Checking tag $TAG doesn't already exist..."
|
|
if git tag | grep -q "^${TAG}$"; then
|
|
echo "ERROR: Tag $TAG already exists."
|
|
exit 1
|
|
fi
|
|
|
|
# ── Update version in build.gradle.kts ──────────────────────────────────────
|
|
echo "→ Updating version to $VERSION in build.gradle.kts..."
|
|
sed -i.bak "s/packageVersion = \"[^\"]*\"/packageVersion = \"${VERSION}\"/" build.gradle.kts
|
|
rm -f build.gradle.kts.bak
|
|
|
|
# ── Commit version bump ──────────────────────────────────────────────────────
|
|
echo "→ Committing version bump..."
|
|
git add build.gradle.kts
|
|
git commit -m "Bump version to $VERSION"
|
|
|
|
# ── Build DMG ───────────────────────────────────────────────────────────────
|
|
echo "→ Building DMG (this takes a few minutes)..."
|
|
./gradlew packageDmg
|
|
|
|
DMG_PATH=$(find build/compose/binaries/main/dmg -name "*.dmg" | head -1)
|
|
if [ -z "$DMG_PATH" ]; then
|
|
echo "ERROR: No DMG found in build/compose/binaries/main/dmg/"
|
|
exit 1
|
|
fi
|
|
DMG_NAME=$(basename "$DMG_PATH")
|
|
echo "→ Built: $DMG_PATH"
|
|
|
|
# ── Tag and push ─────────────────────────────────────────────────────────────
|
|
echo "→ Creating tag $TAG..."
|
|
git tag -a "$TAG" -m "Release $TAG"
|
|
|
|
echo "→ Pushing commits and tag..."
|
|
git push origin main
|
|
git push origin "$TAG"
|
|
|
|
# ── Create Gitea release ─────────────────────────────────────────────────────
|
|
echo "→ Creating Gitea release $TAG..."
|
|
RELEASE_RESPONSE=$(curl -s -X POST \
|
|
"${GITEA_URL}/api/v1/repos/${GITEA_USER}/${GITEA_REPO}/releases" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"tag_name\": \"${TAG}\",
|
|
\"name\": \"PhotoPhetch ${TAG}\",
|
|
\"body\": \"${NOTES}\",
|
|
\"draft\": false,
|
|
\"prerelease\": false
|
|
}")
|
|
|
|
RELEASE_ID=$(echo "$RELEASE_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])" 2>/dev/null)
|
|
if [ -z "$RELEASE_ID" ]; then
|
|
echo "ERROR: Failed to create release. Response:"
|
|
echo "$RELEASE_RESPONSE"
|
|
exit 1
|
|
fi
|
|
echo "→ Created release ID $RELEASE_ID"
|
|
|
|
# ── Upload DMG ───────────────────────────────────────────────────────────────
|
|
echo "→ Uploading $DMG_NAME..."
|
|
UPLOAD_RESPONSE=$(curl -s -X POST \
|
|
"${GITEA_URL}/api/v1/repos/${GITEA_USER}/${GITEA_REPO}/releases/${RELEASE_ID}/assets?name=${DMG_NAME}" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/octet-stream" \
|
|
--data-binary "@${DMG_PATH}")
|
|
|
|
DOWNLOAD_URL=$(echo "$UPLOAD_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin).get('browser_download_url',''))" 2>/dev/null)
|
|
if [ -z "$DOWNLOAD_URL" ]; then
|
|
echo "WARNING: Upload may have failed. Response:"
|
|
echo "$UPLOAD_RESPONSE"
|
|
else
|
|
echo "✓ Released: $DOWNLOAD_URL"
|
|
fi
|
|
|
|
echo ""
|
|
echo "✓ Done! PhotoPhetch $TAG released."
|
|
echo " Release page: ${GITEA_URL}/${GITEA_USER}/${GITEA_REPO}/releases/tag/${TAG}"
|