game-ci / unity-builder

Build Unity projects for different platforms
https://github.com/marketplace/actions/unity-builder
MIT License
822 stars 231 forks source link

Missing module when building different target on same Unity version and self-hosted MacOS runner #615

Open Rycieos opened 6 months ago

Rycieos commented 6 months ago

Bug description

If a second build target is run on the same self-hosted MacOS runner (with the same Unity version), the action will detect that the Unity Editor version is already installed, and it will skip the Unity Editor installation. The build will then fail, as the Unity Editor does not have the build target support installed.

This is admittedly a very specific case, so I'm not surprised no one else has hit this yet, or that no one thought of it.

How to reproduce

  1. On a (clean) self-hosted MacOS runner, build some target, like iOS on some Unity version, like 2020.3.44f1.
  2. On the same self-hosted runner, build a different target, like Android on the same Unity version.
  3. Build will skip installing Unity Editor or modules, as the Unity Editor is already installed.
  4. Build will fail with import errors.

Expected behavior

The action detects that the installed Unity Editor does not have the right build target module installed, and installs it before starting the build.

Additional details

Unfortunately, the Unity Hub CLI does not have a way to test what modules are currently installed. However, the install-modules command is idempotent, so it could be called every run without any downsides other than a bit of extra runtime.

Suggested fix

It should be possible to simply ask Unity Hub to install the required module every build. That might look something like this in this block: https://github.com/game-ci/unity-builder/blob/ff23166e3002a9f3f869621650dc992e657e17ce/src/model/platform-setup/setup-mac.ts#L19-L21

     if (!fs.existsSync(unityEditorPath.replace(/"/g, ''))) {
       await SetupMac.installUnity(buildParameters);
+    } else {
+      await SetupMac.installUnityModules(buildParameters);
     }

and the new function:

  private static async installUnityModules(buildParameters: BuildParameters, silent = false) {
    const moduleArguments = SetupMac.getModuleParametersForTargetPlatform(buildParameters.targetPlatform);

    const execArguments: string[] = [
      '--',
      '--headless',
      'install-modules',
      ...['--version', buildParameters.editorVersion],
      ...moduleArguments,
      '--childModules',
    ];

    // Ignoring return code because the install-modules command will fail if the modules already are installed.
    const errorCode = await exec(this.unityHubExecPath, execArguments, {
      silent,
      ignoreReturnCode: true,
    });
    if (errorCode) {
      throw new Error(`There was an error installing the Unity Editor modules. See logs above for details.`);
    }
  }

This suggested code does not handle the MacOS Editor caching: the cache would likely need to be updated after.

This suggested Unity Hub CLI command is the exact command I used to solve my issue.