neotalk/packaging/release-macos.sh
Andros Fenollosa ba9bbbf3b9
Some checks are pending
build-windows / windows-exe (push) Waiting to run
Add macOS signing and notarized-release scripts
sign-macos.sh signs neotalk.app with the Developer ID under the hardened
runtime; release-macos.sh builds, signs, notarizes, staples and can publish the
zip to the Gitea releases page. Credentials are read from the environment.
2026-08-21 10:17:55 +02:00

77 lines
2.8 KiB
Bash
Executable file

#!/usr/bin/env bash
# Build, sign, notarize, staple and (optionally) publish a macOS release of
# neotalk to the Gitea releases page. Run on macOS.
#
# ./packaging/release-macos.sh v0.1.0
#
# Credentials are read from the environment so nothing secret lives in the repo:
#
# NEOTALK_SIGN_IDENTITY Developer ID (defaults to Andros' Developer ID)
# Notarization (pick one):
# NEOTALK_NOTARY_PROFILE a notarytool keychain profile, created once with:
# xcrun notarytool store-credentials neotalk \
# --apple-id you@example.com --team-id M3K3T47KXF --password APP-SPECIFIC-PW
# or:
# NEOTALK_APPLE_ID, NEOTALK_APPLE_PASSWORD Apple ID + app-specific password
# Publishing (optional):
# NEOTALK_GITEA_TOKEN Gitea token with repo write; uploads the .zip
set -euo pipefail
TAG="${1:?usage: release-macos.sh <tag>, e.g. v0.1.0}"
HERE="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(cd "$HERE/.." && pwd)"
cd "$ROOT"
APP="dist/neotalk.app"
ZIP="dist/neotalk-macos-${TAG}.zip"
TEAM_ID="M3K3T47KXF"
GITEA_API="https://git.andros.dev/api/v1/repos/andros/neotalk"
echo "==> Building"
rm -rf dist build/pyinstaller
uv run --extra build pyinstaller --noconfirm --clean \
--distpath dist --workpath build/pyinstaller packaging/neotalk.spec >/dev/null
echo "==> Signing"
"$HERE/sign-macos.sh" "$APP"
echo "==> Zipping for notarization"
/usr/bin/ditto -c -k --keepParent "$APP" "$ZIP"
echo "==> Notarizing"
if [ -n "${NEOTALK_NOTARY_PROFILE:-}" ]; then
xcrun notarytool submit "$ZIP" --keychain-profile "$NEOTALK_NOTARY_PROFILE" --wait
elif [ -n "${NEOTALK_APPLE_ID:-}" ] && [ -n "${NEOTALK_APPLE_PASSWORD:-}" ]; then
xcrun notarytool submit "$ZIP" --apple-id "$NEOTALK_APPLE_ID" \
--team-id "$TEAM_ID" --password "$NEOTALK_APPLE_PASSWORD" --wait
else
echo "No notarization credentials set. Signed app is at $APP." >&2
echo "Set NEOTALK_NOTARY_PROFILE or NEOTALK_APPLE_ID/NEOTALK_APPLE_PASSWORD." >&2
exit 2
fi
echo "==> Stapling"
xcrun stapler staple "$APP"
xcrun stapler validate "$APP"
rm -f "$ZIP"
/usr/bin/ditto -c -k --keepParent "$APP" "$ZIP"
echo "Notarized, stapled artifact: $ZIP"
if [ -z "${NEOTALK_GITEA_TOKEN:-}" ]; then
echo "NEOTALK_GITEA_TOKEN not set; skipping upload. Upload $ZIP by hand if you like."
exit 0
fi
echo "==> Publishing release $TAG to Gitea"
release_id=$(
curl -fsS -X POST "$GITEA_API/releases" \
-H "Authorization: token $NEOTALK_GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"tag_name\":\"$TAG\",\"name\":\"neotalk $TAG\",\"draft\":false,\"prerelease\":false}" |
python3 -c "import sys,json; print(json.load(sys.stdin)['id'])"
)
curl -fsS -X POST \
"$GITEA_API/releases/$release_id/assets?name=$(basename "$ZIP")" \
-H "Authorization: token $NEOTALK_GITEA_TOKEN" \
-F "attachment=@$ZIP" >/dev/null
echo "Published: https://git.andros.dev/andros/neotalk/releases/tag/$TAG"