Compare commits

..
Author SHA1 Message Date
Tatyana Kostromskaya 71bc34b2d5 . 2023-10-04 09:30:46 +00:00
Tatyana Kostromskaya c25ba9aa99 Merge branch 'main' into takost/addfetchmethod 2023-09-28 11:07:01 +00:00
Tatyana Kostromskaya 9f29c14937 . 2023-09-26 11:01:17 +00:00
44 changed files with 1036 additions and 2108 deletions
+40 -40
View File
@@ -185,12 +185,12 @@
} }
}, },
"node_modules/@babel/generator": { "node_modules/@babel/generator": {
"version": "7.23.0", "version": "7.22.10",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz",
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/types": "^7.23.0", "@babel/types": "^7.22.10",
"@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17", "@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1" "jsesc": "^2.5.1"
@@ -225,22 +225,22 @@
} }
}, },
"node_modules/@babel/helper-environment-visitor": { "node_modules/@babel/helper-environment-visitor": {
"version": "7.22.20", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-function-name": { "node_modules/@babel/helper-function-name": {
"version": "7.23.0", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/template": "^7.22.15", "@babel/template": "^7.22.5",
"@babel/types": "^7.23.0" "@babel/types": "^7.22.5"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -332,9 +332,9 @@
} }
}, },
"node_modules/@babel/helper-validator-identifier": { "node_modules/@babel/helper-validator-identifier": {
"version": "7.22.20", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -449,9 +449,9 @@
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.23.0", "version": "7.22.13",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.13.tgz",
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "integrity": "sha512-3l6+4YOvc9wx7VlCSw4yQfcBo01ECA8TicQfbnCPuCEpRQrf+gTUyGdxNw+pyTUyywp6JRD1w0YQs9TpBXYlkw==",
"dev": true, "dev": true,
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@@ -650,33 +650,33 @@
} }
}, },
"node_modules/@babel/template": { "node_modules/@babel/template": {
"version": "7.22.15", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz",
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.22.13", "@babel/code-frame": "^7.22.5",
"@babel/parser": "^7.22.15", "@babel/parser": "^7.22.5",
"@babel/types": "^7.22.15" "@babel/types": "^7.22.5"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/traverse": { "node_modules/@babel/traverse": {
"version": "7.23.2", "version": "7.22.11",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.11.tgz",
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "integrity": "sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.22.13", "@babel/code-frame": "^7.22.10",
"@babel/generator": "^7.23.0", "@babel/generator": "^7.22.10",
"@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-environment-visitor": "^7.22.5",
"@babel/helper-function-name": "^7.23.0", "@babel/helper-function-name": "^7.22.5",
"@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6", "@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.23.0", "@babel/parser": "^7.22.11",
"@babel/types": "^7.23.0", "@babel/types": "^7.22.11",
"debug": "^4.1.0", "debug": "^4.1.0",
"globals": "^11.1.0" "globals": "^11.1.0"
}, },
@@ -694,13 +694,13 @@
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.23.0", "version": "7.22.11",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz",
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.22.5", "@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.20", "@babel/helper-validator-identifier": "^7.22.5",
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
}, },
"engines": { "engines": {
@@ -3262,9 +3262,9 @@
} }
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.6.2", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
"integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.0", "follow-redirects": "^1.15.0",
@@ -2,14 +2,18 @@ import * as http from 'http'
import * as net from 'net' import * as net from 'net'
import {HttpClient} from '@actions/http-client' import {HttpClient} from '@actions/http-client'
import * as config from '../src/internal/shared/config' import * as config from '../src/internal/shared/config'
import {internalArtifactTwirpClient} from '../src/internal/shared/artifact-twirp-client' import {createArtifactTwirpClient} from '../src/internal/shared/artifact-twirp-client'
import {noopLogs} from './common' import * as core from '@actions/core'
jest.mock('@actions/http-client') jest.mock('@actions/http-client')
describe('artifact-http-client', () => { describe('artifact-http-client', () => {
beforeAll(() => { beforeAll(() => {
noopLogs() // mock all output so that there is less noise when running tests
jest.spyOn(console, 'log').mockImplementation(() => {})
jest.spyOn(core, 'debug').mockImplementation(() => {})
jest.spyOn(core, 'info').mockImplementation(() => {})
jest.spyOn(core, 'warning').mockImplementation(() => {})
jest jest
.spyOn(config, 'getResultsServiceUrl') .spyOn(config, 'getResultsServiceUrl')
.mockReturnValue('http://localhost:8080') .mockReturnValue('http://localhost:8080')
@@ -21,7 +25,7 @@ describe('artifact-http-client', () => {
}) })
it('should successfully create a client', () => { it('should successfully create a client', () => {
const client = internalArtifactTwirpClient() const client = createArtifactTwirpClient('upload')
expect(client).toBeDefined() expect(client).toBeDefined()
}) })
@@ -46,7 +50,7 @@ describe('artifact-http-client', () => {
} }
}) })
const client = internalArtifactTwirpClient() const client = createArtifactTwirpClient('upload')
const artifact = await client.CreateArtifact({ const artifact = await client.CreateArtifact({
workflowRunBackendId: '1234', workflowRunBackendId: '1234',
workflowJobRunBackendId: '5678', workflowJobRunBackendId: '5678',
@@ -94,11 +98,12 @@ describe('artifact-http-client', () => {
} }
}) })
const client = internalArtifactTwirpClient({ const client = createArtifactTwirpClient(
maxAttempts: 5, 'upload',
retryIntervalMs: 1, 5, // retry 5 times
retryMultiplier: 1.5 1, // wait 1 ms
}) 1.5 // backoff factor
)
const artifact = await client.CreateArtifact({ const artifact = await client.CreateArtifact({
workflowRunBackendId: '1234', workflowRunBackendId: '1234',
workflowJobRunBackendId: '5678', workflowJobRunBackendId: '5678',
@@ -133,11 +138,12 @@ describe('artifact-http-client', () => {
post: mockPost post: mockPost
} }
}) })
const client = internalArtifactTwirpClient({ const client = createArtifactTwirpClient(
maxAttempts: 5, 'upload',
retryIntervalMs: 1, 5, // retry 5 times
retryMultiplier: 1.5 1, // wait 1 ms
}) 1.5 // backoff factor
)
await expect(async () => { await expect(async () => {
await client.CreateArtifact({ await client.CreateArtifact({
workflowRunBackendId: '1234', workflowRunBackendId: '1234',
@@ -172,11 +178,12 @@ describe('artifact-http-client', () => {
post: mockPost post: mockPost
} }
}) })
const client = internalArtifactTwirpClient({ const client = createArtifactTwirpClient(
maxAttempts: 5, 'upload',
retryIntervalMs: 1, 5, // retry 5 times
retryMultiplier: 1.5 1, // wait 1 ms
}) 1.5 // backoff factor
)
await expect(async () => { await expect(async () => {
await client.CreateArtifact({ await client.CreateArtifact({
workflowRunBackendId: '1234', workflowRunBackendId: '1234',
-9
View File
@@ -1,9 +0,0 @@
import * as core from '@actions/core'
// noopLogs mocks the console.log and core.* functions to prevent output in the console while testing
export const noopLogs = (): void => {
jest.spyOn(console, 'log').mockImplementation(() => {})
jest.spyOn(core, 'debug').mockImplementation(() => {})
jest.spyOn(core, 'info').mockImplementation(() => {})
jest.spyOn(core, 'warning').mockImplementation(() => {})
}
@@ -2,20 +2,14 @@ import fs from 'fs'
import * as http from 'http' import * as http from 'http'
import * as net from 'net' import * as net from 'net'
import * as path from 'path' import * as path from 'path'
import * as core from '@actions/core'
import * as github from '@actions/github' import * as github from '@actions/github'
import {HttpClient} from '@actions/http-client' import {HttpClient} from '@actions/http-client'
import type {RestEndpointMethods} from '@octokit/plugin-rest-endpoint-methods/dist-types/generated/method-types' import type {RestEndpointMethods} from '@octokit/plugin-rest-endpoint-methods/dist-types/generated/method-types'
import archiver from 'archiver' import archiver from 'archiver'
import { import {downloadArtifact} from '../src/internal/download/download-artifact'
downloadArtifactInternal,
downloadArtifactPublic
} from '../src/internal/download/download-artifact'
import {getUserAgentString} from '../src/internal/shared/user-agent' import {getUserAgentString} from '../src/internal/shared/user-agent'
import {noopLogs} from './common'
import * as config from '../src/internal/shared/config'
import {ArtifactServiceClientJSON} from '../src/generated'
import * as util from '../src/internal/shared/util'
type MockedDownloadArtifact = jest.MockedFunction< type MockedDownloadArtifact = jest.MockedFunction<
RestEndpointMethods['actions']['downloadArtifact'] RestEndpointMethods['actions']['downloadArtifact']
@@ -38,16 +32,10 @@ const fixtures = {
] ]
}, },
artifactID: 1234, artifactID: 1234,
artifactName: 'my-artifact',
artifactSize: 123456,
repositoryOwner: 'actions', repositoryOwner: 'actions',
repositoryName: 'toolkit', repositoryName: 'toolkit',
token: 'ghp_1234567890', token: 'ghp_1234567890',
blobStorageUrl: 'https://blob-storage.local?signed=true', blobStorageUrl: 'https://blob-storage.local?signed=true'
backendIds: {
workflowRunBackendId: 'c4d7c21f-ba3f-4ddc-a8c8-6f2f626f8422',
workflowJobRunBackendId: '760803a1-f890-4d25-9a6e-a3fc01a0c7cf'
}
} }
jest.mock('@actions/github', () => ({ jest.mock('@actions/github', () => ({
@@ -86,46 +74,27 @@ const expectExtractedArchive = async (dir: string): Promise<void> => {
} }
} }
const setup = async (): Promise<void> => { describe('download-artifact', () => {
noopLogs() beforeEach(async () => {
jest.spyOn(core, 'debug').mockImplementation(() => {})
jest.spyOn(core, 'info').mockImplementation(() => {})
jest.spyOn(core, 'warning').mockImplementation(() => {})
await fs.promises.mkdir(testDir, {recursive: true}) await fs.promises.mkdir(testDir, {recursive: true})
await createTestArchive() await createTestArchive()
process.env['GITHUB_WORKSPACE'] = fixtures.workspaceDir process.env['GITHUB_WORKSPACE'] = fixtures.workspaceDir
} })
const cleanup = async (): Promise<void> => { afterEach(async () => {
jest.restoreAllMocks() jest.restoreAllMocks()
await fs.promises.rm(testDir, {recursive: true}) await fs.promises.rm(testDir, {recursive: true})
delete process.env['GITHUB_WORKSPACE'] delete process.env['GITHUB_WORKSPACE']
}
const mockGetArtifactSuccess = jest.fn(() => {
const message = new http.IncomingMessage(new net.Socket())
message.statusCode = 200
message.push(fs.readFileSync(fixtures.exampleArtifact.path))
return {
message
}
}) })
const mockGetArtifactFailure = jest.fn(() => {
const message = new http.IncomingMessage(new net.Socket())
message.statusCode = 500
message.push('Internal Server Error')
return {
message
}
})
describe('download-artifact', () => {
describe('public', () => {
beforeEach(setup)
afterEach(cleanup)
it('should successfully download an artifact to $GITHUB_WORKSPACE', async () => { it('should successfully download an artifact to $GITHUB_WORKSPACE', async () => {
const downloadArtifactMock = github.getOctokit(fixtures.token).rest const downloadArtifactMock = github.getOctokit(fixtures.token).rest.actions
.actions.downloadArtifact as MockedDownloadArtifact .downloadArtifact as MockedDownloadArtifact
downloadArtifactMock.mockResolvedValueOnce({ downloadArtifactMock.mockResolvedValueOnce({
headers: { headers: {
location: fixtures.blobStorageUrl location: fixtures.blobStorageUrl
@@ -135,15 +104,21 @@ describe('download-artifact', () => {
data: Buffer.from('') data: Buffer.from('')
}) })
const mockHttpClient = (HttpClient as jest.Mock).mockImplementation( const getMock = jest.fn(() => {
() => { const message = new http.IncomingMessage(new net.Socket())
message.statusCode = 200
message.push(fs.readFileSync(fixtures.exampleArtifact.path))
return { return {
get: mockGetArtifactSuccess message
} }
})
const httpClientMock = (HttpClient as jest.Mock).mockImplementation(() => {
return {
get: getMock
} }
) })
const response = await downloadArtifactPublic( const response = await downloadArtifact(
fixtures.artifactID, fixtures.artifactID,
fixtures.repositoryOwner, fixtures.repositoryOwner,
fixtures.repositoryName, fixtures.repositoryName,
@@ -159,11 +134,11 @@ describe('download-artifact', () => {
redirect: 'manual' redirect: 'manual'
} }
}) })
expect(mockHttpClient).toHaveBeenCalledWith(getUserAgentString()) expect(httpClientMock).toHaveBeenCalledWith(getUserAgentString())
expect(mockGetArtifactSuccess).toHaveBeenCalledWith( expect(getMock).toHaveBeenCalledWith(fixtures.blobStorageUrl)
fixtures.blobStorageUrl
)
expectExtractedArchive(fixtures.workspaceDir) expectExtractedArchive(fixtures.workspaceDir)
expect(response.success).toBe(true) expect(response.success).toBe(true)
expect(response.downloadPath).toBe(fixtures.workspaceDir) expect(response.downloadPath).toBe(fixtures.workspaceDir)
}) })
@@ -171,8 +146,8 @@ describe('download-artifact', () => {
it('should successfully download an artifact to user defined path', async () => { it('should successfully download an artifact to user defined path', async () => {
const customPath = path.join(testDir, 'custom') const customPath = path.join(testDir, 'custom')
const downloadArtifactMock = github.getOctokit(fixtures.token).rest const downloadArtifactMock = github.getOctokit(fixtures.token).rest.actions
.actions.downloadArtifact as MockedDownloadArtifact .downloadArtifact as MockedDownloadArtifact
downloadArtifactMock.mockResolvedValueOnce({ downloadArtifactMock.mockResolvedValueOnce({
headers: { headers: {
location: fixtures.blobStorageUrl location: fixtures.blobStorageUrl
@@ -182,15 +157,21 @@ describe('download-artifact', () => {
data: Buffer.from('') data: Buffer.from('')
}) })
const mockHttpClient = (HttpClient as jest.Mock).mockImplementation( const getMock = jest.fn(() => {
() => { const message = new http.IncomingMessage(new net.Socket())
message.statusCode = 200
message.push(fs.readFileSync(fixtures.exampleArtifact.path))
return { return {
get: mockGetArtifactSuccess message
} }
})
const httpClientMock = (HttpClient as jest.Mock).mockImplementation(() => {
return {
get: getMock
} }
) })
const response = await downloadArtifactPublic( const response = await downloadArtifact(
fixtures.artifactID, fixtures.artifactID,
fixtures.repositoryOwner, fixtures.repositoryOwner,
fixtures.repositoryName, fixtures.repositoryName,
@@ -209,18 +190,18 @@ describe('download-artifact', () => {
redirect: 'manual' redirect: 'manual'
} }
}) })
expect(mockHttpClient).toHaveBeenCalledWith(getUserAgentString()) expect(httpClientMock).toHaveBeenCalledWith(getUserAgentString())
expect(mockGetArtifactSuccess).toHaveBeenCalledWith( expect(getMock).toHaveBeenCalledWith(fixtures.blobStorageUrl)
fixtures.blobStorageUrl
)
expectExtractedArchive(customPath) expectExtractedArchive(customPath)
expect(response.success).toBe(true) expect(response.success).toBe(true)
expect(response.downloadPath).toBe(customPath) expect(response.downloadPath).toBe(customPath)
}) })
it('should fail if download artifact API does not respond with location', async () => { it('should fail if download artifact API does not respond with location', async () => {
const downloadArtifactMock = github.getOctokit(fixtures.token).rest const downloadArtifactMock = github.getOctokit(fixtures.token).rest.actions
.actions.downloadArtifact as MockedDownloadArtifact .downloadArtifact as MockedDownloadArtifact
downloadArtifactMock.mockResolvedValueOnce({ downloadArtifactMock.mockResolvedValueOnce({
headers: {}, headers: {},
status: 302, status: 302,
@@ -229,7 +210,7 @@ describe('download-artifact', () => {
}) })
await expect( await expect(
downloadArtifactPublic( downloadArtifact(
fixtures.artifactID, fixtures.artifactID,
fixtures.repositoryOwner, fixtures.repositoryOwner,
fixtures.repositoryName, fixtures.repositoryName,
@@ -249,8 +230,8 @@ describe('download-artifact', () => {
}) })
it('should fail if blob storage response is non-200', async () => { it('should fail if blob storage response is non-200', async () => {
const downloadArtifactMock = github.getOctokit(fixtures.token).rest const downloadArtifactMock = github.getOctokit(fixtures.token).rest.actions
.actions.downloadArtifact as MockedDownloadArtifact .downloadArtifact as MockedDownloadArtifact
downloadArtifactMock.mockResolvedValueOnce({ downloadArtifactMock.mockResolvedValueOnce({
headers: { headers: {
location: fixtures.blobStorageUrl location: fixtures.blobStorageUrl
@@ -260,16 +241,22 @@ describe('download-artifact', () => {
data: Buffer.from('') data: Buffer.from('')
}) })
const mockHttpClient = (HttpClient as jest.Mock).mockImplementation( const getMock = jest.fn(() => {
() => { const message = new http.IncomingMessage(new net.Socket())
message.statusCode = 500
message.push('Internal Server Error')
return { return {
get: mockGetArtifactFailure message
} }
})
const httpClientMock = (HttpClient as jest.Mock).mockImplementation(() => {
return {
get: getMock
} }
) })
await expect( await expect(
downloadArtifactPublic( downloadArtifact(
fixtures.artifactID, fixtures.artifactID,
fixtures.repositoryOwner, fixtures.repositoryOwner,
fixtures.repositoryName, fixtures.repositoryName,
@@ -286,185 +273,7 @@ describe('download-artifact', () => {
redirect: 'manual' redirect: 'manual'
} }
}) })
expect(mockHttpClient).toHaveBeenCalledWith(getUserAgentString()) expect(httpClientMock).toHaveBeenCalledWith(getUserAgentString())
expect(mockGetArtifactFailure).toHaveBeenCalledWith( expect(getMock).toHaveBeenCalledWith(fixtures.blobStorageUrl)
fixtures.blobStorageUrl
)
})
})
describe('internal', () => {
beforeEach(async () => {
await setup()
jest.spyOn(config, 'getRuntimeToken').mockReturnValue('test-token')
jest
.spyOn(util, 'getBackendIdsFromToken')
.mockReturnValue(fixtures.backendIds)
jest
.spyOn(config, 'getResultsServiceUrl')
.mockReturnValue('https://results.local')
})
afterEach(async () => {
await cleanup()
})
it('should successfully download an artifact to $GITHUB_WORKSPACE', async () => {
const mockListArtifacts = jest
.spyOn(ArtifactServiceClientJSON.prototype, 'ListArtifacts')
.mockResolvedValue({
artifacts: [
{
...fixtures.backendIds,
databaseId: fixtures.artifactID.toString(),
name: fixtures.artifactName,
size: fixtures.artifactSize.toString()
}
]
})
const mockGetSignedArtifactURL = jest
.spyOn(ArtifactServiceClientJSON.prototype, 'GetSignedArtifactURL')
.mockReturnValue(
Promise.resolve({
signedUrl: fixtures.blobStorageUrl
})
)
const mockHttpClient = (HttpClient as jest.Mock).mockImplementation(
() => {
return {
get: mockGetArtifactSuccess
}
}
)
const response = await downloadArtifactInternal(fixtures.artifactID)
expectExtractedArchive(fixtures.workspaceDir)
expect(response.success).toBe(true)
expect(response.downloadPath).toBe(fixtures.workspaceDir)
expect(mockHttpClient).toHaveBeenCalledWith(getUserAgentString())
expect(mockListArtifacts).toHaveBeenCalledWith({
idFilter: {
value: fixtures.artifactID.toString()
},
...fixtures.backendIds
})
expect(mockGetSignedArtifactURL).toHaveBeenCalledWith({
...fixtures.backendIds,
name: fixtures.artifactName
})
})
it('should successfully download an artifact to user defined path', async () => {
const customPath = path.join(testDir, 'custom')
const mockListArtifacts = jest
.spyOn(ArtifactServiceClientJSON.prototype, 'ListArtifacts')
.mockResolvedValue({
artifacts: [
{
...fixtures.backendIds,
databaseId: fixtures.artifactID.toString(),
name: fixtures.artifactName,
size: fixtures.artifactSize.toString()
}
]
})
const mockGetSignedArtifactURL = jest
.spyOn(ArtifactServiceClientJSON.prototype, 'GetSignedArtifactURL')
.mockReturnValue(
Promise.resolve({
signedUrl: fixtures.blobStorageUrl
})
)
const mockHttpClient = (HttpClient as jest.Mock).mockImplementation(
() => {
return {
get: mockGetArtifactSuccess
}
}
)
const response = await downloadArtifactInternal(fixtures.artifactID, {
path: customPath
})
expectExtractedArchive(customPath)
expect(response.success).toBe(true)
expect(response.downloadPath).toBe(customPath)
expect(mockHttpClient).toHaveBeenCalledWith(getUserAgentString())
expect(mockListArtifacts).toHaveBeenCalledWith({
idFilter: {
value: fixtures.artifactID.toString()
},
...fixtures.backendIds
})
expect(mockGetSignedArtifactURL).toHaveBeenCalledWith({
...fixtures.backendIds,
name: fixtures.artifactName
})
})
it('should fail if download artifact API does not respond with location', async () => {
jest
.spyOn(ArtifactServiceClientJSON.prototype, 'ListArtifacts')
.mockRejectedValue(new Error('boom'))
await expect(
downloadArtifactInternal(fixtures.artifactID)
).rejects.toBeInstanceOf(Error)
})
it('should fail if blob storage response is non-200', async () => {
const mockListArtifacts = jest
.spyOn(ArtifactServiceClientJSON.prototype, 'ListArtifacts')
.mockResolvedValue({
artifacts: [
{
...fixtures.backendIds,
databaseId: fixtures.artifactID.toString(),
name: fixtures.artifactName,
size: fixtures.artifactSize.toString()
}
]
})
const mockGetSignedArtifactURL = jest
.spyOn(ArtifactServiceClientJSON.prototype, 'GetSignedArtifactURL')
.mockReturnValue(
Promise.resolve({
signedUrl: fixtures.blobStorageUrl
})
)
const mockHttpClient = (HttpClient as jest.Mock).mockImplementation(
() => {
return {
get: mockGetArtifactFailure
}
}
)
await expect(
downloadArtifactInternal(fixtures.artifactID)
).rejects.toBeInstanceOf(Error)
expect(mockHttpClient).toHaveBeenCalledWith(getUserAgentString())
expect(mockListArtifacts).toHaveBeenCalledWith({
idFilter: {
value: fixtures.artifactID.toString()
},
...fixtures.backendIds
})
expect(mockGetSignedArtifactURL).toHaveBeenCalledWith({
...fixtures.backendIds,
name: fixtures.artifactName
})
})
}) })
}) })
@@ -3,11 +3,15 @@ import {
validateFilePath validateFilePath
} from '../src/internal/upload/path-and-artifact-name-validation' } from '../src/internal/upload/path-and-artifact-name-validation'
import {noopLogs} from './common' import * as core from '@actions/core'
describe('Path and artifact name validation', () => { describe('Path and artifact name validation', () => {
beforeAll(() => { beforeAll(() => {
noopLogs() // mock all output so that there is less noise when running tests
jest.spyOn(console, 'log').mockImplementation(() => {})
jest.spyOn(core, 'debug').mockImplementation(() => {})
jest.spyOn(core, 'info').mockImplementation(() => {})
jest.spyOn(core, 'warning').mockImplementation(() => {})
}) })
it('Check Artifact Name for any invalid characters', () => { it('Check Artifact Name for any invalid characters', () => {
@@ -1,3 +1,4 @@
import * as core from '@actions/core'
import * as uploadZipSpecification from '../src/internal/upload/upload-zip-specification' import * as uploadZipSpecification from '../src/internal/upload/upload-zip-specification'
import * as zip from '../src/internal/upload/zip' import * as zip from '../src/internal/upload/zip'
import * as util from '../src/internal/shared/util' import * as util from '../src/internal/shared/util'
@@ -6,11 +7,14 @@ import * as config from '../src/internal/shared/config'
import {Timestamp, ArtifactServiceClientJSON} from '../src/generated' import {Timestamp, ArtifactServiceClientJSON} from '../src/generated'
import * as blobUpload from '../src/internal/upload/blob-upload' import * as blobUpload from '../src/internal/upload/blob-upload'
import {uploadArtifact} from '../src/internal/upload/upload-artifact' import {uploadArtifact} from '../src/internal/upload/upload-artifact'
import {noopLogs} from './common'
describe('upload-artifact', () => { describe('upload-artifact', () => {
beforeEach(() => { beforeEach(() => {
noopLogs() // mock all output so that there is less noise when running tests
jest.spyOn(console, 'log').mockImplementation(() => {})
jest.spyOn(core, 'debug').mockImplementation(() => {})
jest.spyOn(core, 'info').mockImplementation(() => {})
jest.spyOn(core, 'warning').mockImplementation(() => {})
}) })
afterEach(() => { afterEach(() => {
@@ -61,7 +65,7 @@ describe('upload-artifact', () => {
Promise.resolve({ Promise.resolve({
isSuccess: true, isSuccess: true,
uploadSize: 1234, uploadSize: 1234,
sha256Hash: 'test-sha256-hash' md5Hash: 'test-md5-hash'
}) })
) )
jest jest
@@ -127,7 +131,7 @@ describe('upload-artifact', () => {
expect(uploadResp).resolves.toEqual({success: false}) expect(uploadResp).resolves.toEqual({success: false})
}) })
it('should reject if no backend IDs are found', () => { it('should return false if no backend IDs are found', () => {
jest jest
.spyOn(uploadZipSpecification, 'validateRootDirectory') .spyOn(uploadZipSpecification, 'validateRootDirectory')
.mockReturnValue() .mockReturnValue()
@@ -151,6 +155,9 @@ describe('upload-artifact', () => {
jest jest
.spyOn(zip, 'createZipUploadStream') .spyOn(zip, 'createZipUploadStream')
.mockReturnValue(Promise.resolve(new zip.ZipUploadStream(1))) .mockReturnValue(Promise.resolve(new zip.ZipUploadStream(1)))
jest
.spyOn(util, 'getBackendIdsFromToken')
.mockReturnValue({workflowRunBackendId: '', workflowJobRunBackendId: ''})
const uploadResp = uploadArtifact( const uploadResp = uploadArtifact(
'test-artifact', 'test-artifact',
@@ -162,7 +169,7 @@ describe('upload-artifact', () => {
'/home/user/files/plz-upload' '/home/user/files/plz-upload'
) )
expect(uploadResp).rejects.toThrow() expect(uploadResp).resolves.toEqual({success: false})
}) })
it('should return false if the creation request fails', () => { it('should return false if the creation request fails', () => {
@@ -327,7 +334,7 @@ describe('upload-artifact', () => {
Promise.resolve({ Promise.resolve({
isSuccess: true, isSuccess: true,
uploadSize: 1234, uploadSize: 1234,
sha256Hash: 'test-sha256-hash' md5Hash: 'test-md5-hash'
}) })
) )
jest jest
@@ -1,11 +1,11 @@
import * as io from '../../io/src/io' import * as io from '../../io/src/io'
import * as path from 'path' import * as path from 'path'
import {promises as fs} from 'fs' import {promises as fs} from 'fs'
import * as core from '@actions/core'
import { import {
getUploadZipSpecification, getUploadZipSpecification,
validateRootDirectory validateRootDirectory
} from '../src/internal/upload/upload-zip-specification' } from '../src/internal/upload/upload-zip-specification'
import {noopLogs} from './common'
const root = path.join(__dirname, '_temp', 'upload-specification') const root = path.join(__dirname, '_temp', 'upload-specification')
const goodItem1Path = path.join( const goodItem1Path = path.join(
@@ -51,7 +51,11 @@ const artifactFilesToUpload = [
describe('Search', () => { describe('Search', () => {
beforeAll(async () => { beforeAll(async () => {
noopLogs() // mock all output so that there is less noise when running tests
jest.spyOn(console, 'log').mockImplementation(() => {})
jest.spyOn(core, 'debug').mockImplementation(() => {})
jest.spyOn(core, 'info').mockImplementation(() => {})
jest.spyOn(core, 'warning').mockImplementation(() => {})
// clear temp directory // clear temp directory
await io.rmRF(root) await io.rmRF(root)
+5 -4
View File
@@ -1,12 +1,13 @@
import * as config from '../src/internal/shared/config' import * as config from '../src/internal/shared/config'
import * as util from '../src/internal/shared/util' import * as util from '../src/internal/shared/util'
export const testRuntimeToken =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2NwIjoiQWN0aW9ucy5FeGFtcGxlIEFjdGlvbnMuQW5vdGhlckV4YW1wbGU6dGVzdCBBY3Rpb25zLlJlc3VsdHM6Y2U3ZjU0YzctNjFjNy00YWFlLTg4N2YtMzBkYTQ3NWY1ZjFhOmNhMzk1MDg1LTA0MGEtNTI2Yi0yY2U4LWJkYzg1ZjY5Mjc3NCIsImlhdCI6MTUxNjIzOTAyMn0.XYnI_wHPBlUi1mqYveJnnkJhp4dlFjqxzRmISPsqfw8'
describe('get-backend-ids-from-token', () => { describe('get-backend-ids-from-token', () => {
it('should return backend ids when the token is valid', () => { it('should return backend ids when the token is valid', () => {
jest.spyOn(config, 'getRuntimeToken').mockReturnValue(testRuntimeToken) jest
.spyOn(config, 'getRuntimeToken')
.mockReturnValue(
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2NwIjoiQWN0aW9ucy5FeGFtcGxlIEFjdGlvbnMuQW5vdGhlckV4YW1wbGU6dGVzdCBBY3Rpb25zLlJlc3VsdHM6Y2U3ZjU0YzctNjFjNy00YWFlLTg4N2YtMzBkYTQ3NWY1ZjFhOmNhMzk1MDg1LTA0MGEtNTI2Yi0yY2U4LWJkYzg1ZjY5Mjc3NCIsImlhdCI6MTUxNjIzOTAyMn0.XYnI_wHPBlUi1mqYveJnnkJhp4dlFjqxzRmISPsqfw8'
)
const backendIds = util.getBackendIdsFromToken() const backendIds = util.getBackendIdsFromToken()
expect(backendIds.workflowRunBackendId).toBe( expect(backendIds.workflowRunBackendId).toBe(
+1 -1
View File
@@ -30,7 +30,7 @@
}, },
"scripts": { "scripts": {
"audit-moderate": "npm install && npm audit --json --audit-level=moderate > audit.json", "audit-moderate": "npm install && npm audit --json --audit-level=moderate > audit.json",
"test": "cd ../../ && npm run test ./packages/artifact", "test": "echo \"Error: run tests from root\" && exit 1",
"bootstrap": "cd ../../ && npm run bootstrap", "bootstrap": "cd ../../ && npm run bootstrap",
"tsc-run": "tsc", "tsc-run": "tsc",
"tsc": "npm run bootstrap && npm run tsc-run" "tsc": "npm run bootstrap && npm run tsc-run"
@@ -12,7 +12,6 @@ import type { PartialMessage } from "@protobuf-ts/runtime";
import { reflectionMergePartial } from "@protobuf-ts/runtime"; import { reflectionMergePartial } from "@protobuf-ts/runtime";
import { MESSAGE_TYPE } from "@protobuf-ts/runtime"; import { MESSAGE_TYPE } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime"; import { MessageType } from "@protobuf-ts/runtime";
import { Int64Value } from "../../../google/protobuf/wrappers";
import { StringValue } from "../../../google/protobuf/wrappers"; import { StringValue } from "../../../google/protobuf/wrappers";
import { Timestamp } from "../../../google/protobuf/timestamp"; import { Timestamp } from "../../../google/protobuf/timestamp";
/** /**
@@ -91,105 +90,6 @@ export interface FinalizeArtifactResponse {
*/ */
artifactId: string; artifactId: string;
} }
/**
* @generated from protobuf message github.actions.results.api.v1.ListArtifactsRequest
*/
export interface ListArtifactsRequest {
/**
* The backend plan ID
*
* @generated from protobuf field: string workflow_run_backend_id = 1;
*/
workflowRunBackendId: string;
/**
* The backend job ID
*
* @generated from protobuf field: string workflow_job_run_backend_id = 2;
*/
workflowJobRunBackendId: string;
/**
* Name of the artifact to filter on
*
* @generated from protobuf field: google.protobuf.StringValue name_filter = 3;
*/
nameFilter?: StringValue; // optional
/**
* Monolith Database ID of the artifact to filter on
*
* @generated from protobuf field: google.protobuf.Int64Value id_filter = 4;
*/
idFilter?: Int64Value; // optional
}
/**
* @generated from protobuf message github.actions.results.api.v1.ListArtifactsResponse
*/
export interface ListArtifactsResponse {
/**
* @generated from protobuf field: repeated github.actions.results.api.v1.ListArtifactsResponse.MonolithArtifact artifacts = 1;
*/
artifacts: ListArtifactsResponse_MonolithArtifact[];
}
/**
* @generated from protobuf message github.actions.results.api.v1.ListArtifactsResponse.MonolithArtifact
*/
export interface ListArtifactsResponse_MonolithArtifact {
/**
* The backend plan ID
*
* @generated from protobuf field: string workflow_run_backend_id = 1;
*/
workflowRunBackendId: string;
/**
* The backend job ID
*
* @generated from protobuf field: string workflow_job_run_backend_id = 2;
*/
workflowJobRunBackendId: string;
/**
* Monolith database ID of the artifact
*
* @generated from protobuf field: int64 database_id = 3;
*/
databaseId: string;
/**
* Name of the artifact
*
* @generated from protobuf field: string name = 4;
*/
name: string;
/**
* Size of the artifact in bytes
*
* @generated from protobuf field: int64 size = 5;
*/
size: string;
}
/**
* @generated from protobuf message github.actions.results.api.v1.GetSignedArtifactURLRequest
*/
export interface GetSignedArtifactURLRequest {
/**
* @generated from protobuf field: string workflow_run_backend_id = 1;
*/
workflowRunBackendId: string;
/**
* @generated from protobuf field: string workflow_job_run_backend_id = 2;
*/
workflowJobRunBackendId: string;
/**
* @generated from protobuf field: string name = 3;
*/
name: string;
}
/**
* @generated from protobuf message github.actions.results.api.v1.GetSignedArtifactURLResponse
*/
export interface GetSignedArtifactURLResponse {
/**
* @generated from protobuf field: string signed_url = 1;
*/
signedUrl: string;
}
// @generated message type with reflection information, may provide speed optimized methods // @generated message type with reflection information, may provide speed optimized methods
class CreateArtifactRequest$Type extends MessageType<CreateArtifactRequest> { class CreateArtifactRequest$Type extends MessageType<CreateArtifactRequest> {
constructor() { constructor() {
@@ -448,310 +348,10 @@ class FinalizeArtifactResponse$Type extends MessageType<FinalizeArtifactResponse
* @generated MessageType for protobuf message github.actions.results.api.v1.FinalizeArtifactResponse * @generated MessageType for protobuf message github.actions.results.api.v1.FinalizeArtifactResponse
*/ */
export const FinalizeArtifactResponse = new FinalizeArtifactResponse$Type(); export const FinalizeArtifactResponse = new FinalizeArtifactResponse$Type();
// @generated message type with reflection information, may provide speed optimized methods
class ListArtifactsRequest$Type extends MessageType<ListArtifactsRequest> {
constructor() {
super("github.actions.results.api.v1.ListArtifactsRequest", [
{ no: 1, name: "workflow_run_backend_id", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 2, name: "workflow_job_run_backend_id", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 3, name: "name_filter", kind: "message", T: () => StringValue },
{ no: 4, name: "id_filter", kind: "message", T: () => Int64Value }
]);
}
create(value?: PartialMessage<ListArtifactsRequest>): ListArtifactsRequest {
const message = { workflowRunBackendId: "", workflowJobRunBackendId: "" };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<ListArtifactsRequest>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListArtifactsRequest): ListArtifactsRequest {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string workflow_run_backend_id */ 1:
message.workflowRunBackendId = reader.string();
break;
case /* string workflow_job_run_backend_id */ 2:
message.workflowJobRunBackendId = reader.string();
break;
case /* google.protobuf.StringValue name_filter */ 3:
message.nameFilter = StringValue.internalBinaryRead(reader, reader.uint32(), options, message.nameFilter);
break;
case /* google.protobuf.Int64Value id_filter */ 4:
message.idFilter = Int64Value.internalBinaryRead(reader, reader.uint32(), options, message.idFilter);
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: ListArtifactsRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string workflow_run_backend_id = 1; */
if (message.workflowRunBackendId !== "")
writer.tag(1, WireType.LengthDelimited).string(message.workflowRunBackendId);
/* string workflow_job_run_backend_id = 2; */
if (message.workflowJobRunBackendId !== "")
writer.tag(2, WireType.LengthDelimited).string(message.workflowJobRunBackendId);
/* google.protobuf.StringValue name_filter = 3; */
if (message.nameFilter)
StringValue.internalBinaryWrite(message.nameFilter, writer.tag(3, WireType.LengthDelimited).fork(), options).join();
/* google.protobuf.Int64Value id_filter = 4; */
if (message.idFilter)
Int64Value.internalBinaryWrite(message.idFilter, writer.tag(4, WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message github.actions.results.api.v1.ListArtifactsRequest
*/
export const ListArtifactsRequest = new ListArtifactsRequest$Type();
// @generated message type with reflection information, may provide speed optimized methods
class ListArtifactsResponse$Type extends MessageType<ListArtifactsResponse> {
constructor() {
super("github.actions.results.api.v1.ListArtifactsResponse", [
{ no: 1, name: "artifacts", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ListArtifactsResponse_MonolithArtifact }
]);
}
create(value?: PartialMessage<ListArtifactsResponse>): ListArtifactsResponse {
const message = { artifacts: [] };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<ListArtifactsResponse>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListArtifactsResponse): ListArtifactsResponse {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* repeated github.actions.results.api.v1.ListArtifactsResponse.MonolithArtifact artifacts */ 1:
message.artifacts.push(ListArtifactsResponse_MonolithArtifact.internalBinaryRead(reader, reader.uint32(), options));
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: ListArtifactsResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* repeated github.actions.results.api.v1.ListArtifactsResponse.MonolithArtifact artifacts = 1; */
for (let i = 0; i < message.artifacts.length; i++)
ListArtifactsResponse_MonolithArtifact.internalBinaryWrite(message.artifacts[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message github.actions.results.api.v1.ListArtifactsResponse
*/
export const ListArtifactsResponse = new ListArtifactsResponse$Type();
// @generated message type with reflection information, may provide speed optimized methods
class ListArtifactsResponse_MonolithArtifact$Type extends MessageType<ListArtifactsResponse_MonolithArtifact> {
constructor() {
super("github.actions.results.api.v1.ListArtifactsResponse.MonolithArtifact", [
{ no: 1, name: "workflow_run_backend_id", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 2, name: "workflow_job_run_backend_id", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 3, name: "database_id", kind: "scalar", T: 3 /*ScalarType.INT64*/ },
{ no: 4, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 5, name: "size", kind: "scalar", T: 3 /*ScalarType.INT64*/ }
]);
}
create(value?: PartialMessage<ListArtifactsResponse_MonolithArtifact>): ListArtifactsResponse_MonolithArtifact {
const message = { workflowRunBackendId: "", workflowJobRunBackendId: "", databaseId: "0", name: "", size: "0" };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<ListArtifactsResponse_MonolithArtifact>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListArtifactsResponse_MonolithArtifact): ListArtifactsResponse_MonolithArtifact {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string workflow_run_backend_id */ 1:
message.workflowRunBackendId = reader.string();
break;
case /* string workflow_job_run_backend_id */ 2:
message.workflowJobRunBackendId = reader.string();
break;
case /* int64 database_id */ 3:
message.databaseId = reader.int64().toString();
break;
case /* string name */ 4:
message.name = reader.string();
break;
case /* int64 size */ 5:
message.size = reader.int64().toString();
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: ListArtifactsResponse_MonolithArtifact, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string workflow_run_backend_id = 1; */
if (message.workflowRunBackendId !== "")
writer.tag(1, WireType.LengthDelimited).string(message.workflowRunBackendId);
/* string workflow_job_run_backend_id = 2; */
if (message.workflowJobRunBackendId !== "")
writer.tag(2, WireType.LengthDelimited).string(message.workflowJobRunBackendId);
/* int64 database_id = 3; */
if (message.databaseId !== "0")
writer.tag(3, WireType.Varint).int64(message.databaseId);
/* string name = 4; */
if (message.name !== "")
writer.tag(4, WireType.LengthDelimited).string(message.name);
/* int64 size = 5; */
if (message.size !== "0")
writer.tag(5, WireType.Varint).int64(message.size);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message github.actions.results.api.v1.ListArtifactsResponse.MonolithArtifact
*/
export const ListArtifactsResponse_MonolithArtifact = new ListArtifactsResponse_MonolithArtifact$Type();
// @generated message type with reflection information, may provide speed optimized methods
class GetSignedArtifactURLRequest$Type extends MessageType<GetSignedArtifactURLRequest> {
constructor() {
super("github.actions.results.api.v1.GetSignedArtifactURLRequest", [
{ no: 1, name: "workflow_run_backend_id", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 2, name: "workflow_job_run_backend_id", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 3, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
]);
}
create(value?: PartialMessage<GetSignedArtifactURLRequest>): GetSignedArtifactURLRequest {
const message = { workflowRunBackendId: "", workflowJobRunBackendId: "", name: "" };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<GetSignedArtifactURLRequest>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetSignedArtifactURLRequest): GetSignedArtifactURLRequest {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string workflow_run_backend_id */ 1:
message.workflowRunBackendId = reader.string();
break;
case /* string workflow_job_run_backend_id */ 2:
message.workflowJobRunBackendId = reader.string();
break;
case /* string name */ 3:
message.name = reader.string();
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: GetSignedArtifactURLRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string workflow_run_backend_id = 1; */
if (message.workflowRunBackendId !== "")
writer.tag(1, WireType.LengthDelimited).string(message.workflowRunBackendId);
/* string workflow_job_run_backend_id = 2; */
if (message.workflowJobRunBackendId !== "")
writer.tag(2, WireType.LengthDelimited).string(message.workflowJobRunBackendId);
/* string name = 3; */
if (message.name !== "")
writer.tag(3, WireType.LengthDelimited).string(message.name);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message github.actions.results.api.v1.GetSignedArtifactURLRequest
*/
export const GetSignedArtifactURLRequest = new GetSignedArtifactURLRequest$Type();
// @generated message type with reflection information, may provide speed optimized methods
class GetSignedArtifactURLResponse$Type extends MessageType<GetSignedArtifactURLResponse> {
constructor() {
super("github.actions.results.api.v1.GetSignedArtifactURLResponse", [
{ no: 1, name: "signed_url", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
]);
}
create(value?: PartialMessage<GetSignedArtifactURLResponse>): GetSignedArtifactURLResponse {
const message = { signedUrl: "" };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<GetSignedArtifactURLResponse>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetSignedArtifactURLResponse): GetSignedArtifactURLResponse {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string signed_url */ 1:
message.signedUrl = reader.string();
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: GetSignedArtifactURLResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string signed_url = 1; */
if (message.signedUrl !== "")
writer.tag(1, WireType.LengthDelimited).string(message.signedUrl);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message github.actions.results.api.v1.GetSignedArtifactURLResponse
*/
export const GetSignedArtifactURLResponse = new GetSignedArtifactURLResponse$Type();
/** /**
* @generated ServiceType for protobuf service github.actions.results.api.v1.ArtifactService * @generated ServiceType for protobuf service github.actions.results.api.v1.ArtifactService
*/ */
export const ArtifactService = new ServiceType("github.actions.results.api.v1.ArtifactService", [ export const ArtifactService = new ServiceType("github.actions.results.api.v1.ArtifactService", [
{ name: "CreateArtifact", options: {}, I: CreateArtifactRequest, O: CreateArtifactResponse }, { name: "CreateArtifact", options: {}, I: CreateArtifactRequest, O: CreateArtifactResponse },
{ name: "FinalizeArtifact", options: {}, I: FinalizeArtifactRequest, O: FinalizeArtifactResponse }, { name: "FinalizeArtifact", options: {}, I: FinalizeArtifactRequest, O: FinalizeArtifactResponse }
{ name: "ListArtifacts", options: {}, I: ListArtifactsRequest, O: ListArtifactsResponse },
{ name: "GetSignedArtifactURL", options: {}, I: GetSignedArtifactURLRequest, O: GetSignedArtifactURLResponse }
]); ]);
@@ -6,18 +6,14 @@ import {
TwirpErrorCode, TwirpErrorCode,
Interceptor, Interceptor,
TwirpContentType, TwirpContentType,
chainInterceptors, chainInterceptors
} from "twirp-ts"; } from 'twirp-ts'
import { import {
CreateArtifactRequest, CreateArtifactRequest,
CreateArtifactResponse, CreateArtifactResponse,
FinalizeArtifactRequest, FinalizeArtifactRequest,
FinalizeArtifactResponse, FinalizeArtifactResponse
ListArtifactsRequest, } from './artifact'
ListArtifactsResponse,
GetSignedArtifactURLRequest,
GetSignedArtifactURLResponse,
} from "./artifact";
//==================================// //==================================//
// Client Code // // Client Code //
@@ -27,51 +23,43 @@ interface Rpc {
request( request(
service: string, service: string,
method: string, method: string,
contentType: "application/json" | "application/protobuf", contentType: 'application/json' | 'application/protobuf',
data: object | Uint8Array data: object | Uint8Array
): Promise<object | Uint8Array>; ): Promise<object | Uint8Array>
} }
export interface ArtifactServiceClient { export interface ArtifactServiceClient {
CreateArtifact( CreateArtifact(
request: CreateArtifactRequest request: CreateArtifactRequest
): Promise<CreateArtifactResponse>; ): Promise<CreateArtifactResponse>
FinalizeArtifact( FinalizeArtifact(
request: FinalizeArtifactRequest request: FinalizeArtifactRequest
): Promise<FinalizeArtifactResponse>; ): Promise<FinalizeArtifactResponse>
ListArtifacts(request: ListArtifactsRequest): Promise<ListArtifactsResponse>;
GetSignedArtifactURL(
request: GetSignedArtifactURLRequest
): Promise<GetSignedArtifactURLResponse>;
} }
export class ArtifactServiceClientJSON implements ArtifactServiceClient { export class ArtifactServiceClientJSON implements ArtifactServiceClient {
private readonly rpc: Rpc; private readonly rpc: Rpc
constructor(rpc: Rpc) { constructor(rpc: Rpc) {
this.rpc = rpc; this.rpc = rpc
this.CreateArtifact.bind(this); this.CreateArtifact.bind(this)
this.FinalizeArtifact.bind(this); this.FinalizeArtifact.bind(this)
this.ListArtifacts.bind(this);
this.GetSignedArtifactURL.bind(this);
} }
CreateArtifact( CreateArtifact(
request: CreateArtifactRequest request: CreateArtifactRequest
): Promise<CreateArtifactResponse> { ): Promise<CreateArtifactResponse> {
const data = CreateArtifactRequest.toJson(request, { const data = CreateArtifactRequest.toJson(request, {
useProtoFieldName: true, useProtoFieldName: true,
emitDefaultValues: false, emitDefaultValues: false
});
const promise = this.rpc.request(
"github.actions.results.api.v1.ArtifactService",
"CreateArtifact",
"application/json",
data as object
);
return promise.then((data) =>
CreateArtifactResponse.fromJson(data as any, {
ignoreUnknownFields: true,
}) })
); const promise = this.rpc.request(
'github.actions.results.api.v1.ArtifactService',
'CreateArtifact',
'application/json',
data as object
)
return promise.then(data =>
CreateArtifactResponse.fromJson(data as any, {ignoreUnknownFields: true})
)
} }
FinalizeArtifact( FinalizeArtifact(
@@ -79,123 +67,57 @@ export class ArtifactServiceClientJSON implements ArtifactServiceClient {
): Promise<FinalizeArtifactResponse> { ): Promise<FinalizeArtifactResponse> {
const data = FinalizeArtifactRequest.toJson(request, { const data = FinalizeArtifactRequest.toJson(request, {
useProtoFieldName: true, useProtoFieldName: true,
emitDefaultValues: false, emitDefaultValues: false
}); })
const promise = this.rpc.request( const promise = this.rpc.request(
"github.actions.results.api.v1.ArtifactService", 'github.actions.results.api.v1.ArtifactService',
"FinalizeArtifact", 'FinalizeArtifact',
"application/json", 'application/json',
data as object data as object
); )
return promise.then((data) => return promise.then(data =>
FinalizeArtifactResponse.fromJson(data as any, { FinalizeArtifactResponse.fromJson(data as any, {
ignoreUnknownFields: true, ignoreUnknownFields: true
}) })
); )
}
ListArtifacts(request: ListArtifactsRequest): Promise<ListArtifactsResponse> {
const data = ListArtifactsRequest.toJson(request, {
useProtoFieldName: true,
emitDefaultValues: false,
});
const promise = this.rpc.request(
"github.actions.results.api.v1.ArtifactService",
"ListArtifacts",
"application/json",
data as object
);
return promise.then((data) =>
ListArtifactsResponse.fromJson(data as any, { ignoreUnknownFields: true })
);
}
GetSignedArtifactURL(
request: GetSignedArtifactURLRequest
): Promise<GetSignedArtifactURLResponse> {
const data = GetSignedArtifactURLRequest.toJson(request, {
useProtoFieldName: true,
emitDefaultValues: false,
});
const promise = this.rpc.request(
"github.actions.results.api.v1.ArtifactService",
"GetSignedArtifactURL",
"application/json",
data as object
);
return promise.then((data) =>
GetSignedArtifactURLResponse.fromJson(data as any, {
ignoreUnknownFields: true,
})
);
} }
} }
export class ArtifactServiceClientProtobuf implements ArtifactServiceClient { export class ArtifactServiceClientProtobuf implements ArtifactServiceClient {
private readonly rpc: Rpc; private readonly rpc: Rpc
constructor(rpc: Rpc) { constructor(rpc: Rpc) {
this.rpc = rpc; this.rpc = rpc
this.CreateArtifact.bind(this); this.CreateArtifact.bind(this)
this.FinalizeArtifact.bind(this); this.FinalizeArtifact.bind(this)
this.ListArtifacts.bind(this);
this.GetSignedArtifactURL.bind(this);
} }
CreateArtifact( CreateArtifact(
request: CreateArtifactRequest request: CreateArtifactRequest
): Promise<CreateArtifactResponse> { ): Promise<CreateArtifactResponse> {
const data = CreateArtifactRequest.toBinary(request); const data = CreateArtifactRequest.toBinary(request)
const promise = this.rpc.request( const promise = this.rpc.request(
"github.actions.results.api.v1.ArtifactService", 'github.actions.results.api.v1.ArtifactService',
"CreateArtifact", 'CreateArtifact',
"application/protobuf", 'application/protobuf',
data data
); )
return promise.then((data) => return promise.then(data =>
CreateArtifactResponse.fromBinary(data as Uint8Array) CreateArtifactResponse.fromBinary(data as Uint8Array)
); )
} }
FinalizeArtifact( FinalizeArtifact(
request: FinalizeArtifactRequest request: FinalizeArtifactRequest
): Promise<FinalizeArtifactResponse> { ): Promise<FinalizeArtifactResponse> {
const data = FinalizeArtifactRequest.toBinary(request); const data = FinalizeArtifactRequest.toBinary(request)
const promise = this.rpc.request( const promise = this.rpc.request(
"github.actions.results.api.v1.ArtifactService", 'github.actions.results.api.v1.ArtifactService',
"FinalizeArtifact", 'FinalizeArtifact',
"application/protobuf", 'application/protobuf',
data data
); )
return promise.then((data) => return promise.then(data =>
FinalizeArtifactResponse.fromBinary(data as Uint8Array) FinalizeArtifactResponse.fromBinary(data as Uint8Array)
); )
}
ListArtifacts(request: ListArtifactsRequest): Promise<ListArtifactsResponse> {
const data = ListArtifactsRequest.toBinary(request);
const promise = this.rpc.request(
"github.actions.results.api.v1.ArtifactService",
"ListArtifacts",
"application/protobuf",
data
);
return promise.then((data) =>
ListArtifactsResponse.fromBinary(data as Uint8Array)
);
}
GetSignedArtifactURL(
request: GetSignedArtifactURLRequest
): Promise<GetSignedArtifactURLResponse> {
const data = GetSignedArtifactURLRequest.toBinary(request);
const promise = this.rpc.request(
"github.actions.results.api.v1.ArtifactService",
"GetSignedArtifactURL",
"application/protobuf",
data
);
return promise.then((data) =>
GetSignedArtifactURLResponse.fromBinary(data as Uint8Array)
);
} }
} }
@@ -207,45 +129,33 @@ export interface ArtifactServiceTwirp<T extends TwirpContext = TwirpContext> {
CreateArtifact( CreateArtifact(
ctx: T, ctx: T,
request: CreateArtifactRequest request: CreateArtifactRequest
): Promise<CreateArtifactResponse>; ): Promise<CreateArtifactResponse>
FinalizeArtifact( FinalizeArtifact(
ctx: T, ctx: T,
request: FinalizeArtifactRequest request: FinalizeArtifactRequest
): Promise<FinalizeArtifactResponse>; ): Promise<FinalizeArtifactResponse>
ListArtifacts(
ctx: T,
request: ListArtifactsRequest
): Promise<ListArtifactsResponse>;
GetSignedArtifactURL(
ctx: T,
request: GetSignedArtifactURLRequest
): Promise<GetSignedArtifactURLResponse>;
} }
export enum ArtifactServiceMethod { export enum ArtifactServiceMethod {
CreateArtifact = "CreateArtifact", CreateArtifact = 'CreateArtifact',
FinalizeArtifact = "FinalizeArtifact", FinalizeArtifact = 'FinalizeArtifact'
ListArtifacts = "ListArtifacts",
GetSignedArtifactURL = "GetSignedArtifactURL",
} }
export const ArtifactServiceMethodList = [ export const ArtifactServiceMethodList = [
ArtifactServiceMethod.CreateArtifact, ArtifactServiceMethod.CreateArtifact,
ArtifactServiceMethod.FinalizeArtifact, ArtifactServiceMethod.FinalizeArtifact
ArtifactServiceMethod.ListArtifacts, ]
ArtifactServiceMethod.GetSignedArtifactURL,
];
export function createArtifactServiceServer< export function createArtifactServiceServer<
T extends TwirpContext = TwirpContext T extends TwirpContext = TwirpContext
>(service: ArtifactServiceTwirp<T>) { >(service: ArtifactServiceTwirp<T>) {
return new TwirpServer<ArtifactServiceTwirp, T>({ return new TwirpServer<ArtifactServiceTwirp, T>({
service, service,
packageName: "github.actions.results.api.v1", packageName: 'github.actions.results.api.v1',
serviceName: "ArtifactService", serviceName: 'ArtifactService',
methodList: ArtifactServiceMethodList, methodList: ArtifactServiceMethodList,
matchRoute: matchArtifactServiceRoute, matchRoute: matchArtifactServiceRoute
}); })
} }
function matchArtifactServiceRoute<T extends TwirpContext = TwirpContext>( function matchArtifactServiceRoute<T extends TwirpContext = TwirpContext>(
@@ -253,7 +163,7 @@ function matchArtifactServiceRoute<T extends TwirpContext = TwirpContext>(
events: RouterEvents<T> events: RouterEvents<T>
) { ) {
switch (method) { switch (method) {
case "CreateArtifact": case 'CreateArtifact':
return async ( return async (
ctx: T, ctx: T,
service: ArtifactServiceTwirp, service: ArtifactServiceTwirp,
@@ -264,16 +174,16 @@ function matchArtifactServiceRoute<T extends TwirpContext = TwirpContext>(
CreateArtifactResponse CreateArtifactResponse
>[] >[]
) => { ) => {
ctx = { ...ctx, methodName: "CreateArtifact" }; ctx = {...ctx, methodName: 'CreateArtifact'}
await events.onMatch(ctx); await events.onMatch(ctx)
return handleArtifactServiceCreateArtifactRequest( return handleArtifactServiceCreateArtifactRequest(
ctx, ctx,
service, service,
data, data,
interceptors interceptors
); )
}; }
case "FinalizeArtifact": case 'FinalizeArtifact':
return async ( return async (
ctx: T, ctx: T,
service: ArtifactServiceTwirp, service: ArtifactServiceTwirp,
@@ -284,59 +194,19 @@ function matchArtifactServiceRoute<T extends TwirpContext = TwirpContext>(
FinalizeArtifactResponse FinalizeArtifactResponse
>[] >[]
) => { ) => {
ctx = { ...ctx, methodName: "FinalizeArtifact" }; ctx = {...ctx, methodName: 'FinalizeArtifact'}
await events.onMatch(ctx); await events.onMatch(ctx)
return handleArtifactServiceFinalizeArtifactRequest( return handleArtifactServiceFinalizeArtifactRequest(
ctx, ctx,
service, service,
data, data,
interceptors interceptors
); )
}; }
case "ListArtifacts":
return async (
ctx: T,
service: ArtifactServiceTwirp,
data: Buffer,
interceptors?: Interceptor<
T,
ListArtifactsRequest,
ListArtifactsResponse
>[]
) => {
ctx = { ...ctx, methodName: "ListArtifacts" };
await events.onMatch(ctx);
return handleArtifactServiceListArtifactsRequest(
ctx,
service,
data,
interceptors
);
};
case "GetSignedArtifactURL":
return async (
ctx: T,
service: ArtifactServiceTwirp,
data: Buffer,
interceptors?: Interceptor<
T,
GetSignedArtifactURLRequest,
GetSignedArtifactURLResponse
>[]
) => {
ctx = { ...ctx, methodName: "GetSignedArtifactURL" };
await events.onMatch(ctx);
return handleArtifactServiceGetSignedArtifactURLRequest(
ctx,
service,
data,
interceptors
);
};
default: default:
events.onNotFound(); events.onNotFound()
const msg = `no handler found`; const msg = `no handler found`
throw new TwirpError(TwirpErrorCode.BadRoute, msg); throw new TwirpError(TwirpErrorCode.BadRoute, msg)
} }
} }
@@ -355,17 +225,17 @@ function handleArtifactServiceCreateArtifactRequest<
service, service,
data, data,
interceptors interceptors
); )
case TwirpContentType.Protobuf: case TwirpContentType.Protobuf:
return handleArtifactServiceCreateArtifactProtobuf<T>( return handleArtifactServiceCreateArtifactProtobuf<T>(
ctx, ctx,
service, service,
data, data,
interceptors interceptors
); )
default: default:
const msg = "unexpected Content-Type"; const msg = 'unexpected Content-Type'
throw new TwirpError(TwirpErrorCode.BadRoute, msg); throw new TwirpError(TwirpErrorCode.BadRoute, msg)
} }
} }
@@ -388,79 +258,17 @@ function handleArtifactServiceFinalizeArtifactRequest<
service, service,
data, data,
interceptors interceptors
); )
case TwirpContentType.Protobuf: case TwirpContentType.Protobuf:
return handleArtifactServiceFinalizeArtifactProtobuf<T>( return handleArtifactServiceFinalizeArtifactProtobuf<T>(
ctx, ctx,
service, service,
data, data,
interceptors interceptors
); )
default: default:
const msg = "unexpected Content-Type"; const msg = 'unexpected Content-Type'
throw new TwirpError(TwirpErrorCode.BadRoute, msg); throw new TwirpError(TwirpErrorCode.BadRoute, msg)
}
}
function handleArtifactServiceListArtifactsRequest<
T extends TwirpContext = TwirpContext
>(
ctx: T,
service: ArtifactServiceTwirp,
data: Buffer,
interceptors?: Interceptor<T, ListArtifactsRequest, ListArtifactsResponse>[]
): Promise<string | Uint8Array> {
switch (ctx.contentType) {
case TwirpContentType.JSON:
return handleArtifactServiceListArtifactsJSON<T>(
ctx,
service,
data,
interceptors
);
case TwirpContentType.Protobuf:
return handleArtifactServiceListArtifactsProtobuf<T>(
ctx,
service,
data,
interceptors
);
default:
const msg = "unexpected Content-Type";
throw new TwirpError(TwirpErrorCode.BadRoute, msg);
}
}
function handleArtifactServiceGetSignedArtifactURLRequest<
T extends TwirpContext = TwirpContext
>(
ctx: T,
service: ArtifactServiceTwirp,
data: Buffer,
interceptors?: Interceptor<
T,
GetSignedArtifactURLRequest,
GetSignedArtifactURLResponse
>[]
): Promise<string | Uint8Array> {
switch (ctx.contentType) {
case TwirpContentType.JSON:
return handleArtifactServiceGetSignedArtifactURLJSON<T>(
ctx,
service,
data,
interceptors
);
case TwirpContentType.Protobuf:
return handleArtifactServiceGetSignedArtifactURLProtobuf<T>(
ctx,
service,
data,
interceptors
);
default:
const msg = "unexpected Content-Type";
throw new TwirpError(TwirpErrorCode.BadRoute, msg);
} }
} }
async function handleArtifactServiceCreateArtifactJSON< async function handleArtifactServiceCreateArtifactJSON<
@@ -471,18 +279,16 @@ async function handleArtifactServiceCreateArtifactJSON<
data: Buffer, data: Buffer,
interceptors?: Interceptor<T, CreateArtifactRequest, CreateArtifactResponse>[] interceptors?: Interceptor<T, CreateArtifactRequest, CreateArtifactResponse>[]
) { ) {
let request: CreateArtifactRequest; let request: CreateArtifactRequest
let response: CreateArtifactResponse; let response: CreateArtifactResponse
try { try {
const body = JSON.parse(data.toString() || "{}"); const body = JSON.parse(data.toString() || '{}')
request = CreateArtifactRequest.fromJson(body, { request = CreateArtifactRequest.fromJson(body, {ignoreUnknownFields: true})
ignoreUnknownFields: true,
});
} catch (e) { } catch (e) {
if (e instanceof Error) { if (e instanceof Error) {
const msg = "the json request could not be decoded"; const msg = 'the json request could not be decoded'
throw new TwirpError(TwirpErrorCode.Malformed, msg).withCause(e, true); throw new TwirpError(TwirpErrorCode.Malformed, msg).withCause(e, true)
} }
} }
@@ -491,20 +297,20 @@ async function handleArtifactServiceCreateArtifactJSON<
T, T,
CreateArtifactRequest, CreateArtifactRequest,
CreateArtifactResponse CreateArtifactResponse
>; >
response = await interceptor(ctx, request!, (ctx, inputReq) => { response = await interceptor(ctx, request!, (ctx, inputReq) => {
return service.CreateArtifact(ctx, inputReq); return service.CreateArtifact(ctx, inputReq)
}); })
} else { } else {
response = await service.CreateArtifact(ctx, request!); response = await service.CreateArtifact(ctx, request!)
} }
return JSON.stringify( return JSON.stringify(
CreateArtifactResponse.toJson(response, { CreateArtifactResponse.toJson(response, {
useProtoFieldName: true, useProtoFieldName: true,
emitDefaultValues: false, emitDefaultValues: false
}) as string }) as string
); )
} }
async function handleArtifactServiceFinalizeArtifactJSON< async function handleArtifactServiceFinalizeArtifactJSON<
@@ -519,18 +325,18 @@ async function handleArtifactServiceFinalizeArtifactJSON<
FinalizeArtifactResponse FinalizeArtifactResponse
>[] >[]
) { ) {
let request: FinalizeArtifactRequest; let request: FinalizeArtifactRequest
let response: FinalizeArtifactResponse; let response: FinalizeArtifactResponse
try { try {
const body = JSON.parse(data.toString() || "{}"); const body = JSON.parse(data.toString() || '{}')
request = FinalizeArtifactRequest.fromJson(body, { request = FinalizeArtifactRequest.fromJson(body, {
ignoreUnknownFields: true, ignoreUnknownFields: true
}); })
} catch (e) { } catch (e) {
if (e instanceof Error) { if (e instanceof Error) {
const msg = "the json request could not be decoded"; const msg = 'the json request could not be decoded'
throw new TwirpError(TwirpErrorCode.Malformed, msg).withCause(e, true); throw new TwirpError(TwirpErrorCode.Malformed, msg).withCause(e, true)
} }
} }
@@ -539,112 +345,20 @@ async function handleArtifactServiceFinalizeArtifactJSON<
T, T,
FinalizeArtifactRequest, FinalizeArtifactRequest,
FinalizeArtifactResponse FinalizeArtifactResponse
>; >
response = await interceptor(ctx, request!, (ctx, inputReq) => { response = await interceptor(ctx, request!, (ctx, inputReq) => {
return service.FinalizeArtifact(ctx, inputReq); return service.FinalizeArtifact(ctx, inputReq)
}); })
} else { } else {
response = await service.FinalizeArtifact(ctx, request!); response = await service.FinalizeArtifact(ctx, request!)
} }
return JSON.stringify( return JSON.stringify(
FinalizeArtifactResponse.toJson(response, { FinalizeArtifactResponse.toJson(response, {
useProtoFieldName: true, useProtoFieldName: true,
emitDefaultValues: false, emitDefaultValues: false
}) as string }) as string
); )
}
async function handleArtifactServiceListArtifactsJSON<
T extends TwirpContext = TwirpContext
>(
ctx: T,
service: ArtifactServiceTwirp,
data: Buffer,
interceptors?: Interceptor<T, ListArtifactsRequest, ListArtifactsResponse>[]
) {
let request: ListArtifactsRequest;
let response: ListArtifactsResponse;
try {
const body = JSON.parse(data.toString() || "{}");
request = ListArtifactsRequest.fromJson(body, {
ignoreUnknownFields: true,
});
} catch (e) {
if (e instanceof Error) {
const msg = "the json request could not be decoded";
throw new TwirpError(TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = chainInterceptors(...interceptors) as Interceptor<
T,
ListArtifactsRequest,
ListArtifactsResponse
>;
response = await interceptor(ctx, request!, (ctx, inputReq) => {
return service.ListArtifacts(ctx, inputReq);
});
} else {
response = await service.ListArtifacts(ctx, request!);
}
return JSON.stringify(
ListArtifactsResponse.toJson(response, {
useProtoFieldName: true,
emitDefaultValues: false,
}) as string
);
}
async function handleArtifactServiceGetSignedArtifactURLJSON<
T extends TwirpContext = TwirpContext
>(
ctx: T,
service: ArtifactServiceTwirp,
data: Buffer,
interceptors?: Interceptor<
T,
GetSignedArtifactURLRequest,
GetSignedArtifactURLResponse
>[]
) {
let request: GetSignedArtifactURLRequest;
let response: GetSignedArtifactURLResponse;
try {
const body = JSON.parse(data.toString() || "{}");
request = GetSignedArtifactURLRequest.fromJson(body, {
ignoreUnknownFields: true,
});
} catch (e) {
if (e instanceof Error) {
const msg = "the json request could not be decoded";
throw new TwirpError(TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = chainInterceptors(...interceptors) as Interceptor<
T,
GetSignedArtifactURLRequest,
GetSignedArtifactURLResponse
>;
response = await interceptor(ctx, request!, (ctx, inputReq) => {
return service.GetSignedArtifactURL(ctx, inputReq);
});
} else {
response = await service.GetSignedArtifactURL(ctx, request!);
}
return JSON.stringify(
GetSignedArtifactURLResponse.toJson(response, {
useProtoFieldName: true,
emitDefaultValues: false,
}) as string
);
} }
async function handleArtifactServiceCreateArtifactProtobuf< async function handleArtifactServiceCreateArtifactProtobuf<
T extends TwirpContext = TwirpContext T extends TwirpContext = TwirpContext
@@ -654,15 +368,15 @@ async function handleArtifactServiceCreateArtifactProtobuf<
data: Buffer, data: Buffer,
interceptors?: Interceptor<T, CreateArtifactRequest, CreateArtifactResponse>[] interceptors?: Interceptor<T, CreateArtifactRequest, CreateArtifactResponse>[]
) { ) {
let request: CreateArtifactRequest; let request: CreateArtifactRequest
let response: CreateArtifactResponse; let response: CreateArtifactResponse
try { try {
request = CreateArtifactRequest.fromBinary(data); request = CreateArtifactRequest.fromBinary(data)
} catch (e) { } catch (e) {
if (e instanceof Error) { if (e instanceof Error) {
const msg = "the protobuf request could not be decoded"; const msg = 'the protobuf request could not be decoded'
throw new TwirpError(TwirpErrorCode.Malformed, msg).withCause(e, true); throw new TwirpError(TwirpErrorCode.Malformed, msg).withCause(e, true)
} }
} }
@@ -671,15 +385,15 @@ async function handleArtifactServiceCreateArtifactProtobuf<
T, T,
CreateArtifactRequest, CreateArtifactRequest,
CreateArtifactResponse CreateArtifactResponse
>; >
response = await interceptor(ctx, request!, (ctx, inputReq) => { response = await interceptor(ctx, request!, (ctx, inputReq) => {
return service.CreateArtifact(ctx, inputReq); return service.CreateArtifact(ctx, inputReq)
}); })
} else { } else {
response = await service.CreateArtifact(ctx, request!); response = await service.CreateArtifact(ctx, request!)
} }
return Buffer.from(CreateArtifactResponse.toBinary(response)); return Buffer.from(CreateArtifactResponse.toBinary(response))
} }
async function handleArtifactServiceFinalizeArtifactProtobuf< async function handleArtifactServiceFinalizeArtifactProtobuf<
@@ -694,15 +408,15 @@ async function handleArtifactServiceFinalizeArtifactProtobuf<
FinalizeArtifactResponse FinalizeArtifactResponse
>[] >[]
) { ) {
let request: FinalizeArtifactRequest; let request: FinalizeArtifactRequest
let response: FinalizeArtifactResponse; let response: FinalizeArtifactResponse
try { try {
request = FinalizeArtifactRequest.fromBinary(data); request = FinalizeArtifactRequest.fromBinary(data)
} catch (e) { } catch (e) {
if (e instanceof Error) { if (e instanceof Error) {
const msg = "the protobuf request could not be decoded"; const msg = 'the protobuf request could not be decoded'
throw new TwirpError(TwirpErrorCode.Malformed, msg).withCause(e, true); throw new TwirpError(TwirpErrorCode.Malformed, msg).withCause(e, true)
} }
} }
@@ -711,89 +425,13 @@ async function handleArtifactServiceFinalizeArtifactProtobuf<
T, T,
FinalizeArtifactRequest, FinalizeArtifactRequest,
FinalizeArtifactResponse FinalizeArtifactResponse
>; >
response = await interceptor(ctx, request!, (ctx, inputReq) => { response = await interceptor(ctx, request!, (ctx, inputReq) => {
return service.FinalizeArtifact(ctx, inputReq); return service.FinalizeArtifact(ctx, inputReq)
}); })
} else { } else {
response = await service.FinalizeArtifact(ctx, request!); response = await service.FinalizeArtifact(ctx, request!)
} }
return Buffer.from(FinalizeArtifactResponse.toBinary(response)); return Buffer.from(FinalizeArtifactResponse.toBinary(response))
}
async function handleArtifactServiceListArtifactsProtobuf<
T extends TwirpContext = TwirpContext
>(
ctx: T,
service: ArtifactServiceTwirp,
data: Buffer,
interceptors?: Interceptor<T, ListArtifactsRequest, ListArtifactsResponse>[]
) {
let request: ListArtifactsRequest;
let response: ListArtifactsResponse;
try {
request = ListArtifactsRequest.fromBinary(data);
} catch (e) {
if (e instanceof Error) {
const msg = "the protobuf request could not be decoded";
throw new TwirpError(TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = chainInterceptors(...interceptors) as Interceptor<
T,
ListArtifactsRequest,
ListArtifactsResponse
>;
response = await interceptor(ctx, request!, (ctx, inputReq) => {
return service.ListArtifacts(ctx, inputReq);
});
} else {
response = await service.ListArtifacts(ctx, request!);
}
return Buffer.from(ListArtifactsResponse.toBinary(response));
}
async function handleArtifactServiceGetSignedArtifactURLProtobuf<
T extends TwirpContext = TwirpContext
>(
ctx: T,
service: ArtifactServiceTwirp,
data: Buffer,
interceptors?: Interceptor<
T,
GetSignedArtifactURLRequest,
GetSignedArtifactURLResponse
>[]
) {
let request: GetSignedArtifactURLRequest;
let response: GetSignedArtifactURLResponse;
try {
request = GetSignedArtifactURLRequest.fromBinary(data);
} catch (e) {
if (e instanceof Error) {
const msg = "the protobuf request could not be decoded";
throw new TwirpError(TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = chainInterceptors(...interceptors) as Interceptor<
T,
GetSignedArtifactURLRequest,
GetSignedArtifactURLResponse
>;
response = await interceptor(ctx, request!, (ctx, inputReq) => {
return service.GetSignedArtifactURL(ctx, inputReq);
});
} else {
response = await service.GetSignedArtifactURL(ctx, request!);
}
return Buffer.from(GetSignedArtifactURLResponse.toBinary(response));
} }
+55 -57
View File
@@ -6,16 +6,12 @@ import {
DownloadArtifactOptions, DownloadArtifactOptions,
GetArtifactResponse, GetArtifactResponse,
ListArtifactsResponse, ListArtifactsResponse,
DownloadArtifactResponse, DownloadArtifactResponse
FindOptions
} from './shared/interfaces' } from './shared/interfaces'
import {uploadArtifact} from './upload/upload-artifact' import {uploadArtifact} from './upload/upload-artifact'
import { import {downloadArtifact} from './download/download-artifact'
downloadArtifactPublic, import {getArtifact} from './find/get-artifact'
downloadArtifactInternal import {listArtifacts} from './find/list-artifacts'
} from './download/download-artifact'
import {getArtifactPublic, getArtifactInternal} from './find/get-artifact'
import {listArtifactsPublic, listArtifactsInternal} from './find/list-artifacts'
export interface ArtifactClient { export interface ArtifactClient {
/** /**
@@ -35,46 +31,62 @@ export interface ArtifactClient {
): Promise<UploadResponse> ): Promise<UploadResponse>
/** /**
* Lists all artifacts that are part of the current workflow run. * Lists all artifacts that are part of a workflow run.
* This function will return at most 1000 artifacts per workflow run.
* *
* If options.findBy is specified, this will call the public List-Artifacts API which can list from other runs. * This calls the public List-Artifacts API https://docs.github.com/en/rest/actions/artifacts?apiVersion=2022-11-28#list-workflow-run-artifacts
* https://docs.github.com/en/rest/actions/artifacts?apiVersion=2022-11-28#list-workflow-run-artifacts * Due to paginated responses from the public API. This function will return at most 1000 artifacts per workflow run (100 per page * maximum 10 calls)
* *
* @param options Extra options that allow for the customization of the list behavior * @param workflowRunId The workflow run id that the artifact belongs to
* @param repositoryOwner The owner of the repository that the artifact belongs to
* @param repositoryName The name of the repository that the artifact belongs to
* @param token A token with the appropriate permission to the repository to list artifacts
* @returns ListArtifactResponse object * @returns ListArtifactResponse object
*/ */
listArtifacts(options?: FindOptions): Promise<ListArtifactsResponse> listArtifacts(
workflowRunId: number,
repositoryOwner: string,
repositoryName: string,
token: string
): Promise<ListArtifactsResponse>
/** /**
* Finds an artifact by name. * Finds an artifact by name given a repository and workflow run id.
* *
* If options.findBy is specified, this will use the public List Artifacts API with a name filter which can get artifacts from other runs. * This calls the public List-Artifacts API with a name filter https://docs.github.com/en/rest/actions/artifacts?apiVersion=2022-11-28#list-workflow-run-artifacts
* https://docs.github.com/en/rest/actions/artifacts?apiVersion=2022-11-28#list-workflow-run-artifacts
* @actions/artifact > 2.0.0 does not allow for creating multiple artifacts with the same name in the same workflow run. * @actions/artifact > 2.0.0 does not allow for creating multiple artifacts with the same name in the same workflow run.
* It is possible to have multiple artifacts with the same name in the same workflow run by using old versions of upload-artifact (v1,v2 and v3), @actions/artifact < v2.0.0 or it is a rerun. * It is possible to have multiple artifacts with the same name in the same workflow run by using old versions of upload-artifact (v1,v2 and v3) or @actions/artifact < v2.0.0
* If there are multiple artifacts with the same name in the same workflow run this function will return the first artifact that matches the name. * If there are multiple artifacts with the same name in the same workflow run this function will return the first artifact that matches the name.
* *
* @param artifactName The name of the artifact to find * @param artifactName The name of the artifact to find
* @param options Extra options that allow for the customization of the get behavior * @param workflowRunId The workflow run id that the artifact belongs to
* @param repositoryOwner The owner of the repository that the artifact belongs to
* @param repositoryName The name of the repository that the artifact belongs to
* @param token A token with the appropriate permission to the repository to find the artifact
*/ */
getArtifact( getArtifact(
artifactName: string, artifactName: string,
options?: FindOptions workflowRunId: number,
repositoryOwner: string,
repositoryName: string,
token: string
): Promise<GetArtifactResponse> ): Promise<GetArtifactResponse>
/** /**
* Downloads an artifact and unzips the content. * Downloads an artifact and unzips the content
*
* If options.findBy is specified, this will use the public Download Artifact API https://docs.github.com/en/rest/actions/artifacts?apiVersion=2022-11-28#download-an-artifact
* *
* @param artifactId The name of the artifact to download * @param artifactId The name of the artifact to download
* @param repositoryOwner The owner of the repository that the artifact belongs to
* @param repositoryName The name of the repository that the artifact belongs to
* @param token A token with the appropriate permission to the repository to download the artifact
* @param options Extra options that allow for the customization of the download behavior * @param options Extra options that allow for the customization of the download behavior
* @returns single DownloadArtifactResponse object * @returns single DownloadArtifactResponse object
*/ */
downloadArtifact( downloadArtifact(
artifactId: number, artifactId: number,
options?: DownloadArtifactOptions & FindOptions repositoryOwner: string,
repositoryName: string,
token: string,
options?: DownloadArtifactOptions
): Promise<DownloadArtifactResponse> ): Promise<DownloadArtifactResponse>
} }
@@ -93,7 +105,7 @@ export class Client implements ArtifactClient {
name: string, name: string,
files: string[], files: string[],
rootDirectory: string, rootDirectory: string,
options?: UploadOptions options?: UploadOptions | undefined
): Promise<UploadResponse> { ): Promise<UploadResponse> {
if (isGhes()) { if (isGhes()) {
warning( warning(
@@ -125,7 +137,10 @@ If the error persists, please check whether Actions is operating normally at [ht
*/ */
async downloadArtifact( async downloadArtifact(
artifactId: number, artifactId: number,
options?: DownloadArtifactOptions & FindOptions repositoryOwner: string,
repositoryName: string,
token: string,
options?: DownloadArtifactOptions
): Promise<DownloadArtifactResponse> { ): Promise<DownloadArtifactResponse> {
if (isGhes()) { if (isGhes()) {
warning( warning(
@@ -137,22 +152,13 @@ If the error persists, please check whether Actions is operating normally at [ht
} }
try { try {
if (options?.findBy) { return downloadArtifact(
const {
findBy: {repositoryOwner, repositoryName, token},
...downloadOptions
} = options
return downloadArtifactPublic(
artifactId, artifactId,
repositoryOwner, repositoryOwner,
repositoryName, repositoryName,
token, token,
downloadOptions options
) )
}
return downloadArtifactInternal(artifactId, options)
} catch (error) { } catch (error) {
warning( warning(
`Artifact download failed with error: ${error}. `Artifact download failed with error: ${error}.
@@ -171,7 +177,12 @@ If the error persists, please check whether Actions and API requests are operati
/** /**
* List Artifacts * List Artifacts
*/ */
async listArtifacts(options?: FindOptions): Promise<ListArtifactsResponse> { async listArtifacts(
workflowRunId: number,
repositoryOwner: string,
repositoryName: string,
token: string
): Promise<ListArtifactsResponse> {
if (isGhes()) { if (isGhes()) {
warning( warning(
`@actions/artifact v2.0.0+ and download-artifact@v4+ are not currently supported on GHES.` `@actions/artifact v2.0.0+ and download-artifact@v4+ are not currently supported on GHES.`
@@ -182,20 +193,12 @@ If the error persists, please check whether Actions and API requests are operati
} }
try { try {
if (options?.findBy) { return listArtifacts(
const {
findBy: {workflowRunId, repositoryOwner, repositoryName, token}
} = options
return listArtifactsPublic(
workflowRunId, workflowRunId,
repositoryOwner, repositoryOwner,
repositoryName, repositoryName,
token token
) )
}
return listArtifactsInternal()
} catch (error: unknown) { } catch (error: unknown) {
warning( warning(
`Listing Artifacts failed with error: ${error}. `Listing Artifacts failed with error: ${error}.
@@ -216,7 +219,10 @@ If the error persists, please check whether Actions and API requests are operati
*/ */
async getArtifact( async getArtifact(
artifactName: string, artifactName: string,
options?: FindOptions workflowRunId: number,
repositoryOwner: string,
repositoryName: string,
token: string
): Promise<GetArtifactResponse> { ): Promise<GetArtifactResponse> {
if (isGhes()) { if (isGhes()) {
warning( warning(
@@ -228,21 +234,13 @@ If the error persists, please check whether Actions and API requests are operati
} }
try { try {
if (options?.findBy) { return getArtifact(
const {
findBy: {workflowRunId, repositoryOwner, repositoryName, token}
} = options
return getArtifactPublic(
artifactName, artifactName,
workflowRunId, workflowRunId,
repositoryOwner, repositoryOwner,
repositoryName, repositoryName,
token token
) )
}
return getArtifactInternal(artifactName)
} catch (error: unknown) { } catch (error: unknown) {
warning( warning(
`Fetching Artifact failed with error: ${error}. `Fetching Artifact failed with error: ${error}.
@@ -9,13 +9,6 @@ import {
} from '../shared/interfaces' } from '../shared/interfaces'
import {getUserAgentString} from '../shared/user-agent' import {getUserAgentString} from '../shared/user-agent'
import {getGitHubWorkspaceDir} from '../shared/config' import {getGitHubWorkspaceDir} from '../shared/config'
import {internalArtifactTwirpClient} from '../shared/artifact-twirp-client'
import {
GetSignedArtifactURLRequest,
Int64Value,
ListArtifactsRequest
} from '../../generated'
import {getBackendIdsFromToken} from '../shared/util'
const scrubQueryParameters = (url: string): string => { const scrubQueryParameters = (url: string): string => {
const parsed = new URL(url) const parsed = new URL(url)
@@ -49,14 +42,23 @@ async function streamExtract(url: string, directory: string): Promise<void> {
return response.message.pipe(unzipper.Extract({path: directory})).promise() return response.message.pipe(unzipper.Extract({path: directory})).promise()
} }
export async function downloadArtifactPublic( export async function downloadArtifact(
artifactId: number, artifactId: number,
repositoryOwner: string, repositoryOwner: string,
repositoryName: string, repositoryName: string,
token: string, token: string,
options?: DownloadArtifactOptions options?: DownloadArtifactOptions
): Promise<DownloadArtifactResponse> { ): Promise<DownloadArtifactResponse> {
const downloadPath = await resolveOrCreateDirectory(options?.path) const downloadPath = options?.path || getGitHubWorkspaceDir()
if (!(await exists(downloadPath))) {
core.debug(
`Artifact destination folder does not exist, creating: ${downloadPath}`
)
await fs.mkdir(downloadPath, {recursive: true})
} else {
core.debug(`Artifact destination folder already exists: ${downloadPath}`)
}
const api = github.getOctokit(token) const api = github.getOctokit(token)
@@ -97,71 +99,3 @@ export async function downloadArtifactPublic(
return {success: true, downloadPath} return {success: true, downloadPath}
} }
export async function downloadArtifactInternal(
artifactId: number,
options?: DownloadArtifactOptions
): Promise<DownloadArtifactResponse> {
const downloadPath = await resolveOrCreateDirectory(options?.path)
const artifactClient = internalArtifactTwirpClient()
const {workflowRunBackendId, workflowJobRunBackendId} =
getBackendIdsFromToken()
const listReq: ListArtifactsRequest = {
workflowRunBackendId,
workflowJobRunBackendId,
idFilter: Int64Value.create({value: artifactId.toString()})
}
const {artifacts} = await artifactClient.ListArtifacts(listReq)
if (artifacts.length === 0) {
core.warning(
`No artifacts found for ID: ${artifactId}\nAre you trying to download from a different run? Try specifying a github-token with \`actions:read\` scope.`
)
return {success: false}
}
if (artifacts.length > 1) {
core.warning('Multiple artifacts found, defaulting to first.')
}
const signedReq: GetSignedArtifactURLRequest = {
workflowRunBackendId: artifacts[0].workflowRunBackendId,
workflowJobRunBackendId: artifacts[0].workflowJobRunBackendId,
name: artifacts[0].name
}
const {signedUrl} = await artifactClient.GetSignedArtifactURL(signedReq)
core.info(
`Redirecting to blob download url: ${scrubQueryParameters(signedUrl)}`
)
try {
core.info(`Starting download of artifact to: ${downloadPath}`)
await streamExtract(signedUrl, downloadPath)
core.info(`Artifact download completed successfully.`)
} catch (error) {
throw new Error(`Unable to download and extract artifact: ${error.message}`)
}
return {success: true, downloadPath}
}
async function resolveOrCreateDirectory(
downloadPath = getGitHubWorkspaceDir()
): Promise<string> {
if (!(await exists(downloadPath))) {
core.debug(
`Artifact destination folder does not exist, creating: ${downloadPath}`
)
await fs.mkdir(downloadPath, {recursive: true})
} else {
core.debug(`Artifact destination folder already exists: ${downloadPath}`)
}
return downloadPath
}
@@ -1,17 +1,14 @@
import {GetArtifactResponse} from '../shared/interfaces'
import {getOctokit} from '@actions/github' import {getOctokit} from '@actions/github'
import {retry} from '@octokit/plugin-retry' import {getUserAgentString} from '../shared/user-agent'
import * as core from '@actions/core'
import {OctokitOptions} from '@octokit/core/dist-types/types'
import {defaults as defaultGitHubOptions} from '@actions/github/lib/utils' import {defaults as defaultGitHubOptions} from '@actions/github/lib/utils'
import {getRetryOptions} from './retry-options' import {getRetryOptions} from './retry-options'
import {requestLog} from '@octokit/plugin-request-log' import {requestLog} from '@octokit/plugin-request-log'
import {GetArtifactResponse} from '../shared/interfaces' import {retry} from '@octokit/plugin-retry'
import {getBackendIdsFromToken} from '../shared/util' import * as core from '@actions/core'
import {getUserAgentString} from '../shared/user-agent' import {OctokitOptions} from '@octokit/core/dist-types/types'
import {internalArtifactTwirpClient} from '../shared/artifact-twirp-client'
import {ListArtifactsRequest, StringValue} from '../../generated'
export async function getArtifactPublic( export async function getArtifact(
artifactName: string, artifactName: string,
workflowRunId: number, workflowRunId: number,
repositoryOwner: string, repositoryOwner: string,
@@ -65,54 +62,8 @@ export async function getArtifactPublic(
artifact: { artifact: {
name: getArtifactResp.data.artifacts[0].name, name: getArtifactResp.data.artifacts[0].name,
id: getArtifactResp.data.artifacts[0].id, id: getArtifactResp.data.artifacts[0].id,
url: getArtifactResp.data.artifacts[0].url,
size: getArtifactResp.data.artifacts[0].size_in_bytes size: getArtifactResp.data.artifacts[0].size_in_bytes
} }
} }
} }
export async function getArtifactInternal(
artifactName: string
): Promise<GetArtifactResponse> {
const artifactClient = internalArtifactTwirpClient()
const {workflowRunBackendId, workflowJobRunBackendId} =
getBackendIdsFromToken()
const req: ListArtifactsRequest = {
workflowRunBackendId,
workflowJobRunBackendId,
nameFilter: StringValue.create({value: artifactName})
}
const res = await artifactClient.ListArtifacts(req)
if (res.artifacts.length === 0) {
core.warning('no artifacts found')
return {
success: false
}
}
if (res.artifacts.length > 1) {
core.warning(
'more than one artifact found for a single name, returning first'
)
}
// In the case of reruns, we may have artifacts with the same name scoped under the same workflow run.
// Let's prefer the artifact closest scoped to this run.
// If it doesn't exist (e.g. partial rerun) we'll use the first match.
const artifact =
res.artifacts.find(
artifact => artifact.workflowRunBackendId === workflowRunBackendId
) || res.artifacts[0]
return {
success: true,
artifact: {
name: artifact.name,
id: Number(artifact.databaseId),
size: Number(artifact.size)
}
}
}
@@ -7,16 +7,13 @@ import {defaults as defaultGitHubOptions} from '@actions/github/lib/utils'
import {requestLog} from '@octokit/plugin-request-log' import {requestLog} from '@octokit/plugin-request-log'
import {retry} from '@octokit/plugin-retry' import {retry} from '@octokit/plugin-retry'
import {OctokitOptions} from '@octokit/core/dist-types/types' import {OctokitOptions} from '@octokit/core/dist-types/types'
import {internalArtifactTwirpClient} from '../shared/artifact-twirp-client'
import {getBackendIdsFromToken} from '../shared/util'
import {ListArtifactsRequest} from 'src/generated'
// Limiting to 1000 for perf reasons // Limiting to 1000 for perf reasons
const maximumArtifactCount = 1000 const maximumArtifactCount = 1000
const paginationCount = 100 const paginationCount = 100
const maxNumberOfPages = maximumArtifactCount / paginationCount const maxNumberOfPages = maximumArtifactCount / paginationCount
export async function listArtifactsPublic( export async function listArtifacts(
workflowRunId: number, workflowRunId: number,
repositoryOwner: string, repositoryOwner: string,
repositoryName: string, repositoryName: string,
@@ -65,6 +62,7 @@ export async function listArtifactsPublic(
artifacts.push({ artifacts.push({
name: artifact.name, name: artifact.name,
id: artifact.id, id: artifact.id,
url: artifact.url,
size: artifact.size_in_bytes size: artifact.size_in_bytes
}) })
} }
@@ -91,37 +89,13 @@ export async function listArtifactsPublic(
artifacts.push({ artifacts.push({
name: artifact.name, name: artifact.name,
id: artifact.id, id: artifact.id,
url: artifact.url,
size: artifact.size_in_bytes size: artifact.size_in_bytes
}) })
} }
} }
info(`Found ${artifacts.length} artifact(s)`) info(`Finished fetching artifact list`)
return {
artifacts
}
}
export async function listArtifactsInternal(): Promise<ListArtifactsResponse> {
const artifactClient = internalArtifactTwirpClient()
const {workflowRunBackendId, workflowJobRunBackendId} =
getBackendIdsFromToken()
const req: ListArtifactsRequest = {
workflowRunBackendId,
workflowJobRunBackendId
}
const res = await artifactClient.ListArtifacts(req)
const artifacts = res.artifacts.map(artifact => ({
name: artifact.name,
id: Number(artifact.databaseId),
size: Number(artifact.size)
}))
info(`Found ${artifacts.length} artifact(s)`)
return { return {
artifacts artifacts
@@ -3,7 +3,6 @@ import {BearerCredentialHandler} from '@actions/http-client/lib/auth'
import {info, debug} from '@actions/core' import {info, debug} from '@actions/core'
import {ArtifactServiceClientJSON} from '../../generated' import {ArtifactServiceClientJSON} from '../../generated'
import {getResultsServiceUrl, getRuntimeToken} from './config' import {getResultsServiceUrl, getRuntimeToken} from './config'
import {getUserAgentString} from './user-agent'
// The twirp http client must implement this interface // The twirp http client must implement this interface
interface Rpc { interface Rpc {
@@ -53,8 +52,8 @@ class ArtifactHttpClient implements Rpc {
contentType: 'application/json' | 'application/protobuf', contentType: 'application/json' | 'application/protobuf',
data: object | Uint8Array data: object | Uint8Array
): Promise<object | Uint8Array> { ): Promise<object | Uint8Array> {
const url = new URL(`/twirp/${service}/${method}`, this.baseUrl).href const url = `${this.baseUrl}/twirp/${service}/${method}`
debug(`[Request] ${method} ${url}`) debug(`Requesting ${url}`)
const headers = { const headers = {
'Content-Type': contentType 'Content-Type': contentType
} }
@@ -80,8 +79,6 @@ class ArtifactHttpClient implements Rpc {
try { try {
const response = await operation() const response = await operation()
const statusCode = response.message.statusCode const statusCode = response.message.statusCode
debug(`[Response] ${response.message.statusCode}`)
debug(JSON.stringify(response.message.headers, null, 2))
if (this.isSuccessStatusCode(statusCode)) { if (this.isSuccessStatusCode(statusCode)) {
return response return response
@@ -160,16 +157,17 @@ class ArtifactHttpClient implements Rpc {
} }
} }
export function internalArtifactTwirpClient(options?: { export function createArtifactTwirpClient(
maxAttempts?: number type: 'upload' | 'download',
retryIntervalMs?: number maxAttempts?: number,
baseRetryIntervalMilliseconds?: number,
retryMultiplier?: number retryMultiplier?: number
}): ArtifactServiceClientJSON { ): ArtifactServiceClientJSON {
const client = new ArtifactHttpClient( const client = new ArtifactHttpClient(
getUserAgentString(), `@actions/artifact-${type}`,
options?.maxAttempts, maxAttempts,
options?.retryIntervalMs, baseRetryIntervalMilliseconds,
options?.retryMultiplier retryMultiplier
) )
return new ArtifactServiceClientJSON(client) return new ArtifactServiceClientJSON(client)
} }
@@ -1,5 +1,3 @@
import os from 'os'
// Used for controlling the highWaterMark value of the zip that is being streamed // Used for controlling the highWaterMark value of the zip that is being streamed
// The same value is used as the chunk size that is use during upload to blob storage // The same value is used as the chunk size that is use during upload to blob storage
export function getUploadChunkSize(): number { export function getUploadChunkSize(): number {
@@ -19,8 +17,7 @@ export function getResultsServiceUrl(): string {
if (!resultsUrl) { if (!resultsUrl) {
throw new Error('Unable to get the ACTIONS_RESULTS_URL env variable') throw new Error('Unable to get the ACTIONS_RESULTS_URL env variable')
} }
return resultsUrl
return new URL(resultsUrl).origin
} }
export function isGhes(): boolean { export function isGhes(): boolean {
@@ -37,17 +34,3 @@ export function getGitHubWorkspaceDir(): string {
} }
return ghWorkspaceDir return ghWorkspaceDir
} }
// 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.
export function getConcurrency(): number {
const numCPUs = os.cpus().length
if (numCPUs <= 4) {
return 32
}
const concurrency = 16 * numCPUs
return concurrency > 300 ? 300 : concurrency
}
@@ -38,17 +38,6 @@ export interface UploadOptions {
* input of 0 assumes default retention setting. * input of 0 assumes default retention setting.
*/ */
retentionDays?: number retentionDays?: number
/**
* The level of compression for Zlib to be applied to the artifact archive.
* The value can range from 0 to 9:
* - 0: No compression
* - 1: Best speed
* - 6: Default compression (same as GNU Gzip)
* - 9: Best compression
* Higher levels will result in better compression, but will take longer to complete.
* For large files that are not easily compressed, a value of 0 is recommended for significantly faster uploads.
*/
compressionLevel?: number
} }
/***************************************************************************** /*****************************************************************************
@@ -120,23 +109,13 @@ export interface Artifact {
*/ */
id: number id: number
/**
* The URL of the artifact
*/
url: string
/** /**
* The size of the artifact in bytes * The size of the artifact in bytes
*/ */
size: number size: number
} }
// FindOptions are for fetching Artifact(s) out of the scope of the current run.
// Must specify a PAT with actions:read scope for cross run/repo lookup otherwise these will be ignored.
export interface FindOptions {
findBy?: {
// Token with actions:read permissions
token: string
// WorkflowRun of the artifact(s) to lookup
workflowRunId: number
// Repository owner
repositoryOwner: string
// Repository name
repositoryName: string
}
}
+9 -15
View File
@@ -1,4 +1,3 @@
import * as core from '@actions/core'
import {getRuntimeToken} from './config' import {getRuntimeToken} from './config'
import jwt_decode from 'jwt-decode' import jwt_decode from 'jwt-decode'
@@ -12,7 +11,7 @@ interface ActionsToken {
} }
const InvalidJwtError = new Error( const InvalidJwtError = new Error(
'Failed to get backend IDs: The provided JWT token is invalid and/or missing claims' 'Failed to get backend IDs: The provided JWT token is invalid'
) )
// uses the JWT token claims to get the // uses the JWT token claims to get the
@@ -42,29 +41,24 @@ export function getBackendIdsFromToken(): BackendIds {
for (const scopes of scpParts) { for (const scopes of scpParts) {
const scopeParts = scopes.split(':') const scopeParts = scopes.split(':')
if (scopeParts?.[0] !== 'Actions.Results') {
// not the Actions.Results scope
continue
}
/* /*
* example scopeParts: * example scopeParts:
* ["Actions.Results", "ce7f54c7-61c7-4aae-887f-30da475f5f1a", "ca395085-040a-526b-2ce8-bdc85f692774"] * ["Actions.Results", "ce7f54c7-61c7-4aae-887f-30da475f5f1a", "ca395085-040a-526b-2ce8-bdc85f692774"]
*/ */
if (scopeParts.length !== 3) { if (scopeParts.length !== 3) {
// missing expected number of claims // not the Actions.Results scope
throw InvalidJwtError continue
} }
const ids = { if (scopeParts[0] !== 'Actions.Results') {
// not the Actions.Results scope
continue
}
return {
workflowRunBackendId: scopeParts[1], workflowRunBackendId: scopeParts[1],
workflowJobRunBackendId: scopeParts[2] workflowJobRunBackendId: scopeParts[2]
} }
core.debug(`Workflow Run Backend ID: ${ids.workflowRunBackendId}`)
core.debug(`Workflow Job Run Backend ID: ${ids.workflowJobRunBackendId}`)
return ids
} }
throw InvalidJwtError throw InvalidJwtError
@@ -1,7 +1,7 @@
import {BlobClient, BlockBlobUploadStreamOptions} from '@azure/storage-blob' import {BlobClient, BlockBlobUploadStreamOptions} from '@azure/storage-blob'
import {TransferProgressEvent} from '@azure/core-http' import {TransferProgressEvent} from '@azure/core-http'
import {ZipUploadStream} from './zip' import {ZipUploadStream} from './zip'
import {getUploadChunkSize, getConcurrency} from '../shared/config' import {getUploadChunkSize} from '../shared/config'
import * as core from '@actions/core' import * as core from '@actions/core'
import * as crypto from 'crypto' import * as crypto from 'crypto'
import * as stream from 'stream' import * as stream from 'stream'
@@ -18,9 +18,9 @@ export interface BlobUploadResponse {
uploadSize?: number uploadSize?: number
/** /**
* The SHA256 hash of the uploaded file. Empty if the upload failed * The MD5 hash of the uploaded file. Empty if the upload failed
*/ */
sha256Hash?: string md5Hash?: string
} }
export async function uploadZipToBlobStorage( export async function uploadZipToBlobStorage(
@@ -29,13 +29,13 @@ export async function uploadZipToBlobStorage(
): Promise<BlobUploadResponse> { ): Promise<BlobUploadResponse> {
let uploadByteCount = 0 let uploadByteCount = 0
const maxConcurrency = getConcurrency() const maxBuffers = 5
const bufferSize = getUploadChunkSize() const bufferSize = getUploadChunkSize()
const blobClient = new BlobClient(authenticatedUploadURL) const blobClient = new BlobClient(authenticatedUploadURL)
const blockBlobClient = blobClient.getBlockBlobClient() const blockBlobClient = blobClient.getBlockBlobClient()
core.debug( core.debug(
`Uploading artifact zip to blob storage with maxConcurrency: ${maxConcurrency}, bufferSize: ${bufferSize}` `Uploading artifact zip to blob storage with maxBuffers: ${maxBuffers}, bufferSize: ${bufferSize}`
) )
const uploadCallback = (progress: TransferProgressEvent): void => { const uploadCallback = (progress: TransferProgressEvent): void => {
@@ -48,9 +48,9 @@ export async function uploadZipToBlobStorage(
onProgress: uploadCallback onProgress: uploadCallback
} }
let sha256Hash: string | undefined = undefined let md5Hash: string | undefined = undefined
const uploadStream = new stream.PassThrough() const uploadStream = new stream.PassThrough()
const hashStream = crypto.createHash('sha256') const hashStream = crypto.createHash('md5')
zipUploadStream.pipe(uploadStream) // This stream is used for the upload zipUploadStream.pipe(uploadStream) // This stream is used for the upload
zipUploadStream.pipe(hashStream).setEncoding('hex') // This stream is used to compute a hash of the zip content that gets used. Integrity check zipUploadStream.pipe(hashStream).setEncoding('hex') // This stream is used to compute a hash of the zip content that gets used. Integrity check
@@ -61,15 +61,15 @@ export async function uploadZipToBlobStorage(
await blockBlobClient.uploadStream( await blockBlobClient.uploadStream(
uploadStream, uploadStream,
bufferSize, bufferSize,
maxConcurrency, maxBuffers,
options options
) )
core.info('Finished uploading artifact content to blob storage!') core.info('Finished uploading artifact content to blob storage!')
hashStream.end() hashStream.end()
sha256Hash = hashStream.read() as string md5Hash = hashStream.read() as string
core.info(`SHA256 hash of uploaded artifact zip is ${sha256Hash}`) core.info(`MD5 hash of uploaded artifact zip is ${md5Hash}`)
} catch (error) { } catch (error) {
core.warning( core.warning(
`Failed to upload artifact zip to blob storage, error: ${error}` `Failed to upload artifact zip to blob storage, error: ${error}`
@@ -91,6 +91,6 @@ export async function uploadZipToBlobStorage(
return { return {
isSuccess: true, isSuccess: true,
uploadSize: uploadByteCount, uploadSize: uploadByteCount,
sha256Hash md5Hash
} }
} }
@@ -2,7 +2,7 @@ import * as core from '@actions/core'
import {UploadOptions, UploadResponse} from '../shared/interfaces' import {UploadOptions, UploadResponse} from '../shared/interfaces'
import {getExpiration} from './retention' import {getExpiration} from './retention'
import {validateArtifactName} from './path-and-artifact-name-validation' import {validateArtifactName} from './path-and-artifact-name-validation'
import {internalArtifactTwirpClient} from '../shared/artifact-twirp-client' import {createArtifactTwirpClient} from '../shared/artifact-twirp-client'
import { import {
UploadZipSpecification, UploadZipSpecification,
getUploadZipSpecification, getUploadZipSpecification,
@@ -37,16 +37,25 @@ export async function uploadArtifact(
} }
} }
const zipUploadStream = await createZipUploadStream( const zipUploadStream = await createZipUploadStream(zipSpecification)
zipSpecification,
options?.compressionLevel
)
// get the IDs needed for the artifact creation // get the IDs needed for the artifact creation
const backendIds = getBackendIdsFromToken() const backendIds = getBackendIdsFromToken()
if (!backendIds.workflowRunBackendId || !backendIds.workflowJobRunBackendId) {
core.warning(
`Failed to get the necessary backend ids which are required to create the artifact`
)
return {
success: false
}
}
core.debug(`Workflow Run Backend ID: ${backendIds.workflowRunBackendId}`)
core.debug(
`Workflow Job Run Backend ID: ${backendIds.workflowJobRunBackendId}`
)
// create the artifact client // create the artifact client
const artifactClient = internalArtifactTwirpClient() const artifactClient = createArtifactTwirpClient('upload')
// create the artifact // create the artifact
const createArtifactReq: CreateArtifactRequest = { const createArtifactReq: CreateArtifactRequest = {
@@ -90,9 +99,9 @@ export async function uploadArtifact(
size: uploadResult.uploadSize ? uploadResult.uploadSize.toString() : '0' size: uploadResult.uploadSize ? uploadResult.uploadSize.toString() : '0'
} }
if (uploadResult.sha256Hash) { if (uploadResult.md5Hash) {
finalizeArtifactReq.hash = StringValue.create({ finalizeArtifactReq.hash = StringValue.create({
value: `sha256:${uploadResult.sha256Hash}` value: `md5:${uploadResult.md5Hash}`
}) })
} }
+6 -10
View File
@@ -5,8 +5,6 @@ import {createReadStream} from 'fs'
import {UploadZipSpecification} from './upload-zip-specification' import {UploadZipSpecification} from './upload-zip-specification'
import {getUploadChunkSize} from '../shared/config' import {getUploadChunkSize} from '../shared/config'
export const DEFAULT_COMPRESSION_LEVEL = 6
// Custom stream transformer so we can set the highWaterMark property // Custom stream transformer so we can set the highWaterMark property
// See https://github.com/nodejs/node/issues/8855 // See https://github.com/nodejs/node/issues/8855
export class ZipUploadStream extends stream.Transform { export class ZipUploadStream extends stream.Transform {
@@ -23,16 +21,14 @@ export class ZipUploadStream extends stream.Transform {
} }
export async function createZipUploadStream( export async function createZipUploadStream(
uploadSpecification: UploadZipSpecification[], uploadSpecification: UploadZipSpecification[]
compressionLevel: number = DEFAULT_COMPRESSION_LEVEL
): Promise<ZipUploadStream> { ): Promise<ZipUploadStream> {
core.debug(
`Creating Artifact archive with compressionLevel: ${compressionLevel}`
)
const zip = archiver.create('zip', { const zip = archiver.create('zip', {
highWaterMark: getUploadChunkSize(), zlib: {level: 9} // Sets the compression level.
zlib: {level: compressionLevel} // Available options are 0-9
// 0 => no compression
// 1 => fastest with low compression
// 9 => highest compression ratio but the slowest
}) })
// register callbacks for various events during the zip lifecycle // register callbacks for various events during the zip lifecycle
-25
View File
@@ -333,28 +333,3 @@ toPlatformPath('/foo/bar') // => \foo\bar
// On a Linux runner. // On a Linux runner.
toPlatformPath('\\foo\\bar') // => /foo/bar toPlatformPath('\\foo\\bar') // => /foo/bar
``` ```
#### Platform helper
Provides shorthands for getting information about platform action is running on.
```js
import { platform } from '@actions/core'
/* equals to a call of os.platform() */
platform.platform // 'win32' | 'darwin' | 'linux' | 'freebsd' | 'openbsd' | 'android' | 'cygwin' | 'sunos'
/* equals to a call of os.arch() */
platform.arch // 'x64' | 'arm' | 'arm64' | 'ia32' | 'mips' | 'mipsel' | 'ppc' | 'ppc64' | 'riscv64' | 's390' | 's390x'
/* common shorthands for platform-specific logic */
platform.isWindows // true
platform.isMacOS // false
platform.isLinux // false
/* run platform-specific script to get more details about the exact platform, works on Windows, MacOS and Linux */
const {
name, // Microsoft Windows 11 Enterprise
version, // 10.0.22621
} = await platform.getDetails()
```
-29
View File
@@ -1,29 +0,0 @@
import os from 'os'
import {platform} from '../src/core'
describe('getInfo', () => {
it('returns the platform info', async () => {
const info = await platform.getDetails()
expect(info).toEqual({
name: expect.any(String),
platform: expect.any(String),
arch: expect.any(String),
version: expect.any(String),
isWindows: expect.any(Boolean),
isMacOS: expect.any(Boolean),
isLinux: expect.any(Boolean)
})
})
it('returns the platform info with the correct name', async () => {
const isWindows = os.platform() === 'win32'
const isMacOS = os.platform() === 'darwin'
const isLinux = os.platform() === 'linux'
const info = await platform.getDetails()
expect(info.platform).toEqual(os.platform())
expect(info.isWindows).toEqual(isWindows)
expect(info.isMacOS).toEqual(isMacOS)
expect(info.isLinux).toEqual(isLinux)
})
})
-27
View File
@@ -9,7 +9,6 @@
"version": "1.10.1", "version": "1.10.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/exec": "^1.1.1",
"@actions/http-client": "^2.0.1", "@actions/http-client": "^2.0.1",
"uuid": "^8.3.2" "uuid": "^8.3.2"
}, },
@@ -18,14 +17,6 @@
"@types/uuid": "^8.3.4" "@types/uuid": "^8.3.4"
} }
}, },
"node_modules/@actions/exec": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
"dependencies": {
"@actions/io": "^1.0.1"
}
},
"node_modules/@actions/http-client": { "node_modules/@actions/http-client": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.0.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.0.tgz",
@@ -34,11 +25,6 @@
"tunnel": "^0.0.6" "tunnel": "^0.0.6"
} }
}, },
"node_modules/@actions/io": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "12.0.2", "version": "12.0.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.2.tgz",
@@ -69,14 +55,6 @@
} }
}, },
"dependencies": { "dependencies": {
"@actions/exec": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
"requires": {
"@actions/io": "^1.0.1"
}
},
"@actions/http-client": { "@actions/http-client": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.0.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.0.tgz",
@@ -85,11 +63,6 @@
"tunnel": "^0.0.6" "tunnel": "^0.0.6"
} }
}, },
"@actions/io": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
},
"@types/node": { "@types/node": {
"version": "12.0.2", "version": "12.0.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.2.tgz",
-1
View File
@@ -36,7 +36,6 @@
"url": "https://github.com/actions/toolkit/issues" "url": "https://github.com/actions/toolkit/issues"
}, },
"dependencies": { "dependencies": {
"@actions/exec": "^1.1.1",
"@actions/http-client": "^2.0.1", "@actions/http-client": "^2.0.1",
"uuid": "^8.3.2" "uuid": "^8.3.2"
}, },
-5
View File
@@ -386,8 +386,3 @@ export {markdownSummary} from './summary'
* Path exports * Path exports
*/ */
export {toPosixPath, toWin32Path, toPlatformPath} from './path-utils' export {toPosixPath, toWin32Path, toPlatformPath} from './path-utils'
/**
* Platform utilities exports
*/
export * as platform from './platform'
-87
View File
@@ -1,87 +0,0 @@
import os from 'os'
import * as exec from '@actions/exec'
const getWindowsInfo = async (): Promise<{name: string; version: string}> => {
const {stdout: version} = await exec.getExecOutput(
'powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"',
undefined,
{
silent: true
}
)
const {stdout: name} = await exec.getExecOutput(
'powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"',
undefined,
{
silent: true
}
)
return {
name: name.trim(),
version: version.trim()
}
}
const getMacOsInfo = async (): Promise<{
name: string
version: string
}> => {
const {stdout} = await exec.getExecOutput('sw_vers', undefined, {
silent: true
})
const version = stdout.match(/ProductVersion:\s*(.+)/)?.[1] ?? ''
const name = stdout.match(/ProductName:\s*(.+)/)?.[1] ?? ''
return {
name,
version
}
}
const getLinuxInfo = async (): Promise<{
name: string
version: string
}> => {
const {stdout} = await exec.getExecOutput('lsb_release', ['-i', '-r', '-s'], {
silent: true
})
const [name, version] = stdout.trim().split('\n')
return {
name,
version
}
}
export const platform = os.platform()
export const arch = os.arch()
export const isWindows = platform === 'win32'
export const isMacOS = platform === 'darwin'
export const isLinux = platform === 'linux'
export async function getDetails(): Promise<{
name: string
platform: string
arch: string
version: string
isWindows: boolean
isMacOS: boolean
isLinux: boolean
}> {
return {
...(await (isWindows
? getWindowsInfo()
: isMacOS
? getMacOsInfo()
: getLinuxInfo())),
platform,
arch,
isWindows,
isMacOS,
isLinux
}
}
-4
View File
@@ -1,9 +1,5 @@
# @actions/github Releases # @actions/github Releases
### 6.0.0
- Support the latest Octokit in @actions/github [#1553](https://github.com/actions/toolkit/pull/1553)
- Drop support of NodeJS v14, v16
### 5.1.1 ### 5.1.1
- Export default octokit options [#1188](https://github.com/actions/toolkit/pull/1188) - Export default octokit options [#1188](https://github.com/actions/toolkit/pull/1188)
+14 -1
View File
@@ -1,6 +1,7 @@
import * as http from 'http' import * as http from 'http'
import * as https from 'https' import * as https from 'https'
import {createProxy} from 'proxy' import { ProxyServer, createProxy } from "proxy";
import { ProxyAgent, fetch as undiciFetch } from "undici";
// Default values are set when the module is imported, so we need to set proxy first. // Default values are set when the module is imported, so we need to set proxy first.
const proxyUrl = 'http://127.0.0.1:8081' const proxyUrl = 'http://127.0.0.1:8081'
@@ -49,6 +50,7 @@ describe('@actions/github', () => {
} }
const octokit = getOctokit(token) const octokit = getOctokit(token)
const branch = await octokit.rest.repos.getBranch({ const branch = await octokit.rest.repos.getBranch({
owner: 'actions', owner: 'actions',
repo: 'toolkit', repo: 'toolkit',
@@ -64,6 +66,17 @@ describe('@actions/github', () => {
return return
} }
process.env['https_proxy'] = proxyUrl process.env['https_proxy'] = proxyUrl
// const myFetch: typeof undiciFetch = (url, opts) => {
// return undiciFetch(url, {
// ...opts,
// dispatcher: new ProxyAgent({
// uri: proxyUrl,
// keepAliveTimeout: 10,
// keepAliveMaxTimeout: 10,
// }),
// });
// };
const octokit = getOctokit(token) const octokit = getOctokit(token)
const repository = await octokit.graphql( const repository = await octokit.graphql(
+5
View File
@@ -0,0 +1,5 @@
declare module 'proxy' {
import * as http from 'http'
function internal(): http.Server
export = internal
}
+290 -138
View File
@@ -1,158 +1,182 @@
{ {
"name": "@actions/github", "name": "@actions/github",
"version": "6.0.0", "version": "5.1.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@actions/github", "name": "@actions/github",
"version": "6.0.0", "version": "5.1.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/http-client": "^2.2.0", "@actions/http-client": "file:../http-client/actions-http-client-3.0.0.tgz",
"@octokit/core": "^5.0.1", "@octokit/core": "^4.2.4",
"@octokit/plugin-paginate-rest": "^9.0.0", "@octokit/plugin-paginate-rest": "^6.1.2",
"@octokit/plugin-rest-endpoint-methods": "^10.0.0" "@octokit/plugin-rest-endpoint-methods": "^7.2.3"
}, },
"devDependencies": { "devDependencies": {
"proxy": "^2.1.1" "@types/proxy": "^1.0.1",
"proxy": "^2.1.1",
"undici": "^5.25.2"
} }
}, },
"node_modules/@actions/http-client": { "node_modules/@actions/http-client": {
"version": "2.2.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz", "resolved": "file:../http-client/actions-http-client-3.0.0.tgz",
"integrity": "sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==", "integrity": "sha512-HiloxFqJ4f0Z34H7pcqYcYb+UK+CqUKJmNY245AITh9HyJMvLz9wCrb5J+UWO6S63klrJBnzYBguTNUYrbCNrQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"tunnel": "^0.0.6", "tunnel": "^0.0.6"
"undici": "^5.25.4"
} }
}, },
"node_modules/@fastify/busboy": { "node_modules/@octokit/auth-token": {
"version": "2.0.0", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz",
"integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==", "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==",
"engines": { "engines": {
"node": ">= 14" "node": ">= 14"
} }
}, },
"node_modules/@octokit/auth-token": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/core": { "node_modules/@octokit/core": {
"version": "5.0.1", "version": "4.2.4",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.1.tgz", "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz",
"integrity": "sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==", "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==",
"dependencies": { "dependencies": {
"@octokit/auth-token": "^4.0.0", "@octokit/auth-token": "^3.0.0",
"@octokit/graphql": "^7.0.0", "@octokit/graphql": "^5.0.0",
"@octokit/request": "^8.0.2", "@octokit/request": "^6.0.0",
"@octokit/request-error": "^5.0.0", "@octokit/request-error": "^3.0.0",
"@octokit/types": "^12.0.0", "@octokit/types": "^9.0.0",
"before-after-hook": "^2.2.0", "before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0" "universal-user-agent": "^6.0.0"
}, },
"engines": { "engines": {
"node": ">= 18" "node": ">= 14"
} }
}, },
"node_modules/@octokit/endpoint": { "node_modules/@octokit/endpoint": {
"version": "9.0.1", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.1.tgz", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz",
"integrity": "sha512-hRlOKAovtINHQPYHZlfyFwaM8OyetxeoC81lAkBy34uLb8exrZB50SQdeW3EROqiY9G9yxQTpp5OHTV54QD+vA==", "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==",
"dependencies": { "dependencies": {
"@octokit/types": "^12.0.0", "@octokit/types": "^9.0.0",
"is-plain-object": "^5.0.0", "is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0" "universal-user-agent": "^6.0.0"
}, },
"engines": { "engines": {
"node": ">= 18" "node": ">= 14"
} }
}, },
"node_modules/@octokit/graphql": { "node_modules/@octokit/graphql": {
"version": "7.0.2", "version": "5.0.6",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz", "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz",
"integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==", "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==",
"dependencies": { "dependencies": {
"@octokit/request": "^8.0.1", "@octokit/request": "^6.0.0",
"@octokit/types": "^12.0.0", "@octokit/types": "^9.0.0",
"universal-user-agent": "^6.0.0" "universal-user-agent": "^6.0.0"
}, },
"engines": { "engines": {
"node": ">= 18" "node": ">= 14"
} }
}, },
"node_modules/@octokit/openapi-types": { "node_modules/@octokit/openapi-types": {
"version": "19.0.0", "version": "18.1.1",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.1.1.tgz",
"integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==" "integrity": "sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw=="
}, },
"node_modules/@octokit/plugin-paginate-rest": { "node_modules/@octokit/plugin-paginate-rest": {
"version": "9.0.0", "version": "6.1.2",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz",
"integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==",
"dependencies": { "dependencies": {
"@octokit/types": "^12.0.0" "@octokit/tsconfig": "^1.0.2",
"@octokit/types": "^9.2.3"
}, },
"engines": { "engines": {
"node": ">= 18" "node": ">= 14"
}, },
"peerDependencies": { "peerDependencies": {
"@octokit/core": ">=5" "@octokit/core": ">=4"
} }
}, },
"node_modules/@octokit/plugin-rest-endpoint-methods": { "node_modules/@octokit/plugin-rest-endpoint-methods": {
"version": "10.0.0", "version": "7.2.3",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz",
"integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==",
"dependencies": { "dependencies": {
"@octokit/types": "^12.0.0" "@octokit/types": "^10.0.0"
}, },
"engines": { "engines": {
"node": ">= 18" "node": ">= 14"
}, },
"peerDependencies": { "peerDependencies": {
"@octokit/core": ">=5" "@octokit/core": ">=3"
}
},
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-10.0.0.tgz",
"integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==",
"dependencies": {
"@octokit/openapi-types": "^18.0.0"
} }
}, },
"node_modules/@octokit/request": { "node_modules/@octokit/request": {
"version": "8.1.4", "version": "6.2.8",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.4.tgz", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz",
"integrity": "sha512-M0aaFfpGPEKrg7XoA/gwgRvc9MSXHRO2Ioki1qrPDbl1e9YhjIwVoHE7HIKmv/m3idzldj//xBujcFNqGX6ENA==", "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==",
"dependencies": { "dependencies": {
"@octokit/endpoint": "^9.0.0", "@octokit/endpoint": "^7.0.0",
"@octokit/request-error": "^5.0.0", "@octokit/request-error": "^3.0.0",
"@octokit/types": "^12.0.0", "@octokit/types": "^9.0.0",
"is-plain-object": "^5.0.0", "is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"universal-user-agent": "^6.0.0" "universal-user-agent": "^6.0.0"
}, },
"engines": { "engines": {
"node": ">= 18" "node": ">= 14"
} }
}, },
"node_modules/@octokit/request-error": { "node_modules/@octokit/request-error": {
"version": "5.0.1", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz", "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz",
"integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==", "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==",
"dependencies": { "dependencies": {
"@octokit/types": "^12.0.0", "@octokit/types": "^9.0.0",
"deprecation": "^2.0.0", "deprecation": "^2.0.0",
"once": "^1.4.0" "once": "^1.4.0"
}, },
"engines": { "engines": {
"node": ">= 18" "node": ">= 14"
} }
}, },
"node_modules/@octokit/tsconfig": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz",
"integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA=="
},
"node_modules/@octokit/types": { "node_modules/@octokit/types": {
"version": "12.0.0", "version": "9.3.2",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz",
"integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==",
"dependencies": { "dependencies": {
"@octokit/openapi-types": "^19.0.0" "@octokit/openapi-types": "^18.0.0"
}
},
"node_modules/@types/node": {
"version": "20.7.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz",
"integrity": "sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==",
"dev": true
},
"node_modules/@types/proxy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/proxy/-/proxy-1.0.2.tgz",
"integrity": "sha512-NDNsg7YuClVzEenn9SUButu43blypWvljGsIkDV7HI4N9apjrS0aeeMTUG0PYa71lD1AvIgvjkBagqHDiomDjA==",
"dev": true,
"dependencies": {
"@types/node": "*"
} }
}, },
"node_modules/ansi-styles": { "node_modules/ansi-styles": {
@@ -193,6 +217,18 @@
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.1.tgz", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.1.tgz",
"integrity": "sha512-/6FKxSTWoJdbsLDF8tdIjaRiFXiE6UHsEHE3OPI/cwPURCVi1ukP0gmLn7XWEiFk5TcwQjjY5PWsU+j+tgXgmw==" "integrity": "sha512-/6FKxSTWoJdbsLDF8tdIjaRiFXiE6UHsEHE3OPI/cwPURCVi1ukP0gmLn7XWEiFk5TcwQjjY5PWsU+j+tgXgmw=="
}, },
"node_modules/busboy": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
"dev": true,
"dependencies": {
"streamsearch": "^1.1.0"
},
"engines": {
"node": ">=10.16.0"
}
},
"node_modules/camelcase": { "node_modules/camelcase": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
@@ -303,6 +339,25 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true "dev": true
}, },
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/once": { "node_modules/once": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -325,6 +380,15 @@
"node": ">= 14" "node": ">= 14"
} }
}, },
"node_modules/streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
"dev": true,
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -337,6 +401,11 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/tunnel": { "node_modules/tunnel": {
"version": "0.0.6", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
@@ -346,11 +415,12 @@
} }
}, },
"node_modules/undici": { "node_modules/undici": {
"version": "5.25.4", "version": "5.25.2",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.25.4.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-5.25.2.tgz",
"integrity": "sha512-450yJxT29qKMf3aoudzFpIciqpx6Pji3hEWaXqXmanbXF58LTAGCKxcJjxMXWu3iG+Mudgo3ZUfDB6YDFd/dAw==", "integrity": "sha512-tch8RbCfn1UUH1PeVCXva4V8gDpGAud/w0WubD6sHC46vYQ3KDxL+xv1A2UxK0N6jrVedutuPHxe1XIoqerwMw==",
"dev": true,
"dependencies": { "dependencies": {
"@fastify/busboy": "^2.0.0" "busboy": "^1.6.0"
}, },
"engines": { "engines": {
"node": ">=14.0" "node": ">=14.0"
@@ -361,6 +431,20 @@
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
}, },
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/wrappy": { "node_modules/wrappy": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -369,107 +453,132 @@
}, },
"dependencies": { "dependencies": {
"@actions/http-client": { "@actions/http-client": {
"version": "2.2.0", "version": "file:../http-client/actions-http-client-3.0.0.tgz",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz", "integrity": "sha512-HiloxFqJ4f0Z34H7pcqYcYb+UK+CqUKJmNY245AITh9HyJMvLz9wCrb5J+UWO6S63klrJBnzYBguTNUYrbCNrQ==",
"integrity": "sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==",
"requires": { "requires": {
"tunnel": "^0.0.6", "tunnel": "^0.0.6"
"undici": "^5.25.4"
} }
}, },
"@fastify/busboy": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
"integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ=="
},
"@octokit/auth-token": { "@octokit/auth-token": {
"version": "4.0.0", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz",
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==" "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ=="
}, },
"@octokit/core": { "@octokit/core": {
"version": "5.0.1", "version": "4.2.4",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.1.tgz", "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz",
"integrity": "sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==", "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==",
"requires": { "requires": {
"@octokit/auth-token": "^4.0.0", "@octokit/auth-token": "^3.0.0",
"@octokit/graphql": "^7.0.0", "@octokit/graphql": "^5.0.0",
"@octokit/request": "^8.0.2", "@octokit/request": "^6.0.0",
"@octokit/request-error": "^5.0.0", "@octokit/request-error": "^3.0.0",
"@octokit/types": "^12.0.0", "@octokit/types": "^9.0.0",
"before-after-hook": "^2.2.0", "before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0" "universal-user-agent": "^6.0.0"
} }
}, },
"@octokit/endpoint": { "@octokit/endpoint": {
"version": "9.0.1", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.1.tgz", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz",
"integrity": "sha512-hRlOKAovtINHQPYHZlfyFwaM8OyetxeoC81lAkBy34uLb8exrZB50SQdeW3EROqiY9G9yxQTpp5OHTV54QD+vA==", "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==",
"requires": { "requires": {
"@octokit/types": "^12.0.0", "@octokit/types": "^9.0.0",
"is-plain-object": "^5.0.0", "is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0" "universal-user-agent": "^6.0.0"
} }
}, },
"@octokit/graphql": { "@octokit/graphql": {
"version": "7.0.2", "version": "5.0.6",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz", "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz",
"integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==", "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==",
"requires": { "requires": {
"@octokit/request": "^8.0.1", "@octokit/request": "^6.0.0",
"@octokit/types": "^12.0.0", "@octokit/types": "^9.0.0",
"universal-user-agent": "^6.0.0" "universal-user-agent": "^6.0.0"
} }
}, },
"@octokit/openapi-types": { "@octokit/openapi-types": {
"version": "19.0.0", "version": "18.1.1",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.1.1.tgz",
"integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==" "integrity": "sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw=="
}, },
"@octokit/plugin-paginate-rest": { "@octokit/plugin-paginate-rest": {
"version": "9.0.0", "version": "6.1.2",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz",
"integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==",
"requires": { "requires": {
"@octokit/types": "^12.0.0" "@octokit/tsconfig": "^1.0.2",
"@octokit/types": "^9.2.3"
} }
}, },
"@octokit/plugin-rest-endpoint-methods": { "@octokit/plugin-rest-endpoint-methods": {
"version": "10.0.0", "version": "7.2.3",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz",
"integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==",
"requires": { "requires": {
"@octokit/types": "^12.0.0" "@octokit/types": "^10.0.0"
},
"dependencies": {
"@octokit/types": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-10.0.0.tgz",
"integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==",
"requires": {
"@octokit/openapi-types": "^18.0.0"
}
}
} }
}, },
"@octokit/request": { "@octokit/request": {
"version": "8.1.4", "version": "6.2.8",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.4.tgz", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz",
"integrity": "sha512-M0aaFfpGPEKrg7XoA/gwgRvc9MSXHRO2Ioki1qrPDbl1e9YhjIwVoHE7HIKmv/m3idzldj//xBujcFNqGX6ENA==", "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==",
"requires": { "requires": {
"@octokit/endpoint": "^9.0.0", "@octokit/endpoint": "^7.0.0",
"@octokit/request-error": "^5.0.0", "@octokit/request-error": "^3.0.0",
"@octokit/types": "^12.0.0", "@octokit/types": "^9.0.0",
"is-plain-object": "^5.0.0", "is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"universal-user-agent": "^6.0.0" "universal-user-agent": "^6.0.0"
} }
}, },
"@octokit/request-error": { "@octokit/request-error": {
"version": "5.0.1", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz", "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz",
"integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==", "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==",
"requires": { "requires": {
"@octokit/types": "^12.0.0", "@octokit/types": "^9.0.0",
"deprecation": "^2.0.0", "deprecation": "^2.0.0",
"once": "^1.4.0" "once": "^1.4.0"
} }
}, },
"@octokit/tsconfig": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz",
"integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA=="
},
"@octokit/types": { "@octokit/types": {
"version": "12.0.0", "version": "9.3.2",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz",
"integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==",
"requires": { "requires": {
"@octokit/openapi-types": "^19.0.0" "@octokit/openapi-types": "^18.0.0"
}
},
"@types/node": {
"version": "20.7.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz",
"integrity": "sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==",
"dev": true
},
"@types/proxy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/proxy/-/proxy-1.0.2.tgz",
"integrity": "sha512-NDNsg7YuClVzEenn9SUButu43blypWvljGsIkDV7HI4N9apjrS0aeeMTUG0PYa71lD1AvIgvjkBagqHDiomDjA==",
"dev": true,
"requires": {
"@types/node": "*"
} }
}, },
"ansi-styles": { "ansi-styles": {
@@ -504,6 +613,15 @@
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.1.tgz", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.1.tgz",
"integrity": "sha512-/6FKxSTWoJdbsLDF8tdIjaRiFXiE6UHsEHE3OPI/cwPURCVi1ukP0gmLn7XWEiFk5TcwQjjY5PWsU+j+tgXgmw==" "integrity": "sha512-/6FKxSTWoJdbsLDF8tdIjaRiFXiE6UHsEHE3OPI/cwPURCVi1ukP0gmLn7XWEiFk5TcwQjjY5PWsU+j+tgXgmw=="
}, },
"busboy": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
"dev": true,
"requires": {
"streamsearch": "^1.1.0"
}
},
"camelcase": { "camelcase": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
@@ -585,6 +703,14 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true "dev": true
}, },
"node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"requires": {
"whatwg-url": "^5.0.0"
}
},
"once": { "once": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -604,6 +730,12 @@
"debug": "^4.3.4" "debug": "^4.3.4"
} }
}, },
"streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
"dev": true
},
"supports-color": { "supports-color": {
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -613,17 +745,23 @@
"has-flag": "^3.0.0" "has-flag": "^3.0.0"
} }
}, },
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"tunnel": { "tunnel": {
"version": "0.0.6", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
}, },
"undici": { "undici": {
"version": "5.25.4", "version": "5.25.2",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.25.4.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-5.25.2.tgz",
"integrity": "sha512-450yJxT29qKMf3aoudzFpIciqpx6Pji3hEWaXqXmanbXF58LTAGCKxcJjxMXWu3iG+Mudgo3ZUfDB6YDFd/dAw==", "integrity": "sha512-tch8RbCfn1UUH1PeVCXva4V8gDpGAud/w0WubD6sHC46vYQ3KDxL+xv1A2UxK0N6jrVedutuPHxe1XIoqerwMw==",
"dev": true,
"requires": { "requires": {
"@fastify/busboy": "^2.0.0" "busboy": "^1.6.0"
} }
}, },
"universal-user-agent": { "universal-user-agent": {
@@ -631,6 +769,20 @@
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
}, },
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+8 -6
View File
@@ -1,6 +1,6 @@
{ {
"name": "@actions/github", "name": "@actions/github",
"version": "6.0.0", "version": "5.1.1",
"description": "Actions github lib", "description": "Actions github lib",
"keywords": [ "keywords": [
"github", "github",
@@ -38,12 +38,14 @@
"url": "https://github.com/actions/toolkit/issues" "url": "https://github.com/actions/toolkit/issues"
}, },
"dependencies": { "dependencies": {
"@actions/http-client": "^2.2.0", "@actions/http-client": "file:../http-client/actions-http-client-3.0.0.tgz",
"@octokit/core": "^5.0.1", "@octokit/core": "^4.2.4",
"@octokit/plugin-paginate-rest": "^9.0.0", "@octokit/plugin-paginate-rest": "^6.1.2",
"@octokit/plugin-rest-endpoint-methods": "^10.0.0" "@octokit/plugin-rest-endpoint-methods": "^7.2.3"
}, },
"devDependencies": { "devDependencies": {
"proxy": "^2.1.1" "@types/proxy": "^1.0.1",
"proxy": "^2.1.1",
"undici": "^5.25.2"
} }
} }
-2
View File
@@ -16,7 +16,6 @@ export class Context {
action: string action: string
actor: string actor: string
job: string job: string
runAttempt: number
runNumber: number runNumber: number
runId: number runId: number
apiUrl: string apiUrl: string
@@ -45,7 +44,6 @@ export class Context {
this.action = process.env.GITHUB_ACTION as string this.action = process.env.GITHUB_ACTION as string
this.actor = process.env.GITHUB_ACTOR as string this.actor = process.env.GITHUB_ACTOR as string
this.job = process.env.GITHUB_JOB as string this.job = process.env.GITHUB_JOB as string
this.runAttempt = parseInt(process.env.GITHUB_RUN_ATTEMPT as string, 10)
this.runNumber = parseInt(process.env.GITHUB_RUN_NUMBER as string, 10) this.runNumber = parseInt(process.env.GITHUB_RUN_NUMBER as string, 10)
this.runId = parseInt(process.env.GITHUB_RUN_ID as string, 10) this.runId = parseInt(process.env.GITHUB_RUN_ID as string, 10)
this.apiUrl = process.env.GITHUB_API_URL ?? `https://api.github.com` this.apiUrl = process.env.GITHUB_API_URL ?? `https://api.github.com`
+12 -13
View File
@@ -1,7 +1,8 @@
import * as http from 'http' import * as http from 'http'
import * as httpClient from '@actions/http-client' import * as httpClient from '@actions/http-client'
import {OctokitOptions} from '@octokit/core/dist-types/types' import {OctokitOptions} from '@octokit/core/dist-types/types'
import {ProxyAgent, fetch} from 'undici' import { ProxyServer, createProxy } from "proxy";
import { ProxyAgent, Agent, fetch as undiciFetch } from "undici";
export function getAuthString( export function getAuthString(
token: string, token: string,
@@ -21,22 +22,20 @@ export function getProxyAgent(destinationUrl: string): http.Agent {
return hc.getAgent(destinationUrl) return hc.getAgent(destinationUrl)
} }
export function getProxyAgentDispatcher( export function getNewProxyAgent(destinationUrl: string): ProxyAgent | Agent {
destinationUrl: string
): ProxyAgent | undefined {
const hc = new httpClient.HttpClient() const hc = new httpClient.HttpClient()
return hc.getAgentDispatcher(destinationUrl) return hc.getNewAgent(destinationUrl)
} }
export function getProxyFetch(destinationUrl): typeof fetch { export function getProxyFetchAgent(destinationUrl): any {
const httpDispatcher = getProxyAgentDispatcher(destinationUrl) const httpAgent = getNewProxyAgent(destinationUrl)
const proxyFetch: typeof fetch = async (url, opts) => { const myFetch: typeof undiciFetch = (url, opts) => {
return fetch(url, { return undiciFetch(url, {
...opts, ...opts,
dispatcher: httpDispatcher dispatcher: httpAgent,
}) });
} };
return proxyFetch return myFetch;
} }
export function getApiBaseUrl(): string { export function getApiBaseUrl(): string {
+1 -2
View File
@@ -13,8 +13,7 @@ const baseUrl = Utils.getApiBaseUrl()
export const defaults: OctokitOptions = { export const defaults: OctokitOptions = {
baseUrl, baseUrl,
request: { request: {
agent: Utils.getProxyAgent(baseUrl), fetch: Utils.getProxyFetchAgent(baseUrl)
fetch: Utils.getProxyFetch(baseUrl)
} }
} }
-3
View File
@@ -1,8 +1,5 @@
## Releases ## Releases
## 2.2.0
- Add function to return proxy agent dispatcher for compatibility with latest octokit packages [#1547](https://github.com/actions/toolkit/pull/1547)
## 2.1.1 ## 2.1.1
- Add `HttpClientResponse.readBodyBuffer` method to read from a response stream and return a buffer [#1475](https://github.com/actions/toolkit/pull/1475) - Add `HttpClientResponse.readBodyBuffer` method to read from a response stream and return a buffer [#1475](https://github.com/actions/toolkit/pull/1475)
+1 -11
View File
@@ -3,7 +3,6 @@
import * as http from 'http' import * as http from 'http'
import * as httpm from '../lib/' import * as httpm from '../lib/'
import * as pm from '../lib/proxy' import * as pm from '../lib/proxy'
import {ProxyAgent} from 'undici'
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
const proxy = require('proxy') const proxy = require('proxy')
@@ -14,7 +13,7 @@ const _proxyUrl = 'http://127.0.0.1:8080'
describe('proxy', () => { describe('proxy', () => {
beforeAll(async () => { beforeAll(async () => {
// Start proxy server // Start proxy server
_proxyServer = proxy.createProxy() _proxyServer = proxy()
await new Promise<void>(resolve => { await new Promise<void>(resolve => {
const port = Number(_proxyUrl.split(':')[2]) const port = Number(_proxyUrl.split(':')[2])
_proxyServer.listen(port, () => resolve()) _proxyServer.listen(port, () => resolve())
@@ -295,15 +294,6 @@ describe('proxy', () => {
expect(agent.proxyOptions.port).toBe('8080') expect(agent.proxyOptions.port).toBe('8080')
expect(agent.proxyOptions.proxyAuth).toBe('user:password') expect(agent.proxyOptions.proxyAuth).toBe('user:password')
}) })
it('ProxyAgent is returned when proxy setting are provided', async () => {
process.env['https_proxy'] = 'http://127.0.0.1:8080'
const httpClient = new httpm.HttpClient()
const agent = httpClient.getAgentDispatcher('https://some-url')
// eslint-disable-next-line no-console
console.log(agent)
expect(agent instanceof ProxyAgent).toBe(true)
})
}) })
function _clearVars(): void { function _clearVars(): void {
Binary file not shown.
+53 -28
View File
@@ -1,30 +1,22 @@
{ {
"name": "@actions/http-client", "name": "@actions/http-client",
"version": "2.2.0", "version": "3.0.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@actions/http-client", "name": "@actions/http-client",
"version": "2.2.0", "version": "3.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tunnel": "^0.0.6", "tunnel": "^0.0.6"
"undici": "^5.25.4"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "20.7.1", "@types/node": "^20.7.1",
"@types/proxy": "^1.0.1", "@types/proxy": "^1.0.2",
"@types/tunnel": "0.0.3", "@types/tunnel": "0.0.3",
"proxy": "^2.1.1" "proxy": "^2.1.1",
} "undici": "^5.25.2"
},
"node_modules/@fastify/busboy": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
"integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==",
"engines": {
"node": ">=14"
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
@@ -84,6 +76,18 @@
"integrity": "sha512-GFj8iVxo9onSU6BnnQvVwqvxh60UcSHJEDnIk3z4B6iOjsKSmqe+ibW0Rsz7YO7IE1HG3D3tqCNIidP46SZVdQ==", "integrity": "sha512-GFj8iVxo9onSU6BnnQvVwqvxh60UcSHJEDnIk3z4B6iOjsKSmqe+ibW0Rsz7YO7IE1HG3D3tqCNIidP46SZVdQ==",
"dev": true "dev": true
}, },
"node_modules/busboy": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
"dev": true,
"dependencies": {
"streamsearch": "^1.1.0"
},
"engines": {
"node": ">=10.16.0"
}
},
"node_modules/camelcase": { "node_modules/camelcase": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
@@ -195,6 +199,15 @@
"node": ">= 14" "node": ">= 14"
} }
}, },
"node_modules/streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
"dev": true,
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -216,11 +229,12 @@
} }
}, },
"node_modules/undici": { "node_modules/undici": {
"version": "5.25.4", "version": "5.25.2",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.25.4.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-5.25.2.tgz",
"integrity": "sha512-450yJxT29qKMf3aoudzFpIciqpx6Pji3hEWaXqXmanbXF58LTAGCKxcJjxMXWu3iG+Mudgo3ZUfDB6YDFd/dAw==", "integrity": "sha512-tch8RbCfn1UUH1PeVCXva4V8gDpGAud/w0WubD6sHC46vYQ3KDxL+xv1A2UxK0N6jrVedutuPHxe1XIoqerwMw==",
"dev": true,
"dependencies": { "dependencies": {
"@fastify/busboy": "^2.0.0" "busboy": "^1.6.0"
}, },
"engines": { "engines": {
"node": ">=14.0" "node": ">=14.0"
@@ -228,11 +242,6 @@
} }
}, },
"dependencies": { "dependencies": {
"@fastify/busboy": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
"integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ=="
},
"@types/node": { "@types/node": {
"version": "20.7.1", "version": "20.7.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz",
@@ -284,6 +293,15 @@
"integrity": "sha512-GFj8iVxo9onSU6BnnQvVwqvxh60UcSHJEDnIk3z4B6iOjsKSmqe+ibW0Rsz7YO7IE1HG3D3tqCNIidP46SZVdQ==", "integrity": "sha512-GFj8iVxo9onSU6BnnQvVwqvxh60UcSHJEDnIk3z4B6iOjsKSmqe+ibW0Rsz7YO7IE1HG3D3tqCNIidP46SZVdQ==",
"dev": true "dev": true
}, },
"busboy": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
"dev": true,
"requires": {
"streamsearch": "^1.1.0"
}
},
"camelcase": { "camelcase": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
@@ -366,6 +384,12 @@
"debug": "^4.3.4" "debug": "^4.3.4"
} }
}, },
"streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
"dev": true
},
"supports-color": { "supports-color": {
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -381,11 +405,12 @@
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
}, },
"undici": { "undici": {
"version": "5.25.4", "version": "5.25.2",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.25.4.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-5.25.2.tgz",
"integrity": "sha512-450yJxT29qKMf3aoudzFpIciqpx6Pji3hEWaXqXmanbXF58LTAGCKxcJjxMXWu3iG+Mudgo3ZUfDB6YDFd/dAw==", "integrity": "sha512-tch8RbCfn1UUH1PeVCXva4V8gDpGAud/w0WubD6sHC46vYQ3KDxL+xv1A2UxK0N6jrVedutuPHxe1XIoqerwMw==",
"dev": true,
"requires": { "requires": {
"@fastify/busboy": "^2.0.0" "busboy": "^1.6.0"
} }
} }
} }
+5 -5
View File
@@ -1,6 +1,6 @@
{ {
"name": "@actions/http-client", "name": "@actions/http-client",
"version": "2.2.0", "version": "3.0.0",
"description": "Actions Http Client", "description": "Actions Http Client",
"keywords": [ "keywords": [
"github", "github",
@@ -39,13 +39,13 @@
"url": "https://github.com/actions/toolkit/issues" "url": "https://github.com/actions/toolkit/issues"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "20.7.1", "@types/node": "^20.7.1",
"@types/proxy": "^1.0.2",
"@types/tunnel": "0.0.3", "@types/tunnel": "0.0.3",
"proxy": "^2.1.1", "proxy": "^2.1.1",
"@types/proxy": "^1.0.1" "undici": "^5.25.2"
}, },
"dependencies": { "dependencies": {
"tunnel": "^0.0.6", "tunnel": "^0.0.6"
"undici": "^5.25.4"
} }
} }
+69 -13
View File
@@ -6,7 +6,7 @@ import * as ifm from './interfaces'
import * as net from 'net' import * as net from 'net'
import * as pm from './proxy' import * as pm from './proxy'
import * as tunnel from 'tunnel' import * as tunnel from 'tunnel'
import {ProxyAgent} from 'undici' import { ProxyAgent, Agent, fetch as undiciFetch } from "undici";
export enum HttpCodes { export enum HttpCodes {
OK = 200, OK = 200,
@@ -137,8 +137,9 @@ export class HttpClient {
private _allowRetries = false private _allowRetries = false
private _maxRetries = 1 private _maxRetries = 1
private _agent: any private _agent: any
private _newAgent: any
private _proxyAgent: any private _proxyAgent: any
private _proxyAgentDispatcher: any private _newProxyAgent: any
private _keepAlive = false private _keepAlive = false
private _disposed = false private _disposed = false
@@ -566,15 +567,16 @@ export class HttpClient {
return this._getAgent(parsedUrl) return this._getAgent(parsedUrl)
} }
getAgentDispatcher(serverUrl: string): ProxyAgent | undefined { getNewAgent(serverUrl: string): ProxyAgent | Agent {
const parsedUrl = new URL(serverUrl) const parsedUrl = new URL(serverUrl)
const proxyUrl = pm.getProxyUrl(parsedUrl) const proxyUrl = pm.getProxyUrl(parsedUrl)
const useProxy = proxyUrl && proxyUrl.hostname const useProxy = proxyUrl && proxyUrl.hostname
if (!useProxy) { if (useProxy) {
return return this._getProxyAgent(parsedUrl)
}
else {
return this._getNewAgent(parsedUrl)
} }
return this._getProxyAgentDispatcher(parsedUrl, proxyUrl)
} }
private _prepareRequest( private _prepareRequest(
@@ -714,11 +716,17 @@ export class HttpClient {
return agent return agent
} }
private _getProxyAgentDispatcher(parsedUrl: URL, proxyUrl: URL): ProxyAgent { private _getProxyAgent(parsedUrl: URL): ProxyAgent {
let proxyAgent let proxyAgent
const proxyUrl = pm.getProxyUrl(parsedUrl)
const useProxy = proxyUrl && proxyUrl.hostname
if (this._keepAlive) { if (this._keepAlive && useProxy) {
proxyAgent = this._proxyAgentDispatcher proxyAgent = this._newProxyAgent
}
if (this._keepAlive && !useProxy) {
proxyAgent = this._newAgent
} }
// if agent is already assigned use that agent. // if agent is already assigned use that agent.
@@ -727,14 +735,22 @@ export class HttpClient {
} }
const usingSsl = parsedUrl.protocol === 'https:' const usingSsl = parsedUrl.protocol === 'https:'
let maxSockets = 100
if (this.requestOptions) {
maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets
}
// This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis.
if (proxyUrl && proxyUrl.hostname) {
proxyAgent = new ProxyAgent({ proxyAgent = new ProxyAgent({
uri: proxyUrl.href, uri: proxyUrl.href,
pipelining: !this._keepAlive ? 0 : 1, pipelining: (!this._keepAlive ? 0 : 1),
...((proxyUrl.username || proxyUrl.password) && { ...((proxyUrl.username || proxyUrl.password) && {
token: `${proxyUrl.username}:${proxyUrl.password}` token: `${proxyUrl.username}:${proxyUrl.password}`
}),
}) })
}) this._newProxyAgent = proxyAgent
this._proxyAgentDispatcher = proxyAgent }
if (usingSsl && this._ignoreSslError) { if (usingSsl && this._ignoreSslError) {
// we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process
@@ -748,6 +764,46 @@ export class HttpClient {
return proxyAgent return proxyAgent
} }
private _getNewAgent(parsedUrl: URL): Agent {
let agent;
if (this._keepAlive) {
agent = this._newAgent
}
// if agent is already assigned use that agent.
if (agent) {
return agent
}
const usingSsl = parsedUrl.protocol === 'https:'
let maxSockets = 100
if (this.requestOptions) {
maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets
}
// if reusing agent across request and tunneling agent isn't assigned create a new agent
if (this._keepAlive && !agent) {
agent = new Agent(
{
pipelining: (!this._keepAlive ? 0 : 1),
}
)
this._newAgent = agent
}
if (usingSsl && this._ignoreSslError) {
// we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process
// http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options
// we have to cast it to any and change it directly
agent.options = Object.assign(agent.options.connect || {}, {
rejectUnauthorized: false
})
}
return agent
}
private async _performExponentialBackoff(retryNumber: number): Promise<void> { private async _performExponentialBackoff(retryNumber: number): Promise<void> {
retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber) retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber)
const ms: number = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber) const ms: number = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber)
+9 -16
View File
@@ -93,20 +93,13 @@
} }
}, },
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.4", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"ms": "2.1.2" "ms": "^2.1.1"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
} }
}, },
"node_modules/json-stringify-safe": { "node_modules/json-stringify-safe": {
@@ -246,12 +239,12 @@
} }
}, },
"debug": { "debug": {
"version": "4.3.4", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true, "dev": true,
"requires": { "requires": {
"ms": "2.1.2" "ms": "^2.1.1"
} }
}, },
"json-stringify-safe": { "json-stringify-safe": {