From 3b283792ab8433286e6277806ab4cc8611677ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20=C5=A0=C4=87eki=C4=87?= Date: Thu, 22 Oct 2026 13:45:31 +0200 Subject: [PATCH 1/2] fix(ci): evaluate the release build config as the production profile --- .github/workflows/kilo-app-release.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/kilo-app-release.yml b/.github/workflows/kilo-app-release.yml index 59c4170841e..49211c79a0e 100644 --- a/.github/workflows/kilo-app-release.yml +++ b/.github/workflows/kilo-app-release.yml @@ -250,9 +250,19 @@ jobs: working-directory: apps/mobile env: EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }} + # eas-cli evaluates app.config.ts itself before it submits, and it syncs + # the App ID capabilities from what that evaluation returns. A release + # must be evaluated as the production profile: an unset EAS_BUILD_PROFILE + # makes app.config.ts evaluate as non-production, which puts the dev-only + # File Provider testing-mode entitlement in the extension's EAS entry. + # Apple then rejects the capability sync and the whole build command + # fails before any artifact exists. env:exec injects the production + # environment for that evaluation (a bare EAS_BUILD_PROFILE throws on the + # values it never sees), and SENTRY_AUTH_TOKEN is a SECRET variable only + # a builder can read, so the evaluation gets the preflight placeholder. run: | mkdir -p artifacts - pnpx eas-cli@24.8.0 build --profile production --platform all --non-interactive --json --wait > build.json + pnpx eas-cli@24.8.0 env:exec production --non-interactive 'EAS_BUILD_PROFILE=production SENTRY_AUTH_TOKEN=preflight-placeholder pnpx eas-cli@24.8.0 build --profile production --platform all --non-interactive --json --wait > build.json' node ../../scripts/inspect-mobile-artifacts.mjs --select build.json > urls.txt echo "IOS_URL=$(sed -n '1p' urls.txt)" >> "$GITHUB_ENV" echo "ANDROID_URL=$(sed -n '2p' urls.txt)" >> "$GITHUB_ENV" From 65d467e994209612937a5e86088182197ffc988f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20=C5=A0=C4=87eki=C4=87?= Date: Thu, 22 Oct 2026 13:52:45 +0200 Subject: [PATCH 2/2] test(mobile): assert the production config omits the File Provider testing mode --- apps/mobile/scripts/assert-expo-config.mjs | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/apps/mobile/scripts/assert-expo-config.mjs b/apps/mobile/scripts/assert-expo-config.mjs index 2de48066ea9..ddad2570c7d 100644 --- a/apps/mobile/scripts/assert-expo-config.mjs +++ b/apps/mobile/scripts/assert-expo-config.mjs @@ -345,6 +345,29 @@ check( appExtensions.some(extension => extension.targetName === 'ArtifactsFileProvider'), 'extra.eas.build.experimental.ios.appExtensions must carry the ArtifactsFileProvider target' ); +// Dev-only capability, asserted where it would break a release: Apple rejects +// the capability sync for `FILEPROVIDER_TESTINGMODE` on the extension's App ID, +// and App Store review rejects the entitlement itself. The release build and +// this assertion share one evaluation, so a production config that carried it +// would fail here before Apple sees it. +if (process.env.EAS_BUILD_PROFILE === 'production') { + const FILE_PROVIDER_TESTING_MODE = 'com.apple.developer.fileprovider.testing-mode'; + const fileProviderExtension = appExtensions.find( + extension => extension.targetName === 'ArtifactsFileProvider' + ); + check( + !(FILE_PROVIDER_TESTING_MODE in (config.ios?.entitlements ?? {})), + `a production build must not carry the ${FILE_PROVIDER_TESTING_MODE} app entitlement` + ); + check( + !('KiloArtifactsFileProviderTesting' in (config.ios?.infoPlist ?? {})), + 'a production build must not carry the KiloArtifactsFileProviderTesting Info.plist key' + ); + check( + !(FILE_PROVIDER_TESTING_MODE in (fileProviderExtension?.entitlements ?? {})), + `a production build must not carry the ${FILE_PROVIDER_TESTING_MODE} extension entitlement` + ); +} // The app target's one `Localizable.strings` (the App Intent copy plus the // appended Focus-filter catalog) is written by this plugin; without it the // Shortcuts actions and the Focus filter stay English on a localized device.