Skip to content

Commit 0195c7c

Browse files
committed
refactor: centralize Good First Issue labels and remove migration script
Signed-off-by: DeathGun44 <krishnamewara841@gmail.com>
1 parent 3ef0b1e commit 0195c7c

9 files changed

Lines changed: 125 additions & 132 deletions

.github/scripts/bot-gfi-assign-on-comment.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
const fs = require('fs'); // For spam list
88

9-
const GOOD_FIRST_ISSUE_LABEL = 'Good First Issue';
9+
const { GOOD_FIRST_ISSUE_LABEL } = require('./shared/labels.js');
1010
const UNASSIGNED_GFI_SEARCH_URL =
11-
'https://github.com/hiero-ledger/hiero-sdk-python/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22Good%20First%20Issue%22%20no%3Aassignee';
11+
`https://github.com/hiero-ledger/hiero-sdk-python/issues?q=${encodeURIComponent(`is:issue state:open label:"${GOOD_FIRST_ISSUE_LABEL}" no:assignee`)}`;
1212

1313
const SPAM_LIST_PATH = '.github/spam-list.txt';
1414

.github/scripts/bot-gfi-candidate-notification.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Script to notify the team when a Good First Issue Candidate is created.
22

3+
const { GOOD_FIRST_ISSUE_CANDIDATE_LABEL } = require('./shared/labels.js');
34
const marker = '<!-- GFI Candidate Notification -->';
45
const TEAM_ALIAS = '@hiero-ledger/hiero-sdk-good-first-issue-support';
56

@@ -53,7 +54,7 @@ module.exports = async ({ github, context }) => {
5354
}
5455

