diff --git a/release.sh b/release.sh new file mode 100755 index 0000000..b4d9af9 --- /dev/null +++ b/release.sh @@ -0,0 +1,141 @@ +#!/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 [release-notes]" + echo " Example: $0 1.0.0 'First stable release'" + exit 1 +fi + +VERSION="$1" +TAG="v${VERSION}" + +# Release notes: from argument or prompt +if [ $# -ge 2 ]; then + NOTES="$2" +else + echo "Enter release notes (press Enter twice when done):" + NOTES="" + while IFS= read -r line; do + [[ -z "$line" ]] && break + NOTES="${NOTES}${line}\n" + done +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}"