Skip to content

Commit

Permalink
validate inputs (#123)
Browse files Browse the repository at this point in the history
* validate inputs
* document job_matrix field
* document `artifacts` in action.yml
  • Loading branch information
michaelglass authored Oct 14, 2022
1 parent 086dd06 commit a645684
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 30 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ tokens [here](https://www.rwx.com/captain/docs/api-tokens).
# - junit_xml
# - rspec_json
# - xunit_dot_net_xml

artifacts: |
[
{
Expand Down
15 changes: 14 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ branding:
inputs:
artifacts:
required: true
description: |
this is a json array of objects with fields...
- name: how the artifact will be shown in captain
- path: path to test result. This field supports bash globbing (e.g. **/*).
- kind: for now, this should always be "test_results"
- parser: one of
- cypress_junit_xml
- jest_json
- junit_xml
- rspec_json
- xunit_dot_net_xml
if-files-not-found:
required: false
default: warn
Expand All @@ -23,9 +34,11 @@ inputs:
This is required if you set the `name` property on your job.
If you provided a name, set that same value here.
job-matrix:
required: true
required: false

captain-token:
required: true

captain-base-url:
required: false
default: https://captain.build
Expand Down
60 changes: 47 additions & 13 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

27 changes: 25 additions & 2 deletions src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ import {
updateBulkArtifactsStatus,
BulkArtifactStatus
} from './api/captain'
import {getInputs, mimeTypeFromExtension, InputArtifact} from './utils'
import {
getInputs,
mimeTypeFromExtension,
InputArtifact,
Invalid,
Valid
} from './utils'

type Artifact = InputArtifact & {
mime_type: BulkArtifactMimeType
Expand All @@ -21,7 +27,24 @@ type Artifact = InputArtifact & {

export default async function run(): Promise<void> {
try {
const inputs = getInputs()
const validatedInputs = getInputs()

if ((validatedInputs as Invalid).errors) {
const errors = (validatedInputs as Invalid).errors
for (const error of errors) {
core.warning(error)
}
core.warning(
[
"Captain Uploader Action is misconfigured and can't upload test results.",
'Please address error(s) above in the GitHub workflow and try again.',
'These warnings will be errors in version 2'
].join('\n')
)
return
}

const inputs = validatedInputs as Valid
const artifacts: Artifact[] = inputs.artifacts
.flatMap(artifact => {
const expandedGlob = fastGlob.sync(artifact.path)
Expand Down
58 changes: 58 additions & 0 deletions src/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,5 +195,63 @@ describe('Utils', () => {
captainToken: 'fake-token'
})
})

it('leaves an error when artifacts are unparsable', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(core.getInput as jest.Mock<any>).mockImplementation(input => {
if (input === 'artifacts') {
return '[{"]'
} else if (input === 'captain-token') {
return 'fake-token'
}
})

expect(getInputs()).toEqual({
errors: ["`artifacts` field isn't valid JSON."]
})
})

it('leaves an error when artifacts is empty', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(core.getInput as jest.Mock<any>).mockImplementation(input => {
if (input === 'artifacts') {
return '[]'
} else if (input === 'captain-token') {
return 'fake-token'
}
})

expect(getInputs()).toEqual({
errors: [
'You must include at least one artifact in the `artifacts` field.'
]
})
})

it('leaves an error when captain_token is missing', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(core.getInput as jest.Mock<any>).mockImplementation(input => {
if (input === 'artifacts') {
return '[{"kind": "test_results", "name": "Some Name", "path": "some_path.json"}]'
}
})

expect(getInputs()).toEqual({
errors: ["`captain_token` field can't be empty."]
})

// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(core.getInput as jest.Mock<any>).mockImplementation(input => {
if (input === 'artifacts') {
return '[{"kind": "test_results", "name": "Some Name", "path": "some_path.json"}]'
} else if (input === 'captain-token') {
return ''
}
})

expect(getInputs()).toEqual({
errors: ["`captain_token` field can't be empty."]
})
})
})
})
55 changes: 43 additions & 12 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,49 @@ function runAttempt(): number {
return parseInt(githubRunAttempt)
}

export function getInputs(): Inputs {
export type Valid = Inputs
export type Invalid = {errors: string[]}
export type ValidatedInputs = Valid | Invalid

export function getInputs(): ValidatedInputs {
const matrix = core.getInput('job-matrix')
return {
accountName: github.context.repo.owner,
artifacts: JSON.parse(core.getInput('artifacts')) as InputArtifact[],
ifFilesNotFound: parseIfFilesNotFound(core.getInput('if-files-not-found')),
jobMatrix: matrix ? JSON.parse(matrix) : null,
jobName: core.getInput('job-name') || github.context.job,
repositoryName: github.context.repo.repo,
runId: github.context.runId.toString(),
runAttempt: runAttempt(),
captainBaseUrl: core.getInput('captain-base-url'),
captainToken: core.getInput('captain-token')
const errors = []
let artifacts: InputArtifact[]

try {
artifacts = JSON.parse(core.getInput('artifacts')) as InputArtifact[]
if (artifacts.length === 0) {
errors.push(
'You must include at least one artifact in the `artifacts` field.'
)
}
} catch (e) {
errors.push("`artifacts` field isn't valid JSON.")
artifacts = []
}

const captainToken = core.getInput('captain-token')

if (!captainToken || captainToken.trim().length === 0) {
errors.push("`captain_token` field can't be empty.")
}

if (errors.length !== 0) {
return {errors}
} else {
return {
accountName: github.context.repo.owner,
ifFilesNotFound: parseIfFilesNotFound(
core.getInput('if-files-not-found')
),
jobMatrix: matrix ? JSON.parse(matrix) : null,
jobName: core.getInput('job-name') || github.context.job,
repositoryName: github.context.repo.repo,
runId: github.context.runId.toString(),
runAttempt: runAttempt(),
captainBaseUrl: core.getInput('captain-base-url'),
artifacts,
captainToken
}
}
}

0 comments on commit a645684

Please sign in to comment.