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,126 @@
|
|
|
1
|
+
{
|
|
2
|
+
"additions": 644,
|
|
3
|
+
"author": {
|
|
4
|
+
"id": "MDQ6VXNlcjE0MzE5MDQ=",
|
|
5
|
+
"is_bot": false,
|
|
6
|
+
"login": "konard",
|
|
7
|
+
"name": "Konstantin Diachenko"
|
|
8
|
+
},
|
|
9
|
+
"baseRefName": "main",
|
|
10
|
+
"body": "## Summary\n\nThis PR makes the changeset CI/CD system more robust by addressing the issue where PRs fail validation when multiple PRs merge before a release cycle completes.\n\n### Changes Made\n\n- **Update validate-changeset.mjs to check only PR-added changesets**\n - Uses git diff to compare base vs head SHA\n - Only validates changesets ADDED by the current PR (not pre-existing ones from merged PRs)\n - Falls back to checking all changesets for local development\n\n- **Add merge-changesets.mjs script**\n - Combines multiple pending changesets into a single merged changeset during release\n - Uses the highest version bump type (major > minor > patch)\n - Preserves all descriptions in chronological order (by file modification time)\n - Cleans up individual changeset files after merging\n\n- **Update release workflow**\n - Adds step to merge multiple changesets before running `changeset version`\n - Passes proper environment variables (GITHUB_BASE_SHA, GITHUB_HEAD_SHA) to validation script\n\n- **Add comprehensive tests**\n - Tests for both validate-changeset.mjs and merge-changesets.mjs\n - Tests for bump type priority, chronological ordering, edge cases\n\n### How It Works\n\n**During PR validation:**\n```\nBefore: Check all .changeset/*.md files → Fail if >1 exists\nAfter: Check only files ADDED in this PR → Fail if >1 was added\n```\n\n**During release:**\n```\nBefore: changeset version → (fail if multiple changesets)\nAfter: merge-changesets.mjs → changeset version → (always single changeset)\n```\n\n### Benefits\n\n1. **No more false failures** - PRs won't fail just because other PRs merged first\n2. **Preserved sequence** - Changesets are merged chronologically\n3. **Correct version bumps** - Major changes won't be downgraded to patch\n4. **Backward compatible** - Local development still works without git context\n\n### Testing\n\nAll tests pass locally:\n- `node experiments/test-changeset-scripts.mjs` - 10/10 tests pass\n- `npm run format:check` - passes\n- `npm run lint` - passes\n\n## Fixes\n\nFixes #960\n\n---\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n",
|
|
11
|
+
"commits": [
|
|
12
|
+
{
|
|
13
|
+
"authoredDate": "2025-12-22T06:32:45Z",
|
|
14
|
+
"authors": [
|
|
15
|
+
{
|
|
16
|
+
"email": "drakonard@gmail.com",
|
|
17
|
+
"id": "MDQ6VXNlcjE0MzE5MDQ=",
|
|
18
|
+
"login": "konard",
|
|
19
|
+
"name": "konard"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"committedDate": "2025-12-22T06:32:45Z",
|
|
23
|
+
"messageBody": "Adding CLAUDE.md with task information for AI processing.\nThis file will be removed when the task is complete.\n\nIssue: https://github.com/link-assistant/hive-mind/issues/960",
|
|
24
|
+
"messageHeadline": "Initial commit with task details",
|
|
25
|
+
"oid": "a352ed4055d96cbc47e3bad062674c37104f2705"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"authoredDate": "2025-12-22T06:39:54Z",
|
|
29
|
+
"authors": [
|
|
30
|
+
{
|
|
31
|
+
"email": "drakonard@gmail.com",
|
|
32
|
+
"id": "MDQ6VXNlcjE0MzE5MDQ=",
|
|
33
|
+
"login": "konard",
|
|
34
|
+
"name": "konard"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"email": "noreply@anthropic.com",
|
|
38
|
+
"id": "MDQ6VXNlcjgxODQ3",
|
|
39
|
+
"login": "claude",
|
|
40
|
+
"name": "Claude"
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"committedDate": "2025-12-22T06:39:54Z",
|
|
44
|
+
"messageBody": "- Update validate-changeset.mjs to check only changesets ADDED by the PR\n (uses git diff to compare base vs head, not all files in .changeset/)\n- Add merge-changesets.mjs to combine multiple pending changesets during release\n (uses highest bump type, preserves descriptions chronologically)\n- Update release workflow to merge multiple changesets before version bump\n- Add comprehensive tests for both changeset scripts\n\nThis fixes the issue where PRs fail validation when multiple PRs merge\nbefore a release cycle completes (each PR sees the other's changesets).\n\nFixes #960\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
|
|
45
|
+
"messageHeadline": "Improve changeset CI/CD robustness for concurrent PRs",
|
|
46
|
+
"oid": "8934ed62e8436b80ab0d620e24731d1d447fbe06"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"authoredDate": "2025-12-22T06:41:49Z",
|
|
50
|
+
"authors": [
|
|
51
|
+
{
|
|
52
|
+
"email": "drakonard@gmail.com",
|
|
53
|
+
"id": "MDQ6VXNlcjE0MzE5MDQ=",
|
|
54
|
+
"login": "konard",
|
|
55
|
+
"name": "konard"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"email": "noreply@anthropic.com",
|
|
59
|
+
"id": "MDQ6VXNlcjgxODQ3",
|
|
60
|
+
"login": "claude",
|
|
61
|
+
"name": "Claude"
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
"committedDate": "2025-12-22T06:41:49Z",
|
|
65
|
+
"messageBody": "🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
|
|
66
|
+
"messageHeadline": "Remove CLAUDE.md task file (not needed in PR)",
|
|
67
|
+
"oid": "70607f2aa60aca2c1ee985f6327dacc5dbc4e9bf"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"authoredDate": "2025-12-22T07:22:07Z",
|
|
71
|
+
"authors": [
|
|
72
|
+
{
|
|
73
|
+
"email": "drakonard@gmail.com",
|
|
74
|
+
"id": "MDQ6VXNlcjE0MzE5MDQ=",
|
|
75
|
+
"login": "konard",
|
|
76
|
+
"name": "konard"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"email": "noreply@anthropic.com",
|
|
80
|
+
"id": "MDQ6VXNlcjgxODQ3",
|
|
81
|
+
"login": "claude",
|
|
82
|
+
"name": "Claude"
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"committedDate": "2025-12-22T07:22:07Z",
|
|
86
|
+
"messageBody": "The test script is not part of regular CI/CD runs, it's meant\nfor one-time verification during development. Per feedback,\nmoving it to experiments folder to better reflect its purpose.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
|
|
87
|
+
"messageHeadline": "Move test-changeset-scripts.mjs to experiments folder",
|
|
88
|
+
"oid": "4b415eca0a66154fea175a8f68121fea5ed509ca"
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"createdAt": "2025-12-22T06:32:52Z",
|
|
92
|
+
"deletions": 53,
|
|
93
|
+
"files": [
|
|
94
|
+
{
|
|
95
|
+
"path": ".changeset/robust-changeset-cicd.md",
|
|
96
|
+
"additions": 11,
|
|
97
|
+
"deletions": 0
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"path": ".github/workflows/release.yml",
|
|
101
|
+
"additions": 14,
|
|
102
|
+
"deletions": 0
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"path": "experiments/test-changeset-scripts.mjs",
|
|
106
|
+
"additions": 257,
|
|
107
|
+
"deletions": 0
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"path": "scripts/merge-changesets.mjs",
|
|
111
|
+
"additions": 184,
|
|
112
|
+
"deletions": 0
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"path": "scripts/validate-changeset.mjs",
|
|
116
|
+
"additions": 178,
|
|
117
|
+
"deletions": 53
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
"headRefName": "issue-960-4b0fdff43593",
|
|
121
|
+
"labels": [],
|
|
122
|
+
"mergedAt": "2025-12-22T19:22:16Z",
|
|
123
|
+
"number": 961,
|
|
124
|
+
"state": "MERGED",
|
|
125
|
+
"title": "Improve changeset CI/CD robustness for concurrent PRs"
|
|
126
|
+
}
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
# Case Study: Issue #21 - Supporting Both Single-Language and Multi-Language Repositories
|
|
2
|
+
|
|
3
|
+
## Executive Summary
|
|
4
|
+
|
|
5
|
+
This case study analyzes two related CI/CD pipeline failures in the [link-assistant/agent](https://github.com/link-assistant/agent) repository and documents best practices for supporting both single-language and multi-language repository structures in CI/CD scripts.
|
|
6
|
+
|
|
7
|
+
The issues stemmed from:
|
|
8
|
+
|
|
9
|
+
1. **Issue #111**: npm peer dependency conflicts requiring `--legacy-peer-deps` flag
|
|
10
|
+
2. **Issue #113**: Working directory corruption caused by the `command-stream` library's virtual `cd` command
|
|
11
|
+
|
|
12
|
+
## Background
|
|
13
|
+
|
|
14
|
+
The link-assistant/agent repository is a multi-language monorepo containing:
|
|
15
|
+
|
|
16
|
+
- JavaScript/TypeScript code in the `js/` subfolder
|
|
17
|
+
- Rust code in the `rust/` subfolder
|
|
18
|
+
|
|
19
|
+
The CI/CD scripts needed to support both:
|
|
20
|
+
|
|
21
|
+
- **Multi-language repositories** (like link-assistant/agent) where `package.json` is at `./js/package.json`
|
|
22
|
+
- **Single-language repositories** where `package.json` is at `./package.json` (repository root)
|
|
23
|
+
|
|
24
|
+
## Timeline of Events
|
|
25
|
+
|
|
26
|
+
### Issue #111 - npm ERESOLVE Error
|
|
27
|
+
|
|
28
|
+
| Timestamp (UTC) | Event |
|
|
29
|
+
| ------------------- | ------------------------------------------------------ |
|
|
30
|
+
| 2026-01-08 02:22:24 | CI Run #20803315337 triggered on push to main branch |
|
|
31
|
+
| 2026-01-08 02:22:46 | Lint and Format Check completed successfully |
|
|
32
|
+
| 2026-01-08 02:22:29 | Ubuntu unit tests passed |
|
|
33
|
+
| 2026-01-08 02:22:32 | macOS unit tests passed |
|
|
34
|
+
| 2026-01-08 02:23:24 | Windows unit tests passed |
|
|
35
|
+
| 2026-01-08 02:23:32 | Release job started |
|
|
36
|
+
| 2026-01-08 02:23:55 | Changeset version ran successfully |
|
|
37
|
+
| 2026-01-08 02:23:56 | `npm install --package-lock-only` failed with ERESOLVE |
|
|
38
|
+
| 2026-01-08 02:23:58 | Release job failed with exit code 1 |
|
|
39
|
+
|
|
40
|
+
### Issue #113 - Working Directory Corruption
|
|
41
|
+
|
|
42
|
+
| Timestamp (UTC) | Event |
|
|
43
|
+
| ------------------- | ------------------------------------------------------------------ |
|
|
44
|
+
| 2026-01-10 22:38:48 | PR #112 merged (fixed --legacy-peer-deps) |
|
|
45
|
+
| 2026-01-10 22:38:56 | CI Run #20885464993 triggered |
|
|
46
|
+
| 2026-01-10 22:40:29 | Version bump completed successfully |
|
|
47
|
+
| 2026-01-10 22:40:29 | Error: ENOENT: no such file or directory, open './js/package.json' |
|
|
48
|
+
| 2026-01-10 22:40:29 | Release job failed with exit code 1 |
|
|
49
|
+
|
|
50
|
+
## Root Cause Analysis
|
|
51
|
+
|
|
52
|
+
### Root Cause #1: Missing `--legacy-peer-deps` Flag
|
|
53
|
+
|
|
54
|
+
**Problem**: The release scripts (`changeset-version.mjs` and `instant-version-bump.mjs`) were running `npm install --package-lock-only` without the `--legacy-peer-deps` flag.
|
|
55
|
+
|
|
56
|
+
**Error Message**:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
npm error code ERESOLVE
|
|
60
|
+
npm error ERESOLVE could not resolve
|
|
61
|
+
npm error While resolving: @opentui/solid@0.1.60
|
|
62
|
+
npm error Found: solid-js@1.9.10
|
|
63
|
+
npm error Could not resolve dependency:
|
|
64
|
+
npm error peer solid-js@"1.9.9" from @opentui/solid@0.1.60
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Root Cause**: Starting with npm 7, the package manager enforces stricter peer dependency rules. The project had conflicting peer dependency requirements:
|
|
68
|
+
|
|
69
|
+
- `@opentui/solid@0.1.60` required exactly `solid-js@1.9.9`
|
|
70
|
+
- The root project specified `solid-js@^1.9.10`
|
|
71
|
+
|
|
72
|
+
**Inconsistency**: The workflow file (`js.yml`) correctly used `--legacy-peer-deps` for initial `npm install`, but the release scripts did not.
|
|
73
|
+
|
|
74
|
+
### Root Cause #2: Virtual `cd` Command Behavior
|
|
75
|
+
|
|
76
|
+
**Problem**: The `command-stream` library implements `cd` as a virtual command that calls `process.chdir()` on the Node.js process itself, permanently changing the working directory.
|
|
77
|
+
|
|
78
|
+
**Code Flow**:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
Repository Root (/)
|
|
82
|
+
├── js/
|
|
83
|
+
│ └── package.json <- Target file
|
|
84
|
+
└── scripts/
|
|
85
|
+
└── version-and-commit.mjs
|
|
86
|
+
|
|
87
|
+
1. Script starts with cwd = /
|
|
88
|
+
2. Script runs: await $`cd js && npm run changeset:version`
|
|
89
|
+
3. command-stream's cd command calls: process.chdir('js')
|
|
90
|
+
4. cwd is now /js/
|
|
91
|
+
5. Script tries to read: readFileSync('./js/package.json')
|
|
92
|
+
6. This resolves to: /js/js/package.json <- DOES NOT EXIST!
|
|
93
|
+
7. Error: ENOENT
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Error Message**:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
Error: ENOENT: no such file or directory, open './js/package.json'
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Why This Was Hard to Detect**:
|
|
103
|
+
|
|
104
|
+
- The `cd` command in most shell scripts only affects the subprocess, not the parent process
|
|
105
|
+
- Developers familiar with Unix shells would not expect `cd` to affect the Node.js process
|
|
106
|
+
- The error message didn't clearly indicate that the working directory had changed
|
|
107
|
+
- The `command-stream` library documentation doesn't prominently warn about this behavior
|
|
108
|
+
|
|
109
|
+
## Solutions Implemented
|
|
110
|
+
|
|
111
|
+
### Solution #1: Add `--legacy-peer-deps` Flag (PR #112)
|
|
112
|
+
|
|
113
|
+
**Files Modified**:
|
|
114
|
+
|
|
115
|
+
- `scripts/changeset-version.mjs`
|
|
116
|
+
- `scripts/instant-version-bump.mjs`
|
|
117
|
+
|
|
118
|
+
**Change**:
|
|
119
|
+
|
|
120
|
+
```javascript
|
|
121
|
+
// Before
|
|
122
|
+
await $`npm install --package-lock-only`;
|
|
123
|
+
|
|
124
|
+
// After
|
|
125
|
+
await $`npm install --package-lock-only --legacy-peer-deps`;
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Solution #2: Working Directory Restoration and Auto-Detection (PR #114)
|
|
129
|
+
|
|
130
|
+
**New Utility Modules Created**:
|
|
131
|
+
|
|
132
|
+
- `scripts/js-paths.mjs` - JavaScript package root detection
|
|
133
|
+
- `scripts/rust-paths.mjs` - Rust package root detection
|
|
134
|
+
|
|
135
|
+
**Key Features**:
|
|
136
|
+
|
|
137
|
+
1. **Automatic Package Root Detection**:
|
|
138
|
+
- Check for `./package.json` or `./Cargo.toml` first (single-language repo)
|
|
139
|
+
- If not found, check `./js/` or `./rust/` subfolder (multi-language repo)
|
|
140
|
+
- Throw helpful error if neither exists
|
|
141
|
+
|
|
142
|
+
2. **Explicit Configuration Options**:
|
|
143
|
+
- CLI arguments: `--js-root <path>` or `--rust-root <path>`
|
|
144
|
+
- Environment variables: `JS_ROOT` or `RUST_ROOT`
|
|
145
|
+
|
|
146
|
+
3. **Working Directory Preservation**:
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
// Store the original working directory
|
|
150
|
+
const originalCwd = process.cwd();
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
// Code that uses cd
|
|
154
|
+
await $`cd js && npm run changeset:version`;
|
|
155
|
+
|
|
156
|
+
// Restore the original working directory
|
|
157
|
+
process.chdir(originalCwd);
|
|
158
|
+
|
|
159
|
+
// Now file operations work correctly
|
|
160
|
+
const packageJson = JSON.parse(readFileSync('./js/package.json', 'utf8'));
|
|
161
|
+
} catch (error) {
|
|
162
|
+
// Handle error
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Updated Scripts**:
|
|
167
|
+
|
|
168
|
+
- `scripts/version-and-commit.mjs`
|
|
169
|
+
- `scripts/instant-version-bump.mjs`
|
|
170
|
+
- `scripts/publish-to-npm.mjs`
|
|
171
|
+
- `scripts/rust-version-and-commit.mjs`
|
|
172
|
+
- `scripts/rust-collect-changelog.mjs`
|
|
173
|
+
- `scripts/rust-get-bump-type.mjs`
|
|
174
|
+
|
|
175
|
+
## Best Practices for Multi-Language Repositories
|
|
176
|
+
|
|
177
|
+
Based on this case study and industry research, here are recommended best practices:
|
|
178
|
+
|
|
179
|
+
### 1. Consistent npm Flag Usage
|
|
180
|
+
|
|
181
|
+
**Problem**: Using `--legacy-peer-deps` in some places but not others causes inconsistent behavior.
|
|
182
|
+
|
|
183
|
+
**Best Practice**:
|
|
184
|
+
|
|
185
|
+
- If using `--legacy-peer-deps`, use it consistently across all npm install commands
|
|
186
|
+
- Consider adding a `.npmrc` file with `legacy-peer-deps=true` for project-wide consistency
|
|
187
|
+
- Document the reason for using this flag for future maintainers
|
|
188
|
+
|
|
189
|
+
### 2. Automatic Package Root Detection
|
|
190
|
+
|
|
191
|
+
**Problem**: Hardcoding paths like `./js/package.json` doesn't work for single-language repos.
|
|
192
|
+
|
|
193
|
+
**Best Practice**:
|
|
194
|
+
|
|
195
|
+
```javascript
|
|
196
|
+
// Detect JavaScript package root
|
|
197
|
+
function getJsRoot() {
|
|
198
|
+
if (existsSync('./package.json')) return '.'; // Single-language
|
|
199
|
+
if (existsSync('./js/package.json')) return 'js'; // Multi-language
|
|
200
|
+
throw new Error('package.json not found');
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### 3. Working Directory Management
|
|
205
|
+
|
|
206
|
+
**Problem**: Some shell libraries modify `process.cwd()` unexpectedly.
|
|
207
|
+
|
|
208
|
+
**Best Practice**:
|
|
209
|
+
|
|
210
|
+
- Always save and restore the original working directory when using `cd` commands
|
|
211
|
+
- Use absolute paths when possible
|
|
212
|
+
- Prefer `--prefix` or `--cwd` options over `cd` when available
|
|
213
|
+
|
|
214
|
+
### 4. Modular Project Structure
|
|
215
|
+
|
|
216
|
+
**Best Practice**: Organize multi-language repositories with clear separation:
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
repository/
|
|
220
|
+
├── js/ # JavaScript/TypeScript
|
|
221
|
+
│ ├── package.json
|
|
222
|
+
│ └── src/
|
|
223
|
+
├── rust/ # Rust
|
|
224
|
+
│ ├── Cargo.toml
|
|
225
|
+
│ └── src/
|
|
226
|
+
├── scripts/ # Shared CI/CD scripts
|
|
227
|
+
└── .github/workflows/
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### 5. Unified Task Commands
|
|
231
|
+
|
|
232
|
+
**Best Practice**: Provide unified scripts that work across both repo structures:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
# Auto-detection (default)
|
|
236
|
+
node scripts/version-and-commit.mjs --mode changeset
|
|
237
|
+
|
|
238
|
+
# Explicit configuration
|
|
239
|
+
node scripts/version-and-commit.mjs --mode changeset --js-root js
|
|
240
|
+
|
|
241
|
+
# Via environment variable
|
|
242
|
+
JS_ROOT=js node scripts/version-and-commit.mjs --mode changeset
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### 6. Caching Language-Specific Artifacts
|
|
246
|
+
|
|
247
|
+
**Best Practice**: Cache appropriately based on language:
|
|
248
|
+
|
|
249
|
+
- JavaScript: `node_modules/`, `package-lock.json`
|
|
250
|
+
- Rust: `target/`, `Cargo.lock`
|
|
251
|
+
- Use remote caches for CI efficiency
|
|
252
|
+
|
|
253
|
+
## Lessons Learned
|
|
254
|
+
|
|
255
|
+
1. **Understand Library Internals**: Third-party libraries may have non-obvious behaviors. The `command-stream` library's virtual `cd` command is powerful but can cause issues if not handled properly.
|
|
256
|
+
|
|
257
|
+
2. **Consistency is Key**: When using npm flags like `--legacy-peer-deps`, ensure they are used consistently across all npm install commands in both workflow files and scripts.
|
|
258
|
+
|
|
259
|
+
3. **Test Release Workflows**: Release workflows often run in different conditions than regular CI. Test them separately to catch issues like these.
|
|
260
|
+
|
|
261
|
+
4. **Add Defensive Code**: When using commands that modify process state, always save and restore the original state.
|
|
262
|
+
|
|
263
|
+
5. **Document Non-Obvious Behaviors**: Include detailed comments explaining why certain patterns (like `process.chdir()` restoration) are necessary.
|
|
264
|
+
|
|
265
|
+
6. **Support Multiple Repository Structures**: Design CI/CD scripts to auto-detect and support both single-language and multi-language repository structures.
|
|
266
|
+
|
|
267
|
+
## References
|
|
268
|
+
|
|
269
|
+
### External Resources
|
|
270
|
+
|
|
271
|
+
- [Managing multiple languages in a monorepo](https://graphite.dev/guides/managing-multiple-languages-in-a-monorepo)
|
|
272
|
+
- [Monorepo Explained](https://monorepo.tools/)
|
|
273
|
+
- [Benefits and challenges of monorepo development practices - CircleCI](https://circleci.com/blog/monorepo-dev-practices/)
|
|
274
|
+
- [Building a Monorepo with Rust - Earthly Blog](https://earthly.dev/blog/rust-monorepo/)
|
|
275
|
+
- [Node.js process.chdir() Method - GeeksforGeeks](https://www.geeksforgeeks.org/node-js-process-chdir-method/)
|
|
276
|
+
- [Fix 'npm ERR! ERESOLVE unable to resolve dependency tree'](https://blog.openreplay.com/fix-npm-err-eresolve-dependency/)
|
|
277
|
+
- [Resolving NPM Peer Dependency Conflicts](https://medium.com/@robert.maiersilldorff/resolving-npm-peer-dependency-conflicts-70d67f4ca7dc)
|
|
278
|
+
|
|
279
|
+
### Related Issues and Pull Requests
|
|
280
|
+
|
|
281
|
+
- [Issue #111](https://github.com/link-assistant/agent/issues/111) - JS release does not work
|
|
282
|
+
- [Issue #113](https://github.com/link-assistant/agent/issues/113) - JavaScript publish does not work
|
|
283
|
+
- [PR #112](https://github.com/link-assistant/agent/pull/112) - fix: Add --legacy-peer-deps flag to release scripts
|
|
284
|
+
- [PR #114](https://github.com/link-assistant/agent/pull/114) - feat: Add configurable package root for release scripts
|
|
285
|
+
|
|
286
|
+
### CI Logs (Preserved)
|
|
287
|
+
|
|
288
|
+
- `ci-logs/run-20803315337.txt` - Issue #111 CI failure log
|
|
289
|
+
- `ci-logs/run-20885464993.txt` - Issue #113 CI failure log
|
|
290
|
+
|
|
291
|
+
## Proposed Solutions for This Template Repository
|
|
292
|
+
|
|
293
|
+
Based on the analysis above, this template repository (js-ai-driven-development-pipeline-template) should incorporate these solutions to ensure best practices by default:
|
|
294
|
+
|
|
295
|
+
### 1. Add Path Detection Utilities
|
|
296
|
+
|
|
297
|
+
Create `scripts/js-paths.mjs` with automatic package root detection:
|
|
298
|
+
|
|
299
|
+
- Support `./package.json` for single-language repos
|
|
300
|
+
- Support `./js/package.json` for multi-language repos
|
|
301
|
+
- Provide CLI and environment variable configuration options
|
|
302
|
+
|
|
303
|
+
### 2. Update Release Scripts
|
|
304
|
+
|
|
305
|
+
Modify all release scripts to:
|
|
306
|
+
|
|
307
|
+
- Use the path detection utilities
|
|
308
|
+
- Save and restore `process.cwd()` after `cd` commands
|
|
309
|
+
- Use `--legacy-peer-deps` consistently for npm commands
|
|
310
|
+
|
|
311
|
+
### 3. Add `.npmrc` Configuration (Optional)
|
|
312
|
+
|
|
313
|
+
Consider adding a `.npmrc` file with:
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
legacy-peer-deps=true
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### 4. Document the Approach
|
|
320
|
+
|
|
321
|
+
Update repository documentation to explain:
|
|
322
|
+
|
|
323
|
+
- How scripts auto-detect repository structure
|
|
324
|
+
- How to configure for different project layouts
|
|
325
|
+
- Known limitations and workarounds
|
|
326
|
+
|
|
327
|
+
### 5. Prevent False Positives in CI/CD (Based on Issue #115/PR #116)
|
|
328
|
+
|
|
329
|
+
**Problem**: The `changeset publish` command exits with code 0 even when packages fail to publish. The `command-stream` library doesn't throw exceptions on non-zero exit codes. This can result in false positive CI/CD statuses where failures are reported as successes.
|
|
330
|
+
|
|
331
|
+
**Best Practice**: Implement multi-layer failure detection:
|
|
332
|
+
|
|
333
|
+
1. **Output pattern matching** - Scan command output for failure patterns:
|
|
334
|
+
|
|
335
|
+
```javascript
|
|
336
|
+
const FAILURE_PATTERNS = [
|
|
337
|
+
'packages failed to publish',
|
|
338
|
+
'error occurred while publishing',
|
|
339
|
+
'npm error code E',
|
|
340
|
+
'npm error 404',
|
|
341
|
+
'npm error 401',
|
|
342
|
+
'npm error 403',
|
|
343
|
+
'Access token expired',
|
|
344
|
+
'ENEEDAUTH',
|
|
345
|
+
];
|
|
346
|
+
|
|
347
|
+
function detectPublishFailure(output) {
|
|
348
|
+
const lowerOutput = output.toLowerCase();
|
|
349
|
+
for (const pattern of FAILURE_PATTERNS) {
|
|
350
|
+
if (lowerOutput.includes(pattern.toLowerCase())) {
|
|
351
|
+
return pattern;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
2. **Exit code checking** - Check the exit code even though `changeset` may return 0 on failure:
|
|
359
|
+
|
|
360
|
+
```javascript
|
|
361
|
+
if (result.code !== 0) {
|
|
362
|
+
throw new Error(`Publish failed with exit code ${result.code}`);
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
3. **Post-publish verification** - Verify the package is actually on npm:
|
|
367
|
+
|
|
368
|
+
```javascript
|
|
369
|
+
async function verifyPublished(packageName, version) {
|
|
370
|
+
const result = await $`npm view "${packageName}@${version}" version`.run({
|
|
371
|
+
capture: true,
|
|
372
|
+
});
|
|
373
|
+
return result.code === 0 && result.stdout.trim().includes(version);
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
4. **Use `.run({ capture: true })`** - Capture command output for analysis instead of just running and assuming success.
|
|
378
|
+
|
|
379
|
+
**Related References**:
|
|
380
|
+
|
|
381
|
+
- [Issue #115](https://github.com/link-assistant/agent/issues/115) - Error was treated as success
|
|
382
|
+
- [PR #116](https://github.com/link-assistant/agent/pull/116) - fix: Add publish verification and failure detection to prevent false positives
|
|
383
|
+
- [Changesets Issue #1621](https://github.com/changesets/changesets/issues/1621) - Git tag failure isn't handled
|
|
384
|
+
- [Changesets Issue #1280](https://github.com/changesets/changesets/issues/1280) - Action succeeds but package is never published
|