-
Notifications
You must be signed in to change notification settings - Fork 144
/
Copy pathconventional-commit-lint.ts
135 lines (127 loc) · 4.28 KB
/
conventional-commit-lint.ts
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
127
128
129
130
131
132
133
134
135
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {
getConfigWithDefault,
ConfigChecker,
} from '@google-automations/bot-config-utils';
// eslint-disable-next-line node/no-extraneous-import
import {Probot} from 'probot';
// eslint-disable-next-line node/no-extraneous-import
import {Octokit} from '@octokit/rest';
import {PullRequest} from '@octokit/webhooks-types';
import {getAuthenticatedOctokit, getContextLogger} from 'gcf-utils';
import schema from './schema.json';
import {scanPullRequest} from './utils';
const CONFIGURATION_FILE = 'conventional-commit-lint.yaml';
interface Configuration {
enabled?: boolean;
always_check_pr_title?: boolean;
}
export = (app: Probot) => {
app.on(
[
'pull_request.opened',
'pull_request.reopened',
'pull_request.edited',
'pull_request.synchronize',
'pull_request.labeled',
],
async context => {
const {owner, repo} = context.repo();
const logger = getContextLogger(context);
let octokit: Octokit;
if (context.payload.installation && context.payload.installation.id) {
octokit = await getAuthenticatedOctokit(
context.payload.installation.id
);
} else {
throw new Error(
`Installation ID not provided in ${context.payload.action} event.` +
' We cannot authenticate Octokit.'
);
}
// Exit if the PR is closed.
if (context.payload.pull_request.state === 'closed') {
logger.info(
`The pull request ${context.payload.pull_request.url} is closed, exiting.`
);
return;
}
// Create a failing check if an attempt is made to submit an invalid config file.
try {
const configChecker = new ConfigChecker<Configuration>(
schema,
CONFIGURATION_FILE
);
const valid = await configChecker.validateConfigChanges(
octokit,
owner,
repo,
context.payload.pull_request.head.sha,
context.payload.pull_request.number
);
// valid === false indicates that a failed check was created on the PR,
// we can return immediately in this case:
if (valid === false) {
logger.warn(
`Invalid config file in PR ${context.payload.pull_request.number} for ${owner}/${repo}`
);
return;
}
} catch (e) {
const err = e as Error;
err.message = `Error validating configuration: ${err.message} ${owner}/${repo}`;
logger.warn(err);
}
// Conventional Commit Lint (unlike most automations) is opt-out, vs.,
// opt in. For this reason config is loaded with default values.
let config: Configuration | undefined = undefined;
try {
config = await getConfigWithDefault<Configuration>(
octokit,
owner,
repo,
CONFIGURATION_FILE,
{}
);
} catch (e) {
const err = e as Error;
err.message = `Error reading configuration: ${err.message} ${owner}/${repo}`;
logger.warn(err);
}
// Skip linting if it's explicitly turned off:
if (config?.enabled === false) {
logger.info(`commit linting not enabled for ${owner}/${repo}`);
return;
}
// If the head repo is null, we can not proceed.
if (
context.payload.pull_request.head.repo === undefined ||
context.payload.pull_request.head.repo === null
) {
logger.info(
`The head repo is undefined for ${context.payload.pull_request.url}, exiting.`
);
return;
}
await scanPullRequest(
context,
context.payload.pull_request as PullRequest,
logger,
octokit,
config?.always_check_pr_title
);
}
);
};