-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
164 lines (142 loc) · 7.05 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
162
163
164
'use strict';
const core = require('@actions/core');
const { GitHub, context } = require('@actions/github');
const superagent = require('superagent');
core.debug(`PR Duplicator - Context ${JSON.stringify(context, null, 2)}`);
const envOwner = context.repo.owner;
const envRepo = context.repo.repo;
const eventPayload = context.payload;
const confFrom = core.getInput('from'); // Branch from which the PR was created (head)
const confBase = core.getInput('base'); // Branch where the PR was requested
const confTo = core.getInput('to'); // Branch to which the new PR is created
const confPrAuthor = core.getInput('pr-author'); // Who has to be author of the PR to be duplicated
const confGithubToken = core.getInput('github-token');
const confSlackIncomingWebhookUrl = core.getInput('slack-incoming-webhook-url');
if (!eventPayload || !eventPayload.pull_request) {
throw new Error('INVALID CONFIGURATION: Invalid event type configuration, event payload must contain "pull_request" property. See: https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#pull-request-event-pull_request');
}
// https://developer.github.com/v3/pulls/
const payloadPullRequest = eventPayload.pull_request;
const payloadPullRequestNumber = payloadPullRequest.number; // Ex: 5
const payloadPullRequestAuthor = payloadPullRequest.user.login; // Ex: tiblu
const payloadBase = payloadPullRequest.base; // Branch where the PR was requested. Ex: master
const payloadFrom = payloadPullRequest.head; // Branch from which the PR was created (head). Ex: l10n_mater
if (payloadFrom.ref !== confFrom || payloadBase.ref !== confBase) {
return core.info(`SKIP! Skipping Action as the configured "from" and "base" ("${confFrom}","${confBase}") don't match the event payload ("${payloadFrom.ref}","${payloadBase.ref}")`);
}
if (confPrAuthor && payloadPullRequestAuthor !== confPrAuthor) {
return core.info(`SKIP! Skipping Action as the configured "pr-author" ("${confPrAuthor}") does not match the PR author in the payload ("${payloadPullRequestAuthor}")`);
}
if (!payloadPullRequest.merged) {
return core.warning(`SKIP! Skipping Action as the closed PR has not been merged! PR url ${payloadPullRequest.url}`);
}
const sendSlackMessage = async (message) => {
return await superagent
.post(confSlackIncomingWebhookUrl)
.send(message);
};
const runAction = async () => {
// https://octokit.github.io/rest.js/
// https://github.com/actions/toolkit/tree/master/packages/github
const octokit = new GitHub(confGithubToken);
// Create a new branch from the state in the branch which PR just got closed/merged.
// Creating a new branch so that it's guaranteed to have same set of changes that were merged with PR (payloadPullRequest)
// https://octokit.github.io/rest.js/#octokit-routes-git-create-ref
// https://developer.github.com/v3/git/refs/#create-a-reference
const {data: branchCreated} = await octokit.git.createRef({
owner: envOwner,
repo: envRepo,
ref: `refs/heads/pr_duplicator_${payloadFrom.ref}_${payloadPullRequestNumber}`,
sha: payloadPullRequest.merge_commit_sha
});
core.debug(`branchCreated - ${JSON.stringify(branchCreated, null, 2)}`);
// Create a PR from the freshly created branch to "to"
// https://octokit.github.io/rest.js/#octokit-routes-pulls-create
// https://developer.github.com/v3/pulls/#create-a-pull-request
const {data: pullRequestCreated} = await octokit.pulls.create({
owner: envOwner,
repo: envRepo,
title: `AUTO: PR-Duplicator - "${payloadPullRequest.title}".`,
body: `This pull request is automatically created by GitHub Action PR Duplicator. Created from: ${payloadPullRequest.html_url}`,
head: branchCreated.ref,
base: confTo
});
core.debug(`pullRequestCreated - ${JSON.stringify(pullRequestCreated, null, 2)}`);
// https://octokit.github.io/rest.js/#octokit-routes-issues-create-comment
// https://developer.github.com/v3/issues/comments/#create-a-comment
// https://developer.github.com/v3/guides/working-with-comments/#pull-request-comments - PR is just a type of issue, thus issue comments API is used.
const {data: commentCreated} = await octokit.issues.createComment({
owner: envOwner,
repo: envRepo,
issue_number: payloadPullRequestNumber,
body: `AUTO: PR-Duplicator - A pull request was automatically created after merging this one. NEW PR: ${pullRequestCreated.html_url}`
});
core.debug(`commentCreated - ${JSON.stringify(commentCreated, null, 2)}`);
// https://api.slack.com/messaging/webhooks
// https://api.slack.com/tools/block-kit-builder
// https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets
if (confSlackIncomingWebhookUrl) {
try {
await sendSlackMessage({
"blocks": [
{
type: 'section',
text: {
type: 'mrkdwn',
text: '*PR-Duplicator*: A pull request has been duplicated!'
}
},
{
type: 'section',
text: {
type: 'mrkdwn',
text: `Merged PR: ${payloadPullRequest.html_url}`
}
},
{
type: 'section',
text: {
type: 'mrkdwn',
text: `NEW PR: ${pullRequestCreated.html_url}`
}
}
]
});
} catch (err) {
core.warning(`SLACK NOTIFICATION FAILED! ${JSON.stringify(err, null, 2)}`);
}
}
core.info(`Pull request has been created - ${pullRequestCreated.html_url}`);
};
runAction()
.then(() => {
core.info('OK!');
})
.catch(async (err) => {
core.error(`ERROR ${JSON.stringify(err, null, 2)} ${JSON.stringify(context, null, 2)}`);
if (confSlackIncomingWebhookUrl) {
try {
await sendSlackMessage({
"blocks": [
{
type: 'section',
text: {
type: 'mrkdwn',
text: '*PR-Duplicator*: A pull request duplication *FAILED*!'
}
},
{
type: 'section',
text: {
type: 'mrkdwn',
text: `View checks: ${eventPayload.html_url}/actions`
}
}
]
});
} catch (err) {
core.warning(`SLACK NOTIFICATION FAILED! ${JSON.stringify(err, null, 2)}`);
}
}
core.setFailed(err.message);
});