Skip to content

Commit deb7aa8

Browse files
committed
Initial commit
0 parents  commit deb7aa8

File tree

382 files changed

+147506
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

382 files changed

+147506
-0
lines changed

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 Dominik Aschbacher
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# GitLint Action
2+
3+
This GitHub Action ensures that your naming conventions for commits, branches, and pull requests
4+
are being respected. GitLint uses min. and max. character counts as well as regular expressions
5+
to check against the data. It is recommended to add a workflow that runs when a pull request is
6+
created or when it gets updated.
7+
8+
## Usage
9+
10+
Create the file `.github/workflows/gitlint.yaml` in your repository and add the following workflow:
11+
12+
```yaml
13+
name: GitLint
14+
15+
on:
16+
pull_request:
17+
18+
jobs:
19+
gitlint:
20+
runs-on: ubuntu-latest
21+
name: GitLint
22+
steps:
23+
- name: Lint commits, branches, and pull requests
24+
uses: aschbacd/[email protected]
25+
with:
26+
github-token: ${{ secrets.GITHUB_TOKEN }}
27+
commit-message-body-max-length: 72
28+
commit-message-subject-max-length: 50
29+
prohibit-unknown-commit-authors: true
30+
prohibit-unknown-commit-committers: true
31+
re-commit-message-subject: "^[A-Z].*((?!\\.).)$"
32+
re-pull-request-title: "^[A-Z].*((?!\\.).)$"
33+
```
34+
35+
## Customization
36+
37+
The following input keys can be used in your GitHub Actions workflow (shown above).
38+
39+
| Key | Description | Default | Recommended |
40+
| ---------------------------------- | ------------------------------------------------------------ | ----------------------- | ----------------------------- |
41+
| commit-message-body-max-length | Max. characters for line in commit message body | -1 (disabled) | 72 |
42+
| commit-message-body-min-length | Min. characters for line in commit message body | -1 (disabled) | -1 (disabled) |
43+
| commit-message-subject-max-length | Max. characters for commit message subject | -1 (disabled) | 50 |
44+
| commit-message-subject-min-length | Min. characters for commit message subject | -1 (disabled) | -1 (disabled) |
45+
| github-token | Token used to authenticate against GitHub api | `-` | `${{ secrets.GITHUB_TOKEN }}` |
46+
| prohibit-unknown-commit-authors | Commit author must be GitHub user | `false` | `true` |
47+
| prohibit-unknown-commit-committers | Commit committer must be GitHub user | `false` | `true` |
48+
| prohibit-unsigned-commits | Commits without a valid signature are invalid | `false` | `false` |
49+
| re-branch-name | Regex used to check branch name | `.*` | `[a-z]+\/.+` |
50+
| re-commit-author-email | Regex used to check commit author email | `.*` | `.*` |
51+
| re-commit-author-name | Regex used to check commit author name | `.*` | `.*` |
52+
| re-commit-committer-email | Regex used to check commit committer email | `.*` | `.*` |
53+
| re-commit-committer-name | Regex used to check commit committer name | `.*` | `.*` |
54+
| re-commit-message-body | Regex used to check commit message body (DotAll) | `.*` | `.*` |
55+
| re-commit-message-split | Regex used to split commit message subject and body (DotAll) | `([^\n]*)(?:\n\n(.*))?` | `([^\n]*)(?:\n\n(.*))?` |
56+
| re-commit-message-subject | Regex used to check commit message subject | `.*` | `^[A-Z].*((?!\.).)$` |
57+
| re-pull-request-title | Regex used to check pull request title | `.*` | `^[A-Z].*((?!\.).)$` |
58+
59+
## Resources
60+
61+
If you want to learn more about Git commits check out [this section](https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History)
62+
of the Pro Git book.