5556
// Only handle Good First Issue Candidate
56-
if (label.name.toLowerCase() !== 'good first issue candidate') {
57+
if (label.name.toLowerCase() !== GOOD_FIRST_ISSUE_CANDIDATE_LABEL.toLowerCase()) {
5758
return;
5859
}
5960

.github/scripts/bot-next-issue-recommendation.js

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
1-
const { BEGINNER_LABEL, INTERMEDIATE_LABEL, ADVANCED_LABEL } = require('./shared/labels.js');
1+
const {
2+
GOOD_FIRST_ISSUE_LABEL,
3+
BEGINNER_LABEL,
4+
INTERMEDIATE_LABEL,
5+
ADVANCED_LABEL,
6+
isSafeLabel,
7+
} = require('./shared/labels.js');
8+
9+
for (const label of [GOOD_FIRST_ISSUE_LABEL, BEGINNER_LABEL, INTERMEDIATE_LABEL, ADVANCED_LABEL]) {
10+
if (!isSafeLabel(label)) {
11+
throw new Error(`Invalid configured label: ${label}`);
12+
}
13+
}
214

315
const SUPPORTED_GFI_REPOS = [
416
'hiero-sdk-cpp',
@@ -61,7 +73,7 @@ module.exports = async ({ github, context, core }) => {
6173
// Determine issue difficulty level
6274
const difficultyLevels = {
6375
beginner: labelSet.has(BEGINNER_LABEL.toLowerCase()),
64-
goodFirstIssue: labelSet.has('good first issue'),
76+
goodFirstIssue: labelSet.has(GOOD_FIRST_ISSUE_LABEL.toLowerCase()),
6577
intermediate: labelSet.has(INTERMEDIATE_LABEL.toLowerCase()),
6678
advanced: labelSet.has(ADVANCED_LABEL.toLowerCase()),
6779
};
@@ -83,21 +95,21 @@ module.exports = async ({ github, context, core }) => {
8395
let isFallback = false;
8496

8597
recommendedIssues = await searchIssues(github, core, repoOwner, repoName, BEGINNER_LABEL);
86-
recommendedLabel = 'Beginner';
98+
recommendedLabel = BEGINNER_LABEL;
8799

88100
if (recommendedIssues.length === 0) {
89101
isFallback = true;
90-
recommendedIssues = await searchIssues(github, core, repoOwner, repoName, 'good first issue');
91-
recommendedLabel = 'Good First Issue';
102+
recommendedIssues = await searchIssues(github, core, repoOwner, repoName, GOOD_FIRST_ISSUE_LABEL);
103+
recommendedLabel = GOOD_FIRST_ISSUE_LABEL;
92104
}
93105

94106

95107
// Remove the issue they just solved
96108
recommendedIssues = recommendedIssues.filter(i => i.number !== issueNumber);
97109

98110
// Generate and post comment
99-
const completedLabel = difficultyLevels.goodFirstIssue ? 'Good First Issue' : 'Beginner';
100-
const completedLabelText = completedLabel === 'Beginner' ? 'Beginner issue' : completedLabel;
111+
const completedLabel = difficultyLevels.goodFirstIssue ? GOOD_FIRST_ISSUE_LABEL : BEGINNER_LABEL;
112+
const completedLabelText = completedLabel === BEGINNER_LABEL ? `${BEGINNER_LABEL} issue` : completedLabel;
101113
const recommendationMeta = {
102114
completedLabelText,
103115
recommendedLabel,
@@ -172,7 +184,7 @@ async function generateAndPostComment(github, context, core, prNumber, recommend
172184
`org:${context.repo.owner}`,
173185
'archived:false',
174186
'no:assignee',
175-
'(label:"good first issue" OR label:"skill: good first issue")',
187+
`label:"${GOOD_FIRST_ISSUE_LABEL}"`,
176188
`(${repoQuery})`,
177189
].join(' ');
178190

.github/scripts/coderabbit_plan_trigger.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Script to trigger CodeRabbit plan for intermediate and advanced issues
22

33
const CODERABBIT_MARKER = '<!-- CodeRabbit Plan Trigger -->';
4-
const { DIFFICULTY_LABELS } = require('./shared/labels.js');
4+
const { DIFFICULTY_LABELS, GOOD_FIRST_ISSUE_LABEL } = require('./shared/labels.js');
55

66
async function triggerCodeRabbitPlan(github, owner, repo, issue, marker = CODERABBIT_MARKER, isDryRun = false) {
77
const comment = `${marker} @coderabbitai plan`;
@@ -33,8 +33,12 @@ async function triggerCodeRabbitPlan(github, owner, repo, issue, marker = CODERA
3333
}
3434

3535
function hasBeginnerOrHigherLabel(issue, label) {
36-
// Check if issue has a difficulty label (case-insensitive)
37-
const allowed = new Set(DIFFICULTY_LABELS.map(d => d.toLowerCase()));
36+
// Only beginner+ labels qualify here; GFI gets its own CodeRabbit plan
37+
// trigger via the assignment bot chain (bot-gfi-assign-on-comment.js).
38+
const beginnerPlus = DIFFICULTY_LABELS
39+
.filter(d => d !== GOOD_FIRST_ISSUE_LABEL)
40+
.map(d => d.toLowerCase());
41+
const allowed = new Set(beginnerPlus);
3842

3943
const hasAllowedLabel = issue.labels?.some(l => allowed.has(l?.name?.toLowerCase()));
4044

.github/scripts/cron-admin-update-spam-list.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
*/
99

1010
const fs = require('fs').promises;
11+
const { GOOD_FIRST_ISSUE_LABEL, isSafeLabel } = require('./shared/labels.js');
12+
13+
if (!isSafeLabel(GOOD_FIRST_ISSUE_LABEL)) {
14+
throw new Error(`Invalid GOOD_FIRST_ISSUE_LABEL: ${GOOD_FIRST_ISSUE_LABEL}`);
15+
}
1116

1217
const SPAM_LIST_PATH = '.github/spam-list.txt';
1318
const dryRun = (process.env.DRY_RUN || 'false').toString().toLowerCase() === 'true';
@@ -137,7 +142,7 @@ module.exports = async ({github, context, core}) => {
137142
},
138143
{
139144
name: 'rehabilitated PRs',
140-
query: `repo:${owner}/${repo} is:pr is:merged label:"Good First Issue"`,
145+
query: `repo:${owner}/${repo} is:pr is:merged label:"${GOOD_FIRST_ISSUE_LABEL}"`,
141146
process: async (pr) => {
142147
if (!pr.user?.login) {
143148
console.log(`Skipping PR #${pr.number}: user account unavailable`);

.github/scripts/migrate-skill-labels.sh

Lines changed: 0 additions & 89 deletions
This file was deleted.

.github/scripts/shared/labels.js

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,28 @@
88
* corresponding workflow YAML `if:` conditions (which cannot import JS).
99
*
1010
* Environment variable overrides are supported for per-workflow customization:
11+
* GOOD_FIRST_ISSUE_LABEL, GOOD_FIRST_ISSUE_CANDIDATE_LABEL,
1112
* BEGINNER_LABEL, INTERMEDIATE_LABEL, ADVANCED_LABEL
1213
*/
1314

14-
const BEGINNER_LABEL = process.env.BEGINNER_LABEL?.trim() || 'skill: beginner';
15-
const INTERMEDIATE_LABEL = process.env.INTERMEDIATE_LABEL?.trim() || 'skill: intermediate';
16-
const ADVANCED_LABEL = process.env.ADVANCED_LABEL?.trim() || 'skill: advanced';
15+
const GOOD_FIRST_ISSUE_LABEL = process.env.GOOD_FIRST_ISSUE_LABEL?.trim() || 'Good First Issue';
16+
const GOOD_FIRST_ISSUE_CANDIDATE_LABEL = process.env.GOOD_FIRST_ISSUE_CANDIDATE_LABEL?.trim() || 'Good First Issue Candidate';
17+
const BEGINNER_LABEL = process.env.BEGINNER_LABEL?.trim() || 'skill: beginner';
18+
const INTERMEDIATE_LABEL = process.env.INTERMEDIATE_LABEL?.trim() || 'skill: intermediate';
19+
const ADVANCED_LABEL = process.env.ADVANCED_LABEL?.trim() || 'skill: advanced';
1720

1821
/**
19-
* All difficulty labels as an array, for scripts that need to check
20-
* whether an issue has *any* difficulty label (e.g. coderabbit_plan_trigger).
22+
* All difficulty labels as an array, ordered by ascending difficulty.
23+
*
24+
* Scripts that need to check whether an issue has *any* difficulty label
25+
* (e.g. coderabbit_plan_trigger) should test against this array.
2126
*/
22-
const DIFFICULTY_LABELS = [BEGINNER_LABEL, INTERMEDIATE_LABEL, ADVANCED_LABEL];
27+
const DIFFICULTY_LABELS = [
28+
GOOD_FIRST_ISSUE_LABEL,
29+
BEGINNER_LABEL,
30+
INTERMEDIATE_LABEL,
31+
ADVANCED_LABEL,
32+
];
2333

2434
/**
2535
* Validates a label string for safe use in API queries.
@@ -35,10 +45,12 @@ const DIFFICULTY_LABELS = [BEGINNER_LABEL, INTERMEDIATE_LABEL, ADVANCED_LABEL];
3545
* @returns {boolean} True if the value is safe for use in queries.
3646
*/
3747
function isSafeLabel(value) {
38-
return typeof value === 'string' && value.length > 0 && /^[a-zA-Z0-9._/: \-]+$/.test(value);
48+
return typeof value === 'string' && value.trim().length > 0 && /^[a-zA-Z0-9._/: \-]+$/.test(value);
3949
}
4050

4151
module.exports = {
52+
GOOD_FIRST_ISSUE_LABEL,
53+
GOOD_FIRST_ISSUE_CANDIDATE_LABEL,
4254
BEGINNER_LABEL,
4355
INTERMEDIATE_LABEL,
4456
ADVANCED_LABEL,

0 commit comments

Comments
 (0)