diff --git a/.github/workflows/bat.yml b/.github/workflows/bat.yml index 103fb59..e9796a5 100644 --- a/.github/workflows/bat.yml +++ b/.github/workflows/bat.yml @@ -92,6 +92,17 @@ jobs: with: release: ${{ matrix.release }} products: ${{ matrix.products }} + - name: Install additional products + if: matrix.os != 'windows-latest' + uses: ./ + with: + release: ${{ matrix.release }} + products: Image_Processing_Toolbox + - name: Check additional product was installed + if: matrix.os != 'windows-latest' + uses: matlab-actions/run-command@v2 + with: + command: assert(any(strcmp({ver().Name},'Image Processing Toolbox'))) - name: Call setup MATLAB again with different release # should not error as in issue 130 uses: ./ with: diff --git a/src/install.ts b/src/install.ts index 9830284..3e9eac5 100644 --- a/src/install.ts +++ b/src/install.ts @@ -38,7 +38,7 @@ export async function install(platform: string, architecture: string, release: s matlabArch = "x64"; } - let [destination, alreadyExists]: [string, boolean] = await matlab.getToolcacheDir(platform, releaseInfo); + let [destination]: [string, boolean] = await matlab.getToolcacheDir(platform, releaseInfo); let cacheHit = false; if (useCache) { @@ -46,7 +46,7 @@ export async function install(platform: string, architecture: string, release: s cacheHit = await cache.restoreMATLAB(releaseInfo, platform, matlabArch, products, destination, supportFilesDir); } - if (!alreadyExists && !cacheHit) { + if (!cacheHit) { const mpmPath: string = await mpm.setup(platform, matlabArch); await mpm.install(mpmPath, releaseInfo, products, destination); core.saveState(State.InstallSuccessful, 'true'); diff --git a/src/install.unit.test.ts b/src/install.unit.test.ts index 4e12666..1e44088 100644 --- a/src/install.unit.test.ts +++ b/src/install.unit.test.ts @@ -79,11 +79,11 @@ describe("install procedure", () => { expect(setOutputMock).toHaveBeenCalledTimes(1); }); - it("NoOp on existing install", async () => { + it("re-calls MPM install even if MATLAB already exists in toolcache", async () => { matlabGetToolcacheDirMock.mockResolvedValue(["/opt/hostedtoolcache/MATLAB/9.13.0/x64", true]); await expect(doInstall()).resolves.toBeUndefined(); - expect(mpmInstallMock).toHaveBeenCalledTimes(0); - expect(saveStateMock).toHaveBeenCalledTimes(0); + expect(mpmInstallMock).toHaveBeenCalledTimes(1); + expect(saveStateMock).toHaveBeenCalledTimes(1); expect(addPathMock).toHaveBeenCalledTimes(1); expect(setOutputMock).toHaveBeenCalledTimes(1); }); diff --git a/src/mpm.ts b/src/mpm.ts index ccd502e..910381f 100644 --- a/src/mpm.ts +++ b/src/mpm.ts @@ -78,14 +78,33 @@ export async function install(mpmPath: string, release: matlab.Release, products } mpmArguments = mpmArguments.concat("--products", ...parsedProducts); - const exitCode = await exec.exec(mpmPath, mpmArguments).catch(async e => { - // Fully remove failed MATLAB installation for self-hosted runners + let output = ""; + const options = { + listeners: { + stdout: (data: Buffer) => { + const text = data.toString(); + output += text; + process.stdout.write(text); + }, + stderr: (data: Buffer) => { + const text = data.toString(); + output += text; + process.stderr.write(text); + }, + }, + ignoreReturnCode: true, + silent: true, + }; + + const exitCode = await exec.exec(mpmPath, mpmArguments, options).catch(async e => { await rmRF(destination); throw e; }); - if (exitCode !== 0) { + + if (exitCode !== 0 && !output.toLowerCase().includes("already installed")) { await rmRF(destination); return Promise.reject(Error(`Script exited with non-zero code ${exitCode}`)); } - return + + return; } diff --git a/src/mpm.unit.test.ts b/src/mpm.unit.test.ts index 37d2cf5..b72da87 100644 --- a/src/mpm.unit.test.ts +++ b/src/mpm.unit.test.ts @@ -180,4 +180,20 @@ describe("mpm install", () => { await expect(mpm.install(mpmPath, releaseInfo, products, destination)).rejects.toBeDefined(); expect(rmRFMock).toHaveBeenCalledWith(destination); }); + + it("does not reject when mpm exits non-zero but reports already installed", async () => { + const destination = "/opt/matlab"; + const products = ["MATLAB", "Compiler"]; + + // Simulate mpm writing the "already installed" message to stdout and returning non-zero + execMock.mockImplementation((cmd: string, args: string[], options?: exec.ExecOptions) => { + if (options && options.listeners && typeof options.listeners.stdout === 'function') { + options.listeners.stdout(Buffer.from("All specified products are already installed.")); + } + return Promise.resolve(1); + }); + + await expect(mpm.install(mpmPath, releaseInfo, products, destination)).resolves.toBeUndefined(); + expect(rmRFMock).not.toHaveBeenCalled(); + }); });