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,879 @@
|
|
|
1
|
+
diff --git a/docs/case-studies/issue-113/README.md b/docs/case-studies/issue-113/README.md
|
|
2
|
+
new file mode 100644
|
|
3
|
+
index 0000000..bd453f9
|
|
4
|
+
--- /dev/null
|
|
5
|
+
+++ b/docs/case-studies/issue-113/README.md
|
|
6
|
+
@@ -0,0 +1,111 @@
|
|
7
|
+
+# Case Study: Issue #113 - JavaScript Publish Does Not Work
|
|
8
|
+
+
|
|
9
|
+
+## Summary
|
|
10
|
+
+
|
|
11
|
+
+The JavaScript CI/CD pipeline was failing during the release step due to a subtle bug related to how the `command-stream` library handles the `cd` command.
|
|
12
|
+
+
|
|
13
|
+
+## Timeline of Events
|
|
14
|
+
+
|
|
15
|
+
+1. **CI Run Triggered**: Push to main branch triggered the JS CI/CD Pipeline (run #20885464993)
|
|
16
|
+
+2. **Tests Passed**: Lint, format check, and unit tests all passed successfully
|
|
17
|
+
+3. **Release Job Started**: The release job started and began processing changesets
|
|
18
|
+
+4. **Version Bump Executed**: The `version-and-commit.mjs` script ran `cd js && npm run changeset:version`
|
|
19
|
+
+5. **Failure**: After the version bump completed, the script failed with:
|
|
20
|
+
+ ```
|
|
21
|
+
+ Error: ENOENT: no such file or directory, open './js/package.json'
|
|
22
|
+
+ ```
|
|
23
|
+
+
|
|
24
|
+
+## Root Cause Analysis
|
|
25
|
+
+
|
|
26
|
+
+### The Bug
|
|
27
|
+
+
|
|
28
|
+
+The root cause was a subtle interaction between the `command-stream` library and Node.js's process working directory:
|
|
29
|
+
+
|
|
30
|
+
+1. **command-stream's Virtual `cd` Command**: The `command-stream` library implements `cd` as a **virtual command** that calls `process.chdir()` on the Node.js process itself, rather than just affecting the subprocess.
|
|
31
|
+
+
|
|
32
|
+
+2. **Working Directory Persistence**: When the script executed:
|
|
33
|
+
+ ```javascript
|
|
34
|
+
+ await $`cd js && npm run changeset:version`;
|
|
35
|
+
+ ```
|
|
36
|
+
+ The `cd js` command permanently changed the Node.js process's working directory from the repository root to the `js/` subdirectory.
|
|
37
|
+
+
|
|
38
|
+
+3. **Subsequent File Access Failure**: After the command returned, when the script tried to read `./js/package.json`, it was looking for the file relative to the **new** working directory (`js/`), which would resolve to `js/js/package.json` - a path that doesn't exist.
|
|
39
|
+
+
|
|
40
|
+
+### Code Flow
|
|
41
|
+
+
|
|
42
|
+
+```
|
|
43
|
+
+Repository Root (/)
|
|
44
|
+
+├── js/
|
|
45
|
+
+│ └── package.json <- This is what we want to read
|
|
46
|
+
+└── scripts/
|
|
47
|
+
+ └── version-and-commit.mjs
|
|
48
|
+
+
|
|
49
|
+
+1. Script starts with cwd = /
|
|
50
|
+
+2. Script runs: await $`cd js && npm run changeset:version`
|
|
51
|
+
+3. command-stream's cd command calls: process.chdir('js')
|
|
52
|
+
+4. cwd is now /js/
|
|
53
|
+
+5. Script tries to read: readFileSync('./js/package.json')
|
|
54
|
+
+6. This resolves to: /js/js/package.json <- DOES NOT EXIST!
|
|
55
|
+
+7. Error: ENOENT
|
|
56
|
+
+```
|
|
57
|
+
+
|
|
58
|
+
+### Why This Was Hard to Detect
|
|
59
|
+
+
|
|
60
|
+
+- The `cd` command in most shell scripts only affects the subprocess, not the parent process
|
|
61
|
+
+- Developers familiar with Unix shells would not expect `cd` to affect the Node.js process
|
|
62
|
+
+- The error message didn't clearly indicate that the working directory had changed
|
|
63
|
+
+- The `command-stream` library documentation doesn't prominently warn about this behavior
|
|
64
|
+
+
|
|
65
|
+
+## Solution
|
|
66
|
+
+
|
|
67
|
+
+The fix involves saving the original working directory and restoring it after any command that uses `cd`:
|
|
68
|
+
+
|
|
69
|
+
+```javascript
|
|
70
|
+
+// Store the original working directory
|
|
71
|
+
+const originalCwd = process.cwd();
|
|
72
|
+
+
|
|
73
|
+
+try {
|
|
74
|
+
+ // ... code that uses cd ...
|
|
75
|
+
+ await $`cd js && npm run changeset:version`;
|
|
76
|
+
+
|
|
77
|
+
+ // Restore the original working directory
|
|
78
|
+
+ process.chdir(originalCwd);
|
|
79
|
+
+
|
|
80
|
+
+ // Now file operations work correctly
|
|
81
|
+
+ const packageJson = JSON.parse(readFileSync('./js/package.json', 'utf8'));
|
|
82
|
+
+} catch (error) {
|
|
83
|
+
+ // Handle error
|
|
84
|
+
+}
|
|
85
|
+
+```
|
|
86
|
+
+
|
|
87
|
+
+### Files Modified
|
|
88
|
+
+
|
|
89
|
+
+1. **scripts/version-and-commit.mjs**: Added cwd preservation and restoration after `cd js && npm run changeset:version`
|
|
90
|
+
+
|
|
91
|
+
+2. **scripts/instant-version-bump.mjs**: Added cwd preservation and restoration after:
|
|
92
|
+
+ - `cd js && npm version ${bumpType} --no-git-tag-version`
|
|
93
|
+
+ - `cd js && npm install --package-lock-only --legacy-peer-deps`
|
|
94
|
+
+
|
|
95
|
+
+3. **scripts/publish-to-npm.mjs**: Added cwd preservation and restoration after `cd js && npm run changeset:publish`, including proper handling in the retry loop error path
|
|
96
|
+
+
|
|
97
|
+
+## Lessons Learned
|
|
98
|
+
+
|
|
99
|
+
+1. **Understand Library Internals**: Third-party libraries may have non-obvious behaviors. The `command-stream` library's virtual `cd` command is a powerful feature for maintaining working directory state, but it can cause issues if not handled properly.
|
|
100
|
+
+
|
|
101
|
+
+2. **Test Edge Cases**: The CI environment differs from local development. File path handling can behave differently depending on the working directory context.
|
|
102
|
+
+
|
|
103
|
+
+3. **Add Defensive Code**: When using commands that modify process state, always save and restore the original state.
|
|
104
|
+
+
|
|
105
|
+
+4. **Document Non-Obvious Behaviors**: The fix includes detailed comments explaining why the `process.chdir()` restoration is necessary.
|
|
106
|
+
+
|
|
107
|
+
+## CI Logs
|
|
108
|
+
+
|
|
109
|
+
+The full CI logs are preserved in:
|
|
110
|
+
+- `ci-logs/full-run-20885464993.log` - Complete run log
|
|
111
|
+
+- `ci-logs/release-job-60008012717.log` - Detailed release job log
|
|
112
|
+
+
|
|
113
|
+
+## References
|
|
114
|
+
+
|
|
115
|
+
+- [GitHub Issue #113](https://github.com/link-assistant/agent/issues/113)
|
|
116
|
+
+- [CI Run #20885464993](https://github.com/link-assistant/agent/actions/runs/20885464993)
|
|
117
|
+
+- [command-stream npm package](https://www.npmjs.com/package/command-stream)
|
|
118
|
+
diff --git a/scripts/instant-version-bump.mjs b/scripts/instant-version-bump.mjs
|
|
119
|
+
index c1a34dd..7673338 100644
|
|
120
|
+
--- a/scripts/instant-version-bump.mjs
|
|
121
|
+
+++ b/scripts/instant-version-bump.mjs
|
|
122
|
+
@@ -14,6 +14,13 @@
|
|
123
|
+
|
|
124
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
125
|
+
|
|
126
|
+
+import {
|
|
127
|
+
+ getJsRoot,
|
|
128
|
+
+ getPackageJsonPath,
|
|
129
|
+
+ needsCd,
|
|
130
|
+
+ parseJsRootConfig,
|
|
131
|
+
+} from './js-paths.mjs';
|
|
132
|
+
+
|
|
133
|
+
// Load use-m dynamically
|
|
134
|
+
const { use } = eval(
|
|
135
|
+
await (await fetch('https://unpkg.com/use-m/use.js')).text()
|
|
136
|
+
@@ -37,11 +44,24 @@ const config = makeConfig({
|
|
137
|
+
type: 'string',
|
|
138
|
+
default: getenv('DESCRIPTION', ''),
|
|
139
|
+
describe: 'Description for the version bump',
|
|
140
|
+
+ })
|
|
141
|
+
+ .option('js-root', {
|
|
142
|
+
+ type: 'string',
|
|
143
|
+
+ default: getenv('JS_ROOT', ''),
|
|
144
|
+
+ describe: 'JavaScript package root directory (auto-detected if not specified)',
|
|
145
|
+
}),
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
+// Store the original working directory to restore after cd commands
|
|
149
|
+
+// IMPORTANT: command-stream's cd is a virtual command that calls process.chdir()
|
|
150
|
+
+const originalCwd = process.cwd();
|
|
151
|
+
+
|
|
152
|
+
try {
|
|
153
|
+
- const { bumpType, description } = config;
|
|
154
|
+
+ const { bumpType, description, jsRoot: jsRootArg } = config;
|
|
155
|
+
+
|
|
156
|
+
+ // Get JavaScript package root (auto-detect or use explicit config)
|
|
157
|
+
+ const jsRootConfig = jsRootArg || parseJsRootConfig();
|
|
158
|
+
+ const jsRoot = getJsRoot({ jsRoot: jsRootConfig, verbose: true });
|
|
159
|
+
const finalDescription = description || `Manual ${bumpType} release`;
|
|
160
|
+
|
|
161
|
+
if (!bumpType || !['major', 'minor', 'patch'].includes(bumpType)) {
|
|
162
|
+
@@ -54,15 +74,22 @@ try {
|
|
163
|
+
console.log(`\nBumping version (${bumpType})...`);
|
|
164
|
+
|
|
165
|
+
// Get current version
|
|
166
|
+
- const packageJson = JSON.parse(readFileSync('js/package.json', 'utf-8'));
|
|
167
|
+
+ const packageJsonPath = getPackageJsonPath({ jsRoot });
|
|
168
|
+
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
169
|
+
const oldVersion = packageJson.version;
|
|
170
|
+
console.log(`Current version: ${oldVersion}`);
|
|
171
|
+
|
|
172
|
+
// Bump version using npm version (doesn't create git tag)
|
|
173
|
+
- await $`cd js && npm version ${bumpType} --no-git-tag-version`;
|
|
174
|
+
+ // IMPORTANT: cd is a virtual command that calls process.chdir(), so we restore after
|
|
175
|
+
+ if (needsCd({ jsRoot })) {
|
|
176
|
+
+ await $`cd ${jsRoot} && npm version ${bumpType} --no-git-tag-version`;
|
|
177
|
+
+ process.chdir(originalCwd);
|
|
178
|
+
+ } else {
|
|
179
|
+
+ await $`npm version ${bumpType} --no-git-tag-version`;
|
|
180
|
+
+ }
|
|
181
|
+
|
|
182
|
+
// Get new version
|
|
183
|
+
- const updatedPackageJson = JSON.parse(readFileSync('js/package.json', 'utf-8'));
|
|
184
|
+
+ const updatedPackageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
185
|
+
const newVersion = updatedPackageJson.version;
|
|
186
|
+
console.log(`New version: ${newVersion}`);
|
|
187
|
+
|
|
188
|
+
@@ -108,7 +135,13 @@ try {
|
|
189
|
+
|
|
190
|
+
// Synchronize package-lock.json
|
|
191
|
+
console.log('\nSynchronizing package-lock.json...');
|
|
192
|
+
- await $`cd js && npm install --package-lock-only --legacy-peer-deps`;
|
|
193
|
+
+ // IMPORTANT: cd is a virtual command that calls process.chdir(), so we restore after
|
|
194
|
+
+ if (needsCd({ jsRoot })) {
|
|
195
|
+
+ await $`cd ${jsRoot} && npm install --package-lock-only --legacy-peer-deps`;
|
|
196
|
+
+ process.chdir(originalCwd);
|
|
197
|
+
+ } else {
|
|
198
|
+
+ await $`npm install --package-lock-only --legacy-peer-deps`;
|
|
199
|
+
+ }
|
|
200
|
+
|
|
201
|
+
console.log('\n✅ Instant version bump complete');
|
|
202
|
+
console.log(`Version: ${oldVersion} → ${newVersion}`);
|
|
203
|
+
diff --git a/scripts/js-paths.mjs b/scripts/js-paths.mjs
|
|
204
|
+
new file mode 100644
|
|
205
|
+
index 0000000..810d56b
|
|
206
|
+
--- /dev/null
|
|
207
|
+
+++ b/scripts/js-paths.mjs
|
|
208
|
+
@@ -0,0 +1,159 @@
|
|
209
|
+
+#!/usr/bin/env node
|
|
210
|
+
+
|
|
211
|
+
+/**
|
|
212
|
+
+ * JavaScript package path detection utility
|
|
213
|
+
+ *
|
|
214
|
+
+ * Automatically detects the JavaScript package root for both:
|
|
215
|
+
+ * - Single-language repositories (package.json in root)
|
|
216
|
+
+ * - Multi-language repositories (package.json in js/ subfolder)
|
|
217
|
+
+ *
|
|
218
|
+
+ * Usage:
|
|
219
|
+
+ * import { getJsRoot, getPackageJsonPath, getChangesetDir } from './js-paths.mjs';
|
|
220
|
+
+ *
|
|
221
|
+
+ * const jsRoot = getJsRoot(); // Returns 'js' or '.'
|
|
222
|
+
+ * const pkgPath = getPackageJsonPath(); // Returns 'js/package.json' or './package.json'
|
|
223
|
+
+ */
|
|
224
|
+
+
|
|
225
|
+
+import { existsSync } from 'fs';
|
|
226
|
+
+import { join } from 'path';
|
|
227
|
+
+
|
|
228
|
+
+// Cache for detected paths (computed once per process)
|
|
229
|
+
+let cachedJsRoot = null;
|
|
230
|
+
+
|
|
231
|
+
+/**
|
|
232
|
+
+ * Detect JavaScript package root directory
|
|
233
|
+
+ * Checks in order:
|
|
234
|
+
+ * 1. ./package.json (single-language repo)
|
|
235
|
+
+ * 2. ./js/package.json (multi-language repo)
|
|
236
|
+
+ *
|
|
237
|
+
+ * @param {Object} options - Configuration options
|
|
238
|
+
+ * @param {string} [options.jsRoot] - Explicitly set JavaScript root (overrides auto-detection)
|
|
239
|
+
+ * @param {boolean} [options.verbose=false] - Log detection details
|
|
240
|
+
+ * @returns {string} The JavaScript root directory ('.' or 'js')
|
|
241
|
+
+ * @throws {Error} If no package.json is found in expected locations
|
|
242
|
+
+ */
|
|
243
|
+
+export function getJsRoot(options = {}) {
|
|
244
|
+
+ const { jsRoot: explicitRoot, verbose = false } = options;
|
|
245
|
+
+
|
|
246
|
+
+ // If explicitly configured, use that
|
|
247
|
+
+ if (explicitRoot !== undefined) {
|
|
248
|
+
+ if (verbose) {
|
|
249
|
+
+ console.log(`Using explicitly configured JavaScript root: ${explicitRoot}`);
|
|
250
|
+
+ }
|
|
251
|
+
+ return explicitRoot;
|
|
252
|
+
+ }
|
|
253
|
+
+
|
|
254
|
+
+ // Return cached value if already computed
|
|
255
|
+
+ if (cachedJsRoot !== null) {
|
|
256
|
+
+ return cachedJsRoot;
|
|
257
|
+
+ }
|
|
258
|
+
+
|
|
259
|
+
+ // Check for single-language repo (package.json in root)
|
|
260
|
+
+ if (existsSync('./package.json')) {
|
|
261
|
+
+ if (verbose) {
|
|
262
|
+
+ console.log('Detected single-language repository (package.json in root)');
|
|
263
|
+
+ }
|
|
264
|
+
+ cachedJsRoot = '.';
|
|
265
|
+
+ return cachedJsRoot;
|
|
266
|
+
+ }
|
|
267
|
+
+
|
|
268
|
+
+ // Check for multi-language repo (package.json in js/ subfolder)
|
|
269
|
+
+ if (existsSync('./js/package.json')) {
|
|
270
|
+
+ if (verbose) {
|
|
271
|
+
+ console.log('Detected multi-language repository (package.json in js/)');
|
|
272
|
+
+ }
|
|
273
|
+
+ cachedJsRoot = 'js';
|
|
274
|
+
+ return cachedJsRoot;
|
|
275
|
+
+ }
|
|
276
|
+
+
|
|
277
|
+
+ // No package.json found
|
|
278
|
+
+ throw new Error(
|
|
279
|
+
+ 'Could not find package.json in expected locations.\n' +
|
|
280
|
+
+ 'Searched in:\n' +
|
|
281
|
+
+ ' - ./package.json (single-language repository)\n' +
|
|
282
|
+
+ ' - ./js/package.json (multi-language repository)\n\n' +
|
|
283
|
+
+ 'To fix this, either:\n' +
|
|
284
|
+
+ ' 1. Run the script from the repository root\n' +
|
|
285
|
+
+ ' 2. Explicitly configure the JavaScript root using --js-root option\n' +
|
|
286
|
+
+ ' 3. Set the JS_ROOT environment variable'
|
|
287
|
+
+ );
|
|
288
|
+
+}
|
|
289
|
+
+
|
|
290
|
+
+/**
|
|
291
|
+
+ * Get the path to package.json
|
|
292
|
+
+ * @param {Object} options - Configuration options (passed to getJsRoot)
|
|
293
|
+
+ * @returns {string} Path to package.json
|
|
294
|
+
+ */
|
|
295
|
+
+export function getPackageJsonPath(options = {}) {
|
|
296
|
+
+ const jsRoot = getJsRoot(options);
|
|
297
|
+
+ return jsRoot === '.' ? './package.json' : join(jsRoot, 'package.json');
|
|
298
|
+
+}
|
|
299
|
+
+
|
|
300
|
+
+/**
|
|
301
|
+
+ * Get the path to package-lock.json
|
|
302
|
+
+ * @param {Object} options - Configuration options (passed to getJsRoot)
|
|
303
|
+
+ * @returns {string} Path to package-lock.json
|
|
304
|
+
+ */
|
|
305
|
+
+export function getPackageLockPath(options = {}) {
|
|
306
|
+
+ const jsRoot = getJsRoot(options);
|
|
307
|
+
+ return jsRoot === '.' ? './package-lock.json' : join(jsRoot, 'package-lock.json');
|
|
308
|
+
+}
|
|
309
|
+
+
|
|
310
|
+
+/**
|
|
311
|
+
+ * Get the path to .changeset directory
|
|
312
|
+
+ * @param {Object} options - Configuration options (passed to getJsRoot)
|
|
313
|
+
+ * @returns {string} Path to .changeset directory
|
|
314
|
+
+ */
|
|
315
|
+
+export function getChangesetDir(options = {}) {
|
|
316
|
+
+ const jsRoot = getJsRoot(options);
|
|
317
|
+
+ return jsRoot === '.' ? './.changeset' : join(jsRoot, '.changeset');
|
|
318
|
+
+}
|
|
319
|
+
+
|
|
320
|
+
+/**
|
|
321
|
+
+ * Get the cd command prefix for running npm commands
|
|
322
|
+
+ * Returns empty string for single-language repos, 'cd js && ' for multi-language repos
|
|
323
|
+
+ * @param {Object} options - Configuration options (passed to getJsRoot)
|
|
324
|
+
+ * @returns {string} CD prefix for shell commands
|
|
325
|
+
+ */
|
|
326
|
+
+export function getCdPrefix(options = {}) {
|
|
327
|
+
+ const jsRoot = getJsRoot(options);
|
|
328
|
+
+ return jsRoot === '.' ? '' : `cd ${jsRoot} && `;
|
|
329
|
+
+}
|
|
330
|
+
+
|
|
331
|
+
+/**
|
|
332
|
+
+ * Check if we need to change directory before running npm commands
|
|
333
|
+
+ * @param {Object} options - Configuration options (passed to getJsRoot)
|
|
334
|
+
+ * @returns {boolean} True if cd is needed
|
|
335
|
+
+ */
|
|
336
|
+
+export function needsCd(options = {}) {
|
|
337
|
+
+ const jsRoot = getJsRoot(options);
|
|
338
|
+
+ return jsRoot !== '.';
|
|
339
|
+
+}
|
|
340
|
+
+
|
|
341
|
+
+/**
|
|
342
|
+
+ * Reset the cached JavaScript root (useful for testing)
|
|
343
|
+
+ */
|
|
344
|
+
+export function resetCache() {
|
|
345
|
+
+ cachedJsRoot = null;
|
|
346
|
+
+}
|
|
347
|
+
+
|
|
348
|
+
+/**
|
|
349
|
+
+ * Parse JavaScript root from CLI arguments or environment
|
|
350
|
+
+ * Supports --js-root argument and JS_ROOT environment variable
|
|
351
|
+
+ * @returns {string|undefined} Configured JavaScript root or undefined for auto-detection
|
|
352
|
+
+ */
|
|
353
|
+
+export function parseJsRootConfig() {
|
|
354
|
+
+ // Check CLI arguments
|
|
355
|
+
+ const args = process.argv.slice(2);
|
|
356
|
+
+ const jsRootIndex = args.indexOf('--js-root');
|
|
357
|
+
+ if (jsRootIndex >= 0 && args[jsRootIndex + 1]) {
|
|
358
|
+
+ return args[jsRootIndex + 1];
|
|
359
|
+
+ }
|
|
360
|
+
+
|
|
361
|
+
+ // Check environment variable
|
|
362
|
+
+ if (process.env.JS_ROOT) {
|
|
363
|
+
+ return process.env.JS_ROOT;
|
|
364
|
+
+ }
|
|
365
|
+
+
|
|
366
|
+
+ return undefined;
|
|
367
|
+
+}
|
|
368
|
+
diff --git a/scripts/publish-to-npm.mjs b/scripts/publish-to-npm.mjs
|
|
369
|
+
index 450af67..9b41bc4 100644
|
|
370
|
+
--- a/scripts/publish-to-npm.mjs
|
|
371
|
+
+++ b/scripts/publish-to-npm.mjs
|
|
372
|
+
@@ -15,6 +15,13 @@
|
|
373
|
+
|
|
374
|
+
import { readFileSync, appendFileSync } from 'fs';
|
|
375
|
+
|
|
376
|
+
+import {
|
|
377
|
+
+ getJsRoot,
|
|
378
|
+
+ getPackageJsonPath,
|
|
379
|
+
+ needsCd,
|
|
380
|
+
+ parseJsRootConfig,
|
|
381
|
+
+} from './js-paths.mjs';
|
|
382
|
+
+
|
|
383
|
+
// Package name from package.json
|
|
384
|
+
const PACKAGE_NAME = '@link-assistant/agent';
|
|
385
|
+
|
|
386
|
+
@@ -30,14 +37,24 @@ const { makeConfig } = await use('lino-arguments');
|
|
387
|
+
// Parse CLI arguments using lino-arguments
|
|
388
|
+
const config = makeConfig({
|
|
389
|
+
yargs: ({ yargs, getenv }) =>
|
|
390
|
+
- yargs.option('should-pull', {
|
|
391
|
+
- type: 'boolean',
|
|
392
|
+
- default: getenv('SHOULD_PULL', false),
|
|
393
|
+
- describe: 'Pull latest changes before publishing',
|
|
394
|
+
- }),
|
|
395
|
+
+ yargs
|
|
396
|
+
+ .option('should-pull', {
|
|
397
|
+
+ type: 'boolean',
|
|
398
|
+
+ default: getenv('SHOULD_PULL', false),
|
|
399
|
+
+ describe: 'Pull latest changes before publishing',
|
|
400
|
+
+ })
|
|
401
|
+
+ .option('js-root', {
|
|
402
|
+
+ type: 'string',
|
|
403
|
+
+ default: getenv('JS_ROOT', ''),
|
|
404
|
+
+ describe: 'JavaScript package root directory (auto-detected if not specified)',
|
|
405
|
+
+ }),
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
-const { shouldPull } = config;
|
|
409
|
+
+const { shouldPull, jsRoot: jsRootArg } = config;
|
|
410
|
+
+
|
|
411
|
+
+// Get JavaScript package root (auto-detect or use explicit config)
|
|
412
|
+
+const jsRootConfig = jsRootArg || parseJsRootConfig();
|
|
413
|
+
+const jsRoot = getJsRoot({ jsRoot: jsRootConfig, verbose: true });
|
|
414
|
+
const MAX_RETRIES = 3;
|
|
415
|
+
const RETRY_DELAY = 10000; // 10 seconds
|
|
416
|
+
|
|
417
|
+
@@ -62,6 +79,10 @@ function setOutput(key, value) {
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
async function main() {
|
|
421
|
+
+ // Store the original working directory to restore after cd commands
|
|
422
|
+
+ // IMPORTANT: command-stream's cd is a virtual command that calls process.chdir()
|
|
423
|
+
+ const originalCwd = process.cwd();
|
|
424
|
+
+
|
|
425
|
+
try {
|
|
426
|
+
if (shouldPull) {
|
|
427
|
+
// Pull the latest changes we just pushed
|
|
428
|
+
@@ -69,7 +90,8 @@ async function main() {
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Get current version
|
|
432
|
+
- const packageJson = JSON.parse(readFileSync('./js/package.json', 'utf8'));
|
|
433
|
+
+ const packageJsonPath = getPackageJsonPath({ jsRoot });
|
|
434
|
+
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
435
|
+
const currentVersion = packageJson.version;
|
|
436
|
+
console.log(`Current version to publish: ${currentVersion}`);
|
|
437
|
+
|
|
438
|
+
@@ -101,7 +123,14 @@ async function main() {
|
|
439
|
+
for (let i = 1; i <= MAX_RETRIES; i++) {
|
|
440
|
+
console.log(`Publish attempt ${i} of ${MAX_RETRIES}...`);
|
|
441
|
+
try {
|
|
442
|
+
- await $`npm run changeset:publish`;
|
|
443
|
+
+ // Run changeset:publish from the js directory where package.json with this script exists
|
|
444
|
+
+ // IMPORTANT: cd is a virtual command that calls process.chdir(), so we restore after
|
|
445
|
+
+ if (needsCd({ jsRoot })) {
|
|
446
|
+
+ await $`cd ${jsRoot} && npm run changeset:publish`;
|
|
447
|
+
+ process.chdir(originalCwd);
|
|
448
|
+
+ } else {
|
|
449
|
+
+ await $`npm run changeset:publish`;
|
|
450
|
+
+ }
|
|
451
|
+
setOutput('published', 'true');
|
|
452
|
+
setOutput('published_version', currentVersion);
|
|
453
|
+
console.log(
|
|
454
|
+
@@ -109,6 +138,10 @@ async function main() {
|
|
455
|
+
);
|
|
456
|
+
return;
|
|
457
|
+
} catch (_error) {
|
|
458
|
+
+ // Restore cwd on error before retry
|
|
459
|
+
+ if (needsCd({ jsRoot })) {
|
|
460
|
+
+ process.chdir(originalCwd);
|
|
461
|
+
+ }
|
|
462
|
+
if (i < MAX_RETRIES) {
|
|
463
|
+
console.log(
|
|
464
|
+
`Publish failed, waiting ${RETRY_DELAY / 1000}s before retry...`
|
|
465
|
+
diff --git a/scripts/rust-collect-changelog.mjs b/scripts/rust-collect-changelog.mjs
|
|
466
|
+
index dc4f385..dd6712c 100644
|
|
467
|
+
--- a/scripts/rust-collect-changelog.mjs
|
|
468
|
+
+++ b/scripts/rust-collect-changelog.mjs
|
|
469
|
+
@@ -15,8 +15,29 @@ import {
|
|
470
|
+
} from 'fs';
|
|
471
|
+
import { join } from 'path';
|
|
472
|
+
|
|
473
|
+
-const CHANGELOG_DIR = 'rust/changelog.d';
|
|
474
|
+
-const CHANGELOG_FILE = 'rust/CHANGELOG.md';
|
|
475
|
+
+import {
|
|
476
|
+
+ getRustRoot,
|
|
477
|
+
+ getCargoTomlPath,
|
|
478
|
+
+ getChangelogDir,
|
|
479
|
+
+ getChangelogPath,
|
|
480
|
+
+ parseRustRootConfig,
|
|
481
|
+
+} from './rust-paths.mjs';
|
|
482
|
+
+
|
|
483
|
+
+// Simple CLI argument parsing
|
|
484
|
+
+const args = process.argv.slice(2);
|
|
485
|
+
+const getArg = (name, defaultValue) => {
|
|
486
|
+
+ const index = args.indexOf(`--${name}`);
|
|
487
|
+
+ return index >= 0 && args[index + 1] ? args[index + 1] : defaultValue;
|
|
488
|
+
+};
|
|
489
|
+
+
|
|
490
|
+
+// Get Rust package root (auto-detect or use explicit config)
|
|
491
|
+
+const rustRootConfig = getArg('rust-root', '') || parseRustRootConfig();
|
|
492
|
+
+const rustRoot = getRustRoot({ rustRoot: rustRootConfig || undefined, verbose: true });
|
|
493
|
+
+
|
|
494
|
+
+// Get paths based on detected/configured rust root
|
|
495
|
+
+const CARGO_TOML = getCargoTomlPath({ rustRoot });
|
|
496
|
+
+const CHANGELOG_DIR = getChangelogDir({ rustRoot });
|
|
497
|
+
+const CHANGELOG_FILE = getChangelogPath({ rustRoot });
|
|
498
|
+
const INSERT_MARKER = '<!-- changelog-insert-here -->';
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
@@ -24,11 +45,11 @@ const INSERT_MARKER = '<!-- changelog-insert-here -->';
|
|
502
|
+
* @returns {string}
|
|
503
|
+
*/
|
|
504
|
+
function getVersionFromCargo() {
|
|
505
|
+
- const cargoToml = readFileSync('rust/Cargo.toml', 'utf-8');
|
|
506
|
+
+ const cargoToml = readFileSync(CARGO_TOML, 'utf-8');
|
|
507
|
+
const match = cargoToml.match(/^version\s*=\s*"([^"]+)"/m);
|
|
508
|
+
|
|
509
|
+
if (!match) {
|
|
510
|
+
- console.error('Error: Could not find version in rust/Cargo.toml');
|
|
511
|
+
+ console.error(`Error: Could not find version in ${CARGO_TOML}`);
|
|
512
|
+
process.exit(1);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
diff --git a/scripts/rust-get-bump-type.mjs b/scripts/rust-get-bump-type.mjs
|
|
516
|
+
index 31b492e..0a608a9 100644
|
|
517
|
+
--- a/scripts/rust-get-bump-type.mjs
|
|
518
|
+
+++ b/scripts/rust-get-bump-type.mjs
|
|
519
|
+
@@ -20,6 +20,12 @@
|
|
520
|
+
import { readFileSync, readdirSync, existsSync, appendFileSync } from 'fs';
|
|
521
|
+
import { join } from 'path';
|
|
522
|
+
|
|
523
|
+
+import {
|
|
524
|
+
+ getRustRoot,
|
|
525
|
+
+ getChangelogDir,
|
|
526
|
+
+ parseRustRootConfig,
|
|
527
|
+
+} from './rust-paths.mjs';
|
|
528
|
+
+
|
|
529
|
+
// Simple CLI argument parsing
|
|
530
|
+
const args = process.argv.slice(2);
|
|
531
|
+
const getArg = (name, defaultValue) => {
|
|
532
|
+
@@ -29,7 +35,12 @@ const getArg = (name, defaultValue) => {
|
|
533
|
+
|
|
534
|
+
const defaultBump = getArg('default', process.env.DEFAULT_BUMP || 'patch');
|
|
535
|
+
|
|
536
|
+
-const CHANGELOG_DIR = 'rust/changelog.d';
|
|
537
|
+
+// Get Rust package root (auto-detect or use explicit config)
|
|
538
|
+
+const rustRootConfig = getArg('rust-root', '') || parseRustRootConfig();
|
|
539
|
+
+const rustRoot = getRustRoot({ rustRoot: rustRootConfig || undefined, verbose: true });
|
|
540
|
+
+
|
|
541
|
+
+// Get paths based on detected/configured rust root
|
|
542
|
+
+const CHANGELOG_DIR = getChangelogDir({ rustRoot });
|
|
543
|
+
|
|
544
|
+
// Bump type priority (higher = more significant)
|
|
545
|
+
const BUMP_PRIORITY = {
|
|
546
|
+
diff --git a/scripts/rust-paths.mjs b/scripts/rust-paths.mjs
|
|
547
|
+
new file mode 100644
|
|
548
|
+
index 0000000..4f4636a
|
|
549
|
+
--- /dev/null
|
|
550
|
+
+++ b/scripts/rust-paths.mjs
|
|
551
|
+
@@ -0,0 +1,169 @@
|
|
552
|
+
+#!/usr/bin/env node
|
|
553
|
+
+
|
|
554
|
+
+/**
|
|
555
|
+
+ * Rust package path detection utility
|
|
556
|
+
+ *
|
|
557
|
+
+ * Automatically detects the Rust package root for both:
|
|
558
|
+
+ * - Single-language repositories (Cargo.toml in root)
|
|
559
|
+
+ * - Multi-language repositories (Cargo.toml in rust/ subfolder)
|
|
560
|
+
+ *
|
|
561
|
+
+ * Usage:
|
|
562
|
+
+ * import { getRustRoot, getCargoTomlPath, getChangelogDir } from './rust-paths.mjs';
|
|
563
|
+
+ *
|
|
564
|
+
+ * const rustRoot = getRustRoot(); // Returns 'rust' or '.'
|
|
565
|
+
+ * const cargoPath = getCargoTomlPath(); // Returns 'rust/Cargo.toml' or './Cargo.toml'
|
|
566
|
+
+ */
|
|
567
|
+
+
|
|
568
|
+
+import { existsSync } from 'fs';
|
|
569
|
+
+import { join } from 'path';
|
|
570
|
+
+
|
|
571
|
+
+// Cache for detected paths (computed once per process)
|
|
572
|
+
+let cachedRustRoot = null;
|
|
573
|
+
+
|
|
574
|
+
+/**
|
|
575
|
+
+ * Detect Rust package root directory
|
|
576
|
+
+ * Checks in order:
|
|
577
|
+
+ * 1. ./Cargo.toml (single-language repo)
|
|
578
|
+
+ * 2. ./rust/Cargo.toml (multi-language repo)
|
|
579
|
+
+ *
|
|
580
|
+
+ * @param {Object} options - Configuration options
|
|
581
|
+
+ * @param {string} [options.rustRoot] - Explicitly set Rust root (overrides auto-detection)
|
|
582
|
+
+ * @param {boolean} [options.verbose=false] - Log detection details
|
|
583
|
+
+ * @returns {string} The Rust root directory ('.' or 'rust')
|
|
584
|
+
+ * @throws {Error} If no Cargo.toml is found in expected locations
|
|
585
|
+
+ */
|
|
586
|
+
+export function getRustRoot(options = {}) {
|
|
587
|
+
+ const { rustRoot: explicitRoot, verbose = false } = options;
|
|
588
|
+
+
|
|
589
|
+
+ // If explicitly configured, use that
|
|
590
|
+
+ if (explicitRoot !== undefined) {
|
|
591
|
+
+ if (verbose) {
|
|
592
|
+
+ console.log(`Using explicitly configured Rust root: ${explicitRoot}`);
|
|
593
|
+
+ }
|
|
594
|
+
+ return explicitRoot;
|
|
595
|
+
+ }
|
|
596
|
+
+
|
|
597
|
+
+ // Return cached value if already computed
|
|
598
|
+
+ if (cachedRustRoot !== null) {
|
|
599
|
+
+ return cachedRustRoot;
|
|
600
|
+
+ }
|
|
601
|
+
+
|
|
602
|
+
+ // Check for single-language repo (Cargo.toml in root)
|
|
603
|
+
+ if (existsSync('./Cargo.toml')) {
|
|
604
|
+
+ if (verbose) {
|
|
605
|
+
+ console.log('Detected single-language repository (Cargo.toml in root)');
|
|
606
|
+
+ }
|
|
607
|
+
+ cachedRustRoot = '.';
|
|
608
|
+
+ return cachedRustRoot;
|
|
609
|
+
+ }
|
|
610
|
+
+
|
|
611
|
+
+ // Check for multi-language repo (Cargo.toml in rust/ subfolder)
|
|
612
|
+
+ if (existsSync('./rust/Cargo.toml')) {
|
|
613
|
+
+ if (verbose) {
|
|
614
|
+
+ console.log('Detected multi-language repository (Cargo.toml in rust/)');
|
|
615
|
+
+ }
|
|
616
|
+
+ cachedRustRoot = 'rust';
|
|
617
|
+
+ return cachedRustRoot;
|
|
618
|
+
+ }
|
|
619
|
+
+
|
|
620
|
+
+ // No Cargo.toml found
|
|
621
|
+
+ throw new Error(
|
|
622
|
+
+ 'Could not find Cargo.toml in expected locations.\n' +
|
|
623
|
+
+ 'Searched in:\n' +
|
|
624
|
+
+ ' - ./Cargo.toml (single-language repository)\n' +
|
|
625
|
+
+ ' - ./rust/Cargo.toml (multi-language repository)\n\n' +
|
|
626
|
+
+ 'To fix this, either:\n' +
|
|
627
|
+
+ ' 1. Run the script from the repository root\n' +
|
|
628
|
+
+ ' 2. Explicitly configure the Rust root using --rust-root option\n' +
|
|
629
|
+
+ ' 3. Set the RUST_ROOT environment variable'
|
|
630
|
+
+ );
|
|
631
|
+
+}
|
|
632
|
+
+
|
|
633
|
+
+/**
|
|
634
|
+
+ * Get the path to Cargo.toml
|
|
635
|
+
+ * @param {Object} options - Configuration options (passed to getRustRoot)
|
|
636
|
+
+ * @returns {string} Path to Cargo.toml
|
|
637
|
+
+ */
|
|
638
|
+
+export function getCargoTomlPath(options = {}) {
|
|
639
|
+
+ const rustRoot = getRustRoot(options);
|
|
640
|
+
+ return rustRoot === '.' ? './Cargo.toml' : join(rustRoot, 'Cargo.toml');
|
|
641
|
+
+}
|
|
642
|
+
+
|
|
643
|
+
+/**
|
|
644
|
+
+ * Get the path to Cargo.lock
|
|
645
|
+
+ * @param {Object} options - Configuration options (passed to getRustRoot)
|
|
646
|
+
+ * @returns {string} Path to Cargo.lock
|
|
647
|
+
+ */
|
|
648
|
+
+export function getCargoLockPath(options = {}) {
|
|
649
|
+
+ const rustRoot = getRustRoot(options);
|
|
650
|
+
+ return rustRoot === '.' ? './Cargo.lock' : join(rustRoot, 'Cargo.lock');
|
|
651
|
+
+}
|
|
652
|
+
+
|
|
653
|
+
+/**
|
|
654
|
+
+ * Get the path to changelog.d directory
|
|
655
|
+
+ * @param {Object} options - Configuration options (passed to getRustRoot)
|
|
656
|
+
+ * @returns {string} Path to changelog.d directory
|
|
657
|
+
+ */
|
|
658
|
+
+export function getChangelogDir(options = {}) {
|
|
659
|
+
+ const rustRoot = getRustRoot(options);
|
|
660
|
+
+ return rustRoot === '.' ? './changelog.d' : join(rustRoot, 'changelog.d');
|
|
661
|
+
+}
|
|
662
|
+
+
|
|
663
|
+
+/**
|
|
664
|
+
+ * Get the path to CHANGELOG.md
|
|
665
|
+
+ * @param {Object} options - Configuration options (passed to getRustRoot)
|
|
666
|
+
+ * @returns {string} Path to CHANGELOG.md
|
|
667
|
+
+ */
|
|
668
|
+
+export function getChangelogPath(options = {}) {
|
|
669
|
+
+ const rustRoot = getRustRoot(options);
|
|
670
|
+
+ return rustRoot === '.' ? './CHANGELOG.md' : join(rustRoot, 'CHANGELOG.md');
|
|
671
|
+
+}
|
|
672
|
+
+
|
|
673
|
+
+/**
|
|
674
|
+
+ * Get the cd command prefix for running cargo commands
|
|
675
|
+
+ * Returns empty string for single-language repos, 'cd rust && ' for multi-language repos
|
|
676
|
+
+ * @param {Object} options - Configuration options (passed to getRustRoot)
|
|
677
|
+
+ * @returns {string} CD prefix for shell commands
|
|
678
|
+
+ */
|
|
679
|
+
+export function getCdPrefix(options = {}) {
|
|
680
|
+
+ const rustRoot = getRustRoot(options);
|
|
681
|
+
+ return rustRoot === '.' ? '' : `cd ${rustRoot} && `;
|
|
682
|
+
+}
|
|
683
|
+
+
|
|
684
|
+
+/**
|
|
685
|
+
+ * Check if we need to change directory before running cargo commands
|
|
686
|
+
+ * @param {Object} options - Configuration options (passed to getRustRoot)
|
|
687
|
+
+ * @returns {boolean} True if cd is needed
|
|
688
|
+
+ */
|
|
689
|
+
+export function needsCd(options = {}) {
|
|
690
|
+
+ const rustRoot = getRustRoot(options);
|
|
691
|
+
+ return rustRoot !== '.';
|
|
692
|
+
+}
|
|
693
|
+
+
|
|
694
|
+
+/**
|
|
695
|
+
+ * Reset the cached Rust root (useful for testing)
|
|
696
|
+
+ */
|
|
697
|
+
+export function resetCache() {
|
|
698
|
+
+ cachedRustRoot = null;
|
|
699
|
+
+}
|
|
700
|
+
+
|
|
701
|
+
+/**
|
|
702
|
+
+ * Parse Rust root from CLI arguments or environment
|
|
703
|
+
+ * Supports --rust-root argument and RUST_ROOT environment variable
|
|
704
|
+
+ * @returns {string|undefined} Configured Rust root or undefined for auto-detection
|
|
705
|
+
+ */
|
|
706
|
+
+export function parseRustRootConfig() {
|
|
707
|
+
+ // Check CLI arguments
|
|
708
|
+
+ const args = process.argv.slice(2);
|
|
709
|
+
+ const rustRootIndex = args.indexOf('--rust-root');
|
|
710
|
+
+ if (rustRootIndex >= 0 && args[rustRootIndex + 1]) {
|
|
711
|
+
+ return args[rustRootIndex + 1];
|
|
712
|
+
+ }
|
|
713
|
+
+
|
|
714
|
+
+ // Check environment variable
|
|
715
|
+
+ if (process.env.RUST_ROOT) {
|
|
716
|
+
+ return process.env.RUST_ROOT;
|
|
717
|
+
+ }
|
|
718
|
+
+
|
|
719
|
+
+ return undefined;
|
|
720
|
+
+}
|
|
721
|
+
diff --git a/scripts/rust-version-and-commit.mjs b/scripts/rust-version-and-commit.mjs
|
|
722
|
+
index f90bbd7..7b9117c 100644
|
|
723
|
+
--- a/scripts/rust-version-and-commit.mjs
|
|
724
|
+
+++ b/scripts/rust-version-and-commit.mjs
|
|
725
|
+
@@ -18,6 +18,14 @@ import {
|
|
726
|
+
import { join } from 'path';
|
|
727
|
+
import { execSync } from 'child_process';
|
|
728
|
+
|
|
729
|
+
+import {
|
|
730
|
+
+ getRustRoot,
|
|
731
|
+
+ getCargoTomlPath,
|
|
732
|
+
+ getChangelogDir,
|
|
733
|
+
+ getChangelogPath,
|
|
734
|
+
+ parseRustRootConfig,
|
|
735
|
+
+} from './rust-paths.mjs';
|
|
736
|
+
+
|
|
737
|
+
// Simple CLI argument parsing
|
|
738
|
+
const args = process.argv.slice(2);
|
|
739
|
+
const getArg = (name, defaultValue) => {
|
|
740
|
+
@@ -28,16 +36,21 @@ const getArg = (name, defaultValue) => {
|
|
741
|
+
const bumpType = getArg('bump-type', process.env.BUMP_TYPE || '');
|
|
742
|
+
const description = getArg('description', process.env.DESCRIPTION || '');
|
|
743
|
+
|
|
744
|
+
+// Get Rust package root (auto-detect or use explicit config)
|
|
745
|
+
+const rustRootConfig = getArg('rust-root', '') || parseRustRootConfig();
|
|
746
|
+
+const rustRoot = getRustRoot({ rustRoot: rustRootConfig || undefined, verbose: true });
|
|
747
|
+
+
|
|
748
|
+
if (!bumpType || !['major', 'minor', 'patch'].includes(bumpType)) {
|
|
749
|
+
console.error(
|
|
750
|
+
- 'Usage: node scripts/rust-version-and-commit.mjs --bump-type <major|minor|patch> [--description <desc>]'
|
|
751
|
+
+ 'Usage: node scripts/rust-version-and-commit.mjs --bump-type <major|minor|patch> [--description <desc>] [--rust-root <path>]'
|
|
752
|
+
);
|
|
753
|
+
process.exit(1);
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
-const CARGO_TOML = 'rust/Cargo.toml';
|
|
757
|
+
-const CHANGELOG_DIR = 'rust/changelog.d';
|
|
758
|
+
-const CHANGELOG_FILE = 'rust/CHANGELOG.md';
|
|
759
|
+
+// Get paths based on detected/configured rust root
|
|
760
|
+
+const CARGO_TOML = getCargoTomlPath({ rustRoot });
|
|
761
|
+
+const CHANGELOG_DIR = getChangelogDir({ rustRoot });
|
|
762
|
+
+const CHANGELOG_FILE = getChangelogPath({ rustRoot });
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Append to GitHub Actions output file
|
|
766
|
+
diff --git a/scripts/version-and-commit.mjs b/scripts/version-and-commit.mjs
|
|
767
|
+
index 7235407..28d21dc 100644
|
|
768
|
+
--- a/scripts/version-and-commit.mjs
|
|
769
|
+
+++ b/scripts/version-and-commit.mjs
|
|
770
|
+
@@ -14,6 +14,14 @@
|
|
771
|
+
|
|
772
|
+
import { readFileSync, appendFileSync, readdirSync } from 'fs';
|
|
773
|
+
|
|
774
|
+
+import {
|
|
775
|
+
+ getJsRoot,
|
|
776
|
+
+ getPackageJsonPath,
|
|
777
|
+
+ getChangesetDir,
|
|
778
|
+
+ needsCd,
|
|
779
|
+
+ parseJsRootConfig,
|
|
780
|
+
+} from './js-paths.mjs';
|
|
781
|
+
+
|
|
782
|
+
// Load use-m dynamically
|
|
783
|
+
const { use } = eval(
|
|
784
|
+
await (await fetch('https://unpkg.com/use-m/use.js')).text()
|
|
785
|
+
@@ -42,16 +50,26 @@ const config = makeConfig({
|
|
786
|
+
type: 'string',
|
|
787
|
+
default: getenv('DESCRIPTION', ''),
|
|
788
|
+
describe: 'Description for instant version bump',
|
|
789
|
+
+ })
|
|
790
|
+
+ .option('js-root', {
|
|
791
|
+
+ type: 'string',
|
|
792
|
+
+ default: getenv('JS_ROOT', ''),
|
|
793
|
+
+ describe: 'JavaScript package root directory (auto-detected if not specified)',
|
|
794
|
+
}),
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
-const { mode, bumpType, description } = config;
|
|
798
|
+
+const { mode, bumpType, description, jsRoot: jsRootArg } = config;
|
|
799
|
+
+
|
|
800
|
+
+// Get JavaScript package root (auto-detect or use explicit config)
|
|
801
|
+
+const jsRootConfig = jsRootArg || parseJsRootConfig();
|
|
802
|
+
+const jsRoot = getJsRoot({ jsRoot: jsRootConfig, verbose: true });
|
|
803
|
+
|
|
804
|
+
// Debug: Log parsed configuration
|
|
805
|
+
console.log('Parsed configuration:', {
|
|
806
|
+
mode,
|
|
807
|
+
bumpType,
|
|
808
|
+
description: description || '(none)',
|
|
809
|
+
+ jsRoot,
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
// Detect if positional arguments were used (common mistake)
|
|
813
|
+
@@ -112,7 +130,7 @@ function setOutput(key, value) {
|
|
814
|
+
*/
|
|
815
|
+
function countChangesets() {
|
|
816
|
+
try {
|
|
817
|
+
- const changesetDir = 'js/.changeset';
|
|
818
|
+
+ const changesetDir = getChangesetDir({ jsRoot });
|
|
819
|
+
const files = readdirSync(changesetDir);
|
|
820
|
+
return files.filter((f) => f.endsWith('.md') && f !== 'README.md').length;
|
|
821
|
+
} catch {
|
|
822
|
+
@@ -125,16 +143,24 @@ function countChangesets() {
|
|
823
|
+
* @param {string} source - 'local' or 'remote'
|
|
824
|
+
*/
|
|
825
|
+
async function getVersion(source = 'local') {
|
|
826
|
+
+ const packageJsonPath = getPackageJsonPath({ jsRoot });
|
|
827
|
+
if (source === 'remote') {
|
|
828
|
+
- const result = await $`git show origin/main:js/package.json`.run({
|
|
829
|
+
+ // For remote, we need the path relative to repo root (without ./ prefix)
|
|
830
|
+
+ const remotePath = packageJsonPath.replace(/^\.\//, '');
|
|
831
|
+
+ const result = await $`git show origin/main:${remotePath}`.run({
|
|
832
|
+
capture: true,
|
|
833
|
+
});
|
|
834
|
+
return JSON.parse(result.stdout).version;
|
|
835
|
+
}
|
|
836
|
+
- return JSON.parse(readFileSync('./js/package.json', 'utf8')).version;
|
|
837
|
+
+ return JSON.parse(readFileSync(packageJsonPath, 'utf8')).version;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
async function main() {
|
|
841
|
+
+ // Store the original working directory to restore after cd commands
|
|
842
|
+
+ // IMPORTANT: command-stream's cd is a virtual command that calls process.chdir()
|
|
843
|
+
+ // This means `cd js` actually changes the Node.js process's working directory
|
|
844
|
+
+ const originalCwd = process.cwd();
|
|
845
|
+
+
|
|
846
|
+
try {
|
|
847
|
+
// Configure git
|
|
848
|
+
await $`git config user.name "github-actions[bot]"`;
|
|
849
|
+
@@ -186,17 +212,26 @@ async function main() {
|
|
850
|
+
|
|
851
|
+
if (mode === 'instant') {
|
|
852
|
+
console.log('Running instant version bump...');
|
|
853
|
+
- // Run instant version bump script
|
|
854
|
+
+ // Run instant version bump script, passing js-root for consistent path handling
|
|
855
|
+
// Rely on command-stream's auto-quoting for proper argument handling
|
|
856
|
+
if (description) {
|
|
857
|
+
- await $`node scripts/instant-version-bump.mjs --bump-type ${bumpType} --description ${description}`;
|
|
858
|
+
+ await $`node scripts/instant-version-bump.mjs --bump-type ${bumpType} --description ${description} --js-root ${jsRoot}`;
|
|
859
|
+
} else {
|
|
860
|
+
- await $`node scripts/instant-version-bump.mjs --bump-type ${bumpType}`;
|
|
861
|
+
+ await $`node scripts/instant-version-bump.mjs --bump-type ${bumpType} --js-root ${jsRoot}`;
|
|
862
|
+
}
|
|
863
|
+
} else {
|
|
864
|
+
console.log('Running changeset version...');
|
|
865
|
+
// Run changeset version to bump versions and update CHANGELOG
|
|
866
|
+
- await $`cd js && npm run changeset:version`;
|
|
867
|
+
+ // IMPORTANT: cd is a virtual command in command-stream that calls process.chdir()
|
|
868
|
+
+ // We need to restore the original directory after this command
|
|
869
|
+
+ if (needsCd({ jsRoot })) {
|
|
870
|
+
+ await $`cd ${jsRoot} && npm run changeset:version`;
|
|
871
|
+
+ // Restore the original working directory
|
|
872
|
+
+ process.chdir(originalCwd);
|
|
873
|
+
+ } else {
|
|
874
|
+
+ // Single-language repo - run in current directory
|
|
875
|
+
+ await $`npm run changeset:version`;
|
|
876
|
+
+ }
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// Get new version after bump
|