2626 issue-labels :
2727 required : true
2828 type : string # JSON stringified array
29+ issue-entry-id-form :
30+ required : true
31+ type : string
32+ default : entry.340898780
33+ issue-entry-id-regression :
34+ required : true
35+ type : string
36+ default : entry.1698032149
37+ issue-entry-id-team :
38+ required : true
39+ type : string
40+ default : entry.1228565618
2941
3042jobs :
3143 post-rca-form :
@@ -40,56 +52,114 @@ jobs:
4052 OWNER_NAME : ${{ inputs.repo-owner }}
4153 REPO_NAME : ${{ inputs.repo-name }}
4254 ISSUE_NUMBER : ${{ inputs.issue-number }}
55+ ENTRY_ID_FORM : ${{ inputs.issue-entry-id-form }}
56+ ENTRY_ID_REGRESSION : ${{ inputs.issue-entry-id-regression }}
57+ ENTRY_ID_TEAM : ${{ inputs.issue-entry-id-team }}
4358 with :
4459 github-token : ${{ secrets.GITHUB_TOKEN }}
4560 script : |
46- const googleFormBaseUrl = process.env.GOOGLE_FORM_BASE_URL;
47- const owner_name = process.env.OWNER_NAME;
48- const repo_name = process.env.REPO_NAME;
49- const issue_number = parseInt(process.env.ISSUE_NUMBER);
50-
51- const allowedLabels = JSON.parse(process.env.ISSUE_LABELS);
52-
53- // Fetch issue details to get the assignees
54- const { data: issue } = await github.rest.issues.get({
55- owner: owner_name,
56- repo: repo_name,
57- issue_number: issue_number,
58- });
59-
60- const prefixes = ['team-', 'regression-'];
61-
62- const wildcardLabels = issue.labels
63- .map(({ name }) => name)
64- .filter(name => prefixes.some(pref => name.startsWith(pref)));
61+ const {
62+ GOOGLE_FORM_BASE_URL: baseUrl,
63+ OWNER_NAME: owner,
64+ REPO_NAME: repo,
65+ ISSUE_NUMBER: issueNumberStr,
66+ ISSUE_LABELS: issueLabelsJson,
67+ ENTRY_ID_FORM: entryIssue,
68+ ENTRY_ID_REGRESSION: entryRegression,
69+ ENTRY_ID_TEAM: entryTeam
70+ } = process.env;
6571
66- // checks if it has a label that matches exactly OR has any wildcard labels
67- const hasAllowedLabel = issue.labels
68- .some(({ name }) => allowedLabels.includes(name)) || wildcardLabels.length > 0;
69-
70- if (!hasAllowedLabel) {
71- console.log(`❌ Issue #${issue_number} skipped — no matching label.`);
72- return;
72+ const issueNumber = parseInt(issueNumberStr);
73+ const allowedLabels = JSON.parse(issueLabelsJson);
74+
75+ async function getIssueDetails() {
76+ const { data: issue } = await github.rest.issues.get({
77+ owner,
78+ repo,
79+ issue_number: issueNumber,
80+ });
81+ return issue;
7382 }
7483
75- // TODO add wildcard labels to the form url
84+ // Check if issue has required labels
85+ function hasRequiredLabels(issue, allowedLabels) {
86+ return issue.labels.some(l => allowedLabels.includes(l.name));
87+ }
88+
89+ function extractTeamAndRegressionLabels(issueLabels) {
90+ const teamLabels = [];
91+ const regressionLabels = [];
7692
77- const assignees = issue.assignees.map(user => `@${user.login}`).join(', ');
78- const formUrl = `${googleFormBaseUrl}${issue_number}`;
79- const message = `
80- Hi ${assignees},
93+ // fills every label into the arrays
94+ for (const { name } of issueLabels) {
95+ if (name.startsWith('team-')) {
96+ teamLabels.push(name.slice('team-'.length));
97+ }
98+ if (name.startsWith('regression-')) {
99+ regressionLabels.push(name.slice('regression-'.length));
100+ }
101+ }
102+
103+ return { teamLabels, regressionLabels };
104+ }
105+
106+ // Build google form URL Form URL
107+ function buildFormUrl(baseUrl, entryIssue, entryRegression, entryTeam, issueNumber, regressionLabels, teamLabels) {
108+ const formUrlObj = new URL(baseUrl);
109+ formUrlObj.searchParams.append(entryIssue, issueNumber.toString());
110+ // works if empty
111+ formUrlObj.searchParams.append(entryRegression, regressionLabels.join(','));
112+ formUrlObj.searchParams.append(entryTeam, teamLabels.join(','));
113+ return formUrlObj.toString();
114+ }
115+
116+ async function postComment(owner, repo, issueNumber, assignees, formUrl) {
117+ const assigneeMentions = assignees.map(u => `@${u.login}`).join(', ');
118+ const body = `
119+ Hi ${assigneeMentions},
81120
82121 This issue has been closed. Please complete this RCA form:
83122 ${formUrl}
84-
123+
85124 <!-- AUTO-FORM -->
86- `;
87-
88- // Post the comment on the closed issue
89- await github.rest.issues.createComment({
90- owner: owner_name,
91- repo: repo_name,
92- issue_number: issue_number,
93- body: message,
94- });
95- console.log(`✅ Comment posted on issue #${issue_number}`);
125+ `;
126+
127+ await github.rest.issues.createComment({
128+ owner,
129+ repo,
130+ issue_number: issueNumber,
131+ body,
132+ });
133+
134+ console.log(`✅ Comment posted on issue #${issueNumber}`);
135+ }
136+
137+
138+ async function main() {
139+ try {
140+ const issue = await getIssueDetails();
141+
142+ if (!hasRequiredLabels(issue, allowedLabels)) {
143+ console.log(`❌ Issue #${issueNumber} skipped — no matching label.`);
144+ return;
145+ }
146+
147+ const { teamLabels, regressionLabels } = extractTeamAndRegressionLabels(issue.labels);
148+ const formUrl = buildFormUrl(
149+ baseUrl,
150+ entryIssue,
151+ entryRegression,
152+ entryTeam,
153+ issueNumber,
154+ regressionLabels,
155+ teamLabels
156+ );
157+
158+ await postComment(owner, repo, issueNumber, issue.assignees, formUrl);
159+ } catch (error) {
160+ console.error(`Error processing issue #${issueNumber}: ${error.message}`);
161+ throw error;
162+ }
163+ }
164+
165+ main();
0 commit comments