From 5ba4d45e2aeb89ca78ae79cf2cbba13941d3c96f Mon Sep 17 00:00:00 2001 From: GitHub Workshop Bot Date: Sun, 17 May 2026 18:29:20 -0700 Subject: [PATCH] chore: enforce challenge 2 issue format and guidance --- .../challenge-02-first-issue.yml | 22 ++++-- .../challenge-02-first-issue.yml | 22 ++++-- .../workflows/autograder-issue-filed.yml | 78 ++++++++++++++++++- 3 files changed, 111 insertions(+), 11 deletions(-) diff --git a/admin/qa-bundle/learning-room/.github/ISSUE_TEMPLATE/challenge-02-first-issue.yml b/admin/qa-bundle/learning-room/.github/ISSUE_TEMPLATE/challenge-02-first-issue.yml index 48bdfcc2..9e8f2298 100644 --- a/admin/qa-bundle/learning-room/.github/ISSUE_TEMPLATE/challenge-02-first-issue.yml +++ b/admin/qa-bundle/learning-room/.github/ISSUE_TEMPLATE/challenge-02-first-issue.yml @@ -16,11 +16,23 @@ body: 1. Open `docs/welcome.md` and look for a line that contains `TODO` -- this marks something that needs fixing. 2. Go to the **Issues** tab and select **New issue**. - 3. Write a clear, descriptive title (not just "Fix TODO"). - 4. In the description, explain: - - **What** needs to change - - **Where** the problem is (file name and what section) - - **Why** it matters + 3. Write a clear, descriptive title (not just "Fix TODO"). + 4. In the description, use this required format: + - `What:` what needs to change + - `Where:` where the problem is (must include `docs/welcome.md`) + - `Why:` why the change matters + - Mention the exact `TODO` text you found + + ### Required format (checked automatically) + + Use this structure in your issue description: + + ```text + What: Replace the placeholder TODO with real welcome text. + Where: docs/welcome.md, intro section. + Why: New contributors need clear context when they open the file. + TODO found: TODO: Add a short workshop welcome paragraph. + ``` ### What makes a good issue title? diff --git a/learning-room/.github/ISSUE_TEMPLATE/challenge-02-first-issue.yml b/learning-room/.github/ISSUE_TEMPLATE/challenge-02-first-issue.yml index 48bdfcc2..9e8f2298 100644 --- a/learning-room/.github/ISSUE_TEMPLATE/challenge-02-first-issue.yml +++ b/learning-room/.github/ISSUE_TEMPLATE/challenge-02-first-issue.yml @@ -16,11 +16,23 @@ body: 1. Open `docs/welcome.md` and look for a line that contains `TODO` -- this marks something that needs fixing. 2. Go to the **Issues** tab and select **New issue**. - 3. Write a clear, descriptive title (not just "Fix TODO"). - 4. In the description, explain: - - **What** needs to change - - **Where** the problem is (file name and what section) - - **Why** it matters + 3. Write a clear, descriptive title (not just "Fix TODO"). + 4. In the description, use this required format: + - `What:` what needs to change + - `Where:` where the problem is (must include `docs/welcome.md`) + - `Why:` why the change matters + - Mention the exact `TODO` text you found + + ### Required format (checked automatically) + + Use this structure in your issue description: + + ```text + What: Replace the placeholder TODO with real welcome text. + Where: docs/welcome.md, intro section. + Why: New contributors need clear context when they open the file. + TODO found: TODO: Add a short workshop welcome paragraph. + ``` ### What makes a good issue title? diff --git a/learning-room/.github/workflows/autograder-issue-filed.yml b/learning-room/.github/workflows/autograder-issue-filed.yml index fca56e97..ed2d2603 100644 --- a/learning-room/.github/workflows/autograder-issue-filed.yml +++ b/learning-room/.github/workflows/autograder-issue-filed.yml @@ -42,9 +42,43 @@ jobs: uses: actions/github-script@v7 with: script: | + const issue = context.payload.issue; + const title = (issue.title || '').trim(); + const bodyText = (issue.body || '').trim(); + const genericTitlePattern = /^(fix|bug|update|todo|fix\s+todo|update\s+file)$/i; + const hasSpecificTitle = title.length >= 12 && !genericTitlePattern.test(title); + + const hasWhatLine = /^\s*what\s*:/im.test(bodyText); + const hasWhereLine = /^\s*where\s*:/im.test(bodyText); + const hasWhyLine = /^\s*why\s*:/im.test(bodyText); + const hasFileReference = /\bdocs\/welcome\.md\b/i.test(bodyText); + const hasTodoReference = /\bTODO\b/i.test(bodyText); + + const missing = []; + if (!hasSpecificTitle) { + missing.push('Use a specific, descriptive title (not generic like "Bug" or "Fix TODO").'); + } + if (!hasWhatLine) { + missing.push('Add a `What:` line describing what must change.'); + } + if (!hasWhereLine) { + missing.push('Add a `Where:` line that includes `docs/welcome.md`.'); + } + if (!hasWhyLine) { + missing.push('Add a `Why:` line explaining why the change matters.'); + } + if (!hasFileReference) { + missing.push('Reference `docs/welcome.md` in the issue description.'); + } + if (!hasTodoReference) { + missing.push('Mention the `TODO` you found in `docs/welcome.md`.'); + } + + const passesInstructionCheck = missing.length === 0; const count = parseInt('${{ steps.count.outputs.count }}', 10); const isFirst = count === 1; - const body = isFirst + const body = passesInstructionCheck + ? (isFirst ? [ '## Challenge 2: First issue filed!', '', @@ -60,9 +94,51 @@ jobs: '## Challenge 2: Another issue filed', '', 'You have now filed ' + count + ' issues in this Learning Room. Keep going!' + ].join('\n')) + : [ + '## Challenge 2: Needs revision', + '', + 'Thanks for filing an issue. To complete Challenge 2, update this issue so it follows the required format:', + '', + '- Use a specific title (not generic).', + '- Include lines for `What:`, `Where:`, and `Why:`.', + '- Mention `docs/welcome.md` and the `TODO` you found.', + '', + '### Missing items', + ...missing.map(item => '- ' + item), + '', + 'After editing the issue, your facilitator can re-run the Challenge 2 check from Actions.' ].join('\n'); const MARKER = '## Challenge 2:'; try { + const labelsToAdd = passesInstructionCheck ? ['challenge-2-complete'] : ['challenge-2-needs-revision']; + const labelsToRemove = passesInstructionCheck ? ['challenge-2-needs-revision'] : ['challenge-2-complete']; + + try { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + labels: labelsToAdd + }); + } catch (labelErr) { + console.log('Could not add Challenge 2 status label:', labelErr.message); + } + + for (const labelName of labelsToRemove) { + try { + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + name: labelName + }); + } catch (removeErr) { + // Ignore when label does not exist yet. + console.log('Label remove skipped:', removeErr.message); + } + } + const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo,