mirror of
https://github.com/actions/download-artifact.git
synced 2025-04-03 01:20:12 +08:00
Lint
This commit is contained in:
parent
96a6f165f4
commit
9a869e9c49
@ -1,19 +1,8 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as github from '@actions/github'
|
|
||||||
import * as os from 'os'
|
|
||||||
import artifact, {ArtifactNotFoundError} from '@actions/artifact'
|
import artifact, {ArtifactNotFoundError} from '@actions/artifact'
|
||||||
import {run} from '../src/download-artifact'
|
import {run} from '../src/download-artifact'
|
||||||
import {Inputs} from '../src/constants'
|
import {Inputs} from '../src/constants'
|
||||||
|
|
||||||
const fixtures = {
|
|
||||||
artifactName: 'artifact-name',
|
|
||||||
rootDirectory: '/some/artifact/path',
|
|
||||||
filesToUpload: [
|
|
||||||
'/some/artifact/path/file1.txt',
|
|
||||||
'/some/artifact/path/file2.txt'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
jest.mock('@actions/github', () => ({
|
jest.mock('@actions/github', () => ({
|
||||||
context: {
|
context: {
|
||||||
repo: {
|
repo: {
|
||||||
@ -27,7 +16,7 @@ jest.mock('@actions/github', () => ({
|
|||||||
|
|
||||||
jest.mock('@actions/core')
|
jest.mock('@actions/core')
|
||||||
|
|
||||||
/* eslint-disable no-unused-vars */
|
/* eslint-disable no-unused-vars */ /* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
const mockInputs = (overrides?: Partial<{[K in Inputs]?: any}>) => {
|
const mockInputs = (overrides?: Partial<{[K in Inputs]?: any}>) => {
|
||||||
const inputs = {
|
const inputs = {
|
||||||
[Inputs.Name]: 'artifact-name',
|
[Inputs.Name]: 'artifact-name',
|
||||||
@ -50,177 +39,177 @@ const mockInputs = (overrides?: Partial<{[K in Inputs]?: any}>) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('download', () => {
|
describe('download', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockInputs()
|
mockInputs()
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
|
|
||||||
// Mock artifact client methods
|
// Mock artifact client methods
|
||||||
jest.spyOn(artifact, 'listArtifacts').mockImplementation(() =>
|
jest
|
||||||
Promise.resolve({ artifacts: [] })
|
.spyOn(artifact, 'listArtifacts')
|
||||||
)
|
.mockImplementation(() => Promise.resolve({artifacts: []}))
|
||||||
jest.spyOn(artifact, 'getArtifact').mockImplementation((name) => {
|
jest.spyOn(artifact, 'getArtifact').mockImplementation(name => {
|
||||||
throw new ArtifactNotFoundError(`Artifact '${name}' not found`)
|
throw new ArtifactNotFoundError(`Artifact '${name}' not found`)
|
||||||
|
})
|
||||||
|
jest
|
||||||
|
.spyOn(artifact, 'downloadArtifact')
|
||||||
|
.mockImplementation(() => Promise.resolve({digestMismatch: false}))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('downloads a single artifact by name', async () => {
|
||||||
|
const mockArtifact = {
|
||||||
|
id: 123,
|
||||||
|
name: 'artifact-name',
|
||||||
|
size: 1024,
|
||||||
|
digest: 'abc123'
|
||||||
|
}
|
||||||
|
|
||||||
|
jest
|
||||||
|
.spyOn(artifact, 'getArtifact')
|
||||||
|
.mockImplementation(() => Promise.resolve({artifact: mockArtifact}))
|
||||||
|
|
||||||
|
await run()
|
||||||
|
|
||||||
|
expect(artifact.downloadArtifact).toHaveBeenCalledWith(
|
||||||
|
mockArtifact.id,
|
||||||
|
expect.objectContaining({
|
||||||
|
expectedHash: mockArtifact.digest
|
||||||
})
|
})
|
||||||
jest.spyOn(artifact, 'downloadArtifact').mockImplementation(() =>
|
)
|
||||||
Promise.resolve({ digestMismatch: false })
|
expect(core.info).toHaveBeenCalledWith('Total of 1 artifact(s) downloaded')
|
||||||
)
|
})
|
||||||
|
|
||||||
|
test('downloads multiple artifacts when no name or pattern provided', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
mockInputs({
|
||||||
|
[Inputs.Name]: '',
|
||||||
|
[Inputs.Pattern]: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
test('downloads a single artifact by name', async () => {
|
const mockArtifacts = [
|
||||||
const mockArtifact = {
|
{id: 123, name: 'artifact1', size: 1024, digest: 'abc123'},
|
||||||
id: 123,
|
{id: 456, name: 'artifact2', size: 2048, digest: 'def456'}
|
||||||
name: 'artifact-name',
|
]
|
||||||
size: 1024,
|
|
||||||
digest: 'abc123'
|
// Set up artifact mock after clearing mocks
|
||||||
}
|
jest
|
||||||
|
.spyOn(artifact, 'listArtifacts')
|
||||||
jest.spyOn(artifact, 'getArtifact').mockImplementation(() =>
|
.mockImplementation(() => Promise.resolve({artifacts: mockArtifacts}))
|
||||||
Promise.resolve({ artifact: mockArtifact })
|
|
||||||
)
|
// Reset downloadArtifact mock as well
|
||||||
|
jest
|
||||||
await run()
|
.spyOn(artifact, 'downloadArtifact')
|
||||||
|
.mockImplementation(() => Promise.resolve({digestMismatch: false}))
|
||||||
expect(artifact.downloadArtifact).toHaveBeenCalledWith(
|
|
||||||
mockArtifact.id,
|
await run()
|
||||||
expect.objectContaining({
|
|
||||||
expectedHash: mockArtifact.digest
|
expect(core.info).toHaveBeenCalledWith(
|
||||||
})
|
'No input name or pattern filtered specified, downloading all artifacts'
|
||||||
)
|
)
|
||||||
expect(core.info).toHaveBeenCalledWith('Total of 1 artifact(s) downloaded')
|
|
||||||
|
expect(core.info).toHaveBeenCalledWith('Total of 2 artifact(s) downloaded')
|
||||||
|
expect(artifact.downloadArtifact).toHaveBeenCalledTimes(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('sets download path output even when no artifacts are found', async () => {
|
||||||
|
mockInputs({[Inputs.Name]: ''})
|
||||||
|
|
||||||
|
await run()
|
||||||
|
|
||||||
|
expect(core.setOutput).toHaveBeenCalledWith(
|
||||||
|
'download-path',
|
||||||
|
expect.any(String)
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(core.info).toHaveBeenCalledWith(
|
||||||
|
'Download artifact has finished successfully'
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(core.info).toHaveBeenCalledWith('Total of 0 artifact(s) downloaded')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('filters artifacts by pattern', async () => {
|
||||||
|
const mockArtifacts = [
|
||||||
|
{id: 123, name: 'test-artifact', size: 1024, digest: 'abc123'},
|
||||||
|
{id: 456, name: 'prod-artifact', size: 2048, digest: 'def456'}
|
||||||
|
]
|
||||||
|
|
||||||
|
jest
|
||||||
|
.spyOn(artifact, 'listArtifacts')
|
||||||
|
.mockImplementation(() => Promise.resolve({artifacts: mockArtifacts}))
|
||||||
|
|
||||||
|
mockInputs({
|
||||||
|
[Inputs.Name]: '',
|
||||||
|
[Inputs.Pattern]: 'test-*'
|
||||||
})
|
})
|
||||||
|
|
||||||
test('downloads multiple artifacts when no name or pattern provided', async () => {
|
await run()
|
||||||
jest.clearAllMocks()
|
|
||||||
mockInputs({
|
expect(artifact.downloadArtifact).toHaveBeenCalledTimes(1)
|
||||||
[Inputs.Name]: '',
|
expect(artifact.downloadArtifact).toHaveBeenCalledWith(
|
||||||
[Inputs.Pattern]: ''
|
123,
|
||||||
|
expect.anything()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('uses token and repository information when provided', async () => {
|
||||||
|
const token = 'ghp_testtoken123'
|
||||||
|
|
||||||
|
mockInputs({
|
||||||
|
[Inputs.Name]: '',
|
||||||
|
[Inputs.GitHubToken]: token,
|
||||||
|
[Inputs.Repository]: 'myorg/myrepo',
|
||||||
|
[Inputs.RunID]: '789'
|
||||||
|
})
|
||||||
|
|
||||||
|
jest
|
||||||
|
.spyOn(artifact, 'listArtifacts')
|
||||||
|
.mockImplementation(() => Promise.resolve({artifacts: []}))
|
||||||
|
|
||||||
|
await run()
|
||||||
|
|
||||||
|
expect(artifact.listArtifacts).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
findBy: {
|
||||||
|
token,
|
||||||
|
workflowRunId: 789,
|
||||||
|
repositoryName: 'myrepo',
|
||||||
|
repositoryOwner: 'myorg'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
)
|
||||||
const mockArtifacts = [
|
})
|
||||||
{ id: 123, name: 'artifact1', size: 1024, digest: 'abc123' },
|
|
||||||
{ id: 456, name: 'artifact2', size: 2048, digest: 'def456' }
|
|
||||||
]
|
|
||||||
|
|
||||||
// Set up artifact mock after clearing mocks
|
|
||||||
jest.spyOn(artifact, 'listArtifacts').mockImplementation(() =>
|
|
||||||
Promise.resolve({ artifacts: mockArtifacts })
|
|
||||||
)
|
|
||||||
|
|
||||||
// Reset downloadArtifact mock as well
|
|
||||||
jest.spyOn(artifact, 'downloadArtifact').mockImplementation(() =>
|
|
||||||
Promise.resolve({ digestMismatch: false })
|
|
||||||
)
|
|
||||||
|
|
||||||
await run()
|
|
||||||
|
|
||||||
expect(core.info).toHaveBeenCalledWith('No input name or pattern filtered specified, downloading all artifacts')
|
test('throws error when repository format is invalid', async () => {
|
||||||
|
mockInputs({
|
||||||
expect(core.info).toHaveBeenCalledWith('Total of 2 artifact(s) downloaded')
|
[Inputs.GitHubToken]: 'some-token',
|
||||||
expect(artifact.downloadArtifact).toHaveBeenCalledTimes(2)
|
[Inputs.Repository]: 'invalid-format' // Missing the owner/repo format
|
||||||
})
|
|
||||||
|
|
||||||
test('sets download path output even when no artifacts are found', async () => {
|
|
||||||
mockInputs({ [Inputs.Name]: '' })
|
|
||||||
|
|
||||||
await run()
|
|
||||||
|
|
||||||
expect(core.setOutput).toHaveBeenCalledWith(
|
|
||||||
'download-path',
|
|
||||||
expect.any(String)
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(core.info).toHaveBeenCalledWith(
|
|
||||||
'Download artifact has finished successfully'
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(core.info).toHaveBeenCalledWith(
|
|
||||||
'Total of 0 artifact(s) downloaded'
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('filters artifacts by pattern', async () => {
|
await expect(run()).rejects.toThrow(
|
||||||
const mockArtifacts = [
|
"Invalid repository: 'invalid-format'. Must be in format owner/repo"
|
||||||
{ id: 123, name: 'test-artifact', size: 1024, digest: 'abc123' },
|
)
|
||||||
{ id: 456, name: 'prod-artifact', size: 2048, digest: 'def456' }
|
})
|
||||||
]
|
|
||||||
|
|
||||||
jest.spyOn(artifact, 'listArtifacts').mockImplementation(() =>
|
|
||||||
Promise.resolve({ artifacts: mockArtifacts })
|
|
||||||
)
|
|
||||||
|
|
||||||
mockInputs({
|
|
||||||
[Inputs.Name]: '',
|
|
||||||
[Inputs.Pattern]: 'test-*'
|
|
||||||
})
|
|
||||||
|
|
||||||
await run()
|
|
||||||
|
|
||||||
expect(artifact.downloadArtifact).toHaveBeenCalledTimes(1)
|
|
||||||
expect(artifact.downloadArtifact).toHaveBeenCalledWith(
|
|
||||||
123,
|
|
||||||
expect.anything()
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
test('uses token and repository information when provided', async () => {
|
test('warns when digest validation fails', async () => {
|
||||||
const token = 'ghp_testtoken123'
|
const mockArtifact = {
|
||||||
|
id: 123,
|
||||||
mockInputs({
|
name: 'corrupted-artifact',
|
||||||
[Inputs.Name]: '',
|
size: 1024,
|
||||||
[Inputs.GitHubToken]: token,
|
digest: 'abc123'
|
||||||
[Inputs.Repository]: 'myorg/myrepo',
|
}
|
||||||
[Inputs.RunID]: '789'
|
|
||||||
})
|
|
||||||
|
|
||||||
jest.spyOn(artifact, 'listArtifacts').mockImplementation(() =>
|
|
||||||
Promise.resolve({ artifacts: [] })
|
|
||||||
)
|
|
||||||
|
|
||||||
await run()
|
|
||||||
|
|
||||||
expect(artifact.listArtifacts).toHaveBeenCalledWith(
|
|
||||||
expect.objectContaining({
|
|
||||||
findBy: {
|
|
||||||
token,
|
|
||||||
workflowRunId: 789,
|
|
||||||
repositoryName: 'myrepo',
|
|
||||||
repositoryOwner: 'myorg'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
test('throws error when repository format is invalid', async () => {
|
jest
|
||||||
mockInputs({
|
.spyOn(artifact, 'getArtifact')
|
||||||
[Inputs.GitHubToken]: 'some-token',
|
.mockImplementation(() => Promise.resolve({artifact: mockArtifact}))
|
||||||
[Inputs.Repository]: 'invalid-format' // Missing the owner/repo format
|
|
||||||
})
|
jest
|
||||||
|
.spyOn(artifact, 'downloadArtifact')
|
||||||
await expect(run()).rejects.toThrow(
|
.mockImplementation(() => Promise.resolve({digestMismatch: true}))
|
||||||
"Invalid repository: 'invalid-format'. Must be in format owner/repo"
|
|
||||||
)
|
await run()
|
||||||
})
|
|
||||||
|
expect(core.warning).toHaveBeenCalledWith(
|
||||||
test('warns when digest validation fails', async () => {
|
expect.stringContaining('digest validation failed')
|
||||||
const mockArtifact = {
|
)
|
||||||
id: 123,
|
})
|
||||||
name: 'corrupted-artifact',
|
})
|
||||||
size: 1024,
|
|
||||||
digest: 'abc123'
|
|
||||||
}
|
|
||||||
|
|
||||||
jest.spyOn(artifact, 'getArtifact').mockImplementation(() =>
|
|
||||||
Promise.resolve({ artifact: mockArtifact })
|
|
||||||
)
|
|
||||||
|
|
||||||
jest.spyOn(artifact, 'downloadArtifact').mockImplementation(() =>
|
|
||||||
Promise.resolve({ digestMismatch: true })
|
|
||||||
)
|
|
||||||
|
|
||||||
await run()
|
|
||||||
|
|
||||||
expect(core.warning).toHaveBeenCalledWith(
|
|
||||||
expect.stringContaining('digest validation failed')
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user