mb-run 1.0.2-dev-20260929-2a0c292 → 1.0.2
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/CHANGELOG.md +8 -2
- package/dist/upgrade.js +1 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/vendor/.oxfmtrc.root.json +4 -4
- package/vendor/.oxlintrc.root.json +4 -4
- package/vendor/scripts/clean.mjs +3 -9
- package/vendor/scripts/create-release.mjs +5 -1
- package/vendor/scripts/deep-clean.mjs +3 -9
- package/vendor/scripts/downloads.mjs +17 -9
- package/vendor/scripts/esbuild.mjs +7 -5
- package/vendor/scripts/git-status.mjs +18 -4
- package/vendor/scripts/git-sync-dev.mjs +2 -0
- package/vendor/scripts/prepublish-clean.mjs +12 -10
- package/vendor/scripts/prune-releases.mjs +17 -6
- package/vendor/scripts/prune-tags.mjs +13 -2
- package/vendor/scripts/remove-workflows.mjs +5 -1
- package/vendor/scripts/run-chip-tests.mjs +10 -6
- package/vendor/scripts/version.mjs +4 -3
- package/vendor/scripts/run-automator.mjs +0 -77
package/CHANGELOG.md
CHANGED
|
@@ -23,7 +23,7 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
23
23
|
|
|
24
24
|
<a href="https://www.buymeacoffee.com/luligugithub"><img src="https://matterbridge.io/assets/bmc-button.svg" alt="Buy me a coffee" width="120"></a>
|
|
25
25
|
|
|
26
|
-
## [1.0.2] -
|
|
26
|
+
## [1.0.2] - 2026-09-29
|
|
27
27
|
|
|
28
28
|
### Added
|
|
29
29
|
|
|
@@ -49,7 +49,13 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
49
49
|
|
|
50
50
|
- [antigravity]: Bump the vendored `.antigravity/settings.json` to v.1.0.5: count the removed sandboxing comments and allow the read-only git commands already approved in `.vscode/settings.json`.
|
|
51
51
|
- [vscode]: Bump the vendored `.vscode/settings.json` to v.1.0.14: ask before dependency installs and removals and approve `npm run test:watch` and `npm run test:verbose`, in sync with `.antigravity/settings.json`.
|
|
52
|
-
- [scripts]: Remove the obsolete `eslint-disable` comments from the vendored `scripts/*.mjs` and bump each touched script's patch version
|
|
52
|
+
- [scripts]: Remove the obsolete `eslint-disable` comments from the vendored `scripts/*.mjs` and bump each touched script's patch version.
|
|
53
|
+
- [scripts]: Make the vendored `scripts/*.mjs` pass oxlint: file-level `no-console` disables, behavior-preserving fixes, and local disables where a fix would change runtime behavior.
|
|
54
|
+
- [esbuild]: Make the vendored `scripts/esbuild.mjs` pass oxlint: file-level `no-console` disable, JSDoc descriptions and an optional chain.
|
|
55
|
+
- [oxlint]: Bump the vendored `.oxlintrc.root.json` to v.1.0.19: lint `scripts/` and `bin/`, and ignore `docs/**`, `**/tmp/**` and `**/bun.lock`.
|
|
56
|
+
- [oxfmt]: Bump the vendored `.oxfmtrc.root.json` to v.1.0.7: ignore `docs/**`, `**/tmp/**` and `**/bun.lock`, and drop the `scripts/*.html` and `eslint.config.js` ignores.
|
|
57
|
+
- [scripts]: Remove the unused vendored `scripts/run-automator.mjs`, which every upgrade deleted right after copying it.
|
|
58
|
+
- [upgrade]: Delete the obsolete `scripts/install-experimental.mjs` from upgraded repositories.
|
|
53
59
|
- [version]: Breaking change: rename `--version [tag]` to `--set-version [tag]`, so `--version` no longer rewrites `package.json`. The old `mb-run --version <tag>` form exits with an error pointing to `--set-version`.
|
|
54
60
|
- [package]: Upgrade package.
|
|
55
61
|
- [package]: Bump `oxfmt` to v.0.71.0.
|
package/dist/upgrade.js
CHANGED
|
@@ -197,6 +197,7 @@ export async function runPackageJsonUpgrade(opts, pkgPath, pkgJson, isMonorepo =
|
|
|
197
197
|
unlinkSafe(path.join(dstDir, 'scripts', 'run-chip-tests.mjs'));
|
|
198
198
|
unlinkSafe(path.join(dstDir, 'scripts', 'run-automator.mjs'));
|
|
199
199
|
unlinkSafe(path.join(dstDir, 'scripts', 'runAutomator.mjs'));
|
|
200
|
+
unlinkSafe(path.join(dstDir, 'scripts', 'install-experimental.mjs'));
|
|
200
201
|
unlinkSafe(path.join(dstDir, 'scripts', 'prune-tags.sh'));
|
|
201
202
|
unlinkSafe(path.join(dstDir, 'scripts', 'git-status.sh'));
|
|
202
203
|
unlinkSafe(path.join(dstDir, 'scripts', 'mb-run.mjs'));
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mb-run",
|
|
3
|
-
"version": "1.0.2
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "mb-run",
|
|
9
|
-
"version": "1.0.2
|
|
9
|
+
"version": "1.0.2",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"cross-spawn": "7.0.6",
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// .oxfmtrc.json 1.0.
|
|
1
|
+
// .oxfmtrc.json 1.0.7
|
|
2
2
|
|
|
3
3
|
// This Oxfmt configuration (shared between all matterbridge packages) is designed for a TypeScript project using ESM modules.
|
|
4
4
|
{
|
|
@@ -10,16 +10,16 @@
|
|
|
10
10
|
"**/build/**",
|
|
11
11
|
"chip/**",
|
|
12
12
|
"**/coverage/**",
|
|
13
|
-
"docs",
|
|
13
|
+
"docs/**",
|
|
14
14
|
"**/dist/**",
|
|
15
15
|
"**/temp/**",
|
|
16
|
+
"**/tmp/**",
|
|
16
17
|
"**/node_modules/**",
|
|
17
18
|
"**/out/**",
|
|
18
19
|
"**/screenshots/**",
|
|
19
20
|
"vendor/**",
|
|
20
21
|
"**/package-lock.json",
|
|
21
|
-
"
|
|
22
|
-
"eslint.config.js"
|
|
22
|
+
"**/bun.lock"
|
|
23
23
|
],
|
|
24
24
|
"printWidth": 180,
|
|
25
25
|
"tabWidth": 2,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// .oxlintrc.json 1.0.
|
|
1
|
+
// .oxlintrc.json 1.0.19
|
|
2
2
|
|
|
3
3
|
// This Oxlint configuration (shared between all matterbridge packages) is designed for a TypeScript project using ESM modules.
|
|
4
4
|
{
|
|
@@ -10,16 +10,16 @@
|
|
|
10
10
|
"**/build/**",
|
|
11
11
|
"chip/**",
|
|
12
12
|
"**/coverage/**",
|
|
13
|
+
"docs/**",
|
|
13
14
|
"**/dist/**",
|
|
14
15
|
"**/temp/**",
|
|
16
|
+
"**/tmp/**",
|
|
15
17
|
"**/node_modules/**",
|
|
16
18
|
"**/out/**",
|
|
17
|
-
"**/scripts/**",
|
|
18
19
|
"**/screenshots/**",
|
|
19
20
|
"vendor/**",
|
|
20
21
|
"**/package-lock.json",
|
|
21
|
-
"**/
|
|
22
|
-
"**/src/mock/**"
|
|
22
|
+
"**/bun.lock"
|
|
23
23
|
],
|
|
24
24
|
"env": {
|
|
25
25
|
"builtin": true,
|
package/vendor/scripts/clean.mjs
CHANGED
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
* Unknown arguments are rejected with exit code 1, so a mistyped flag never starts a clean.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
+
/* oxlint-disable no-console */
|
|
25
|
+
|
|
24
26
|
import { lstatSync, existsSync, readdirSync, readFileSync, rmSync } from 'node:fs';
|
|
25
27
|
import path from 'node:path';
|
|
26
28
|
|
|
@@ -37,20 +39,17 @@ const handleArgs = () => {
|
|
|
37
39
|
const knownArgs = new Set(['--workspaces', '--version', '-v', '--help', '-h']);
|
|
38
40
|
const unknownArgs = args.filter((arg) => !knownArgs.has(arg));
|
|
39
41
|
if (unknownArgs.length > 0) {
|
|
40
|
-
// oxlint-disable-next-line no-console
|
|
41
42
|
console.error(`Unknown argument${unknownArgs.length === 1 ? '' : 's'}: ${unknownArgs.join(', ')}. Run with --help for usage.`);
|
|
42
43
|
process.exitCode = 1;
|
|
43
44
|
return false;
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
if (args.includes('--version') || args.includes('-v')) {
|
|
47
|
-
// oxlint-disable-next-line no-console
|
|
48
48
|
console.log(version);
|
|
49
49
|
return false;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
if (args.includes('--help') || args.includes('-h')) {
|
|
53
|
-
// oxlint-disable-next-line no-console
|
|
54
53
|
console.log(`${scriptName} v.${version}
|
|
55
54
|
|
|
56
55
|
Remove every *.tsbuildinfo file and the dist and build directories.
|
|
@@ -71,7 +70,6 @@ Options:
|
|
|
71
70
|
const shouldClean = handleArgs();
|
|
72
71
|
|
|
73
72
|
if (shouldClean) {
|
|
74
|
-
// oxlint-disable-next-line no-console
|
|
75
73
|
console.log(`${scriptName} v.${version}`);
|
|
76
74
|
}
|
|
77
75
|
|
|
@@ -80,7 +78,7 @@ const root = process.cwd();
|
|
|
80
78
|
|
|
81
79
|
// Colors follow the NO_COLOR convention and are left out when the output is redirected,
|
|
82
80
|
// so a piped or captured log stays free of escape sequences.
|
|
83
|
-
const useColor = process.env.NO_COLOR === undefined && (process.stdout.isTTY
|
|
81
|
+
const useColor = process.env.NO_COLOR === undefined && (process.stdout.isTTY || process.env.FORCE_COLOR !== undefined);
|
|
84
82
|
const red = (text) => (useColor ? `\u001B[31m${text}\u001B[0m` : text);
|
|
85
83
|
|
|
86
84
|
let removed = 0;
|
|
@@ -91,11 +89,9 @@ const logRemoved = (dir, entry) => {
|
|
|
91
89
|
if (loggedDir !== dir) {
|
|
92
90
|
loggedDir = dir;
|
|
93
91
|
const name = path.relative(root, dir);
|
|
94
|
-
// oxlint-disable-next-line no-console
|
|
95
92
|
console.log(name === '' ? path.basename(dir) : name);
|
|
96
93
|
}
|
|
97
94
|
removed += 1;
|
|
98
|
-
// oxlint-disable-next-line no-console
|
|
99
95
|
console.log(` ${red('-')} ${entry}`);
|
|
100
96
|
};
|
|
101
97
|
|
|
@@ -114,7 +110,6 @@ const rm = (dir, target) => {
|
|
|
114
110
|
rmSync(path.resolve(dir, target), { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
115
111
|
} catch (error) {
|
|
116
112
|
if (error.code === 'EPERM' || error.code === 'EBUSY' || error.code === 'ENOTEMPTY') {
|
|
117
|
-
// oxlint-disable-next-line no-console
|
|
118
113
|
console.warn(`Skipped locked path (${error.code}): ${error.path ?? target} — likely held by a running process.`);
|
|
119
114
|
return;
|
|
120
115
|
}
|
|
@@ -177,6 +172,5 @@ if (shouldClean) {
|
|
|
177
172
|
}
|
|
178
173
|
|
|
179
174
|
const elapsed = `${Math.round(performance.now() - start)}ms`;
|
|
180
|
-
// oxlint-disable-next-line no-console
|
|
181
175
|
console.log(removed === 0 ? `Nothing to clean in ${elapsed}.` : `Cleaned ${removed} path${removed === 1 ? '' : 's'} in ${elapsed}.`);
|
|
182
176
|
}
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
* - Print tag/title/description and pause for user confirmation before creating
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
/* oxlint-disable no-console */
|
|
20
|
+
|
|
19
21
|
import { spawn } from 'node:child_process';
|
|
20
22
|
import fs from 'node:fs/promises';
|
|
21
23
|
import os from 'node:os';
|
|
@@ -90,6 +92,7 @@ async function promptToContinue({ tag, title, description }) {
|
|
|
90
92
|
console.log(`Tag: ${tag}`);
|
|
91
93
|
console.log(`Title: ${title}`);
|
|
92
94
|
console.log('Description:');
|
|
95
|
+
// oxlint-disable-next-line typescript/prefer-nullish-coalescing
|
|
93
96
|
console.log(description || '(empty)');
|
|
94
97
|
console.log('---');
|
|
95
98
|
|
|
@@ -106,7 +109,7 @@ async function promptToContinue({ tag, title, description }) {
|
|
|
106
109
|
}
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
function runGhReleaseCreate({ tag, title, notesFilePath }) {
|
|
112
|
+
async function runGhReleaseCreate({ tag, title, notesFilePath }) {
|
|
110
113
|
return new Promise((resolve, reject) => {
|
|
111
114
|
const args = ['release', 'create', tag, '--title', title, '--notes-file', notesFilePath, '--target', 'main'];
|
|
112
115
|
const child = spawn('gh', args, {
|
|
@@ -157,6 +160,7 @@ async function main() {
|
|
|
157
160
|
}
|
|
158
161
|
}
|
|
159
162
|
|
|
163
|
+
// oxlint-disable-next-line typescript/use-unknown-in-catch-callback-variable
|
|
160
164
|
main().catch((err) => {
|
|
161
165
|
console.error(`create-release: ${err?.message ?? err}`);
|
|
162
166
|
console.error('Make sure you are authenticated with GitHub CLI: gh auth status');
|
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
* Unknown arguments are rejected with exit code 1, so a mistyped flag never starts a clean.
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
+
/* oxlint-disable no-console */
|
|
32
|
+
|
|
31
33
|
import { existsSync, lstatSync, readdirSync, readFileSync, rmSync } from 'node:fs';
|
|
32
34
|
import path from 'node:path';
|
|
33
35
|
|
|
@@ -44,20 +46,17 @@ const handleArgs = () => {
|
|
|
44
46
|
const knownArgs = new Set(['--workspaces', '--version', '-v', '--help', '-h']);
|
|
45
47
|
const unknownArgs = args.filter((arg) => !knownArgs.has(arg));
|
|
46
48
|
if (unknownArgs.length > 0) {
|
|
47
|
-
// oxlint-disable-next-line no-console
|
|
48
49
|
console.error(`Unknown argument${unknownArgs.length === 1 ? '' : 's'}: ${unknownArgs.join(', ')}. Run with --help for usage.`);
|
|
49
50
|
process.exitCode = 1;
|
|
50
51
|
return false;
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
if (args.includes('--version') || args.includes('-v')) {
|
|
54
|
-
// oxlint-disable-next-line no-console
|
|
55
55
|
console.log(version);
|
|
56
56
|
return false;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
if (args.includes('--help') || args.includes('-h')) {
|
|
60
|
-
// oxlint-disable-next-line no-console
|
|
61
60
|
console.log(`${scriptName} v.${version}
|
|
62
61
|
|
|
63
62
|
Remove every *.tsbuildinfo file, the build/test output directories and the lock files,\nand empty .cache and node_modules.
|
|
@@ -78,7 +77,6 @@ Options:
|
|
|
78
77
|
const shouldClean = handleArgs();
|
|
79
78
|
|
|
80
79
|
if (shouldClean) {
|
|
81
|
-
// oxlint-disable-next-line no-console
|
|
82
80
|
console.log(`${scriptName} v.${version}`);
|
|
83
81
|
}
|
|
84
82
|
|
|
@@ -87,7 +85,7 @@ const root = process.cwd();
|
|
|
87
85
|
|
|
88
86
|
// Colors follow the NO_COLOR convention and are left out when the output is redirected,
|
|
89
87
|
// so a piped or captured log stays free of escape sequences.
|
|
90
|
-
const useColor = process.env.NO_COLOR === undefined && (process.stdout.isTTY
|
|
88
|
+
const useColor = process.env.NO_COLOR === undefined && (process.stdout.isTTY || process.env.FORCE_COLOR !== undefined);
|
|
91
89
|
const red = (text) => (useColor ? `\u001B[31m${text}\u001B[0m` : text);
|
|
92
90
|
|
|
93
91
|
let removed = 0;
|
|
@@ -98,11 +96,9 @@ const logRemoved = (dir, entry, count = 1) => {
|
|
|
98
96
|
if (loggedDir !== dir) {
|
|
99
97
|
loggedDir = dir;
|
|
100
98
|
const name = path.relative(root, dir);
|
|
101
|
-
// oxlint-disable-next-line no-console
|
|
102
99
|
console.log(name === '' ? path.basename(dir) : name);
|
|
103
100
|
}
|
|
104
101
|
removed += count;
|
|
105
|
-
// oxlint-disable-next-line no-console
|
|
106
102
|
console.log(` ${red('-')} ${entry}`);
|
|
107
103
|
};
|
|
108
104
|
|
|
@@ -123,7 +119,6 @@ const rm = (dir, target) => {
|
|
|
123
119
|
rmSync(path.resolve(dir, target), { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
124
120
|
} catch (error) {
|
|
125
121
|
if (error.code === 'EPERM' || error.code === 'EBUSY' || error.code === 'ENOTEMPTY') {
|
|
126
|
-
// oxlint-disable-next-line no-console
|
|
127
122
|
console.warn(`Skipped locked path (${error.code}): ${error.path ?? target} — likely held by a running process.`);
|
|
128
123
|
return null;
|
|
129
124
|
}
|
|
@@ -214,6 +209,5 @@ if (shouldClean) {
|
|
|
214
209
|
}
|
|
215
210
|
|
|
216
211
|
const elapsed = `${Math.round(performance.now() - start)}ms`;
|
|
217
|
-
// oxlint-disable-next-line no-console
|
|
218
212
|
console.log(removed === 0 ? `Nothing to clean in ${elapsed}.` : `Cleaned ${removed} path${removed === 1 ? '' : 's'} in ${elapsed}.`);
|
|
219
213
|
}
|
|
@@ -11,6 +11,12 @@
|
|
|
11
11
|
* Node.js 18+ (for global fetch)
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
/* oxlint-disable no-console */
|
|
15
|
+
/* oxlint-disable typescript/no-unnecessary-type-conversion */
|
|
16
|
+
/* oxlint-disable typescript/use-unknown-in-catch-callback-variable */
|
|
17
|
+
/* oxlint-disable typescript/prefer-nullish-coalescing */
|
|
18
|
+
/* oxlint-disable typescript/no-unsafe-type-assertion */
|
|
19
|
+
|
|
14
20
|
import { readFile } from 'node:fs/promises';
|
|
15
21
|
import { fileURLToPath } from 'node:url';
|
|
16
22
|
|
|
@@ -94,7 +100,7 @@ async function fetchCurrentDayDownloads(pkgName) {
|
|
|
94
100
|
*/
|
|
95
101
|
function sumDownloads(rows) {
|
|
96
102
|
let total = 0;
|
|
97
|
-
for (const r of rows) total +=
|
|
103
|
+
for (const r of rows) total += r.downloads || 0;
|
|
98
104
|
return total;
|
|
99
105
|
}
|
|
100
106
|
|
|
@@ -106,8 +112,7 @@ function sumDownloads(rows) {
|
|
|
106
112
|
* @returns {string} Left-padded string.
|
|
107
113
|
*/
|
|
108
114
|
function padLeft(s, width) {
|
|
109
|
-
|
|
110
|
-
return str.length >= width ? str : ' '.repeat(width - str.length) + str;
|
|
115
|
+
return s.length >= width ? s : ' '.repeat(width - s.length) + s;
|
|
111
116
|
}
|
|
112
117
|
|
|
113
118
|
/**
|
|
@@ -118,8 +123,7 @@ function padLeft(s, width) {
|
|
|
118
123
|
* @returns {string} Right-padded string.
|
|
119
124
|
*/
|
|
120
125
|
function padRight(s, width) {
|
|
121
|
-
|
|
122
|
-
return str.length >= width ? str : str + ' '.repeat(width - str.length);
|
|
126
|
+
return s.length >= width ? s : s + ' '.repeat(width - s.length);
|
|
123
127
|
}
|
|
124
128
|
|
|
125
129
|
/**
|
|
@@ -129,7 +133,7 @@ function padRight(s, width) {
|
|
|
129
133
|
* @returns {string} Formatted number.
|
|
130
134
|
*/
|
|
131
135
|
function formatNumber(n) {
|
|
132
|
-
return new Intl.NumberFormat(undefined, { maximumFractionDigits: 0 }).format(
|
|
136
|
+
return new Intl.NumberFormat(undefined, { maximumFractionDigits: 0 }).format(n || 0);
|
|
133
137
|
}
|
|
134
138
|
|
|
135
139
|
/**
|
|
@@ -230,10 +234,14 @@ async function main() {
|
|
|
230
234
|
const total = sumDownloads(summaryRows);
|
|
231
235
|
const days = summaryRows.length || 1;
|
|
232
236
|
const avg = Math.round(total / days);
|
|
233
|
-
|
|
234
|
-
|
|
237
|
+
let minRow = summaryRows[0] ?? { day: '-', downloads: 0 };
|
|
238
|
+
let maxRow = minRow;
|
|
239
|
+
for (const r of summaryRows) {
|
|
240
|
+
if (r.downloads < minRow.downloads) minRow = r;
|
|
241
|
+
if (r.downloads > maxRow.downloads) maxRow = r;
|
|
242
|
+
}
|
|
235
243
|
|
|
236
|
-
const dayWidth = Math.max(3, ...rows.map((r) =>
|
|
244
|
+
const dayWidth = Math.max(3, ...rows.map((r) => r.day.length));
|
|
237
245
|
const downloadStrings = rows.map((r) => formatNumber(r.downloads));
|
|
238
246
|
const downloadsWidth = Math.max('DOWNLOADS'.length, ...downloadStrings.map((s) => s.length));
|
|
239
247
|
const rangeStart = rows[0]?.day ?? lastMonthData.start;
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
* Node.js 18+ (for global fetch)
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
/* oxlint-disable no-console */
|
|
15
|
+
|
|
14
16
|
import { readdir, rm, stat, writeFile } from 'node:fs/promises';
|
|
15
17
|
import { createRequire } from 'node:module';
|
|
16
18
|
import path from 'node:path';
|
|
@@ -47,14 +49,14 @@ if (dirs.length === 0) {
|
|
|
47
49
|
/**
|
|
48
50
|
* Recursively lists all files under a directory.
|
|
49
51
|
*
|
|
50
|
-
* @param {string} rootDir
|
|
51
|
-
* @returns {Promise<string[]>}
|
|
52
|
+
* @param {string} rootDir - Directory to walk.
|
|
53
|
+
* @returns {Promise<string[]>} Absolute paths of all files below rootDir.
|
|
52
54
|
*/
|
|
53
55
|
const listFilesRecursive = async (rootDir) => {
|
|
54
56
|
/** @type {string[]} */
|
|
55
57
|
const files = [];
|
|
56
58
|
|
|
57
|
-
/** @param {string} currentDir */
|
|
59
|
+
/** @param {string} currentDir - Directory being walked. */
|
|
58
60
|
const walk = async (currentDir) => {
|
|
59
61
|
const entries = await readdir(currentDir, { withFileTypes: true });
|
|
60
62
|
for (const entry of entries) {
|
|
@@ -71,11 +73,11 @@ const listFilesRecursive = async (rootDir) => {
|
|
|
71
73
|
return files;
|
|
72
74
|
};
|
|
73
75
|
|
|
74
|
-
/** @param {string} distDir */
|
|
76
|
+
/** @param {string} distDir - Dist directory to bundle in place. */
|
|
75
77
|
const bundleDir = async (distDir) => {
|
|
76
78
|
console.log(`[esbuild] dir: ${distDir}`);
|
|
77
79
|
const dirStat = await stat(distDir).catch(() => null);
|
|
78
|
-
if (!dirStat
|
|
80
|
+
if (!dirStat?.isDirectory()) {
|
|
79
81
|
throw new Error(`Not a directory: ${distDir}`);
|
|
80
82
|
}
|
|
81
83
|
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
* node scripts/git-status.mjs
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
/* oxlint-disable no-console */
|
|
12
|
+
/* oxlint-disable typescript/prefer-nullish-coalescing */
|
|
13
|
+
|
|
11
14
|
import { spawnSync } from 'node:child_process';
|
|
12
15
|
|
|
13
16
|
class ExitError extends Error {
|
|
@@ -67,6 +70,13 @@ function section(title) {
|
|
|
67
70
|
hr();
|
|
68
71
|
}
|
|
69
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Throw an ExitError.
|
|
75
|
+
*
|
|
76
|
+
* @param {string} message - Error message.
|
|
77
|
+
* @param {number} [code] - Exit code.
|
|
78
|
+
* @returns {never} Never returns.
|
|
79
|
+
*/
|
|
70
80
|
function fail(message, code = 1) {
|
|
71
81
|
throw new ExitError(message, code);
|
|
72
82
|
}
|
|
@@ -74,6 +84,7 @@ function fail(message, code = 1) {
|
|
|
74
84
|
function parseArgs(argv) {
|
|
75
85
|
if (argv.includes('--help') || argv.includes('-h')) {
|
|
76
86
|
console.log(usage());
|
|
87
|
+
// oxlint-disable-next-line unicorn/no-useless-undefined
|
|
77
88
|
return undefined;
|
|
78
89
|
}
|
|
79
90
|
|
|
@@ -88,6 +99,7 @@ function parseArgs(argv) {
|
|
|
88
99
|
};
|
|
89
100
|
}
|
|
90
101
|
|
|
102
|
+
// oxlint-disable-next-line typescript/consistent-return -- ends with fail(), which always throws
|
|
91
103
|
function git(args, options = {}) {
|
|
92
104
|
const { allowFailure = false, input } = options;
|
|
93
105
|
const result = spawnSync('git', args, {
|
|
@@ -106,6 +118,7 @@ function git(args, options = {}) {
|
|
|
106
118
|
}
|
|
107
119
|
|
|
108
120
|
if (allowFailure) {
|
|
121
|
+
// oxlint-disable-next-line unicorn/no-useless-undefined
|
|
109
122
|
return undefined;
|
|
110
123
|
}
|
|
111
124
|
|
|
@@ -132,6 +145,7 @@ function printKeyValue(key, value, colorizer) {
|
|
|
132
145
|
function parseRemoteTagCount(remote) {
|
|
133
146
|
const raw = git(['ls-remote', '--tags', remote], { allowFailure: true });
|
|
134
147
|
if (raw === undefined) {
|
|
148
|
+
// oxlint-disable-next-line unicorn/no-useless-undefined
|
|
135
149
|
return undefined;
|
|
136
150
|
}
|
|
137
151
|
|
|
@@ -263,7 +277,7 @@ function main() {
|
|
|
263
277
|
|
|
264
278
|
section('Repository status');
|
|
265
279
|
const repoRoot = git(['rev-parse', '--show-toplevel']);
|
|
266
|
-
const repoName = repoRoot.split(/[\\/]/).
|
|
280
|
+
const repoName = repoRoot.split(/[\\/]/).findLast(Boolean) ?? repoRoot;
|
|
267
281
|
const branch = git(['branch', '--show-current'], { allowFailure: true }) || '(detached)';
|
|
268
282
|
const head = git(['rev-parse', '--short', 'HEAD']);
|
|
269
283
|
const dirty = git(['status', '--porcelain']) ? 'yes' : 'no';
|
|
@@ -281,11 +295,11 @@ function main() {
|
|
|
281
295
|
section('Tag reachability');
|
|
282
296
|
const tagOnlyCount = git(['rev-list', '--tags', '--not', '--branches', '--count'], { allowFailure: true }) || '0';
|
|
283
297
|
printKeyValue('Tag-only commits (should be 0):', tagOnlyCount, Number(tagOnlyCount) === 0 ? colors.green : colors.yellow);
|
|
284
|
-
if (git(['remote', 'get-url', remote], { allowFailure: true })
|
|
298
|
+
if (git(['remote', 'get-url', remote], { allowFailure: true }) === undefined) {
|
|
299
|
+
printKeyValue('Remote tag count:', '(remote not found)', colors.yellow);
|
|
300
|
+
} else {
|
|
285
301
|
const remoteTagCount = parseRemoteTagCount(remote);
|
|
286
302
|
printKeyValue(`Remote tag count (${remote}):`, remoteTagCount ?? '(remote query failed)');
|
|
287
|
-
} else {
|
|
288
|
-
printKeyValue('Remote tag count:', '(remote not found)', colors.yellow);
|
|
289
303
|
}
|
|
290
304
|
console.log();
|
|
291
305
|
|
|
@@ -18,8 +18,10 @@
|
|
|
18
18
|
* node scripts/prepublish-clean.mjs --workspaces
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
/* oxlint-disable no-console */
|
|
22
|
+
|
|
21
23
|
import { existsSync, readdirSync, readFileSync, rmSync } from 'node:fs';
|
|
22
|
-
import
|
|
24
|
+
import path from 'node:path';
|
|
23
25
|
|
|
24
26
|
const root = process.cwd();
|
|
25
27
|
|
|
@@ -29,7 +31,7 @@ const root = process.cwd();
|
|
|
29
31
|
// so warn and continue instead of aborting the whole clean.
|
|
30
32
|
const rm = (dir, target) => {
|
|
31
33
|
try {
|
|
32
|
-
rmSync(resolve(dir, target), { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
34
|
+
rmSync(path.resolve(dir, target), { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
33
35
|
} catch (error) {
|
|
34
36
|
if (error.code === 'EPERM' || error.code === 'EBUSY' || error.code === 'ENOTEMPTY') {
|
|
35
37
|
console.warn(`Skipped locked path (${error.code}): ${error.path ?? target} — likely held by a running process.`);
|
|
@@ -42,8 +44,8 @@ const rm = (dir, target) => {
|
|
|
42
44
|
const clean = (dir) => {
|
|
43
45
|
// Empty the contents (including dotfiles) of node_modules but keep the directory itself.
|
|
44
46
|
try {
|
|
45
|
-
for (const entry of readdirSync(resolve(dir, 'node_modules'))) {
|
|
46
|
-
rm(resolve(dir, 'node_modules'), entry);
|
|
47
|
+
for (const entry of readdirSync(path.resolve(dir, 'node_modules'))) {
|
|
48
|
+
rm(path.resolve(dir, 'node_modules'), entry);
|
|
47
49
|
}
|
|
48
50
|
} catch {
|
|
49
51
|
// node_modules does not exist, nothing to empty.
|
|
@@ -55,18 +57,18 @@ const clean = (dir) => {
|
|
|
55
57
|
};
|
|
56
58
|
|
|
57
59
|
const getWorkspaceDirs = () => {
|
|
58
|
-
const { workspaces = [] } = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8'));
|
|
60
|
+
const { workspaces = [] } = JSON.parse(readFileSync(path.resolve(root, 'package.json'), 'utf8'));
|
|
59
61
|
const patterns = Array.isArray(workspaces) ? workspaces : (workspaces.packages ?? []);
|
|
60
62
|
const dirs = [];
|
|
61
63
|
|
|
62
64
|
for (const pattern of patterns) {
|
|
63
65
|
if (!pattern.endsWith('/*')) {
|
|
64
|
-
const dir = resolve(root, pattern);
|
|
65
|
-
if (existsSync(resolve(dir, 'package.json'))) dirs.push(dir);
|
|
66
|
+
const dir = path.resolve(root, pattern);
|
|
67
|
+
if (existsSync(path.resolve(dir, 'package.json'))) dirs.push(dir);
|
|
66
68
|
continue;
|
|
67
69
|
}
|
|
68
70
|
|
|
69
|
-
const parentDir = resolve(root, pattern.slice(0, -2));
|
|
71
|
+
const parentDir = path.resolve(root, pattern.slice(0, -2));
|
|
70
72
|
let entries;
|
|
71
73
|
try {
|
|
72
74
|
entries = readdirSync(parentDir, { withFileTypes: true });
|
|
@@ -76,8 +78,8 @@ const getWorkspaceDirs = () => {
|
|
|
76
78
|
|
|
77
79
|
for (const entry of entries) {
|
|
78
80
|
if (!entry.isDirectory()) continue;
|
|
79
|
-
const dir = resolve(parentDir, entry.name);
|
|
80
|
-
if (existsSync(resolve(dir, 'package.json'))) dirs.push(dir);
|
|
81
|
+
const dir = path.resolve(parentDir, entry.name);
|
|
82
|
+
if (existsSync(path.resolve(dir, 'package.json'))) dirs.push(dir);
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
85
|
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
* node scripts/prune-releases.mjs [--help|-h] [--dry-run|-n] <tag-prefix-to-keep>
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
/* oxlint-disable no-console */
|
|
12
|
+
/* oxlint-disable typescript/prefer-nullish-coalescing */
|
|
13
|
+
|
|
11
14
|
import { spawnSync } from 'node:child_process';
|
|
12
15
|
import { readFileSync } from 'node:fs';
|
|
13
16
|
import { createInterface } from 'node:readline';
|
|
@@ -70,6 +73,13 @@ function section(title) {
|
|
|
70
73
|
hr();
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Throw an ExitError.
|
|
78
|
+
*
|
|
79
|
+
* @param {string} message - Error message.
|
|
80
|
+
* @param {number} [code] - Exit code.
|
|
81
|
+
* @returns {never} Never returns.
|
|
82
|
+
*/
|
|
73
83
|
function fail(message, code = 1) {
|
|
74
84
|
throw new ExitError(message, code);
|
|
75
85
|
}
|
|
@@ -77,6 +87,7 @@ function fail(message, code = 1) {
|
|
|
77
87
|
function parseArgs(argv) {
|
|
78
88
|
if (argv.includes('--help') || argv.includes('-h')) {
|
|
79
89
|
console.log(usage());
|
|
90
|
+
// oxlint-disable-next-line unicorn/no-useless-undefined
|
|
80
91
|
return undefined;
|
|
81
92
|
}
|
|
82
93
|
|
|
@@ -88,8 +99,7 @@ function parseArgs(argv) {
|
|
|
88
99
|
fail(`Unknown option(s): ${unknownFlags.join(', ')}\n\n${usage()}`);
|
|
89
100
|
}
|
|
90
101
|
|
|
91
|
-
const
|
|
92
|
-
const [keepPrefix] = positional;
|
|
102
|
+
const keepPrefix = argv.find((value) => !value.startsWith('-'));
|
|
93
103
|
if (!keepPrefix) {
|
|
94
104
|
fail(usage());
|
|
95
105
|
}
|
|
@@ -97,6 +107,7 @@ function parseArgs(argv) {
|
|
|
97
107
|
return { dryRun, keepPrefix };
|
|
98
108
|
}
|
|
99
109
|
|
|
110
|
+
// oxlint-disable-next-line typescript/consistent-return -- ends with fail(), which always throws
|
|
100
111
|
function runCapture(command, args, options = {}) {
|
|
101
112
|
const { allowFailure = false } = options;
|
|
102
113
|
const result = spawnSync(command, args, {
|
|
@@ -178,7 +189,7 @@ function normalizeRepositoryUrl(remoteUrl) {
|
|
|
178
189
|
/**
|
|
179
190
|
* Read the repository from git remote.origin.url.
|
|
180
191
|
*
|
|
181
|
-
* @returns {
|
|
192
|
+
* @returns {string | null} Repository in owner/repo form, or null.
|
|
182
193
|
*/
|
|
183
194
|
function getRepositoryFromGit() {
|
|
184
195
|
const result = runCapture('git', ['remote', 'get-url', 'origin'], { allowFailure: true });
|
|
@@ -191,7 +202,7 @@ function getRepositoryFromGit() {
|
|
|
191
202
|
/**
|
|
192
203
|
* Read the repository from package.json.
|
|
193
204
|
*
|
|
194
|
-
* @returns {
|
|
205
|
+
* @returns {string | null} Repository in owner/repo form, or null.
|
|
195
206
|
*/
|
|
196
207
|
function getRepositoryFromPackageJson() {
|
|
197
208
|
try {
|
|
@@ -208,7 +219,7 @@ function getRepositoryFromPackageJson() {
|
|
|
208
219
|
/**
|
|
209
220
|
* Determine the current GitHub repository.
|
|
210
221
|
*
|
|
211
|
-
* @returns {
|
|
222
|
+
* @returns {string} Repository in owner/repo form.
|
|
212
223
|
*/
|
|
213
224
|
function getRepositoryNameWithOwner() {
|
|
214
225
|
const fromGit = getRepositoryFromGit();
|
|
@@ -228,7 +239,7 @@ function getRepositoryNameWithOwner() {
|
|
|
228
239
|
* Call the GitHub API and parse a JSON response.
|
|
229
240
|
*
|
|
230
241
|
* @param {string} pathname - GitHub API path.
|
|
231
|
-
* @returns {
|
|
242
|
+
* @returns {unknown} Parsed JSON payload.
|
|
232
243
|
*/
|
|
233
244
|
function ghApiJson(pathname) {
|
|
234
245
|
const { stdout } = runCapture('gh', ['api', '--method', 'GET', pathname]);
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
* node scripts/prune-tags.mjs [--dry-run|-n] <tag-prefix-to-keep> [remote]
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
/* oxlint-disable no-console */
|
|
12
|
+
|
|
11
13
|
import { spawnSync } from 'node:child_process';
|
|
12
14
|
import { createInterface } from 'node:readline';
|
|
13
15
|
|
|
@@ -68,6 +70,13 @@ function section(title) {
|
|
|
68
70
|
hr();
|
|
69
71
|
}
|
|
70
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Throw an ExitError.
|
|
75
|
+
*
|
|
76
|
+
* @param {string} message - Error message.
|
|
77
|
+
* @param {number} [code] - Exit code.
|
|
78
|
+
* @returns {never} Never returns.
|
|
79
|
+
*/
|
|
71
80
|
function fail(message, code = 1) {
|
|
72
81
|
throw new ExitError(message, code);
|
|
73
82
|
}
|
|
@@ -75,6 +84,7 @@ function fail(message, code = 1) {
|
|
|
75
84
|
function parseArgs(argv) {
|
|
76
85
|
if (argv.includes('--help') || argv.includes('-h')) {
|
|
77
86
|
console.log(usage());
|
|
87
|
+
// oxlint-disable-next-line unicorn/no-useless-undefined
|
|
78
88
|
return undefined;
|
|
79
89
|
}
|
|
80
90
|
|
|
@@ -95,6 +105,7 @@ function parseArgs(argv) {
|
|
|
95
105
|
return { dryRun, keepPrefix, remote };
|
|
96
106
|
}
|
|
97
107
|
|
|
108
|
+
// oxlint-disable-next-line typescript/consistent-return -- ends with fail(), which always throws
|
|
98
109
|
function runGit(args, options = {}) {
|
|
99
110
|
const { allowFailure = false, input, inherit = false } = options;
|
|
100
111
|
const result = spawnSync('git', args, {
|
|
@@ -158,7 +169,7 @@ function parseTagNames(raw) {
|
|
|
158
169
|
tags.add(ref.replace(/^refs\/tags\//, '').replace(/\^\{\}$/, ''));
|
|
159
170
|
}
|
|
160
171
|
|
|
161
|
-
return Array.from(tags).
|
|
172
|
+
return Array.from(tags).toSorted((left, right) => left.localeCompare(right));
|
|
162
173
|
}
|
|
163
174
|
|
|
164
175
|
function printTagTable(tags, colorizer = (value) => value) {
|
|
@@ -306,7 +317,7 @@ async function main() {
|
|
|
306
317
|
? localTagsRaw
|
|
307
318
|
.split('\n')
|
|
308
319
|
.filter(Boolean)
|
|
309
|
-
.
|
|
320
|
+
.toSorted((left, right) => left.localeCompare(right))
|
|
310
321
|
: [];
|
|
311
322
|
printTagTable(localTags, colors.green);
|
|
312
323
|
}
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
* git remote.origin.url configured, or package.json repository.url set
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
+
/* oxlint-disable no-console */
|
|
17
|
+
/* oxlint-disable typescript/prefer-nullish-coalescing */
|
|
18
|
+
|
|
16
19
|
import { spawn } from 'node:child_process';
|
|
17
20
|
import { readFile } from 'node:fs/promises';
|
|
18
21
|
|
|
@@ -92,7 +95,7 @@ function parseArgs(argv) {
|
|
|
92
95
|
* @param {string[]} args - Command arguments.
|
|
93
96
|
* @returns {Promise<{ stdout: string, stderr: string }>} Captured output.
|
|
94
97
|
*/
|
|
95
|
-
function execCapture(command, args) {
|
|
98
|
+
async function execCapture(command, args) {
|
|
96
99
|
return new Promise((resolve, reject) => {
|
|
97
100
|
const child = spawn(command, args, {
|
|
98
101
|
shell: false,
|
|
@@ -411,6 +414,7 @@ async function main() {
|
|
|
411
414
|
}
|
|
412
415
|
}
|
|
413
416
|
|
|
417
|
+
// oxlint-disable-next-line typescript/use-unknown-in-catch-callback-variable
|
|
414
418
|
main().catch((error) => {
|
|
415
419
|
console.error(`remove-workflows: ${error?.message || error}`);
|
|
416
420
|
console.error('Make sure GitHub CLI is installed and authenticated: gh auth status');
|
|
@@ -52,16 +52,18 @@
|
|
|
52
52
|
* requiring the CSA reference app's --app-pipe debug hook, which Matterbridge doesn't implement).
|
|
53
53
|
*/
|
|
54
54
|
|
|
55
|
+
/* oxlint-disable no-console */
|
|
56
|
+
|
|
55
57
|
import { spawnSync } from 'node:child_process';
|
|
56
58
|
import { appendFileSync, readFileSync, writeFileSync } from 'node:fs';
|
|
57
|
-
import
|
|
59
|
+
import path from 'node:path';
|
|
58
60
|
|
|
59
61
|
const root = process.cwd();
|
|
60
62
|
const containerName = 'chip-test';
|
|
61
63
|
const image = 'luligu/matterbridge:chip-test';
|
|
62
|
-
const testsFile = resolve(root, 'chipTests.json');
|
|
63
|
-
const logFile = resolve(root, 'chipTests.log');
|
|
64
|
-
const summaryLogFile = resolve(root, 'chipTestsSummary.log');
|
|
64
|
+
const testsFile = path.resolve(root, 'chipTests.json');
|
|
65
|
+
const logFile = path.resolve(root, 'chipTests.log');
|
|
66
|
+
const summaryLogFile = path.resolve(root, 'chipTestsSummary.log');
|
|
65
67
|
// Node storage for the bridged endpoints; only stateful cluster attributes that get written during a
|
|
66
68
|
// test create a file here, so these globs only ever remove test-mutated state, never device identity.
|
|
67
69
|
const matterstorageRoot = '/root/.matterbridge/matterstorage/Matterbridge';
|
|
@@ -175,7 +177,7 @@ function start() {
|
|
|
175
177
|
'-p',
|
|
176
178
|
'8585:8283',
|
|
177
179
|
'-v',
|
|
178
|
-
`${join(root, 'temp')}:/tmp/matter_testing/logs`,
|
|
180
|
+
`${path.join(root, 'temp')}:/tmp/matter_testing/logs`,
|
|
179
181
|
'-v',
|
|
180
182
|
`${root}:/root/Matterbridge/${pluginName}`,
|
|
181
183
|
// Shadows just the node_modules subpath of the bind mount above with a named volume backed by the
|
|
@@ -236,6 +238,7 @@ function waitForContainerReady(sinceIso, timeoutMs = 45000, pollMs = 1000) {
|
|
|
236
238
|
const result = run('docker', ['logs', '--since', sinceIso, containerName], { capture: true });
|
|
237
239
|
// Matterbridge colorizes its log output with ANSI escapes even without a TTY, splitting the marker
|
|
238
240
|
// text across escape sequences (e.g. "Matterbridge " <esc> "is online"); strip them before matching.
|
|
241
|
+
// oxlint-disable-next-line eslint/no-control-regex
|
|
239
242
|
const plainOutput = `${result.stdout ?? ''}${result.stderr ?? ''}`.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
|
|
240
243
|
if (plainOutput.includes(readyLogMarker)) {
|
|
241
244
|
return;
|
|
@@ -280,7 +283,7 @@ function loadChipTestsFile() {
|
|
|
280
283
|
const parsed = JSON.parse(raw);
|
|
281
284
|
|
|
282
285
|
pluginConfig = parsed.config;
|
|
283
|
-
if (!pluginConfig
|
|
286
|
+
if (!pluginConfig?.name) {
|
|
284
287
|
fail(`Expected a "config" object with a "name" property in ${testsFile}`);
|
|
285
288
|
}
|
|
286
289
|
pluginName = pluginConfig.name;
|
|
@@ -355,6 +358,7 @@ function filterTests(tests, nameFilter) {
|
|
|
355
358
|
}
|
|
356
359
|
|
|
357
360
|
const needle = nameFilter.toLowerCase();
|
|
361
|
+
// oxlint-disable-next-line typescript/prefer-nullish-coalescing
|
|
358
362
|
const filtered = tests.filter((test) => test.name.toLowerCase().includes(needle) || test.test.toLowerCase().includes(needle));
|
|
359
363
|
if (filtered.length === 0) {
|
|
360
364
|
fail(`No test found with "name" or "test" including ${JSON.stringify(nameFilter)}`);
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* node scripts/version.mjs <dev|edge|git|local|bun> [--dry-run]
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
/* oxlint-disable no-console */
|
|
13
|
+
|
|
12
14
|
import { execFileSync } from 'node:child_process';
|
|
13
15
|
import fs from 'node:fs/promises';
|
|
14
16
|
import path from 'node:path';
|
|
@@ -40,7 +42,7 @@ function shortSha7FromGit(repoRoot) {
|
|
|
40
42
|
encoding: 'utf8',
|
|
41
43
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
42
44
|
});
|
|
43
|
-
const sha =
|
|
45
|
+
const sha = out.trim();
|
|
44
46
|
if (!/^[0-9a-f]{7}$/i.test(sha)) {
|
|
45
47
|
throw new Error(`Unexpected git short SHA output: ${JSON.stringify(sha)}`);
|
|
46
48
|
}
|
|
@@ -74,8 +76,7 @@ if (unknownFlags.length > 0) {
|
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
const dryRun = args.includes('--dry-run') || args.includes('-n');
|
|
77
|
-
const
|
|
78
|
-
const tag = positional[0]?.toLowerCase();
|
|
79
|
+
const tag = args.find((a) => !a.startsWith('-'))?.toLowerCase();
|
|
79
80
|
if (tag !== 'dev' && tag !== 'edge' && tag !== 'git' && tag !== 'local' && tag !== 'bun') {
|
|
80
81
|
console.error(usage());
|
|
81
82
|
process.exitCode = 1;
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* run-automator.mjs
|
|
3
|
-
* Version: 1.0.2
|
|
4
|
-
*
|
|
5
|
-
* Launcher script for a developer "automator".
|
|
6
|
-
*
|
|
7
|
-
* The automator is a tool that automates package updates for internal projects.
|
|
8
|
-
*
|
|
9
|
-
* - Locates `automator.mjs` either via `AUTOMATOR_PATH` or common OneDrive roots.
|
|
10
|
-
* - Invokes it with the current Node executable, forwarding CLI args and stdio.
|
|
11
|
-
* - Exits with the same status code (or 1 on failure).
|
|
12
|
-
*
|
|
13
|
-
* Usage:
|
|
14
|
-
* node scripts/run-automator.mjs [args...]
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { spawnSync } from 'node:child_process';
|
|
18
|
-
import { access } from 'node:fs/promises';
|
|
19
|
-
import os from 'node:os';
|
|
20
|
-
import path from 'node:path';
|
|
21
|
-
|
|
22
|
-
const argv = process.argv.slice(2);
|
|
23
|
-
|
|
24
|
-
const candidateOneDriveRoots = [
|
|
25
|
-
process.env.ONE_DRIVE_ROOT,
|
|
26
|
-
process.env.OneDriveCommercial,
|
|
27
|
-
process.env.OneDriveConsumer,
|
|
28
|
-
process.env.OneDrive,
|
|
29
|
-
process.env.ONEDRIVE,
|
|
30
|
-
process.env.HOMEPATH && process.env.HOMEDRIVE ? path.join(process.env.HOMEDRIVE, process.env.HOMEPATH, 'OneDrive') : undefined,
|
|
31
|
-
process.env.USERPROFILE ? path.join(process.env.USERPROFILE, 'OneDrive') : undefined,
|
|
32
|
-
process.env.HOME ? path.join(process.env.HOME, 'OneDrive') : undefined,
|
|
33
|
-
].filter(Boolean);
|
|
34
|
-
|
|
35
|
-
const defaultAutomatorRelative = path.join('Code', 'automator', 'automator.mjs');
|
|
36
|
-
|
|
37
|
-
const candidateAutomatorPaths = [process.env.AUTOMATOR_PATH, ...candidateOneDriveRoots.map((root) => path.join(root, defaultAutomatorRelative))].filter(Boolean);
|
|
38
|
-
|
|
39
|
-
const exists = async (filePath) => {
|
|
40
|
-
try {
|
|
41
|
-
await access(filePath);
|
|
42
|
-
return true;
|
|
43
|
-
} catch {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
let automatorPath;
|
|
49
|
-
for (const candidate of candidateAutomatorPaths) {
|
|
50
|
-
if (await exists(candidate)) {
|
|
51
|
-
automatorPath = candidate;
|
|
52
|
-
break;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (!automatorPath) {
|
|
57
|
-
const lines = [
|
|
58
|
-
'[automator] Could not locate automator.mjs.',
|
|
59
|
-
'',
|
|
60
|
-
'Tried:',
|
|
61
|
-
...candidateAutomatorPaths.map((p) => ` - ${p}`),
|
|
62
|
-
'',
|
|
63
|
-
'Fix options:',
|
|
64
|
-
' - Set env var AUTOMATOR_PATH to the full path of automator.mjs',
|
|
65
|
-
' - Or set env var ONE_DRIVE_ROOT to your OneDrive root directory',
|
|
66
|
-
' - Or ensure OneDrive env vars (OneDrive/OneDriveCommercial/OneDriveConsumer) are set',
|
|
67
|
-
];
|
|
68
|
-
console.error(lines.join(os.EOL));
|
|
69
|
-
process.exit(1);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const result = spawnSync(process.execPath, [automatorPath, ...argv], {
|
|
73
|
-
stdio: 'inherit',
|
|
74
|
-
windowsHide: true,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
process.exit(result.status ?? 1);
|