@magnusekdahl/parallix 1.2.1 → 1.3.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/index.js +190 -185
- package/lib/commands/active.js +502 -579
- package/lib/commands/active.ts +665 -0
- package/lib/commands/checkpoint.js +98 -74
- package/lib/commands/checkpoint.ts +79 -0
- package/lib/commands/config.js +61 -31
- package/lib/commands/config.ts +47 -0
- package/lib/commands/coverage-gate.js +271 -246
- package/lib/commands/coverage-gate.ts +362 -0
- package/lib/commands/diff.js +140 -119
- package/lib/commands/diff.ts +125 -0
- package/lib/commands/draft.js +770 -923
- package/lib/commands/draft.ts +1021 -0
- package/lib/commands/handoff.js +588 -608
- package/lib/commands/handoff.ts +694 -0
- package/lib/commands/integrate.js +1331 -1468
- package/lib/commands/integrate.ts +1688 -0
- package/lib/commands/mission-start.js +279 -237
- package/lib/commands/mission-start.ts +263 -0
- package/lib/commands/rebase.js +606 -582
- package/lib/commands/rebase.ts +635 -0
- package/lib/commands/repair-handoff.js +181 -179
- package/lib/commands/repair-handoff.ts +228 -0
- package/lib/commands/resolve-conflict.js +121 -102
- package/lib/commands/resolve-conflict.ts +112 -0
- package/lib/commands/review.js +3 -4
- package/lib/commands/review.ts +14 -0
- package/lib/commands/setup-review.js +4 -5
- package/lib/commands/setup-review.ts +14 -0
- package/lib/commands/setup.js +3 -3
- package/lib/commands/setup.ts +2 -0
- package/lib/commands/stats-backfill.js +394 -359
- package/lib/commands/stats-backfill.ts +418 -0
- package/lib/commands/stats.js +1424 -1665
- package/lib/commands/stats.ts +2186 -0
- package/lib/commands/status.js +219 -200
- package/lib/commands/status.ts +219 -0
- package/lib/commands/verify.js +3 -1
- package/lib/commands/verify.ts +2 -0
- package/lib/core/nels.js +112 -127
- package/lib/core/nels.ts +189 -0
- package/lib/core/subagent-limit.js +15 -16
- package/lib/core/subagent-limit.ts +25 -0
- package/lib/index.js +142 -59
- package/lib/index.ts +134 -0
- package/lib/review/rebase.js +142 -145
- package/lib/review/rebase.ts +188 -0
- package/lib/review/review-adapter.js +99 -87
- package/lib/review/review-adapter.ts +198 -0
- package/lib/review/review-artifacts.js +486 -629
- package/lib/review/review-artifacts.ts +622 -0
- package/lib/review/review-commands.js +1220 -1373
- package/lib/review/review-commands.ts +1579 -0
- package/lib/review/review-events.js +544 -886
- package/lib/review/review-events.ts +954 -0
- package/lib/review/review-loop.js +945 -1020
- package/lib/review/review-loop.ts +1174 -0
- package/lib/review/review-polling.js +86 -115
- package/lib/review/review-polling.ts +194 -0
- package/lib/review/review-prompts.js +154 -189
- package/lib/review/review-prompts.ts +182 -0
- package/lib/review/review-state.js +246 -225
- package/lib/review/review-state.ts +353 -0
- package/lib/review/review.js +63 -84
- package/lib/review/review.ts +138 -0
- package/lib/tools/backlog.js +694 -680
- package/lib/tools/backlog.ts +835 -0
- package/lib/tools/forgejo.js +1270 -1405
- package/lib/tools/forgejo.ts +1793 -0
- package/lib/tools/gatekeeper.js +106 -96
- package/lib/tools/gatekeeper.ts +124 -0
- package/lib/tools/redgreen.js +200 -181
- package/lib/tools/redgreen.ts +221 -0
- package/lib/tools/sessions.js +58 -52
- package/lib/tools/sessions.ts +81 -0
- package/lib/tools/setup-review.js +902 -975
- package/lib/tools/setup-review.ts +1152 -0
- package/package.json +4 -4
- package/px.js +226 -208
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
"use strict";
|
|
3
3
|
/**
|
|
4
4
|
* coverage-gate.js - run parallix tests with Node's built-in coverage support
|
|
5
5
|
* and enforce a configurable line-coverage threshold (default 90%).
|
|
@@ -47,122 +47,156 @@
|
|
|
47
47
|
* Cleanup strategy: per-process inventory (PER_RUN_SCRATCH) + exit/SIGINT/SIGTERM
|
|
48
48
|
* handlers (lines 131-141) that remove only tracked dirs. No blanket rm -rf.
|
|
49
49
|
*/
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
51
|
+
if (k2 === undefined) k2 = k;
|
|
52
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
53
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
54
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
55
|
+
}
|
|
56
|
+
Object.defineProperty(o, k2, desc);
|
|
57
|
+
}) : (function(o, m, k, k2) {
|
|
58
|
+
if (k2 === undefined) k2 = k;
|
|
59
|
+
o[k2] = m[k];
|
|
60
|
+
}));
|
|
61
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
62
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
63
|
+
}) : function(o, v) {
|
|
64
|
+
o["default"] = v;
|
|
65
|
+
});
|
|
66
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
67
|
+
var ownKeys = function(o) {
|
|
68
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
69
|
+
var ar = [];
|
|
70
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
71
|
+
return ar;
|
|
72
|
+
};
|
|
73
|
+
return ownKeys(o);
|
|
74
|
+
};
|
|
75
|
+
return function (mod) {
|
|
76
|
+
if (mod && mod.__esModule) return mod;
|
|
77
|
+
var result = {};
|
|
78
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
79
|
+
__setModuleDefault(result, mod);
|
|
80
|
+
return result;
|
|
81
|
+
};
|
|
82
|
+
})();
|
|
83
|
+
const node_child_process_1 = require("node:child_process");
|
|
84
|
+
const fs = __importStar(require("node:fs"));
|
|
85
|
+
const os = __importStar(require("node:os"));
|
|
86
|
+
const path = __importStar(require("node:path"));
|
|
87
|
+
const fmt = __importStar(require("../core/fmt.js"));
|
|
57
88
|
const REPO_ROOT = path.resolve(__dirname, '..', '..');
|
|
58
89
|
const SELF_TEST_FILE = 'coverage-gate.test.js';
|
|
59
90
|
const TEMP_DIR_PREFIXES = [
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
91
|
+
'agents-',
|
|
92
|
+
'sessions-',
|
|
93
|
+
'review-',
|
|
94
|
+
'forgejo-',
|
|
95
|
+
'workflow-',
|
|
96
|
+
'gatekeeper-',
|
|
97
|
+
'graphify-',
|
|
98
|
+
'claude-',
|
|
99
|
+
'codex-',
|
|
100
|
+
'gemini-',
|
|
101
|
+
'opencode-',
|
|
102
|
+
'startagent-',
|
|
103
|
+
'test-',
|
|
104
|
+
'mission-task-',
|
|
105
|
+
'visualBoard-task-',
|
|
106
|
+
'backlog-'
|
|
76
107
|
];
|
|
77
108
|
const COVERAGE_INCLUDES = [
|
|
78
|
-
|
|
79
|
-
|
|
109
|
+
'index.js',
|
|
110
|
+
'lib/**/*.js'
|
|
80
111
|
];
|
|
81
112
|
const COVERAGE_EXCLUDES = [
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
113
|
+
'test/**',
|
|
114
|
+
'prompts/**',
|
|
115
|
+
'config/*.json',
|
|
116
|
+
'.workflow/**',
|
|
117
|
+
'node_modules/**'
|
|
87
118
|
];
|
|
88
119
|
// The full suite regularly exceeds 10 minutes in this repository, especially
|
|
89
120
|
// under cold caches. Keep the gate generous so it can finish without a manual
|
|
90
121
|
// override while still failing on real hangs.
|
|
91
122
|
const DEFAULT_TEST_TIMEOUT_MS = 3_600_000;
|
|
92
|
-
/** @type {string[]} */
|
|
93
123
|
const PER_RUN_SCRATCH = [];
|
|
94
124
|
let threshold = 90;
|
|
95
125
|
let dryRun = false;
|
|
96
126
|
let lcov = false;
|
|
97
127
|
let cleanupDone = false;
|
|
98
|
-
|
|
99
128
|
for (let i = 2; i < process.argv.length; i++) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
129
|
+
if (process.argv[i] === '--threshold' && process.argv[i + 1]) {
|
|
130
|
+
threshold = parseFloat(process.argv[i + 1]);
|
|
131
|
+
i++;
|
|
132
|
+
}
|
|
133
|
+
else if (process.argv[i] === '--dry-run') {
|
|
134
|
+
dryRun = true;
|
|
135
|
+
}
|
|
136
|
+
else if (process.argv[i] === '--lcov') {
|
|
137
|
+
lcov = true;
|
|
138
|
+
}
|
|
108
139
|
}
|
|
109
|
-
|
|
110
140
|
function discoverTestFiles() {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
.
|
|
116
|
-
|
|
117
|
-
|
|
141
|
+
const testDir = path.join(REPO_ROOT, 'test');
|
|
142
|
+
if (!fs.existsSync(testDir)) {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
return fs.readdirSync(testDir)
|
|
146
|
+
.filter(file => file.endsWith('.test.js'))
|
|
147
|
+
.filter(file => file !== SELF_TEST_FILE)
|
|
148
|
+
.map(file => path.join(testDir, file))
|
|
149
|
+
.sort();
|
|
118
150
|
}
|
|
119
|
-
|
|
120
151
|
function listTempEntries(tmpRoot = os.tmpdir()) {
|
|
121
|
-
|
|
122
|
-
|
|
152
|
+
if (!fs.existsSync(tmpRoot)) {
|
|
153
|
+
return new Set();
|
|
154
|
+
}
|
|
155
|
+
return new Set(fs.readdirSync(tmpRoot));
|
|
123
156
|
}
|
|
124
|
-
|
|
125
|
-
/** @param {string} name */
|
|
126
157
|
function shouldCleanTempDir(name) {
|
|
127
|
-
|
|
158
|
+
return TEMP_DIR_PREFIXES.some(prefix => name.startsWith(prefix));
|
|
128
159
|
}
|
|
129
|
-
|
|
130
|
-
/** @param {Set<string>} beforeEntries @param {string} tmpRoot */
|
|
131
160
|
function cleanupNewTempDirs(beforeEntries, tmpRoot = os.tmpdir()) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
161
|
+
if (!fs.existsSync(tmpRoot)) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
for (const name of fs.readdirSync(tmpRoot)) {
|
|
165
|
+
if (beforeEntries.has(name) || !shouldCleanTempDir(name)) {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
const fullPath = path.join(tmpRoot, name);
|
|
169
|
+
let stat = null;
|
|
170
|
+
try {
|
|
171
|
+
stat = fs.statSync(fullPath);
|
|
172
|
+
}
|
|
173
|
+
catch (_) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (!stat.isDirectory()) {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
fs.rmSync(fullPath, { recursive: true, force: true });
|
|
181
|
+
}
|
|
182
|
+
catch (_) { }
|
|
141
183
|
}
|
|
142
|
-
if (!stat.isDirectory()) {continue;}
|
|
143
|
-
try {
|
|
144
|
-
fs.rmSync(fullPath, { recursive: true, force: true });
|
|
145
|
-
} catch (_) {}
|
|
146
|
-
}
|
|
147
184
|
}
|
|
148
|
-
|
|
149
185
|
function createPerRunScratchDirs() {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
186
|
+
const coverageDir = fs.mkdtempSync(path.join(os.tmpdir(), 'node-coverage-'));
|
|
187
|
+
PER_RUN_SCRATCH.push(coverageDir);
|
|
188
|
+
return coverageDir;
|
|
153
189
|
}
|
|
154
|
-
|
|
155
190
|
function createPerRunTmpRoot() {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
191
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'coverage-gate-tmp-'));
|
|
192
|
+
PER_RUN_SCRATCH.push(tmpRoot);
|
|
193
|
+
return tmpRoot;
|
|
159
194
|
}
|
|
160
|
-
|
|
161
195
|
function createMockGraphifyBin() {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
196
|
+
const graphifyDir = fs.mkdtempSync(path.join(os.tmpdir(), 'graphify-'));
|
|
197
|
+
PER_RUN_SCRATCH.push(graphifyDir);
|
|
198
|
+
const graphifyBin = path.join(graphifyDir, 'graphify');
|
|
199
|
+
fs.writeFileSync(graphifyBin, `#!/usr/bin/env bash
|
|
166
200
|
set -euo pipefail
|
|
167
201
|
if [[ "\${1:-}" == "--help" ]]; then
|
|
168
202
|
echo "mock graphify"
|
|
@@ -178,188 +212,179 @@ fi
|
|
|
178
212
|
echo "Unhandled graphify command: $*" >&2
|
|
179
213
|
exit 1
|
|
180
214
|
`, { mode: 0o755 });
|
|
181
|
-
|
|
215
|
+
return graphifyBin;
|
|
182
216
|
}
|
|
183
|
-
|
|
184
217
|
function cleanupPerRunScratch() {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
218
|
+
if (cleanupDone) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
cleanupDone = true;
|
|
222
|
+
for (const dir of PER_RUN_SCRATCH) {
|
|
223
|
+
try {
|
|
224
|
+
if (fs.existsSync(dir)) {
|
|
225
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch (_) { }
|
|
229
|
+
}
|
|
230
|
+
PER_RUN_SCRATCH.length = 0;
|
|
195
231
|
}
|
|
196
|
-
|
|
197
232
|
function registerExitHandlers() {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
233
|
+
process.on('exit', cleanupPerRunScratch);
|
|
234
|
+
process.on('SIGINT', () => {
|
|
235
|
+
cleanupPerRunScratch();
|
|
236
|
+
process.exit(130);
|
|
237
|
+
});
|
|
238
|
+
process.on('SIGTERM', () => {
|
|
239
|
+
cleanupPerRunScratch();
|
|
240
|
+
process.exit(143);
|
|
241
|
+
});
|
|
207
242
|
}
|
|
208
|
-
|
|
209
243
|
function resetPerRunScratchState() {
|
|
210
|
-
|
|
211
|
-
|
|
244
|
+
PER_RUN_SCRATCH.length = 0;
|
|
245
|
+
cleanupDone = false;
|
|
212
246
|
}
|
|
213
|
-
|
|
214
|
-
/** @param {string[]} testFiles @param {number} coverageThreshold @param {boolean} useLcov */
|
|
215
247
|
function buildCoverageArgs(testFiles, coverageThreshold = threshold, useLcov = lcov) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
248
|
+
const args = [
|
|
249
|
+
'--test',
|
|
250
|
+
'--experimental-test-coverage',
|
|
251
|
+
`--test-coverage-lines=${coverageThreshold}`,
|
|
252
|
+
...COVERAGE_INCLUDES.flatMap(pattern => ['--test-coverage-include', pattern]),
|
|
253
|
+
...COVERAGE_EXCLUDES.flatMap(pattern => ['--test-coverage-exclude', pattern]),
|
|
254
|
+
];
|
|
255
|
+
if (useLcov) {
|
|
256
|
+
const coverageDir = path.join(REPO_ROOT, 'coverage');
|
|
257
|
+
if (!fs.existsSync(coverageDir)) {
|
|
258
|
+
fs.mkdirSync(coverageDir, { recursive: true });
|
|
259
|
+
}
|
|
260
|
+
args.push('--test-reporter=lcov');
|
|
261
|
+
args.push(`--test-reporter-destination=${path.join(coverageDir, 'lcov.info')}`);
|
|
262
|
+
args.push('--test-reporter=spec');
|
|
263
|
+
args.push('--test-reporter-destination=stdout');
|
|
228
264
|
}
|
|
229
|
-
args.push(
|
|
230
|
-
args
|
|
231
|
-
args.push('--test-reporter=spec');
|
|
232
|
-
args.push('--test-reporter-destination=stdout');
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
args.push(...testFiles);
|
|
236
|
-
return args;
|
|
265
|
+
args.push(...testFiles);
|
|
266
|
+
return args;
|
|
237
267
|
}
|
|
238
|
-
|
|
239
268
|
function resolveTestTimeoutMs(env = process.env) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
269
|
+
const raw = env.WORKFLOW_COVERAGE_GATE_TIMEOUT_MS;
|
|
270
|
+
if (raw === undefined || raw === '') {
|
|
271
|
+
return DEFAULT_TEST_TIMEOUT_MS;
|
|
272
|
+
}
|
|
273
|
+
const parsed = Number(raw);
|
|
274
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_TEST_TIMEOUT_MS;
|
|
244
275
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
if (result.signal) {
|
|
275
|
-
fmt.log.error(`[coverage-gate] test runner killed by signal ${result.signal}`);
|
|
276
|
-
return 1;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return result.status === null ? 1 : result.status;
|
|
276
|
+
function runTests(testFiles, coverageThreshold = threshold, _spawnSync = node_child_process_1.spawnSync) {
|
|
277
|
+
const tmpRoot = createPerRunTmpRoot();
|
|
278
|
+
const tmpEntriesBefore = listTempEntries(tmpRoot);
|
|
279
|
+
const nodeCoverageDir = createPerRunScratchDirs();
|
|
280
|
+
const childEnv = { ...process.env };
|
|
281
|
+
delete childEnv.NODE_TEST_CONTEXT;
|
|
282
|
+
delete childEnv.NODE_OPTIONS;
|
|
283
|
+
childEnv.TMPDIR = tmpRoot;
|
|
284
|
+
childEnv.NODE_V8_COVERAGE = nodeCoverageDir;
|
|
285
|
+
childEnv.GRAPHIFY_BIN = createMockGraphifyBin();
|
|
286
|
+
const result = _spawnSync(process.execPath, buildCoverageArgs(testFiles, coverageThreshold), {
|
|
287
|
+
encoding: 'utf8',
|
|
288
|
+
cwd: REPO_ROOT,
|
|
289
|
+
env: childEnv,
|
|
290
|
+
stdio: ['pipe', 'inherit', 'inherit'],
|
|
291
|
+
timeout: resolveTestTimeoutMs(),
|
|
292
|
+
});
|
|
293
|
+
cleanupNewTempDirs(tmpEntriesBefore, tmpRoot);
|
|
294
|
+
cleanupPerRunScratch();
|
|
295
|
+
if (result.error) {
|
|
296
|
+
fmt.log.error(`[coverage-gate] failed to spawn test runner: ${result.error.message}`);
|
|
297
|
+
return 1;
|
|
298
|
+
}
|
|
299
|
+
if (result.signal) {
|
|
300
|
+
fmt.log.error(`[coverage-gate] test runner killed by signal ${result.signal}`);
|
|
301
|
+
return 1;
|
|
302
|
+
}
|
|
303
|
+
return result.status === null ? 1 : result.status;
|
|
280
304
|
}
|
|
281
|
-
|
|
282
305
|
function main() {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
fmt.log.info(`Found ${testFiles.length} test file(s)`);
|
|
290
|
-
|
|
291
|
-
if (dryRun) {
|
|
292
|
-
fmt.log.info(`DRY-RUN mode — threshold=${threshold}%`);
|
|
293
|
-
fmt.log.info('Denominator: index.js + lib/**/*.js');
|
|
294
|
-
fmt.log.info(`Include globs: ${COVERAGE_INCLUDES.join(', ')}`);
|
|
295
|
-
fmt.log.info(`Exclude globs: ${COVERAGE_EXCLUDES.join(', ')}`);
|
|
296
|
-
fmt.log.info(`Would run: ${fmt.command(`${process.execPath} ${buildCoverageArgs(testFiles, threshold).join(' ')}`)}`);
|
|
297
|
-
process.exit(0);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
registerExitHandlers();
|
|
301
|
-
process.exit(runTests(testFiles, threshold));
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (require.main === module) {
|
|
305
|
-
main();
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/** @param {string[]} args @param {{exitFn?: Function}} options */
|
|
309
|
-
function run(args, options = {}) {
|
|
310
|
-
/** @type{Function} */
|
|
311
|
-
const exitFn = options.exitFn || process.exit;
|
|
312
|
-
let threshold_ = 90;
|
|
313
|
-
let dryRun_ = false;
|
|
314
|
-
for (let i = 0; i < args.length; i++) {
|
|
315
|
-
if (args[i] === '--threshold' && args[i + 1]) {
|
|
316
|
-
threshold_ = parseFloat(args[i + 1]);
|
|
317
|
-
i++;
|
|
318
|
-
} else if (args[i] === '--dry-run') {
|
|
319
|
-
dryRun_ = true;
|
|
306
|
+
const testFiles = discoverTestFiles();
|
|
307
|
+
if (testFiles.length === 0) {
|
|
308
|
+
fmt.log.fail('no parallix test files found under test/');
|
|
309
|
+
process.exit(1);
|
|
320
310
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
const savedDryRun = dryRun;
|
|
324
|
-
threshold = threshold_;
|
|
325
|
-
dryRun = dryRun_;
|
|
326
|
-
try {
|
|
327
|
-
if (dryRun_) {
|
|
328
|
-
const testFiles = discoverTestFiles();
|
|
329
|
-
if (testFiles.length === 0) {
|
|
330
|
-
if (typeof exitFn === 'function') {exitFn(1);}
|
|
331
|
-
} else {
|
|
332
|
-
fmt.log.info(`Found ${testFiles.length} test file(s)`);
|
|
311
|
+
fmt.log.info(`Found ${testFiles.length} test file(s)`);
|
|
312
|
+
if (dryRun) {
|
|
333
313
|
fmt.log.info(`DRY-RUN mode — threshold=${threshold}%`);
|
|
334
314
|
fmt.log.info('Denominator: index.js + lib/**/*.js');
|
|
335
315
|
fmt.log.info(`Include globs: ${COVERAGE_INCLUDES.join(', ')}`);
|
|
336
316
|
fmt.log.info(`Exclude globs: ${COVERAGE_EXCLUDES.join(', ')}`);
|
|
337
317
|
fmt.log.info(`Would run: ${fmt.command(`${process.execPath} ${buildCoverageArgs(testFiles, threshold).join(' ')}`)}`);
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
318
|
+
process.exit(0);
|
|
319
|
+
}
|
|
320
|
+
registerExitHandlers();
|
|
321
|
+
process.exit(runTests(testFiles, threshold));
|
|
322
|
+
}
|
|
323
|
+
if (typeof require !== 'undefined' && require.main === module) {
|
|
324
|
+
main();
|
|
325
|
+
}
|
|
326
|
+
function run(args, options = {}) {
|
|
327
|
+
const exitFn = options.exitFn || process.exit;
|
|
328
|
+
let threshold_ = 90;
|
|
329
|
+
let dryRun_ = false;
|
|
330
|
+
for (let i = 0; i < args.length; i++) {
|
|
331
|
+
if (args[i] === '--threshold' && args[i + 1]) {
|
|
332
|
+
threshold_ = parseFloat(args[i + 1]);
|
|
333
|
+
i++;
|
|
334
|
+
}
|
|
335
|
+
else if (args[i] === '--dry-run') {
|
|
336
|
+
dryRun_ = true;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const savedThreshold = threshold;
|
|
340
|
+
const savedDryRun = dryRun;
|
|
341
|
+
threshold = threshold_;
|
|
342
|
+
dryRun = dryRun_;
|
|
343
|
+
try {
|
|
344
|
+
if (dryRun_) {
|
|
345
|
+
const testFiles = discoverTestFiles();
|
|
346
|
+
if (testFiles.length === 0) {
|
|
347
|
+
if (typeof exitFn === 'function') {
|
|
348
|
+
exitFn(1);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
fmt.log.info(`Found ${testFiles.length} test file(s)`);
|
|
353
|
+
fmt.log.info(`DRY-RUN mode — threshold=${threshold}%`);
|
|
354
|
+
fmt.log.info('Denominator: index.js + lib/**/*.js');
|
|
355
|
+
fmt.log.info(`Include globs: ${COVERAGE_INCLUDES.join(', ')}`);
|
|
356
|
+
fmt.log.info(`Exclude globs: ${COVERAGE_EXCLUDES.join(', ')}`);
|
|
357
|
+
fmt.log.info(`Would run: ${fmt.command(`${process.execPath} ${buildCoverageArgs(testFiles, threshold).join(' ')}`)}`);
|
|
358
|
+
if (typeof exitFn === 'function') {
|
|
359
|
+
exitFn(0);
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
process.exit(0);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
registerExitHandlers();
|
|
368
|
+
exitFn(runTests(discoverTestFiles(), threshold));
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
finally {
|
|
372
|
+
threshold = savedThreshold;
|
|
373
|
+
dryRun = savedDryRun;
|
|
344
374
|
}
|
|
345
|
-
} finally {
|
|
346
|
-
threshold = savedThreshold;
|
|
347
|
-
dryRun = savedDryRun;
|
|
348
|
-
}
|
|
349
375
|
}
|
|
350
|
-
|
|
376
|
+
run.buildCoverageArgs = buildCoverageArgs;
|
|
377
|
+
run.cleanupNewTempDirs = cleanupNewTempDirs;
|
|
378
|
+
run.cleanupPerRunScratch = cleanupPerRunScratch;
|
|
379
|
+
run.createPerRunScratchDirs = createPerRunScratchDirs;
|
|
380
|
+
run.COVERAGE_EXCLUDES = COVERAGE_EXCLUDES;
|
|
381
|
+
run.COVERAGE_INCLUDES = COVERAGE_INCLUDES;
|
|
382
|
+
run.DEFAULT_TEST_TIMEOUT_MS = DEFAULT_TEST_TIMEOUT_MS;
|
|
383
|
+
run.discoverTestFiles = discoverTestFiles;
|
|
384
|
+
run.listTempEntries = listTempEntries;
|
|
385
|
+
run.registerExitHandlers = registerExitHandlers;
|
|
386
|
+
run.resetPerRunScratchState = resetPerRunScratchState;
|
|
387
|
+
run.resolveTestTimeoutMs = resolveTestTimeoutMs;
|
|
388
|
+
run.runTests = runTests;
|
|
389
|
+
run.shouldCleanTempDir = shouldCleanTempDir;
|
|
351
390
|
module.exports = run;
|
|
352
|
-
module.exports.buildCoverageArgs = buildCoverageArgs;
|
|
353
|
-
module.exports.cleanupNewTempDirs = cleanupNewTempDirs;
|
|
354
|
-
module.exports.cleanupPerRunScratch = cleanupPerRunScratch;
|
|
355
|
-
module.exports.createPerRunScratchDirs = createPerRunScratchDirs;
|
|
356
|
-
module.exports.COVERAGE_EXCLUDES = COVERAGE_EXCLUDES;
|
|
357
|
-
module.exports.COVERAGE_INCLUDES = COVERAGE_INCLUDES;
|
|
358
|
-
module.exports.DEFAULT_TEST_TIMEOUT_MS = DEFAULT_TEST_TIMEOUT_MS;
|
|
359
|
-
module.exports.discoverTestFiles = discoverTestFiles;
|
|
360
|
-
module.exports.listTempEntries = listTempEntries;
|
|
361
|
-
module.exports.registerExitHandlers = registerExitHandlers;
|
|
362
|
-
module.exports.resetPerRunScratchState = resetPerRunScratchState;
|
|
363
|
-
module.exports.resolveTestTimeoutMs = resolveTestTimeoutMs;
|
|
364
|
-
module.exports.runTests = runTests;
|
|
365
|
-
module.exports.shouldCleanTempDir = shouldCleanTempDir;
|