mirror of
https://github.com/wagoid/commitlint-github-action.git
synced 2025-11-07 08:06:54 +00:00
Merge pull request #41 from wagoid/feat/add-outputs-to-the-action
feat: add `results` output to the action
This commit is contained in:
commit
6c53f9a94c
12 changed files with 398 additions and 176 deletions
|
|
@ -6,5 +6,5 @@ action.yml
|
|||
CHANGELOG.md
|
||||
coverage
|
||||
fixtures
|
||||
action.test.js
|
||||
testUtils.js
|
||||
src/action.test.js
|
||||
src/testUtils.js
|
||||
|
|
|
|||
4
.github/workflows/commitlint.yml
vendored
4
.github/workflows/commitlint.yml
vendored
|
|
@ -13,6 +13,10 @@ jobs:
|
|||
- run: sed -i -E "s/([']docker:.+)/Dockerfile/" ./action.yml
|
||||
- run: echo -n '' > .dockerignore
|
||||
- uses: ./
|
||||
id: run_commitlint
|
||||
- name: Show results from JSON output
|
||||
if: ${{ always() }}
|
||||
run: echo ${{ toJSON(steps.run_commitlint.outputs.results) }}
|
||||
commitlint-with-yml-file:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
|
|
|
|||
44
README.md
44
README.md
|
|
@ -54,6 +54,50 @@ Link to a page explaining your commit message convention.
|
|||
|
||||
default: `https://github.com/conventional-changelog/commitlint/#what-is-commitlint`
|
||||
|
||||
## 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
|
||||
|
||||
⧗ input: wrong message
|
||||
✖ subject may not be empty [subject-empty]
|
||||
✖ type may not be empty [type-empty]
|
||||
|
||||
✖ found 2 problems, 0 warnings
|
||||
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
|
||||
|
||||
⧗ input: chore: my message
|
||||
⚠ body must have leading blank line [body-leading-blank]
|
||||
|
||||
⚠ found 0 problems, 1 warnings
|
||||
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
|
||||
```
|
||||
|
||||
```JSON
|
||||
[
|
||||
{
|
||||
"hash": "cb0f846f13b490c2fd17bd5ed0b6f65ba9b86c75",
|
||||
"message": "wrong message",
|
||||
"valid": false,
|
||||
"errors": ["subject may not be empty", "type may not be empty"],
|
||||
"warnings": [],
|
||||
},
|
||||
{
|
||||
"hash": "cb14483cbde23b61322ffb8d3fcdc87f514a3141",
|
||||
"message": "chore: my message\n\nsome context without leading blank line",
|
||||
"valid": true,
|
||||
"errors": [],
|
||||
"warnings": ["body must have leading blank line"],
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
## About `extends` in your config file
|
||||
|
||||
This is a [`Docker` action](https://github.com/actions/toolkit/blob/e2adf403d6d14a9ca7474976ccaca20f72ff8209/docs/action-types.md#why-would-i-choose-a-docker-action), and was made like this so that you can run it with minimum setup, regardless of your repo's environment. It comes packed with the most famous shared configurations that you can use in your commitlint config's `extends` field:
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ inputs:
|
|||
description: 'Link to a page explaining your commit message convention'
|
||||
default: 'https://github.com/conventional-changelog/commitlint/#what-is-commitlint'
|
||||
required: false
|
||||
outputs:
|
||||
results:
|
||||
description: The error and warning messages for each one of the analyzed commits
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'docker://wagoid/commitlint-github-action:1.7.0'
|
||||
|
|
|
|||
118
package-lock.json
generated
118
package-lock.json
generated
|
|
@ -5,9 +5,9 @@
|
|||
"requires": true,
|
||||
"dependencies": {
|
||||
"@actions/core": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.1.1.tgz",
|
||||
"integrity": "sha512-O5G6EmlzTVsng7VSpNtszIoQq6kOgMGNTFB/hmwKNNA4V71JyxImCIrL27vVHCt2Cb3ImkaCr6o27C2MV9Ylwg=="
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.4.tgz",
|
||||
"integrity": "sha512-YJCEq8BE3CdN8+7HPZ/4DxJjk/OkZV2FFIf+DlZTC/4iBlzYCD5yjRR6eiOS5llO11zbRltIRuKAjMKaWTE6cg=="
|
||||
},
|
||||
"@actions/github": {
|
||||
"version": "1.1.0",
|
||||
|
|
@ -1349,6 +1349,14 @@
|
|||
"through2": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dargs": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz",
|
||||
"integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=",
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"through2": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
|
||||
|
|
@ -3784,6 +3792,15 @@
|
|||
"through2": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dargs": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz",
|
||||
"integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"through2": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
|
||||
|
|
@ -4019,6 +4036,14 @@
|
|||
"through2": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dargs": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz",
|
||||
"integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=",
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
|
|
@ -4151,10 +4176,9 @@
|
|||
}
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz",
|
||||
"integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==",
|
||||
"dev": true,
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"requires": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
|
|
@ -4164,14 +4188,12 @@
|
|||
"path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
}
|
||||
|
|
@ -4179,14 +4201,12 @@
|
|||
"shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
|
|
@ -4222,12 +4242,9 @@
|
|||
"integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk="
|
||||
},
|
||||
"dargs": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz",
|
||||
"integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=",
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
|
||||
"integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg=="
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
|
|
@ -4600,10 +4617,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"execa": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz",
|
||||
"integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==",
|
||||
"dev": true,
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz",
|
||||
"integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==",
|
||||
"requires": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"get-stream": "^5.0.0",
|
||||
|
|
@ -4612,7 +4628,6 @@
|
|||
"merge-stream": "^2.0.0",
|
||||
"npm-run-path": "^4.0.0",
|
||||
"onetime": "^5.1.0",
|
||||
"p-finally": "^2.0.0",
|
||||
"signal-exit": "^3.0.2",
|
||||
"strip-final-newline": "^2.0.0"
|
||||
},
|
||||
|
|
@ -4621,7 +4636,6 @@
|
|||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
|
||||
"integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
|
|
@ -4629,20 +4643,17 @@
|
|||
"is-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw=="
|
||||
},
|
||||
"mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
|
||||
},
|
||||
"npm-run-path": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.0.tgz",
|
||||
"integrity": "sha512-8eyAOAH+bYXFPSnNnKr3J+yoybe8O87Is5rtAQ8qRczJz1ajcsjg8l2oZqP+Ppx15Ii3S1vUTjQN2h4YO2tWWQ==",
|
||||
"dev": true,
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
|
||||
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
|
||||
"requires": {
|
||||
"path-key": "^3.0.0"
|
||||
}
|
||||
|
|
@ -4651,22 +4662,14 @@
|
|||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
|
||||
"integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mimic-fn": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz",
|
||||
"integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==",
|
||||
"dev": true
|
||||
},
|
||||
"path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -5775,28 +5778,6 @@
|
|||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"git-raw-commits": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.2.tgz",
|
||||
"integrity": "sha512-HVvl6J3dx7CS9fWTtyZXA2ejhdq9p/GSU9EEVlJPb2pSgMuD7IWK3dERcUPsJj9SZrJJ6IIB+3Rsjx9FUDdE1Q==",
|
||||
"requires": {
|
||||
"dargs": "^4.0.1",
|
||||
"lodash.template": "^4.0.2",
|
||||
"meow": "^4.0.0",
|
||||
"split2": "^2.0.0",
|
||||
"through2": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"through2": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz",
|
||||
"integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==",
|
||||
"requires": {
|
||||
"readable-stream": "2 || 3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"git-remote-origin-url": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz",
|
||||
|
|
@ -6066,8 +6047,7 @@
|
|||
"human-signals": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
|
||||
"integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw=="
|
||||
},
|
||||
"humanize-ms": {
|
||||
"version": "1.2.1",
|
||||
|
|
@ -8178,8 +8158,7 @@
|
|||
"merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
|
||||
"dev": true
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
|
||||
},
|
||||
"merge2": {
|
||||
"version": "1.3.0",
|
||||
|
|
@ -10356,8 +10335,7 @@
|
|||
"strip-final-newline": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
|
||||
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="
|
||||
},
|
||||
"strip-indent": {
|
||||
"version": "2.0.0",
|
||||
|
|
|
|||
26
package.json
26
package.json
|
|
@ -15,8 +15,8 @@
|
|||
"license": "ISC",
|
||||
"homepage": "https://github.com/wagoid/commitlint-github-action",
|
||||
"dependencies": {
|
||||
"@actions/core": "1.1.1",
|
||||
"@actions/github": "1.1.0",
|
||||
"@actions/core": "^1.2.4",
|
||||
"@actions/github": "^1.1.0",
|
||||
"@commitlint/config-angular": "^8.3.4",
|
||||
"@commitlint/config-conventional": "^8.3.4",
|
||||
"@commitlint/config-lerna-scopes": "^8.3.4",
|
||||
|
|
@ -24,21 +24,21 @@
|
|||
"@commitlint/format": "^8.3.4",
|
||||
"@commitlint/lint": "^8.3.5",
|
||||
"@commitlint/load": "^8.3.5",
|
||||
"commitlint-config-jira": "1.2.0",
|
||||
"commitlint-plugin-jira-rules": "1.2.0",
|
||||
"conventional-changelog-lint-config-canonical": "1.0.0",
|
||||
"git-raw-commits": "2.0.2",
|
||||
"lerna": "3.18.1"
|
||||
"commitlint-config-jira": "^1.2.0",
|
||||
"commitlint-plugin-jira-rules": "^1.2.0",
|
||||
"conventional-changelog-lint-config-canonical": "^1.0.0",
|
||||
"dargs": "^7.0.0",
|
||||
"execa": "^4.0.3",
|
||||
"lerna": "^3.18.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/test": "^8.2.0",
|
||||
"conventional-changelog-cli": "2.0.23",
|
||||
"execa": "3.4.0",
|
||||
"husky": "3.0.7",
|
||||
"conventional-changelog-cli": "^2.0.23",
|
||||
"husky": "^3.0.7",
|
||||
"jest": "^24.9.0",
|
||||
"prettier": "1.18.2",
|
||||
"pretty-quick": "1.11.1",
|
||||
"testdouble": "3.12.4"
|
||||
"prettier": "^1.18.2",
|
||||
"pretty-quick": "^1.11.1",
|
||||
"testdouble": "^3.12.4"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
|
|
|||
2
run.js
2
run.js
|
|
@ -1,3 +1,3 @@
|
|||
const action = require('./action')
|
||||
const action = require('./src/action')
|
||||
|
||||
action()
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ const github = require('@actions/github')
|
|||
const lint = require('@commitlint/lint')
|
||||
const { format } = require('@commitlint/format')
|
||||
const load = require('@commitlint/load')
|
||||
const gitRawCommits = require('git-raw-commits')
|
||||
const gitCommits = require('./gitCommits')
|
||||
const generateOutputs = require('./generateOutputs')
|
||||
|
||||
const pullRequestEvent = 'pull_request'
|
||||
|
||||
|
|
@ -76,16 +77,7 @@ function getHistoryCommits(from, to) {
|
|||
options.maxCount = 1
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = []
|
||||
|
||||
gitRawCommits(options)
|
||||
.on('data', chunk => data.push(chunk.toString('utf-8')))
|
||||
.on('error', reject)
|
||||
.on('end', () => {
|
||||
resolve(data)
|
||||
})
|
||||
})
|
||||
return gitCommits(options)
|
||||
}
|
||||
|
||||
function getOptsFromConfig(config) {
|
||||
|
|
@ -101,26 +93,21 @@ function getOptsFromConfig(config) {
|
|||
}
|
||||
}
|
||||
|
||||
const formatErrors = results =>
|
||||
const formatErrors = lintedCommits =>
|
||||
format(
|
||||
{ results },
|
||||
{ results: lintedCommits.map(commit => commit.lintResult) },
|
||||
{
|
||||
color: true,
|
||||
helpUrl: core.getInput('helpURL'),
|
||||
},
|
||||
)
|
||||
|
||||
const hasOnlyWarnings = results => {
|
||||
const resultsWithOnlyWarnings = results.filter(
|
||||
result => result.valid && result.warnings.length,
|
||||
const hasOnlyWarnings = lintedCommits =>
|
||||
lintedCommits.length &&
|
||||
lintedCommits.every(
|
||||
({ lintResult }) => lintResult.valid && lintResult.warnings.length,
|
||||
)
|
||||
|
||||
return (
|
||||
resultsWithOnlyWarnings.length &&
|
||||
resultsWithOnlyWarnings.length === results.length
|
||||
)
|
||||
}
|
||||
|
||||
const setFailed = formattedResults => {
|
||||
core.setFailed(`You have commit messages with errors\n\n${formattedResults}`)
|
||||
}
|
||||
|
|
@ -140,12 +127,17 @@ const showLintResults = async ([from, to]) => {
|
|||
? await load({}, { file: configPath })
|
||||
: {}
|
||||
const opts = getOptsFromConfig(config)
|
||||
const results = await Promise.all(
|
||||
commits.map(commit => lint(commit, config.rules, opts)),
|
||||
const lintedCommits = await Promise.all(
|
||||
commits.map(async commit => ({
|
||||
lintResult: await lint(commit.message, config.rules, opts),
|
||||
hash: commit.hash,
|
||||
})),
|
||||
)
|
||||
const formattedResults = formatErrors(results)
|
||||
const formattedResults = formatErrors(lintedCommits)
|
||||
|
||||
if (hasOnlyWarnings(results)) {
|
||||
generateOutputs(lintedCommits)
|
||||
|
||||
if (hasOnlyWarnings(lintedCommits)) {
|
||||
handleOnlyWarnings(formattedResults)
|
||||
} else if (formattedResults) {
|
||||
setFailed(formattedResults)
|
||||
|
|
@ -11,6 +11,8 @@ const {
|
|||
updatePullRequestEnvVars,
|
||||
} = require('./testUtils')
|
||||
|
||||
const resultsOutputId = 'results'
|
||||
|
||||
const {
|
||||
matchers: { contains },
|
||||
} = td
|
||||
|
|
@ -43,6 +45,7 @@ describe('Commit Linter action', () => {
|
|||
core = require('@actions/core')
|
||||
td.replace(core, 'getInput')
|
||||
td.replace(core, 'setFailed')
|
||||
td.replace(core, 'setOutput')
|
||||
td.when(core.getInput('configFile')).thenReturn('./commitlint.config.js')
|
||||
td.when(core.getInput('firstParent')).thenReturn('true')
|
||||
td.when(core.getInput('failOnWarnings')).thenReturn('false')
|
||||
|
|
@ -70,21 +73,6 @@ describe('Commit Linter action', () => {
|
|||
td.verify(core.setFailed(contains('You have commit messages with errors')))
|
||||
})
|
||||
|
||||
it('should pass for single push with correct message', async () => {
|
||||
cwd = await git.bootstrap('fixtures/conventional')
|
||||
await gitEmptyCommit(cwd, 'chore: correct message')
|
||||
const [to] = await getCommitHashes(cwd)
|
||||
await createPushEventPayload(cwd, { to })
|
||||
updatePushEnvVars(cwd, to)
|
||||
td.replace(process, 'cwd', () => cwd)
|
||||
td.replace(console, 'log')
|
||||
|
||||
await runAction()
|
||||
|
||||
td.verify(core.setFailed(), { times: 0, ignoreExtraArgs: true })
|
||||
td.verify(console.log('Lint free! 🎉'))
|
||||
})
|
||||
|
||||
it('should fail for push range with wrong messages', async () => {
|
||||
cwd = await git.bootstrap('fixtures/conventional')
|
||||
await gitEmptyCommit(cwd, 'message from before push')
|
||||
|
|
@ -259,64 +247,157 @@ describe('Commit Linter action', () => {
|
|||
td.verify(core.setFailed(contains('wrong commit from another branch')))
|
||||
})
|
||||
|
||||
it('should lint all commits from a pull request', async () => {
|
||||
cwd = await git.bootstrap('fixtures/conventional')
|
||||
td.when(core.getInput('configFile')).thenReturn('./commitlint.config.js')
|
||||
await gitEmptyCommit(cwd, 'message from before push')
|
||||
await gitEmptyCommit(cwd, 'wrong message 1')
|
||||
await gitEmptyCommit(cwd, 'wrong message 2')
|
||||
await gitEmptyCommit(cwd, 'wrong message 3')
|
||||
await createPullRequestEventPayload(cwd)
|
||||
const [, first, second, to] = await getCommitHashes(cwd)
|
||||
updatePullRequestEnvVars(cwd, to)
|
||||
td.when(
|
||||
listCommits({
|
||||
owner: 'wagoid',
|
||||
repo: 'commitlint-github-action',
|
||||
pull_number: '1',
|
||||
}),
|
||||
).thenResolve({
|
||||
data: [first, second, to].map(sha => ({ sha })),
|
||||
})
|
||||
td.replace(process, 'cwd', () => cwd)
|
||||
describe('when there are multiple commits failing in the pull request', () => {
|
||||
let expectedResultsOutput
|
||||
const firstMessage = 'wrong message 1'
|
||||
const secondMessage = 'wrong message 2'
|
||||
|
||||
await runAction()
|
||||
beforeEach(async () => {
|
||||
cwd = await git.bootstrap('fixtures/conventional')
|
||||
td.when(core.getInput('configFile')).thenReturn('./commitlint.config.js')
|
||||
await gitEmptyCommit(cwd, 'message from before push')
|
||||
await gitEmptyCommit(cwd, firstMessage)
|
||||
await gitEmptyCommit(cwd, secondMessage)
|
||||
await createPullRequestEventPayload(cwd)
|
||||
const [, first, to] = await getCommitHashes(cwd)
|
||||
updatePullRequestEnvVars(cwd, to)
|
||||
td.when(
|
||||
listCommits({
|
||||
owner: 'wagoid',
|
||||
repo: 'commitlint-github-action',
|
||||
pull_number: '1',
|
||||
}),
|
||||
).thenResolve({
|
||||
data: [first, to].map(sha => ({ sha })),
|
||||
})
|
||||
td.replace(process, 'cwd', () => cwd)
|
||||
|
||||
td.verify(core.setFailed(contains('message from before push')), {
|
||||
times: 0,
|
||||
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 () => {
|
||||
await runAction()
|
||||
|
||||
td.verify(core.setFailed(contains('message from before push')), {
|
||||
times: 0,
|
||||
})
|
||||
})
|
||||
|
||||
it('should show errors for the first wrong message', async () => {
|
||||
await runAction()
|
||||
|
||||
td.verify(core.setFailed(contains(firstMessage)))
|
||||
})
|
||||
|
||||
it('should show errors for the second wrong message', async () => {
|
||||
await runAction()
|
||||
|
||||
td.verify(core.setFailed(contains(secondMessage)))
|
||||
})
|
||||
|
||||
it('should generate a JSON output of the errors', async () => {
|
||||
await runAction()
|
||||
|
||||
td.verify(core.setOutput(resultsOutputId, expectedResultsOutput))
|
||||
})
|
||||
td.verify(core.setFailed(contains('wrong message 1')))
|
||||
td.verify(core.setFailed(contains('wrong message 2')))
|
||||
td.verify(core.setFailed(contains('wrong message 3')))
|
||||
})
|
||||
|
||||
it('should show an error message when failing to fetch commits', async () => {
|
||||
cwd = await git.bootstrap('fixtures/conventional')
|
||||
td.when(core.getInput('configFile')).thenReturn('./commitlint.config.js')
|
||||
await gitEmptyCommit(cwd, 'commit message')
|
||||
await createPullRequestEventPayload(cwd)
|
||||
const [to] = await getCommitHashes(cwd)
|
||||
updatePullRequestEnvVars(cwd, to)
|
||||
td.when(
|
||||
listCommits({
|
||||
owner: 'wagoid',
|
||||
repo: 'commitlint-github-action',
|
||||
pull_number: '1',
|
||||
}),
|
||||
).thenReject(new Error('HttpError: Bad credentials'))
|
||||
td.replace(process, 'cwd', () => cwd)
|
||||
describe('when it fails to fetch commits', () => {
|
||||
beforeEach(async () => {
|
||||
cwd = await git.bootstrap('fixtures/conventional')
|
||||
td.when(core.getInput('configFile')).thenReturn('./commitlint.config.js')
|
||||
await gitEmptyCommit(cwd, 'commit message')
|
||||
await createPullRequestEventPayload(cwd)
|
||||
const [to] = await getCommitHashes(cwd)
|
||||
updatePullRequestEnvVars(cwd, to)
|
||||
td.when(
|
||||
listCommits({
|
||||
owner: 'wagoid',
|
||||
repo: 'commitlint-github-action',
|
||||
pull_number: '1',
|
||||
}),
|
||||
).thenReject(new Error('HttpError: Bad credentials'))
|
||||
td.replace(process, 'cwd', () => cwd)
|
||||
})
|
||||
|
||||
await runAction()
|
||||
it('should show an error message', async () => {
|
||||
await runAction()
|
||||
|
||||
td.verify(
|
||||
core.setFailed(
|
||||
contains("error trying to get list of pull request's commits"),
|
||||
),
|
||||
)
|
||||
td.verify(core.setFailed(contains('HttpError: Bad credentials')))
|
||||
td.verify(
|
||||
core.setFailed(
|
||||
contains("error trying to get list of pull request's commits"),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
it('should show the original error message', async () => {
|
||||
await runAction()
|
||||
|
||||
td.verify(core.setFailed(contains('HttpError: Bad credentials')))
|
||||
})
|
||||
})
|
||||
|
||||
describe("when there's a single commit with correct message", () => {
|
||||
let commitHash
|
||||
|
||||
beforeEach(async () => {
|
||||
cwd = await git.bootstrap('fixtures/conventional')
|
||||
await gitEmptyCommit(cwd, 'chore: correct message')
|
||||
const [to] = await getCommitHashes(cwd)
|
||||
commitHash = to
|
||||
await createPushEventPayload(cwd, { to })
|
||||
updatePushEnvVars(cwd, to)
|
||||
td.replace(process, 'cwd', () => cwd)
|
||||
td.replace(console, 'log')
|
||||
})
|
||||
|
||||
it('should pass', async () => {
|
||||
await runAction()
|
||||
|
||||
td.verify(core.setFailed(), { times: 0, ignoreExtraArgs: true })
|
||||
})
|
||||
|
||||
it('should show success message', async () => {
|
||||
await runAction()
|
||||
|
||||
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', () => {
|
||||
let expectedResultsOutput
|
||||
|
||||
beforeEach(async () => {
|
||||
cwd = await git.bootstrap('fixtures/conventional')
|
||||
await gitEmptyCommit(
|
||||
|
|
@ -328,6 +409,17 @@ describe('Commit Linter action', () => {
|
|||
updatePushEnvVars(cwd, to)
|
||||
td.replace(process, 'cwd', () => cwd)
|
||||
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'],
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
it('should pass and show that warnings exist', async () => {
|
||||
|
|
@ -337,6 +429,12 @@ describe('Commit Linter action', () => {
|
|||
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', () => {
|
||||
beforeEach(() => {
|
||||
td.when(core.getInput('failOnWarnings')).thenReturn('true')
|
||||
|
|
@ -349,18 +447,30 @@ describe('Commit Linter action', () => {
|
|||
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))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('when a subset of errors are just warnings', () => {
|
||||
let firstHash
|
||||
let secondHash
|
||||
|
||||
beforeEach(async () => {
|
||||
cwd = await git.bootstrap('fixtures/conventional')
|
||||
await gitEmptyCommit(cwd, 'message from before push')
|
||||
await gitEmptyCommit(
|
||||
cwd,
|
||||
'chore: correct message\nsome context without leading blank line',
|
||||
)
|
||||
await gitEmptyCommit(cwd, 'wrong message')
|
||||
const [before, to] = await getCommitHashes(cwd)
|
||||
const [before, firstCommit, to] = await getCommitHashes(cwd)
|
||||
firstHash = firstCommit
|
||||
secondHash = to
|
||||
await createPushEventPayload(cwd, { before, to })
|
||||
updatePushEnvVars(cwd, to)
|
||||
td.replace(process, 'cwd', () => cwd)
|
||||
|
|
@ -375,6 +485,30 @@ describe('Commit Linter action', () => {
|
|||
)
|
||||
})
|
||||
|
||||
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', () => {
|
||||
beforeEach(() => {
|
||||
td.when(core.getInput('failOnWarnings')).thenReturn('true')
|
||||
24
src/generateOutputs.js
Normal file
24
src/generateOutputs.js
Normal 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
|
||||
43
src/gitCommits.js
Normal file
43
src/gitCommits.js
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
const dargs = require('dargs')
|
||||
const execa = require('execa')
|
||||
|
||||
const commitDelimiter = '--------->commit---------'
|
||||
|
||||
const hashDelimiter = '--------->hash---------'
|
||||
|
||||
const format = `%H${hashDelimiter}%B%n${commitDelimiter}`
|
||||
|
||||
const buildGitArgs = gitOpts => {
|
||||
const { from, to, ...otherOpts } = gitOpts
|
||||
var formatArg = `--format=${format}`
|
||||
var fromToArg = [from, to].filter(Boolean).join('..')
|
||||
|
||||
var gitArgs = ['log', formatArg, fromToArg]
|
||||
|
||||
return gitArgs.concat(
|
||||
dargs(gitOpts, {
|
||||
includes: Object.keys(otherOpts),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
const gitCommits = async gitOpts => {
|
||||
var args = buildGitArgs(gitOpts)
|
||||
|
||||
var { stdout } = await execa('git', args, {
|
||||
cwd: process.cwd(),
|
||||
})
|
||||
|
||||
const commits = stdout.split(`${commitDelimiter}\n`).map(messageItem => {
|
||||
const [hash, message] = messageItem.split(hashDelimiter)
|
||||
|
||||
return {
|
||||
hash,
|
||||
message,
|
||||
}
|
||||
})
|
||||
|
||||
return commits
|
||||
}
|
||||
|
||||
module.exports = gitCommits
|
||||
Loading…
Reference in a new issue