From ec1cbdfe75162ae2b3d9ebc1bda0f8291409dc39 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 10 Nov 2026 10:18:32 -0800 Subject: [PATCH] iOS: release/dev/prov builds, publish.sh, dev icon variants release = org.cdnutter. (main, Gitea release + Sideload) dev = org.cdnutter.-dev (dev branch, Gitea pre-release + Sideload Developer) prov = org.cdnutter.-prov (personal signed, never published) Co-Authored-By: Claude Opus 5.5 --- README.md | 16 +++- .../AppIconDev.appiconset/Contents.json | 9 ++- .../AppIconDev.appiconset/icon-dark.png | Bin 0 -> 43498 bytes .../AppIconDev.appiconset/icon-tinted.png | Bin 0 -> 21616 bytes ios/scripts/build-ipa.sh | 74 +++++++++--------- ios/scripts/build-remote.sh | 24 +++--- ios/scripts/make-source.py | 3 +- ios/scripts/publish.sh | 36 +++++++++ ios/source.json | 30 +++++++ 9 files changed, 133 insertions(+), 59 deletions(-) create mode 100644 ios/Stemify/Resources/Assets.xcassets/AppIconDev.appiconset/icon-dark.png create mode 100644 ios/Stemify/Resources/Assets.xcassets/AppIconDev.appiconset/icon-tinted.png create mode 100755 ios/scripts/publish.sh diff --git a/README.md b/README.md index b3cd56f..0fce23a 100644 --- a/README.md +++ b/README.md @@ -338,12 +338,20 @@ docs/specs.txt original design doc for the desktop separator ```sh cd ios -scripts/build-ipa.sh # unsigned build/public/stemify-.ipa -scripts/build-remote.sh # from DevOps: build on White-M1 and pull IPAs back to build/{public,prov} -xcodegen generate # or open Stemify.xcodeproj in Xcode +scripts/build-remote.sh # from DevOps: dev build on WHITE-M1, pulled back to build/dev +scripts/build-remote.sh release # release build, build/release +scripts/build-remote.sh prov # personal signed build, build/prov +scripts/build-ipa.sh release|dev|prov # same thing directly on the Mac +xcodegen generate # or open Stemify.xcodeproj in Xcode ``` -The version lives in `ios/project.yml` (`MARKETING_VERSION` and `CURRENT_PROJECT_VERSION`). To release, tag `ios-v`, attach `stemify-.ipa`, then run `GITEA_TOKEN=... ios/scripts/make-source.py` and commit the new `ios/source.json`. +There are three builds, each with its own bundle ID so they install side by side: + +- `org.cdnutter.stemify` (build/release): releases from `main`. `scripts/publish.sh release` tags `ios-v`, uploads the IPA to Gitea and Sideload, and regenerates `ios/source.json`. +- `org.cdnutter.stemify-dev` (build/dev): "Stemify Dev" with the ribbon icon, built from the `dev` branch. `scripts/publish.sh dev` makes a Gitea pre-release `ios-v-dev.` and uploads it to Sideload Developer. Bump `CURRENT_PROJECT_VERSION` for each one. +- `org.cdnutter.stemify-prov` (build/prov): "Stemify Prov", signed with the personal profile in `ios/prov/` so CarPlay and Siri work. Never published. + +The version lives in `ios/project.yml` (`VERSION_LABEL`, `MARKETING_VERSION` and `CURRENT_PROJECT_VERSION`). **Android** needs JDK 21 and the Android SDK (`android/local.properties` points at it): diff --git a/ios/Stemify/Resources/Assets.xcassets/AppIconDev.appiconset/Contents.json b/ios/Stemify/Resources/Assets.xcassets/AppIconDev.appiconset/Contents.json index 7c85906..f0c5b8f 100644 --- a/ios/Stemify/Resources/Assets.xcassets/AppIconDev.appiconset/Contents.json +++ b/ios/Stemify/Resources/Assets.xcassets/AppIconDev.appiconset/Contents.json @@ -1 +1,8 @@ -{"images":[{"filename":"icon.png","idiom":"universal","platform":"ios","size":"1024x1024"}],"info":{"author":"xcode","version":1}} +{ + "images" : [ + { "filename" : "icon.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" }, + { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon-dark.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" }, + { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "filename" : "icon-tinted.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" } + ], + "info" : { "author" : "xcode", "version" : 1 } +} diff --git a/ios/Stemify/Resources/Assets.xcassets/AppIconDev.appiconset/icon-dark.png b/ios/Stemify/Resources/Assets.xcassets/AppIconDev.appiconset/icon-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..4b05ee9dcb1e87781c7c99a5d023b6def9dc4809 GIT binary patch literal 43498 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�hU*IV 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 literal 0 HcmV?d00001 diff --git a/ios/Stemify/Resources/Assets.xcassets/AppIconDev.appiconset/icon-tinted.png b/ios/Stemify/Resources/Assets.xcassets/AppIconDev.appiconset/icon-tinted.png new file mode 100644 index 0000000000000000000000000000000000000000..c97eaef7b285ad4333f9ef2b3fa3220411c988f7 GIT binary patch literal 21616 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 pZB;n.ipa on a Mac: ad-hoc signed, for releases and re-signing with Sideloadly/AltStore. -# With prov/Stemify.mobileprovision, prov/key.p12 and P12_PASS set, it also writes a signed -# build/prov/stemify--signed.ipa (keeps CarPlay/Siri) for the owner's own device. -# Finished IPAs are kept per version; build/work is scratch and is wiped each run. -# "build-ipa.sh dev" builds only build/dev/stemify--dev.ipa: bundle id org.cdnutter.stemify-dev, -# named "Stemify Dev", ad-hoc signed, so it installs next to the release app. For internal tests, never released. -# "build-ipa.sh prov" builds only the signed prov IPA (no public one). -# ios/scripts/build-remote.sh runs this on White-M1 and copies build/public and build/prov back to DevOps. +# Builds one Stemify IPA on a Mac. ios/scripts/build-remote.sh runs this on WHITE-M1 from DevOps. +# build-ipa.sh release build/release/stemify-.ipa org.cdnutter.stemify, ad-hoc signed. Gitea releases (main) + Sideload. +# build-ipa.sh dev build/dev/stemify--dev.ipa org.cdnutter.stemify-dev, "Stemify Dev", ribbon icon. +# Gitea pre-releases (dev branch) + Sideload Developer. +# build-ipa.sh prov build/prov/stemify--prov.ipa org.cdnutter.stemify-prov, "Stemify Prov", signed with the +# personal profile (CarPlay, Siri). Never published anywhere. +# prov needs prov/Stemify.mobileprovision (App ID org.cdnutter.stemify-prov), prov/key.p12 and P12_PASS. +# prov/StemifyWidgets.mobileprovision (org.cdnutter.stemify-prov.widgets) is optional, without it the widgets are left out. +# build/work is scratch and is wiped each run. set -euo pipefail cd "$(dirname "$0")/.." export PATH=/opt/homebrew/bin:$PATH B=build; OUT=$B/work; APP=$OUT/Payload/Stemify.app; EXT=$APP/PlugIns/StemifyWidgets.appex -MODE=${1:-release} -if [ "$MODE" = dev ]; then APP_ID=org.cdnutter.stemify-dev; APP_NAME="Stemify Dev"; APP_ICON=AppIconDev; DD=$B/dd-dev -else APP_ID=org.cdnutter.stemify; APP_NAME=Stemify; APP_ICON=AppIcon; DD=$B/dd; fi -rm -rf $OUT && mkdir -p $OUT/Payload $B/public $B/prov $B/dev +MODE=${1:-dev} +case $MODE in + release) APP_ID=org.cdnutter.stemify; APP_NAME=Stemify; APP_ICON=AppIcon; SUFFIX= ;; + dev) APP_ID=org.cdnutter.stemify-dev; APP_NAME="Stemify Dev"; APP_ICON=AppIconDev; SUFFIX=-dev ;; + prov) APP_ID=org.cdnutter.stemify-prov; APP_NAME="Stemify Prov"; APP_ICON=AppIcon; SUFFIX=-prov ;; + *) echo "usage: $0 release|dev|prov" >&2; exit 1 ;; +esac +DD=$B/dd-$MODE # "1.0 RC 1" -> 1.0-rc1, used in file names and release tags. -VERSION=$(sed -nE 's/^ *VERSION_LABEL: "(.*)"/\1/p' project.yml | tr 'A-Z' 'a-z' | sed -E 's/ rc /-rc/; s/ /-/g') +VERSION=$(sed -nE 's/^ *VERSION_LABEL: "(.*)"/\1/p' project.yml | tr 'A-Z' 'a-z' | sed -E 's/ (rc|beta) /-\1/; s/ /-/g') +IPA=$B/$MODE/stemify-$VERSION$SUFFIX.ipa +if [ "$MODE" = prov ]; then + for f in prov/Stemify.mobileprovision prov/key.p12; do [ -f $f ] || { echo "missing $f" >&2; exit 1; }; done + [ -n "${P12_PASS:-}" ] || { echo "P12_PASS not set" >&2; exit 1; } + PROF_ID=$(security cms -D -i prov/Stemify.mobileprovision | plutil -extract Entitlements.application-identifier raw -) + [ "${PROF_ID#*.}" = "$APP_ID" ] || { echo "prov/Stemify.mobileprovision is for ${PROF_ID#*.}, need a profile for $APP_ID" >&2; exit 1; } +fi + +rm -rf $OUT && mkdir -p $OUT/Payload $B/$MODE # xcodebuild compiles the app, the widget extension, the asset catalog and the App Intents metadata. xcodegen generate -q xcodebuild -project Stemify.xcodeproj -scheme Stemify -configuration Release -sdk iphoneos \ @@ -25,30 +39,16 @@ xcodebuild -project Stemify.xcodeproj -scheme Stemify -configuration Release -sd cp -R $DD/Build/Products/Release-iphoneos/Stemify.app $APP [ -d $EXT ] || { echo "widget extension missing" >&2; exit 1; } -# Ad-hoc signature carrying only the App Group, so Sideloadly/AltStore keep the widgets' shared data when re-signing. -cat > $OUT/group.plist < $OUT/group.plist < com.apple.security.application-groupsgroup.$APP_ID PL -codesign -f -s - --entitlements $OUT/group.plist $EXT -codesign -f -s - --entitlements $OUT/group.plist $APP - -if [ "$MODE" = dev ]; then - rm -f $B/dev/stemify-$VERSION-dev.ipa - (cd $OUT && zip -qry ../dev/stemify-$VERSION-dev.ipa Payload) - echo "$B/dev/stemify-$VERSION-dev.ipa" - exit 0 -fi - -# Public build, for the releases and AltStore/Sideloadly. -if [ "$MODE" != prov ]; then - rm -f $B/public/stemify-$VERSION.ipa - (cd $OUT && zip -qry ../public/stemify-$VERSION.ipa Payload) - echo "$B/public/stemify-$VERSION.ipa" -fi - -if [ -f prov/Stemify.mobileprovision ] && [ -f prov/key.p12 ] && [ -n "${P12_PASS:-}" ]; then + codesign -f -s - --entitlements $OUT/group.plist $EXT + codesign -f -s - --entitlements $OUT/group.plist $APP +else KC=$PWD/$OUT/sign.keychain-db; KP=$(uuidgen) security create-keychain -p "$KP" $KC security set-keychain-settings -lut 3600 $KC @@ -62,7 +62,6 @@ if [ -f prov/Stemify.mobileprovision ] && [ -f prov/key.p12 ] && [ -n "${P12_PAS ID=$(security find-identity -v -p codesigning $KC | sed -nE 's/.*"(Apple Development:.*)"/\1/p' | head -1) security cms -D -i prov/Stemify.mobileprovision > $OUT/prov.plist /usr/libexec/PlistBuddy -x -c 'Print :Entitlements' $OUT/prov.plist > $OUT/ent.plist - # The widgets need their own profile (org.cdnutter.stemify.widgets with the App Group). Without one they're left out. if [ -f prov/StemifyWidgets.mobileprovision ]; then security cms -D -i prov/StemifyWidgets.mobileprovision > $OUT/wprov.plist /usr/libexec/PlistBuddy -x -c 'Print :Entitlements' $OUT/wprov.plist > $OUT/went.plist @@ -75,9 +74,8 @@ if [ -f prov/Stemify.mobileprovision ] && [ -f prov/key.p12 ] && [ -n "${P12_PAS codesign -f -s "$ID" --entitlements $OUT/ent.plist --timestamp=none $APP security list-keychains -d user -s $(security list-keychains -d user | tr -d "\"" | grep -v sign.keychain) security delete-keychain $KC - # Personal build for this device only: stays in build/prov (gitignored), never released. - rm -f $B/prov/stemify-$VERSION-signed.ipa - (cd $OUT && zip -qry ../prov/stemify-$VERSION-signed.ipa Payload) - echo "$B/prov/stemify-$VERSION-signed.ipa (signed as $ID)" fi +rm -f $IPA +(cd $OUT && zip -qry ../$MODE/$(basename $IPA) Payload) +echo "$IPA" diff --git a/ios/scripts/build-remote.sh b/ios/scripts/build-remote.sh index 904a7c7..6e935d9 100755 --- a/ios/scripts/build-remote.sh +++ b/ios/scripts/build-remote.sh @@ -1,23 +1,17 @@ #!/bin/bash -# Run from DevOps: syncs ios/ to White-M1, builds there, and pulls the IPAs back into ios/build. -# build-remote.sh dev + prov (the usual build): build/dev and build/prov -# build-remote.sh public public + prov, only when a public release is asked for: build/public and build/prov -# build-remote.sh dev dev only +# Run from DevOps: syncs ios/ to WHITE-M1, builds there, and pulls the IPAs back into ios/build/. +# build-remote.sh dev build (the usual one): build/dev +# build-remote.sh release release build, only when a release is asked for: build/release +# build-remote.sh prov personal signed build: build/prov +# build-remote.sh dev prov ... several at once set -euo pipefail cd "$(dirname "$0")/.." H=${BUILD_HOST:-white-m1}; R=stemify-build/ios -case "${1:-}" in - "") MODES="dev prov" ;; - public) MODES="release" ;; - dev) MODES="dev" ;; - *) echo "usage: $0 [public|dev]" >&2; exit 1 ;; -esac +MODES=${*:-dev} +for m in $MODES; do case $m in release|dev|prov) ;; *) echo "usage: $0 [release|dev|prov]..." >&2; exit 1 ;; esac; done rsync -a --exclude build --exclude prov --exclude Stemify.xcodeproj ./ $H:$R/ for m in $MODES; do ssh $H "cd $R && P12_PASS=\$(cat prov/cert_pass.txt 2>/dev/null) bash scripts/build-ipa.sh $m" + mkdir -p build/$m && rsync -a $H:$R/build/$m/ build/$m/ done -for m in $MODES; do - case $m in dev) DIRS=dev ;; prov) DIRS=prov ;; release) DIRS="public prov" ;; esac - for d in $DIRS; do mkdir -p build/$d; rsync -a $H:$R/build/$d/ build/$d/; done -done -ls build/*/stemify-$(sed -nE 's/^ *VERSION_LABEL: "(.*)"/\1/p' project.yml | tr 'A-Z' 'a-z' | sed -E 's/ rc /-rc/; s/ /-/g')*.ipa 2>/dev/null +ls build/{release,dev,prov}/stemify-$(sed -nE 's/^ *VERSION_LABEL: "(.*)"/\1/p' project.yml | tr 'A-Z' 'a-z' | sed -E 's/ (rc|beta) /-\1/; s/ /-/g')*.ipa 2>/dev/null diff --git a/ios/scripts/make-source.py b/ios/scripts/make-source.py index a9ba461..31890bd 100755 --- a/ios/scripts/make-source.py +++ b/ios/scripts/make-source.py @@ -36,7 +36,8 @@ versions = [] for rel in get(API + "/releases?limit=50"): v = rel["tag_name"].removeprefix("ios-v") ipa = next((a for a in rel["assets"] if a["name"] == f"stemify-{v}.ipa"), None) - if not rel["tag_name"].startswith("ios-v") or not ipa: + # Pre-releases are dev builds (org.cdnutter.stemify-dev), they go to Sideload Developer instead. + if not rel["tag_name"].startswith("ios-v") or not ipa or rel["prerelease"]: continue versions.append({ "version": v.split("-")[0], diff --git a/ios/scripts/publish.sh b/ios/scripts/publish.sh new file mode 100755 index 0000000..e2de035 --- /dev/null +++ b/ios/scripts/publish.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Publishes an IPA built by build-remote.sh. Run from DevOps with everything committed. +# publish.sh dev on the dev branch: Gitea pre-release ios-v-dev. + Sideload Developer (WHITE-M1 :8097) +# publish.sh release on main, only when the owner says so: Gitea release ios-v + Sideload (:8093), then source.json +# Release notes come from $NOTES, else the last commit subject. prov builds are never published. +set -euo pipefail +cd "$(dirname "$0")/.." +MODE=${1:-}; NAME=stemify; TAGP=ios-v +API=https://git.iamchrisama.com/api/v1/repos/cdnutter/stemify +T=$(sed -n 's#.*://cdnutter:\([^@]*\)@.*#\1#p' ~/.config/gitea/cdnutter.credentials | head -1) +V=$(sed -nE 's/^ *VERSION_LABEL: "(.*)"/\1/p' project.yml | tr 'A-Z' 'a-z' | sed -E 's/ (rc|beta) /-\1/; s/ /-/g') +BUILD=$(sed -nE 's/^ *CURRENT_PROJECT_VERSION: "(.*)"/\1/p' project.yml) +BRANCH=$(git rev-parse --abbrev-ref HEAD) +die() { echo "$*" >&2; exit 1; } +case $MODE in + dev) WANT=dev; IPA=build/dev/$NAME-$V-dev.ipa; TAG=$TAGP$V-dev.$BUILD; PRE=true; UP=http://10.0.0.11:8097 ;; + release) WANT=main; IPA=build/release/$NAME-$V.ipa; TAG=$TAGP$V; PRE=false; UP=http://10.0.0.11:8093 ;; + *) die "usage: $0 dev|release" ;; +esac +[ "$BRANCH" = "$WANT" ] || die "$MODE builds publish from $WANT (on $BRANCH)" +[ -f "$IPA" ] || die "missing $IPA, run scripts/build-remote.sh $MODE" +git diff --quiet HEAD || die "uncommitted changes" +[ "$(curl -s -o /dev/null -w '%{http_code}' -H "Authorization: token $T" $API/releases/tags/$TAG)" = 404 ] \ + || die "$TAG already exists, bump CURRENT_PROJECT_VERSION (dev) or VERSION_LABEL (release)" +git push -q -u origin $BRANCH +BODY=${NOTES:-$(git log -1 --format=%s)} +ID=$(jq -n --arg t "$TAG" --arg c "$(git rev-parse HEAD)" --arg b "$BODY" --argjson p $PRE \ + '{tag_name:$t, target_commitish:$c, name:$t, body:$b, prerelease:$p}' | + curl -fsS -H "Authorization: token $T" -H 'Content-Type: application/json' -d @- $API/releases | jq -r .id) +curl -fsS -o /dev/null -H "Authorization: token $T" -F "attachment=@$IPA" "$API/releases/$ID/assets?name=$(basename $IPA)" +curl -fsS -o /dev/null -X POST --data-binary @$IPA $UP/api/upload/ipa +echo "published $TAG ($(basename $IPA)) to Gitea and $UP" +if [ $MODE = release ]; then + GITEA_TOKEN=$T python3 scripts/make-source.py + git add source.json && git commit -qm "iOS source.json for $TAG" && git push -q origin main +fi diff --git a/ios/source.json b/ios/source.json index f62b53b..481a3dd 100644 --- a/ios/source.json +++ b/ios/source.json @@ -174,6 +174,36 @@ "downloadURL": "https://git.iamchrisama.com/cdnutter/stemify/releases/download/ios-v1.0.3/stemify-1.0.3.ipa", "size": 1319672, "minOSVersion": "17.0" + }, + { + "version": "1.0.2", + "marketingVersion": "1.0.2", + "buildVersion": "1.0.2", + "date": "2026-10-20T08:53:24-07:00", + "localizedDescription": "Unsigned, iOS 17 or newer. Sideload `Stemify.ipa` with Sideloadly or AltStore.\n\n- Shuffle on the Songs screen now picks from the whole library instead of only the songs loaded so far (the A's and B's)\n\nIncludes everything in 1.0.1. CarPlay and Siri still need entitlements a free Apple ID can't sign.", + "downloadURL": "https://git.iamchrisama.com/cdnutter/stemify/releases/download/ios-v1.0.2/stemify-1.0.2.ipa", + "size": 1319672, + "minOSVersion": "17.0" + }, + { + "version": "1.0.1", + "marketingVersion": "1.0.1", + "buildVersion": "1.0.1", + "date": "2026-10-20T08:50:56-07:00", + "localizedDescription": "Unsigned, iOS 17 or newer. Sideload `Stemify.ipa` with Sideloadly or AltStore.\n\n- The mini player no longer covers the bottom of lists, and it is now a solid card that matches the app instead of system glass\n- More room between the title and the scrubber on Now Playing\n- The play button no longer spins forever after you change tracks\n- The stems and queue buttons now animate their panels in and out\n- Springier button presses and play/pause transitions\n\nCarPlay and Siri still need entitlements a free Apple ID can't sign.", + "downloadURL": "https://git.iamchrisama.com/cdnutter/stemify/releases/download/ios-v1.0.1/stemify-1.0.1.ipa", + "size": 1317680, + "minOSVersion": "17.0" + }, + { + "version": "1.0", + "marketingVersion": "1.0", + "buildVersion": "1.0", + "date": "2026-10-20T07:16:41-07:00", + "localizedDescription": "First iOS build. Unsigned, iOS 17 or newer.\n\nSideload `Stemify.ipa` with Sideloadly or AltStore, which sign it with your Apple ID.\n\nCarPlay and Siri need entitlements a free Apple ID can't sign, so on a free sideload they won't show up. Everything on the phone works. Not yet tested on a device.", + "downloadURL": "https://git.iamchrisama.com/cdnutter/stemify/releases/download/ios-v1.0/stemify-1.0.ipa", + "size": 1305649, + "minOSVersion": "17.0" } ], "appPermissions": {