@quenty/nevermore-cli 4.22.0 → 4.23.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/CHANGELOG.md +11 -0
- package/dist/commands/batch-command/batch-deploy-command.js +1 -2
- package/dist/commands/batch-command/batch-deploy-command.js.map +1 -1
- package/dist/commands/batch-command/batch-test-command.d.ts.map +1 -1
- package/dist/commands/batch-command/batch-test-command.js +35 -7
- package/dist/commands/batch-command/batch-test-command.js.map +1 -1
- package/dist/commands/deploy-command/index.js +1 -1
- package/dist/commands/deploy-command/index.js.map +1 -1
- package/dist/commands/test-command/test-command.d.ts.map +1 -1
- package/dist/commands/test-command/test-command.js +6 -3
- package/dist/commands/test-command/test-command.js.map +1 -1
- package/dist/utils/batch/batch-runner.d.ts +2 -1
- package/dist/utils/batch/batch-runner.d.ts.map +1 -1
- package/dist/utils/batch/batch-runner.js +8 -3
- package/dist/utils/batch/batch-runner.js.map +1 -1
- package/dist/utils/build/upload.d.ts.map +1 -1
- package/dist/utils/build/upload.js +10 -1
- package/dist/utils/build/upload.js.map +1 -1
- package/dist/utils/job-context/base-job-context.d.ts +4 -3
- package/dist/utils/job-context/base-job-context.d.ts.map +1 -1
- package/dist/utils/job-context/base-job-context.js +6 -4
- package/dist/utils/job-context/base-job-context.js.map +1 -1
- package/dist/utils/job-context/batch-script-job-context.d.ts +4 -2
- package/dist/utils/job-context/batch-script-job-context.d.ts.map +1 -1
- package/dist/utils/job-context/batch-script-job-context.js +39 -19
- package/dist/utils/job-context/batch-script-job-context.js.map +1 -1
- package/dist/utils/job-context/cloud-job-context.d.ts +3 -3
- package/dist/utils/job-context/cloud-job-context.d.ts.map +1 -1
- package/dist/utils/job-context/cloud-job-context.js +23 -8
- package/dist/utils/job-context/cloud-job-context.js.map +1 -1
- package/dist/utils/job-context/job-context.d.ts +2 -3
- package/dist/utils/job-context/job-context.d.ts.map +1 -1
- package/dist/utils/job-context/local-job-context.d.ts +3 -3
- package/dist/utils/job-context/local-job-context.d.ts.map +1 -1
- package/dist/utils/job-context/local-job-context.js +6 -6
- package/dist/utils/job-context/local-job-context.js.map +1 -1
- package/dist/utils/open-cloud/open-cloud-client.d.ts +1 -1
- package/dist/utils/open-cloud/open-cloud-client.d.ts.map +1 -1
- package/dist/utils/open-cloud/open-cloud-client.js +40 -11
- package/dist/utils/open-cloud/open-cloud-client.js.map +1 -1
- package/dist/utils/testing/parsers/batch-log-parser.d.ts +2 -0
- package/dist/utils/testing/parsers/batch-log-parser.d.ts.map +1 -1
- package/dist/utils/testing/parsers/batch-log-parser.js +3 -1
- package/dist/utils/testing/parsers/batch-log-parser.js.map +1 -1
- package/dist/utils/testing/runner/combined-project-generator.d.ts +9 -0
- package/dist/utils/testing/runner/combined-project-generator.d.ts.map +1 -1
- package/dist/utils/testing/runner/combined-project-generator.js +17 -1
- package/dist/utils/testing/runner/combined-project-generator.js.map +1 -1
- package/dist/utils/testing/runner/test-runner.d.ts +3 -2
- package/dist/utils/testing/runner/test-runner.d.ts.map +1 -1
- package/dist/utils/testing/runner/test-runner.js +5 -5
- package/dist/utils/testing/runner/test-runner.js.map +1 -1
- package/dist/utils/testing/test-log-parser.d.ts +11 -0
- package/dist/utils/testing/test-log-parser.d.ts.map +1 -1
- package/dist/utils/testing/test-log-parser.js +22 -0
- package/dist/utils/testing/test-log-parser.js.map +1 -1
- package/package.json +6 -6
- package/src/commands/batch-command/batch-deploy-command.ts +1 -2
- package/src/commands/batch-command/batch-test-command.ts +42 -10
- package/src/commands/deploy-command/index.ts +1 -1
- package/src/commands/test-command/test-command.ts +6 -2
- package/src/utils/batch/batch-runner.ts +12 -2
- package/src/utils/build/upload.ts +13 -1
- package/src/utils/job-context/base-job-context.ts +8 -6
- package/src/utils/job-context/batch-script-job-context.ts +40 -21
- package/src/utils/job-context/cloud-job-context.ts +24 -8
- package/src/utils/job-context/job-context.ts +2 -3
- package/src/utils/job-context/local-job-context.ts +4 -6
- package/src/utils/open-cloud/open-cloud-client.ts +43 -11
- package/src/utils/testing/parsers/batch-log-parser.ts +4 -1
- package/src/utils/testing/runner/combined-project-generator.ts +28 -1
- package/src/utils/testing/runner/test-runner.ts +5 -6
- package/src/utils/testing/test-log-parser.ts +33 -0
- package/templates/batch-test-runner.luau +9 -9
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combined-project-generator.js","sourceRoot":"","sources":["../../../../src/utils/testing/runner/combined-project-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EACL,YAAY,EACZ,kBAAkB,GACnB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAEL,qBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"combined-project-generator.js","sourceRoot":"","sources":["../../../../src/utils/testing/runner/combined-project-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { type Reporter } from '@quenty/cli-output-helpers/reporting';
|
|
2
1
|
import { type JobContext } from '../../job-context/job-context.js';
|
|
2
|
+
import { type ParsedTestCounts } from '../test-log-parser.js';
|
|
3
3
|
export interface SingleTestResult {
|
|
4
4
|
success: boolean;
|
|
5
5
|
logs: string;
|
|
6
|
+
testCounts?: ParsedTestCounts;
|
|
6
7
|
}
|
|
7
8
|
export interface SingleTestOptions {
|
|
8
9
|
packagePath: string;
|
|
@@ -17,7 +18,7 @@ export interface SingleTestOptions {
|
|
|
17
18
|
*
|
|
18
19
|
* Creates and releases its own deployment handle — the caller owns the context lifetime.
|
|
19
20
|
*/
|
|
20
|
-
export declare function runSingleTestAsync(context: JobContext,
|
|
21
|
+
export declare function runSingleTestAsync(context: JobContext, options: SingleTestOptions): Promise<SingleTestResult>;
|
|
21
22
|
/**
|
|
22
23
|
* Read a test script from the deploy target's configured script path.
|
|
23
24
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../../../../src/utils/testing/runner/test-runner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../../../../src/utils/testing/runner/test-runner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,KAAK,gBAAgB,EAAkC,MAAM,uBAAuB,CAAC;AAE9F,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CA2C3B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,MAAM,CAAC,CAajB"}
|
|
@@ -1,31 +1,30 @@
|
|
|
1
1
|
import * as fs from 'fs/promises';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { randomUUID } from 'crypto';
|
|
4
|
-
import { parseTestLogs } from '../test-log-parser.js';
|
|
4
|
+
import { parseTestLogs, parseTestCounts } from '../test-log-parser.js';
|
|
5
5
|
/**
|
|
6
6
|
* Build, deploy, and run a test for a single package using the provided
|
|
7
7
|
* JobContext. The context determines the execution environment (cloud or local).
|
|
8
8
|
*
|
|
9
9
|
* Creates and releases its own deployment handle — the caller owns the context lifetime.
|
|
10
10
|
*/
|
|
11
|
-
export async function runSingleTestAsync(context,
|
|
11
|
+
export async function runSingleTestAsync(context, options) {
|
|
12
12
|
const { packagePath, packageName, timeoutMs = 120_000, scriptText, } = options;
|
|
13
13
|
const sessionId = randomUUID();
|
|
14
14
|
const builtPlace = await context.buildPlaceAsync({
|
|
15
15
|
targetName: 'test',
|
|
16
16
|
outputFileName: `test-${sessionId}.rbxl`,
|
|
17
17
|
packagePath,
|
|
18
|
-
reporter,
|
|
19
18
|
packageName,
|
|
20
19
|
});
|
|
21
20
|
const scriptContent = scriptText ?? (await readTestScriptAsync(packagePath, builtPlace.target.scriptTemplate));
|
|
22
|
-
const deployment = await context.deployBuiltPlaceAsync(
|
|
21
|
+
const deployment = await context.deployBuiltPlaceAsync({
|
|
23
22
|
builtPlace,
|
|
24
23
|
packageName,
|
|
25
24
|
packagePath,
|
|
26
25
|
});
|
|
27
26
|
try {
|
|
28
|
-
const result = await context.runScriptAsync(deployment,
|
|
27
|
+
const result = await context.runScriptAsync(deployment, {
|
|
29
28
|
scriptContent,
|
|
30
29
|
packageName,
|
|
31
30
|
timeoutMs,
|
|
@@ -35,6 +34,7 @@ export async function runSingleTestAsync(context, reporter, options) {
|
|
|
35
34
|
return {
|
|
36
35
|
success: result.success && parsed.success,
|
|
37
36
|
logs: parsed.logs,
|
|
37
|
+
testCounts: parseTestCounts(parsed.logs),
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-runner.js","sourceRoot":"","sources":["../../../../src/utils/testing/runner/test-runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"test-runner.js","sourceRoot":"","sources":["../../../../src/utils/testing/runner/test-runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC,OAAO,EAAyB,aAAa,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAgB9F;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAmB,EACnB,OAA0B;IAE1B,MAAM,EACJ,WAAW,EACX,WAAW,EACX,SAAS,GAAG,OAAO,EACnB,UAAU,GACX,GAAG,OAAO,CAAC;IAEZ,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC;QAC/C,UAAU,EAAE,MAAM;QAClB,cAAc,EAAE,QAAQ,SAAS,OAAO;QACxC,WAAW;QACX,WAAW;KACZ,CAAC,CAAC;IAEH,MAAM,aAAa,GACjB,UAAU,IAAI,CAAC,MAAM,mBAAmB,CAAC,WAAW,EAAE,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;IAE3F,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,qBAAqB,CAAC;QACrD,UAAU;QACV,WAAW;QACX,WAAW;KACZ,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,UAAU,EAAE;YACtD,aAAa;YACb,WAAW;YACX,SAAS;SACV,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QAEtC,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO;YACzC,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,UAAU,EAAE,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC;SACzC,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,WAAmB,EACnB,UAA8B;IAE9B,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,mDAAmD,WAAW,2EAA2E,CAC1I,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACvD,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;IACxD,CAAC;AACH,CAAC"}
|
|
@@ -1,10 +1,21 @@
|
|
|
1
|
+
export interface ParsedTestCounts {
|
|
2
|
+
passed: number;
|
|
3
|
+
failed: number;
|
|
4
|
+
total: number;
|
|
5
|
+
}
|
|
1
6
|
export interface ParsedTestLogs {
|
|
2
7
|
success: boolean;
|
|
3
8
|
logs: string;
|
|
9
|
+
testCounts?: ParsedTestCounts;
|
|
4
10
|
}
|
|
5
11
|
/**
|
|
6
12
|
* Analyze test output for Jest failures and Luau runtime errors.
|
|
7
13
|
* Shared by both Open Cloud log fetching and local run-in-roblox output.
|
|
8
14
|
*/
|
|
9
15
|
export declare function parseTestLogs(rawOutput: string): ParsedTestLogs;
|
|
16
|
+
/**
|
|
17
|
+
* Parse Jest "Tests: N failed, N passed, N total" line into structured counts.
|
|
18
|
+
* Returns undefined if no test summary line is found.
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseTestCounts(rawOutput: string): ParsedTestCounts | undefined;
|
|
10
21
|
//# sourceMappingURL=test-log-parser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-log-parser.d.ts","sourceRoot":"","sources":["../../../src/utils/testing/test-log-parser.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"test-log-parser.d.ts","sourceRoot":"","sources":["../../../src/utils/testing/test-log-parser.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAkB/D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAmB/E"}
|
|
@@ -15,6 +15,28 @@ export function parseTestLogs(rawOutput) {
|
|
|
15
15
|
return {
|
|
16
16
|
success: !hasJestFailures && !hasRuntimeError,
|
|
17
17
|
logs: rawOutput,
|
|
18
|
+
testCounts: parseTestCounts(rawOutput),
|
|
18
19
|
};
|
|
19
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Parse Jest "Tests: N failed, N passed, N total" line into structured counts.
|
|
23
|
+
* Returns undefined if no test summary line is found.
|
|
24
|
+
*/
|
|
25
|
+
export function parseTestCounts(rawOutput) {
|
|
26
|
+
const clean = OutputHelper.stripAnsi(rawOutput);
|
|
27
|
+
// Match "Tests: 2 failed, 23 passed, 25 total" or "Tests: 25 passed, 25 total"
|
|
28
|
+
const match = clean.match(/Tests:\s+(.+?)\s+total/);
|
|
29
|
+
if (!match)
|
|
30
|
+
return undefined;
|
|
31
|
+
const prefix = match[1];
|
|
32
|
+
const totalMatch = clean.match(/Tests:\s+.+?(\d+)\s+total/);
|
|
33
|
+
if (!totalMatch)
|
|
34
|
+
return undefined;
|
|
35
|
+
const total = parseInt(totalMatch[1], 10);
|
|
36
|
+
const passedMatch = prefix.match(/(\d+)\s+passed/);
|
|
37
|
+
const failedMatch = prefix.match(/(\d+)\s+failed/);
|
|
38
|
+
const passed = passedMatch ? parseInt(passedMatch[1], 10) : 0;
|
|
39
|
+
const failed = failedMatch ? parseInt(failedMatch[1], 10) : 0;
|
|
40
|
+
return { passed, failed, total };
|
|
41
|
+
}
|
|
20
42
|
//# sourceMappingURL=test-log-parser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-log-parser.js","sourceRoot":"","sources":["../../../src/utils/testing/test-log-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"test-log-parser.js","sourceRoot":"","sources":["../../../src/utils/testing/test-log-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAc1D;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAEpD,qCAAqC;IACrC,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACtE,MAAM,WAAW,GAAG,SAAS,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC/D,MAAM,eAAe,GACnB,CAAC,YAAY,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;QACnD,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAEpD,+CAA+C;IAC/C,MAAM,eAAe,GAAG,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAExD,OAAO;QACL,OAAO,EAAE,CAAC,eAAe,IAAI,CAAC,eAAe;QAC7C,IAAI,EAAE,SAAS;QACf,UAAU,EAAE,eAAe,CAAC,SAAS,CAAC;KACvC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAEhD,iFAAiF;IACjF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACpD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAE7B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC5D,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAElC,MAAM,KAAK,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAEnD,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9D,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACnC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/nevermore-cli",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.23.0",
|
|
4
4
|
"description": "CLI interface for Nevermore",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
"Quenty"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@quenty/cli-output-helpers": "1.
|
|
29
|
-
"@quenty/nevermore-cli-helpers": "1.
|
|
30
|
-
"@quenty/nevermore-template-helpers": "1.
|
|
31
|
-
"@quenty/studio-bridge": "0.
|
|
28
|
+
"@quenty/cli-output-helpers": "1.10.0",
|
|
29
|
+
"@quenty/nevermore-cli-helpers": "1.8.0",
|
|
30
|
+
"@quenty/nevermore-template-helpers": "1.11.0",
|
|
31
|
+
"@quenty/studio-bridge": "0.7.0",
|
|
32
32
|
"execa": "^9.6.1",
|
|
33
33
|
"find-git-root": "^1.0.4",
|
|
34
34
|
"inquirer": "^13.2.0",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"engines": {
|
|
58
58
|
"node": ">=16"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "7f6f73dc51f43fa1050f76f86a5935f5a64ab99f"
|
|
61
61
|
}
|
|
@@ -172,7 +172,7 @@ async function _runAsync(args: BatchDeployArgs): Promise<void> {
|
|
|
172
172
|
apiKey,
|
|
173
173
|
rateLimiter: new RateLimiter(),
|
|
174
174
|
});
|
|
175
|
-
const context = new CloudJobContext(client);
|
|
175
|
+
const context = new CloudJobContext(reporter, client);
|
|
176
176
|
|
|
177
177
|
await reporter.startAsync();
|
|
178
178
|
|
|
@@ -188,7 +188,6 @@ async function _runAsync(args: BatchDeployArgs): Promise<void> {
|
|
|
188
188
|
targetName,
|
|
189
189
|
outputFileName: publish ? 'publish.rbxl' : 'deploy.rbxl',
|
|
190
190
|
packagePath: pkg.path,
|
|
191
|
-
reporter: pkgReporter,
|
|
192
191
|
packageName: pkg.name,
|
|
193
192
|
});
|
|
194
193
|
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { CommandModule } from 'yargs';
|
|
2
2
|
import { OutputHelper } from '@quenty/cli-output-helpers';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
type Reporter,
|
|
5
|
+
type JobPhase,
|
|
6
|
+
type ProgressSummary,
|
|
7
|
+
} from '@quenty/cli-output-helpers/reporting';
|
|
4
8
|
import { NevermoreGlobalArgs } from '../../args/global-args.js';
|
|
5
9
|
import { getApiKeyAsync } from '../../utils/auth/credential-store.js';
|
|
6
10
|
import { runBatchAsync } from '../../utils/batch/batch-runner.js';
|
|
@@ -188,15 +192,22 @@ async function _runAsync(args: BatchTestArgs): Promise<void> {
|
|
|
188
192
|
|
|
189
193
|
const timeoutMs = 120_000;
|
|
190
194
|
|
|
195
|
+
// In aggregated mode, the inner context gets a broadcast reporter that translates
|
|
196
|
+
// phase changes from the shared '_batch_' operation to all real packages
|
|
197
|
+
const innerReporter: Reporter = args.aggregated
|
|
198
|
+
? _createBroadcastReporter(reporter, packageNames)
|
|
199
|
+
: reporter;
|
|
200
|
+
|
|
191
201
|
const innerContext: JobContext = cloud
|
|
192
|
-
? new CloudJobContext(client)
|
|
193
|
-
: new LocalJobContext(client);
|
|
202
|
+
? new CloudJobContext(innerReporter, client)
|
|
203
|
+
: new LocalJobContext(innerReporter, client);
|
|
194
204
|
|
|
195
205
|
const context: JobContext = args.aggregated
|
|
196
206
|
? new BatchScriptJobContext(innerContext, packages, {
|
|
197
207
|
batchPlaceId: args.batchPlaceId,
|
|
198
208
|
batchUniverseId: args.batchUniverseId,
|
|
199
209
|
perPackageTimeoutMs: timeoutMs,
|
|
210
|
+
reporter,
|
|
200
211
|
})
|
|
201
212
|
: innerContext;
|
|
202
213
|
|
|
@@ -208,12 +219,12 @@ async function _runAsync(args: BatchTestArgs): Promise<void> {
|
|
|
208
219
|
concurrency,
|
|
209
220
|
reporter,
|
|
210
221
|
bufferOutput: isGrouped,
|
|
211
|
-
|
|
222
|
+
stateTracker: reporter.state,
|
|
223
|
+
executeAsync: async (pkg) => {
|
|
212
224
|
const result = await _runWithRetryAsync(
|
|
213
225
|
pkg,
|
|
214
226
|
context,
|
|
215
|
-
timeoutMs
|
|
216
|
-
pkgReporter
|
|
227
|
+
timeoutMs
|
|
217
228
|
);
|
|
218
229
|
|
|
219
230
|
return {
|
|
@@ -221,6 +232,9 @@ async function _runAsync(args: BatchTestArgs): Promise<void> {
|
|
|
221
232
|
placeId: pkg.target.placeId,
|
|
222
233
|
success: result.success,
|
|
223
234
|
logs: result.logs,
|
|
235
|
+
progressSummary: result.testCounts
|
|
236
|
+
? { kind: 'test-counts' as const, ...result.testCounts }
|
|
237
|
+
: undefined,
|
|
224
238
|
};
|
|
225
239
|
},
|
|
226
240
|
});
|
|
@@ -238,8 +252,7 @@ async function _runAsync(args: BatchTestArgs): Promise<void> {
|
|
|
238
252
|
async function _runWithRetryAsync(
|
|
239
253
|
pkg: TargetPackage,
|
|
240
254
|
context: JobContext,
|
|
241
|
-
timeoutMs: number
|
|
242
|
-
reporter: Reporter
|
|
255
|
+
timeoutMs: number
|
|
243
256
|
): Promise<SingleTestResult> {
|
|
244
257
|
const opts = {
|
|
245
258
|
packagePath: pkg.path,
|
|
@@ -248,15 +261,34 @@ async function _runWithRetryAsync(
|
|
|
248
261
|
};
|
|
249
262
|
|
|
250
263
|
try {
|
|
251
|
-
return await runSingleTestAsync(context,
|
|
264
|
+
return await runSingleTestAsync(context, opts);
|
|
252
265
|
} catch (err) {
|
|
253
266
|
const message = err instanceof Error ? err.message : String(err);
|
|
254
267
|
|
|
255
268
|
if (message.includes('timed out') || message.includes('fetch failed')) {
|
|
256
269
|
OutputHelper.warn(`${pkg.name}: transient failure, retrying...`);
|
|
257
|
-
return await runSingleTestAsync(context,
|
|
270
|
+
return await runSingleTestAsync(context, opts);
|
|
258
271
|
}
|
|
259
272
|
|
|
260
273
|
throw err;
|
|
261
274
|
}
|
|
262
275
|
}
|
|
276
|
+
|
|
277
|
+
function _createBroadcastReporter(target: Reporter, packageNames: string[]): Reporter {
|
|
278
|
+
return {
|
|
279
|
+
startAsync: async () => {},
|
|
280
|
+
stopAsync: async () => {},
|
|
281
|
+
onPackageStart: () => {},
|
|
282
|
+
onPackageResult: () => {},
|
|
283
|
+
onPackagePhaseChange: (_name: string, phase: JobPhase) => {
|
|
284
|
+
for (const name of packageNames) {
|
|
285
|
+
target.onPackagePhaseChange(name, phase);
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
onPackageProgressUpdate: (_name: string, progress: ProgressSummary) => {
|
|
289
|
+
for (const name of packageNames) {
|
|
290
|
+
target.onPackageProgressUpdate(name, progress);
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
}
|
|
@@ -168,7 +168,7 @@ export class DeployCommand<T> implements CommandModule<T, DeployArgs> {
|
|
|
168
168
|
|
|
169
169
|
const apiKey = await getApiKeyAsync(args);
|
|
170
170
|
const client = new OpenCloudClient({ apiKey, rateLimiter: new RateLimiter() });
|
|
171
|
-
const context = new CloudJobContext(client);
|
|
171
|
+
const context = new CloudJobContext(reporter, client);
|
|
172
172
|
|
|
173
173
|
await reporter.startAsync();
|
|
174
174
|
|
|
@@ -105,16 +105,17 @@ export class TestProjectCommand<T>
|
|
|
105
105
|
|
|
106
106
|
const context = args.cloud
|
|
107
107
|
? new CloudJobContext(
|
|
108
|
+
reporter,
|
|
108
109
|
new OpenCloudClient({
|
|
109
110
|
apiKey: await getApiKeyAsync(args),
|
|
110
111
|
rateLimiter: new RateLimiter(),
|
|
111
112
|
})
|
|
112
113
|
)
|
|
113
|
-
: new LocalJobContext();
|
|
114
|
+
: new LocalJobContext(reporter);
|
|
114
115
|
|
|
115
116
|
let result;
|
|
116
117
|
try {
|
|
117
|
-
result = await runSingleTestAsync(context,
|
|
118
|
+
result = await runSingleTestAsync(context, {
|
|
118
119
|
packagePath: cwd,
|
|
119
120
|
packageName,
|
|
120
121
|
scriptText: args.scriptText,
|
|
@@ -128,6 +129,9 @@ export class TestProjectCommand<T>
|
|
|
128
129
|
success: result.success,
|
|
129
130
|
logs: result.logs,
|
|
130
131
|
durationMs: 0,
|
|
132
|
+
progressSummary: result.testCounts
|
|
133
|
+
? { kind: 'test-counts', ...result.testCounts }
|
|
134
|
+
: undefined,
|
|
131
135
|
});
|
|
132
136
|
|
|
133
137
|
await reporter.stopAsync();
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
type Reporter,
|
|
4
4
|
type PackageResult,
|
|
5
5
|
type BatchSummary,
|
|
6
|
+
type IStateTracker,
|
|
6
7
|
} from '@quenty/cli-output-helpers/reporting';
|
|
7
8
|
import { type TargetPackage } from './changed-packages-utils.js';
|
|
8
9
|
|
|
@@ -11,6 +12,7 @@ export interface BatchOptions<TResult extends PackageResult> {
|
|
|
11
12
|
concurrency?: number;
|
|
12
13
|
reporter: Reporter;
|
|
13
14
|
bufferOutput?: boolean;
|
|
15
|
+
stateTracker?: IStateTracker;
|
|
14
16
|
executeAsync: (
|
|
15
17
|
pkg: TargetPackage,
|
|
16
18
|
reporter: Reporter
|
|
@@ -25,6 +27,7 @@ export async function runBatchAsync<TResult extends PackageResult>(
|
|
|
25
27
|
concurrency = Infinity,
|
|
26
28
|
reporter,
|
|
27
29
|
bufferOutput = false,
|
|
30
|
+
stateTracker,
|
|
28
31
|
executeAsync,
|
|
29
32
|
} = options;
|
|
30
33
|
|
|
@@ -39,7 +42,7 @@ export async function runBatchAsync<TResult extends PackageResult>(
|
|
|
39
42
|
const pkg = packages[nextIndex++];
|
|
40
43
|
runningCount++;
|
|
41
44
|
|
|
42
|
-
_runOneAsync<TResult>(pkg, executeAsync, reporter, bufferOutput)
|
|
45
|
+
_runOneAsync<TResult>(pkg, executeAsync, reporter, bufferOutput, stateTracker)
|
|
43
46
|
.then((result) => {
|
|
44
47
|
results.push(result);
|
|
45
48
|
})
|
|
@@ -78,7 +81,8 @@ async function _runOneAsync<TResult extends PackageResult>(
|
|
|
78
81
|
reporter: Reporter
|
|
79
82
|
) => Promise<Omit<TResult, 'durationMs'>>,
|
|
80
83
|
reporter: Reporter,
|
|
81
|
-
bufferOutput: boolean
|
|
84
|
+
bufferOutput: boolean,
|
|
85
|
+
stateTracker?: IStateTracker
|
|
82
86
|
): Promise<TResult> {
|
|
83
87
|
reporter.onPackageStart(pkg.name);
|
|
84
88
|
const startMs = Date.now();
|
|
@@ -89,12 +93,18 @@ async function _runOneAsync<TResult extends PackageResult>(
|
|
|
89
93
|
return { ...partial, durationMs: Date.now() - startMs } as TResult;
|
|
90
94
|
} catch (err) {
|
|
91
95
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
96
|
+
const currentPhase = stateTracker?.getCurrentPhase(pkg.name);
|
|
97
|
+
const failedPhase =
|
|
98
|
+
currentPhase && currentPhase !== 'pending' && currentPhase !== 'passed' && currentPhase !== 'failed'
|
|
99
|
+
? currentPhase
|
|
100
|
+
: undefined;
|
|
92
101
|
return {
|
|
93
102
|
packageName: pkg.name,
|
|
94
103
|
success: false,
|
|
95
104
|
logs: '',
|
|
96
105
|
durationMs: Date.now() - startMs,
|
|
97
106
|
error: errorMessage,
|
|
107
|
+
failedPhase,
|
|
98
108
|
} as TResult;
|
|
99
109
|
}
|
|
100
110
|
};
|
|
@@ -33,11 +33,23 @@ export async function uploadPlaceAsync(
|
|
|
33
33
|
const apiKey = await getApiKeyAsync(args);
|
|
34
34
|
|
|
35
35
|
reporter?.onPackagePhaseChange(packageName ?? '', 'uploading');
|
|
36
|
+
|
|
37
|
+
const onProgress = reporter && packageName
|
|
38
|
+
? (transferred: number, total: number) => {
|
|
39
|
+
reporter.onPackageProgressUpdate(packageName, {
|
|
40
|
+
kind: 'bytes',
|
|
41
|
+
transferredBytes: transferred,
|
|
42
|
+
totalBytes: total,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
: undefined;
|
|
46
|
+
|
|
36
47
|
const version = await client.uploadPlaceAsync(
|
|
37
48
|
target.universeId,
|
|
38
49
|
target.placeId,
|
|
39
50
|
rbxlPath,
|
|
40
|
-
args.publish
|
|
51
|
+
args.publish,
|
|
52
|
+
onProgress
|
|
41
53
|
);
|
|
42
54
|
|
|
43
55
|
return { client, apiKey, target, version };
|
|
@@ -44,15 +44,17 @@ class TrackedBuiltPlace implements BuiltPlace {
|
|
|
44
44
|
* — even when individual deployments fail.
|
|
45
45
|
*/
|
|
46
46
|
export abstract class BaseJobContext implements JobContext {
|
|
47
|
+
protected _reporter: Reporter;
|
|
47
48
|
protected _openCloudClient: OpenCloudClient | undefined;
|
|
48
49
|
private _builtPlaces = new Set<TrackedBuiltPlace>();
|
|
49
50
|
|
|
50
|
-
constructor(openCloudClient?: OpenCloudClient) {
|
|
51
|
+
constructor(reporter: Reporter, openCloudClient?: OpenCloudClient) {
|
|
52
|
+
this._reporter = reporter;
|
|
51
53
|
this._openCloudClient = openCloudClient;
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
async buildPlaceAsync(options: BuildPlaceOptions): Promise<BuiltPlace> {
|
|
55
|
-
const result = await buildPlaceAsync(options);
|
|
57
|
+
const result = await buildPlaceAsync({ ...options, reporter: this._reporter });
|
|
56
58
|
const tracked = new TrackedBuiltPlace(result.rbxlPath, result.target, result.buildContext);
|
|
57
59
|
this._builtPlaces.add(tracked);
|
|
58
60
|
|
|
@@ -76,7 +78,7 @@ export abstract class BaseJobContext implements JobContext {
|
|
|
76
78
|
|
|
77
79
|
const resolvedName = options.packageName ?? '';
|
|
78
80
|
|
|
79
|
-
|
|
81
|
+
this._reporter.onPackagePhaseChange(resolvedName, 'downloading');
|
|
80
82
|
OutputHelper.verbose('Downloading base place for merge...');
|
|
81
83
|
const buffer = await this._openCloudClient.downloadPlaceAsync(
|
|
82
84
|
basePlace.universeId,
|
|
@@ -85,7 +87,7 @@ export abstract class BaseJobContext implements JobContext {
|
|
|
85
87
|
const basePath = buildContext.resolvePath('base.rbxl');
|
|
86
88
|
await fs.writeFile(basePath, buffer);
|
|
87
89
|
|
|
88
|
-
|
|
90
|
+
this._reporter.onPackagePhaseChange(resolvedName, 'merging');
|
|
89
91
|
const packagePath = options.packagePath ?? process.cwd();
|
|
90
92
|
const projectPath = path.resolve(packagePath, tracked.target.project);
|
|
91
93
|
const mergedPath = buildContext.resolvePath('merged.rbxl');
|
|
@@ -111,8 +113,8 @@ export abstract class BaseJobContext implements JobContext {
|
|
|
111
113
|
this._builtPlaces.delete(tracked);
|
|
112
114
|
}
|
|
113
115
|
|
|
114
|
-
abstract deployBuiltPlaceAsync(
|
|
115
|
-
abstract runScriptAsync(deployment: Deployment,
|
|
116
|
+
abstract deployBuiltPlaceAsync(options: DeployPlaceOptions): Promise<Deployment>;
|
|
117
|
+
abstract runScriptAsync(deployment: Deployment, options: RunScriptOptions): Promise<ScriptRunResult>;
|
|
116
118
|
abstract getLogsAsync(deployment: Deployment): Promise<string>;
|
|
117
119
|
abstract releaseAsync(deployment: Deployment): Promise<void>;
|
|
118
120
|
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from '../build/deploy-config.js';
|
|
24
24
|
import { type TargetPackage } from '../batch/changed-packages-utils.js';
|
|
25
25
|
import {
|
|
26
|
+
type CombinedBuildProgress,
|
|
26
27
|
type CombinedProjectResult,
|
|
27
28
|
generateCombinedProjectAsync,
|
|
28
29
|
} from '../testing/runner/combined-project-generator.js';
|
|
@@ -57,6 +58,7 @@ export class BatchScriptJobContext implements JobContext {
|
|
|
57
58
|
private _batchPlaceId?: number;
|
|
58
59
|
private _batchUniverseId?: number;
|
|
59
60
|
private _perPackageTimeoutMs: number;
|
|
61
|
+
private _reporter?: Reporter;
|
|
60
62
|
|
|
61
63
|
// Lazy-promise state
|
|
62
64
|
private _combinedBuildPromise?: Promise<CombinedBuildState>;
|
|
@@ -76,6 +78,7 @@ export class BatchScriptJobContext implements JobContext {
|
|
|
76
78
|
batchPlaceId?: number;
|
|
77
79
|
batchUniverseId?: number;
|
|
78
80
|
perPackageTimeoutMs?: number;
|
|
81
|
+
reporter?: Reporter;
|
|
79
82
|
}
|
|
80
83
|
) {
|
|
81
84
|
this._inner = inner;
|
|
@@ -84,6 +87,7 @@ export class BatchScriptJobContext implements JobContext {
|
|
|
84
87
|
this._batchPlaceId = options?.batchPlaceId;
|
|
85
88
|
this._batchUniverseId = options?.batchUniverseId;
|
|
86
89
|
this._perPackageTimeoutMs = options?.perPackageTimeoutMs ?? 120_000;
|
|
90
|
+
this._reporter = options?.reporter;
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
async buildPlaceAsync(options: BuildPlaceOptions): Promise<BuiltPlace> {
|
|
@@ -109,17 +113,15 @@ export class BatchScriptJobContext implements JobContext {
|
|
|
109
113
|
}
|
|
110
114
|
|
|
111
115
|
async deployBuiltPlaceAsync(
|
|
112
|
-
reporter: Reporter,
|
|
113
116
|
options: DeployPlaceOptions
|
|
114
117
|
): Promise<Deployment> {
|
|
115
|
-
const innerDeployment = await this._getSharedDeploymentAsync(
|
|
118
|
+
const innerDeployment = await this._getSharedDeploymentAsync();
|
|
116
119
|
|
|
117
120
|
return new BatchDeployment(options.packageName, innerDeployment);
|
|
118
121
|
}
|
|
119
122
|
|
|
120
123
|
async runScriptAsync(
|
|
121
124
|
deployment: Deployment,
|
|
122
|
-
_reporter: Reporter,
|
|
123
125
|
options: RunScriptOptions
|
|
124
126
|
): Promise<ScriptRunResult> {
|
|
125
127
|
const batchDeployment = deployment as BatchDeployment;
|
|
@@ -183,11 +185,42 @@ export class BatchScriptJobContext implements JobContext {
|
|
|
183
185
|
private async _doCombinedBuildAsync(): Promise<CombinedBuildState> {
|
|
184
186
|
OutputHelper.verbose('Building combined batch place...');
|
|
185
187
|
|
|
188
|
+
// Set all packages to "waiting" — they're queued for building
|
|
189
|
+
if (this._reporter) {
|
|
190
|
+
for (const pkg of this._packages) {
|
|
191
|
+
this._reporter.onPackagePhaseChange(pkg.name, 'waiting');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const progress: CombinedBuildProgress = {
|
|
196
|
+
onPackageBuildStart: (name) => {
|
|
197
|
+
this._reporter?.onPackagePhaseChange(name, 'building');
|
|
198
|
+
},
|
|
199
|
+
onPackageBuildComplete: (name) => {
|
|
200
|
+
this._reporter?.onPackagePhaseChange(name, 'waiting');
|
|
201
|
+
},
|
|
202
|
+
onCombineStart: () => {
|
|
203
|
+
if (this._reporter) {
|
|
204
|
+
for (const pkg of this._packages) {
|
|
205
|
+
this._reporter.onPackagePhaseChange(pkg.name, 'combining');
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
onStepProgress: (stepProgress) => {
|
|
210
|
+
if (this._reporter) {
|
|
211
|
+
for (const pkg of this._packages) {
|
|
212
|
+
this._reporter.onPackageProgressUpdate(pkg.name, stepProgress);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
|
|
186
218
|
const combinedResult = await generateCombinedProjectAsync({
|
|
187
219
|
packages: this._packages,
|
|
188
220
|
repoRoot: this._repoRoot,
|
|
189
221
|
batchPlaceId: this._batchPlaceId,
|
|
190
222
|
batchUniverseId: this._batchUniverseId,
|
|
223
|
+
progress,
|
|
191
224
|
});
|
|
192
225
|
|
|
193
226
|
this._combinedBuildContext = combinedResult.buildContext;
|
|
@@ -195,26 +228,23 @@ export class BatchScriptJobContext implements JobContext {
|
|
|
195
228
|
return { combinedResult, rbxlPath: combinedResult.rbxlPath };
|
|
196
229
|
}
|
|
197
230
|
|
|
198
|
-
private _getSharedDeploymentAsync(
|
|
231
|
+
private _getSharedDeploymentAsync(): Promise<Deployment> {
|
|
199
232
|
if (!this._deployPromise) {
|
|
200
|
-
this._deployPromise = this._doSharedDeployAsync(
|
|
233
|
+
this._deployPromise = this._doSharedDeployAsync();
|
|
201
234
|
}
|
|
202
235
|
return this._deployPromise;
|
|
203
236
|
}
|
|
204
237
|
|
|
205
|
-
private async _doSharedDeployAsync(
|
|
238
|
+
private async _doSharedDeployAsync(): Promise<Deployment> {
|
|
206
239
|
const buildState = await this._getCombinedBuildAsync();
|
|
207
240
|
const { primaryTarget } = buildState.combinedResult;
|
|
208
241
|
|
|
209
|
-
// Create a minimal reporter that doesn't emit per-package phases
|
|
210
|
-
const batchReporter = reporter ?? _noopReporter();
|
|
211
|
-
|
|
212
242
|
const builtPlace: BuiltPlace = {
|
|
213
243
|
rbxlPath: buildState.rbxlPath,
|
|
214
244
|
target: primaryTarget,
|
|
215
245
|
};
|
|
216
246
|
|
|
217
|
-
const deployment = await this._inner.deployBuiltPlaceAsync(
|
|
247
|
+
const deployment = await this._inner.deployBuiltPlaceAsync({
|
|
218
248
|
builtPlace,
|
|
219
249
|
packageName: '_batch_',
|
|
220
250
|
packagePath: this._repoRoot,
|
|
@@ -265,7 +295,6 @@ export class BatchScriptJobContext implements JobContext {
|
|
|
265
295
|
|
|
266
296
|
const result = await this._inner.runScriptAsync(
|
|
267
297
|
deployment,
|
|
268
|
-
_noopReporter(),
|
|
269
298
|
{
|
|
270
299
|
scriptContent: batchScript,
|
|
271
300
|
packageName: '_batch_',
|
|
@@ -287,13 +316,3 @@ export class BatchScriptJobContext implements JobContext {
|
|
|
287
316
|
return parseBatchTestLogs(rawLogs, slugMap);
|
|
288
317
|
}
|
|
289
318
|
}
|
|
290
|
-
|
|
291
|
-
function _noopReporter(): Reporter {
|
|
292
|
-
return {
|
|
293
|
-
onPackageStart: () => {},
|
|
294
|
-
onPackagePhaseChange: () => {},
|
|
295
|
-
onPackageResult: () => {},
|
|
296
|
-
startAsync: async () => {},
|
|
297
|
-
stopAsync: async () => {},
|
|
298
|
-
};
|
|
299
|
-
}
|