@samitouri / QOS-React / commits / a731a51696

Add GitHub action to check for bug repro (#21542)

Brian Vaughn committed May 21, 2021 at 12:48 UTC a731a51696239a69a6cd89cdd34f23ce2fc39099
1 file changed +209
.github/workflows/devtools_check_repro.yml new
+209
@@ -0,0 +1,209 @@
1 +name: DevTools Check for bug repro
2 +on:
3 + issues:
4 + types: [opened, edited]
5 + issue_comment:
6 + types: [created, edited]
7 +
8 +jobs:
9 + check-repro:
10 + runs-on: ubuntu-latest
11 + steps:
12 + - uses: actions/github-script@v3
13 + with:
14 + github-token: ${{ secrets.GITHUB_TOKEN }}
15 + script: |
16 + const URL_REGEXP = /### Website or app[\r\n]+([^#]+)###/m;
17 + const REPRO_STEPS_REGEXP = /### Repro steps[\r\n]+([^#]+)###/m;
18 + const LABEL_NEEDS_MORE_INFORMATION = "Resolution: Needs More Information";
19 + const LABEL_UNCONFIRMED = "Status: Unconfirmed";
20 +
21 + function debug(...args) {
22 + core.info(args.map(JSON.stringify).join(' '));
23 + }
24 +
25 + if (context.payload.comment) {
26 + debug('Ignoring comment update.');
27 + return;
28 + }
29 +
30 + const user = context.payload.sender.login;
31 + const issue = context.payload.issue;
32 + const body = issue.body;
33 +
34 + const urlMatch = body.match(URL_REGEXP);
35 + const reproStepsMatch = body.match(REPRO_STEPS_REGEXP);
36 +
37 + const url = urlMatch !== null ? urlMatch[1].trim() : null;
38 + const reproSteps = reproStepsMatch !== null ? reproStepsMatch[1].trim() : null;
39 +
40 + if (!url || !reproSteps) {
41 + debug('This issue is not a DevTools bug report.');
42 + return;
43 + }
44 +
45 + debug(`found URL "${url}"`);
46 + debug(`found repro steps "${reproSteps}"`);
47 +
48 + function formatComment(comment) {
49 + return comment
50 + .split("\n")
51 + .map((line) => line.trim())
52 + .join("\n")
53 + .trim();
54 + }
55 +
56 + async function getGitHubActionComments() {
57 + debug(`Loading existing comments...`);
58 +
59 + const comments = await github.issues.listComments({
60 + issue_number: context.issue.number,
61 + owner: context.repo.owner,
62 + repo: context.repo.repo,
63 + });
64 +
65 + return comments.data.filter(comment => {
66 + debug(`comment by user: "${comment.user.login}"`);
67 + return comment.user.login === 'github-actions[bot]';
68 + });
69 + }
70 +
71 + async function getIssueLabels() {
72 + const issues = await github.issues.listLabelsOnIssue({
73 + issue_number: context.issue.number,
74 + owner: context.repo.owner,
75 + repo: context.repo.repo,
76 + });
77 +
78 + return issues.data;
79 + }
80 +
81 + async function closeWithComment(comment) {
82 + if (issue.state !== 'open') {
83 + debug(`Issue is not open`);
84 + return;
85 + }
86 +
87 + const labels = await getIssueLabels();
88 + const label = labels.find(label => label.name === LABEL_UNCONFIRMED);
89 + if (!label) {
90 + debug(`Issue was not opened via DevTools bug report template`);
91 + return;
92 + }
93 +
94 + const comments = await getGitHubActionComments();
95 + if (comments.length > 0) {
96 + debug(`Already commented on issue; won't comment again`);
97 + return;
98 + }
99 +
100 + debug(`Missing required information`);
101 +
102 + await github.issues.addLabels({
103 + issue_number: context.issue.number,
104 + owner: context.repo.owner,
105 + repo: context.repo.repo,
106 + labels: [LABEL_NEEDS_MORE_INFORMATION],
107 + });
108 +
109 + await github.issues.createComment({
110 + issue_number: context.issue.number,
111 + owner: context.repo.owner,
112 + repo: context.repo.repo,
113 + body: formatComment(comment),
114 + });
115 +
116 + await github.issues.update({
117 + issue_number: context.issue.number,
118 + owner: context.repo.owner,
119 + repo: context.repo.repo,
120 + state: 'closed',
121 + });
122 + }
123 +
124 + async function openWithComment(comment) {
125 + if (issue.state !== 'closed') {
126 + debug(`Issue is already open`);
127 + return;
128 + }
129 +
130 + const labels = await getIssueLabels();
131 + const label = labels.find(label => label.name === LABEL_NEEDS_MORE_INFORMATION);
132 + if (!label) {
133 + debug(`Issue was not tagged as needs information`);
134 + return;
135 + }
136 +
137 + const comments = await getGitHubActionComments();
138 + if (comments.length === 0) {
139 + debug(`Issue was closed by someone else; won't reopen`);
140 + return;
141 + }
142 +
143 + debug(`Re-opening closed issue`);
144 +
145 + await github.issues.removeLabel({
146 + issue_number: context.issue.number,
147 + owner: context.repo.owner,
148 + repo: context.repo.repo,
149 + name: LABEL_NEEDS_MORE_INFORMATION,
150 + });
151 +
152 + await github.issues.createComment({
153 + issue_number: context.issue.number,
154 + owner: context.repo.owner,
155 + repo: context.repo.repo,
156 + body: formatComment(comment),
157 + });
158 +
159 + await github.issues.update({
160 + issue_number: context.issue.number,
161 + owner: context.repo.owner,
162 + repo: context.repo.repo,
163 + state: 'open',
164 + });
165 + }
166 +
167 + const PROBABLY_NOT_A_URL_REGEX = /(^Chrome$|^Firefox$| Website)/i;
168 +
169 + const COMMENT_HEADER = `
170 + @${user}: We're sorry you've seen this error. ❤️
171 + `.trim();
172 +
173 + const COMMENT_FOOTER = `
174 + Please help us by providing a link to a CodeSandbox (https://codesandbox.io/s/new), a repository on GitHub, or a minimal code example that reproduces the problem. (Screenshots or videos can also be helpful if they help provide context on how to repro the bug.)
175 +
176 + Here are some tips for providing a minimal example: https://stackoverflow.com/help/mcve
177 +
178 + Issues without repros are automatically closed but we will re-open if you update with repro info.
179 + `.trim();
180 +
181 + if (url.includes("/localhost")) {
182 + closeWithComment(`
183 + ${COMMENT_HEADER}
184 +
185 + Unfortunately the URL you provided ("localhost") is not publicly accessible. (This means that we will not be able to reproduce the problem you're reporting.)
186 +
187 + ${COMMENT_FOOTER}
188 + `);
189 + } else if (url.length < 10 || url.match(PROBABLY_NOT_A_URL_REGEX)) {
190 + closeWithComment(`
191 + ${COMMENT_HEADER}
192 +
193 + It looks like you forgot to specify a valid URL. (This means that we will not be able to reproduce the problem you're reporting.)
194 +
195 + ${COMMENT_FOOTER}
196 + `);
197 + } else if (reproSteps.length < 25) {
198 + closeWithComment(`
199 + ${COMMENT_HEADER}
200 +
201 + Unfortunately, it doesn't look like this issue has enough info for one of us to reproduce and fix it though.
202 +
203 + ${COMMENT_FOOTER}
204 + `);
205 + } else {
206 + openWithComment(`
207 + Thank you for providing repro steps! Re-opening issue now for triage.
208 + `);
209 + }