microsoft / appcenter-cli

Command-line Interface (CLI) for Visual Studio App Center
https://appcenter.ms/
MIT License
582 stars 235 forks source link

Hermes output different every build #2158

Closed nedjs closed 5 months ago

nedjs commented 1 year ago

Description

When running the command multiple times I never get a collision of code when using Hermes:

appcenter codepush release-react \                                                                                                      
  --app "ned.stuart/test" \
  --deployment-name "Staging" \
  --description "testing" \ 
  --target-binary-version "1.5.x"

The Hermes engine output is different every release-react despite no code or resource changes. This difference seems to stem from the JS path being baked into the binary output.

Repro Steps

Run the provided command (with your own variables) on a Hermes enabled project 2 times back to back.

Expected behavior

Releasing code which contains duplicate code results in

Error: The uploaded package was not released because it is identical to the contents of the specified deployment's current release.

Details

  1. Is there a particular beacon/command that you are having trouble with?
    • appcenter codepush release-react
  2. Which version of the App Center CLI are you using?
    • 2.11.0
  3. Which OS version did you experience the issue on?
    • MacOS M1 13.0.1
  4. What command line/shell are you using?
    • N/A
  5. What version of Node.js and NPM/Yarn are you using?
    • Node v16.13.2 (but shouldnt be applicable I dont think)

Relavant information

This is not unique to any specific library and can be observed on a simple 1 liner JS file. As mentioned above the issue seems to be that Hermes bakes in the JS file path into the output, since CodePush builds to a temp folder which is auto generated by the system its different every time.

Recreating diff Hermes output
  1. Create a javascript file (or any project will do)

    // index.js
    console.log('hello');
  2. Compile JS to Hermes using a relative path

    
    hermesc -emit-binary -out index_a.hbc index.js -w
    xxd index_a.hbc > index_a.hex
3. Compile using an different path (literally any other path to the file)
```shell
hermesc -emit-binary -out index_b.hbc ~/test_hermes/index.js -w
xxd index_b.hbc > index_b.hex
  1. Diff the 2 hex files
    > diff index_a.hex index_b.hex                                                                                       
    3c3
    < 00000020: 3701 0000 0000 0000 0100 0000 0200 0000  7...............
    ---
    > 00000020: 5201 0000 0000 0000 0100 0000 0200 0000  R...............
    15,20c15,22
    < 000000e0: 0000 0000 0100 0000 0800 0000 0100 0000  ................
    < 000000f0: 0d00 0000 0f00 0000 0000 0000 0800 0000  ................
    < 00000100: 696e 6465 782e 6a73 0000 0000 0000 0000  index.js........
    < 00000110: 0000 0000 0001 0102 0000 0600 0b09 0000  ................
    < 00000120: 7f7f 004b 1a3e f8c5 5e2b 87b4 6890 a25e  ...K.>..^+..h..^
    < 00000130: e393 1487 f006 52                        ......R
    ---
    > 000000e0: 0000 0000 0100 0000 2300 0000 0100 0000  ........#.......
    > 000000f0: 0d00 0000 0f00 0000 0000 0000 2300 0000  ............#...
    > 00000100: 2f55 7365 7273 2f6e 7374 7561 7274 2f74  /Users/nstuart/t
    > 00000110: 6573 745f 6865 726d 6573 2f69 6e64 6578  est_hermes/index
    > 00000120: 2e6a 7300 0000 0000 0000 0000 0000 0000  .js.............
    > 00000130: 0101 0200 0006 000b 0900 007f 7f00 4b1b  ..............K.
    > 00000140: e318 a347 0a8c a247 c874 0560 75d5 ef80  ...G...G.t.`u...
    > 00000150: 278e 

A possible fix

When generating the Hermes hbc file do it relative to the temp folder so the path is always the same:

diff --git a/./react-native-utils.ts b/./react-native-utils_patched.ts
index 1d5ef8c..ec4839b 100644
--- a/./react-native-utils.ts
+++ b/./react-native-utils_patched.ts
@@ -354,8 +354,8 @@ export async function runHermesEmitBinaryCommand(
    Array.prototype.push.apply(hermesArgs, [
        "-emit-binary",
        "-out",
-       path.join(outputFolder, bundleName + ".hbc"),
-       path.join(outputFolder, bundleName),
+       path.join(bundleName + ".hbc"),
+       path.join(bundleName),
        ...extraHermesFlags,
    ]);

@@ -369,7 +369,9 @@ export async function runHermesEmitBinaryCommand(

    out.text(chalk.cyan("Converting JS bundle to byte code via Hermes, running command:\n"));
    const hermesCommand = await getHermesCommand(gradleFile);
-   const hermesProcess = childProcess.spawn(hermesCommand, hermesArgs);
+   const hermesProcess = childProcess.spawn(path.join(process.cwd(), hermesCommand), hermesArgs, {
+       cwd: outputFolder
+   });
    out.text(`${hermesCommand} ${hermesArgs.join(" ")}`);

    return new Promise<void>((resolve, reject) => {
IlyaBausovAkvelon commented 1 year ago

@nedjs Thank you for the report! Let take a look how many users are experiencing this issue.

DmitriyKirakosyan commented 5 months ago

As we do not have plans to fix this bug in the next year, I'm closing the issue.