Skip to content

Commit eb89975

Browse files
authored
Merge pull request #152 from exploreriii/shared-libraries-guards
feat: dynamic comments
2 parents f090551 + c8cc9df commit eb89975

5 files changed

Lines changed: 180 additions & 33 deletions

File tree

.github/scripts/lib/comments/difficulty-02-beginner.js

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,42 @@
1212
* @param {string} params.browseGfiUrl - URL to browse available Good First Issues
1313
* @returns {string} Formatted markdown message explaining the restriction
1414
*/
15+
const {
16+
ISSUE_TYPES,
17+
ELIGIBILITY_REQUIREMENTS,
18+
} = require('../eligibility/requirements');
19+
1520
const beginnerRejection = ({
1621
username,
1722
completedGfiCount,
1823
browseGfiUrl,
1924
}) => {
20-
const gfiPlural = completedGfiCount === 1 ? '' : 's';
25+
const req =
26+
ELIGIBILITY_REQUIREMENTS[ISSUE_TYPES.BEGINNER];
27+
28+
const gfiRequirement =
29+
req.prerequisites.find(p => p.type === 'gfi');
30+
31+
const requiredCount = gfiRequirement.requiredCount;
32+
const met = completedGfiCount >= requiredCount;
2133

2234
return `Hi @${username},
2335
2436
Thank you for your interest in contributing — we’re glad to see you here.
2537
26-
This issue is labeled **Beginner**, which is intended as the next step after completing a **Good First Issue**.
38+
This issue is labeled **Beginner**, which is intended as the next step after completing **Good First Issues (GFIs)**.
2739
28-
**Requirement:**
29-
- Completion of **one Good First Issue**
40+
**Requirements:**
41+
- Completion of **${requiredCount} Good First Issue${requiredCount === 1 ? '' : 's'}**
3042
3143
**Your progress:**
32-
- Completed **${completedGfiCount}** Good First Issue${gfiPlural}
44+
- Good First Issues completed: **${completedGfiCount} / ${requiredCount}** ${met ? '✅' : '❌'}
45+
46+
To build the required experience, please work on a GFI first:
3347
34-
You can find available tasks here:
3548
**[Browse unassigned Good First Issues](${browseGfiUrl})**
3649
37-
Once you’ve completed a GFI, feel free to come back and request this issue again.`;
50+
Once the requirement is met, feel free to come back and request this issue again.`;
3851
};
3952

4053
module.exports = {

.github/scripts/lib/comments/difficulty-03-intermediate.js

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,42 @@
1313
* @param {string} params.browseBeginnerUrl - URL to browse Beginner issues
1414
* @returns {string} Formatted markdown message explaining the restriction
1515
*/
16+
const {
17+
ISSUE_TYPES,
18+
ELIGIBILITY_REQUIREMENTS,
19+
} = require('../eligibility/requirements');
20+
1621
const INTERMEDIATE_GUARD_MARKER = '<!-- Intermediate Issue Guard -->';
1722

1823
const intermediateRejection = ({
1924
username,
20-
completedGfiCount,
21-
hasBeginner,
22-
browseGfiUrl,
25+
completedBeginnerCount,
2326
browseBeginnerUrl,
2427
}) => {
25-
const gfiPlural = completedGfiCount === 1 ? '' : 's';
26-
const reasons = [];
28+
const req =
29+
ELIGIBILITY_REQUIREMENTS[ISSUE_TYPES.INTERMEDIATE];
2730

28-
if (completedGfiCount === 0) {
29-
reasons.push('• You have not completed a **Good First Issue** yet');
30-
}
31+
const beginnerReq =
32+
req.prerequisites.find(p => p.type === 'beginner');
3133

32-
if (!hasBeginner) {
33-
reasons.push('• You have not completed a **Beginner issue** yet');
34-
}
34+
const requiredCount = beginnerReq.requiredCount;
35+
const met = completedBeginnerCount >= requiredCount;
3536

3637
return `${INTERMEDIATE_GUARD_MARKER}
3738
Hi @${username}, thank you for your interest in this issue.
3839
39-
This issue is labeled **Intermediate**, which means it requires some prior experience with the project.
40+
This issue is labeled **Intermediate**, which requires prior experience working on **Beginner issues**.
4041
41-
**Why you can’t be assigned right now:**
42-
${reasons.join('\n')}
42+
**Requirements:**
43+
- Completion of **${requiredCount} Beginner issue${requiredCount === 1 ? '' : 's'}**
4344
44-
**Your progress so far:**
45-
- Completed **${completedGfiCount}** Good First Issue${gfiPlural}
46-
- Beginner issue completed: **${hasBeginner ? 'Yes' : 'No'}**
45+
**Your progress:**
46+
- Beginner issues completed: **${completedBeginnerCount} / ${requiredCount}** ${met ? '✅' : '❌'}
4747
48-
**Suggested next steps:**
49-
- [Browse unassigned Good First Issues](${browseGfiUrl})
48+
**Suggested next steps:**
5049
- [Browse unassigned Beginner issues](${browseBeginnerUrl})
5150
52-
Once you meet the requirements, you’re welcome to come back and request this issue again.`;
51+
Once the requirement is met, you’re welcome to come back and request this issue again.`;
5352
};
5453

