mirror of
				https://github.com/actions/download-artifact.git
				synced 2025-10-31 16:23:41 +00: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