forked from vijaykramesh/pr-lint-action
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
126 lines (106 loc) · 3.94 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
const { Toolkit } = require('actions-toolkit')
const getConfig = require('./utils/config')
const CONFIG_FILENAME = 'pr-lint.yml'
const defaults = {
projects: ['PROJ'],
keywords: [],
check_title: true,
check_branch: false,
check_commits: false,
ignore_case: false
}
Toolkit.run(
async tools => {
const { repository, pull_request } = tools.context.payload
const repoInfo = {
owner: repository.owner.login,
repo: repository.name,
ref: pull_request.head.ref
}
const config = {
...defaults,
...(await getConfig(tools.github, CONFIG_FILENAME, repoInfo))
}
const title = config.ignore_case ?
pull_request.title.toLowerCase() :
pull_request.title
const head_branch = config.ignore_case ?
pull_request.head.ref.toLowerCase() :
pull_request.head.ref
const projects = config.projects.map(project => config.ignore_case ? project.toLowerCase() : project)
const keywords = config.keywords.map(keywords => config.ignore_case ? keywords.toLowerCase() : keywords)
const title_passed = (() => {
if (config.check_title) {
// check the PR title matches PROJECT-1234 somewhere
const isProjectMatch = projects.some(project => title.match(createProjectRegex(project)))
const isKeywordMatch = keywords.some(keyword => title.includes(keyword))
if (!isProjectMatch && !isKeywordMatch) {
tools.log('PR title ' + title + ' does not contain approved project')
return false
}
}
return true
})()
const branch_passed = (() => {
// check the branch matches PROJECT-1234 or PROJECT_1234 somewhere
if (config.check_branch) {
const isProjectMatch = projects.some(project => head_branch.match(createProjectRegex(project)))
const isKeywordMatch = keywords.some(keyword => head_branch.includes(keyword))
if (!isProjectMatch && !isKeywordMatch) {
tools.log('PR branch ' + head_branch + ' does not contain an approved project')
return false
}
}
return true
})()
const commits_passed = await (async () => {
// check the branch matches PROJECT-1234 or PROJECT_1234 somewhere
if (config.check_commits) {
const listCommitsParams = {
owner: repository.owner.login,
repo: repository.name,
pull_number: pull_request.number
}
const commitsInPR = (await tools.github.pulls.listCommits(listCommitsParams)).data
const failedCommits = findFailedCommits(projects, keywords, commitsInPR, config.ignore_case);
if(failedCommits.length) {
failedCommits.forEach(
failedCommit => tools.log('Commit message \'' + failedCommit + '\' does not contain an approved project')
)
return false
}
}
return true
})()
const statuses = [title_passed, branch_passed, commits_passed]
if (statuses.some(status => status === false )){
tools.exit.failure("PR Linting Failed")
} else {
tools.exit.success()
}
},
{ event: ['pull_request.opened', 'pull_request.edited', 'pull_request.synchronize', 'pull_request.ready_for_review', 'pull_request.labeled', 'pull_request.unlabeled'], secrets: ['GITHUB_TOKEN'] }
)
function findFailedCommits(projects, keywords, commitsInPR, ignoreCase) {
const failedCommits = [];
commitsInPR.forEach(commit => {
const commitMessage = ignoreCase ? commit.commit.message.toLowerCase() : commit.commit.message
for (const project of projects) {
const isProjectMatch = commitMessage.match(createProjectRegex(project))
if (isProjectMatch) {
return;
}
}
for (const keyword of keywords) {
const isKeywordMatch = commitMessage.includes(keyword)
if (isKeywordMatch) {
return;
}
}
failedCommits.push(commit)
});
return failedCommits;
}
function createProjectRegex(project) {
return new RegExp(project + '[-_]\\d*')
}