-
Notifications
You must be signed in to change notification settings - Fork 19
/
writeSummaryToPR.ts
171 lines (148 loc) · 4.89 KB
/
writeSummaryToPR.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
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
165
166
167
168
169
170
171
import * as core from "@actions/core";
import * as github from "@actions/github";
const gitHubToken = core.getInput("github-token").trim();
const octokit: Octokit = github.getOctokit(gitHubToken);
const COMMENT_MARKER = (markerPostfix = "root") =>
`<!-- vitest-coverage-report-marker-${markerPostfix} -->`;
type Octokit = ReturnType<typeof github.getOctokit>;
const writeSummaryToPR = async ({
summary,
markerPostfix,
userDefinedPrNumber,
}: {
summary: typeof core.summary;
markerPostfix?: string;
userDefinedPrNumber?: number;
}) => {
// The user-defined pull request number takes precedence
let pullRequestNumber = userDefinedPrNumber;
if (!pullRequestNumber) {
// If in the context of a pull-request, get the pull-request number
pullRequestNumber = github.context.payload.pull_request?.number;
// This is to allow commenting on pull_request from forks
if (github.context.eventName === "workflow_run") {
pullRequestNumber =
await getPullRequestNumberFromTriggeringWorkflow(octokit);
}
}
if (!pullRequestNumber) {
core.info("No pull-request-number found. Skipping comment creation.");
return;
}
const commentBody = `${summary.stringify()}\n\n${COMMENT_MARKER(markerPostfix)}`;
const existingComment = await findCommentByBody(
octokit,
COMMENT_MARKER(markerPostfix),
pullRequestNumber,
);
if (existingComment) {
await octokit.rest.issues.updateComment({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
comment_id: existingComment.id,
body: commentBody,
});
} else {
await octokit.rest.issues.createComment({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
issue_number: pullRequestNumber,
body: commentBody,
});
}
};
async function findCommentByBody(
octokit: Octokit,
commentBodyIncludes: string,
pullRequestNumber: number,
) {
const commentsIterator = octokit.paginate.iterator(
octokit.rest.issues.listComments,
{
owner: github.context.repo.owner,
repo: github.context.repo.repo,
issue_number: pullRequestNumber,
},
);
for await (const { data: comments } of commentsIterator) {
const comment = comments.find((comment) =>
comment.body?.includes(commentBodyIncludes),
);
if (comment) return comment;
}
return;
}
async function getPullRequestNumberFromTriggeringWorkflow(
octokit: Octokit,
): Promise<number | undefined> {
core.info(
"Trying to get the triggering workflow in order to find the pull-request-number to comment the results on...",
);
if (!github.context.payload.workflow_run) {
core.info(
"The triggering workflow does not have a workflow_run payload. Skipping comment creation.",
);
return undefined;
}
const originalWorkflowRunId = github.context.payload.workflow_run.id;
const { data: originalWorkflowRun } =
await octokit.rest.actions.getWorkflowRun({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
run_id: originalWorkflowRunId,
});
if (originalWorkflowRun.event !== "pull_request") {
core.info(
"The triggering workflow is not a pull-request. Skipping comment creation.",
);
return undefined;
}
// When the actual pull-request is not coming from a fork, the pull_request object is correctly populated and we can shortcut here
if (
originalWorkflowRun.pull_requests &&
originalWorkflowRun.pull_requests.length > 0
) {
return originalWorkflowRun.pull_requests[0].number;
}
// When the actual pull-request is coming from a fork, the pull_request object is not populated (see https://github.com/orgs/community/discussions/25220)
core.info(
`Trying to find the pull-request for the triggering workflow run with id: ${originalWorkflowRunId} (${originalWorkflowRun.url}) with HEAD_SHA ${originalWorkflowRun.head_sha}...`,
);
// The way to find the pull-request in this scenario is to query all existing pull_requests on the target repository and find the one with the same HEAD_SHA as the original workflow run
const pullRequest = await findPullRequest(
octokit,
originalWorkflowRun.head_sha,
);
if (!pullRequest) {
core.info(
"Could not find the pull-request for the triggering workflow run. Skipping comment creation.",
);
return undefined;
}
return pullRequest.number;
}
async function findPullRequest(octokit: Octokit, headSha: string) {
core.startGroup("Querying REST API for Pull-Requests.");
const pullRequestsIterator = octokit.paginate.iterator(
octokit.rest.pulls.list,
{
owner: github.context.repo.owner,
repo: github.context.repo.repo,
per_page: 30,
},
);
for await (const { data: pullRequests } of pullRequestsIterator) {
core.info(`Found ${pullRequests.length} pull-requests in this page.`);
for (const pullRequest of pullRequests) {
core.debug(
`Comparing: ${pullRequest.number} sha: ${pullRequest.head.sha} with expected: ${headSha}.`,
);
if (pullRequest.head.sha === headSha) {
return pullRequest;
}
}
}
core.endGroup();
return undefined;
}
export { writeSummaryToPR };