WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit b15614d

Browse files
author
Vijay Ramesh
authored
Merge pull request #2 from jedster1111/GH-1
GH-1 Add ability to check commit messages
2 parents 5b50f29 + 7dea184 commit b15614d

File tree

5 files changed

+1248
-1080
lines changed

5 files changed

+1248
-1080
lines changed

fixtures/all.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
projects: ['PROJ']
22
check_title: true
33
check_branch: true
4+
check_commits: true
45
ignore_case: true

fixtures/commits.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
projects: ['PROJ']
2+
check_title: false
3+
check_branch: false
4+
check_commits: true
5+
ignore_case: false

index.js

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,18 @@ const defaults = {
77
projects: ['PROJ'],
88
check_title: true,
99
check_branch: false,
10+
check_commits: false,
1011
ignore_case: false
1112
}
1213

1314
Toolkit.run(
1415
async tools => {
16+
const { repository, pull_request } = tools.context.payload
17+
1518
const repoInfo = {
16-
owner: tools.context.payload.repository.owner.login,
17-
repo: tools.context.payload.repository.name,
18-
ref: tools.context.payload.pull_request.head.ref
19+
owner: repository.owner.login,
20+
repo: repository.name,
21+
ref: pull_request.head.ref
1922
}
2023

2124
const config = {
@@ -24,18 +27,18 @@ Toolkit.run(
2427
}
2528

2629
const title = config.ignore_case ?
27-
tools.context.payload.pull_request.title.toLowerCase() :
28-
tools.context.payload.pull_request.title
30+
pull_request.title.toLowerCase() :
31+
pull_request.title
2932

3033
const head_branch = config.ignore_case ?
31-
tools.context.payload.pull_request.head.ref.toLowerCase() :
32-
tools.context.payload.pull_request.head.ref
34+
pull_request.head.ref.toLowerCase() :
35+
pull_request.head.ref
3336

3437
const projects = config.projects.map(project => config.ignore_case ? project.toLowerCase() : project)
3538
const title_passed = (() => {
3639
if (config.check_title) {
3740
// check the title matches [PROJECT-1234] somewhere
38-
if (!projects.some(project => title.match(new RegExp('\\[' + project + '-\\d*\\]')))) {
41+
if (!projects.some(project => title.match(createWrappedProjectRegex(project)))) {
3942
tools.log('PR title ' + title + ' does not contain approved project')
4043
return false
4144
}
@@ -46,15 +49,36 @@ Toolkit.run(
4649
const branch_passed = (() => {
4750
// check the branch matches PROJECT-1234 or PROJECT_1234 somewhere
4851
if (config.check_branch) {
49-
if (!projects.some(project => head_branch.match(new RegExp(project + '[-_]\\d*')))) {
52+
if (!projects.some(project => head_branch.match(createProjectRegex(project)))) {
5053
tools.log('PR branch ' + head_branch + ' does not contain an approved project')
5154
return false
5255
}
5356
}
5457
return true
5558
})()
5659

57-
const statuses = [title_passed, branch_passed]
60+
const commits_passed = await (async () => {
61+
// check the branch matches PROJECT-1234 or PROJECT_1234 somewhere
62+
if (config.check_commits) {
63+
const listCommitsParams = {
64+
owner: repository.owner.login,
65+
repo: repository.name,
66+
pull_number: pull_request.number
67+
}
68+
const commitsInPR = (await tools.github.pulls.listCommits(listCommitsParams)).data
69+
const failedCommits = findFailedCommits(projects, commitsInPR, config.ignore_case);
70+
71+
if(failedCommits.length) {
72+
failedCommits.forEach(
73+
failedCommit => tools.log('Commit message \'' + failedCommit + '\' does not contain an approved project')
74+
)
75+
return false
76+
}
77+
}
78+
return true
79+
})()
80+
81+
const statuses = [title_passed, branch_passed, commits_passed]
5882

5983
if (statuses.some(status => status === false )){
6084
tools.exit.failure("PR Linting Failed")
@@ -64,3 +88,24 @@ Toolkit.run(
6488
},
6589
{ event: ['pull_request.opened', 'pull_request.edited', 'pull_request.synchronize'], secrets: ['GITHUB_TOKEN'] }
6690
)
91+
92+
function findFailedCommits(projects, commitsInPR, ignoreCase) {
93+
const failedCommits = [];
94+
projects.forEach(project => {
95+
commitsInPR.forEach(commit => {
96+
const commitMessage = ignoreCase ? commit.commit.message.toLowerCase() : commit.commit.message
97+
if (!commitMessage.match(createProjectRegex(project))) {
98+
failedCommits.push(commitMessage);
99+
}
100+
});
101+
});
102+
return failedCommits;
103+
}
104+
105+
function createProjectRegex(project) {
106+
return new RegExp(project + '[-_]\\d*')
107+
}
108+
109+
function createWrappedProjectRegex(project) {
110+
return new RegExp('\\[' + project + '-\\d*\\]')
111+
}

index.test.js

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,21 @@ describe('pr-lint-action', () => {
1919
const good_title_and_bad_branch = { title: '[PROJ-1234] a good PR title', ref_name: 'fix_things' }
2020
const bad_title_and_good_branch = { title: 'no ticket in me', ref_name: 'bug/PROJ_1234/a_good_branch' }
2121
const lower_case_good_title_and_branch = { title: '[proj-1234] a lower case good title', ref_name: 'bug/proj_1234/a_good_lowercase_branch' }
22+
const good_commits = [
23+
{ commit: { message: "PROJ-1234 Commit 1" } },
24+
{ commit: { message: "PROJ-1234 Commit 2" } },
25+
{ commit: { message: "PROJ-1234 Commit 3" } }
26+
];
27+
const lower_case_good_commits = [
28+
{ commit: { message: "PROJ-1234 Commit 1" } },
29+
{ commit: { message: "PROJ-1234 Commit 2" } },
30+
{ commit: { message: "PROJ-1234 Commit 3" } }
31+
];
32+
const bad_commits = [
33+
{ commit: { message: "PRJ-123 Commit 1" } },
34+
{ commit: { message: "PROJ-1234 Commit 2" } },
35+
{ commit: { message: "Commit 3" } }
36+
];
2237

2338
beforeEach(() => {
2439
// Create a new Toolkit instance
@@ -112,13 +127,70 @@ describe('pr-lint-action', () => {
112127
expect.assertions(1)
113128
})
114129

130+
it('passes if check_commits is true and all commits match', async () => {
131+
nock('https://api.github.com')
132+
.get('/repos/vijaykramesh/pr-lint-action-test/contents/.github/pr-lint.yml')
133+
.query(true)
134+
.reply(200, configFixture('commits.yml'))
135+
136+
mockGetPRCommitListRequest(good_commits);
137+
138+
tools.context.payload = pullRequestOpenedFixture(good_title_and_branch)
139+
await action(tools)
140+
expect(tools.exit.success).toHaveBeenCalled()
141+
expect.assertions(1)
142+
})
143+
144+
it('fails if check_commits is true and some commits do not match', async () => {
145+
nock('https://api.github.com')
146+
.get('/repos/vijaykramesh/pr-lint-action-test/contents/.github/pr-lint.yml')
147+
.query(true)
148+
.reply(200, configFixture('commits.yml'))
149+
150+
mockGetPRCommitListRequest(bad_commits)
151+
152+
tools.context.payload = pullRequestOpenedFixture(good_title_and_branch)
153+
await action(tools)
154+
expect(tools.exit.failure).toHaveBeenCalledWith("PR Linting Failed")
155+
expect.assertions(1)
156+
})
157+
158+
it('passes if check_commits is false and all commits match', async () => {
159+
nock('https://api.github.com')
160+
.get('/repos/vijaykramesh/pr-lint-action-test/contents/.github/pr-lint.yml')
161+
.query(true)
162+
.reply(200, configFixture('title.yml'))
163+
164+
mockGetPRCommitListRequest(good_commits);
165+
166+
tools.context.payload = pullRequestOpenedFixture(good_title_and_branch)
167+
await action(tools)
168+
expect(tools.exit.success).toHaveBeenCalled()
169+
expect.assertions(1)
170+
})
171+
172+
it('passes if check_commits is false and some commits do not match', async () => {
173+
nock('https://api.github.com')
174+
.get('/repos/vijaykramesh/pr-lint-action-test/contents/.github/pr-lint.yml')
175+
.query(true)
176+
.reply(200, configFixture('title.yml'))
177+
178+
mockGetPRCommitListRequest(bad_commits)
179+
180+
tools.context.payload = pullRequestOpenedFixture(good_title_and_branch)
181+
await action(tools)
182+
expect(tools.exit.success).toHaveBeenCalled()
183+
expect.assertions(1)
184+
})
185+
115186
it('fails if check_branch and check_title is true and title does not match', async () => {
116187
nock('https://api.github.com')
117188
.get('/repos/vijaykramesh/pr-lint-action-test/contents/.github/pr-lint.yml')
118189
.query(true)
119190
.reply(200, configFixture('all.yml'))
120191

121-
192+
mockGetPRCommitListRequest(good_commits);
193+
122194
tools.context.payload = pullRequestOpenedFixture(bad_title_and_good_branch)
123195
await action(tools)
124196
expect(tools.exit.failure).toHaveBeenCalledWith("PR Linting Failed")
@@ -132,6 +204,8 @@ describe('pr-lint-action', () => {
132204
.query(true)
133205
.reply(200, configFixture('all.yml'))
134206

207+
mockGetPRCommitListRequest(good_commits);
208+
135209
tools.context.payload = pullRequestOpenedFixture(bad_title_and_good_branch)
136210
await action(tools)
137211
expect(tools.exit.failure).toHaveBeenCalledWith("PR Linting Failed")
@@ -145,6 +219,7 @@ describe('pr-lint-action', () => {
145219
.query(true)
146220
.reply(200, configFixture('all.yml'))
147221

222+
mockGetPRCommitListRequest(good_commits);
148223

149224
tools.context.payload = pullRequestOpenedFixture(good_title_and_branch)
150225
await action(tools)
@@ -158,27 +233,50 @@ describe('pr-lint-action', () => {
158233
.query(true)
159234
.reply(200, configFixture('all.yml'))
160235

236+
mockGetPRCommitListRequest(good_commits);
161237

162238
tools.context.payload = pullRequestOpenedFixture(lower_case_good_title_and_branch)
163239
await action(tools)
164240
expect(tools.exit.success).toHaveBeenCalled()
165241
expect.assertions(1)
166242
})
167243

244+
it('passes if ignore_case and lower case commits', async () => {
245+
nock('https://api.github.com')
246+
.get('/repos/vijaykramesh/pr-lint-action-test/contents/.github/pr-lint.yml')
247+
.query(true)
248+
.reply(200, configFixture('all.yml'))
249+
250+
mockGetPRCommitListRequest(lower_case_good_commits);
168251

169-
it('fails if not ignore_case and lower case title/branch', async () => {
252+
tools.context.payload = pullRequestOpenedFixture(lower_case_good_title_and_branch)
253+
await action(tools)
254+
expect(tools.exit.success).toHaveBeenCalled()
255+
expect.assertions(1)
256+
})
257+
258+
it('fails if not ignore_case and lower case title/branch', async () => {
170259
nock('https://api.github.com')
171260
.get('/repos/vijaykramesh/pr-lint-action-test/contents/.github/pr-lint.yml')
172261
.query(true)
173262
.reply(200, configFixture('no-ignore-case.yml'))
174263

264+
mockGetPRCommitListRequest(good_commits);
175265

176266
tools.context.payload = pullRequestOpenedFixture(lower_case_good_title_and_branch)
177267
await action(tools)
178268
expect(tools.exit.failure).toHaveBeenCalledWith("PR Linting Failed")
179269
expect.assertions(1)
180270
})
181-
})
271+
})
272+
273+
274+
function mockGetPRCommitListRequest(commits) {
275+
nock('https://api.github.com')
276+
.get('/repos/vijaykramesh/pr-lint-action-test/pulls/1/commits')
277+
.query(true)
278+
.reply(200, commits);
279+
}
182280

183281
function encodeContent(content) {
184282
return Buffer.from(content).toString('base64')

0 commit comments

Comments
 (0)