Skip to content

Commit c8754b4

Browse files
GitHub Workshop Botclaude
andcommitted
fix(challenge-07): make merge-conflict practice actually create a conflict for self-paced students
seedMergeConflict() only replaced a [TODO] placeholder in docs/welcome.md that Challenge 1 always resolves first, so it silently no-op'd for every self-paced student and no facilitator exists to trigger a conflict by hand (Community-Access/support#61). Replace it with ensureMergeConflictPractice(), which opens a dedicated branch, commits a different edit to the same line on that branch and on main, and opens a PR between them so GitHub reports a real, resolvable conflict regardless of prior challenge state. Also correct four chapters (06, 07, 08, 09) that told students to look for a specific quoted issue title the automation never actually creates; real challenge issues are always titled "Challenge N: <name>", not "Chapter N.M: <name>". Chapter 8's walkthrough was also missing the label-triage step its real issue requires, and Chapter 9's triage practice has no dedicated issue of its own, so its evidence now correctly routes to the Challenge 8 issue. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 444fbe0 commit c8754b4

14 files changed

Lines changed: 357 additions & 146 deletions
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// Regression tests for Challenge 7 merge conflict seeding. The previous
2+
// implementation replaced a `[TODO]` placeholder in docs/welcome.md on main,
3+
// but that placeholder is always resolved back in Challenge 1, long before
4+
// Challenge 7 opens - so the seed silently skipped every time and no student
5+
// ever saw a real conflict (Community-Access/support#61, 2026-07-05). The
6+
// fix opens a dedicated branch and commits a different edit to the same line
7+
// on that branch and on main, then opens a PR between them, so a genuine
8+
// conflict exists regardless of what any earlier challenge did.
9+
const test = require('node:test');
10+
const assert = require('node:assert/strict');
11+
const path = require('node:path');
12+
13+
process.env.GITHUB_TOKEN = 'test-token';
14+
process.env.GITHUB_REPOSITORY = 'org/room';
15+
process.env.START_CHALLENGE = '';
16+
process.env.GITHUB_EVENT_NAME = '';
17+
process.env.CLOSED_ISSUE_TITLE = '';
18+
19+
// The script resolves its issue-template directory from the working
20+
// directory, so requiring it must happen from inside learning-room/.
21+
process.chdir(path.join(__dirname, '..', '..', '..', 'learning-room'));
22+
23+
const { ensureMergeConflictPractice } = require('../../../learning-room/.github/scripts/challenge-progression');
24+
25+
const WELCOME_CONTENT = 'Welcome to the Learning Room!\n';
26+
const WELCOME_SHA = 'welcome-sha';
27+
28+
function fakeRequest(overrides = {}) {
29+
const calls = [];
30+
const request = async (route, options = {}) => {
31+
const method = options.method || 'GET';
32+
calls.push({ method, route, body: options.body });
33+
for (const [pattern, handler] of Object.entries(overrides)) {
34+
const [overrideMethod, routePrefix] = pattern.split(' ');
35+
if (method === overrideMethod && route.startsWith(routePrefix)) {
36+
return handler({ route, options });
37+
}
38+
}
39+
if (method === 'GET' && route.startsWith('/repos/org/room/pulls?')) {
40+
return [];
41+
}
42+
if (method === 'GET' && route.startsWith('/repos/org/room/git/ref/heads/main')) {
43+
return { object: { sha: 'main-sha' } };
44+
}
45+
if (method === 'GET' && route.startsWith('/repos/org/room/contents/docs/welcome.md')) {
46+
return { content: Buffer.from(WELCOME_CONTENT).toString('base64'), sha: WELCOME_SHA };
47+
}
48+
if (method === 'POST' && route === '/repos/org/room/pulls') {
49+
return { number: 99, html_url: 'https://example.test/pull/99' };
50+
}
51+
return null;
52+
};
53+
return { calls, request };
54+
}
55+
56+
test('opens a branch, two conflicting edits, a PR, and comments the issue', async () => {
57+
const { calls, request } = fakeRequest();
58+
59+
await ensureMergeConflictPractice(11, request);
60+
61+
const refPosts = calls.filter((c) => c.method === 'POST' && c.route === '/repos/org/room/git/refs');
62+
assert.equal(refPosts.length, 1);
63+
assert.equal(refPosts[0].body.ref, 'refs/heads/challenge-7/conflict-practice');
64+
assert.equal(refPosts[0].body.sha, 'main-sha');
65+
66+
const filePuts = calls.filter((c) => c.method === 'PUT');
67+
assert.equal(filePuts.length, 2);
68+
assert.equal(filePuts[0].body.branch, 'challenge-7/conflict-practice');
69+
assert.equal(filePuts[1].body.branch, 'main');
70+
const branchText = Buffer.from(filePuts[0].body.content, 'base64').toString('utf8');
71+
const mainText = Buffer.from(filePuts[1].body.content, 'base64').toString('utf8');
72+
assert.notEqual(branchText, mainText);
73+
assert.match(branchText, /practice branch/);
74+
assert.match(mainText, /directly on main/);
75+
76+
const prPosts = calls.filter((c) => c.method === 'POST' && c.route === '/repos/org/room/pulls');
77+
assert.equal(prPosts.length, 1);
78+
assert.equal(prPosts[0].body.head, 'challenge-7/conflict-practice');
79+
assert.equal(prPosts[0].body.base, 'main');
80+
assert.match(prPosts[0].body.body, /#11/);
81+
82+
const issueComments = calls.filter((c) => c.method === 'POST' && c.route === '/repos/org/room/issues/11/comments');
83+
assert.equal(issueComments.length, 1);
84+
assert.match(issueComments[0].body.body, /#99/);
85+
});
86+
87+
test('is idempotent: does nothing when a practice PR already exists in any state', async () => {
88+
const { calls, request } = fakeRequest({
89+
'GET /repos/org/room/pulls?': () => [{ number: 5, state: 'closed' }]
90+
});
91+
92+
await ensureMergeConflictPractice(11, request);
93+
94+
const writes = calls.filter((c) => c.method === 'POST' || c.method === 'PUT');
95+
assert.deepEqual(writes, [
96+
{ method: 'POST', route: '/repos/org/room/issues/11/comments', body: { body: 'Your merge conflict practice PR is ready: #5. Open that PR (not any other pull request you may already have open) and follow Step 1 below.' } }
97+
]);
98+
});
99+
100+
test('is idempotent: skips when the conflict anchor is already on main', async () => {
101+
const { calls, request } = fakeRequest({
102+
'GET /repos/org/room/contents/docs/welcome.md': () => ({
103+
content: Buffer.from(`${WELCOME_CONTENT}\n<!-- challenge-7-conflict-anchor -->\n`).toString('base64'),
104+
sha: WELCOME_SHA
105+
})
106+
});
107+
108+
await ensureMergeConflictPractice(11, request);
109+
110+
const writes = calls.filter((c) => c.method === 'POST' || c.method === 'PUT');
111+
assert.deepEqual(writes, []);
112+
});
113+
114+
test('falls back to looking up the issue when no issue number is passed', async () => {
115+
const { calls, request } = fakeRequest({
116+
'GET /repos/org/room/issues?': () => [
117+
{ number: 21, title: 'Challenge 7: Survive a Merge Conflict (@student)' }
118+
]
119+
});
120+
121+
await ensureMergeConflictPractice(null, request);
122+
123+
const issueComments = calls.filter((c) => c.method === 'POST' && c.route === '/repos/org/room/issues/21/comments');
124+
assert.equal(issueComments.length, 1);
125+
});
126+
127+
test('never throws: progression survives a seeding failure', async () => {
128+
const request = async () => {
129+
throw new Error('boom: no network');
130+
};
131+
132+
await assert.doesNotReject(ensureMergeConflictPractice(11, request));
133+
});

docs/06-working-with-pull-requests.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ For reliable PR workflows in the terminal:
6363

6464
**Where you are working:** your Learning Room repository on GitHub.com, using the web editor.
6565

66-
**Before you start:** Open your **assigned Chapter 6.1 challenge issue** (the one titled "Chapter 6.1: Create One Small Branch Change (@yourname)"). The issue description tells you which file to edit and what to fix.
66+
**Before you start:** This section is preparation for your **Challenge 6: Open Your First PR** issue - there is no separate issue for making the edit itself. Pick one of the three practice files below, make one focused change, and save it on a new branch. When your branch has a commit, come back and continue with the PR steps later in this chapter.
6767

6868
The Learning Room has three practice files with intentional problems. Your assigned issue points you to one of them:
6969

docs/07-merge-conflicts.md

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ Chapter 7 uses **one controlled practice challenge** so students can learn confl
2020

2121
### Chapter 7 Challenge Set
2222

23-
1. **Resolve conflict markers** - identify and clean up conflict markers in a practice file, then open a linked PR.
23+
1. **Resolve conflict markers** - identify and clean up conflict markers in an automatically opened practice pull request.
2424

25-
> **Branch guidance for Chapter 7:** Use a short-lived feature branch: `fix/yourname-issueXX` (for example, `fix/maria-issue48`). The same pattern you used in Chapter 6.
25+
> **Branch guidance for Chapter 7:** No manual branch is needed this time. Opening your Challenge 7 issue automatically creates the practice branch and pull request for you.
2626
2727
### Challenge 7.1 Step-by-Step: Resolve Conflict Markers
2828

@@ -32,11 +32,9 @@ Chapter 7 uses **one controlled practice challenge** so students can learn confl
3232
3333
**Where you are working:** your Learning Room repository on GitHub.com (web editor) or in VS Code if you cloned locally.
3434

35-
**Before you start:** Open your **assigned Chapter 7 challenge issue** (the one titled "Chapter 7.1: Resolve Conflict Markers (@yourname)"). The issue description tells you which practice file contains the conflict markers.
35+
**Before you start:** Open your **assigned Challenge 7 issue** (the one titled "Challenge 7: Survive a Merge Conflict (@yourname)"). Opening that issue automatically opens a practice pull request in your repository with a real merge conflict already showing in `docs/welcome.md` - look for a comment on the issue linking that PR.
3636

37-
Practice sample: [`learning-room/docs/samples/chapter-6-conflict-practice-sample.md`](https://github.com/Community-Access/git-going-with-github/blob/main/learning-room/docs/samples/chapter-6-conflict-practice-sample.md)
38-
39-
1. Open the practice file specified in your challenge issue.
37+
1. Open the practice PR linked in the issue comment, then open `docs/welcome.md` in the conflict editor.
4038
2. Search the file for `<<<<<<<`. This is the **start marker** - it shows where the conflict begins.
4139
3. Read the content between `<<<<<<<` and `=======`. This is **your version** (the current branch).
4240
4. Read the content between `=======` and `>>>>>>>`. This is **their version** (the incoming branch).
@@ -49,22 +47,19 @@ Practice sample: [`learning-room/docs/samples/chapter-6-conflict-practice-sample
4947
- The `=======` separator line
5048
- The `>>>>>>> branch-name` line
5149
7. Review the file to confirm no marker lines remain. Search for `<<<<<<<` again - there should be zero results.
52-
8. Commit your changes on a branch named `fix/yourname-issueXX`.
53-
9. Open a pull request with:
54-
- Title: `fix: resolve conflict markers in [filename]`
55-
- Body: Include `Closes #XX` (your challenge issue number) and a 1-2 sentence description of which content you kept and why.
50+
8. Click **Mark as resolved**, then **Commit merge** to finish resolving the conflict on the practice PR.
5651

5752
**Screen reader tip:** Use your screen reader's find command (`Ctrl+F` in browser, `Ctrl+H` in VS Code) to jump directly to `<<<<<<<`. The markers are plain text, so they are fully readable.
5853

59-
**You are done when:** Your PR passes bot validation checks and contains no remaining conflict markers.
54+
**You are done when:** Your practice PR passes bot validation checks and contains no remaining conflict markers.
6055

6156
### Completing Chapter 7: Submit Your Evidence
6257

63-
When your PR is open and passing checks, post a comment on your assigned Chapter 7 challenge issue:
58+
When your practice PR is resolved and passing checks, post a comment on your Challenge 7 issue:
6459

6560
```text
6661
Chapter 7 completed:
67-
- Challenge 7.1: Opened PR #[number] resolving conflict markers in [filename]
62+
- Challenge 7.1: Resolved conflict markers in docs/welcome.md on the practice PR
6863
- Content decision: kept [your version / their version / combined both] because [reason]
6964
```
7065

docs/08-open-source-culture.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,18 @@ Chapter 8 is a **communication and culture chapter**.
2020

2121
### Chapter 8 Challenge Set
2222

23-
1. **Guided reflection** - read the chapter, then post a short reflection comment committing to three specific collaboration behaviors.
23+
1. **The Culture Layer** - read the chapter, reflect on three specific collaboration behaviors, then practice triaging an issue by adding a descriptive label.
2424

25-
### Challenge 8.1 Step-by-Step: Guided Reflection
25+
### Challenge 8.1 Step-by-Step: The Culture Layer
2626

27-
**Goal:** Identify three concrete communication behaviors you will practice during the rest of the workshop.
27+
**Goal:** Identify three concrete communication behaviors you will practice during the rest of the workshop, then triage an issue with a label.
2828

29-
**Where you are working:** your assigned Chapter 8 challenge issue in your Learning Room repository on GitHub.com.
29+
**Where you are working:** your **assigned Challenge 8 issue** (the one titled "Challenge 8: The Culture Layer (@yourname)") in your Learning Room repository on GitHub.com.
3030

3131
1. Read through the chapter content below, paying attention to the sections on GitHub Flow, constructive feedback, and asking for help.
3232
2. As you read, think about one situation from Day 1 where communication helped (or could have helped) you.
33-
3. Open your **assigned Chapter 8 challenge issue** (the one titled "Chapter 8.1: Guided Reflection (@yourname)").
34-
4. Scroll to the comment box at the bottom of the issue.
35-
5. Post a reflection comment using this format:
33+
3. Open your Challenge 8 issue and scroll to the comment box at the bottom.
34+
4. Post a reflection comment using this format:
3635

3736
```text
3837
Chapter 8 reflection:
@@ -47,12 +46,14 @@ Chapter 8 reflection:
4746
- Good: "I will include the exact step where I got stuck and what I already tried."
4847
- Vague: "I will ask good questions."
4948
2. Activate the **Comment** button (or press `Ctrl+Enter`).
49+
3. Open the **Peer Simulation: Welcome Link Needs Context** issue (or a real classmate's issue if you have buddy access) and apply one label that describes it (`bug`, `enhancement`, `documentation`, `good first issue`, or `question`).
50+
4. Optionally, leave a short comment on that issue explaining why you chose that label.
5051

51-
**You are done when:** Your reflection comment appears on the issue with three specific, actionable behaviors.
52+
**You are done when:** Your reflection comment appears on your Challenge 8 issue with three specific, actionable behaviors, and you have applied a label to the peer-simulation issue.
5253

5354
### Completing Chapter 8: Submit Your Evidence
5455

55-
The reflection comment itself is your evidence. No additional steps are needed. The facilitator reviews your comment for specificity. Close your Chapter 8 challenge issue when done.
56+
Post your evidence on your Challenge 8 issue: the reflection comment plus which issue you triaged and which label you applied. No additional steps are needed. Close your Challenge 8 issue when done.
5657

5758
### Expected Outcomes
5859

docs/09-labels-milestones-projects.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,32 @@
1111
1212
## Workshop Recommendation (Chapter 9)
1313

14-
Chapter 9 is a **guided triage chapter** focused on organization skills.
14+
Chapter 9 is a **guided triage chapter** focused on organization skills. It does not have its own separate GitHub issue - your label-triage evidence for this stage of the workshop is submitted as part of your **Challenge 8: The Culture Layer** issue (see [Chapter 8](08-open-source-culture.md)). Use the exercise below as practice before you finish that evidence.
1515

16-
- **Challenge count:** 1 guided challenge
16+
- **Challenge count:** 0 (practice only - folded into Challenge 8's evidence)
1717
- **Automation check:** none by default
18-
- **Evidence:** structured issue comment in assigned challenge issue
18+
- **Evidence:** structured comment on your Challenge 8 issue
1919
- **Pattern:** inspect, classify, explain
2020

21-
### Chapter 9 Challenge Set
21+
### Chapter 9 Practice Set
2222

2323
1. **Post a triage recommendation** - read an issue, recommend labels/milestone/project placement, and explain your reasoning.
2424

25-
### Challenge 9.1 Step-by-Step: Triage Recommendation Comment
25+
### Practice Step-by-Step: Triage Recommendation Comment
2626

2727
**Goal:** Read the details of a Learning Room issue and post a structured triage recommendation that a maintainer could act on immediately.
2828

2929
> **Agentic strategy:** Labels and issue states are how we wake up agents. In the Day 2 capstone, you can design an agent that only activates when an issue gets a specific label, such as `needs-review` or `accessibility-check`.
3030
31-
**Where you are working:** your assigned Chapter 9 challenge issue in your Learning Room repository on GitHub.com, plus one other open issue you will triage.
31+
**Where you are working:** your Learning Room repository on GitHub.com - pick one open issue to triage, then record your evidence on your Challenge 8 issue.
3232

3333
1. Open the **Issues** tab in your Learning Room repository.
34-
2. Find any **open issue** that does not already have labels applied (or pick one your facilitator assigns).
34+
2. Find any **open issue** that does not already have labels applied.
3535
3. Read the issue title and full description carefully. Note:
3636
- What type of work is it? (documentation fix, bug report, accessibility improvement, new content)
3737
- How urgent does it seem? (blocking other work, nice-to-have, unclear)
3838
- Which file or area of the repo does it affect?
39-
4. Open your **assigned Chapter 9 challenge issue** (the one titled "Chapter 9.1: Triage Recommendation (@yourname)").
39+
4. Open your **Challenge 8: The Culture Layer** issue.
4040
5. Scroll to the comment box and post a triage recommendation using this format:
4141

4242
```text
@@ -52,11 +52,11 @@ Chapter 9 triage recommendation for issue #[number]:
5252

5353
**Screen reader tip:** When browsing available labels, open the Labels page (`/labels` path on the repo) to see all label names and descriptions. Your screen reader will read each label name and its description text.
5454

55-
**You are done when:** Your triage recommendation comment appears on your assigned challenge issue with all four fields filled in.
55+
**You are done when:** Your triage recommendation comment appears on your Challenge 8 issue with all four fields filled in.
5656

5757
### Completing Chapter 9: Submit Your Evidence
5858

59-
Your triage recommendation comment is your evidence. Close your Chapter 9 challenge issue when done. If you also applied labels directly, mention that in your comment.
59+
This practice folds into your Challenge 8 evidence - there is no separate issue to close for Chapter 9. If you also applied labels directly, mention that in the same comment.
6060

6161
### Expected Outcomes
6262

html/docs/06-working-with-pull-requests.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ <h3 id="cli-getting-started-principles-for-pull-request-work">CLI getting-starte
362362
<h3 id="challenge-61-step-by-step-create-one-small-branch-change">Challenge 6.1 Step-by-Step: Create One Small Branch Change</h3>
363363
<p><strong>Goal:</strong> Edit one of the practice files and save your change on a new branch.</p>
364364
<p><strong>Where you are working:</strong> your Learning Room repository on GitHub.com, using the web editor.</p>
365-
<p><strong>Before you start:</strong> Open your <strong>assigned Chapter 6.1 challenge issue</strong> (the one titled &quot;Chapter 6.1: Create One Small Branch Change (@yourname)&quot;). The issue description tells you which file to edit and what to fix.</p>
365+
<p><strong>Before you start:</strong> This section is preparation for your <strong>Challenge 6: Open Your First PR</strong> issue - there is no separate issue for making the edit itself. Pick one of the three practice files below, make one focused change, and save it on a new branch. When your branch has a commit, come back and continue with the PR steps later in this chapter.</p>
366366
<p>The Learning Room has three practice files with intentional problems. Your assigned issue points you to one of them:</p>
367367
<p>The following table summarizes the practice files in the learning-room, what each file contains, and the type of issues to look for.</p>
368368
<table>

0 commit comments

Comments
 (0)