Skip to content

Commit dbaa9ed

Browse files
committed
Remove toolchain directories from the cache
1 parent bfd2fb3 commit dbaa9ed

16 files changed

+527
-14
lines changed

.github/workflows/toolchain.yml

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Validate 'setup-go'
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths-ignore:
8+
- '**.md'
9+
pull_request:
10+
paths-ignore:
11+
- '**.md'
12+
schedule:
13+
- cron: 0 0 * * *
14+
15+
jobs:
16+
local-cache:
17+
name: Setup local-cache version
18+
runs-on: ${{ matrix.os }}
19+
strategy:
20+
fail-fast: false
21+
matrix:
22+
os: [macos-latest, windows-latest, ubuntu-latest]
23+
go: [1.21]
24+
steps:
25+
- name: Checkout
26+
uses: actions/checkout@v4
27+
28+
- name: substitute go.mod with toolchain
29+
run: |
30+
cp __tests__/toolchain.go.mod go.mod
31+
shell: bash
32+
33+
- name: setup-go ${{ matrix.go }}
34+
uses: ./
35+
with:
36+
go-version: ${{ matrix.go }}
37+
38+
- name: verify go
39+
run: __tests__/verify-go.sh ${{ matrix.go }}
40+
shell: bash

.idea/.gitignore

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/setup-go.iml

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

__tests__/cache-utils.test.ts

+177
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import * as cache from '@actions/cache';
33
import * as core from '@actions/core';
44
import * as cacheUtils from '../src/cache-utils';
55
import {PackageManagerInfo} from '../src/package-managers';
6+
import fs, {ObjectEncodingOptions, PathLike} from 'fs';
7+
import {getToolchainDirectoriesFromCachedDirectories} from '../src/cache-utils';
68

79
describe('getCommandOutput', () => {
810
//Arrange
@@ -209,3 +211,178 @@ describe('isCacheFeatureAvailable', () => {
209211
expect(warningSpy).toHaveBeenCalledWith(warningMessage);
210212
});
211213
});
214+
215+
describe('parseGoModForToolchainVersion', () => {
216+
const readFileSyncSpy = jest.spyOn(fs, 'readFileSync');
217+
218+
afterEach(() => {
219+
jest.clearAllMocks();
220+
});
221+
222+
it('should return null when go.mod file not exist', async () => {
223+
//Arrange
224+
//Act
225+
const toolchainVersion = cacheUtils.parseGoModForToolchainVersion(
226+
'/tmp/non/exist/foo.bar'
227+
);
228+
//Assert
229+
expect(toolchainVersion).toBeNull();
230+
});
231+
232+
it('should return null when go.mod file is empty', async () => {
233+
//Arrange
234+
readFileSyncSpy.mockImplementation(() => '');
235+
//Act
236+
const toolchainVersion = cacheUtils.parseGoModForToolchainVersion('go.mod');
237+
//Assert
238+
expect(toolchainVersion).toBeNull();
239+
});
240+
241+
it('should return null when go.mod file does not contain toolchain version', async () => {
242+
//Arrange
243+
readFileSyncSpy.mockImplementation(() =>
244+
`
245+
module example-mod
246+
247+
go 1.21.0
248+
249+
require golang.org/x/tools v0.13.0
250+
251+
require (
252+
golang.org/x/mod v0.12.0 // indirect
253+
golang.org/x/sys v0.12.0 // indirect
254+
)
255+
`.replace(/^\s+/gm, '')
256+
);
257+
//Act
258+
const toolchainVersion = cacheUtils.parseGoModForToolchainVersion('go.mod');
259+
//Assert
260+
expect(toolchainVersion).toBeNull();
261+
});
262+
263+
it('should return go version when go.mod file contains go version', () => {
264+
//Arrange
265+
readFileSyncSpy.mockImplementation(() =>
266+
`
267+
module example-mod
268+
269+
go 1.21.0
270+
271+
toolchain go1.21.1
272+
273+
require golang.org/x/tools v0.13.0
274+
275+
require (
276+
golang.org/x/mod v0.12.0 // indirect
277+
golang.org/x/sys v0.12.0 // indirect
278+
)
279+
`.replace(/^\s+/gm, '')
280+
);
281+
282+
//Act
283+
const toolchainVersion = cacheUtils.parseGoModForToolchainVersion('go.mod');
284+
//Assert
285+
expect(toolchainVersion).toBe('1.21.1');
286+
});
287+
288+
it('should return go version when go.mod file contains more than one go version', () => {
289+
//Arrange
290+
readFileSyncSpy.mockImplementation(() =>
291+
`
292+
module example-mod
293+
294+
go 1.21.0
295+
296+
toolchain go1.21.0
297+
toolchain go1.21.1
298+
299+
require golang.org/x/tools v0.13.0
300+
301+
require (
302+
golang.org/x/mod v0.12.0 // indirect
303+
golang.org/x/sys v0.12.0 // indirect
304+
)
305+
`.replace(/^\s+/gm, '')
306+
);
307+
308+
//Act
309+
const toolchainVersion = cacheUtils.parseGoModForToolchainVersion('go.mod');
310+
//Assert
311+
expect(toolchainVersion).toBe('1.21.1');
312+
});
313+
});
314+
315+
describe('getToolchainDirectoriesFromCachedDirectories', () => {
316+
const readdirSyncSpy = jest.spyOn(fs, 'readdirSync');
317+
const existsSyncSpy = jest.spyOn(fs, 'existsSync');
318+
const lstatSync = jest.spyOn(fs, 'lstatSync');
319+
320+
afterEach(() => {
321+
jest.clearAllMocks();
322+
});
323+
324+
it('should return empty array when cacheDirectories is empty', async () => {
325+
const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories(
326+
'foo',
327+
[]
328+
);
329+
expect(toolcacheDirectories).toEqual([]);
330+
});
331+
332+
it('should return empty array when cacheDirectories does not contain /go/pkg', async () => {
333+
readdirSyncSpy.mockImplementation(dir =>
334+
[`${dir}1`, `${dir}2`, `${dir}3`].map(s => {
335+
const de = new fs.Dirent();
336+
de.name = s;
337+
de.isDirectory = () => true;
338+
return de;
339+
})
340+
);
341+
342+
const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories(
343+
'1.1.1',
344+
['foo', 'bar']
345+
);
346+
expect(toolcacheDirectories).toEqual([]);
347+
});
348+
349+
it('should return empty array when cacheDirectories does not contain toolchain@v[0-9.]+-go{goVersion}', async () => {
350+
readdirSyncSpy.mockImplementation(dir =>
351+
[`${dir}1`, `${dir}2`, `${dir}3`].map(s => {
352+
const de = new fs.Dirent();
353+
de.name = s;
354+
de.isDirectory = () => true;
355+
return de;
356+
})
357+
);
358+
359+
const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories(
360+
'foo',
361+
['foo/go/pkg/mod', 'bar']
362+
);
363+
expect(toolcacheDirectories).toEqual([]);
364+
});
365+
366+
it('should return one entry when cacheDirectories contains toolchain@v[0-9.]+-go{goVersion} in /pkg/mod', async () => {
367+
let seqNo = 1;
368+
readdirSyncSpy.mockImplementation(dir =>
369+
[`[email protected]${seqNo++}`].map(s => {
370+
const de = new fs.Dirent();
371+
de.name = s;
372+
de.isDirectory = () => true;
373+
return de;
374+
})
375+
);
376+
existsSyncSpy.mockReturnValue(true);
377+
// @ts-ignore - jest does not have relaxed mocks, so we ignore not-implemented methods
378+
lstatSync.mockImplementation(() => ({isDirectory: () => true}));
379+
380+
const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories(
381+
'1.1.1',
382+
['/foo/go/pkg/mod', 'bar']
383+
);
384+
expect(toolcacheDirectories).toEqual([
385+
'/foo/go/pkg/mod/golang.org/[email protected]'
386+
]);
387+
});
388+
});

