Skip to content

Commit 10404e3

Browse files
Fix MATLAB caching problems (#107)
1 parent ff32d3e commit 10404e3

File tree

5 files changed

+63
-45
lines changed

5 files changed

+63
-45
lines changed

src/cache-save.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ export async function cacheMATLAB() {
1616
return;
1717
}
1818

19-
await cache.saveCache([matlabPath, supportPackagesPath], primaryKey);
20-
core.info(`Cache saved with the key: ${primaryKey}`);
19+
try {
20+
await cache.saveCache([matlabPath, supportPackagesPath], primaryKey);
21+
core.info(`Cache saved with the key: ${primaryKey}`);
22+
} catch (e) {
23+
core.warning(`Failed to save MATLAB to cache: ${e}`);
24+
}
2125
}

src/install.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export async function install(platform: string, architecture: string, release: s
2929
);
3030

3131
await core.group("Setting up MATLAB", async () => {
32-
let [destination, alreadyExists]: [string, boolean] = await matlab.makeToolcacheDir(releaseInfo, platform);
32+
let [destination, alreadyExists]: [string, boolean] = await matlab.getToolcacheDir(platform, releaseInfo);
3333
let cacheHit = false;
3434

3535
if (useCache) {

src/install.unit.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ afterEach(() => {
1818
describe("install procedure", () => {
1919
let matlabInstallSystemDependenciesMock: jest.Mock;
2020
let matlabGetReleaseInfoMock: jest.Mock;
21-
let matlabMakeToolcacheDirMock: jest.Mock;
21+
let matlabGetToolcacheDirMock: jest.Mock;
2222
let matlabSetupBatchMock: jest.Mock;
2323
let mpmSetupMock: jest.Mock;
2424
let mpmInstallMock: jest.Mock;
@@ -42,7 +42,7 @@ describe("install procedure", () => {
4242
beforeEach(() => {
4343
matlabInstallSystemDependenciesMock = matlab.installSystemDependencies as jest.Mock;
4444
matlabGetReleaseInfoMock = matlab.getReleaseInfo as jest.Mock;
45-
matlabMakeToolcacheDirMock = matlab.makeToolcacheDir as jest.Mock;
45+
matlabGetToolcacheDirMock = matlab.getToolcacheDir as jest.Mock;
4646
matlabSetupBatchMock = matlab.setupBatch as jest.Mock;
4747
mpmSetupMock = mpm.setup as jest.Mock;
4848
mpmInstallMock = mpm.install as jest.Mock;
@@ -56,7 +56,7 @@ describe("install procedure", () => {
5656
return func();
5757
});
5858
matlabGetReleaseInfoMock.mockResolvedValue(releaseInfo);
59-
matlabMakeToolcacheDirMock.mockResolvedValue(["/opt/hostedtoolcache/MATLAB/9.13.0/x64", false]);
59+
matlabGetToolcacheDirMock.mockResolvedValue(["/opt/hostedtoolcache/MATLAB/9.13.0/x64", false]);
6060
});
6161

6262
it("ideally works", async () => {
@@ -70,7 +70,7 @@ describe("install procedure", () => {
7070
});
7171

7272
it("NoOp on existing install", async () => {
73-
matlabMakeToolcacheDirMock.mockResolvedValue(["/opt/hostedtoolcache/MATLAB/9.13.0/x64", true]);
73+
matlabGetToolcacheDirMock.mockResolvedValue(["/opt/hostedtoolcache/MATLAB/9.13.0/x64", true]);
7474
await expect(doInstall()).resolves.toBeUndefined();
7575
expect(mpmInstallMock).toHaveBeenCalledTimes(0);
7676
expect(addPathMock).toHaveBeenCalledTimes(1);

src/matlab.ts

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,33 @@ export interface Release {
1818
isPrerelease: boolean;
1919
}
2020

21-
export async function makeToolcacheDir(release: Release, platform: string): Promise<[string, boolean]> {
21+
export async function getToolcacheDir(platform: string, release: Release): Promise<[string, boolean]> {
2222
let toolpath: string = tc.find("MATLAB", release.version);
2323
let alreadyExists = false;
2424
if (toolpath) {
2525
core.info(`Found MATLAB ${release.name} in cache at ${toolpath}.`);
2626
alreadyExists = true;
2727
} else {
28-
if (platform === "win32") {
29-
toolpath = await windowsHostedToolpath(release).catch(async () => {
30-
return await defaultToolpath(release, platform);
31-
});
32-
} else {
33-
toolpath = await defaultToolpath(release, platform);
34-
}
28+
toolpath = await makeToolcacheDir(platform, release);
29+
}
30+
if (platform == "darwin") {
31+
toolpath = toolpath + "/MATLAB.app";
3532
}
3633
return [toolpath, alreadyExists]
3734
}
3835

39-
async function windowsHostedToolpath(release: Release): Promise<string> {
36+
async function makeToolcacheDir(platform: string, release: Release): Promise<string> {
37+
let toolcacheDir: string;
38+
if (platform === "win32") {
39+
toolcacheDir = await makeWindowsHostedToolpath(release)
40+
.catch(async () => await makeDefaultToolpath(release));
41+
} else {
42+
toolcacheDir = await makeDefaultToolpath(release);
43+
}
44+
return toolcacheDir;
45+
}
46+
47+
async function makeWindowsHostedToolpath(release: Release): Promise<string> {
4048
// bail early if not on a github hosted runner
4149
if (process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' && process.env['AGENT_ISSELFHOSTED'] === '1') {
4250
return Promise.reject();
@@ -55,30 +63,36 @@ async function windowsHostedToolpath(release: Release): Promise<string> {
5563
const actualToolCacheRoot = defaultToolCacheRoot.replace("C:", "D:").replace("c:", "d:");
5664
process.env['RUNNER_TOOL_CACHE'] = actualToolCacheRoot;
5765

58-
// create install directory and link it to the toolcache directory
59-
fs.writeFileSync(".keep", "");
60-
let actualToolCacheDir = await tc.cacheFile(".keep", ".keep", "MATLAB", release.version);
61-
io.rmRF(".keep");
62-
let defaultToolCacheDir = actualToolCacheDir.replace(actualToolCacheRoot, defaultToolCacheRoot);
63-
fs.mkdirSync(path.dirname(defaultToolCacheDir), {recursive: true});
64-
fs.symlinkSync(actualToolCacheDir, defaultToolCacheDir, 'junction');
65-
66-
// required for github actions to make the cacheDir persistent
67-
const actualToolCacheCompleteFile = `${actualToolCacheDir}.complete`;
68-
const defaultToolCacheCompleteFile = `${defaultToolCacheDir}.complete`;
69-
fs.symlinkSync(actualToolCacheCompleteFile, defaultToolCacheCompleteFile, 'file');
70-
71-
process.env['RUNNER_TOOL_CACHE'] = defaultToolCacheRoot;
72-
return actualToolCacheDir;
66+
try {
67+
// create install directory and link it to the toolcache directory
68+
fs.writeFileSync(".keep", "");
69+
let actualToolCacheDir = await tc.cacheFile(".keep", ".keep", "MATLAB", release.version);
70+
await io.rmRF(".keep");
71+
let defaultToolCacheDir = actualToolCacheDir.replace(actualToolCacheRoot, defaultToolCacheRoot);
72+
73+
// remove cruft from incomplete installs
74+
await io.rmRF(defaultToolCacheDir);
75+
76+
// link to actual tool cache directory
77+
fs.mkdirSync(path.dirname(defaultToolCacheDir), {recursive: true});
78+
fs.symlinkSync(actualToolCacheDir, defaultToolCacheDir, 'junction');
79+
80+
// .complete file is required for github actions to make the cacheDir persistent
81+
const actualToolCacheCompleteFile = `${actualToolCacheDir}.complete`;
82+
const defaultToolCacheCompleteFile = `${defaultToolCacheDir}.complete`;
83+
await io.rmRF(defaultToolCacheCompleteFile);
84+
fs.symlinkSync(actualToolCacheCompleteFile, defaultToolCacheCompleteFile, 'file');
85+
86+
return actualToolCacheDir;
87+
} finally {
88+
process.env['RUNNER_TOOL_CACHE'] = defaultToolCacheRoot;
89+
}
7390
}
7491

75-
async function defaultToolpath(release: Release, platform: string): Promise<string> {
92+
async function makeDefaultToolpath(release: Release): Promise<string> {
7693
fs.writeFileSync(".keep", "");
7794
let toolpath = await tc.cacheFile(".keep", ".keep", "MATLAB", release.version);
78-
io.rmRF(".keep");
79-
if (platform == "darwin") {
80-
toolpath = toolpath + "/MATLAB.app";
81-
}
95+
await io.rmRF(".keep");
8296
return toolpath
8397
}
8498

@@ -199,7 +213,7 @@ export async function installSystemDependencies(platform: string, architecture:
199213

200214
async function installAppleSiliconJdk() {
201215
const jdkPath = path.join(process.env["RUNNER_TEMP"] ?? "", "jdk.pkg");
202-
io.rmRF(jdkPath);
216+
await io.rmRF(jdkPath);
203217
const jdk = await tc.downloadTool(properties.appleSiliconJdkUrl, jdkPath);
204218
const exitCode = await exec.exec(`sudo installer -pkg "${jdk}" -target /`);
205219
if (exitCode !== 0) {

src/matlab.unit.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,20 @@ describe("matlab tests", () => {
4646

4747
it("returns toolpath if in toolcache", async () => {
4848
findMock.mockReturnValue("/opt/hostedtoolcache/matlab/r2022b");
49-
await expect(matlab.makeToolcacheDir(release, platform)).resolves.toMatchObject(["/opt/hostedtoolcache/matlab/r2022b", true]);
49+
await expect(matlab.getToolcacheDir(platform, release)).resolves.toMatchObject(["/opt/hostedtoolcache/matlab/r2022b", true]);
5050
expect(infoMock).toHaveBeenCalledTimes(1);
5151
});
5252

5353
it("creates cache and returns default path for linux", async () => {
5454
findMock.mockReturnValue("");
5555
cacheFileMock.mockReturnValue("/opt/hostedtoolcache/matlab/r2022b");
56-
await expect(matlab.makeToolcacheDir(release, platform)).resolves.toMatchObject(["/opt/hostedtoolcache/matlab/r2022b", false]);
56+
await expect(matlab.getToolcacheDir(platform, release)).resolves.toMatchObject(["/opt/hostedtoolcache/matlab/r2022b", false]);
5757
});
5858

5959
it("creates cache and returns default path for mac", async () => {
6060
findMock.mockReturnValue("");
6161
cacheFileMock.mockReturnValue("/opt/hostedtoolcache/matlab/r2022b");
62-
await expect(matlab.makeToolcacheDir(release, "darwin")).resolves.toMatchObject(["/opt/hostedtoolcache/matlab/r2022b/MATLAB.app", false]);
62+
await expect(matlab.getToolcacheDir("darwin", release)).resolves.toMatchObject(["/opt/hostedtoolcache/matlab/r2022b/MATLAB.app", false]);
6363
});
6464

6565
describe("windows performance workaround", () => {
@@ -94,7 +94,7 @@ describe("matlab tests", () => {
9494
let mkdirSyncSpy = jest.spyOn(fs, "mkdirSync").mockImplementation(() => "");
9595
let symlinkSyncSpy = jest.spyOn(fs, "symlinkSync").mockImplementation(() => {});
9696

97-
await expect(matlab.makeToolcacheDir(release, "win32")).resolves.toMatchObject([expectedToolcacheDir, false]);
97+
await expect(matlab.getToolcacheDir("win32", release)).resolves.toMatchObject([expectedToolcacheDir, false]);
9898
expect(existsSyncSpy).toHaveBeenCalledTimes(2);
9999
expect(mkdirSyncSpy).toHaveBeenCalledTimes(1);
100100
expect(symlinkSyncSpy).toHaveBeenCalledTimes(2);
@@ -104,26 +104,26 @@ describe("matlab tests", () => {
104104
let expectedToolcacheDir = "C:\\hostedtoolcache\\windows\\matlab\\r2022b";
105105
process.env["AGENT_ISSELFHOSTED"] = "1";
106106
process.env["RUNNER_ENVIRONMENT"] = "self-hosted";
107-
await expect(matlab.makeToolcacheDir(release, "win32")).resolves.toMatchObject([expectedToolcacheDir, false]);
107+
await expect(matlab.getToolcacheDir("win32", release)).resolves.toMatchObject([expectedToolcacheDir, false]);
108108
});
109109

110110
it("uses default toolcache directory toolcache directory is not defined", async () => {
111111
let expectedToolcacheDir = "C:\\hostedtoolcache\\windows\\matlab\\r2022b";
112112
process.env["RUNNER_TOOL_CACHE"] = '';
113113
cacheFileMock.mockReturnValue(expectedToolcacheDir);
114-
await expect(matlab.makeToolcacheDir(release, "win32")).resolves.toMatchObject([expectedToolcacheDir, false]);
114+
await expect(matlab.getToolcacheDir("win32", release)).resolves.toMatchObject([expectedToolcacheDir, false]);
115115
});
116116

117117
it("uses default toolcache directory if d: drive doesn't exist", async () => {
118118
jest.spyOn(fs, "existsSync").mockReturnValue(false);
119119
let expectedToolcacheDir = "C:\\hostedtoolcache\\windows\\matlab\\r2022b";
120-
await expect(matlab.makeToolcacheDir(release, "win32")).resolves.toMatchObject([expectedToolcacheDir, false]);
120+
await expect(matlab.getToolcacheDir("win32", release)).resolves.toMatchObject([expectedToolcacheDir, false]);
121121
});
122122

123123
it("uses default toolcache directory if c: drive doesn't exist", async () => {
124124
jest.spyOn(fs, "existsSync").mockReturnValueOnce(true).mockReturnValue(false);
125125
let expectedToolcacheDir = "C:\\hostedtoolcache\\windows\\matlab\\r2022b";
126-
await expect(matlab.makeToolcacheDir(release, "win32")).resolves.toMatchObject([expectedToolcacheDir, false]);
126+
await expect(matlab.getToolcacheDir("win32", release)).resolves.toMatchObject([expectedToolcacheDir, false]);
127127

128128
});
129129
});

0 commit comments

Comments
 (0)