Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize upload code in prep for merge logic & add more tests #504

Merged
merged 3 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/check-dist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
run: npm ci

- name: Rebuild the dist/ directory
run: npm run build
run: npm run release
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: this was not working properly, the build npm script did not change the dist/ contents. I fixed it so it's properly calling release now to ncc the new js


- name: Compare the expected and actual dist/ directories
run: |
Expand Down
2 changes: 1 addition & 1 deletion __tests__/search.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as core from '@actions/core'
import * as path from 'path'
import * as io from '@actions/io'
import {promises as fs} from 'fs'
import {findFilesToUpload} from '../src/search'
import {findFilesToUpload} from '../src/shared/search'

const root = path.join(__dirname, '_temp', 'search')
const searchItem1Path = path.join(
Expand Down
231 changes: 231 additions & 0 deletions __tests__/upload.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
import * as core from '@actions/core'
import * as github from '@actions/github'
import artifact, {ArtifactNotFoundError} from '@actions/artifact'
import {run} from '../src/upload/upload-artifact'
import {Inputs} from '../src/upload/constants'
import * as search from '../src/shared/search'

const fixtures = {
artifactName: 'artifact-name',
rootDirectory: '/some/artifact/path',
filesToUpload: [
'/some/artifact/path/file1.txt',
'/some/artifact/path/file2.txt'
]
}

jest.mock('@actions/github', () => ({
context: {
repo: {
owner: 'actions',
repo: 'toolkit'
},
runId: 123,
serverUrl: 'https://github.com'
}
}))

jest.mock('@actions/core')

/* eslint-disable no-unused-vars */
const mockInputs = (overrides?: Partial<{[K in Inputs]?: any}>) => {
const inputs = {
[Inputs.Name]: 'artifact-name',
[Inputs.Path]: '/some/artifact/path',
[Inputs.IfNoFilesFound]: 'warn',
[Inputs.RetentionDays]: 0,
[Inputs.CompressionLevel]: 6,
[Inputs.Overwrite]: false,
...overrides
}

;(core.getInput as jest.Mock).mockImplementation((name: string) => {
return inputs[name]
})
;(core.getBooleanInput as jest.Mock).mockImplementation((name: string) => {
return inputs[name]
})

return inputs
}

describe('upload', () => {
beforeEach(async () => {
mockInputs()

jest.spyOn(search, 'findFilesToUpload').mockResolvedValue({
filesToUpload: fixtures.filesToUpload,
rootDirectory: fixtures.rootDirectory
})

jest.spyOn(artifact, 'uploadArtifact').mockResolvedValue({
size: 123,
id: 1337
})
})

it('uploads a single file', async () => {
jest.spyOn(search, 'findFilesToUpload').mockResolvedValue({
filesToUpload: [fixtures.filesToUpload[0]],
rootDirectory: fixtures.rootDirectory
})

await run()

expect(artifact.uploadArtifact).toHaveBeenCalledWith(
fixtures.artifactName,
[fixtures.filesToUpload[0]],
fixtures.rootDirectory,
{compressionLevel: 6}
)
})

it('uploads multiple files', async () => {
await run()

expect(artifact.uploadArtifact).toHaveBeenCalledWith(
fixtures.artifactName,
fixtures.filesToUpload,
fixtures.rootDirectory,
{compressionLevel: 6}
)
})

it('sets outputs', async () => {
await run()

expect(core.setOutput).toHaveBeenCalledWith('artifact-id', 1337)
expect(core.setOutput).toHaveBeenCalledWith(
'artifact-url',
`${github.context.serverUrl}/${github.context.repo.owner}/${
github.context.repo.repo
}/actions/runs/${github.context.runId}/artifacts/${1337}`
)
})

it('supports custom compression level', async () => {
mockInputs({
[Inputs.CompressionLevel]: 2
})

await run()

expect(artifact.uploadArtifact).toHaveBeenCalledWith(
fixtures.artifactName,
fixtures.filesToUpload,
fixtures.rootDirectory,
{compressionLevel: 2}
)
})

it('supports custom retention days', async () => {
mockInputs({
[Inputs.RetentionDays]: 7
})

await run()

expect(artifact.uploadArtifact).toHaveBeenCalledWith(
fixtures.artifactName,
fixtures.filesToUpload,
fixtures.rootDirectory,
{retentionDays: 7, compressionLevel: 6}
)
})

it('supports warn if-no-files-found', async () => {
mockInputs({
[Inputs.IfNoFilesFound]: 'warn'
})

jest.spyOn(search, 'findFilesToUpload').mockResolvedValue({
filesToUpload: [],
rootDirectory: fixtures.rootDirectory
})

await run()

expect(core.warning).toHaveBeenCalledWith(
`No files were found with the provided path: ${fixtures.rootDirectory}. No artifacts will be uploaded.`
)
})

it('supports error if-no-files-found', async () => {
mockInputs({
[Inputs.IfNoFilesFound]: 'error'
})

jest.spyOn(search, 'findFilesToUpload').mockResolvedValue({
filesToUpload: [],
rootDirectory: fixtures.rootDirectory
})

await run()

expect(core.setFailed).toHaveBeenCalledWith(
`No files were found with the provided path: ${fixtures.rootDirectory}. No artifacts will be uploaded.`
)
})

it('supports ignore if-no-files-found', async () => {
mockInputs({
[Inputs.IfNoFilesFound]: 'ignore'
})

jest.spyOn(search, 'findFilesToUpload').mockResolvedValue({
filesToUpload: [],
rootDirectory: fixtures.rootDirectory
})

await run()

expect(core.info).toHaveBeenCalledWith(
`No files were found with the provided path: ${fixtures.rootDirectory}. No artifacts will be uploaded.`
)
})

it('supports overwrite', async () => {
mockInputs({
[Inputs.Overwrite]: true
})

jest.spyOn(artifact, 'deleteArtifact').mockResolvedValue({
id: 1337
})

await run()

expect(artifact.uploadArtifact).toHaveBeenCalledWith(
fixtures.artifactName,
fixtures.filesToUpload,
fixtures.rootDirectory,
{compressionLevel: 6}
)

expect(artifact.deleteArtifact).toHaveBeenCalledWith(fixtures.artifactName)
})

it('supports overwrite and continues if not found', async () => {
mockInputs({
[Inputs.Overwrite]: true
})

jest
.spyOn(artifact, 'deleteArtifact')
.mockRejectedValue(new ArtifactNotFoundError('not found'))

await run()

expect(artifact.uploadArtifact).toHaveBeenCalledWith(
fixtures.artifactName,
fixtures.filesToUpload,
fixtures.rootDirectory,
{compressionLevel: 6}
)

expect(artifact.deleteArtifact).toHaveBeenCalledWith(fixtures.artifactName)
expect(core.debug).toHaveBeenCalledWith(
`Skipping deletion of '${fixtures.artifactName}', it does not exist`
)
})
})
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,4 @@ outputs:
Common uses cases for such a download URL can be adding download links to artifacts in descriptions or comments on pull requests or issues.
runs:
using: 'node20'
main: 'dist/index.js'
main: 'dist/upload/index.js'