__tests__/toolchain.go.mod

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module example-mod
2+
3+
go 1.21.0
4+
5+
toolchain go1.21.0
6+
toolchain go1.21.1
7+
8+
require golang.org/x/tools v0.13.0
9+
10+
require (
11+
golang.org/x/mod v0.12.0 // indirect
12+
golang.org/x/sys v0.12.0 // indirect
13+
)

__tests__/utils.test.ts

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import {isSelfHosted} from '../src/utils';
2+
3+
describe('utils', () => {
4+
describe('isSelfHosted', () => {
5+
let AGENT_ISSELFHOSTED: string | undefined;
6+
let RUNNER_ENVIRONMENT: string | undefined;
7+
8+
beforeEach(() => {
9+
AGENT_ISSELFHOSTED = process.env['AGENT_ISSELFHOSTED'];
10+
delete process.env['AGENT_ISSELFHOSTED'];
11+
RUNNER_ENVIRONMENT = process.env['RUNNER_ENVIRONMENT'];
12+
delete process.env['RUNNER_ENVIRONMENT'];
13+
});
14+
15+
afterEach(() => {
16+
if (AGENT_ISSELFHOSTED === undefined) {
17+
delete process.env['AGENT_ISSELFHOSTED'];
18+
} else {
19+
process.env['AGENT_ISSELFHOSTED'] = AGENT_ISSELFHOSTED;
20+
}
21+
if (RUNNER_ENVIRONMENT === undefined) {
22+
delete process.env['RUNNER_ENVIRONMENT'];
23+
} else {
24+
process.env['RUNNER_ENVIRONMENT'] = RUNNER_ENVIRONMENT;
25+
}
26+
});
27+
28+
it('isSelfHosted should be true if no environment variables set', () => {
29+
expect(isSelfHosted()).toBeTruthy();
30+
});
31+
32+
it('isSelfHosted should be true if environment variable is not set to denote GitHub hosted', () => {
33+
process.env['RUNNER_ENVIRONMENT'] = 'some';
34+
expect(isSelfHosted()).toBeTruthy();
35+
});
36+
37+
it('isSelfHosted should be true if environment variable set to denote Azure Pipelines self hosted', () => {
38+
process.env['AGENT_ISSELFHOSTED'] = '1';
39+
expect(isSelfHosted()).toBeTruthy();
40+
});
41+
42+
it('isSelfHosted should be false if environment variable set to denote GitHub hosted', () => {
43+
process.env['RUNNER_ENVIRONMENT'] = 'github-hosted';
44+
expect(isSelfHosted()).toBeFalsy();
45+
});
46+
47+
it('isSelfHosted should be false if environment variable is not set to denote Azure Pipelines self hosted', () => {
48+
process.env['AGENT_ISSELFHOSTED'] = 'some';
49+
expect(isSelfHosted()).toBeFalsy();
50+
});
51+
});
52+
});

0 commit comments

Comments
 (0)