mirror of https://github.com/actions/toolkit
adding delayed response to message body http mock
parent
9d70b8a9fb
commit
67d2d582dc
|
@ -9,7 +9,8 @@ import archiver from 'archiver'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
downloadArtifactInternal,
|
downloadArtifactInternal,
|
||||||
downloadArtifactPublic
|
downloadArtifactPublic,
|
||||||
|
streamExtractExternal
|
||||||
} from '../src/internal/download/download-artifact'
|
} 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 {noopLogs} from './common'
|
||||||
|
@ -120,47 +121,6 @@ const mockGetArtifactFailure = jest.fn(() => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const mockDelayWritableResponse = jest.fn(async () => {
|
|
||||||
//const message = new stream.PassThrough()
|
|
||||||
const message = new http.IncomingMessage(new net.Socket())
|
|
||||||
message.statusCode = 200
|
|
||||||
message.push('Internal Server Error')
|
|
||||||
message.push(null)
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
message.emit('error', () => {})
|
|
||||||
}, 31000)
|
|
||||||
return {
|
|
||||||
message
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const mockDelayBlobResponse = jest.fn(async () => {
|
|
||||||
const message = new http.IncomingMessage(new net.Socket())
|
|
||||||
message.on('data', () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
message.statusCode = 200
|
|
||||||
message.push('OK')
|
|
||||||
message.push(null)
|
|
||||||
}, 31000)
|
|
||||||
})
|
|
||||||
// setTimeout(() => {
|
|
||||||
// setTimeout(() => {
|
|
||||||
// message.statusCode = 200
|
|
||||||
// message.push('OK')
|
|
||||||
// message.push(null)
|
|
||||||
// }, 31000)
|
|
||||||
// message.emit('data')
|
|
||||||
// }, 31000)
|
|
||||||
// message.on('done', () => {
|
|
||||||
// message.statusCode = 200
|
|
||||||
// message.push('OK')
|
|
||||||
// message.push(null)
|
|
||||||
// })
|
|
||||||
return {
|
|
||||||
message
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('download-artifact', () => {
|
describe('download-artifact', () => {
|
||||||
describe('public', () => {
|
describe('public', () => {
|
||||||
beforeEach(setup)
|
beforeEach(setup)
|
||||||
|
@ -290,62 +250,43 @@ describe('download-artifact', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should fail if blob storage storage chunk does not respond within 30s', async () => {
|
it('should fail if blob storage storage chunk does not respond within 30s', async () => {
|
||||||
// jest.useFakeTimers()
|
// mock http client to delay response data by 30s
|
||||||
|
//
|
||||||
|
const msg = new http.IncomingMessage(new net.Socket())
|
||||||
|
msg.statusCode = 200
|
||||||
|
|
||||||
const downloadArtifactMock = github.getOctokit(fixtures.token).rest
|
const mockGet = jest.fn(async () => {
|
||||||
.actions.downloadArtifact as MockedDownloadArtifact
|
return new Promise((resolve, reject) => {
|
||||||
downloadArtifactMock.mockResolvedValueOnce({
|
// Resolve with a 200 status code immediately
|
||||||
headers: {
|
resolve({
|
||||||
location: fixtures.blobStorageUrl
|
message: msg,
|
||||||
},
|
readBody: async () => {
|
||||||
status: 302,
|
return Promise.resolve(`{"ok": true}`)
|
||||||
url: '',
|
}
|
||||||
data: Buffer.from('')
|
})
|
||||||
|
|
||||||
|
// Reject with an error after 31 seconds
|
||||||
|
setTimeout(() => {
|
||||||
|
reject(new Error('Request timeout'))
|
||||||
|
}, 31000) // Timeout after 31 seconds
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const mockHttpClient = (HttpClient as jest.Mock).mockImplementation(
|
const mockHttpClient = (HttpClient as jest.Mock).mockImplementation(
|
||||||
() => {
|
() => {
|
||||||
return {
|
return {
|
||||||
get: mockDelayWritableResponse
|
get: mockGet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
try {
|
await expect(
|
||||||
await downloadArtifactPublic(
|
streamExtractExternal(fixtures.blobStorageUrl, fixtures.workspaceDir)
|
||||||
fixtures.artifactID,
|
).rejects.toBeInstanceOf(Error)
|
||||||
fixtures.repositoryOwner,
|
|
||||||
fixtures.repositoryName,
|
|
||||||
fixtures.token
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(
|
expect(mockHttpClient).toHaveBeenCalledWith(getUserAgentString())
|
||||||
downloadArtifactPublic(
|
}, 35000)
|
||||||
fixtures.artifactID,
|
|
||||||
fixtures.repositoryOwner,
|
|
||||||
fixtures.repositoryName,
|
|
||||||
fixtures.token
|
|
||||||
)
|
|
||||||
).rejects.toBeInstanceOf(Error)
|
|
||||||
|
|
||||||
expect(downloadArtifactMock).toHaveBeenCalledWith({
|
|
||||||
owner: fixtures.repositoryOwner,
|
|
||||||
repo: fixtures.repositoryName,
|
|
||||||
artifact_id: fixtures.artifactID,
|
|
||||||
archive_format: 'zip',
|
|
||||||
request: {
|
|
||||||
redirect: 'manual'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
expect(mockHttpClient).toHaveBeenCalledWith(getUserAgentString())
|
|
||||||
expect(mockGetArtifactFailure).toHaveBeenCalledWith(
|
|
||||||
fixtures.blobStorageUrl
|
|
||||||
)
|
|
||||||
expect(mockGetArtifactFailure).toHaveBeenCalledTimes(5)
|
|
||||||
} catch (err) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(err)
|
|
||||||
}
|
|
||||||
}, 40000)
|
|
||||||
it('should fail if blob storage response is non-200 after 5 retries', async () => {
|
it('should fail if blob storage response is non-200 after 5 retries', async () => {
|
||||||
const downloadArtifactMock = github.getOctokit(fixtures.token).rest
|
const downloadArtifactMock = github.getOctokit(fixtures.token).rest
|
||||||
.actions.downloadArtifact as MockedDownloadArtifact
|
.actions.downloadArtifact as MockedDownloadArtifact
|
||||||
|
|
|
@ -42,7 +42,7 @@ async function streamExtract(url: string, directory: string): Promise<void> {
|
||||||
let retryCount = 0
|
let retryCount = 0
|
||||||
while (retryCount < 5) {
|
while (retryCount < 5) {
|
||||||
try {
|
try {
|
||||||
await streamExtractInternal(url, directory)
|
await streamExtractExternal(url, directory)
|
||||||
core.info(`Artifact downloaded successfully after ${retryCount} retries.`)
|
core.info(`Artifact downloaded successfully after ${retryCount} retries.`)
|
||||||
return
|
return
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -58,7 +58,7 @@ async function streamExtract(url: string, directory: string): Promise<void> {
|
||||||
throw new Error(`Artifact download failed after ${retryCount} retries.`)
|
throw new Error(`Artifact download failed after ${retryCount} retries.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function streamExtractInternal(
|
export async function streamExtractExternal(
|
||||||
url: string,
|
url: string,
|
||||||
directory: string
|
directory: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
|
Loading…
Reference in New Issue