Compare commits

..

1 Commits

Author SHA1 Message Date
Brian DeHamer bb12edf482 bump undici in http-client to 5.28.5
Signed-off-by: Brian DeHamer <bdehamer@github.com>
2025-02-14 07:54:38 -08:00
23 changed files with 127 additions and 136 deletions
-4
View File
@@ -1,9 +1,5 @@
# @actions/artifact Releases
### 2.2.2
- Default concurrency to 5 for uploading artifacts [#1962](https://github.com/actions/toolkit/pull/1962
### 2.2.1
- Add `ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY` and `ACTIONS_ARTIFACT_UPLOAD_TIMEOUT_MS` environment variables [#1928](https://github.com/actions/toolkit/pull/1928)
+14 -16
View File
@@ -56,30 +56,22 @@ describe('uploadChunkTimeoutEnv', () => {
})
describe('uploadConcurrencyEnv', () => {
it('Concurrency default to 5', () => {
it('should return default 32 when cpu num is <= 4', () => {
;(os.cpus as jest.Mock).mockReturnValue(new Array(4))
expect(config.getConcurrency()).toBe(5)
})
it('Concurrency max out at 300 on systems with many CPUs', () => {
;(os.cpus as jest.Mock).mockReturnValue(new Array(32))
process.env.ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY = '301'
expect(config.getConcurrency()).toBe(300)
})
it('Concurrency can be set to 32 when cpu num is <= 4', () => {
;(os.cpus as jest.Mock).mockReturnValue(new Array(4))
process.env.ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY = '32'
expect(config.getConcurrency()).toBe(32)
})
it('Concurrency can be set 16 * num of cpu when cpu num is > 4', () => {
it('should return 16 * num of cpu when cpu num is > 4', () => {
;(os.cpus as jest.Mock).mockReturnValue(new Array(6))
process.env.ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY = '96'
expect(config.getConcurrency()).toBe(96)
})
it('Concurrency can be overridden by env var ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY', () => {
it('should return up to 300 max value', () => {
;(os.cpus as jest.Mock).mockReturnValue(new Array(32))
expect(config.getConcurrency()).toBe(300)
})
it('should return override value when ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY is set', () => {
;(os.cpus as jest.Mock).mockReturnValue(new Array(4))
process.env.ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY = '10'
expect(config.getConcurrency()).toBe(10)
@@ -100,4 +92,10 @@ describe('uploadConcurrencyEnv', () => {
config.getConcurrency()
}).toThrow()
})
it('cannot go over currency cap when override value is greater', () => {
;(os.cpus as jest.Mock).mockReturnValue(new Array(4))
process.env.ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY = '40'
expect(config.getConcurrency()).toBe(32)
})
})
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@actions/artifact",
"version": "2.2.2",
"version": "2.2.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@actions/artifact",
"version": "2.2.2",
"version": "2.2.1",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.10.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@actions/artifact",
"version": "2.2.2",
"version": "2.2.1",
"preview": true,
"description": "Actions artifact lib",
"keywords": [
@@ -70,14 +70,14 @@ export async function listArtifactsPublic(
createdAt: artifact.created_at ? new Date(artifact.created_at) : undefined
})
}
// Move to the next page
currentPageNumber++
// Iterate over any remaining pages
for (
currentPageNumber;
currentPageNumber < numberOfPages;
currentPageNumber++
) {
currentPageNumber++
debug(`Fetching page ${currentPageNumber} of artifact list`)
const {data: listArtifactResponse} =
@@ -45,8 +45,10 @@ export function getGitHubWorkspaceDir(): string {
return ghWorkspaceDir
}
// The maximum value of concurrency is 300.
// This value can be changed with ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY variable.
// Mimics behavior of azcopy: https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azcopy-optimize
// If your machine has fewer than 5 CPUs, then the value of this variable is set to 32.
// Otherwise, the default value is equal to 16 multiplied by the number of CPUs. The maximum value of this variable is 300.
// This value can be lowered with ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY variable.
export function getConcurrency(): number {
const numCPUs = os.cpus().length
let concurrencyCap = 32
@@ -66,20 +68,15 @@ export function getConcurrency(): number {
}
if (concurrency < concurrencyCap) {
info(
`Set concurrency based on the value set in ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY.`
)
return concurrency
}
info(
`ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY is higher than the cap of ${concurrencyCap} based on the number of cpus. Set it to the maximum value allowed.`
`ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY is higher than the cap of ${concurrencyCap} based on the number of cpus. Lowering it to the cap.`
)
return concurrencyCap
}
// default concurrency to 5
return 5
return concurrencyCap
}
export function getUploadChunkTimeout(): number {
-4
View File
@@ -1,9 +1,5 @@
# @actions/attest Releases
### 1.6.0
- Update `buildSLSAProvenancePredicate` to populate `workflow.ref` field from the `ref` claim in the OIDC token [#1969](https://github.com/actions/toolkit/pull/1969)
### 1.5.0
- Bump @actions/core from 1.10.1 to 1.11.1 [#1847](https://github.com/actions/toolkit/pull/1847)
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`provenance functions buildSLSAProvenancePredicate returns a provenance hydrated from an OIDC token 1`] = `
exports[`provenance functions buildSLSAProvenancePredicate handle tags including "@" character 1`] = `
{
"params": {
"buildDefinition": {
@@ -8,7 +8,49 @@ exports[`provenance functions buildSLSAProvenancePredicate returns a provenance
"externalParameters": {
"workflow": {
"path": ".github/workflows/main.yml",
"ref": "refs/heads/main",
"ref": "foo@1.0.0",
"repository": "https://foo.ghe.com/owner/repo",
},
},
"internalParameters": {
"github": {
"event_name": "push",
"repository_id": "repo-id",
"repository_owner_id": "owner-id",
"runner_environment": "github-hosted",
},
},
"resolvedDependencies": [
{
"digest": {
"gitCommit": "babca52ab0c93ae16539e5923cb0d7403b9a093b",
},
"uri": "git+https://foo.ghe.com/owner/repo@refs/heads/main",
},
],
},
"runDetails": {
"builder": {
"id": "https://foo.ghe.com/owner/workflows/.github/workflows/publish.yml@main",
},
"metadata": {
"invocationId": "https://foo.ghe.com/owner/repo/actions/runs/run-id/attempts/run-attempt",
},
},
},
"type": "https://slsa.dev/provenance/v1",
}
`;
exports[`provenance functions buildSLSAProvenancePredicate returns a provenance hydrated from an OIDC token 1`] = `
{
"params": {
"buildDefinition": {
"buildType": "https://actions.github.io/buildtypes/workflow/v1",
"externalParameters": {
"workflow": {
"path": ".github/workflows/main.yml",
"ref": "main",
"repository": "https://foo.ghe.com/owner/repo",
},
},
@@ -75,6 +75,16 @@ describe('provenance functions', () => {
const predicate = await buildSLSAProvenancePredicate()
expect(predicate).toMatchSnapshot()
})
it('handle tags including "@" character', async () => {
nock.cleanAll()
await mockIssuer({
...claims,
workflow_ref: 'owner/repo/.github/workflows/main.yml@foo@1.0.0'
})
const predicate = await buildSLSAProvenancePredicate()
expect(predicate).toMatchSnapshot()
})
})
describe('attestProvenance', () => {
+15 -16
View File
@@ -1,12 +1,12 @@
{
"name": "@actions/attest",
"version": "1.6.0",
"version": "1.5.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@actions/attest",
"version": "1.6.0",
"version": "1.5.0",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.11.1",
@@ -22,7 +22,7 @@
"@sigstore/rekor-types": "^3.0.0",
"@types/jsonwebtoken": "^9.0.6",
"nock": "^13.5.1",
"undici": "^5.28.5"
"undici": "^5.28.4"
}
},
"node_modules/@actions/core": {
@@ -783,9 +783,9 @@
"license": "MIT"
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
@@ -1657,10 +1657,9 @@
}
},
"node_modules/undici": {
"version": "5.28.5",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
"license": "MIT",
"version": "5.28.4",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
"integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
@@ -2455,9 +2454,9 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
@@ -3048,9 +3047,9 @@
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
},
"undici": {
"version": "5.28.5",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
"version": "5.28.4",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
"integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
"requires": {
"@fastify/busboy": "^2.0.0"
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@actions/attest",
"version": "1.6.0",
"version": "1.5.0",
"description": "Actions attestation lib",
"keywords": [
"github",
@@ -39,7 +39,7 @@
"@sigstore/rekor-types": "^3.0.0",
"@types/jsonwebtoken": "^9.0.6",
"nock": "^13.5.1",
"undici": "^5.28.5"
"undici": "^5.28.4"
},
"dependencies": {
"@actions/core": "^1.11.1",
+4 -2
View File
@@ -30,9 +30,11 @@ export const buildSLSAProvenancePredicate = async (
// Split just the path and ref from the workflow string.
// owner/repo/.github/workflows/main.yml@main =>
// .github/workflows/main.yml, main
const [workflowPath] = claims.workflow_ref
const [workflowPath, ...workflowRefChunks] = claims.workflow_ref
.replace(`${claims.repository}/`, '')
.split('@')
// Handle case where tag contains `@` (e.g: when using changesets in a monorepo context),
const workflowRef = workflowRefChunks.join('@')
return {
type: SLSA_PREDICATE_V1_TYPE,
@@ -41,7 +43,7 @@ export const buildSLSAProvenancePredicate = async (
buildType: GITHUB_BUILD_TYPE,
externalParameters: {
workflow: {
ref: claims.ref,
ref: workflowRef,
repository: `${serverURL}/${claims.repository}`,
path: workflowPath
}
-9
View File
@@ -1,14 +1,5 @@
# @actions/cache Releases
### 4.0.2
- Wrap create failures in ReserveCacheError [#1966](https://github.com/actions/toolkit/pull/1966)
### 4.0.1
- Remove runtime dependency on `twirp-ts` [#1947](https://github.com/actions/toolkit/pull/1947)
- Cache miss as debug, not warning annotation [#1954](https://github.com/actions/toolkit/pull/1954)
### 4.0.0
#### Important changes
+2 -1
View File
@@ -115,6 +115,7 @@ test('restore with restore keys and no cache found', async () => {
const paths = ['node_modules']
const key = 'node-test'
const restoreKeys = ['node-']
const logWarningMock = jest.spyOn(core, 'warning')
jest
.spyOn(CacheServiceClientJSON.prototype, 'GetCacheEntryDownloadURL')
@@ -129,7 +130,7 @@ test('restore with restore keys and no cache found', async () => {
const cacheKey = await restoreCache(paths, key, restoreKeys)
expect(cacheKey).toBe(undefined)
expect(logDebugMock).toHaveBeenCalledWith(
expect(logWarningMock).toHaveBeenCalledWith(
`Cache not found for keys: ${[key, ...restoreKeys].join(', ')}`
)
})
+3 -36
View File
@@ -92,14 +92,14 @@ test('save with large cache outputs should fail using', async () => {
expect(getCompressionMock).toHaveBeenCalledTimes(1)
})
test('create cache entry failure on non-ok response', async () => {
test('create cache entry failure', async () => {
const paths = ['node_modules']
const key = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
const infoLogMock = jest.spyOn(core, 'info')
const createCacheEntryMock = jest
.spyOn(CacheServiceClientJSON.prototype, 'CreateCacheEntry')
.mockResolvedValue({ok: false, signedUploadUrl: ''})
.mockReturnValue(Promise.resolve({ok: false, signedUploadUrl: ''}))
const createTarMock = jest.spyOn(tar, 'createTar')
const finalizeCacheEntryMock = jest.spyOn(
@@ -109,7 +109,7 @@ test('create cache entry failure on non-ok response', async () => {
const compression = CompressionMethod.Zstd
const getCompressionMock = jest
.spyOn(cacheUtils, 'getCompressionMethod')
.mockResolvedValueOnce(compression)
.mockReturnValueOnce(Promise.resolve(compression))
const archiveFileSize = 1024
jest
.spyOn(cacheUtils, 'getArchiveFileSizeInBytes')
@@ -133,39 +133,6 @@ test('create cache entry failure on non-ok response', async () => {
expect(saveCacheMock).toHaveBeenCalledTimes(0)
})
test('create cache entry fails on rejected promise', async () => {
const paths = ['node_modules']
const key = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
const infoLogMock = jest.spyOn(core, 'info')
const createCacheEntryMock = jest
.spyOn(CacheServiceClientJSON.prototype, 'CreateCacheEntry')
.mockRejectedValue(new Error('Failed to create cache entry'))
const createTarMock = jest.spyOn(tar, 'createTar')
const compression = CompressionMethod.Zstd
const getCompressionMock = jest
.spyOn(cacheUtils, 'getCompressionMethod')
.mockResolvedValueOnce(compression)
const archiveFileSize = 1024
jest
.spyOn(cacheUtils, 'getArchiveFileSizeInBytes')
.mockReturnValueOnce(archiveFileSize)
const cacheId = await saveCache(paths, key)
expect(cacheId).toBe(-1)
expect(infoLogMock).toHaveBeenCalledWith(
`Failed to save: Unable to reserve cache with key ${key}, another job may be creating this cache.`
)
expect(createCacheEntryMock).toHaveBeenCalledWith({
key,
version: cacheUtils.getCacheVersion(paths, compression)
})
expect(createTarMock).toHaveBeenCalledTimes(1)
expect(getCompressionMock).toHaveBeenCalledTimes(1)
})
test('save cache fails if a signedUploadURL was not passed', async () => {
const paths = 'node_modules'
const key = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@actions/cache",
"version": "4.0.2",
"version": "4.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@actions/cache",
"version": "4.0.2",
"version": "4.0.0",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.11.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@actions/cache",
"version": "4.0.2",
"version": "4.0.0",
"preview": true,
"description": "Actions cache lib",
"keywords": [
+4 -12
View File
@@ -256,7 +256,7 @@ async function restoreCacheV2(
const response = await twirpClient.GetCacheEntryDownloadURL(request)
if (!response.ok) {
core.debug(`Cache not found for keys: ${keys.join(', ')}`)
core.warning(`Cache not found for keys: ${keys.join(', ')}`)
return undefined
}
@@ -525,16 +525,8 @@ async function saveCacheV2(
version
}
let signedUploadUrl
try {
const response = await twirpClient.CreateCacheEntry(request)
if (!response.ok) {
throw new Error('Response was not ok')
}
signedUploadUrl = response.signedUploadUrl
} catch (error) {
core.debug(`Failed to reserve cache: ${error}`)
const response = await twirpClient.CreateCacheEntry(request)
if (!response.ok) {
throw new ReserveCacheError(
`Unable to reserve cache with key ${key}, another job may be creating this cache.`
)
@@ -544,7 +536,7 @@ async function saveCacheV2(
await cacheHttpClient.saveCache(
cacheId,
archivePath,
signedUploadUrl,
response.signedUploadUrl,
options
)
+7 -9
View File
@@ -12,8 +12,7 @@
"@actions/http-client": "^2.2.0",
"@octokit/core": "^5.0.1",
"@octokit/plugin-paginate-rest": "^9.0.0",
"@octokit/plugin-rest-endpoint-methods": "^10.0.0",
"undici": "^5.28.5"
"@octokit/plugin-rest-endpoint-methods": "^10.0.0"
},
"devDependencies": {
"proxy": "^2.1.1"
@@ -347,10 +346,9 @@
}
},
"node_modules/undici": {
"version": "5.28.5",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
"license": "MIT",
"version": "5.25.4",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.25.4.tgz",
"integrity": "sha512-450yJxT29qKMf3aoudzFpIciqpx6Pji3hEWaXqXmanbXF58LTAGCKxcJjxMXWu3iG+Mudgo3ZUfDB6YDFd/dAw==",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
@@ -621,9 +619,9 @@
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
},
"undici": {
"version": "5.28.5",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
"version": "5.25.4",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.25.4.tgz",
"integrity": "sha512-450yJxT29qKMf3aoudzFpIciqpx6Pji3hEWaXqXmanbXF58LTAGCKxcJjxMXWu3iG+Mudgo3ZUfDB6YDFd/dAw==",
"requires": {
"@fastify/busboy": "^2.0.0"
}
+2 -3
View File
@@ -41,10 +41,9 @@
"@actions/http-client": "^2.2.0",
"@octokit/core": "^5.0.1",
"@octokit/plugin-paginate-rest": "^9.0.0",
"@octokit/plugin-rest-endpoint-methods": "^10.0.0",
"undici": "^5.28.5"
"@octokit/plugin-rest-endpoint-methods": "^10.0.0"
},
"devDependencies": {
"proxy": "^2.1.1"
}
}
}
+3
View File
@@ -1,5 +1,8 @@
## Releases
## 2.2.4
- Bump `undici` to version 5.28.5 [#1956](https://github.com/actions/toolkit/pull/1956)
## 2.2.3
- Fixed an issue where proxy username and password were not handled correctly [#1799](https://github.com/actions/toolkit/pull/1799)
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@actions/http-client",
"version": "2.2.3",
"version": "2.2.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@actions/http-client",
"version": "2.2.3",
"version": "2.2.4",
"license": "MIT",
"dependencies": {
"tunnel": "^0.0.6",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@actions/http-client",
"version": "2.2.3",
"version": "2.2.4",
"description": "Actions Http Client",
"keywords": [
"github",