diff --git a/__tests__/cache-utils.test.ts b/__tests__/cache-utils.test.ts index 695c561cc..755752985 100644 --- a/__tests__/cache-utils.test.ts +++ b/__tests__/cache-utils.test.ts @@ -3,209 +3,341 @@ import * as cache from '@actions/cache'; import * as core from '@actions/core'; import * as cacheUtils from '../src/cache-utils'; import {PackageManagerInfo} from '../src/package-managers'; +import fs, {ObjectEncodingOptions, PathLike} from "fs"; +import {getToolchainDirectoriesFromCachedDirectories} from "../src/cache-utils"; describe('getCommandOutput', () => { - //Arrange - const getExecOutputSpy = jest.spyOn(exec, 'getExecOutput'); - - it('should return trimmed stdout in case of successful exit code', async () => { //Arrange - const stdoutResult = ' stdout '; - const trimmedStdout = stdoutResult.trim(); - - getExecOutputSpy.mockImplementation((commandLine: string) => { - return new Promise(resolve => { - resolve({exitCode: 0, stdout: stdoutResult, stderr: ''}); - }); + const getExecOutputSpy = jest.spyOn(exec, 'getExecOutput'); + + it('should return trimmed stdout in case of successful exit code', async () => { + //Arrange + const stdoutResult = ' stdout '; + const trimmedStdout = stdoutResult.trim(); + + getExecOutputSpy.mockImplementation((commandLine: string) => { + return new Promise(resolve => { + resolve({exitCode: 0, stdout: stdoutResult, stderr: ''}); + }); + }); + + //Act + Assert + return cacheUtils + .getCommandOutput('command') + .then(data => expect(data).toBe(trimmedStdout)); }); - //Act + Assert - return cacheUtils - .getCommandOutput('command') - .then(data => expect(data).toBe(trimmedStdout)); - }); + it('should return error in case of unsuccessful exit code', async () => { + //Arrange + const stderrResult = 'error message'; - it('should return error in case of unsuccessful exit code', async () => { - //Arrange - const stderrResult = 'error message'; + getExecOutputSpy.mockImplementation((commandLine: string) => { + return new Promise(resolve => { + resolve({exitCode: 10, stdout: '', stderr: stderrResult}); + }); + }); - getExecOutputSpy.mockImplementation((commandLine: string) => { - return new Promise(resolve => { - resolve({exitCode: 10, stdout: '', stderr: stderrResult}); - }); + //Act + Assert + await expect(async () => { + await cacheUtils.getCommandOutput('command'); + }).rejects.toThrow(); }); - - //Act + Assert - await expect(async () => { - await cacheUtils.getCommandOutput('command'); - }).rejects.toThrow(); - }); }); describe('getPackageManagerInfo', () => { - it('should return package manager info in case of valid package manager name', async () => { - //Arrange - const packageManagerName = 'default'; - const expectedResult = { - dependencyFilePattern: 'go.sum', - cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE'] - }; - - //Act + Assert - return cacheUtils - .getPackageManagerInfo(packageManagerName) - .then(data => expect(data).toEqual(expectedResult)); - }); + it('should return package manager info in case of valid package manager name', async () => { + //Arrange + const packageManagerName = 'default'; + const expectedResult = { + dependencyFilePattern: 'go.sum', + cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE'] + }; + + //Act + Assert + return cacheUtils + .getPackageManagerInfo(packageManagerName) + .then(data => expect(data).toEqual(expectedResult)); + }); - it('should throw the error in case of invalid package manager name', async () => { - //Arrange - const packageManagerName = 'invalidName'; + it('should throw the error in case of invalid package manager name', async () => { + //Arrange + const packageManagerName = 'invalidName'; - //Act + Assert - await expect(async () => { - await cacheUtils.getPackageManagerInfo(packageManagerName); - }).rejects.toThrow(); - }); + //Act + Assert + await expect(async () => { + await cacheUtils.getPackageManagerInfo(packageManagerName); + }).rejects.toThrow(); + }); }); describe('getCacheDirectoryPath', () => { - //Arrange - const getExecOutputSpy = jest.spyOn(exec, 'getExecOutput'); + //Arrange + const getExecOutputSpy = jest.spyOn(exec, 'getExecOutput'); - const validPackageManager: PackageManagerInfo = { - dependencyFilePattern: 'go.sum', - cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE'] - }; + const validPackageManager: PackageManagerInfo = { + dependencyFilePattern: 'go.sum', + cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE'] + }; - it('should return path to the cache folders which specified package manager uses', async () => { - //Arrange - getExecOutputSpy.mockImplementation((commandLine: string) => { - return new Promise(resolve => { - resolve({exitCode: 0, stdout: 'path/to/cache/folder', stderr: ''}); - }); - }); + it('should return path to the cache folders which specified package manager uses', async () => { + //Arrange + getExecOutputSpy.mockImplementation((commandLine: string) => { + return new Promise(resolve => { + resolve({exitCode: 0, stdout: 'path/to/cache/folder', stderr: ''}); + }); + }); - const expectedResult = ['path/to/cache/folder', 'path/to/cache/folder']; + const expectedResult = ['path/to/cache/folder', 'path/to/cache/folder']; - //Act + Assert - return cacheUtils - .getCacheDirectoryPath(validPackageManager) - .then(data => expect(data).toEqual(expectedResult)); - }); + //Act + Assert + return cacheUtils + .getCacheDirectoryPath(validPackageManager) + .then(data => expect(data).toEqual(expectedResult)); + }); - it('should return path to the cache folder if one command return empty str', async () => { - //Arrange - getExecOutputSpy.mockImplementationOnce((commandLine: string) => { - return new Promise(resolve => { - resolve({exitCode: 0, stdout: 'path/to/cache/folder', stderr: ''}); - }); + it('should return path to the cache folder if one command return empty str', async () => { + //Arrange + getExecOutputSpy.mockImplementationOnce((commandLine: string) => { + return new Promise(resolve => { + resolve({exitCode: 0, stdout: 'path/to/cache/folder', stderr: ''}); + }); + }); + + getExecOutputSpy.mockImplementationOnce((commandLine: string) => { + return new Promise(resolve => { + resolve({exitCode: 0, stdout: '', stderr: ''}); + }); + }); + + const expectedResult = ['path/to/cache/folder']; + + //Act + Assert + return cacheUtils + .getCacheDirectoryPath(validPackageManager) + .then(data => expect(data).toEqual(expectedResult)); }); - getExecOutputSpy.mockImplementationOnce((commandLine: string) => { - return new Promise(resolve => { - resolve({exitCode: 0, stdout: '', stderr: ''}); - }); + it('should throw if the both commands return empty str', async () => { + getExecOutputSpy.mockImplementation((commandLine: string) => { + return new Promise(resolve => { + resolve({exitCode: 10, stdout: '', stderr: ''}); + }); + }); + + //Act + Assert + await expect(async () => { + await cacheUtils.getCacheDirectoryPath(validPackageManager); + }).rejects.toThrow(); }); - const expectedResult = ['path/to/cache/folder']; + it('should throw if the specified package name is invalid', async () => { + getExecOutputSpy.mockImplementation((commandLine: string) => { + return new Promise(resolve => { + resolve({exitCode: 10, stdout: '', stderr: 'Error message'}); + }); + }); + + //Act + Assert + await expect(async () => { + await cacheUtils.getCacheDirectoryPath(validPackageManager); + }).rejects.toThrow(); + }); +}); - //Act + Assert - return cacheUtils - .getCacheDirectoryPath(validPackageManager) - .then(data => expect(data).toEqual(expectedResult)); - }); +describe('isCacheFeatureAvailable', () => { + //Arrange + const isFeatureAvailableSpy = jest.spyOn(cache, 'isFeatureAvailable'); + const warningSpy = jest.spyOn(core, 'warning'); - it('should throw if the both commands return empty str', async () => { - getExecOutputSpy.mockImplementation((commandLine: string) => { - return new Promise(resolve => { - resolve({exitCode: 10, stdout: '', stderr: ''}); - }); - }); + it('should return true when cache feature is available', () => { + //Arrange + isFeatureAvailableSpy.mockImplementation(() => { + return true; + }); - //Act + Assert - await expect(async () => { - await cacheUtils.getCacheDirectoryPath(validPackageManager); - }).rejects.toThrow(); - }); + //Act + const functionResult = cacheUtils.isCacheFeatureAvailable(); - it('should throw if the specified package name is invalid', async () => { - getExecOutputSpy.mockImplementation((commandLine: string) => { - return new Promise(resolve => { - resolve({exitCode: 10, stdout: '', stderr: 'Error message'}); - }); + //Assert + expect(functionResult).toBeTruthy(); }); - //Act + Assert - await expect(async () => { - await cacheUtils.getCacheDirectoryPath(validPackageManager); - }).rejects.toThrow(); - }); -}); + it('should warn when cache feature is unavailable and GHES is not used', () => { + //Arrange + isFeatureAvailableSpy.mockImplementation(() => { + return false; + }); -describe('isCacheFeatureAvailable', () => { - //Arrange - const isFeatureAvailableSpy = jest.spyOn(cache, 'isFeatureAvailable'); - const warningSpy = jest.spyOn(core, 'warning'); + process.env['GITHUB_SERVER_URL'] = 'https://github.com'; - it('should return true when cache feature is available', () => { - //Arrange - isFeatureAvailableSpy.mockImplementation(() => { - return true; + const warningMessage = + 'The runner was not able to contact the cache service. Caching will be skipped'; + + //Act + cacheUtils.isCacheFeatureAvailable(); + + //Assert + expect(warningSpy).toHaveBeenCalledWith(warningMessage); }); - //Act - const functionResult = cacheUtils.isCacheFeatureAvailable(); + it('should return false when cache feature is unavailable', () => { + //Arrange + isFeatureAvailableSpy.mockImplementation(() => { + return false; + }); - //Assert - expect(functionResult).toBeTruthy(); - }); + process.env['GITHUB_SERVER_URL'] = 'https://github.com'; - it('should warn when cache feature is unavailable and GHES is not used', () => { - //Arrange - isFeatureAvailableSpy.mockImplementation(() => { - return false; + //Act + const functionResult = cacheUtils.isCacheFeatureAvailable(); + + //Assert + expect(functionResult).toBeFalsy(); }); - process.env['GITHUB_SERVER_URL'] = 'https://github.com'; + it('should warn when cache feature is unavailable and GHES is used', () => { + //Arrange + isFeatureAvailableSpy.mockImplementation(() => { + return false; + }); - const warningMessage = - 'The runner was not able to contact the cache service. Caching will be skipped'; + process.env['GITHUB_SERVER_URL'] = 'https://nongithub.com'; - //Act - cacheUtils.isCacheFeatureAvailable(); + const warningMessage = + 'Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.'; - //Assert - expect(warningSpy).toHaveBeenCalledWith(warningMessage); - }); + //Act + Assert + expect(cacheUtils.isCacheFeatureAvailable()).toBeFalsy(); + expect(warningSpy).toHaveBeenCalledWith(warningMessage); + }); +}); - it('should return false when cache feature is unavailable', () => { - //Arrange - isFeatureAvailableSpy.mockImplementation(() => { - return false; +describe('parseGoModForToolchainVersion', () => { + const readFileSyncSpy = jest.spyOn(fs, 'readFileSync'); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should return null when go.mod file not exist', async () => { + //Arrange + //Act + const toolchainVersion = cacheUtils.parseGoModForToolchainVersion('/tmp/non/exist/foo.bar') + //Assert + expect(toolchainVersion).toBeNull() }); - process.env['GITHUB_SERVER_URL'] = 'https://github.com'; + it('should return null when go.mod file is empty', async () => { + //Arrange + readFileSyncSpy.mockImplementation(() => ''); + //Act + const toolchainVersion = cacheUtils.parseGoModForToolchainVersion('go.mod') + //Assert + expect(toolchainVersion).toBeNull() + }); - //Act - const functionResult = cacheUtils.isCacheFeatureAvailable(); + it('should return null when go.mod file does not contain toolchain version', async () => { + //Arrange + readFileSyncSpy.mockImplementation(() => ` + module example-mod - //Assert - expect(functionResult).toBeFalsy(); - }); + go 1.21.0 - it('should warn when cache feature is unavailable and GHES is used', () => { - //Arrange - isFeatureAvailableSpy.mockImplementation(() => { - return false; + require golang.org/x/tools v0.13.0 + + require ( + golang.org/x/mod v0.12.0 // indirect + golang.org/x/sys v0.12.0 // indirect + ) + `.replace(/^\s+/gm, '')) + //Act + const toolchainVersion = cacheUtils.parseGoModForToolchainVersion('go.mod') + //Assert + expect(toolchainVersion).toBeNull() }); - process.env['GITHUB_SERVER_URL'] = 'https://nongithub.com'; + it('should return go version when go.mod file contains go version', () => { + //Arrange + readFileSyncSpy.mockImplementation(() => ` + module example-mod + + go 1.21.0 + + toolchain go1.21.1 + + require golang.org/x/tools v0.13.0 - const warningMessage = - 'Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.'; + require ( + golang.org/x/mod v0.12.0 // indirect + golang.org/x/sys v0.12.0 // indirect + ) + `.replace(/^\s+/gm, '')) - //Act + Assert - expect(cacheUtils.isCacheFeatureAvailable()).toBeFalsy(); - expect(warningSpy).toHaveBeenCalledWith(warningMessage); - }); + //Act + const toolchainVersion = cacheUtils.parseGoModForToolchainVersion('go.mod') + //Assert + expect(toolchainVersion).toBe('1.21.1') + }) }); + +describe('getToolchainDirectoriesFromCachedDirectories', () => { + const readdirSyncSpy = jest.spyOn(fs, 'readdirSync'); + const existsSyncSpy = jest.spyOn(fs, 'existsSync'); + const lstatSync = jest.spyOn(fs, 'lstatSync'); + + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should return empty array when cacheDirectories is empty', async () => { + const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories('foo', []) + expect(toolcacheDirectories).toEqual([]) + }) + + it('should return empty array when cacheDirectories does not contain /go/pkg', async () => { + readdirSyncSpy.mockImplementation( + (dir) => [`${dir}1`, `${dir}2`, `${dir}3`] + .map(s => { + const de = new fs.Dirent(); + de.name = s; + de.isDirectory = () => true; + return de + })); + + const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories('1.1.1', ['foo', 'bar']) + expect(toolcacheDirectories).toEqual([]) + }) + + it('should return empty array when cacheDirectories does not contain toolchain@v[0-9.]+-go{goVersion}', async () => { + readdirSyncSpy.mockImplementation( + dir => [`${dir}1`, `${dir}2`, `${dir}3`] + .map(s => { + const de = new fs.Dirent(); + de.name = s; + de.isDirectory = () => true; + return de + })); + + const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories('foo', ['foo/go/pkg/mod', 'bar']) + expect(toolcacheDirectories).toEqual([]) + }) + + it('should return one entry when cacheDirectories contains toolchain@v[0-9.]+-go{goVersion} in /pkg/mod', async () => { + let seqNo = 1 + readdirSyncSpy.mockImplementation( + (dir) => [`toolchain@v0.0.1-go1.1.1.arch-${seqNo++}`] + .map(s => { + const de = new fs.Dirent(); + de.name = s; + de.isDirectory = () => true; + return de + })); + existsSyncSpy.mockReturnValue(true) + // @ts-ignore + lstatSync.mockImplementation(() => ({isDirectory: () => true})) + + const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories('1.1.1', ['/foo/go/pkg/mod', 'bar']) + expect(toolcacheDirectories).toEqual(['/foo/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.1.1.arch-1']) + }) +}) diff --git a/src/cache-restore.ts b/src/cache-restore.ts index 183df9ea5..968a3f730 100644 --- a/src/cache-restore.ts +++ b/src/cache-restore.ts @@ -6,7 +6,7 @@ import fs from 'fs'; import {State, Outputs} from './constants'; import {PackageManagerInfo} from './package-managers'; -import {getCacheDirectoryPath, getPackageManagerInfo} from './cache-utils'; +import {getCacheDirectoryPath, getPackageManagerInfo, parseGoModForToolchainVersion} from './cache-utils'; export const restoreCache = async ( versionSpec: string, @@ -21,6 +21,14 @@ export const restoreCache = async ( const dependencyFilePath = cacheDependencyPath ? cacheDependencyPath : findDependencyFile(packageManagerInfo); + + // In order to do not duplicate evaluation of dependency paths, we get + // toolchain Version here and pass to the saveCache via the state + const toolchainVersion = cacheDependencyPath && path.basename(cacheDependencyPath) === 'go.mod' + ? parseGoModForToolchainVersion(cacheDependencyPath) + : null + core.saveState(State.ToolchainVersion, toolchainVersion); + const fileHash = await glob.hashFiles(dependencyFilePath); if (!fileHash) { diff --git a/src/cache-save.ts b/src/cache-save.ts index 584d0a697..a6fdf3723 100644 --- a/src/cache-save.ts +++ b/src/cache-save.ts @@ -2,7 +2,8 @@ import * as core from '@actions/core'; import * as cache from '@actions/cache'; import fs from 'fs'; import {State} from './constants'; -import {getCacheDirectoryPath, getPackageManagerInfo} from './cache-utils'; +import {getCacheDirectoryPath, getPackageManagerInfo, getToolchainDirectoriesFromCachedDirectories} from './cache-utils'; +import {isSelfHosted} from "./utils"; // Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in // @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to @@ -72,6 +73,16 @@ const cachePackages = async () => { ); return; } + if (!isSelfHosted()) { + const toolchainVersion = core.getState(State.ToolchainVersion); + if (toolchainVersion) { + const toolchainDirectories = getToolchainDirectoriesFromCachedDirectories(toolchainVersion, cachePaths) + toolchainDirectories.forEach(toolchainDirectory => { + core.warning(`Toolchain version ${toolchainVersion} will be removed from cache: ${toolchainDirectory}`); + fs.rmSync(toolchainDirectory, {recursive: true}); + }) + } + } const cacheId = await cache.saveCache(cachePaths, primaryKey); if (cacheId === -1) { diff --git a/src/cache-utils.ts b/src/cache-utils.ts index 545c97af1..8b2580a4a 100644 --- a/src/cache-utils.ts +++ b/src/cache-utils.ts @@ -2,84 +2,121 @@ import * as cache from '@actions/cache'; import * as core from '@actions/core'; import * as exec from '@actions/exec'; import {supportedPackageManagers, PackageManagerInfo} from './package-managers'; +import fs from "fs"; export const getCommandOutput = async (toolCommand: string) => { - let {stdout, stderr, exitCode} = await exec.getExecOutput( - toolCommand, - undefined, - {ignoreReturnCode: true} - ); - - if (exitCode) { - stderr = !stderr.trim() - ? `The '${toolCommand}' command failed with exit code: ${exitCode}` - : stderr; - throw new Error(stderr); - } - - return stdout.trim(); + let {stdout, stderr, exitCode} = await exec.getExecOutput( + toolCommand, + undefined, + {ignoreReturnCode: true} + ); + + if (exitCode) { + stderr = !stderr.trim() + ? `The '${toolCommand}' command failed with exit code: ${exitCode}` + : stderr; + throw new Error(stderr); + } + + return stdout.trim(); }; export const getPackageManagerInfo = async (packageManager: string) => { - if (!supportedPackageManagers[packageManager]) { - throw new Error( - `It's not possible to use ${packageManager}, please, check correctness of the package manager name spelling.` - ); - } - const obtainedPackageManager = supportedPackageManagers[packageManager]; + if (!supportedPackageManagers[packageManager]) { + throw new Error( + `It's not possible to use ${packageManager}, please, check correctness of the package manager name spelling.` + ); + } + const obtainedPackageManager = supportedPackageManagers[packageManager]; - return obtainedPackageManager; + return obtainedPackageManager; }; export const getCacheDirectoryPath = async ( - packageManagerInfo: PackageManagerInfo + packageManagerInfo: PackageManagerInfo ) => { - const pathOutputs = await Promise.allSettled( - packageManagerInfo.cacheFolderCommandList.map(async command => - getCommandOutput(command) - ) - ); - - const results = pathOutputs.map(item => { - if (item.status === 'fulfilled') { - return item.value; - } else { - core.info(`[warning]getting cache directory path failed: ${item.reason}`); - } + const pathOutputs = await Promise.allSettled( + packageManagerInfo.cacheFolderCommandList.map(async command => + getCommandOutput(command) + ) + ); - return ''; - }); + const results = pathOutputs.map(item => { + if (item.status === 'fulfilled') { + return item.value; + } else { + core.info(`[warning]getting cache directory path failed: ${item.reason}`); + } - const cachePaths = results.filter(item => item); + return ''; + }); - if (!cachePaths.length) { - throw new Error(`Could not get cache folder paths.`); - } + const cachePaths = results.filter(item => item); + + if (!cachePaths.length) { + throw new Error(`Could not get cache folder paths.`); + } - return cachePaths; + return cachePaths; }; export function isGhes(): boolean { - const ghUrl = new URL( - process.env['GITHUB_SERVER_URL'] || 'https://github.com' - ); - return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM'; + const ghUrl = new URL( + process.env['GITHUB_SERVER_URL'] || 'https://github.com' + ); + return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM'; } export function isCacheFeatureAvailable(): boolean { - if (cache.isFeatureAvailable()) { - return true; - } + if (cache.isFeatureAvailable()) { + return true; + } + + if (isGhes()) { + core.warning( + 'Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.' + ); + return false; + } - if (isGhes()) { core.warning( - 'Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.' + 'The runner was not able to contact the cache service. Caching will be skipped' ); return false; - } +} + +export function parseGoModForToolchainVersion(goModPath: string): string | null { + try { + const goMod = fs.readFileSync(goModPath, 'utf8'); + const matches = goMod.match(/^toolchain\s+go(\S+)/m); + if (matches && matches.length > 0) { + return matches[1] + } + } catch (error) { + if (error.message && error.message.startsWith('ENOENT')) { + core.warning(`go.mod file not found at ${goModPath}, can't parse toolchain version`) + return null + } + throw error + } + return null; +} + +function isDirent(item: fs.Dirent | string): item is fs.Dirent { + return item instanceof fs.Dirent; +} - core.warning( - 'The runner was not able to contact the cache service. Caching will be skipped' - ); - return false; +export function getToolchainDirectoriesFromCachedDirectories(goVersion: string, cacheDirectories: string[]): string[] { + const re = new RegExp(`^toolchain@v[0-9.]+-go${goVersion}\.`) + return cacheDirectories + // This line should be replaced with separating the cache directory from build artefact directory + // see PoC PR: https://github.com/actions/setup-go/pull/426 + // Till then, the workaround is expected to work in most cases, and it won't cause any harm + .filter(dir => dir.endsWith('/pkg/mod')) + .map(dir => `${dir}/golang.org`) + .flatMap(dir => + fs.readdirSync(dir).map(subdir => isDirent(subdir) ? subdir.name : dir) + .filter(subdir => re.test(subdir)) + .map(subdir => `${dir}/${subdir}`) + ) } diff --git a/src/constants.ts b/src/constants.ts index b43d18c00..f5d8d1ab5 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,6 +1,7 @@ export enum State { CachePrimaryKey = 'CACHE_KEY', - CacheMatchedKey = 'CACHE_RESULT' + CacheMatchedKey = 'CACHE_RESULT', + ToolchainVersion = 'TOOLCACHE_VERSION' } export enum Outputs { diff --git a/src/installer.ts b/src/installer.ts index d8ac3a125..d3179dc50 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -6,7 +6,7 @@ import * as httpm from '@actions/http-client'; import * as sys from './system'; import fs from 'fs'; import os from 'os'; -import {StableReleaseAlias} from './utils'; +import {isSelfHosted, StableReleaseAlias} from './utils'; type InstallationType = 'dist' | 'manifest'; @@ -175,10 +175,7 @@ async function cacheWindowsDir( if (os.platform() !== 'win32') return false; // make sure the action runs in the hosted environment - if ( - process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' && - process.env['AGENT_ISSELFHOSTED'] === '1' - ) + if (isSelfHosted()) return false; const defaultToolCacheRoot = process.env['RUNNER_TOOL_CACHE']; diff --git a/src/utils.ts b/src/utils.ts index 79d03bcad..3043596dd 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -2,3 +2,7 @@ export enum StableReleaseAlias { Stable = 'stable', OldStable = 'oldstable' } + +export function isSelfHosted(): boolean { + return process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' || process.env['AGENT_ISSELFHOSTED'] === '1' +}