-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.js
161 lines (129 loc) · 4.46 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
const core = require('@actions/core');
const github = require('@actions/github');
const run = async () => {
// Get octokit
const token = core.getInput('token', { required: true });
const is_oauth_token = core.getInput('is-oauth-token');
const githubToken = is_oauth_token ? '' : token;
const oauthToken = is_oauth_token ? token : '';
const client = github.getOctokit(githubToken, {auth: oauthToken});
// Get issue and pr message
const issueMessage = core.getInput('issue-message');
const prMessage = core.getInput('pr-message');
if (!issueMessage && !prMessage) {
throw new Error(
'Action must have at least one of issue-message or pr-message set'
);
}
const context = github.context;
// Do nothing if `action` is not `opened`.
if (context.payload.action !== 'opened') {
console.log('No issue or PR was opened, skipping');
return;
}
// Do nothing if its not a pr or issue
const isIssue = !!context.payload.issue;
if (!isIssue && !context.payload.pull_request) {
console.log(
'The event that triggered this action was not a pull request or issue, skipping.'
);
return;
}
// Do nothing if no message set for this type of contribution
const message = isIssue ? issueMessage : prMessage;
if (!message) {
console.log('No message provided for this type of contribution');
return;
}
// Get sender, repo and issue/pr info
if (!context.payload.sender) {
throw new Error('Internal error, no sender provided by GitHub');
}
const sender = context.payload.sender.login;
// Both issue and pr_number (or payload number, as applicable)
// can be found in `context.issue`.
const {owner, repo, number} = context.issue;
// Do nothing if its not their first contribution
console.log('Checking if it is the user\'s first contribution');
let firstContribution = false;
if (isIssue) {
firstContribution = await isFirstIssue(client, owner, repo, sender, number);
} else {
firstContribution = await isFirstPull(client, owner, repo, sender, number);
}
if (!firstContribution) {
console.log('Not the user\'s first contribution');
return;
}
// Prepare the final message
const final_message = message.replace(/@contributor_name/g, `@${sender}`);
// To create a comment on a pull request, we hit the issue endpoint only.
// See: https://octokit.github.io/rest.js/v18#pulls-create-review-comment
//
// So, from here, both issue and pull will be considered as `issue`.
const issueType = isIssue ? 'issue' : 'pull request';
// Add a comment to the appropriate place
console.log(`Adding message: ${final_message} to ${issueType} ${number}`);
// Add comment (greeting) to issue/PR
try {
await client.issues.createComment({
owner,
repo,
issue_number: number,
body: final_message
});
} catch (error) {
core.setFailed(error.message);
}
};
async function isFirstIssue(client, owner, repo, sender, curIssueNumber) {
const {status, data: issues} = await client.issues.listForRepo({
owner,
repo,
creator: sender,
state: 'all'
});
if (status !== 200) {
throw new Error(`Received unexpected API status code ${status}`);
}
if (issues.length === 0) {
return true;
}
for (const issue of issues) {
if (issue.number < curIssueNumber && !issue.pull_request) {
return false;
}
}
return true;
}
// No way to filter pulls by creator
async function isFirstPull(client, owner, repo, sender, curPullNumber, page = 1) {
// Provide console output if we loop for a while.
console.log(`Checking for first pull (at page ${page})`);
const {status, data: pulls} = await client.pulls.list({
owner,
repo,
per_page: 100,
page: page,
state: 'all'
});
if (status !== 200) {
throw new Error(`Received unexpected API status code ${status}`);
}
if (pulls.length === 0) {
return true;
}
for (const pull of pulls) {
const login = pull.user.login;
if (login === sender && pull.number < curPullNumber) {
return false;
}
}
return await isFirstPull(client, owner, repo, sender, curPullNumber, page + 1);
}
// Run the script
try {
run();
} catch (error) {
core.setFailed(error.message);
}