fix(android): make prebuild work on Expo SDK 56 and 57 - #28
Merged
Conversation
`applyImplementation` searched app/build.gradle for one of four
`apply from:` lines and threw when it found none. React Native 0.75
folded autolinking into `autolinkLibrariesWithApp()` inside the
`react { }` block, so by Expo SDK 56 the file has no `apply from:` left
and prebuild died with "Cannot find a suitable place to insert the
CodePush buildscript dependency".
Those anchors were never the requirement. `codepush.gradle` reads the
`react` extension and iterates `android.buildTypes` as it is applied, so
it has to run after both blocks are configured, and the end of the file
is where that holds on every template. It also happens to be where the
old anchor sat in RN 0.71-0.73, so SDK 49 and 50 land in the same place
they always did.
Closes #26
Claude-Session: https://claude.ai/code/session_01QsVEsfkynXpJWK4t33exG9
Expo SDK 56 dropped `ReactNativeHost` from the template, so there is no `getJSBundleFile()` left to override. `MainApplication` now builds a `ReactHost` through `ExpoReactHostFactory.getDefaultReactHost`, which takes `jsBundleFilePath` as an argument instead. The mod passes `CodePush.getJSBundleFile()` there. It has to be the last argument: Kotlin evaluates arguments in source order, and that call throws until `PackageList(this).packages` has constructed the CodePush instance. Finding the closing parenthesis means matching it rather than searching for one, since the template's argument list contains a commented-out `add(MyReactNativePackage())`. The import anchor moves with it. It used to be `import expo.modules.ReactNativeHostWrapper`, which SDK 56 also stopped emitting, and is now the end of the import block. The `ReactNativeHost` paths stay for SDK 49 through 55, minus the `getJSMainModuleName` anchor that only ever matched SDK 50's exact string. Claude-Session: https://claude.ai/code/session_01QsVEsfkynXpJWK4t33exG9
Android is covered on SDK 50 and 57. iOS writes Info.plist but leaves the Swift AppDelegate that SDK 52 and up generate untouched, since the mod still looks for the Objective-C `#import "AppDelegate.h"`. Claude-Session: https://claude.ai/code/session_01QsVEsfkynXpJWK4t33exG9
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.
Closes #26.
npx expo prebuildthrows on Expo SDK 57 and SDK 56. Both broken mods anchor on strings the template stopped emitting.app/build.gradle
applyImplementationlooked for one of fourapply from:lines and threw when it found none. RN 0.75 folded autolinking intoautolinkLibrariesWithApp()inside thereact { }block, so on SDK 56+ there's noapply from:in the file at all.codepush.gradlereads thereactextension and iteratesandroid.buildTypeswhile it's being applied, so it has to run after both blocks are configured. The end of the app module's build.gradle is where that holds on every template shape, and it's also where the RN 0.71-0.73 anchor happened to sit, so SDK 49 and 50 land in the same spot they always did. The mod appends there now.It also throws a readable error if
app/build.gradleis Kotlin DSL, whereapply from:wouldn't parse.MainApplication
Flagged in the issue as the next one waiting, and prebuild hits it as soon as the gradle mod stops throwing.
SDK 56 dropped
ReactNativeHostfrom the template, so there's nogetJSBundleFile()to override. The host comes fromExpoReactHostFactory.getDefaultReactHost, which takesjsBundleFilePathas an argument. The mod passesCodePush.getJSBundleFile()there, as the last argument: Kotlin evaluates arguments in source order, and that call throwsCodePushNotInitializedExceptionuntilPackageList(this).packageshas built the CodePush instance. Getting to the closing parenthesis means matching it, because the argument list contains a commented-outadd(MyReactNativePackage())that a plain search walks straight into.import expo.modules.ReactNativeHostWrapperis gone too, so the CodePush import now goes below the last import in the file. TheReactNativeHostpaths stay for SDK 49-55, minus thegetJSMainModuleName(): String = ".expo/.virtual-metro-entry"anchor, which only ever matched SDK 50's exact string.Proof
Blank
create-expo-apponexpo@57.0.8/react-native@0.86.0, plugin wired intoapp.json,npx expo prebuild --platform android --clean.Before, v1.0.11 from npm:
After, this branch packed and installed into the same app:
Same branch against an
expo@50.0.21/react-native@0.73.6app, which is what the README was tested on:Running prebuild twice without
--cleanleaves oneapply from:, onegetJSBundleFile, one import and oneinclude ':react-native-code-push'.Local checks:
Tests run against both templates verbatim, kept in
src/android/__tests__/templates.ts, plus the parenthesis matcher on comments, escaped strings, Kotlin raw strings and nesting. 31 tests, up from 5.Out of scope
I stopped at prebuild. No Gradle build ran, so
codepush.gradleapplying cleanly under AGP on RN 0.86 is unverified, andreact-native-code-push@9.0.1was published against RN 0.72 and hasn't moved since the repo was archived. If the runtime turns out to be broken under bridgeless, that belongs in the SDK's tracker and needs its own issue here.iOS is still broken on SDK 52+ for the same class of reason:
withIosAppDelegateDependencylooks for#import "AppDelegate.h"and the template is Swift now. Nothing throws, soInfo.plistgets written and the bundle URL never gets redirected. Separate fix, filing it.https://claude.ai/code/session_01QsVEsfkynXpJWK4t33exG9