103 lines
4.4 KiB
Bash
Executable File
103 lines
4.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Upload the built macOS artifacts to a Gitea release. No runners, no CI.
|
|
# Auth comes from the macOS keychain (same creds `git` uses to push).
|
|
# Usage: ./scripts/gitea-release.sh [v0.2.0]
|
|
# No arg = auto patch-bump (0.1.0 -> 0.1.1). Explicit arg syncs version files.
|
|
# Requires: jq, curl, npm run tauri build deps. If scripts/apple-signing.env is
|
|
# present, builds a signed + notarized DMG automatically; else ad-hoc (unsigned).
|
|
set -euo pipefail
|
|
|
|
GITEA_URL="https://gitea.jms.rocks"
|
|
OWNER_REPO="jameshtwose/dm-pal"
|
|
API="$GITEA_URL/api/v1/repos/$OWNER_REPO"
|
|
HOST="${GITEA_URL#https://}"
|
|
|
|
# Auth: explicit token wins, else pull from the git credential helper (keychain).
|
|
auth_header() {
|
|
if [ -n "${GITEA_TOKEN:-}" ]; then
|
|
printf 'Authorization: token %s' "$GITEA_TOKEN"; return
|
|
fi
|
|
creds=$(git credential fill <<< "protocol=https
|
|
host=$HOST" 2>/dev/null || true)
|
|
user=$(printf '%s\n' "$creds" | sed -n 's/^username=//p')
|
|
pass=$(printf '%s\n' "$creds" | sed -n 's/^password=//p')
|
|
[ -n "$pass" ] || { echo "no creds in keychain and GITEA_TOKEN unset"; exit 1; }
|
|
printf 'Authorization: Basic %s' "$(printf '%s:%s' "$user" "$pass" | base64)"
|
|
}
|
|
|
|
# Resolve the release tag. No arg => auto-bump patch from the current version.
|
|
# An explicit arg (v0.2.0) wins and also syncs both version files to it, so the
|
|
# built DMG's embedded version always matches the release tag.
|
|
# ponytail: patch-only auto-bump; pass v0.2.0 / v1.0.0 for minor/major.
|
|
if [ -n "${1:-}" ]; then
|
|
VER="${1#v}"
|
|
else
|
|
VER=$(node -e 'const v=require("./package.json").version;const [a,b,c]=v.split(".").map(Number);process.stdout.write(`${a}.${b}.${c+1}`)')
|
|
fi
|
|
TAG="v$VER"
|
|
node -e '
|
|
const fs=require("fs"),ver=process.argv[1];
|
|
for(const f of ["package.json","src-tauri/tauri.conf.json"]){
|
|
const t=fs.readFileSync(f,"utf8");
|
|
const out=t.replace(/("version"\s*:\s*")\d+\.\d+\.\d+(")/,`$1${ver}$2`);
|
|
if(out===t)throw new Error("version not replaced in "+f);
|
|
fs.writeFileSync(f,out);
|
|
}
|
|
' "$VER"
|
|
echo "release $TAG (version files synced)"
|
|
git add package.json src-tauri/tauri.conf.json
|
|
if ! git diff --cached --quiet; then
|
|
git commit -m "chore: release $TAG" -q
|
|
echo "committed version bump"
|
|
fi
|
|
|
|
# If Apple signing creds are present, do a signed + notarized build now so the
|
|
# uploaded DMG passes Gatekeeper on a browser download. Without these the DMG
|
|
# is only ad-hoc signed and macOS shows it as "damaged" when downloaded.
|
|
ENV_FILE="$(dirname "$0")/apple-signing.env"
|
|
if [ -f "$ENV_FILE" ]; then
|
|
set -a; . "$ENV_FILE"; set +a
|
|
echo "Building signed + notarized DMG ..."
|
|
npm run tauri build -- --bundles app,dmg
|
|
else
|
|
echo "warn: scripts/apple-signing.env missing — building unsigned (ad-hoc) DMG."
|
|
echo " Browser downloads will be blocked by Gatekeeper. See apple-signing.env.example."
|
|
npm run tauri build -- --bundles app,dmg
|
|
fi
|
|
|
|
DMG=$(ls -t src-tauri/target/release/bundle/dmg/*.dmg | head -1)
|
|
APP_BUNDLE=$(ls -d src-tauri/target/release/bundle/macos/*.app | head -1)
|
|
[ -f "$DMG" ] || { echo "no dmg found — build failed"; exit 1; }
|
|
[ -d "$APP_BUNDLE" ] || { echo "no .app found"; exit 1; }
|
|
|
|
# ponytail: ship the dmg as the installer; also zip the .app for unmanaged
|
|
# installs / inspection. Skip if zip already present.
|
|
ZIP="${APP_BUNDLE%.app}.zip"
|
|
[ -f "$ZIP" ] || ditto -c -k --keepParent "$APP_BUNDLE" "$ZIP"
|
|
|
|
AUTH=$(auth_header)
|
|
|
|
echo "Creating release $TAG ..."
|
|
REL=$(curl -sf -X POST "$API/releases" \
|
|
-H "$AUTH" -H "Content-Type: application/json" \
|
|
-d "$(jq -n --arg t "$TAG" --arg n "$TAG" \
|
|
'{tag_name:$t, name:$n, body:"DM-Pal macOS build.", draft:false, prerelease:false}')")
|
|
RID=$(echo "$REL" | jq -r .id)
|
|
[ "$RID" != "null" ] || { echo "release create failed: $REL"; exit 1; }
|
|
echo "release id=$RID"
|
|
|
|
for f in "$DMG" "$ZIP"; do
|
|
echo "attaching $(basename "$f") ..."
|
|
curl -sf -X POST "$API/releases/$RID/assets?name=$(basename "$f")" \
|
|
-H "$AUTH" -F "attachment=@$f" -o /dev/null
|
|
done
|
|
|
|
# ponytail: guard against shipping an unsigned bundle by mistake — if creds
|
|
# were configured, confirm the app is actually Developer-ID signed.
|
|
if [ -f "$ENV_FILE" ]; then
|
|
codesign -dv --verbose=2 "$APP_BUNDLE" 2>&1 | grep -q "Authority=Developer ID" \
|
|
|| { echo "error: APPLE creds set but app is not Developer-ID signed — notarization failed or skipped"; exit 1; }
|
|
echo "verified: Developer ID signature present"
|
|
fi
|
|
|
|
echo "done -> $GITEA_URL/$OWNER_REPO/releases/tag/$TAG" |