build: 3d326e8d-e3da-4f61-941d-6fd836a5b391

This commit is contained in:
AppCakes
2026-06-01 11:34:15 +00:00
commit 5dee0a52dc
107 changed files with 6866 additions and 0 deletions
+380
View File
@@ -0,0 +1,380 @@
workflows:
android-debug:
name: Android Debug APK
max_build_duration: 45
instance_type: mac_mini_m2
environment:
node: 22
java: 21
cache:
cache_paths:
- $HOME/.gradle/caches
- $HOME/.gradle/wrapper
scripts:
# Template ships with optional native plugins (maps, push, firebase auth) that most apps
# won't use. Keeping unused plugins in package.json adds SPM/Gradle deps and bloats the
# build. Strip any that have no import in src/ so only actually-used plugins are compiled.
- name: Strip unused scaffold packages
script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
if ! grep -rq "$pkg" src/; then
node -e "const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));delete p.dependencies['${pkg}'];fs.writeFileSync('package.json',JSON.stringify(p,null,2));"
echo "Stripped $pkg (not used in src/)"
else
echo "Keeping $pkg (used in src/)"
fi
done
# Delete package-lock.json (generated if user ever ran npm locally) so it doesn't
# conflict with yarn.lock. --legacy-peer-deps silences peer dep warnings from older
# Ionic/React packages that haven't updated their peerDependencies for React 18/19.
- name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets
script: npm run build
# Firebase config files are injected as base64 env vars by the Appcakes backend at
# build time. Decode them here so cap sync and Gradle can pick them up. Optional —
# builds without Firebase still succeed; native Firebase SDK just won't initialise.
- name: Write Firebase config
script: |
if [ -n "$GOOGLE_SERVICES_JSON" ]; then
echo "$GOOGLE_SERVICES_JSON" | base64 --decode > android/app/google-services.json
echo "Wrote google-services.json ($(wc -c < android/app/google-services.json) bytes)"
else
echo "GOOGLE_SERVICES_JSON is empty — skipping"
fi
if [ -n "$GOOGLE_SERVICE_INFO_PLIST" ]; then
echo "$GOOGLE_SERVICE_INFO_PLIST" | base64 --decode > ios/App/App/GoogleService-Info.plist
echo "Wrote GoogleService-Info.plist ($(wc -c < ios/App/App/GoogleService-Info.plist) bytes)"
fi
# cap sync copies the built web assets (dist/) into android/app/src/main/assets/public/
# and updates Capacitor plugin registrations in MainActivity. Must run after npm build.
- name: Capacitor sync
script: npx cap sync android
- name: Set up debug keystore
script: |
if [ -n "$CM_DEBUG_KEYSTORE" ]; then
echo "$CM_DEBUG_KEYSTORE" | base64 --decode > /tmp/debug-keystore.p12
fi
- name: Build debug APK
script: |
cd android
if [ -n "$CM_DEBUG_KEYSTORE" ]; then
./gradlew assembleDebug \
-Pandroid.injected.signing.store.file=/tmp/debug-keystore.p12 \
-Pandroid.injected.signing.store.password=$CM_DEBUG_KEYSTORE_PASSWORD \
-Pandroid.injected.signing.key.alias=debug \
-Pandroid.injected.signing.key.password=$CM_DEBUG_KEYSTORE_PASSWORD \
--no-daemon
else
./gradlew assembleDebug --no-daemon
fi
artifacts:
- android/app/build/outputs/apk/debug/app-debug.apk
android-release-apk:
name: Android Release APK
max_build_duration: 45
instance_type: mac_mini_m2
environment:
node: 22
java: 21
cache:
cache_paths:
- $HOME/.gradle/caches
- $HOME/.gradle/wrapper
scripts:
- name: Strip unused scaffold packages
script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
if ! grep -rq "$pkg" src/; then
node -e "const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));delete p.dependencies['${pkg}'];fs.writeFileSync('package.json',JSON.stringify(p,null,2));"
echo "Stripped $pkg (not used in src/)"
else
echo "Keeping $pkg (used in src/)"
fi
done
- name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets
script: npm run build
- name: Write Firebase config
script: |
if [ -n "$GOOGLE_SERVICES_JSON" ]; then
echo "$GOOGLE_SERVICES_JSON" | base64 --decode > android/app/google-services.json
fi
- name: Capacitor sync
script: npx cap sync android
- name: Set up keystore
script: echo "$CM_KEYSTORE" | base64 --decode > /tmp/keystore.jks
- name: Build Release APK
script: |
cd android
./gradlew assembleRelease \
-Pandroid.injected.signing.store.file=/tmp/keystore.jks \
-Pandroid.injected.signing.store.password=$CM_KEYSTORE_PASSWORD \
-Pandroid.injected.signing.key.alias=$CM_KEY_ALIAS \
-Pandroid.injected.signing.key.password=$CM_KEY_PASSWORD \
--no-daemon
artifacts:
- android/app/build/outputs/apk/release/app-release.apk
android-release-aab:
name: Android Release AAB
max_build_duration: 45
instance_type: mac_mini_m2
environment:
node: 22
java: 21
cache:
cache_paths:
- $HOME/.gradle/caches
- $HOME/.gradle/wrapper
scripts:
- name: Strip unused scaffold packages
script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
if ! grep -rq "$pkg" src/; then
node -e "const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));delete p.dependencies['${pkg}'];fs.writeFileSync('package.json',JSON.stringify(p,null,2));"
echo "Stripped $pkg (not used in src/)"
else
echo "Keeping $pkg (used in src/)"
fi
done
- name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets
script: npm run build
- name: Write Firebase config
script: |
if [ -n "$GOOGLE_SERVICES_JSON" ]; then
echo "$GOOGLE_SERVICES_JSON" | base64 --decode > android/app/google-services.json
fi
- name: Capacitor sync
script: npx cap sync android
- name: Set up keystore
script: echo "$CM_KEYSTORE" | base64 --decode > /tmp/keystore.jks
- name: Build Release AAB
script: |
cd android
./gradlew bundleRelease \
-Pandroid.injected.signing.store.file=/tmp/keystore.jks \
-Pandroid.injected.signing.store.password=$CM_KEYSTORE_PASSWORD \
-Pandroid.injected.signing.key.alias=$CM_KEY_ALIAS \
-Pandroid.injected.signing.key.password=$CM_KEY_PASSWORD \
--no-daemon
artifacts:
- android/app/build/outputs/bundle/release/app-release.aab
android-release:
name: Android Publish to Google Play
max_build_duration: 60
instance_type: mac_mini_m2
environment:
node: 22
java: 21
cache:
cache_paths:
- $HOME/.gradle/caches
- $HOME/.gradle/wrapper
scripts:
- name: Strip unused scaffold packages
script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
if ! grep -rq "$pkg" src/; then
node -e "const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));delete p.dependencies['${pkg}'];fs.writeFileSync('package.json',JSON.stringify(p,null,2));"
echo "Stripped $pkg (not used in src/)"
else
echo "Keeping $pkg (used in src/)"
fi
done
- name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets
script: npm run build
- name: Write Firebase config
script: |
if [ -n "$GOOGLE_SERVICES_JSON" ]; then
echo "$GOOGLE_SERVICES_JSON" | base64 --decode > android/app/google-services.json
fi
- name: Capacitor sync
script: npx cap sync android
- name: Set up keystore
script: echo "$CM_KEYSTORE" | base64 --decode > /tmp/keystore.jks
- name: Build Release AAB
script: |
cd android
./gradlew bundleRelease \
-Pandroid.injected.signing.store.file=/tmp/keystore.jks \
-Pandroid.injected.signing.store.password=$CM_KEYSTORE_PASSWORD \
-Pandroid.injected.signing.key.alias=$CM_KEY_ALIAS \
-Pandroid.injected.signing.key.password=$CM_KEY_PASSWORD \
--no-daemon
publishing:
google_play:
credentials: $GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS
track: $GOOGLE_PLAY_TRACK
submit_as_draft: false
artifacts:
- android/app/build/outputs/bundle/release/app-release.aab
ios-debug:
name: iOS Debug IPA
max_build_duration: 60
instance_type: mac_mini_m2
environment:
node: 22
xcode: latest
scripts:
- name: Strip unused scaffold packages
script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
if ! grep -rq "$pkg" src/; then
node -e "const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));delete p.dependencies['${pkg}'];fs.writeFileSync('package.json',JSON.stringify(p,null,2));"
echo "Stripped $pkg (not used in src/)"
else
echo "Keeping $pkg (used in src/)"
fi
done
- name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets
script: npm run build
# First sync: regenerates CapApp-SPM/Package.swift with the correct plugin list.
# Note: this project uses Capacitor SPM (no CocoaPods/Podfile), so cap sync replaces
# pod install — it regenerates CapApp-SPM/Package.swift and copies web assets.
- name: Capacitor sync
script: npx cap sync ios
# Decode Firebase plist to disk so it is present during the second sync.
- name: Write Firebase config
script: |
if [ -n "$GOOGLE_SERVICE_INFO_PLIST" ]; then
echo "$GOOGLE_SERVICE_INFO_PLIST" | base64 --decode > ios/App/App/GoogleService-Info.plist
fi
# Second sync ensures CapApp-SPM/Package.swift is consistent after the plist write.
- name: Capacitor sync
script: npx cap sync ios
# Run configure_xcode.rb after both syncs so its xcodeproj changes (plist file
# reference + SPM product linking) are not overwritten by a subsequent cap sync.
# configure_xcode.rb is stamped fresh from template on every build push.
- name: Configure Xcode project
script: ruby configure_xcode.rb
- name: Set up signing
script: |
keychain initialize
if [ -n "$APP_STORE_CONNECT_PRIVATE_KEY" ]; then
app-store-connect fetch-signing-files \
$(xcode-project detect-bundle-id) \
--type IOS_APP_DEVELOPMENT \
--certificate-key=@env:APP_STORE_CONNECT_PRIVATE_KEY \
--issuer-id=$APP_STORE_CONNECT_ISSUER_ID \
--key-id=$APP_STORE_CONNECT_KEY_IDENTIFIER \
--create
xcode-project use-profiles
elif [ -n "$CM_CERTIFICATE" ]; then
echo "$CM_CERTIFICATE" | base64 --decode > /tmp/cert.p12
keychain add-certificates \
--certificate /tmp/cert.p12 \
--certificate-password "$CM_CERTIFICATE_PASSWORD"
mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
echo "$CM_PROVISIONING_PROFILE" | base64 --decode > "$HOME/Library/MobileDevice/Provisioning Profiles/profile.mobileprovision"
xcode-project use-profiles
else
echo "No signing credentials configured — build will fail at signing"
exit 1
fi
# --workspace: Capacitor SPM projects require workspace context for Xcode to resolve
# the CapApp-SPM local package. Using --project causes xcodebuild to fail on
# Xcode 26+ because SPM resolution requires workspace scope. App.xcworkspace is a
# static file committed to the template (not generated by cap sync) that wraps
# App.xcodeproj for this purpose.
# --no-show-build-settings: xcode-project runs xcodebuild -showBuildSettings as a
# pre-build diagnostic. Xcode 26 fails this step for SPM projects even with
# --workspace, so we skip it. The actual archive step still surfaces real errors.
# --disable-xcpretty: xcpretty reformats and filters xcodebuild output, swallowing
# the actual error lines when a build fails. Raw output makes failures debuggable.
- name: Build IPA
script: |
xcode-project build-ipa \
--workspace ios/App/App.xcworkspace \
--scheme App \
--no-show-build-settings \
--disable-xcpretty
artifacts:
- build/ios/ipa/*.ipa
ios-release:
name: iOS Release IPA
max_build_duration: 90
instance_type: mac_mini_m2
environment:
node: 22
xcode: latest
scripts:
- name: Strip unused scaffold packages
script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
if ! grep -rq "$pkg" src/; then
node -e "const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));delete p.dependencies['${pkg}'];fs.writeFileSync('package.json',JSON.stringify(p,null,2));"
echo "Stripped $pkg (not used in src/)"
else
echo "Keeping $pkg (used in src/)"
fi
done
- name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets
script: npm run build
- name: Capacitor sync
script: npx cap sync ios
- name: Configure Xcode project
script: |
if [ -n "$GOOGLE_SERVICE_INFO_PLIST" ]; then
echo "$GOOGLE_SERVICE_INFO_PLIST" | base64 --decode > ios/App/App/GoogleService-Info.plist
fi
- name: Capacitor sync
script: npx cap sync ios
- name: Configure Xcode project
script: ruby configure_xcode.rb
- name: Set up signing
script: |
keychain initialize
if [ -n "$APP_STORE_CONNECT_PRIVATE_KEY" ]; then
app-store-connect fetch-signing-files \
$(xcode-project detect-bundle-id) \
--type IOS_APP_STORE \
--certificate-key=@env:APP_STORE_CONNECT_PRIVATE_KEY \
--issuer-id=$APP_STORE_CONNECT_ISSUER_ID \
--key-id=$APP_STORE_CONNECT_KEY_IDENTIFIER \
--create
xcode-project use-profiles
else
echo "$CM_CERTIFICATE" | base64 --decode > /tmp/cert.p12
keychain add-certificates \
--certificate /tmp/cert.p12 \
--certificate-password "$CM_CERTIFICATE_PASSWORD"
mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
echo "$CM_PROVISIONING_PROFILE" | base64 --decode > "$HOME/Library/MobileDevice/Provisioning Profiles/profile.mobileprovision"
xcode-project use-profiles
fi
# See ios-debug Build IPA comments for --workspace, --no-show-build-settings,
# and --disable-xcpretty rationale — same reasons apply here.
- name: Build IPA
script: |
xcode-project build-ipa \
--workspace ios/App/App.xcworkspace \
--scheme App \
--config Release \
--no-show-build-settings \
--disable-xcpretty
- name: Publish
script: |
if [ "$SUBMIT_TO_TESTFLIGHT" = "true" ] || [ "$SUBMIT_TO_APP_STORE" = "true" ]; then
app-store-connect publish \
--certificate-key=@env:APP_STORE_CONNECT_PRIVATE_KEY \
--issuer-id=$APP_STORE_CONNECT_ISSUER_ID \
--key-id=$APP_STORE_CONNECT_KEY_IDENTIFIER \
--submit-to-testflight=$SUBMIT_TO_TESTFLIGHT \
--submit-to-app-store=$SUBMIT_TO_APP_STORE
fi
artifacts:
- build/ios/ipa/*.ipa