action.yml

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: "GitLint Action"
2+
description: "Check if naming conventions for commits, branches, and PRs are respected"
3+
inputs:
4+
commit-message-body-max-length:
5+
description: "Max. length of commit message body"
6+
required: false
7+
default: -1
8+
commit-message-body-min-length:
9+
description: "Min. length of commit message body"
10+
required: false
11+
default: -1
12+
commit-message-subject-max-length:
13+
description: "Max. length of commit message subject"
14+
required: false
15+
default: -1
16+
commit-message-subject-min-length:
17+
description: "Min. length of commit message subject"
18+
required: false
19+
default: -1
20+
github-token:
21+
description: "GitHub token used to access api"
22+
required: true
23+
prohibit-unknown-commit-authors:
24+
description: "Prohibit commit authors that are not known to GitHub"
25+
required: false
26+
default: false
27+
prohibit-unknown-commit-committers:
28+
description: "Prohibit commit committers that are not known to GitHub"
29+
required: false
30+
default: false
31+
prohibit-unsigned-commits:
32+
description: "Prohibit commits without a valid signature"
33+
required: false
34+
default: false
35+
re-branch-name:
36+
description: "Regular expression to check branch name"
37+
required: false
38+
default: ".*"
39+
re-commit-author-email:
40+
description: "Regular expression to check commit author email"
41+
required: false
42+
default: ".*"
43+
re-commit-author-name:
44+
description: "Regular expression to check commit author name"
45+
required: false
46+
default: ".*"
47+
re-commit-committer-email:
48+
description: "Regular expression to check commit author email"
49+
required: false
50+
default: ".*"
51+
re-commit-committer-name:
52+
description: "Regular expression to check commit author name"
53+
required: false
54+
default: ".*"
55+
re-commit-message-body:
56+
description: "Regular expression to check commit message body"
57+
required: false
58+
default: ".*"
59+
re-commit-message-split:
60+
description: "Regular expression to split commit message into subject and body"
61+
required: false
62+
default: "([^\n]*)(?:\n\n(.*))?"
63+
re-commit-message-subject:
64+
description: "Regular expression to check commit message subject"
65+
required: false
66+
default: ".*"
67+
re-pull-request-title:
68+
description: "Regular expression to check pull request title"
69+
required: false
70+
default: ".*"
71+
runs:
72+
using: "node12"
73+
main: "index.js"

