@actions/tool-cache: convert to an ESM module (#2274)

* `@actions/tool-cache`: convert to an ESM module

* Fix jest config

* Downgrade `nock` since it's conflicting with `@actions/attest`'s version
This commit is contained in:
Daniel Kennedy
2026-01-29 11:26:14 -05:00
committed by GitHub
parent 7a0147b5c6
commit 9d912b1840
10 changed files with 99 additions and 85 deletions
+3 -3
View File
@@ -15,11 +15,11 @@ module.exports = {
'^@actions/http-client/lib/interfaces$': '<rootDir>/packages/http-client/lib/interfaces.js', '^@actions/http-client/lib/interfaces$': '<rootDir>/packages/http-client/lib/interfaces.js',
'^@actions/github$': '<rootDir>/packages/github/lib/github.js', '^@actions/github$': '<rootDir>/packages/github/lib/github.js',
'^@actions/github/lib/utils$': '<rootDir>/packages/github/lib/utils.js', '^@actions/github/lib/utils$': '<rootDir>/packages/github/lib/utils.js',
'^@actions/glob$': '<rootDir>/packages/glob/lib/glob.js' '^@actions/glob$': '<rootDir>/packages/glob/lib/glob.js',
'^@actions/tool-cache$': '<rootDir>/packages/tool-cache/lib/tool-cache.js'
}, },
transform: { transform: {
'^.+\\.(ts|js)$': ['ts-jest', { '^.+\\.(ts|js)$': ['ts-jest', {
isolatedModules: true,
diagnostics: {warnOnly: true}, diagnostics: {warnOnly: true},
tsconfig: { tsconfig: {
allowJs: true, allowJs: true,
@@ -30,7 +30,7 @@ module.exports = {
}] }]
}, },
transformIgnorePatterns: [ transformIgnorePatterns: [
'/node_modules/(?!(@octokit|@actions/github|@actions/http-client|@actions/io|@actions/exec|@actions/core|@actions/glob|universal-user-agent|before-after-hook)/)' '/node_modules/(?!(@octokit|@actions/github|@actions/http-client|@actions/io|@actions/exec|@actions/core|@actions/glob|@actions/tool-cache|universal-user-agent|before-after-hook)/)'
], ],
verbose: true verbose: true
} }
+15 -3
View File
@@ -1,5 +1,10 @@
# @actions/tool-cache Releases # @actions/tool-cache Releases
## 4.0.0
- **Breaking change**: Package is now ESM-only
- CommonJS consumers must use dynamic `import()` instead of `require()`
### 3.0.1 ### 3.0.1
- Bump `@actions/http-client` to `3.0.2` - Bump `@actions/http-client` to `3.0.2`
@@ -17,29 +22,36 @@
- Remove dependency on `uuid` package [#1824](https://github.com/actions/toolkit/pull/1824), [#1842](https://github.com/actions/toolkit/pull/1842) - Remove dependency on `uuid` package [#1824](https://github.com/actions/toolkit/pull/1824), [#1842](https://github.com/actions/toolkit/pull/1842)
### 2.0.1 ### 2.0.1
- Update to v2.0.1 of `@actions/http-client` [#1087](https://github.com/actions/toolkit/pull/1087) - Update to v2.0.1 of `@actions/http-client` [#1087](https://github.com/actions/toolkit/pull/1087)
### 2.0.0 ### 2.0.0
- Update to v2.0.0 of `@actions/http-client` - Update to v2.0.0 of `@actions/http-client`
- The type of the `headers` parameter in the exported function `downloadTool` has been narrowed from `{ [header: string]: any }` to `{ [header: string]: number | string | string[] | undefined; }` (that is, `http.OutgoingHttpHeaders`). - The type of the `headers` parameter in the exported function `downloadTool` has been narrowed from `{ [header: string]: any }` to `{ [header: string]: number | string | string[] | undefined; }` (that is, `http.OutgoingHttpHeaders`).
This is strictly a compile-time change for TypeScript consumers. Previous attempts to use a header value of a type other than those now accepted would have resulted in an error at run time. This is strictly a compile-time change for TypeScript consumers. Previous attempts to use a header value of a type other than those now accepted would have resulted in an error at run time.
### 1.7.2 ### 1.7.2
- Update `lockfileVersion` to `v2` in `package-lock.json [#1025](https://github.com/actions/toolkit/pull/1025)
- Update `lockfileVersion` to `v2` in `package-lock.json` [#1025](https://github.com/actions/toolkit/pull/1025)
### 1.7.1 ### 1.7.1
- [Fallback to os-releases file to get linux version](https://github.com/actions/toolkit/pull/594) - [Fallback to os-releases file to get linux version](https://github.com/actions/toolkit/pull/594)
- [Update to latest @actions/io verison](https://github.com/actions/toolkit/pull/838) - [Update to latest @actions/io verison](https://github.com/actions/toolkit/pull/838)
### 1.7.0 ### 1.7.0
- [Allow arbirtary headers when downloading tools to the tc](https://github.com/actions/toolkit/pull/530) - [Allow arbirtary headers when downloading tools to the tc](https://github.com/actions/toolkit/pull/530)
- [Export `isExplicitVersion` and `evaluateVersions` functions](https://github.com/actions/toolkit/pull/796) - [Export `isExplicitVersion` and `evaluateVersions` functions](https://github.com/actions/toolkit/pull/796)
- [Force overwrite on default when extracted compressed files](https://github.com/actions/toolkit/pull/807) - [Force overwrite on default when extracted compressed files](https://github.com/actions/toolkit/pull/807)
### 1.6.1 ### 1.6.1
- [Update @actions/core version](https://github.com/actions/toolkit/pull/636) - [Update @actions/core version](https://github.com/actions/toolkit/pull/636)
### 1.6.0 ### 1.6.0
- [Add extractXar function to extract XAR files](https://github.com/actions/toolkit/pull/207) - [Add extractXar function to extract XAR files](https://github.com/actions/toolkit/pull/207)
### 1.3.5 ### 1.3.5
@@ -82,4 +94,4 @@ Here is [the security issue](https://github.com/actions/http-client/pull/27) tha
### 1.0.0 ### 1.0.0
- Initial release - Initial release
@@ -1,5 +1,5 @@
import * as tc from '../src/tool-cache' import * as tc from '../src/tool-cache.js'
import * as mm from '../src/manifest' // --> OFF import * as mm from '../src/manifest.js'
// needs to be require for core node modules to be mocked // needs to be require for core node modules to be mocked
// eslint-disable-next-line @typescript-eslint/no-require-imports // eslint-disable-next-line @typescript-eslint/no-require-imports
@@ -36,7 +36,7 @@ describe('@actions/tool-cache-manifest', () => {
archSpy.mockImplementation(() => os.arch) archSpy.mockImplementation(() => os.arch)
execSpy = jest.spyOn(cp, 'execSync') execSpy = jest.spyOn(cp, 'execSync')
readLsbSpy = jest.spyOn(mm, '_readLinuxVersionFile') readLsbSpy = jest.spyOn(mm._internal, 'readLinuxVersionFile')
getSpy = jest.spyOn(tc, 'getManifestFromRepo') getSpy = jest.spyOn(tc, 'getManifestFromRepo')
getSpy.mockImplementation(() => <mm.IToolRelease[]>manifestData) getSpy.mockImplementation(() => <mm.IToolRelease[]>manifestData)
@@ -1,5 +1,5 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import {RetryHelper} from '../src/retry-helper' import {RetryHelper} from '../src/retry-helper.js'
let info: string[] let info: string[]
let retryHelper: RetryHelper let retryHelper: RetryHelper
@@ -12,7 +12,7 @@ process.env['RUNNER_TEMP'] = tempPath
process.env['RUNNER_TOOL_CACHE'] = cachePath process.env['RUNNER_TOOL_CACHE'] = cachePath
// eslint-disable-next-line import/first // eslint-disable-next-line import/first
import * as tc from '../src/tool-cache' import * as tc from '../src/tool-cache.js'
const IS_WINDOWS = process.platform === 'win32' const IS_WINDOWS = process.platform === 'win32'
const IS_MAC = process.platform === 'darwin' const IS_MAC = process.platform === 'darwin'
+33 -42
View File
@@ -1,49 +1,48 @@
{ {
"name": "@actions/tool-cache", "name": "@actions/tool-cache",
"version": "3.0.1", "version": "4.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@actions/tool-cache", "name": "@actions/tool-cache",
"version": "3.0.1", "version": "4.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^2.0.1", "@actions/core": "^3.0.0",
"@actions/exec": "^2.0.0", "@actions/exec": "^3.0.0",
"@actions/http-client": "^3.0.2", "@actions/http-client": "^4.0.0",
"@actions/io": "^2.0.0", "@actions/io": "^3.0.0",
"semver": "^6.1.0" "semver": "^7.7.3"
}, },
"devDependencies": { "devDependencies": {
"@types/nock": "^11.1.0", "@types/semver": "^7.7.1",
"@types/semver": "^6.0.0", "nock": "^13.5.1"
"nock": "^13.2.9"
} }
}, },
"node_modules/@actions/core": { "node_modules/@actions/core": {
"version": "2.0.1", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-2.0.1.tgz", "resolved": "https://registry.npmjs.org/@actions/core/-/core-3.0.0.tgz",
"integrity": "sha512-oBfqT3GwkvLlo1fjvhQLQxuwZCGTarTE5OuZ2Wg10hvhBj7LRIlF611WT4aZS6fDhO5ZKlY7lCAZTlpmyaHaeg==", "integrity": "sha512-zYt6cz+ivnTmiT/ksRVriMBOiuoUpDCJJlZ5KPl2/FRdvwU3f7MPh9qftvbkXJThragzUZieit2nyHUyw53Seg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/exec": "^2.0.0", "@actions/exec": "^3.0.0",
"@actions/http-client": "^3.0.0" "@actions/http-client": "^4.0.0"
} }
}, },
"node_modules/@actions/exec": { "node_modules/@actions/exec": {
"version": "2.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-2.0.0.tgz", "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-3.0.0.tgz",
"integrity": "sha512-k8ngrX2voJ/RIN6r9xB82NVqKpnMRtxDoiO+g3olkIUpQNqjArXrCQceduQZCQj3P3xm32pChRLqRrtXTlqhIw==", "integrity": "sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/io": "^2.0.0" "@actions/io": "^3.0.2"
} }
}, },
"node_modules/@actions/http-client": { "node_modules/@actions/http-client": {
"version": "3.0.2", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-4.0.0.tgz",
"integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==", "integrity": "sha512-QuwPsgVMsD6qaPD57GLZi9sqzAZCtiJT8kVBCDpLtxhL5MydQ4gS+DrejtZZPdIYyB1e95uCK9Luyds7ybHI3g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tunnel": "^0.0.6", "tunnel": "^0.0.6",
@@ -51,26 +50,15 @@
} }
}, },
"node_modules/@actions/io": { "node_modules/@actions/io": {
"version": "2.0.0", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-2.0.0.tgz", "resolved": "https://registry.npmjs.org/@actions/io/-/io-3.0.2.tgz",
"integrity": "sha512-Jv33IN09XLO+0HS79aaODsvIRyduiF7NY/F6LYeK5oeUmrsz7aFdRphQjFoESF4jS7lMauDOttKALcpapVDIAg==", "integrity": "sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/nock": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/@types/nock/-/nock-11.1.0.tgz",
"integrity": "sha512-jI/ewavBQ7X5178262JQR0ewicPAcJhXS/iFaNJl0VHLfyosZ/kwSrsa6VNQNSO8i9d8SqdRgOtZSOKJ/+iNMw==",
"deprecated": "This is a stub types definition. nock provides its own type definitions, so you do not need this installed.",
"dev": true,
"license": "MIT",
"dependencies": {
"nock": "*"
}
},
"node_modules/@types/semver": { "node_modules/@types/semver": {
"version": "6.2.7", "version": "7.7.1",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-6.2.7.tgz", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-blctEWbzUFzQx799RZjzzIdBJOXmE37YYEyDtKkx5Dg+V7o/zyyAxLPiI98A2jdTtDgxZleMdfV+7p8WbRJ1OQ==", "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
@@ -132,12 +120,15 @@
} }
}, },
"node_modules/semver": { "node_modules/semver": {
"version": "6.3.1", "version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"license": "ISC", "license": "ISC",
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
} }
}, },
"node_modules/tunnel": { "node_modules/tunnel": {
+15 -9
View File
@@ -1,6 +1,6 @@
{ {
"name": "@actions/tool-cache", "name": "@actions/tool-cache",
"version": "3.0.1", "version": "4.0.0",
"description": "Actions tool-cache lib", "description": "Actions tool-cache lib",
"keywords": [ "keywords": [
"github", "github",
@@ -9,8 +9,15 @@
], ],
"homepage": "https://github.com/actions/toolkit/tree/main/packages/tool-cache", "homepage": "https://github.com/actions/toolkit/tree/main/packages/tool-cache",
"license": "MIT", "license": "MIT",
"type": "module",
"main": "lib/tool-cache.js", "main": "lib/tool-cache.js",
"types": "lib/tool-cache.d.ts", "types": "lib/tool-cache.d.ts",
"exports": {
".": {
"types": "./lib/tool-cache.d.ts",
"import": "./lib/tool-cache.js"
}
},
"directories": { "directories": {
"lib": "lib", "lib": "lib",
"test": "__tests__" "test": "__tests__"
@@ -36,15 +43,14 @@
"url": "https://github.com/actions/toolkit/issues" "url": "https://github.com/actions/toolkit/issues"
}, },
"dependencies": { "dependencies": {
"@actions/core": "^2.0.1", "@actions/core": "^3.0.0",
"@actions/exec": "^2.0.0", "@actions/exec": "^3.0.0",
"@actions/http-client": "^3.0.2", "@actions/http-client": "^4.0.0",
"@actions/io": "^2.0.0", "@actions/io": "^3.0.0",
"semver": "^6.1.0" "semver": "^7.7.3"
}, },
"devDependencies": { "devDependencies": {
"@types/nock": "^11.1.0", "@types/semver": "^7.7.1",
"@types/semver": "^6.0.0", "nock": "^13.5.1"
"nock": "^13.2.9"
} }
} }
+22 -18
View File
@@ -1,12 +1,25 @@
import * as semver from 'semver' import * as semver from 'semver'
import {debug} from '@actions/core' import {debug} from '@actions/core'
import * as os from 'os'
import * as cp from 'child_process'
import * as fs from 'fs'
// needs to be require for core node modules to be mocked // Internal object for testability (allows mocking in ESM)
/* eslint @typescript-eslint/no-require-imports: 0 */ export const _internal = {
readLinuxVersionFile(): string {
const lsbReleaseFile = '/etc/lsb-release'
const osReleaseFile = '/etc/os-release'
let contents = ''
import os = require('os') if (fs.existsSync(lsbReleaseFile)) {
import cp = require('child_process') contents = fs.readFileSync(lsbReleaseFile).toString()
import fs = require('fs') } else if (fs.existsSync(osReleaseFile)) {
contents = fs.readFileSync(osReleaseFile).toString()
}
return contents
}
}
/* /*
NOTE: versions must be sorted descending by version in the manifest NOTE: versions must be sorted descending by version in the manifest
@@ -86,7 +99,7 @@ export async function _findMatch(
let chk = item.arch === archFilter && item.platform === platFilter let chk = item.arch === archFilter && item.platform === platFilter
if (chk && item.platform_version) { if (chk && item.platform_version) {
const osVersion = module.exports._getOsVersion() const osVersion = _getOsVersion()
if (osVersion === item.platform_version) { if (osVersion === item.platform_version) {
chk = true chk = true
@@ -130,7 +143,7 @@ export function _getOsVersion(): string {
// DISTRIB_RELEASE=18.04 // DISTRIB_RELEASE=18.04
// DISTRIB_CODENAME=bionic // DISTRIB_CODENAME=bionic
// DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS" // DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS"
const lsbContents = module.exports._readLinuxVersionFile() const lsbContents = _internal.readLinuxVersionFile()
if (lsbContents) { if (lsbContents) {
const lines = lsbContents.split('\n') const lines = lsbContents.split('\n')
for (const line of lines) { for (const line of lines) {
@@ -150,16 +163,7 @@ export function _getOsVersion(): string {
return version return version
} }
// Alias for backwards compatibility
export function _readLinuxVersionFile(): string { export function _readLinuxVersionFile(): string {
const lsbReleaseFile = '/etc/lsb-release' return _internal.readLinuxVersionFile()
const osReleaseFile = '/etc/os-release'
let contents = ''
if (fs.existsSync(lsbReleaseFile)) {
contents = fs.readFileSync(lsbReleaseFile).toString()
} else if (fs.existsSync(osReleaseFile)) {
contents = fs.readFileSync(osReleaseFile).toString()
}
return contents
} }
+3 -4
View File
@@ -2,7 +2,7 @@ import * as core from '@actions/core'
import * as io from '@actions/io' import * as io from '@actions/io'
import * as crypto from 'crypto' import * as crypto from 'crypto'
import * as fs from 'fs' import * as fs from 'fs'
import * as mm from './manifest' import * as mm from './manifest.js'
import * as os from 'os' import * as os from 'os'
import * as path from 'path' import * as path from 'path'
import * as httpm from '@actions/http-client' import * as httpm from '@actions/http-client'
@@ -11,9 +11,8 @@ import * as stream from 'stream'
import * as util from 'util' import * as util from 'util'
import {ok} from 'assert' import {ok} from 'assert'
import {OutgoingHttpHeaders} from 'http' import {OutgoingHttpHeaders} from 'http'
import {exec} from '@actions/exec/lib/exec' import {exec, ExecOptions} from '@actions/exec'
import {ExecOptions} from '@actions/exec/lib/interfaces' import {RetryHelper} from './retry-helper.js'
import {RetryHelper} from './retry-helper'
export class HTTPError extends Error { export class HTTPError extends Error {
constructor(readonly httpStatusCode: number | undefined) { constructor(readonly httpStatusCode: number | undefined) {
+3 -1
View File
@@ -3,7 +3,9 @@
"compilerOptions": { "compilerOptions": {
"baseUrl": "./", "baseUrl": "./",
"outDir": "./lib", "outDir": "./lib",
"rootDir": "./src" "rootDir": "./src",
"module": "node16",
"moduleResolution": "node16"
}, },
"include": [ "include": [
"./src" "./src"