# Push something the apps bundle -> the ingest Mac builds both apps and emails you. # # WHY THIS STOPS SHORT OF UPLOADING # Uploading needs a build number that has never been used before, and Play will never # accept a versionCode twice or accept one that goes down. Bumping it means committing # the new number back to this repo on every build, which needs write access from the # build machine and permanently changes how the apps are numbered. That is a one-way # door, so it is left as a deliberate command: ./release.sh --ios --android # # What this does remove is having to REMEMBER. A change that the apps bundle no longer # sits unnoticed: it gets built immediately, you find out straight away if it no longer # compiles, and you get an email saying the shipped apps are now behind the website. # # WHY THE INGEST MAC AND NOT THE NAS # An app build needs Xcode, the Android SDK and the signing keys. The NAS runner is # Linux in a container and has none of them. This job runs in HOST mode (label # "macos:host") directly on the ingest Mac, which has all three. name: Build apps on: push: branches: [main] paths: # Only what actually ends up inside an app bundle. Deliberately NOT all of mobile/: # release.config.json is excluded so that bumping a build number by hand never # triggers a rebuild of the thing that was just built. - 'server/public/**' - 'mobile/src/**' - 'mobile/capacitor.config.json' - 'mobile/package.json' - '.gitea/workflows/build-apps.yml' workflow_dispatch: jobs: build: runs-on: macos steps: - name: Build both apps id: build run: | set -eu export PATH="/usr/local/bin:/opt/homebrew/bin:$PATH" APP="$HOME/checklist-app" cd "$APP" echo "── syncing the checkout ──" # Retried, because this is the one step that talks to another machine. A push # fires the web deploy and this build at the same moment, and Gitea has been seen # to answer the second SSH session with "Failed to update public key" — a # transient contention error that has nothing to do with the code. Without a # retry that blip emails "App build FAILED", which is precisely the false alarm # that makes an alert worth ignoring. for attempt in 1 2 3; do if git pull --ff-only; then break; fi if [ "$attempt" = 3 ]; then echo "git pull failed three times — giving up"; exit 1; fi echo " pull failed (attempt $attempt), retrying in 15s" sleep 15 done echo "── dependencies ──" ( cd mobile && npm install --no-audit --no-fund >/dev/null ) echo "── rebuilding www/ from server/public ──" ( cd mobile && node scripts/sync-web.js ) # Without this the iOS build fails on a missing ios/App/App/public, because that # directory is generated rather than committed. release.sh does the same thing. echo "── capacitor sync ──" ( cd mobile && npx cap sync >/dev/null ) echo "── android ──" ( cd mobile/android && . ../scripts/env.sh && ./gradlew :app:bundleRelease --no-daemon -q ) AAB="$APP/mobile/android/app/build/outputs/bundle/release/app-release.aab" test -f "$AAB" echo " $AAB ($(du -h "$AAB" | cut -f1))" echo "── ios ──" . mobile/ios-signing.config rm -rf mobile/build/App.xcarchive mobile/build/ios ( cd mobile/ios/App && xcodebuild -project App.xcodeproj -scheme App \ -configuration Release -destination 'generic/platform=iOS' \ -archivePath "$APP/mobile/build/App.xcarchive" \ DEVELOPMENT_TEAM="$DEVELOPMENT_TEAM" CODE_SIGN_STYLE=Automatic \ -allowProvisioningUpdates archive -quiet ) cat > mobile/ExportOptions.plist < methodapp-store-connect teamID$DEVELOPMENT_TEAM destinationexport uploadSymbols PLIST ( cd mobile/ios/App && xcodebuild -exportArchive \ -archivePath "$APP/mobile/build/App.xcarchive" \ -exportOptionsPlist "$APP/mobile/ExportOptions.plist" \ -exportPath "$APP/mobile/build/ios" \ -allowProvisioningUpdates -quiet ) IPA="$(find "$APP/mobile/build/ios" -name '*.ipa' | head -1)" test -n "$IPA" echo " $IPA ($(du -h "$IPA" | cut -f1))" - name: Tell Christian the apps are behind if: success() run: | export PATH="/usr/local/bin:$PATH" cd "$HOME/checklist-app" V="$(node -e 'const c=require("./mobile/release.config.json");console.log(c.version+" (ios build "+c.iosBuild+", android code "+c.androidVersionCode+")")')" # The body goes to a file first. It must NOT be built with $(cat < "$BODY_FILE" < "$BODY_FILE" <