Commit 28e4abd663
Unsigned
Layout: unified · split
App/README.org +14
| @@ -15,3 +15,17 @@ subsystem =sh.krz.moonrise=. | |||
| 15 | Backend: both configurations use https://moonrise-server.audit-labs.workers.dev | 15 | Backend: both configurations use https://moonrise-server.audit-labs.workers.dev |
| 16 | (=MOONRISE_API_URL= in =project.yml=). For a local Worker, set it to | 16 | (=MOONRISE_API_URL= in =project.yml=). For a local Worker, set it to |
| 17 | =http://localhost:8787= and regenerate. | 17 | =http://localhost:8787= and regenerate. |
| 18 | |||
| 19 | * Release | ||
| 20 | |||
| 21 | #+begin_src sh | ||
| 22 | scripts/release-ios.sh | ||
| 23 | #+end_src | ||
| 24 | |||
| 25 | Run from a clean =main=. It regenerates the project, archives the iPhone | ||
| 26 | app with its widgets and the Watch app, and uploads it to App Store | ||
| 27 | Connect, signed through the Apple ID in Xcode. The version is | ||
| 28 | =MARKETING_VERSION= in =project.yml=; the build number is | ||
| 29 | =git rev-list --count HEAD=, so each build maps to a commit. | ||
| 30 | =MOONRISE_PUBLISH=0= exports the =.ipa= to =.build/ios-release= without | ||
| 31 | uploading. The visionOS app is a separate product and is not uploaded. | ||
App/Sources/InAppBrowser.swift −1
| @@ -9,7 +9,6 @@ enum InAppBrowser { | |||
| 9 | static let action = OpenURLAction { url in | 9 | static let action = OpenURLAction { url in |
| 10 | guard url.scheme == "https" || url.scheme == "http", let top = topViewController() else { return .systemAction } | 10 | guard url.scheme == "https" || url.scheme == "http", let top = topViewController() else { return .systemAction } |
| 11 | let safari = SFSafariViewController(url: url) | 11 | let safari = SFSafariViewController(url: url) |
| 12 | safari.preferredControlTintColor = UIColor(red: 0.88, green: 0.24, blue: 0.19, alpha: 1) | ||
| 13 | safari.dismissButtonStyle = .done | 12 | safari.dismissButtonStyle = .done |
| 14 | top.present(safari, animated: true) | 13 | top.present(safari, animated: true) |
| 15 | return .handled | 14 | return .handled |
App/Watch/Widgets-Info.plist +2 −2
| @@ -17,9 +17,9 @@ | |||
| 17 | <key>CFBundlePackageType</key> | 17 | <key>CFBundlePackageType</key> |
| 18 | <string>XPC!</string> | 18 | <string>XPC!</string> |
| 19 | <key>CFBundleShortVersionString</key> | 19 | <key>CFBundleShortVersionString</key> |
| 20 | <string>1.0</string> | 20 | <string>$(MARKETING_VERSION)</string> |
| 21 | <key>CFBundleVersion</key> | 21 | <key>CFBundleVersion</key> |
| 22 | <string>1</string> | 22 | <string>$(CURRENT_PROJECT_VERSION)</string> |
| 23 | <key>NSExtension</key> | 23 | <key>NSExtension</key> |
| 24 | <dict> | 24 | <dict> |
| 25 | <key>NSExtensionPointIdentifier</key> | 25 | <key>NSExtensionPointIdentifier</key> |
App/Widgets/Info.plist +2 −2
| @@ -17,9 +17,9 @@ | |||
| 17 | <key>CFBundlePackageType</key> | 17 | <key>CFBundlePackageType</key> |
| 18 | <string>XPC!</string> | 18 | <string>XPC!</string> |
| 19 | <key>CFBundleShortVersionString</key> | 19 | <key>CFBundleShortVersionString</key> |
| 20 | <string>1.0</string> | 20 | <string>$(MARKETING_VERSION)</string> |
| 21 | <key>CFBundleVersion</key> | 21 | <key>CFBundleVersion</key> |
| 22 | <string>1</string> | 22 | <string>$(CURRENT_PROJECT_VERSION)</string> |
| 23 | <key>NSExtension</key> | 23 | <key>NSExtension</key> |
| 24 | <dict> | 24 | <dict> |
| 25 | <key>NSExtensionPointIdentifier</key> | 25 | <key>NSExtensionPointIdentifier</key> |
App/project.yml +14 −10
| @@ -54,8 +54,8 @@ targets: | |||
| 54 | CODE_SIGN_STYLE: Automatic | 54 | CODE_SIGN_STYLE: Automatic |
| 55 | SWIFT_VERSION: "6.0" | 55 | SWIFT_VERSION: "6.0" |
| 56 | TARGETED_DEVICE_FAMILY: "1,2" | 56 | TARGETED_DEVICE_FAMILY: "1,2" |
| 57 | MARKETING_VERSION: "1.0" | 57 | MARKETING_VERSION: "1.0.0" |
| 58 | CURRENT_PROJECT_VERSION: "1" | 58 | CURRENT_PROJECT_VERSION: "52" |
| 59 | GENERATE_INFOPLIST_FILE: YES | 59 | GENERATE_INFOPLIST_FILE: YES |
| 60 | INFOPLIST_KEY_CFBundleDisplayName: Moonrise | 60 | INFOPLIST_KEY_CFBundleDisplayName: Moonrise |
| 61 | INFOPLIST_KEY_NSSupportsLiveActivities: YES | 61 | INFOPLIST_KEY_NSSupportsLiveActivities: YES |
| @@ -83,6 +83,8 @@ targets: | |||
| 83 | path: Widgets/Info.plist | 83 | path: Widgets/Info.plist |
| 84 | properties: | 84 | properties: |
| 85 | CFBundleDisplayName: Moonrise | 85 | CFBundleDisplayName: Moonrise |
| 86 | CFBundleShortVersionString: $(MARKETING_VERSION) | ||
| 87 | CFBundleVersion: $(CURRENT_PROJECT_VERSION) | ||
| 86 | NSWidgetWantsLocation: true | 88 | NSWidgetWantsLocation: true |
| 87 | NSExtension: | 89 | NSExtension: |
| 88 | NSExtensionPointIdentifier: com.apple.widgetkit-extension | 90 | NSExtensionPointIdentifier: com.apple.widgetkit-extension |
| @@ -93,8 +95,8 @@ targets: | |||
| 93 | CODE_SIGN_STYLE: Automatic | 95 | CODE_SIGN_STYLE: Automatic |
| 94 | SWIFT_VERSION: "6.0" | 96 | SWIFT_VERSION: "6.0" |
| 95 | TARGETED_DEVICE_FAMILY: "1,2" | 97 | TARGETED_DEVICE_FAMILY: "1,2" |
| 96 | MARKETING_VERSION: "1.0" | 98 | MARKETING_VERSION: "1.0.0" |
| 97 | CURRENT_PROJECT_VERSION: "1" | 99 | CURRENT_PROJECT_VERSION: "52" |
| 98 | MoonriseWatch: | 100 | MoonriseWatch: |
| 99 | type: application | 101 | type: application |
| 100 | platform: watchOS | 102 | platform: watchOS |
| @@ -111,8 +113,8 @@ targets: | |||
| 111 | DEVELOPMENT_TEAM: ZCNAX3VL9D | 113 | DEVELOPMENT_TEAM: ZCNAX3VL9D |
| 112 | CODE_SIGN_STYLE: Automatic | 114 | CODE_SIGN_STYLE: Automatic |
| 113 | SWIFT_VERSION: "6.0" | 115 | SWIFT_VERSION: "6.0" |
| 114 | MARKETING_VERSION: "1.0" | 116 | MARKETING_VERSION: "1.0.0" |
| 115 | CURRENT_PROJECT_VERSION: "1" | 117 | CURRENT_PROJECT_VERSION: "52" |
| 116 | GENERATE_INFOPLIST_FILE: YES | 118 | GENERATE_INFOPLIST_FILE: YES |
| 117 | INFOPLIST_KEY_CFBundleDisplayName: Moonrise | 119 | INFOPLIST_KEY_CFBundleDisplayName: Moonrise |
| 118 | INFOPLIST_KEY_WKCompanionAppBundleIdentifier: sh.krz.moonrise | 120 | INFOPLIST_KEY_WKCompanionAppBundleIdentifier: sh.krz.moonrise |
| @@ -135,6 +137,8 @@ targets: | |||
| 135 | path: Watch/Widgets-Info.plist | 137 | path: Watch/Widgets-Info.plist |
| 136 | properties: | 138 | properties: |
| 137 | CFBundleDisplayName: Moonrise | 139 | CFBundleDisplayName: Moonrise |
| 140 | CFBundleShortVersionString: $(MARKETING_VERSION) | ||
| 141 | CFBundleVersion: $(CURRENT_PROJECT_VERSION) | ||
| 138 | NSWidgetWantsLocation: true | 142 | NSWidgetWantsLocation: true |
| 139 | NSExtension: | 143 | NSExtension: |
| 140 | NSExtensionPointIdentifier: com.apple.widgetkit-extension | 144 | NSExtensionPointIdentifier: com.apple.widgetkit-extension |
| @@ -144,8 +148,8 @@ targets: | |||
| 144 | DEVELOPMENT_TEAM: ZCNAX3VL9D | 148 | DEVELOPMENT_TEAM: ZCNAX3VL9D |
| 145 | CODE_SIGN_STYLE: Automatic | 149 | CODE_SIGN_STYLE: Automatic |
| 146 | SWIFT_VERSION: "6.0" | 150 | SWIFT_VERSION: "6.0" |
| 147 | MARKETING_VERSION: "1.0" | 151 | MARKETING_VERSION: "1.0.0" |
| 148 | CURRENT_PROJECT_VERSION: "1" | 152 | CURRENT_PROJECT_VERSION: "52" |
| 149 | MoonriseVision: | 153 | MoonriseVision: |
| 150 | type: application | 154 | type: application |
| 151 | platform: visionOS | 155 | platform: visionOS |
| @@ -169,8 +173,8 @@ targets: | |||
| 169 | DEVELOPMENT_TEAM: ZCNAX3VL9D | 173 | DEVELOPMENT_TEAM: ZCNAX3VL9D |
| 170 | CODE_SIGN_STYLE: Automatic | 174 | CODE_SIGN_STYLE: Automatic |
| 171 | SWIFT_VERSION: "6.0" | 175 | SWIFT_VERSION: "6.0" |
| 172 | MARKETING_VERSION: "1.0" | 176 | MARKETING_VERSION: "1.0.0" |
| 173 | CURRENT_PROJECT_VERSION: "1" | 177 | CURRENT_PROJECT_VERSION: "52" |
| 174 | GENERATE_INFOPLIST_FILE: YES | 178 | GENERATE_INFOPLIST_FILE: YES |
| 175 | INFOPLIST_KEY_CFBundleDisplayName: Moonrise | 179 | INFOPLIST_KEY_CFBundleDisplayName: Moonrise |
| 176 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation: YES | 180 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation: YES |
scripts/release-ios.sh added +63
| @@ -0,0 +1,63 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | # Archives the iOS app (with its widgets and the watch app) and uploads it to App Store Connect, | ||
| 3 | # signed automatically with the team's distribution certificate through the Apple ID signed in | ||
| 4 | # to Xcode. The version is MARKETING_VERSION in App/project.yml; the build number is the commit | ||
| 5 | # count on main, so every upload can be traced to a commit. The upload then shows in TestFlight | ||
| 6 | # and can be picked for an App Store submission. | ||
| 7 | # Usage: scripts/release-ios.sh | ||
| 8 | # MOONRISE_PUBLISH 0 archives and exports the .ipa to .build/ios-release without uploading | ||
| 9 | set -eu | ||
| 10 | |||
| 11 | cd "$(dirname "$0")/.." | ||
| 12 | publish="${MOONRISE_PUBLISH:-1}" | ||
| 13 | team=ZCNAX3VL9D | ||
| 14 | |||
| 15 | if [ "$publish" != 0 ]; then | ||
| 16 | [ -z "$(git status --porcelain)" ] || { echo "The working tree has changes." >&2; exit 1; } | ||
| 17 | [ "$(git branch --show-current)" = main ] || { echo "Release from main." >&2; exit 1; } | ||
| 18 | fi | ||
| 19 | |||
| 20 | version="$(sed -n 's/.*MARKETING_VERSION: "\(.*\)"/\1/p' App/project.yml | sort -u)" | ||
| 21 | [ "$(printf '%s\n' "$version" | wc -l | tr -d ' ')" = 1 ] || { echo "The targets' MARKETING_VERSION differ: $version" >&2; exit 1; } | ||
| 22 | build="$(git rev-list --count HEAD)" | ||
| 23 | |||
| 24 | command -v xcodegen >/dev/null || { echo "Install XcodeGen: brew install xcodegen" >&2; exit 1; } | ||
| 25 | (cd App && xcodegen generate --quiet) | ||
| 26 | |||
| 27 | out=.build/ios-release | ||
| 28 | rm -rf "${out:?}" | ||
| 29 | mkdir -p "$out" | ||
| 30 | archive="$out/moonrise.xcarchive" | ||
| 31 | xcodebuild archive -project App/Moonrise.xcodeproj -scheme Moonrise -configuration Release \ | ||
| 32 | -destination 'generic/platform=iOS' -archivePath "$archive" -allowProvisioningUpdates -quiet \ | ||
| 33 | MARKETING_VERSION="$version" CURRENT_PROJECT_VERSION="$build" | ||
| 34 | |||
| 35 | if [ "$publish" = 0 ]; then destination=export; else destination=upload; fi | ||
| 36 | cat > "$out/ExportOptions.plist" <<PLIST | ||
| 37 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 38 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| 39 | <plist version="1.0"> | ||
| 40 | <dict> | ||
| 41 | <key>method</key> | ||
| 42 | <string>app-store-connect</string> | ||
| 43 | <key>destination</key> | ||
| 44 | <string>$destination</string> | ||
| 45 | <key>teamID</key> | ||
| 46 | <string>$team</string> | ||
| 47 | <key>signingStyle</key> | ||
| 48 | <string>automatic</string> | ||
| 49 | <key>manageAppVersionAndBuildNumber</key> | ||
| 50 | <false/> | ||
| 51 | <key>uploadSymbols</key> | ||
| 52 | <true/> | ||
| 53 | </dict> | ||
| 54 | </plist> | ||
| 55 | PLIST | ||
| 56 | xcodebuild -exportArchive -archivePath "$archive" -exportOptionsPlist "$out/ExportOptions.plist" \ | ||
| 57 | -exportPath "$out/export" -allowProvisioningUpdates -quiet | ||
| 58 | |||
| 59 | if [ "$publish" = 0 ]; then | ||
| 60 | echo "Exported $(ls "$out"/export/*.ipa): $version ($build), not uploaded" | ||
| 61 | else | ||
| 62 | echo "Uploaded Moonrise $version ($build) to App Store Connect; it shows in TestFlight once processed" | ||
| 63 | fi | ||