From a81a7be25e8f651d24221f18962fd39058a1b562 Mon Sep 17 00:00:00 2001 From: David Buzinski <103441853+davidbuzinski@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:06:51 -0400 Subject: [PATCH 1/5] Cache fix (#106) --- src/cache-save.ts | 8 ++++++-- src/install.ts | 2 +- src/install.unit.test.ts | 2 +- src/matlab.ts | 34 +++++++++++++++++++++------------- src/matlab.unit.test.ts | 16 ++++++++-------- 5 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/cache-save.ts b/src/cache-save.ts index 548cdac..3525034 100644 --- a/src/cache-save.ts +++ b/src/cache-save.ts @@ -16,6 +16,10 @@ export async function cacheMATLAB() { return; } - await cache.saveCache([matlabPath, supportPackagesPath], primaryKey); - core.info(`Cache saved with the key: ${primaryKey}`); + try { + await cache.saveCache([matlabPath, supportPackagesPath], primaryKey); + core.info(`Cache saved with the key: ${primaryKey}`); + } catch (e) { + core.warning(`Failed to save MATLAB to cache: ${e}`); + } } diff --git a/src/install.ts b/src/install.ts index 384abe5..6d4b0df 100644 --- a/src/install.ts +++ b/src/install.ts @@ -29,7 +29,7 @@ export async function install(platform: string, architecture: string, release: s ); await core.group("Setting up MATLAB", async () => { - let [destination, alreadyExists]: [string, boolean] = await matlab.makeToolcacheDir(releaseInfo, platform); + let [destination, alreadyExists]: [string, boolean] = await matlab.getToolcacheDir(platform, releaseInfo); let cacheHit = false; if (useCache) { diff --git a/src/install.unit.test.ts b/src/install.unit.test.ts index cd01fdf..bd9c566 100644 --- a/src/install.unit.test.ts +++ b/src/install.unit.test.ts @@ -42,7 +42,7 @@ describe("install procedure", () => { beforeEach(() => { matlabInstallSystemDependenciesMock = matlab.installSystemDependencies as jest.Mock; matlabGetReleaseInfoMock = matlab.getReleaseInfo as jest.Mock; - matlabMakeToolcacheDirMock = matlab.makeToolcacheDir as jest.Mock; + matlabMakeToolcacheDirMock = matlab.getToolcacheDir as jest.Mock; matlabSetupBatchMock = matlab.setupBatch as jest.Mock; mpmSetupMock = mpm.setup as jest.Mock; mpmInstallMock = mpm.install as jest.Mock; diff --git a/src/matlab.ts b/src/matlab.ts index 6413f63..ca0e517 100644 --- a/src/matlab.ts +++ b/src/matlab.ts @@ -18,25 +18,36 @@ export interface Release { isPrerelease: boolean; } -export async function makeToolcacheDir(release: Release, platform: string): Promise<[string, boolean]> { +export async function getToolcacheDir(platform: string, release: Release): Promise<[string, boolean]> { let toolpath: string = tc.find("MATLAB", release.version); let alreadyExists = false; if (toolpath) { core.info(`Found MATLAB ${release.name} in cache at ${toolpath}.`); alreadyExists = true; } else { - if (platform === "win32") { - toolpath = await windowsHostedToolpath(release).catch(async () => { - return await defaultToolpath(release, platform); - }); - } else { - toolpath = await defaultToolpath(release, platform); - } + toolpath = await makeToolcacheDir(platform, release); + } + if (platform == "darwin") { + toolpath = toolpath + "/MATLAB.app"; } return [toolpath, alreadyExists] } -async function windowsHostedToolpath(release: Release): Promise { +async function makeToolcacheDir(platform: string, release: Release): Promise { + let toolcacheDir: string; + if (platform === "win32") { + toolcacheDir = await makeWindowsHostedToolpath(release) + .catch(async (e) => { + console.log(e) + return await makeDefaultToolpath(release) + }); + } else { + toolcacheDir = await makeDefaultToolpath(release); + } + return toolcacheDir; +} + +async function makeWindowsHostedToolpath(release: Release): Promise { // bail early if not on a github hosted runner if (process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' && process.env['AGENT_ISSELFHOSTED'] === '1') { return Promise.reject(); @@ -72,13 +83,10 @@ async function windowsHostedToolpath(release: Release): Promise { return actualToolCacheDir; } -async function defaultToolpath(release: Release, platform: string): Promise { +async function makeDefaultToolpath(release: Release): Promise { fs.writeFileSync(".keep", ""); let toolpath = await tc.cacheFile(".keep", ".keep", "MATLAB", release.version); io.rmRF(".keep"); - if (platform == "darwin") { - toolpath = toolpath + "/MATLAB.app"; - } return toolpath } diff --git a/src/matlab.unit.test.ts b/src/matlab.unit.test.ts index b51df75..3b262b4 100644 --- a/src/matlab.unit.test.ts +++ b/src/matlab.unit.test.ts @@ -46,20 +46,20 @@ describe("matlab tests", () => { it("returns toolpath if in toolcache", async () => { findMock.mockReturnValue("/opt/hostedtoolcache/matlab/r2022b"); - await expect(matlab.makeToolcacheDir(release, platform)).resolves.toMatchObject(["/opt/hostedtoolcache/matlab/r2022b", true]); + await expect(matlab.getToolcacheDir(platform, release)).resolves.toMatchObject(["/opt/hostedtoolcache/matlab/r2022b", true]); expect(infoMock).toHaveBeenCalledTimes(1); }); it("creates cache and returns default path for linux", async () => { findMock.mockReturnValue(""); cacheFileMock.mockReturnValue("/opt/hostedtoolcache/matlab/r2022b"); - await expect(matlab.makeToolcacheDir(release, platform)).resolves.toMatchObject(["/opt/hostedtoolcache/matlab/r2022b", false]); + await expect(matlab.getToolcacheDir(platform, release)).resolves.toMatchObject(["/opt/hostedtoolcache/matlab/r2022b", false]); }); it("creates cache and returns default path for mac", async () => { findMock.mockReturnValue(""); cacheFileMock.mockReturnValue("/opt/hostedtoolcache/matlab/r2022b"); - await expect(matlab.makeToolcacheDir(release, "darwin")).resolves.toMatchObject(["/opt/hostedtoolcache/matlab/r2022b/MATLAB.app", false]); + await expect(matlab.getToolcacheDir("darwin", release)).resolves.toMatchObject(["/opt/hostedtoolcache/matlab/r2022b/MATLAB.app", false]); }); describe("windows performance workaround", () => { @@ -94,7 +94,7 @@ describe("matlab tests", () => { let mkdirSyncSpy = jest.spyOn(fs, "mkdirSync").mockImplementation(() => ""); let symlinkSyncSpy = jest.spyOn(fs, "symlinkSync").mockImplementation(() => {}); - await expect(matlab.makeToolcacheDir(release, "win32")).resolves.toMatchObject([expectedToolcacheDir, false]); + await expect(matlab.getToolcacheDir("win32", release)).resolves.toMatchObject([expectedToolcacheDir, false]); expect(existsSyncSpy).toHaveBeenCalledTimes(2); expect(mkdirSyncSpy).toHaveBeenCalledTimes(1); expect(symlinkSyncSpy).toHaveBeenCalledTimes(2); @@ -104,26 +104,26 @@ describe("matlab tests", () => { let expectedToolcacheDir = "C:\\hostedtoolcache\\windows\\matlab\\r2022b"; process.env["AGENT_ISSELFHOSTED"] = "1"; process.env["RUNNER_ENVIRONMENT"] = "self-hosted"; - await expect(matlab.makeToolcacheDir(release, "win32")).resolves.toMatchObject([expectedToolcacheDir, false]); + await expect(matlab.getToolcacheDir("win32", release)).resolves.toMatchObject([expectedToolcacheDir, false]); }); it("uses default toolcache directory toolcache directory is not defined", async () => { let expectedToolcacheDir = "C:\\hostedtoolcache\\windows\\matlab\\r2022b"; process.env["RUNNER_TOOL_CACHE"] = ''; cacheFileMock.mockReturnValue(expectedToolcacheDir); - await expect(matlab.makeToolcacheDir(release, "win32")).resolves.toMatchObject([expectedToolcacheDir, false]); + await expect(matlab.getToolcacheDir("win32", release)).resolves.toMatchObject([expectedToolcacheDir, false]); }); it("uses default toolcache directory if d: drive doesn't exist", async () => { jest.spyOn(fs, "existsSync").mockReturnValue(false); let expectedToolcacheDir = "C:\\hostedtoolcache\\windows\\matlab\\r2022b"; - await expect(matlab.makeToolcacheDir(release, "win32")).resolves.toMatchObject([expectedToolcacheDir, false]); + await expect(matlab.getToolcacheDir("win32", release)).resolves.toMatchObject([expectedToolcacheDir, false]); }); it("uses default toolcache directory if c: drive doesn't exist", async () => { jest.spyOn(fs, "existsSync").mockReturnValueOnce(true).mockReturnValue(false); let expectedToolcacheDir = "C:\\hostedtoolcache\\windows\\matlab\\r2022b"; - await expect(matlab.makeToolcacheDir(release, "win32")).resolves.toMatchObject([expectedToolcacheDir, false]); + await expect(matlab.getToolcacheDir("win32", release)).resolves.toMatchObject([expectedToolcacheDir, false]); }); }); From 0f3e3a2c7cd903250836aba3711bac184fdd0e61 Mon Sep 17 00:00:00 2001 From: David Buzinski <103441853+davidbuzinski@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:19:58 -0400 Subject: [PATCH 2/5] Update matlab.ts --- src/matlab.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/matlab.ts b/src/matlab.ts index ca0e517..2deb5c5 100644 --- a/src/matlab.ts +++ b/src/matlab.ts @@ -38,7 +38,6 @@ async function makeToolcacheDir(platform: string, release: Release): Promise { - console.log(e) return await makeDefaultToolpath(release) }); } else { From 9dc6a9f2fc52bc775faa5b9f98952979517d3cd2 Mon Sep 17 00:00:00 2001 From: David Buzinski <103441853+davidbuzinski@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:24:10 -0400 Subject: [PATCH 3/5] Update matlab.ts --- src/matlab.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matlab.ts b/src/matlab.ts index 2deb5c5..25b9d3f 100644 --- a/src/matlab.ts +++ b/src/matlab.ts @@ -37,7 +37,7 @@ async function makeToolcacheDir(platform: string, release: Release): Promise { + .catch(async () => { return await makeDefaultToolpath(release) }); } else { From 6a7b6fca08c1ab53a662d85084db8580bf4d10b0 Mon Sep 17 00:00:00 2001 From: David Buzinski Date: Thu, 11 Apr 2024 09:26:51 -0400 Subject: [PATCH 4/5] fix cruft problems on windows and unchange var names --- src/install.unit.test.ts | 8 ++++---- src/matlab.ts | 43 ++++++++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/install.unit.test.ts b/src/install.unit.test.ts index bd9c566..7527563 100644 --- a/src/install.unit.test.ts +++ b/src/install.unit.test.ts @@ -18,7 +18,7 @@ afterEach(() => { describe("install procedure", () => { let matlabInstallSystemDependenciesMock: jest.Mock; let matlabGetReleaseInfoMock: jest.Mock; - let matlabMakeToolcacheDirMock: jest.Mock; + let matlabGetToolcacheDirMock: jest.Mock; let matlabSetupBatchMock: jest.Mock; let mpmSetupMock: jest.Mock; let mpmInstallMock: jest.Mock; @@ -42,7 +42,7 @@ describe("install procedure", () => { beforeEach(() => { matlabInstallSystemDependenciesMock = matlab.installSystemDependencies as jest.Mock; matlabGetReleaseInfoMock = matlab.getReleaseInfo as jest.Mock; - matlabMakeToolcacheDirMock = matlab.getToolcacheDir as jest.Mock; + matlabGetToolcacheDirMock = matlab.getToolcacheDir as jest.Mock; matlabSetupBatchMock = matlab.setupBatch as jest.Mock; mpmSetupMock = mpm.setup as jest.Mock; mpmInstallMock = mpm.install as jest.Mock; @@ -56,7 +56,7 @@ describe("install procedure", () => { return func(); }); matlabGetReleaseInfoMock.mockResolvedValue(releaseInfo); - matlabMakeToolcacheDirMock.mockResolvedValue(["/opt/hostedtoolcache/MATLAB/9.13.0/x64", false]); + matlabGetToolcacheDirMock.mockResolvedValue(["/opt/hostedtoolcache/MATLAB/9.13.0/x64", false]); }); it("ideally works", async () => { @@ -70,7 +70,7 @@ describe("install procedure", () => { }); it("NoOp on existing install", async () => { - matlabMakeToolcacheDirMock.mockResolvedValue(["/opt/hostedtoolcache/MATLAB/9.13.0/x64", true]); + matlabGetToolcacheDirMock.mockResolvedValue(["/opt/hostedtoolcache/MATLAB/9.13.0/x64", true]); await expect(doInstall()).resolves.toBeUndefined(); expect(mpmInstallMock).toHaveBeenCalledTimes(0); expect(addPathMock).toHaveBeenCalledTimes(1); diff --git a/src/matlab.ts b/src/matlab.ts index 25b9d3f..19c5a6d 100644 --- a/src/matlab.ts +++ b/src/matlab.ts @@ -65,27 +65,36 @@ async function makeWindowsHostedToolpath(release: Release): Promise { const actualToolCacheRoot = defaultToolCacheRoot.replace("C:", "D:").replace("c:", "d:"); process.env['RUNNER_TOOL_CACHE'] = actualToolCacheRoot; - // create install directory and link it to the toolcache directory - fs.writeFileSync(".keep", ""); - let actualToolCacheDir = await tc.cacheFile(".keep", ".keep", "MATLAB", release.version); - io.rmRF(".keep"); - let defaultToolCacheDir = actualToolCacheDir.replace(actualToolCacheRoot, defaultToolCacheRoot); - fs.mkdirSync(path.dirname(defaultToolCacheDir), {recursive: true}); - fs.symlinkSync(actualToolCacheDir, defaultToolCacheDir, 'junction'); - - // required for github actions to make the cacheDir persistent - const actualToolCacheCompleteFile = `${actualToolCacheDir}.complete`; - const defaultToolCacheCompleteFile = `${defaultToolCacheDir}.complete`; - fs.symlinkSync(actualToolCacheCompleteFile, defaultToolCacheCompleteFile, 'file'); - - process.env['RUNNER_TOOL_CACHE'] = defaultToolCacheRoot; - return actualToolCacheDir; + try { + // create install directory and link it to the toolcache directory + fs.writeFileSync(".keep", ""); + let actualToolCacheDir = await tc.cacheFile(".keep", ".keep", "MATLAB", release.version); + await io.rmRF(".keep"); + let defaultToolCacheDir = actualToolCacheDir.replace(actualToolCacheRoot, defaultToolCacheRoot); + + // remove cruft from incomplete installs + await io.rmRF(defaultToolCacheDir); + + // link to actual tool cache directory + fs.mkdirSync(path.dirname(defaultToolCacheDir), {recursive: true}); + fs.symlinkSync(actualToolCacheDir, defaultToolCacheDir, 'junction'); + + // .complete file is required for github actions to make the cacheDir persistent + const actualToolCacheCompleteFile = `${actualToolCacheDir}.complete`; + const defaultToolCacheCompleteFile = `${defaultToolCacheDir}.complete`; + await io.rmRF(defaultToolCacheCompleteFile); + fs.symlinkSync(actualToolCacheCompleteFile, defaultToolCacheCompleteFile, 'file'); + + return actualToolCacheDir; + } finally { + process.env['RUNNER_TOOL_CACHE'] = defaultToolCacheRoot; + } } async function makeDefaultToolpath(release: Release): Promise { fs.writeFileSync(".keep", ""); let toolpath = await tc.cacheFile(".keep", ".keep", "MATLAB", release.version); - io.rmRF(".keep"); + await io.rmRF(".keep"); return toolpath } @@ -206,7 +215,7 @@ export async function installSystemDependencies(platform: string, architecture: async function installAppleSiliconJdk() { const jdkPath = path.join(process.env["RUNNER_TEMP"] ?? "", "jdk.pkg"); - io.rmRF(jdkPath); + await io.rmRF(jdkPath); const jdk = await tc.downloadTool(properties.appleSiliconJdkUrl, jdkPath); const exitCode = await exec.exec(`sudo installer -pkg "${jdk}" -target /`); if (exitCode !== 0) { From 1a1d13b97908b210d71ad3b2dfadb1e0973a9dc0 Mon Sep 17 00:00:00 2001 From: David Buzinski <103441853+davidbuzinski@users.noreply.github.com> Date: Thu, 11 Apr 2024 09:43:33 -0400 Subject: [PATCH 5/5] Update src/matlab.ts Co-authored-by: Mark Cafaro <34887852+mcafaro@users.noreply.github.com> --- src/matlab.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/matlab.ts b/src/matlab.ts index 19c5a6d..ac552c8 100644 --- a/src/matlab.ts +++ b/src/matlab.ts @@ -37,9 +37,7 @@ async function makeToolcacheDir(platform: string, release: Release): Promise { - return await makeDefaultToolpath(release) - }); + .catch(async () => await makeDefaultToolpath(release)); } else { toolcacheDir = await makeDefaultToolpath(release); }