index.js

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
const core = require('@actions/core')
2+
const github = require('@actions/github')
3+
4+
async function run() {
5+
try {
6+
7+
// -----
8+
// --------------- GET DATA
9+
// ----------
10+
11+
// Get octokit
12+
const githubToken = core.getInput('github-token')
13+
const octokit = github.getOctokit(githubToken)
14+
15+
// Get data
16+
const { data: pullRequest } = await octokit.pulls.get({
17+
owner: github.context.payload.repository.owner.login,
18+
repo: github.context.payload.repository.name,
19+
pull_number: github.context.payload.pull_request.number
20+
})
21+
const { data: commits } = await octokit.pulls.listCommits({
22+
owner: github.context.payload.repository.owner.login,
23+
repo: github.context.payload.repository.name,
24+
pull_number: github.context.payload.pull_request.number
25+
})
26+
27+
// -----
28+
// --------------- GET INPUT
29+
// ----------
30+
31+
const commitMessageBodyMaxLength = parseInt(core.getInput('commit-message-body-max-length'))
32+
const commitMessageBodyMinLength = parseInt(core.getInput('commit-message-body-min-length'))
33+
const commitMessageSubjectMaxLength = parseInt(core.getInput('commit-message-subject-max-length'))
34+
const commitMessageSubjectMinLength = parseInt(core.getInput('commit-message-subject-min-length'))
35+
36+
const prohibitUnknownCommitAuthors = (core.getInput('prohibit-unknown-commit-authors') == 'true')
37+
const prohibitUnknownCommitCommitters = (core.getInput('prohibit-unknown-commit-committers') == 'true')
38+
const prohibitUnsignedCommits = (core.getInput('prohibit-unsigned-commits') == 'true')
39+
40+
const regexBranchName = RegExp(core.getInput('re-branch-name'))
41+
const regexCommitAuthorEmail = RegExp(core.getInput('re-commit-author-email'))
42+
const regexCommitAuthorName = RegExp(core.getInput('re-commit-author-name'))
43+
const regexCommitCommitterEmail = RegExp(core.getInput('re-commit-committer-email'))
44+
const regexCommitCommitterName = RegExp(core.getInput('re-commit-committer-name'))
45+
const regexCommitMessageBody = RegExp(core.getInput('re-commit-message-body'), 's')
46+
const regexCommitMessageSplit = RegExp(core.getInput('re-commit-message-split'), 's')
47+
const regexCommitMessageSubject = RegExp(core.getInput('re-commit-message-subject'))
48+
const regexPullRequestTitle = RegExp(core.getInput('re-pull-request-title'))
49+
50+
// -----
51+
// --------------- CHECK DATA
52+
// ----------
53+
54+
core.info(`Pull request title: ${pullRequest.title}`)
55+
core.info(`Branch name: ${pullRequest.head.ref}`)
56+
57+
// Check pull request title
58+
if (!regexPullRequestTitle.test(pullRequest.title))
59+
core.setFailed("Pull Request title does not match regex")
60+
61+
// Check branch name
62+
if (!regexBranchName.test(pullRequest.head.ref))
63+
core.setFailed("Branch name does not match regex")
64+
65+
// Check all commits
66+
commits.forEach(commit => {
67+
// Split commit message
68+
let matches = regexCommitMessageSplit.exec(commit.commit.message)
69+
let commitMessageSubject = matches[1]
70+
let commitMessageBody = matches[2]
71+
72+
console.log('-----')
73+
core.info(`Commit hash: ${commit.sha}`)
74+
core.info(`Commit author email: ${commit.commit.author.email}`)
75+
core.info(`Commit author name: ${commit.commit.author.name}`)
76+
core.info(`Commit author GitHub account: ${commit.author}`)
77+
core.info(`Commit committer email: ${commit.commit.committer.email}`)
78+
core.info(`Commit committer name: ${commit.commit.committer.name}`)
79+
core.info(`Commit committer GitHub account: ${commit.committer}`)
80+
core.info(`Commit has valid signature: ${commit.commit.verification.verified}`)
81+
core.info(`Commit message subject: ${commitMessageSubject}`)
82+
core.info(`Commit message body: ${commitMessageBody}`)
83+
84+
// Check commit author
85+
if (prohibitUnknownCommitAuthors && commit.author == null)
86+
core.setFailed(`Commit author does not exist on GitHub (${commit.sha.substr(0, 7)})`)
87+
88+
if (!regexCommitAuthorEmail.test(commit.commit.author.email))
89+
core.setFailed(`Commit author email does not match regex (${commit.sha.substr(0, 7)})`)
90+
91+
if (!regexCommitAuthorName.test(commit.commit.author.name))
92+
core.setFailed(`Commit author name does not match regex (${commit.sha.substr(0, 7)})`)
93+
94+
// Check commit committer
95+
if (prohibitUnknownCommitCommitters && commit.committer == null)
96+
core.setFailed(`Commit committer does not exist on GitHub (${commit.sha.substr(0, 7)})`)
97+
98+
if (!regexCommitCommitterEmail.test(commit.commit.committer.email))
99+
core.setFailed(`Commit committer email does not match regex (${commit.sha.substr(0, 7)})`)
100+
101+
if (!regexCommitCommitterName.test(commit.commit.committer.name))
102+
core.setFailed(`Commit committer name does not match regex (${commit.sha.substr(0, 7)})`)
103+
104+
// Check for valid signature
105+
if (prohibitUnsignedCommits && !commit.commit.verification.verified)
106+
core.setFailed(`Commit has no valid signature (${commit.sha.substr(0, 7)})`)
107+
108+
// Check commit message subject
109+
if (commitMessageSubjectMinLength != -1 && commitMessageSubject.length < commitMessageSubjectMinLength)
110+
core.setFailed(`Commit message subject is too short (${commit.sha.substr(0, 7)})`)
111+
112+
if (commitMessageSubjectMaxLength != -1 && commitMessageSubject.length > commitMessageSubjectMaxLength)
113+
core.setFailed(`Commit message subject is too long (${commit.sha.substr(0, 7)})`)
114+
115+
if (!regexCommitMessageSubject.test(commitMessageSubject))
116+
core.setFailed(`Commit message subject does not match regex (${commit.sha.substr(0, 7)})`)
117+
118+
// Check commit message body
119+
if (commitMessageBody != null) {
120+
commitMessageBody.split("\n").forEach(function (line, index) {
121+
if (commitMessageBodyMinLength != -1 && line.length < commitMessageBodyMinLength)
122+
core.setFailed(`Commit message body line ${(index+1).toString()} is too short (${commit.sha.substr(0, 7)})`)
123+
124+
if (commitMessageBodyMaxLength != -1 && line.length > commitMessageBodyMaxLength)
125+
core.setFailed(`Commit message body line ${(index+1).toString()} is too long (${commit.sha.substr(0, 7)})`)
126+
})
127+
128+
if (!regexCommitMessageBody.test(commitMessageBody))
129+
core.setFailed(`Commit message body does not match regex (${commit.sha.substr(0, 7)})`)
130+
}
131+
})
132+
} catch (error) {
133+
core.setFailed(error.message);
134+
}
135+
}
136+
137+
run()

node_modules/@actions/core/LICENSE.md

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)