5
0
Fork 0
mirror of https://github.com/wagoid/commitlint-github-action.git synced 2025-11-07 16:06:56 +00:00

Merge pull request #74 from wagoid/feat/add-command-execution-again

feat: add command execution again
This commit is contained in:
Wagner Santos 2021-02-07 07:26:00 -03:00 committed by GitHub
commit 51f76f12f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 165 additions and 41 deletions

View file

@ -62,6 +62,14 @@ You can see more info about GitHub's default token [here](https://docs.github.co
default: `${{ github.token }}` default: `${{ github.token }}`
## Outputs
### `results`
The error and warning messages for each one of the analyzed commits. This is useful if you want to use the commitlint results in a JSON format in other jobs. See [the documentation](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#fromjson) on how to read JSON information from outputs.
Below you can see an example text output together with its corresponding JSON output:
``` ```
You have commit messages with errors You have commit messages with errors

View file

@ -7,6 +7,7 @@ const lint = require('@commitlint/lint').default
const { format } = require('@commitlint/format') const { format } = require('@commitlint/format')
const load = require('@commitlint/load').default const load = require('@commitlint/load').default
const gitCommits = require('./gitCommits') const gitCommits = require('./gitCommits')
const generateOutputs = require('./generateOutputs')
const pullRequestEvent = 'pull_request' const pullRequestEvent = 'pull_request'
@ -108,9 +109,7 @@ const hasOnlyWarnings = lintedCommits =>
lintedCommits.some(({ lintResult }) => lintResult.warnings.length) lintedCommits.some(({ lintResult }) => lintResult.warnings.length)
const setFailed = formattedResults => { const setFailed = formattedResults => {
process.exitCode = 1 core.setFailed(`You have commit messages with errors\n\n${formattedResults}`)
console.error(`You have commit messages with errors\n\n${formattedResults}`)
} }
const handleOnlyWarnings = formattedResults => { const handleOnlyWarnings = formattedResults => {
@ -135,9 +134,7 @@ const showLintResults = async ([from, to]) => {
) )
const formattedResults = formatErrors(lintedCommits) const formattedResults = formatErrors(lintedCommits)
// disable workflow commands generateOutputs(lintedCommits)
const token = uuidv4()
console.log(`::stop-commands::${token}`)
if (hasOnlyWarnings(lintedCommits)) { if (hasOnlyWarnings(lintedCommits)) {
handleOnlyWarnings(formattedResults) handleOnlyWarnings(formattedResults)
@ -146,15 +143,10 @@ const showLintResults = async ([from, to]) => {
} else { } else {
console.log('Lint free! 🎉') console.log('Lint free! 🎉')
} }
// enable workflow commands
console.log(`::${token}::`)
} }
const exitWithMessage = message => error => { const exitWithMessage = message => error => {
process.exitCode = 1 core.setFailed(`${message}\n${error.message}\n${error.stack}`)
console.error(`${message}\n${error.message}\n${error.stack}`)
} }
const commitLinterAction = () => const commitLinterAction = () =>

View file

@ -11,6 +11,8 @@ const {
updatePullRequestEnvVars, updatePullRequestEnvVars,
} = require('./testUtils') } = require('./testUtils')
const resultsOutputId = 'results'
const { const {
matchers: { contains }, matchers: { contains },
} = td } = td
@ -42,8 +44,8 @@ describe('Commit Linter action', () => {
beforeEach(() => { beforeEach(() => {
core = require('@actions/core') core = require('@actions/core')
td.replace(core, 'getInput') td.replace(core, 'getInput')
td.replace(console, 'log') td.replace(core, 'setFailed')
td.replace(console, 'error') td.replace(core, 'setOutput')
td.when(core.getInput('configFile')).thenReturn('./commitlint.config.js') td.when(core.getInput('configFile')).thenReturn('./commitlint.config.js')
td.when(core.getInput('firstParent')).thenReturn('true') td.when(core.getInput('firstParent')).thenReturn('true')
td.when(core.getInput('failOnWarnings')).thenReturn('false') td.when(core.getInput('failOnWarnings')).thenReturn('false')
@ -69,8 +71,7 @@ describe('Commit Linter action', () => {
await runAction() await runAction()
td.verify(console.error(contains('You have commit messages with errors'))) td.verify(core.setFailed(contains('You have commit messages with errors')))
expect(process.exitCode).toBe(1)
}) })
it('should fail for single push with incorrect message', async () => { it('should fail for single push with incorrect message', async () => {
@ -83,7 +84,7 @@ describe('Commit Linter action', () => {
await runAction() await runAction()
td.verify(console.error(contains('You have commit messages with errors'))) td.verify(core.setFailed(contains('You have commit messages with errors')))
}) })
it('should fail for push range with wrong messages', async () => { it('should fail for push range with wrong messages', async () => {
@ -98,8 +99,8 @@ describe('Commit Linter action', () => {
await runAction() await runAction()
td.verify(console.error(contains('wrong message 1'))) td.verify(core.setFailed(contains('wrong message 1')))
td.verify(console.error(contains('wrong message 2'))) td.verify(core.setFailed(contains('wrong message 2')))
}) })
it('should pass for push range with correct messages', async () => { it('should pass for push range with correct messages', async () => {
@ -115,7 +116,7 @@ describe('Commit Linter action', () => {
await runAction() await runAction()
td.verify(console.error(), { times: 0, ignoreExtraArgs: true }) td.verify(core.setFailed(), { times: 0, ignoreExtraArgs: true })
td.verify(console.log('Lint free! 🎉')) td.verify(console.log('Lint free! 🎉'))
}) })
@ -137,8 +138,8 @@ describe('Commit Linter action', () => {
'Commit was forced, checking only the latest commit from push instead of a range of commit messages', 'Commit was forced, checking only the latest commit from push instead of a range of commit messages',
), ),
) )
td.verify(console.error(contains('wrong message 1')), { times: 0 }) td.verify(core.setFailed(contains('wrong message 1')), { times: 0 })
td.verify(console.error(contains('wrong message 2'))) td.verify(core.setFailed(contains('wrong message 2')))
}) })
it('should lint only last commit when "before" field is an empty sha', async () => { it('should lint only last commit when "before" field is an empty sha', async () => {
@ -154,8 +155,8 @@ describe('Commit Linter action', () => {
await runAction() await runAction()
td.verify(console.error(contains('wrong message 1')), { times: 0 }) td.verify(core.setFailed(contains('wrong message 1')), { times: 0 })
td.verify(console.error(contains('chore(WRONG): message 2'))) td.verify(core.setFailed(contains('chore(WRONG): message 2')))
}) })
it('should fail for commit with scope that is not a lerna package', async () => { it('should fail for commit with scope that is not a lerna package', async () => {
@ -170,7 +171,7 @@ describe('Commit Linter action', () => {
await runAction() await runAction()
td.verify( td.verify(
console.error(contains('chore(wrong): not including package scope')), core.setFailed(contains('chore(wrong): not including package scope')),
) )
}) })
@ -200,21 +201,23 @@ describe('Commit Linter action', () => {
await runAction() await runAction()
td.verify(console.error(contains('ib-21212121212121: without jira ticket')))
td.verify( td.verify(
console.error( core.setFailed(contains('ib-21212121212121: without jira ticket')),
)
td.verify(
core.setFailed(
contains( contains(
'ib-21212121212121 taskId must not be loonger than 9 characters', 'ib-21212121212121 taskId must not be loonger than 9 characters',
), ),
), ),
) )
td.verify( td.verify(
console.error( core.setFailed(
contains('ib-21212121212121 taskId must be uppercase case'), contains('ib-21212121212121 taskId must be uppercase case'),
), ),
) )
td.verify( td.verify(
console.error( core.setFailed(
contains('ib-21212121212121 commitStatus must be uppercase case'), contains('ib-21212121212121 commitStatus must be uppercase case'),
), ),
) )
@ -255,10 +258,11 @@ describe('Commit Linter action', () => {
await runAction() await runAction()
td.verify(console.error(contains('wrong commit from another branch'))) td.verify(core.setFailed(contains('wrong commit from another branch')))
}) })
describe('when there are multiple commits failing in the pull request', () => { describe('when there are multiple commits failing in the pull request', () => {
let expectedResultsOutput
const firstMessage = 'wrong message 1' const firstMessage = 'wrong message 1'
const secondMessage = 'wrong message 2' const secondMessage = 'wrong message 2'
@ -281,12 +285,29 @@ describe('Commit Linter action', () => {
data: [first, to].map(sha => ({ sha })), data: [first, to].map(sha => ({ sha })),
}) })
td.replace(process, 'cwd', () => cwd) td.replace(process, 'cwd', () => cwd)
expectedResultsOutput = [
{
hash: to,
message: secondMessage,
valid: false,
errors: ['subject may not be empty', 'type may not be empty'],
warnings: [],
},
{
hash: first,
message: firstMessage,
valid: false,
errors: ['subject may not be empty', 'type may not be empty'],
warnings: [],
},
]
}) })
it('should NOT show errors for a message from before the push', async () => { it('should NOT show errors for a message from before the push', async () => {
await runAction() await runAction()
td.verify(console.error(contains('message from before push')), { td.verify(core.setFailed(contains('message from before push')), {
times: 0, times: 0,
}) })
}) })
@ -294,13 +315,19 @@ describe('Commit Linter action', () => {
it('should show errors for the first wrong message', async () => { it('should show errors for the first wrong message', async () => {
await runAction() await runAction()
td.verify(console.error(contains(firstMessage))) td.verify(core.setFailed(contains(firstMessage)))
}) })
it('should show errors for the second wrong message', async () => { it('should show errors for the second wrong message', async () => {
await runAction() await runAction()
td.verify(console.error(contains(secondMessage))) td.verify(core.setFailed(contains(secondMessage)))
})
it('should generate a JSON output of the errors', async () => {
await runAction()
td.verify(core.setOutput(resultsOutputId, expectedResultsOutput))
}) })
}) })
@ -325,9 +352,8 @@ describe('Commit Linter action', () => {
it('should show an error message', async () => { it('should show an error message', async () => {
await runAction() await runAction()
expect(process.exitCode).toBe(1)
td.verify( td.verify(
console.error( core.setFailed(
contains("error trying to get list of pull request's commits"), contains("error trying to get list of pull request's commits"),
), ),
) )
@ -336,7 +362,7 @@ describe('Commit Linter action', () => {
it('should show the original error message', async () => { it('should show the original error message', async () => {
await runAction() await runAction()
td.verify(console.error(contains('HttpError: Bad credentials'))) td.verify(core.setFailed(contains('HttpError: Bad credentials')))
}) })
}) })
@ -357,7 +383,7 @@ describe('Commit Linter action', () => {
it('should pass', async () => { it('should pass', async () => {
await runAction() await runAction()
td.verify(console.error(), { times: 0, ignoreExtraArgs: true }) td.verify(core.setFailed(), { times: 0, ignoreExtraArgs: true })
}) })
it('should show success message', async () => { it('should show success message', async () => {
@ -365,9 +391,27 @@ describe('Commit Linter action', () => {
td.verify(console.log('Lint free! 🎉')) td.verify(console.log('Lint free! 🎉'))
}) })
it('should generate a JSON output of the messages', async () => {
const expectedResultsOutput = [
{
hash: commitHash,
message: 'chore: correct message',
valid: true,
errors: [],
warnings: [],
},
]
await runAction()
td.verify(core.setOutput(resultsOutputId, expectedResultsOutput))
})
}) })
describe('when all errors are just warnings', () => { describe('when all errors are just warnings', () => {
let expectedResultsOutput
beforeEach(async () => { beforeEach(async () => {
cwd = await git.bootstrap('fixtures/conventional') cwd = await git.bootstrap('fixtures/conventional')
await gitEmptyCommit(cwd, 'chore: previous commit') await gitEmptyCommit(cwd, 'chore: previous commit')
@ -381,15 +425,39 @@ describe('Commit Linter action', () => {
updatePushEnvVars(cwd, to) updatePushEnvVars(cwd, to)
td.replace(process, 'cwd', () => cwd) td.replace(process, 'cwd', () => cwd)
td.replace(console, 'log') td.replace(console, 'log')
expectedResultsOutput = [
{
hash: to,
message:
'chore: correct message\n\nsome context without leading blank line',
valid: true,
errors: [],
warnings: ['body must have leading blank line'],
},
{
hash: from,
message: 'chore: correct message with no warnings',
valid: true,
errors: [],
warnings: [],
},
]
}) })
it('should pass and show that warnings exist', async () => { it('should pass and show that warnings exist', async () => {
await runAction() await runAction()
td.verify(console.error(), { times: 0, ignoreExtraArgs: true }) td.verify(core.setFailed(), { times: 0, ignoreExtraArgs: true })
td.verify(console.log(contains('You have commit messages with warnings'))) td.verify(console.log(contains('You have commit messages with warnings')))
}) })
it('should show the results in an output', async () => {
await runAction()
td.verify(core.setOutput(resultsOutputId, expectedResultsOutput))
})
describe('and failOnWarnings is set to true', () => { describe('and failOnWarnings is set to true', () => {
beforeEach(() => { beforeEach(() => {
td.when(core.getInput('failOnWarnings')).thenReturn('true') td.when(core.getInput('failOnWarnings')).thenReturn('true')
@ -399,9 +467,15 @@ describe('Commit Linter action', () => {
await runAction() await runAction()
td.verify( td.verify(
console.error(contains('You have commit messages with errors')), core.setFailed(contains('You have commit messages with errors')),
) )
}) })
it('should show the results in an output', async () => {
await runAction()
td.verify(core.setOutput(resultsOutputId, expectedResultsOutput))
})
}) })
}) })
@ -429,7 +503,33 @@ describe('Commit Linter action', () => {
it('should fail', async () => { it('should fail', async () => {
await runAction() await runAction()
td.verify(console.error(contains('You have commit messages with errors'))) td.verify(
core.setFailed(contains('You have commit messages with errors')),
)
})
it('should show the results in an output', async () => {
const expectedResultsOutput = [
{
hash: secondHash,
message: 'wrong message',
valid: false,
errors: ['subject may not be empty', 'type may not be empty'],
warnings: [],
},
{
hash: firstHash,
message:
'chore: correct message\n\nsome context without leading blank line',
valid: true,
errors: [],
warnings: ['body must have leading blank line'],
},
]
await runAction()
td.verify(core.setOutput(resultsOutputId, expectedResultsOutput))
}) })
describe('and failOnWarnings is set to true', () => { describe('and failOnWarnings is set to true', () => {
@ -441,7 +541,7 @@ describe('Commit Linter action', () => {
await runAction() await runAction()
td.verify( td.verify(
console.error(contains('You have commit messages with errors')), core.setFailed(contains('You have commit messages with errors')),
) )
}) })
}) })

24
src/generateOutputs.js Normal file
View file

@ -0,0 +1,24 @@
const core = require('@actions/core')
const resultsOutputId = 'results'
const mapMessageValidation = item => item.message
const mapResultOutput = ({
hash,
lintResult: { valid, errors, warnings, input },
}) => ({
hash,
message: input,
valid,
errors: errors.map(mapMessageValidation),
warnings: warnings.map(mapMessageValidation),
})
const generateOutputs = lintedCommits => {
const resultsOutput = lintedCommits.map(mapResultOutput)
core.setOutput(resultsOutputId, resultsOutput)
}
module.exports = generateOutputs