Repository navigation
Fix the iOS publish workflow so it can actually run - #1
Merged
Merged
Conversation
mirzemehdi
force-pushed
the
fix/ios-publish-without-mac
branch
2 times, most recently
from
August 16, 2026 14:08
8cc3470 to
ee8ce7c
Compare
The workflow has never run on any generated app — it needs eight secrets that nobody can produce without a Mac, so every KAppMaker user has been told to buy one to ship iOS. Three separate problems, all fixable: 1. Signing needed a hand-exported .p12 (IOS_APP_CERTIFICATE_P12_BASE64), and exporting one requires a Mac — the very thing this workflow exists to avoid. fastlane match now creates the certificate on the runner from the App Store Connect API key and stores it encrypted in a private repo, so the second and later builds reuse it. Xcode automatic signing is deliberately NOT used: it mints a new distribution certificate per run and Apple caps those at three per account, so it works three times and then fails forever. 2. local.properties was written with three keys, of which two (REVENUECAT_ANDROID_API_KEY, REVENUECAT_IOS_API_KEY) no longer exist — the build reads SUBSCRIPTION_PROVIDER_*. Meanwhile fourteen keys the build DOES read were missing. Every getRequiredProperty() carries a defaultValue, so this never failed the build: it shipped green binaries carrying and testValue, with dead sign-in, analytics and paywall. That is the worst failure mode available and it was silent. 3. Archive used CODE_SIGN_STYLE=Manual with a hardcoded profile UUID while export declared signingStyle=automatic — the two halves disagreed. Also a duplicated -destination flag. The build now goes through the project's own Fastfile rather than a parallel xcodebuild invocation, so -- Publishing Android to production track... -- Fastlane: Android Play Store release [15:58:45]: �[31mWARNING: fastlane requires your locale to be set to UTF-8. To learn more go to https://docs.fastlane.tools/getting-started/ios/setup/#set-up-environment-variables�[0m [15:58:45]: Detected package name: com.kotlinfoundation.koko [15:58:45]: �[32mDriving the lane 'android playstore_release' 🚀�[0m [15:58:45]: 🏗 Building Android AAB... [15:58:45]: �[32m--------------------------------------------------------------------�[0m [15:58:45]: �[32mStep: cd /private/tmp/claude-501/-Users-mirzemehdi-Documents-SAAS-KAppMaker-KAppMaker-AI/932620e6-77bb-4ad5-9df3-8db04538eacc/scratchpad/kappmaker-all/MobileApp && ./gradlew :androidApp:bundleRelease�[0m [15:58:45]: �[32m--------------------------------------------------------------------�[0m [15:58:45]: �[36m$ cd /private/tmp/claude-501/-Users-mirzemehdi-Documents-SAAS-KAppMaker-KAppMaker-AI/932620e6-77bb-4ad5-9df3-8db04538eacc/scratchpad/kappmaker-all/MobileApp && ./gradlew :androidApp:bundleRelease�[0m [15:58:46]: ▸ �[35mStarting a Gradle Daemon, 1 incompatible Daemon could not be reused, use --status for details�[0m [15:58:46]: ▸ �[35mFAILURE: Build failed with an exception.�[0m [15:58:46]: ▸ �[35m* What went wrong:�[0m [15:58:46]: ▸ �[35mGradle requires JVM 17 or later to run. Your build is currently configured to use JVM 11.�[0m [15:58:46]: ▸ �[35m* Try:�[0m [15:58:46]: ▸ �[35m> Run with --stacktrace option to get the stack trace.�[0m [15:58:46]: ▸ �[35m> Run with --info or --debug option to get more log output.�[0m [15:58:46]: ▸ �[35m> Run with --scan to get full insights from a Build Scan (powered by Develocity).�[0m [15:58:46]: ▸ �[35m> Get more help at https://help.gradle.org.�[0m +-------------------------------------------+ | �[33mLane Context�[0m | +---------------+---------------------------+ | PLATFORM_NAME | android | | LANE_NAME | android playstore_release | +---------------+---------------------------+ [15:58:46]: �[31mCalled from Fastfile at line 108�[0m [15:58:46]: �[31m```�[0m [15:58:46]: �[31m 106: # Build AAB�[0m [15:58:46]: �[31m 107: UI.message("🏗 Building Android AAB...")�[0m [15:58:46]: �[31m => 108: sh("cd #{root_dir} && ./gradlew :androidApp:bundleRelease")�[0m [15:58:46]: �[31m 109: �[0m [15:58:46]: �[31m 110: # Find generated AAB�[0m [15:58:46]: �[31m```�[0m [15:58:46]: �[31mExit status of command 'cd /private/tmp/claude-501/-Users-mirzemehdi-Documents-SAAS-KAppMaker-KAppMaker-AI/932620e6-77bb-4ad5-9df3-8db04538eacc/scratchpad/kappmaker-all/MobileApp && ./gradlew :androidApp:bundleRelease' was 1 instead of 0. Starting a Gradle Daemon, 1 incompatible Daemon could not be reused, use --status for details FAILURE: Build failed with an exception. * What went wrong: Gradle requires JVM 17 or later to run. Your build is currently configured to use JVM 11. * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to get full insights from a Build Scan (powered by Develocity). > Get more help at https://help.gradle.org. �[0m +---------------------------------------------+ | �[32mfastlane summary�[0m | +------+------------------------+-------------+ | Step | Action | Time (in s) | +------+------------------------+-------------+ | 💥 | �[31mcd �[0m | 0 | | | �[31m/private/tmp/claude-5 �[0m | | | | �[31m01/-Users-mirzemehdi- �[0m | | | | �[31mDocuments-SAAS-K�[0m | | +------+------------------------+-------------+ [15:58:46]: �[31mfastlane finished with errors�[0m Looking for related GitHub issues on fastlane/fastlane... ####################################################################### # fastlane 2.238.0 is available. You are on 2.231.1. # You should use the latest version. # Please update using `bundle update fastlane`. ####################################################################### �[32m2.238.0 Improvements�[0m * [ci] support releases with PRs that were deleted (or users) (#30105) via Connor Tumbleson (@iBotPeaches) * [pilot] Match groups by either name or id (#30104) via Alexander Chapliuk (@krin-san) * [update_project_team] add support for sdk conditionals (#30142) via Connor Tumbleson (@iBotPeaches) * harden: detected non-static command inside ` in... (#30148) via Anupam Mediratta (@anupamme) * [fastlane_core] Create a unique package directory for non-macOS uploads (#30144) via Victor Amorim dos Santos (@victoramsantos) * [gem] move to webrick 1.9.x (#30135) via Connor Tumbleson (@iBotPeaches) * [gem] upgrade 'terminal-table' to drop monkey patch (#30137) via Connor Tumbleson (@iBotPeaches) * [core] Fix video resolution parsing when audio track precedes video track (#30143) via Thomas Walther (@tcwalther) * [gym] Fix Mac Catalyst package type detection when catalyst_platform is not set (#29829) via Josh Holtz (@joshdholtz) * [deliver/pilot] change instruction on how to run iTMSTransporter (#21155) via Merlin Ran (@merlinran) * [gem] move to sinatra 4 (#30134) via Connor Tumbleson (@iBotPeaches) * [action][spm] add `--skip-update` (#21127) via Atsuto Yamashita (@att55) * Fix precheck copyright rule wording (#19500) via Andreas Ganske (@ChaosCoder) * docs: add detailed notation of what metrics collected (#30132) via Connor Tumbleson (@iBotPeaches) * Bump actions/labeler from 6 to 7 (#30133) via dependabot[bot] (@dependabot[bot]) * [upload_symbols_to_crashlytics] Adds option to let the action fail when an upload fails (#29700) via Tobias Kreß (@Myrronth) * [deliver] add support for social media rating keys (#30128) via Connor Tumbleson (@iBotPeaches) * [core] Support for Ruby 4 (+ testing) (#29849) via Connor Tumbleson (@iBotPeaches) * [register_devices] Ignore blank lines and comment lines in devices_file (#30129) via David Cordero (@dcordero) * [core] detect installed Developer ID intermediate certificates by their common name (#30126) via Rinat Kutuev (@ReilganInt) * [core] move to xcodeproj 1.28.1 (from 1.27.0) (#30124) via Nuno de Carvalho (@nmcc24) * [core] normalize FastlaneSwiftRunner.xcodeproj plist quoting (#30125) via Nuno de Carvalho (@nmcc24) * [register_devices] Register devices normalization for UDIDs. (#29981) via Muhammet Ilendemli (@ilendemli) * [crashlytics] improve logging during error (#30077) via Connor Tumbleson (@iBotPeaches) * [setup_ci] Add option to opt out of setting the default keychain (#30121) via Eyüp Can Akman (@eyupcanakman) * [snapshot] Open the requested simulator for non-headless runs (#30119) via huven (@huven) * [core] improve operating_system detection (#30118) via Connor Tumbleson (@iBotPeaches) * [core] fix: upgrade yard to >= 0.9.42 (CVE-2026-41493) (#30117) via OrbisAI Security (@orbisai0security) * [core] move to Faraday 2 (#30089) via Connor Tumbleson (@iBotPeaches) * [docs] clarify platform resolution behavior (#22185) via Douglas Hill (@douglashill) * [core] fix crash when uploading large `.pkg` by using `Digest::MD5.file` instead of `Digest::MD5.hexdigest` (#21999) via reflexing (@reflexing) * [docs] fix a missing negation in `pilot` error message (#22331) via Gemma Barlow (@gemmakbarlow) * [notarize] Fix erroring out with `bundle_id` parameter being absent (#29736) via Timur Sharifianov (@Scvairy) * [metrics] move to GA4 and improve metrics (#30111) via Connor Tumbleson (@iBotPeaches) �[32m2.237.0 Improvements�[0m * [ci] drop CircleCI for GHA (#30108) via Connor Tumbleson (@iBotPeaches) * [fastlane_core] Restore altool -f flag, keep -assetFile only for iTMSTransporter (#30106) via Roman Gardukevich (@OdNairy) * [gym] handle xcpretty errors cleaner & promote xcbeautify (#30099) via Connor Tumbleson (@iBotPeaches) * [docs] Reflect specification changes regarding iPad Pro 12.9-inch screenshots in `deliver` (#30103) via 417-72KI (@417-72KI) * [core] Reduce duplication on output and noise during failure. (#30097) via Connor Tumbleson (@iBotPeaches) * Bump actions/checkout from 6 to 7 (#30100) via dependabot[bot] (@dependabot[bot]) * [match] Restore renew expired certs (opt in) (#30096) via Roman Gardukevich (@OdNairy) * [match] fail fast for SSH authentication prompts in non-interactive shell (#30078) via Pratik Patil (@PratikPatil131) * [gem] move to faraday 1.10.6 (#30095) via Connor Tumbleson (@iBotPeaches) * [core] Skip repeating the output again when an sh command fails (#19545) via Peter Tutervai (@tutipeti) * [scan] Forward force_legacy_xcresulttool to trainer (#30092) via Eyüp Can Akman (@eyupcanakman) * [trainer] Fix output_remove_retry_attempts not stripping failures for skipped-on-retry tests (modern xcresult parser) (#30081) via Oliver Fox (@foxware00) * [scan] Handle array destination in xcodebuild_destination_parameter (#30069) via Ricardo Sawir (@sawirricardo) * [action][swiftlint] Fix path option for SwiftLint 0.48.0 and above (#30080) via Augusto Xavier (@augustocbx) * [ci] move more workflows from CircleCI -> GHA (#30090) via Connor Tumbleson (@iBotPeaches) * [core] remove upper bound on excon (#30085) via Connor Tumbleson (@iBotPeaches) * Bump actions/checkout from 6 to 7 (#30091) via dependabot[bot] (@dependabot[bot]) * [spaceship] Fix appInfoLocalizations create/delete on the Tunes API (#30084) via Marcel Hoppe (@hoppsen) * [match] Fix keychain import path escaping (#30072) via Ricardo Sawir (@sawirricardo) * [precheck] Fix copyright year check to allow past years (#30076) via Augusto Xavier (@augustocbx) * [supply] Fix version_codes_to_retain causing promote-only flow to use… (#30073) via Pratik Patil (@PratikPatil131) * Bump rubygems/configure-rubygems-credentials from 2.0.0 to 2.1.0 (#30074) via dependabot[bot] (@dependabot[bot]) * [fastlane_core] Fix deprecated Transporter -f flag, use -assetFile fo… (#30061) via Pratik Patil (@PratikPatil131) * [core] fix: update addressable to 2.9.0 min for CVE-2026-35611 (#30060) via OrbisAI Security (@orbisai0security) �[32m2.236.1 Improvements�[0m * Revert "[transporter] Decode Base64 key content for .p8 file generation in Al…" (#30066) via Connor Tumbleson (@iBotPeaches) �[32mTo see all new releases, open https://github.com/fastlane/fastlane/releases�[0m �[32mPlease update using `bundle update fastlane`�[0m [15:58:47]: �[31mWARNING: fastlane requires your locale to be set to UTF-8. To learn more go to https://docs.fastlane.tools/getting-started/ios/setup/#set-up-environment-variables�[0m locally and CI run the same code and cannot drift. Adds workflow_dispatch (on-demand, and drivable by tooling) alongside the existing tag trigger, keeps the GitHub release step for tags, and uploads the .ipa as an artifact so a failed upload does not cost another 20-minute rebuild. [1/6] Checking prerequisites -- Repo: KAppMaker/KAppMaker-All -- App dir: MobileApp -- Bundle ID: com.kotlinfoundation.koko WARN KAppMaker/KAppMaker-All is PUBLIC. Secrets stay private, but anyone can read your source and build logs. [2/6] Setting up the signing-certificate repo OK Created private repo KAppMaker/KAppMaker-All-certs [3/6] Resolving the certificate password [4/6] Pushing secrets to GitHub provisions the certs repo and every secret listed at the top of the file.
mirzemehdi
added a commit
that referenced
this pull request
Aug 16, 2026
PR #1 merged before the pipeline had been run end to end. Three problems remained on main, each fatal on its own: xcargs: '-allowProvisioningUpdates NO' — the flag takes no value, so xcodebuild read NO as a build action and refused to start. The lane took a bump_build option the workflow never declared as an input, so every tool-triggered dispatch was rejected with HTTP 422. Dropped: update-version owns the build number and keeps it in git where it is auditable. Signing could not go through xcargs at all, because those settings hit every target and the Swift Package dependencies reject a provisioning profile. It is now applied per target with update_code_signing_settings, and manually: on automatic Xcode looks for a Development profile while match installs an App Store one. DEVELOPMENT_TEAM comes from match, since the project sets none. Verified against a live Apple account up to and including the Kotlin/Native iOS compile; the remaining failure is in the test app's own source.
mirzemehdi
added a commit
that referenced
this pull request
Aug 16, 2026
…otlinFoundation#48) * Fix the iOS publish workflow so it can actually run (#1) The workflow has never run on any generated app — it needs eight secrets that nobody can produce without a Mac, so every KAppMaker user has been told to buy one to ship iOS. Three separate problems, all fixable: 1. Signing needed a hand-exported .p12 (IOS_APP_CERTIFICATE_P12_BASE64), and exporting one requires a Mac — the very thing this workflow exists to avoid. fastlane match now creates the certificate on the runner from the App Store Connect API key and stores it encrypted in a private repo, so the second and later builds reuse it. Xcode automatic signing is deliberately NOT used: it mints a new distribution certificate per run and Apple caps those at three per account, so it works three times and then fails forever. 2. local.properties was written with three keys, of which two (REVENUECAT_ANDROID_API_KEY, REVENUECAT_IOS_API_KEY) no longer exist — the build reads SUBSCRIPTION_PROVIDER_*. Meanwhile fourteen keys the build DOES read were missing. Every getRequiredProperty() carries a defaultValue, so this never failed the build: it shipped green binaries carrying and testValue, with dead sign-in, analytics and paywall. That is the worst failure mode available and it was silent. 3. Archive used CODE_SIGN_STYLE=Manual with a hardcoded profile UUID while export declared signingStyle=automatic — the two halves disagreed. Also a duplicated -destination flag. The build now goes through the project's own Fastfile rather than a parallel xcodebuild invocation, so -- Publishing Android to production track... -- Fastlane: Android Play Store release [15:58:45]: �[31mWARNING: fastlane requires your locale to be set to UTF-8. To learn more go to https://docs.fastlane.tools/getting-started/ios/setup/#set-up-environment-variables�[0m [15:58:45]: Detected package name: com.kotlinfoundation.koko [15:58:45]: �[32mDriving the lane 'android playstore_release' 🚀�[0m [15:58:45]: 🏗 Building Android AAB... [15:58:45]: �[32m--------------------------------------------------------------------�[0m [15:58:45]: �[32mStep: cd /private/tmp/claude-501/-Users-mirzemehdi-Documents-SAAS-KAppMaker-KAppMaker-AI/932620e6-77bb-4ad5-9df3-8db04538eacc/scratchpad/kappmaker-all/MobileApp && ./gradlew :androidApp:bundleRelease�[0m [15:58:45]: �[32m--------------------------------------------------------------------�[0m [15:58:45]: �[36m$ cd /private/tmp/claude-501/-Users-mirzemehdi-Documents-SAAS-KAppMaker-KAppMaker-AI/932620e6-77bb-4ad5-9df3-8db04538eacc/scratchpad/kappmaker-all/MobileApp && ./gradlew :androidApp:bundleRelease�[0m [15:58:46]: ▸ �[35mStarting a Gradle Daemon, 1 incompatible Daemon could not be reused, use --status for details�[0m [15:58:46]: ▸ �[35mFAILURE: Build failed with an exception.�[0m [15:58:46]: ▸ �[35m* What went wrong:�[0m [15:58:46]: ▸ �[35mGradle requires JVM 17 or later to run. Your build is currently configured to use JVM 11.�[0m [15:58:46]: ▸ �[35m* Try:�[0m [15:58:46]: ▸ �[35m> Run with --stacktrace option to get the stack trace.�[0m [15:58:46]: ▸ �[35m> Run with --info or --debug option to get more log output.�[0m [15:58:46]: ▸ �[35m> Run with --scan to get full insights from a Build Scan (powered by Develocity).�[0m [15:58:46]: ▸ �[35m> Get more help at https://help.gradle.org.�[0m +-------------------------------------------+ | �[33mLane Context�[0m | +---------------+---------------------------+ | PLATFORM_NAME | android | | LANE_NAME | android playstore_release | +---------------+---------------------------+ [15:58:46]: �[31mCalled from Fastfile at line 108�[0m [15:58:46]: �[31m```�[0m [15:58:46]: �[31m 106: # Build AAB�[0m [15:58:46]: �[31m 107: UI.message("🏗 Building Android AAB...")�[0m [15:58:46]: �[31m => 108: sh("cd #{root_dir} && ./gradlew :androidApp:bundleRelease")�[0m [15:58:46]: �[31m 109: �[0m [15:58:46]: �[31m 110: # Find generated AAB�[0m [15:58:46]: �[31m```�[0m [15:58:46]: �[31mExit status of command 'cd /private/tmp/claude-501/-Users-mirzemehdi-Documents-SAAS-KAppMaker-KAppMaker-AI/932620e6-77bb-4ad5-9df3-8db04538eacc/scratchpad/kappmaker-all/MobileApp && ./gradlew :androidApp:bundleRelease' was 1 instead of 0. Starting a Gradle Daemon, 1 incompatible Daemon could not be reused, use --status for details FAILURE: Build failed with an exception. * What went wrong: Gradle requires JVM 17 or later to run. Your build is currently configured to use JVM 11. * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to get full insights from a Build Scan (powered by Develocity). > Get more help at https://help.gradle.org. �[0m +---------------------------------------------+ | �[32mfastlane summary�[0m | +------+------------------------+-------------+ | Step | Action | Time (in s) | +------+------------------------+-------------+ | 💥 | �[31mcd �[0m | 0 | | | �[31m/private/tmp/claude-5 �[0m | | | | �[31m01/-Users-mirzemehdi- �[0m | | | | �[31mDocuments-SAAS-K�[0m | | +------+------------------------+-------------+ [15:58:46]: �[31mfastlane finished with errors�[0m Looking for related GitHub issues on fastlane/fastlane... ####################################################################### # fastlane 2.238.0 is available. You are on 2.231.1. # You should use the latest version. # Please update using `bundle update fastlane`. ####################################################################### �[32m2.238.0 Improvements�[0m * [ci] support releases with PRs that were deleted (or users) (#30105) via Connor Tumbleson (@iBotPeaches) * [pilot] Match groups by either name or id (#30104) via Alexander Chapliuk (@krin-san) * [update_project_team] add support for sdk conditionals (#30142) via Connor Tumbleson (@iBotPeaches) * harden: detected non-static command inside ` in... (#30148) via Anupam Mediratta (@anupamme) * [fastlane_core] Create a unique package directory for non-macOS uploads (#30144) via Victor Amorim dos Santos (@victoramsantos) * [gem] move to webrick 1.9.x (#30135) via Connor Tumbleson (@iBotPeaches) * [gem] upgrade 'terminal-table' to drop monkey patch (#30137) via Connor Tumbleson (@iBotPeaches) * [core] Fix video resolution parsing when audio track precedes video track (#30143) via Thomas Walther (@tcwalther) * [gym] Fix Mac Catalyst package type detection when catalyst_platform is not set (#29829) via Josh Holtz (@joshdholtz) * [deliver/pilot] change instruction on how to run iTMSTransporter (#21155) via Merlin Ran (@merlinran) * [gem] move to sinatra 4 (#30134) via Connor Tumbleson (@iBotPeaches) * [action][spm] add `--skip-update` (#21127) via Atsuto Yamashita (@att55) * Fix precheck copyright rule wording (#19500) via Andreas Ganske (@ChaosCoder) * docs: add detailed notation of what metrics collected (#30132) via Connor Tumbleson (@iBotPeaches) * Bump actions/labeler from 6 to 7 (#30133) via dependabot[bot] (@dependabot[bot]) * [upload_symbols_to_crashlytics] Adds option to let the action fail when an upload fails (#29700) via Tobias Kreß (@Myrronth) * [deliver] add support for social media rating keys (#30128) via Connor Tumbleson (@iBotPeaches) * [core] Support for Ruby 4 (+ testing) (#29849) via Connor Tumbleson (@iBotPeaches) * [register_devices] Ignore blank lines and comment lines in devices_file (#30129) via David Cordero (@dcordero) * [core] detect installed Developer ID intermediate certificates by their common name (#30126) via Rinat Kutuev (@ReilganInt) * [core] move to xcodeproj 1.28.1 (from 1.27.0) (#30124) via Nuno de Carvalho (@nmcc24) * [core] normalize FastlaneSwiftRunner.xcodeproj plist quoting (#30125) via Nuno de Carvalho (@nmcc24) * [register_devices] Register devices normalization for UDIDs. (#29981) via Muhammet Ilendemli (@ilendemli) * [crashlytics] improve logging during error (#30077) via Connor Tumbleson (@iBotPeaches) * [setup_ci] Add option to opt out of setting the default keychain (#30121) via Eyüp Can Akman (@eyupcanakman) * [snapshot] Open the requested simulator for non-headless runs (#30119) via huven (@huven) * [core] improve operating_system detection (#30118) via Connor Tumbleson (@iBotPeaches) * [core] fix: upgrade yard to >= 0.9.42 (CVE-2026-41493) (#30117) via OrbisAI Security (@orbisai0security) * [core] move to Faraday 2 (#30089) via Connor Tumbleson (@iBotPeaches) * [docs] clarify platform resolution behavior (#22185) via Douglas Hill (@douglashill) * [core] fix crash when uploading large `.pkg` by using `Digest::MD5.file` instead of `Digest::MD5.hexdigest` (#21999) via reflexing (@reflexing) * [docs] fix a missing negation in `pilot` error message (#22331) via Gemma Barlow (@gemmakbarlow) * [notarize] Fix erroring out with `bundle_id` parameter being absent (#29736) via Timur Sharifianov (@Scvairy) * [metrics] move to GA4 and improve metrics (#30111) via Connor Tumbleson (@iBotPeaches) �[32m2.237.0 Improvements�[0m * [ci] drop CircleCI for GHA (#30108) via Connor Tumbleson (@iBotPeaches) * [fastlane_core] Restore altool -f flag, keep -assetFile only for iTMSTransporter (#30106) via Roman Gardukevich (@OdNairy) * [gym] handle xcpretty errors cleaner & promote xcbeautify (#30099) via Connor Tumbleson (@iBotPeaches) * [docs] Reflect specification changes regarding iPad Pro 12.9-inch screenshots in `deliver` (#30103) via 417-72KI (@417-72KI) * [core] Reduce duplication on output and noise during failure. (#30097) via Connor Tumbleson (@iBotPeaches) * Bump actions/checkout from 6 to 7 (#30100) via dependabot[bot] (@dependabot[bot]) * [match] Restore renew expired certs (opt in) (#30096) via Roman Gardukevich (@OdNairy) * [match] fail fast for SSH authentication prompts in non-interactive shell (#30078) via Pratik Patil (@PratikPatil131) * [gem] move to faraday 1.10.6 (#30095) via Connor Tumbleson (@iBotPeaches) * [core] Skip repeating the output again when an sh command fails (#19545) via Peter Tutervai (@tutipeti) * [scan] Forward force_legacy_xcresulttool to trainer (#30092) via Eyüp Can Akman (@eyupcanakman) * [trainer] Fix output_remove_retry_attempts not stripping failures for skipped-on-retry tests (modern xcresult parser) (#30081) via Oliver Fox (@foxware00) * [scan] Handle array destination in xcodebuild_destination_parameter (#30069) via Ricardo Sawir (@sawirricardo) * [action][swiftlint] Fix path option for SwiftLint 0.48.0 and above (#30080) via Augusto Xavier (@augustocbx) * [ci] move more workflows from CircleCI -> GHA (#30090) via Connor Tumbleson (@iBotPeaches) * [core] remove upper bound on excon (#30085) via Connor Tumbleson (@iBotPeaches) * Bump actions/checkout from 6 to 7 (#30091) via dependabot[bot] (@dependabot[bot]) * [spaceship] Fix appInfoLocalizations create/delete on the Tunes API (#30084) via Marcel Hoppe (@hoppsen) * [match] Fix keychain import path escaping (#30072) via Ricardo Sawir (@sawirricardo) * [precheck] Fix copyright year check to allow past years (#30076) via Augusto Xavier (@augustocbx) * [supply] Fix version_codes_to_retain causing promote-only flow to use… (#30073) via Pratik Patil (@PratikPatil131) * Bump rubygems/configure-rubygems-credentials from 2.0.0 to 2.1.0 (#30074) via dependabot[bot] (@dependabot[bot]) * [fastlane_core] Fix deprecated Transporter -f flag, use -assetFile fo… (#30061) via Pratik Patil (@PratikPatil131) * [core] fix: update addressable to 2.9.0 min for CVE-2026-35611 (#30060) via OrbisAI Security (@orbisai0security) �[32m2.236.1 Improvements�[0m * Revert "[transporter] Decode Base64 key content for .p8 file generation in Al…" (#30066) via Connor Tumbleson (@iBotPeaches) �[32mTo see all new releases, open https://github.com/fastlane/fastlane/releases�[0m �[32mPlease update using `bundle update fastlane`�[0m [15:58:47]: �[31mWARNING: fastlane requires your locale to be set to UTF-8. To learn more go to https://docs.fastlane.tools/getting-started/ios/setup/#set-up-environment-variables�[0m locally and CI run the same code and cannot drift. Adds workflow_dispatch (on-demand, and drivable by tooling) alongside the existing tag trigger, keeps the GitHub release step for tags, and uploads the .ipa as an artifact so a failed upload does not cost another 20-minute rebuild. [1/6] Checking prerequisites -- Repo: KAppMaker/KAppMaker-All -- App dir: MobileApp -- Bundle ID: com.kotlinfoundation.koko WARN KAppMaker/KAppMaker-All is PUBLIC. Secrets stay private, but anyone can read your source and build logs. [2/6] Setting up the signing-certificate repo OK Created private repo KAppMaker/KAppMaker-All-certs [3/6] Resolving the certificate password [4/6] Pushing secrets to GitHub provisions the certs repo and every secret listed at the top of the file. * Fix the iOS signing configuration that six real builds exposed (#2) PR #1 merged before the pipeline had been run end to end. Three problems remained on main, each fatal on its own: xcargs: '-allowProvisioningUpdates NO' — the flag takes no value, so xcodebuild read NO as a build action and refused to start. The lane took a bump_build option the workflow never declared as an input, so every tool-triggered dispatch was rejected with HTTP 422. Dropped: update-version owns the build number and keeps it in git where it is auditable. Signing could not go through xcargs at all, because those settings hit every target and the Swift Package dependencies reject a provisioning profile. It is now applied per target with update_code_signing_settings, and manually: on automatic Xcode looks for a Development profile while match installs an App Store one. DEVELOPMENT_TEAM comes from match, since the project sets none. Verified against a live Apple account up to and including the Kotlin/Native iOS compile; the remaining failure is in the test app's own source. * Use the template's own app name in the iOS publish workflow Carried over from the source repo: the workflow named that app and kept an internal version marker. refactor_package.sh rewrites app_name in this file from rootProject.name, so the template has to ship Koko for a generated app to get its own name. * Changelog entry for the iOS publishing fixes * Write every build key in the Android and PR workflows too The iOS fix only covered one of three workflows. Android release builds and PR checks still wrote the same three-key block, two of which (REVENUECAT_ANDROID_API_KEY, REVENUECAT_IOS_API_KEY) no longer exist — the build reads SUBSCRIPTION_PROVIDER_*. So Play Store releases shipped with the same silent placeholders the iOS workflow was just fixed for: getRequiredProperty carries a defaultValue, the build stays green, and the app ships with dead sign-in, ads, AI and paywall. All three workflows now derive the key list from local.properties.example, so adding a key there needs no workflow edit. The release workflows warn about any key with no matching repo secret; PR checks stay silent because they ship nothing and fork PRs get no secrets at all. Verified the two lists agree: the build reads 15 keys and the example file lists exactly those 15. * Changelog entry for the Android and PR workflow key fix * Update the signing and publishing skills for the new secret set setup-signing still told developers to export a p12 and collect provisioning profile UUIDs, none of which the workflow uses now. It documents the four iOS secrets that exist, says plainly that MATCH_PASSWORD is theirs to invent rather than something Apple issues, warns that Apple caps distribution certificates at three per account, and adds the rule the workflows depend on: every key in local.properties.example needs a repo secret of the same name, because a missing one ships a placeholder instead of failing. Also bump the Documentation submodule for the matching docs-site changes. * Changelog entry for the publishing docs update * Share one certificate store per Apple account, not per app (#3) An iOS distribution certificate belongs to the Apple Developer account and Apple issues at most three; a provisioning profile is the per-app piece. Storing the certificate on a branch of each app's own repo therefore minted a certificate per app and locked the account out on the fourth. Signing material now comes from a separate private repo shared across the account, supplied as MATCH_GIT_URL, with a PAT for cross-repo read since the built-in GITHUB_TOKEN only reaches the repo it runs in. * Point at the manual certs-repo setup instead of a CLI the template has no * Share one certificate store per Apple account in the skills and docs Follows the workflow change: setup-signing now explains why the certs repo is separate from the app repo (Apple issues three distribution certificates per account, so a per-app store locks you out on the fourth), lists MATCH_GIT_URL and MATCH_GIT_BASIC_AUTHORIZATION with the commands that produce them, and corrects APPSTORE_PRIVATE_KEY to the base64 of the .p8 — the Fastfile passes is_key_content_base64, so the raw contents would fail. Every value now says where it comes from: which App Store Connect page, which role the API key needs, and why the built-in GITHUB_TOKEN cannot reach the certs repo. * Run match read-only by default (#4) Apple issues at most two Apple Distribution certificates per account, shared by every app. With readonly:false match mints a new one whenever it is not satisfied with what it finds, so a couple of builds can consume both slots and lock the account out of iOS releases entirely. Builds now only use the certificate store; MATCH_READONLY=false covers the single bootstrap run that populates an empty one. * Correct the certificate limit to two and document MATCH_READONLY The count came from the earlier commit and was wrong: Apple issues two Apple Distribution certificates per account, not three, which makes the per-app store worse than described and the read-only default more important. Releases now run match read-only so no build can mint a certificate. Document the one exception — MATCH_READONLY=false for the single bootstrap run against an empty certs repo — and say plainly to unset it afterwards, since leaving it on lets any later build exhaust the account. * Re-trigger CI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This workflow has never run on any generated app. It required a secret nobody can produce without a Mac — so shipping iOS effectively meant buying one. Three separate problems:
1. Signing required a hand-exported
.p12IOS_APP_CERTIFICATE_P12_BASE64can only be exported from a Mac keychain — the exact thing this workflow exists to avoid. Replaced with fastlanematch, which creates the certificate on the runner from the App Store Connect API key.The encrypted certificates are committed to a
match-certificatesbranch of the same repository, so the built-inGITHUB_TOKENreaches them: no second repo and no personal access token. The git URL and auth are derived from the Actions context rather than stored as secrets.Xcode automatic signing is deliberately not used: it mints a new distribution certificate per run and Apple caps those at three per account. It works three times, then fails permanently.
2.
local.propertieswas wrong in both directionsIt wrote three keys — two of which (
REVENUECAT_ANDROID_API_KEY,REVENUECAT_IOS_API_KEY) no longer exist; the build readsSUBSCRIPTION_PROVIDER_*. Meanwhile 14 keys the build does read were missing (Firebase ×3, OpenAI, Replicate, AdMob ×7, subscription provider ×2).This never failed a build, because every
getRequiredProperty()declares adefaultValue. It shipped green binaries carrying""and"testValue"— dead sign-in, no analytics, broken paywall. Silent, and the worst failure mode available.Rather than replace one hardcoded list with another, the step now derives the key list from
MobileApp/local.properties.exampleand pulls each value out oftoJSON(secrets). Adding a key means editing that one file and setting a repo secret of the same name — the workflow never needs touching again. Keys with no secret are written empty and reported as a build annotation, rather than failing the release: a placeholder only breaks the feature that uses it, and a half-configured app still needs to reach TestFlight.3. Signing config contradicted itself
Archive used
CODE_SIGN_STYLE=Manualwith a hardcoded profile UUID; export declaredsigningStyle: automatic. Plus a duplicated-destinationflag.Also
xcodebuildinvocation, so a local release and a CI release run the same lane.workflow_dispatch(on-demand) alongside the existing tag trigger..ipaas an artifact, so a failed upload doesn't cost another 20-minute rebuild.Secrets required after this change
APPSTORE_KEY_ID,APPSTORE_ISSUER_ID,APPSTORE_PRIVATE_KEY,MATCH_PASSWORD,GRADLE_CACHE_ENCRYPTION_KEY, plus one per build key in thelocal.propertiesstep.Gone:
IOS_APP_CERTIFICATE_P12_BASE64,IOS_APP_CERTIFICATE_P12_PASSWORD,IOS_APP_DEVELOPMENT_PROVISION_UUID,APPSTORE_TEAM_ID.Not yet proven
No live run against a real Apple account. Two unknowns, both pre-existing: whether
xcodebuildresolves theiosAppscheme with no shared scheme committed, and whether the ASC API key's role permits certificate creation.If this repo is public, the encrypted certificates on the branch are public too — useless without
MATCH_PASSWORD, but worth a deliberate decision.