5554
module.exports = {

.github/scripts/lib/comments/difficulty-04-advanced.js

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,40 @@
1212
* @param {string} params.suggestionUrl - URL to suggested issues - pass advanced URL
1313
* @returns {string} Formatted markdown message explaining the restriction
1414
*/
15+
const {
16+
ISSUE_TYPES,
17+
ELIGIBILITY_REQUIREMENTS,
18+
} = require('../eligibility/requirements');
19+
1520
const advancedRejection = ({
1621
username,
17-
intermediateCount,
22+
completedIntermediateCount,
1823
suggestionLabel,
1924
suggestionUrl,
20-
}) => `Hi @${username}, I can’t assign you to this issue just yet.
25+
}) => {
26+
const req =
27+
ELIGIBILITY_REQUIREMENTS[ISSUE_TYPES.ADVANCED];
28+
29+
const intermediateReq =
30+
req.prerequisites.find(p => p.type === 'intermediate');
31+
32+
const requiredCount = intermediateReq.requiredCount;
33+
const met = completedIntermediateCount >= requiredCount;
34+
35+
return `Hi @${username}, I can’t assign you to this issue just yet.
2136
2237
**Why?**
2338
Advanced issues involve higher-risk changes to core parts of the codebase. They typically require more extensive testing and may impact automation and CI behavior.
2439
2540
**Requirements:**
26-
- Completion of at least **2 intermediate issues**
27-
(you have completed **${intermediateCount}**)
41+
- Completion of **${requiredCount} Intermediate issue${requiredCount === 1 ? '' : 's'}**
2842
29-
To build the required experience, please review our **[${suggestionLabel}](${suggestionUrl})** tasks. Once you’ve completed a few more, you’ll be eligible to work on advanced issues.`;
43+
**Your progress:**
44+
- Intermediate issues completed: **${completedIntermediateCount} / ${requiredCount}** ${met ? '✅' : '❌'}
45+
46+
To build the required experience, please review our **[${suggestionLabel}](${suggestionUrl})** tasks. Once the requirement is met, you’ll be eligible to work on advanced issues.`;
47+
};
3048

3149
module.exports = {
3250
advancedRejection,
33-
};
51+
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// comments/renderRequirements.js
2+
const { ELIGIBILITY_REQUIREMENTS } =
3+
require('../eligibility/requirements');
4+
5+
const renderRequirements = ({
6+
issueType,
7+
stats, // counts collected by caller
8+
}) => {
9+
const req = ELIGIBILITY_REQUIREMENTS[issueType];
10+
const lines = [];
11+
12+
if (req.capacity) {
13+
const max =
14+
typeof req.capacity === 'object'
15+
? req.capacity.maxOpenIssues
16+
: stats.maxAllowed;
17+
18+
lines.push(
19+
`- Open assignments: **${stats.openAssignedCount} / ${max}**`
20+
);
21+
}
22+
23+
for (const prereq of req.prerequisites || []) {
24+
const actual = stats[`${prereq.type}Completed`] ?? 0;
25+
const met = actual >= prereq.requiredCount;
26+
27+
lines.push(
28+
`- ${prereq.type} issues completed: **${actual} / ${prereq.requiredCount}** ${met ? '✅' : '❌'}`
29+
);
30+
}
31+
32+
return lines.join('\n');
33+
};
34+
35+
module.exports = { renderRequirements };
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
const ISSUE_TYPES = {
2+
GFI: 'gfi',
3+
BEGINNER: 'beginner',
4+
INTERMEDIATE: 'intermediate',
5+
ADVANCED: 'advanced',
6+
};
7+
8+
const ELIGIBILITY_REQUIREMENTS = {
9+
[ISSUE_TYPES.GFI]: {
10+
bypass: {
11+
team: true,
12+
},
13+
spamPolicy: {
14+
allowed: true,
15+
maxOpenIssues: {
16+
spamListed: 1,
17+
normal: 2,
18+
},
19+
},
20+
capacity: true,
21+
prerequisites: [],
22+
},
23+
24+
[ISSUE_TYPES.BEGINNER]: {
25+
bypass: {
26+
team: true,
27+
},
28+
spamPolicy: {
29+
allowed: false,
30+
},
31+
capacity: {
32+
maxOpenIssues: 2,
33+
},
34+
prerequisites: [
35+
{
36+
type: 'gfi',
37+
requiredCount: 1,
38+
},
39+
],
40+
},
41+
42+
[ISSUE_TYPES.INTERMEDIATE]: {
43+
bypass: {
44+
team: true,
45+
},
46+
spamPolicy: {
47+
allowed: false,
48+
},
49+
capacity: {
50+
maxOpenIssues: 2,
51+
},
52+
prerequisites: [
53+
{
54+
type: 'beginner',
55+
requiredCount: 1,
56+
},
57+
],
58+
},
59+
60+
[ISSUE_TYPES.ADVANCED]: {
61+
bypass: {
62+
committer: true,
63+
},
64+
spamPolicy: {
65+
allowed: false,
66+
},
67+
capacity: {
68+
maxOpenIssues: 2,
69+
},
70+
prerequisites: [
71+
{
72+
type: 'intermediate',
73+
requiredCount: 1,
74+
},
75+
],
76+
},
77+
};
78+
79+
module.exports = {
80+
ISSUE_TYPES,
81+
ELIGIBILITY_REQUIREMENTS,
82+
};

0 commit comments

Comments
 (0)