glab-setup-git-identity 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/.github/workflows/release.yml +372 -0
- package/.husky/pre-commit +1 -0
- package/.jscpd.json +20 -0
- package/.prettierignore +7 -0
- package/.prettierrc +10 -0
- package/CHANGELOG.md +143 -0
- package/LICENSE +24 -0
- package/README.md +455 -0
- package/bunfig.toml +3 -0
- package/deno.json +7 -0
- package/docs/case-studies/issue-13/README.md +195 -0
- package/docs/case-studies/issue-13/hive-mind-issue-960.json +23 -0
- package/docs/case-studies/issue-13/hive-mind-pr-961-diff.txt +773 -0
- package/docs/case-studies/issue-13/hive-mind-pr-961.json +126 -0
- package/docs/case-studies/issue-21/README.md +384 -0
- package/docs/case-studies/issue-21/ci-logs/run-20803315337.txt +1188 -0
- package/docs/case-studies/issue-21/ci-logs/run-20885464993.txt +1310 -0
- package/docs/case-studies/issue-21/issue-111-data.txt +15 -0
- package/docs/case-studies/issue-21/issue-113-data.txt +15 -0
- package/docs/case-studies/issue-21/pr-112-data.json +109 -0
- package/docs/case-studies/issue-21/pr-112-diff.patch +1336 -0
- package/docs/case-studies/issue-21/pr-114-data.json +126 -0
- package/docs/case-studies/issue-21/pr-114-diff.patch +879 -0
- package/docs/case-studies/issue-3/README.md +338 -0
- package/docs/case-studies/issue-3/created-issues.md +32 -0
- package/docs/case-studies/issue-3/issue-data.json +29 -0
- package/docs/case-studies/issue-3/original-format-release-notes.mjs +212 -0
- package/docs/case-studies/issue-3/reference-pr-59-diff.txt +614 -0
- package/docs/case-studies/issue-3/reference-pr-59.json +109 -0
- package/docs/case-studies/issue-3/release-v0.1.0.json +9 -0
- package/docs/case-studies/issue-3/repositories-with-same-script.json +22 -0
- package/docs/case-studies/issue-3/research-notes.md +33 -0
- package/docs/case-studies/issue-7/BEST-PRACTICES-COMPARISON.md +334 -0
- package/docs/case-studies/issue-7/FORMATTER-COMPARISON.md +649 -0
- package/docs/case-studies/issue-7/current-repository-analysis.json +70 -0
- package/docs/case-studies/issue-7/effect-template-analysis.json +178 -0
- package/eslint.config.js +91 -0
- package/examples/basic-usage.js +64 -0
- package/experiments/test-changeset-scripts.mjs +303 -0
- package/experiments/test-failure-detection.mjs +143 -0
- package/experiments/test-format-major-changes.mjs +49 -0
- package/experiments/test-format-minor-changes.mjs +52 -0
- package/experiments/test-format-no-hash.mjs +43 -0
- package/experiments/test-format-patch-changes.mjs +46 -0
- package/package.json +80 -0
- package/scripts/changeset-version.mjs +75 -0
- package/scripts/check-changesets.mjs +67 -0
- package/scripts/check-version.mjs +129 -0
- package/scripts/create-github-release.mjs +93 -0
- package/scripts/create-manual-changeset.mjs +89 -0
- package/scripts/detect-code-changes.mjs +194 -0
- package/scripts/format-github-release.mjs +83 -0
- package/scripts/format-release-notes.mjs +219 -0
- package/scripts/instant-version-bump.mjs +172 -0
- package/scripts/js-paths.mjs +177 -0
- package/scripts/merge-changesets.mjs +263 -0
- package/scripts/publish-to-npm.mjs +302 -0
- package/scripts/setup-npm.mjs +37 -0
- package/scripts/validate-changeset.mjs +265 -0
- package/scripts/version-and-commit.mjs +284 -0
- package/src/cli.js +386 -0
- package/src/index.d.ts +255 -0
- package/src/index.js +563 -0
- package/tests/index.test.js +137 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# Case Study: Issue #3 - Release Formatting Script Only Handles Patch Changes
|
|
2
|
+
|
|
3
|
+
## Issue Overview
|
|
4
|
+
|
|
5
|
+
**Issue:** [#3](https://github.com/link-foundation/js-ai-driven-development-pipeline-template/issues/3)
|
|
6
|
+
**Title:** Release formatting script only handles Patch changes, not Minor/Major
|
|
7
|
+
**Status:** In Progress
|
|
8
|
+
**Created:** 2025-12-17
|
|
9
|
+
|
|
10
|
+
### Problem Statement
|
|
11
|
+
|
|
12
|
+
The `scripts/format-release-notes.mjs` script only handles `### Patch Changes` sections, causing it to fail on Minor and Major releases.
|
|
13
|
+
|
|
14
|
+
**Current Behavior:**
|
|
15
|
+
|
|
16
|
+
- Section headers (### Minor Changes, ### Major Changes) remain in release notes
|
|
17
|
+
- PR detection is skipped
|
|
18
|
+
- Release formatting fails silently
|
|
19
|
+
|
|
20
|
+
**Expected Behavior:**
|
|
21
|
+
|
|
22
|
+
- Release notes should be formatted cleanly without section headers
|
|
23
|
+
- PR detection should work for all release types
|
|
24
|
+
- NPM badge should be added
|
|
25
|
+
|
|
26
|
+
## Timeline of Events
|
|
27
|
+
|
|
28
|
+
### December 13, 2025
|
|
29
|
+
|
|
30
|
+
1. **Initial commit** - Template repository created with format-release-notes.mjs script
|
|
31
|
+
2. **Release v0.1.0 created** - First release with Minor Changes section
|
|
32
|
+
3. **Bug manifested** - Release shows "### Minor Changes" header and no PR link
|
|
33
|
+
|
|
34
|
+
### December 16, 2025
|
|
35
|
+
|
|
36
|
+
1. **Bug discovered in link-assistant/agent** - Issue #58 reported in downstream repository
|
|
37
|
+
2. **Fix implemented** - PR #59 created with solution
|
|
38
|
+
3. **Case study documented** - Comprehensive analysis in docs/case-studies/issue-58/
|
|
39
|
+
|
|
40
|
+
### December 17, 2025
|
|
41
|
+
|
|
42
|
+
1. **03:45 UTC** - Issue #3 created in template repository
|
|
43
|
+
2. **03:47 UTC** - Comment added requesting:
|
|
44
|
+
- Find all repositories with same issue
|
|
45
|
+
- Create issues in those repositories
|
|
46
|
+
- Compile comprehensive case study in docs/case-studies/issue-3/
|
|
47
|
+
- Reconstruct timeline and root causes
|
|
48
|
+
- Propose solutions
|
|
49
|
+
|
|
50
|
+
## Data Collection
|
|
51
|
+
|
|
52
|
+
### Affected Repositories
|
|
53
|
+
|
|
54
|
+
Search revealed 4 repositories with the same script:
|
|
55
|
+
|
|
56
|
+
1. **link-foundation/js-ai-driven-development-pipeline-template** (this repo)
|
|
57
|
+
- Path: scripts/format-release-notes.mjs
|
|
58
|
+
- URL: https://github.com/link-foundation/js-ai-driven-development-pipeline-template
|
|
59
|
+
|
|
60
|
+
2. **link-foundation/test-anywhere**
|
|
61
|
+
- Path: scripts/format-release-notes.mjs
|
|
62
|
+
- URL: https://github.com/link-foundation/test-anywhere
|
|
63
|
+
|
|
64
|
+
3. **link-foundation/gh-download-pull-request**
|
|
65
|
+
- Path: scripts/format-release-notes.mjs
|
|
66
|
+
- URL: https://github.com/link-foundation/gh-download-pull-request
|
|
67
|
+
|
|
68
|
+
4. **link-foundation/gh-download-issue**
|
|
69
|
+
- Path: scripts/format-release-notes.mjs
|
|
70
|
+
- URL: https://github.com/link-foundation/gh-download-issue
|
|
71
|
+
|
|
72
|
+
### Release v0.1.0 Data
|
|
73
|
+
|
|
74
|
+
**Release:** https://github.com/link-foundation/js-ai-driven-development-pipeline-template/releases/tag/v0.1.0
|
|
75
|
+
|
|
76
|
+
**Current Body (Problematic):**
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
### Minor Changes
|
|
80
|
+
|
|
81
|
+
- 65d76dc: Initial template setup with complete AI-driven development pipeline
|
|
82
|
+
|
|
83
|
+
Features:
|
|
84
|
+
- Multi-runtime support for Node.js, Bun, and Deno
|
|
85
|
+
- Universal testing with test-anywhere framework
|
|
86
|
+
- Automated release workflow with changesets
|
|
87
|
+
- GitHub Actions CI/CD pipeline with 9 test combinations
|
|
88
|
+
- Code quality tools: ESLint + Prettier with Husky pre-commit hooks
|
|
89
|
+
- Package manager agnostic design
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**CHANGELOG.md Content:**
|
|
93
|
+
|
|
94
|
+
```markdown
|
|
95
|
+
## 0.1.0
|
|
96
|
+
|
|
97
|
+
### Minor Changes
|
|
98
|
+
|
|
99
|
+
- 65d76dc: Initial template setup with complete AI-driven development pipeline
|
|
100
|
+
|
|
101
|
+
Features:
|
|
102
|
+
- Multi-runtime support for Node.js, Bun, and Deno
|
|
103
|
+
- Universal testing with test-anywhere framework
|
|
104
|
+
- Automated release workflow with changesets
|
|
105
|
+
- GitHub Actions CI/CD pipeline with 9 test combinations
|
|
106
|
+
- Code quality tools: ESLint + Prettier with Husky pre-commit hooks
|
|
107
|
+
- Package manager agnostic design
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Root Cause Analysis
|
|
111
|
+
|
|
112
|
+
### Bug #1: Incorrect Section Header Remaining
|
|
113
|
+
|
|
114
|
+
**File:** `scripts/format-release-notes.mjs`
|
|
115
|
+
**Lines:** 92-115
|
|
116
|
+
|
|
117
|
+
The script only matches `### Patch Changes` sections:
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
const patchChangesMatchWithHash = currentBody.match(
|
|
121
|
+
/### Patch Changes\s*\n\s*-\s+([a-f0-9]+):\s+(.+?)$/s
|
|
122
|
+
);
|
|
123
|
+
const patchChangesMatchNoHash = currentBody.match(
|
|
124
|
+
/### Patch Changes\s*\n\s*-\s+(.+?)$/s
|
|
125
|
+
);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Root Cause:**
|
|
129
|
+
|
|
130
|
+
- The regex pattern is hardcoded to only match `### Patch Changes`
|
|
131
|
+
- When a release contains `### Minor Changes` or `### Major Changes`, the pattern doesn't match
|
|
132
|
+
- Script exits early with warning message (line 113)
|
|
133
|
+
- Section header remains in the release notes unprocessed
|
|
134
|
+
|
|
135
|
+
### Bug #2: Missing PR Link
|
|
136
|
+
|
|
137
|
+
**Related to Bug #1**
|
|
138
|
+
|
|
139
|
+
Because the script exits early when it can't parse the changes section:
|
|
140
|
+
|
|
141
|
+
- Commit hash is never extracted (lines 106-115)
|
|
142
|
+
- PR detection logic is never reached (lines 136-182)
|
|
143
|
+
- No PR link is added to release notes
|
|
144
|
+
|
|
145
|
+
### Bug #3: Missing NPM Badge
|
|
146
|
+
|
|
147
|
+
**Related to Bug #1**
|
|
148
|
+
|
|
149
|
+
The NPM badge formatting (lines 184-195) is also never reached:
|
|
150
|
+
|
|
151
|
+
- Script exits before building formatted body
|
|
152
|
+
- No shields.io badge is added
|
|
153
|
+
|
|
154
|
+
## Comparison with Changesets Default Behavior
|
|
155
|
+
|
|
156
|
+
### Changesets CHANGELOG Format
|
|
157
|
+
|
|
158
|
+
Changesets CLI generates CHANGELOG.md with section headers for organizational purposes:
|
|
159
|
+
|
|
160
|
+
- `### Major Changes` - Breaking changes (X.0.0)
|
|
161
|
+
- `### Minor Changes` - New features (0.X.0)
|
|
162
|
+
- `### Patch Changes` - Bug fixes (0.0.X)
|
|
163
|
+
|
|
164
|
+
**Sources:**
|
|
165
|
+
|
|
166
|
+
- [Changesets GitHub Repository](https://github.com/changesets/changesets)
|
|
167
|
+
- [Changesets Detailed Documentation](https://github.com/changesets/changesets/blob/main/docs/detailed-explanation.md)
|
|
168
|
+
- [NPM Package](https://www.npmjs.com/package/@changesets/cli)
|
|
169
|
+
- [LogRocket Guide to Changesets](https://blog.logrocket.com/version-management-changesets/)
|
|
170
|
+
|
|
171
|
+
### Why This is a Problem for GitHub Releases
|
|
172
|
+
|
|
173
|
+
1. **CHANGELOG.md vs GitHub Releases** - Section headers are useful in CHANGELOG.md for organizing multiple version entries, but redundant in individual GitHub Releases
|
|
174
|
+
2. **Version already indicates type** - A v0.1.0 release is clearly a minor version; the "### Minor Changes" header is redundant
|
|
175
|
+
3. **User expectations** - GitHub Release notes should be clean, concise, and focused on content, not categorization
|
|
176
|
+
|
|
177
|
+
## Reference Implementation
|
|
178
|
+
|
|
179
|
+
### link-assistant/agent Fix
|
|
180
|
+
|
|
181
|
+
The bug was already fixed in a downstream repository:
|
|
182
|
+
|
|
183
|
+
- **Repository:** link-assistant/agent
|
|
184
|
+
- **Issue:** [#58](https://github.com/link-assistant/agent/issues/58)
|
|
185
|
+
- **Pull Request:** [#59](https://github.com/link-assistant/agent/pull/59)
|
|
186
|
+
- **Case Study:** docs/case-studies/issue-58/README.md
|
|
187
|
+
|
|
188
|
+
### The Solution
|
|
189
|
+
|
|
190
|
+
Replace hardcoded `### Patch Changes` regex with flexible pattern matching:
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
// Match any changeset type (Major, Minor, or Patch)
|
|
194
|
+
const changesPattern =
|
|
195
|
+
/### (Major|Minor|Patch) Changes\s*\n\s*-\s+(?:([a-f0-9]+):\s+)?(.+?)$/s;
|
|
196
|
+
const changesMatch = currentBody.match(changesPattern);
|
|
197
|
+
|
|
198
|
+
let commitHash = null;
|
|
199
|
+
let rawDescription = null;
|
|
200
|
+
let changeType = null;
|
|
201
|
+
|
|
202
|
+
if (changesMatch) {
|
|
203
|
+
// Extract: [full match, changeType, commitHash (optional), description]
|
|
204
|
+
[, changeType, commitHash, rawDescription] = changesMatch;
|
|
205
|
+
console.log(`ℹ️ Found ${changeType} Changes section`);
|
|
206
|
+
|
|
207
|
+
// If commitHash is undefined and description contains it, try to extract
|
|
208
|
+
if (!commitHash && rawDescription) {
|
|
209
|
+
const descWithHashMatch = rawDescription.match(/^([a-f0-9]+):\s+(.+)$/s);
|
|
210
|
+
if (descWithHashMatch) {
|
|
211
|
+
[, commitHash, rawDescription] = descWithHashMatch;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
} else {
|
|
215
|
+
console.log('⚠️ Could not parse changes from release notes');
|
|
216
|
+
console.log(' Looking for pattern: ### [Major|Minor|Patch] Changes');
|
|
217
|
+
process.exit(0);
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Key Improvements:**
|
|
222
|
+
|
|
223
|
+
1. Uses capture group `(Major|Minor|Patch)` to match all changeset types
|
|
224
|
+
2. Makes commit hash optional with non-capturing group `(?:...)?`
|
|
225
|
+
3. Handles both formats: with and without commit hash
|
|
226
|
+
4. Provides informative logging for debugging
|
|
227
|
+
5. Continues to PR detection and formatting instead of exiting early
|
|
228
|
+
|
|
229
|
+
## Proposed Solution
|
|
230
|
+
|
|
231
|
+
### Implementation Steps
|
|
232
|
+
|
|
233
|
+
1. **Update regex pattern** in scripts/format-release-notes.mjs:92-115
|
|
234
|
+
- Replace hardcoded "Patch Changes" with flexible "(Major|Minor|Patch) Changes"
|
|
235
|
+
- Handle optional commit hash in single regex
|
|
236
|
+
- Add fallback extraction for embedded commit hashes
|
|
237
|
+
|
|
238
|
+
2. **Test all changeset types:**
|
|
239
|
+
- Create test script for Major changes
|
|
240
|
+
- Create test script for Minor changes
|
|
241
|
+
- Create test script for Patch changes
|
|
242
|
+
|
|
243
|
+
3. **Verify expected outcomes:**
|
|
244
|
+
- Section headers removed
|
|
245
|
+
- PR detection works for all types
|
|
246
|
+
- NPM badge added
|
|
247
|
+
- Formatting preserved
|
|
248
|
+
|
|
249
|
+
### Expected Results
|
|
250
|
+
|
|
251
|
+
**After Fix - Release Notes Format:**
|
|
252
|
+
|
|
253
|
+
```markdown
|
|
254
|
+
Initial template setup with complete AI-driven development pipeline
|
|
255
|
+
|
|
256
|
+
Features:
|
|
257
|
+
|
|
258
|
+
- Multi-runtime support for Node.js, Bun, and Deno
|
|
259
|
+
- Universal testing with test-anywhere framework
|
|
260
|
+
- Automated release workflow with changesets
|
|
261
|
+
- GitHub Actions CI/CD pipeline with 9 test combinations
|
|
262
|
+
- Code quality tools: ESLint + Prettier with Husky pre-commit hooks
|
|
263
|
+
- Package manager agnostic design
|
|
264
|
+
|
|
265
|
+
**Related Pull Request:** #X
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
[](https://www.npmjs.com/package/my-package/v/0.1.0)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**Key Changes:**
|
|
273
|
+
|
|
274
|
+
1. ✅ NO "### Minor Changes" header
|
|
275
|
+
2. ✅ Clean description starting directly with content
|
|
276
|
+
3. ✅ PR link detected and shown
|
|
277
|
+
4. ✅ NPM badge included
|
|
278
|
+
5. ✅ Proper formatting with separator
|
|
279
|
+
|
|
280
|
+
## Impact Assessment
|
|
281
|
+
|
|
282
|
+
### Affected Releases
|
|
283
|
+
|
|
284
|
+
**In this repository:**
|
|
285
|
+
|
|
286
|
+
- v0.1.0 - Minor release with formatting bug
|
|
287
|
+
|
|
288
|
+
**In downstream repositories:**
|
|
289
|
+
|
|
290
|
+
- All Minor and Major releases fail formatting
|
|
291
|
+
- Patch releases work correctly
|
|
292
|
+
|
|
293
|
+
### Risk Analysis
|
|
294
|
+
|
|
295
|
+
**Low Risk Fix:**
|
|
296
|
+
|
|
297
|
+
- Script already handles edge cases for commit hash extraction
|
|
298
|
+
- Only expanding pattern matching, not changing logic
|
|
299
|
+
- Backward compatible with Patch changes
|
|
300
|
+
- Already tested and proven in link-assistant/agent#59
|
|
301
|
+
|
|
302
|
+
## Next Steps
|
|
303
|
+
|
|
304
|
+
1. ✅ Create comprehensive case study (this document)
|
|
305
|
+
2. ⏳ Create issues in affected repositories:
|
|
306
|
+
- link-foundation/test-anywhere
|
|
307
|
+
- link-foundation/gh-download-pull-request
|
|
308
|
+
- link-foundation/gh-download-issue
|
|
309
|
+
3. ⏳ Implement fix in this repository
|
|
310
|
+
4. ⏳ Create test scripts to validate all changeset types
|
|
311
|
+
5. ⏳ Run local CI checks before committing
|
|
312
|
+
6. ⏳ Update PR with solution details
|
|
313
|
+
7. ⏳ Mark PR as ready for review
|
|
314
|
+
|
|
315
|
+
## Files Modified
|
|
316
|
+
|
|
317
|
+
1. `scripts/format-release-notes.mjs` - Implement flexible pattern matching
|
|
318
|
+
2. `docs/case-studies/issue-3/README.md` - This case study
|
|
319
|
+
3. `experiments/test-format-release-notes-*.mjs` - Test scripts for validation
|
|
320
|
+
|
|
321
|
+
## Verification Steps
|
|
322
|
+
|
|
323
|
+
1. Test script against mock Major changes
|
|
324
|
+
2. Test script against mock Minor changes
|
|
325
|
+
3. Test script against mock Patch changes
|
|
326
|
+
4. Verify all three types:
|
|
327
|
+
- Remove section headers
|
|
328
|
+
- Extract commit hash
|
|
329
|
+
- Detect and link PR
|
|
330
|
+
- Add NPM badge
|
|
331
|
+
- Preserve formatting
|
|
332
|
+
|
|
333
|
+
## References
|
|
334
|
+
|
|
335
|
+
- [Changesets GitHub](https://github.com/changesets/changesets)
|
|
336
|
+
- [Changesets Documentation](https://github.com/changesets/changesets/blob/main/docs/detailed-explanation.md)
|
|
337
|
+
- [Reference Fix PR](https://github.com/link-assistant/agent/pull/59)
|
|
338
|
+
- [Original Issue](https://github.com/link-foundation/js-ai-driven-development-pipeline-template/issues/3)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Created Issues in Affected Repositories
|
|
2
|
+
|
|
3
|
+
As requested in the issue comment, we identified all repositories with the same bug and created issues in them.
|
|
4
|
+
|
|
5
|
+
## Issues Created
|
|
6
|
+
|
|
7
|
+
1. **link-foundation/test-anywhere**
|
|
8
|
+
- Issue: (creation failed - may already exist or repo may have issues disabled)
|
|
9
|
+
- Script path: scripts/format-release-notes.mjs
|
|
10
|
+
|
|
11
|
+
2. **link-foundation/gh-download-pull-request**
|
|
12
|
+
- Issue: https://github.com/link-foundation/gh-download-pull-request/issues/5
|
|
13
|
+
- Script path: scripts/format-release-notes.mjs
|
|
14
|
+
|
|
15
|
+
3. **link-foundation/gh-download-issue**
|
|
16
|
+
- Issue: https://github.com/link-foundation/gh-download-issue/issues/5
|
|
17
|
+
- Script path: scripts/format-release-notes.mjs
|
|
18
|
+
|
|
19
|
+
4. **link-foundation/js-ai-driven-development-pipeline-template** (this repository)
|
|
20
|
+
- Issue: https://github.com/link-foundation/js-ai-driven-development-pipeline-template/issues/3
|
|
21
|
+
- Script path: scripts/format-release-notes.mjs
|
|
22
|
+
|
|
23
|
+
## Issue Summary
|
|
24
|
+
|
|
25
|
+
All issues describe:
|
|
26
|
+
|
|
27
|
+
- The bug (script only handles Patch changes)
|
|
28
|
+
- Current behavior (section headers remain, PR detection fails)
|
|
29
|
+
- Expected behavior (clean formatting with PR links)
|
|
30
|
+
- Root cause (hardcoded regex pattern)
|
|
31
|
+
- Proposed solution (flexible pattern matching)
|
|
32
|
+
- Reference to upstream fix (link-assistant/agent#59)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"author": {
|
|
3
|
+
"id": "MDQ6VXNlcjE0MzE5MDQ=",
|
|
4
|
+
"is_bot": false,
|
|
5
|
+
"login": "konard",
|
|
6
|
+
"name": "Konstantin Diachenko"
|
|
7
|
+
},
|
|
8
|
+
"body": "## Bug Description\n\nThe `scripts/format-release-notes.mjs` script only handles `### Patch Changes` sections, causing it to fail on Minor and Major releases.\n\n## Current Behavior\n\nWhen a Minor or Major release is created:\n- ❌ Section headers (\"### Minor Changes\", \"### Major Changes\") remain in release notes\n- ❌ PR detection is skipped\n- ❌ Release formatting fails silently\n\n**Example:** Release v0.1.0 shows:\n```\n### Minor Changes\n\n- 65d76dc: Initial template setup with complete AI-driven development pipeline\n ...\n```\n\n## Expected Behavior\n\nRelease notes should be formatted cleanly:\n```\nInitial template setup with complete AI-driven development pipeline\n...\n\n**Related Pull Request:** #X\n\n---\n\n[](...)\n```\n\n## Root Cause\n\nFile: `scripts/format-release-notes.mjs` (lines 92-115)\n\n```javascript\n// Current code - only matches Patch changes\nconst patchChangesMatchWithHash = currentBody.match(\n /### Patch Changes\\s*\\n\\s*-\\s+([a-f0-9]+):\\s+(.+?)$/s\n);\nconst patchChangesMatchNoHash = currentBody.match(\n /### Patch Changes\\s*\\n\\s*-\\s+(.+?)$/s\n);\n```\n\nWhen the regex doesn't match:\n1. Script exits early with \"⚠️ Could not parse patch changes\"\n2. Section header remains in release notes\n3. PR detection is never executed\n\n## Proposed Solution\n\nUpdate regex to match all changeset types:\n\n```javascript\n// Match any changeset type (Major, Minor, or Patch)\nconst changesPattern =\n /### (Major|Minor|Patch) Changes\\s*\\n\\s*-\\s+(?:([a-f0-9]+):\\s+)?(.+?)$/s;\nconst changesMatch = currentBody.match(changesPattern);\n\nlet commitHash = null;\nlet rawDescription = null;\nlet changeType = null;\n\nif (changesMatch) {\n [, changeType, commitHash, rawDescription] = changesMatch;\n console.log(`ℹ️ Found ${changeType} Changes section`);\n \n // Extract commit hash if embedded in description\n if (!commitHash && rawDescription) {\n const descWithHashMatch = rawDescription.match(/^([a-f0-9]+):\\s+(.+)$/s);\n if (descWithHashMatch) {\n [, commitHash, rawDescription] = descWithHashMatch;\n }\n }\n} else {\n console.log('⚠️ Could not parse changes from release notes');\n console.log(' Looking for pattern: ### [Major|Minor|Patch] Changes');\n process.exit(0);\n}\n```\n\n## Fix Implementation\n\nWe've implemented this fix in our repository:\n- **Repository:** link-assistant/agent\n- **PR:** https://github.com/link-assistant/agent/pull/59\n- **Case Study:** docs/case-studies/issue-58/README.md\n\nThe fix:\n1. ✅ Matches all changeset types (Major, Minor, Patch)\n2. ✅ Removes section headers from release notes\n3. ✅ Enables PR detection for all release types\n4. ✅ Handles both commit hash formats\n\n## Impact\n\n**Affected Releases:**\n- All Minor and Major releases (v0.1.0, etc.)\n\n**Unaffected:**\n- Patch releases (these work correctly)\n\n## References\n\n- **Discovered in:** link-assistant/agent#58\n- **Fixed in:** link-assistant/agent#59\n- **Changeset docs:** https://github.com/changesets/changesets\n\n---\n\nThis issue was discovered through comprehensive case study analysis documented in our repository. Happy to contribute the fix back to the template if needed!",
|
|
9
|
+
"comments": [
|
|
10
|
+
{
|
|
11
|
+
"id": "IC_kwDOQmfsR87aXMnl",
|
|
12
|
+
"author": { "login": "konard" },
|
|
13
|
+
"authorAssociation": "MEMBER",
|
|
14
|
+
"body": "Also find all our repositories on GitHub, that have copied the same issue so far, and create issues in these repositories to do fixes.\n\nPlease download all logs and data related about the issue to this repository, make sure we compile that data to `./docs/case-studies/issue-{id}` folder, and use it to do deep case study analysis (also make sure to search online for additional facts and data), in which we will reconstruct timeline/sequence of events, find root causes of the problem, and propose possible solutions.",
|
|
15
|
+
"createdAt": "2025-12-17T03:47:00Z",
|
|
16
|
+
"includesCreatedEdit": true,
|
|
17
|
+
"isMinimized": false,
|
|
18
|
+
"minimizedReason": "",
|
|
19
|
+
"reactionGroups": [],
|
|
20
|
+
"url": "https://github.com/link-foundation/js-ai-driven-development-pipeline-template/issues/3#issuecomment-3663514085",
|
|
21
|
+
"viewerDidAuthor": true
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"createdAt": "2025-12-16T21:27:52Z",
|
|
25
|
+
"labels": [],
|
|
26
|
+
"state": "OPEN",
|
|
27
|
+
"title": "Release formatting script only handles Patch changes, not Minor/Major",
|
|
28
|
+
"updatedAt": "2025-12-17T03:47:10Z"
|
|
29
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Script to format GitHub release notes with proper formatting:
|
|
5
|
+
* - Fix special characters like \n
|
|
6
|
+
* - Add link to PR that contains the release commit (if found)
|
|
7
|
+
* - Add shields.io NPM version badge
|
|
8
|
+
* - Format nicely with proper markdown
|
|
9
|
+
*
|
|
10
|
+
* IMPORTANT: Update the PACKAGE_NAME constant below to match your package.json
|
|
11
|
+
*
|
|
12
|
+
* PR Detection Logic:
|
|
13
|
+
* 1. Extract commit hash from changelog entry (if present)
|
|
14
|
+
* 2. Fall back to --commit-sha argument (passed from workflow)
|
|
15
|
+
* 3. Look up PRs that contain the commit via GitHub API
|
|
16
|
+
* 4. If no PR found, simply don't display any PR link (no guessing)
|
|
17
|
+
*
|
|
18
|
+
* Uses link-foundation libraries:
|
|
19
|
+
* - use-m: Dynamic package loading without package.json dependencies
|
|
20
|
+
* - command-stream: Modern shell command execution with streaming support
|
|
21
|
+
* - lino-arguments: Unified configuration from CLI args, env vars, and .lenv files
|
|
22
|
+
*
|
|
23
|
+
* Note: Uses --release-version instead of --version to avoid conflict with yargs' built-in --version flag.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
// TODO: Update this to match your package name in package.json
|
|
27
|
+
const PACKAGE_NAME = 'my-package';
|
|
28
|
+
|
|
29
|
+
// Load use-m dynamically
|
|
30
|
+
const { use } = eval(
|
|
31
|
+
await (await fetch('https://unpkg.com/use-m/use.js')).text()
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// Import link-foundation libraries
|
|
35
|
+
const { $ } = await use('command-stream');
|
|
36
|
+
const { makeConfig } = await use('lino-arguments');
|
|
37
|
+
|
|
38
|
+
// Parse CLI arguments using lino-arguments
|
|
39
|
+
// Note: Using --release-version instead of --version to avoid conflict with yargs' built-in --version flag
|
|
40
|
+
const config = makeConfig({
|
|
41
|
+
yargs: ({ yargs, getenv }) =>
|
|
42
|
+
yargs
|
|
43
|
+
.option('release-version', {
|
|
44
|
+
type: 'string',
|
|
45
|
+
default: getenv('VERSION', ''),
|
|
46
|
+
describe: 'Version number (e.g., v0.8.36)',
|
|
47
|
+
})
|
|
48
|
+
.option('release-id', {
|
|
49
|
+
type: 'string',
|
|
50
|
+
default: getenv('RELEASE_ID', ''),
|
|
51
|
+
describe: 'GitHub release ID',
|
|
52
|
+
})
|
|
53
|
+
.option('repository', {
|
|
54
|
+
type: 'string',
|
|
55
|
+
default: getenv('REPOSITORY', ''),
|
|
56
|
+
describe: 'GitHub repository (e.g., owner/repo)',
|
|
57
|
+
})
|
|
58
|
+
.option('commit-sha', {
|
|
59
|
+
type: 'string',
|
|
60
|
+
default: getenv('COMMIT_SHA', ''),
|
|
61
|
+
describe: 'Commit SHA for PR detection',
|
|
62
|
+
}),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const releaseId = config.releaseId;
|
|
66
|
+
const version = config.releaseVersion;
|
|
67
|
+
const repository = config.repository;
|
|
68
|
+
const passedCommitSha = config.commitSha;
|
|
69
|
+
|
|
70
|
+
if (!releaseId || !version || !repository) {
|
|
71
|
+
console.error(
|
|
72
|
+
'Usage: format-release-notes.mjs --release-id <releaseId> --release-version <version> --repository <repository> [--commit-sha <sha>]'
|
|
73
|
+
);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
// Get current release body
|
|
79
|
+
const result = await $`gh api repos/${repository}/releases/${releaseId}`.run({
|
|
80
|
+
capture: true,
|
|
81
|
+
});
|
|
82
|
+
const releaseData = JSON.parse(result.stdout);
|
|
83
|
+
|
|
84
|
+
const currentBody = releaseData.body || '';
|
|
85
|
+
|
|
86
|
+
// Skip if already formatted (has shields.io badge image)
|
|
87
|
+
if (currentBody.includes('img.shields.io')) {
|
|
88
|
+
console.log('ℹ️ Release notes already formatted');
|
|
89
|
+
process.exit(0);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Extract the patch changes section
|
|
93
|
+
// This regex handles two formats:
|
|
94
|
+
// 1. With commit hash: "- abc1234: Description"
|
|
95
|
+
// 2. Without commit hash: "- Description"
|
|
96
|
+
const patchChangesMatchWithHash = currentBody.match(
|
|
97
|
+
/### Patch Changes\s*\n\s*-\s+([a-f0-9]+):\s+(.+?)$/s
|
|
98
|
+
);
|
|
99
|
+
const patchChangesMatchNoHash = currentBody.match(
|
|
100
|
+
/### Patch Changes\s*\n\s*-\s+(.+?)$/s
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
let commitHash = null;
|
|
104
|
+
let rawDescription = null;
|
|
105
|
+
|
|
106
|
+
if (patchChangesMatchWithHash) {
|
|
107
|
+
// Format: - abc1234: Description
|
|
108
|
+
[, commitHash, rawDescription] = patchChangesMatchWithHash;
|
|
109
|
+
} else if (patchChangesMatchNoHash) {
|
|
110
|
+
// Format: - Description (no commit hash)
|
|
111
|
+
[, rawDescription] = patchChangesMatchNoHash;
|
|
112
|
+
} else {
|
|
113
|
+
console.log('⚠️ Could not parse patch changes from release notes');
|
|
114
|
+
process.exit(0);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Clean up the description:
|
|
118
|
+
// 1. Convert literal \n sequences (escaped newlines from GitHub API) to actual newlines
|
|
119
|
+
// 2. Remove leading/trailing quotes (including escaped quotes from command-stream shell escaping)
|
|
120
|
+
// 3. Remove any trailing npm package links or markdown that might be there
|
|
121
|
+
// 4. Normalize whitespace while preserving line breaks
|
|
122
|
+
const cleanDescription = rawDescription
|
|
123
|
+
.replace(/\\n/g, '\n') // Convert escaped \n to actual newlines
|
|
124
|
+
.replace(/^(\\['"])+/g, '') // Remove leading escaped quotes (e.g., \', \", \'', \'')
|
|
125
|
+
.replace(/(['"])+$/g, '') // Remove trailing unescaped quotes (e.g., ', ", '', '')
|
|
126
|
+
.replace(/^(['"])+/g, '') // Remove leading unescaped quotes
|
|
127
|
+
.replace(/📦.*$/s, '') // Remove any existing npm package info
|
|
128
|
+
.replace(/---.*$/s, '') // Remove any existing separators and everything after
|
|
129
|
+
.trim()
|
|
130
|
+
.split('\n') // Split by lines
|
|
131
|
+
.map((line) => line.trim()) // Trim whitespace from each line
|
|
132
|
+
.join('\n') // Rejoin with newlines
|
|
133
|
+
.replace(/\n{3,}/g, '\n\n'); // Normalize excessive blank lines (3+ becomes 2)
|
|
134
|
+
|
|
135
|
+
// Find the PR that contains the release commit
|
|
136
|
+
// Uses commit hash from changelog or passed commit SHA from workflow
|
|
137
|
+
let prNumber = null;
|
|
138
|
+
|
|
139
|
+
// Determine which commit SHA to use for PR lookup
|
|
140
|
+
const commitShaToLookup = commitHash || passedCommitSha;
|
|
141
|
+
|
|
142
|
+
if (commitShaToLookup) {
|
|
143
|
+
const source = commitHash ? 'changelog' : 'workflow';
|
|
144
|
+
console.log(
|
|
145
|
+
`ℹ️ Looking up PR for commit ${commitShaToLookup} (from ${source})`
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
const prResult =
|
|
150
|
+
await $`gh api "repos/${repository}/commits/${commitShaToLookup}/pulls"`.run(
|
|
151
|
+
{ capture: true }
|
|
152
|
+
);
|
|
153
|
+
const prsData = JSON.parse(prResult.stdout);
|
|
154
|
+
|
|
155
|
+
// Find the PR that's not the version bump PR (not "chore: version packages")
|
|
156
|
+
const relevantPr = prsData.find(
|
|
157
|
+
(pr) => !pr.title.includes('version packages')
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
if (relevantPr) {
|
|
161
|
+
prNumber = relevantPr.number;
|
|
162
|
+
console.log(`✅ Found PR #${prNumber} containing commit`);
|
|
163
|
+
} else if (prsData.length > 0) {
|
|
164
|
+
console.log(
|
|
165
|
+
'⚠️ Found PRs but all are version bump PRs, not linking any'
|
|
166
|
+
);
|
|
167
|
+
} else {
|
|
168
|
+
console.log(
|
|
169
|
+
'ℹ️ No PR found containing this commit - not adding PR link'
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
} catch (error) {
|
|
173
|
+
console.log('⚠️ Could not find PR for commit', commitShaToLookup);
|
|
174
|
+
console.log(' Error:', error.message);
|
|
175
|
+
if (process.env.DEBUG) {
|
|
176
|
+
console.error(error);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
// No commit hash available from any source
|
|
181
|
+
console.log('ℹ️ No commit SHA available - not adding PR link');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Build formatted release notes
|
|
185
|
+
const versionWithoutV = version.replace(/^v/, '');
|
|
186
|
+
const npmBadge = `[](https://www.npmjs.com/package/${PACKAGE_NAME}/v/${versionWithoutV})`;
|
|
187
|
+
|
|
188
|
+
let formattedBody = `${cleanDescription}`;
|
|
189
|
+
|
|
190
|
+
// Add PR link if available
|
|
191
|
+
if (prNumber) {
|
|
192
|
+
formattedBody += `\n\n**Related Pull Request:** #${prNumber}`;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
formattedBody += `\n\n---\n\n${npmBadge}`;
|
|
196
|
+
|
|
197
|
+
// Update the release using JSON input to properly handle special characters
|
|
198
|
+
const updatePayload = JSON.stringify({ body: formattedBody });
|
|
199
|
+
await $`gh api repos/${repository}/releases/${releaseId} -X PATCH --input -`.run(
|
|
200
|
+
{ stdin: updatePayload }
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
console.log(`✅ Formatted release notes for v${versionWithoutV}`);
|
|
204
|
+
if (prNumber) {
|
|
205
|
+
console.log(` - Added link to PR #${prNumber}`);
|
|
206
|
+
}
|
|
207
|
+
console.log(' - Added shields.io npm badge');
|
|
208
|
+
console.log(' - Cleaned up formatting');
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error('❌ Error formatting release notes:', error.message);
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|