microsoft / react-native-code-push

React Native module for CodePush
http://appcenter.ms
Other
8.99k stars 1.47k forks source link

Sync with successful update but auto restarts then back to "production" version (Android) #2610

Closed jlong4223 closed 1 year ago

jlong4223 commented 1 year ago

I currently have a react native app setup with codepush for Android & iOS. iOS is working as expected and android works as expected with react native debug builds. On Android release builds or builds from Google Play, I allow a user to sync to staging for "beta testing". Based on native android studio logs, the sync & update install is successful. After restarting the app, I see the version change correctly to our apps staging version but moments later, there's a quick flash/restart, and then the app reverts back to the production version. There are no rollbacks in appcenter.

I have attempted to disallow restarts.

Here are the logs I see in android studio logcat:

(ReactNativeJS) [CodePush] Disallowing restarts

.... # file is downloaded & the process is visible in logs:
'πŸš€ ~ file: ~ codePush.sync ~ ', { receivedBytes: 2178636, totalBytes: 2402756 }
'πŸš€ ~ file: ~ codePush.sync ~ ', { receivedBytes: 2326092, totalBytes: 2402756 }
'πŸš€ ~ file: ~ codePush.sync ~ , { receivedBytes: 2402756, totalBytes: 2402756 }
(ReactNative)     [CodePush] Applying full update.
(ReactNativeJS) [CodePush] Installing update.
(ReactNativeJS) [CodePush] Update installed.

# I close and open the app here 

(ReactNativeJS)  [CodePush] Checking for update.
(ReactNativeJS)  [CodePush] Reporting CodePush update success (v33)

# above is correct after choosing Staging
# moments later i see these logs 

(ReactNativeJS)  [CodePush] Downloading package.
(ReactNative)      [CodePush] Applying full update.
(ReactNativeJS)  [CodePush] Installing update.
(ReactNative)      [CodePush] Loading JS bundle from "/file-location"
(ReactNative)      [CodePush] Restarting app

# automatically restarts 
(ReactNativeJS) [CodePush] Checking for update.
(ReactNativeJS) [CodePush] Reporting CodePush update success (v223)

So it seems to be downloading & installing the correct version for Staging but then it will automatically load from the bundle and/or install the update for the production build with a auto restart instead of remain on the environment that I attempted to sync to.

React Native JSX Setup:

const codePushOptions = {
    checkFrequency: CodePush.CheckFrequency.MANUAL, 
};

export default CodePush(codePushOptions)(App);
    useEffect(() => {
        codePush.disallowRestart();

        // codePush.clearUpdates(); // auto restarts either way 
        codePush.sync(
            {
                deploymentKey: codePushKeys[cpEnvName],
                // installMode: codePush.InstallMode.IMMEDIATE, // auto restarts with this 
                installMode: codePush.InstallMode.ON_NEXT_RESTART, // auto restarts with this too 
            },
            statuses => {
                switch (statuses) {
                    case codePush.SyncStatus.CHECKING_FOR_UPDATE:
                        console.log('[CodePush] Checking for updates.');
                        break;

                    case codePush.SyncStatus.UP_TO_DATE:
                        console.log('[CodePush] Up-to-date.');
                        break;

                    case codePush.SyncStatus.UPDATE_INSTALLED:
                        console.log('[CodePush] Update installed.');
                        break;

                    case codePush.SyncStatus.INSTALLING_UPDATE:
                        console.log('[CodePush] Installing update.');
                        break;

                    case codePush.SyncStatus.DOWNLOADING_PACKAGE:
                        console.log('[CodePush] Downloading package.');
                        break;

                    default:
                        break;
                },
            anything => {
                            // logs the download process 
                console.log(
                    'πŸš€ ~  ~ codePush.sync ~ anything', 
                    anything,
                );
            },

Expected Behavior

What you expected to happen? I expect it to remain on the environment that I manually synced to.

Actual Behavior

What actually happens? It syncs to the environment that I select and then reverts back to production/release.

STACK TRACE AND/OR SCREENSHOTS

No rollbacks

Screen Shot 2023-10-30 at 5 44 17 PM

Heres the flash in action. It changes and then goes back: https://github.com/microsoft/react-native-code-push/assets/71945780/71cb3c27-1daa-4b03-a571-0b455b3bf8f7

Environment

(The more info the faster we will be able to address it!)

jlong4223 commented 1 year ago

Got a workaround figured out thats working for me so ill close this issue. Did some refactoring:

Here's what ive got put together. I set up a "CodePushProvider"

export const codePushKeys: { [key: string]: string | undefined } = {
    staging: Platform.select({
        ios: CodePushKeys.STAGING_IOS,
        android: CodePushKeys.STAGING_ANDROID,
    }),
    prerelease: Platform.select({
        ios: CodePushKeys.PRERELEASE_IOS,
        android: CodePushKeys.PRERELEASE_ANDROID,
    }),
    production: Platform.select({
        ios: CodePushKeys.PROD_IOS,
        android: CodePushKeys.PROD_ANDROID,
    }),
};

const checkIfLowerCPEnvSelected = async () => {
    const res = await AsyncStorage.getItem('CP_LOWER_ENV');
    return res;
};

function CodePushProvider() {
    log('[SYNC] CodePush: Provider Setting up');
    useEffect(() => {
        codePush
            .notifyAppReady()
            .then(() => {
                return checkIfLowerCPEnvSelected();
            })
            .then(lowerCPEnvSelection => {
                if (lowerCPEnvSelection) {
                    log('[SYNC] CodePush: Beta Tester');
                    codePush.sync({
                        deploymentKey: codePushKeys[lowerCPEnvSelection],
                        installMode: codePush.InstallMode.IMMEDIATE,
                    });
                } else {
                    log('[SYNC] CodePush: Production');

                    codePush.sync({
                        deploymentKey: codePushKeys.production,
                        installMode: codePush.InstallMode.ON_NEXT_RESTART, // default
                    });
                }
            })
            .catch(() => {
                logError('πŸš€ ~ file: CodePushProvider.tsx:28 ~ codePush.notifyAppReady ~ error');
            });
    }, []);

    return null;
}

export default codePush({
    checkFrequency: codePush.CheckFrequency.MANUAL,
})(CodePushProvider);

Then im using this CodePushProvider in App.tsx like so:

export function App() {

    return (
        <>
            <Provider store={appStore}>
                    ....<SomeCodeHere/>
            </Provider>
            <CodePushProvider />
        </>
    );
}

export default App;