@isentinel/jest-roblox 0.3.9 → 0.3.10
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/dist/cli.mjs +1 -1
- package/dist/index.d.mts +19 -3
- package/dist/index.mjs +1 -1
- package/dist/{run-BM5sqclu.mjs → run-BKP7mem2.mjs} +62 -3
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as parseGameOutput, J as formatBanner, N as outputMultiResult, P as outputSingleResult, bt as version, ct as loadConfig, ht as VALID_BACKENDS, n as runJestRoblox, st as mergeCliWithConfig, tt as LuauScriptError, v as formatMissingScopes, vt as isValidBackend, y as walkErrorChain, yt as ConfigError } from "./run-
|
|
1
|
+
import { B as parseGameOutput, J as formatBanner, N as outputMultiResult, P as outputSingleResult, bt as version, ct as loadConfig, ht as VALID_BACKENDS, n as runJestRoblox, st as mergeCliWithConfig, tt as LuauScriptError, v as formatMissingScopes, vt as isValidBackend, y as walkErrorChain, yt as ConfigError } from "./run-BKP7mem2.mjs";
|
|
2
2
|
import { OpenCloudError } from "@bedrock-rbx/ocale";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { parseArgs as parseArgs$1 } from "node:util";
|
package/dist/index.d.mts
CHANGED
|
@@ -461,9 +461,25 @@ interface OpenCloudOptions {
|
|
|
461
461
|
}
|
|
462
462
|
declare class OpenCloudBackend implements Backend {
|
|
463
463
|
private readonly runner;
|
|
464
|
-
|
|
464
|
+
/** One-shot per run so parallel raced tasks don't repeat the warning. */
|
|
465
|
+
private raceWarned;
|
|
466
|
+
readonly kind: "open-cloud";
|
|
465
467
|
constructor(credentials: OpenCloudCredentials, options?: OpenCloudOptions);
|
|
466
468
|
runTests(options: BackendOptions): Promise<BackendResult>;
|
|
469
|
+
/**
|
|
470
|
+
* Optimistic version pinning. Pinned tasks
|
|
471
|
+
* (`/versions/{v}/luau-execution-session-tasks`) miss the warm-server pool
|
|
472
|
+
* whenever no server holds the freshly-uploaded version yet, costing a cold
|
|
473
|
+
* place boot per task (~10-45s, scaling with place size). Unpinned tasks
|
|
474
|
+
* boot the latest saved version from the warm pool, so the first attempt
|
|
475
|
+
* runs unpinned with a guard prepended: if the booted server is not on this
|
|
476
|
+
* run's version (a concurrent upload won the boot race), the task returns
|
|
477
|
+
* {@link PLACE_VERSION_RACE_SENTINEL} instead of running. On the sentinel,
|
|
478
|
+
* the task is retried once, pinned — correct by construction, no re-upload
|
|
479
|
+
* (the version exists even when it is no longer head), and no unpinned
|
|
480
|
+
* retry loop for a concurrent uploader to keep winning against.
|
|
481
|
+
*/
|
|
482
|
+
private executeGuarded;
|
|
467
483
|
private runBucket;
|
|
468
484
|
private runStaticBuckets;
|
|
469
485
|
private runWorkStealing;
|
|
@@ -606,7 +622,7 @@ declare class StudioCliBackend implements Backend {
|
|
|
606
622
|
private readonly launch;
|
|
607
623
|
private readonly studioPath?;
|
|
608
624
|
private readonly timeout;
|
|
609
|
-
readonly kind
|
|
625
|
+
readonly kind: "studio-cli";
|
|
610
626
|
constructor(options?: StudioCliOptions);
|
|
611
627
|
runTests(options: BackendOptions): Promise<BackendResult>;
|
|
612
628
|
/**
|
|
@@ -635,7 +651,7 @@ declare class StudioBackend implements Backend {
|
|
|
635
651
|
private readonly timeout;
|
|
636
652
|
private preConnected?;
|
|
637
653
|
private wss?;
|
|
638
|
-
readonly kind
|
|
654
|
+
readonly kind: "studio";
|
|
639
655
|
constructor(options: StudioOptions);
|
|
640
656
|
close(): void;
|
|
641
657
|
runTests(options: BackendOptions): Promise<BackendResult>;
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as writeManifest, A as buildManifestSchema, B as parseGameOutput, C as COVERAGE_MANIFEST_PATH, D as visitStatement, E as visitExpression, F as formatAnnotations, G as formatFailure, H as createTimingCollector, I as formatJobSummary, K as formatResult, L as formatExecuteOutput, M as readBuildManifest, O as buildPlace, Q as readManifest, R as runProjects, S as COVERAGE_BUILD_MANIFEST_PATH, T as visitBlock, U as formatJson, V as writeGameOutput, W as writeJsonFile, X as MANIFEST_VERSION, Y as hashFile, Z as manifestSchema, _ as createOpenCloudBackend, _t as defineProject, a as collectStubMounts, at as parseCoverageEnvelope, b as buildJestArgv, c as runTypecheck, ct as loadConfig, d as resolveAllProjects, dt as GLOBAL_TEST_KEYS, et as applyAttribution, f as StudioBackend, ft as JEST_ARGV_EXCLUDED_KEYS, g as OpenCloudBackend, gt as defineConfig, h as createStudioCliBackend, i as buildImplicitProject, it as normalizeRawCoverage, j as emitBuildManifest, k as BUILD_MANIFEST_VERSION, l as cleanLeftoverStubs, lt as resolveConfig, m as StudioCliBackend, mt as SHARED_TEST_KEYS, n as runJestRoblox, nt as extractJsonFromOutput, o as loadRojoTree, ot as mergeRawCoverage, p as createStudioBackend, pt as ROOT_CLI_KEYS, q as formatTestSummary, r as runSingleOrMulti, rt as parseJestOutput, s as prepareBakedCoverage, st as mergeCliWithConfig, t as getRawProjects, u as generateProjectStubs, ut as DEFAULT_CONFIG, w as findRojoProject, x as generateTestScript, z as formatGameOutputNotice } from "./run-
|
|
1
|
+
import { $ as writeManifest, A as buildManifestSchema, B as parseGameOutput, C as COVERAGE_MANIFEST_PATH, D as visitStatement, E as visitExpression, F as formatAnnotations, G as formatFailure, H as createTimingCollector, I as formatJobSummary, K as formatResult, L as formatExecuteOutput, M as readBuildManifest, O as buildPlace, Q as readManifest, R as runProjects, S as COVERAGE_BUILD_MANIFEST_PATH, T as visitBlock, U as formatJson, V as writeGameOutput, W as writeJsonFile, X as MANIFEST_VERSION, Y as hashFile, Z as manifestSchema, _ as createOpenCloudBackend, _t as defineProject, a as collectStubMounts, at as parseCoverageEnvelope, b as buildJestArgv, c as runTypecheck, ct as loadConfig, d as resolveAllProjects, dt as GLOBAL_TEST_KEYS, et as applyAttribution, f as StudioBackend, ft as JEST_ARGV_EXCLUDED_KEYS, g as OpenCloudBackend, gt as defineConfig, h as createStudioCliBackend, i as buildImplicitProject, it as normalizeRawCoverage, j as emitBuildManifest, k as BUILD_MANIFEST_VERSION, l as cleanLeftoverStubs, lt as resolveConfig, m as StudioCliBackend, mt as SHARED_TEST_KEYS, n as runJestRoblox, nt as extractJsonFromOutput, o as loadRojoTree, ot as mergeRawCoverage, p as createStudioBackend, pt as ROOT_CLI_KEYS, q as formatTestSummary, r as runSingleOrMulti, rt as parseJestOutput, s as prepareBakedCoverage, st as mergeCliWithConfig, t as getRawProjects, u as generateProjectStubs, ut as DEFAULT_CONFIG, w as findRojoProject, x as generateTestScript, z as formatGameOutputNotice } from "./run-BKP7mem2.mjs";
|
|
2
2
|
import * as path$1 from "node:path";
|
|
3
3
|
//#region src/artifacts/build-coverage-place.ts
|
|
4
4
|
const CACHE_DIR$1 = path$1.join(".jest-roblox", "cache");
|
|
@@ -36,7 +36,7 @@ import { once } from "node:events";
|
|
|
36
36
|
import { parseJSONC, parseYAML } from "confbox";
|
|
37
37
|
import { Visitor, parseSync } from "oxc-parser";
|
|
38
38
|
//#region package.json
|
|
39
|
-
var version = "0.3.
|
|
39
|
+
var version = "0.3.10";
|
|
40
40
|
//#endregion
|
|
41
41
|
//#region src/config/errors.ts
|
|
42
42
|
var ConfigError = class extends Error {
|
|
@@ -7554,6 +7554,15 @@ function readStringProperty(err, key) {
|
|
|
7554
7554
|
}
|
|
7555
7555
|
//#endregion
|
|
7556
7556
|
//#region src/backends/open-cloud.ts
|
|
7557
|
+
/**
|
|
7558
|
+
* The value the version guard returns when the booted server is not running
|
|
7559
|
+
* the version this run uploaded — i.e. a concurrent upload won the boot race.
|
|
7560
|
+
* The backend retries that task once, pinned to the uploaded version.
|
|
7561
|
+
*
|
|
7562
|
+
* Embedded verbatim in a Luau double-quoted string literal, so it must not
|
|
7563
|
+
* contain backslashes, double quotes, or newlines.
|
|
7564
|
+
*/
|
|
7565
|
+
const PLACE_VERSION_RACE_SENTINEL = "__JEST_ROBLOX_PLACE_VERSION_RACE__";
|
|
7557
7566
|
const PARALLEL_AUTO_CAP = 3;
|
|
7558
7567
|
const BASE_URL_ENV = "JEST_ROBLOX_OPEN_CLOUD_BASE_URL";
|
|
7559
7568
|
const MAX_RETRIES_ENV = "JEST_ROBLOX_OCALE_MAX_RETRIES";
|
|
@@ -7561,11 +7570,14 @@ const DEFAULT_STREAM_POLL_MS = 250;
|
|
|
7561
7570
|
const TrailingSlashesPattern = /\/+$/;
|
|
7562
7571
|
var OpenCloudBackend = class {
|
|
7563
7572
|
runner;
|
|
7573
|
+
/** One-shot per run so parallel raced tasks don't repeat the warning. */
|
|
7574
|
+
raceWarned = false;
|
|
7564
7575
|
kind = "open-cloud";
|
|
7565
7576
|
constructor(credentials, options) {
|
|
7566
7577
|
this.runner = options?.runner ?? new OcaleRunner(credentials, resolveRunnerOptions());
|
|
7567
7578
|
}
|
|
7568
7579
|
async runTests(options) {
|
|
7580
|
+
this.raceWarned = false;
|
|
7569
7581
|
const { jobs, parallel, scriptOverride, streaming, workStealing } = options;
|
|
7570
7582
|
if (jobs.length === 0) throw new Error("OpenCloudBackend requires at least one job");
|
|
7571
7583
|
if (workStealing === true && scriptOverride === void 0) throw new Error("OpenCloudBackend work-stealing mode requires scriptOverride");
|
|
@@ -7588,6 +7600,37 @@ var OpenCloudBackend = class {
|
|
|
7588
7600
|
}
|
|
7589
7601
|
};
|
|
7590
7602
|
}
|
|
7603
|
+
/**
|
|
7604
|
+
* Optimistic version pinning. Pinned tasks
|
|
7605
|
+
* (`/versions/{v}/luau-execution-session-tasks`) miss the warm-server pool
|
|
7606
|
+
* whenever no server holds the freshly-uploaded version yet, costing a cold
|
|
7607
|
+
* place boot per task (~10-45s, scaling with place size). Unpinned tasks
|
|
7608
|
+
* boot the latest saved version from the warm pool, so the first attempt
|
|
7609
|
+
* runs unpinned with a guard prepended: if the booted server is not on this
|
|
7610
|
+
* run's version (a concurrent upload won the boot race), the task returns
|
|
7611
|
+
* {@link PLACE_VERSION_RACE_SENTINEL} instead of running. On the sentinel,
|
|
7612
|
+
* the task is retried once, pinned — correct by construction, no re-upload
|
|
7613
|
+
* (the version exists even when it is no longer head), and no unpinned
|
|
7614
|
+
* retry loop for a concurrent uploader to keep winning against.
|
|
7615
|
+
*/
|
|
7616
|
+
async executeGuarded(options) {
|
|
7617
|
+
const { placeVersion, script, timeout } = options;
|
|
7618
|
+
const guarded = injectVersionGuard(script, placeVersion);
|
|
7619
|
+
const first = await this.runner.executeScript({
|
|
7620
|
+
script: guarded,
|
|
7621
|
+
timeout
|
|
7622
|
+
});
|
|
7623
|
+
if (first.outputs[0] !== "__JEST_ROBLOX_PLACE_VERSION_RACE__") return first;
|
|
7624
|
+
if (!this.raceWarned) {
|
|
7625
|
+
this.raceWarned = true;
|
|
7626
|
+
process.stderr.write("Warning: place version raced by a concurrent upload — raced tasks retried pinned (slower, cold place boot).\n");
|
|
7627
|
+
}
|
|
7628
|
+
return this.runner.executeScript({
|
|
7629
|
+
placeVersion,
|
|
7630
|
+
script,
|
|
7631
|
+
timeout
|
|
7632
|
+
});
|
|
7633
|
+
}
|
|
7591
7634
|
async runBucket(bucket, placeVersion, scriptOverride) {
|
|
7592
7635
|
const { indices, jobs } = bucket;
|
|
7593
7636
|
const primary = jobs[0];
|
|
@@ -7598,7 +7641,7 @@ var OpenCloudBackend = class {
|
|
|
7598
7641
|
};
|
|
7599
7642
|
});
|
|
7600
7643
|
const script = scriptOverride ?? generateTestScript(inputs);
|
|
7601
|
-
const scriptResult = await this.
|
|
7644
|
+
const scriptResult = await this.executeGuarded({
|
|
7602
7645
|
placeVersion,
|
|
7603
7646
|
script,
|
|
7604
7647
|
timeout: primary.config.timeout
|
|
@@ -7643,7 +7686,7 @@ var OpenCloudBackend = class {
|
|
|
7643
7686
|
},
|
|
7644
7687
|
places: [{ runTask: async () => {
|
|
7645
7688
|
launched += 1;
|
|
7646
|
-
return this.
|
|
7689
|
+
return this.executeGuarded({
|
|
7647
7690
|
placeVersion,
|
|
7648
7691
|
script: scriptOverride,
|
|
7649
7692
|
timeout: primaryConfig.timeout
|
|
@@ -7743,6 +7786,22 @@ async function sleep(ms) {
|
|
|
7743
7786
|
setTimeout(resolve, ms);
|
|
7744
7787
|
});
|
|
7745
7788
|
}
|
|
7789
|
+
/**
|
|
7790
|
+
* Insert the version guard after any leading `--!` directive lines — Luau
|
|
7791
|
+
* honors directives only in the leading comment block, so a plain line-1
|
|
7792
|
+
* prepend would silently disable a caller's `--!strict`/`--!native`/etc.
|
|
7793
|
+
*/
|
|
7794
|
+
function injectVersionGuard(script, placeVersion) {
|
|
7795
|
+
const guard = `if game.PlaceVersion ~= ${String(placeVersion)} then return "${PLACE_VERSION_RACE_SENTINEL}" end`;
|
|
7796
|
+
const lines = script.split("\n");
|
|
7797
|
+
let insertAt = 0;
|
|
7798
|
+
for (const line of lines) {
|
|
7799
|
+
if (!line.startsWith("--!")) break;
|
|
7800
|
+
insertAt += 1;
|
|
7801
|
+
}
|
|
7802
|
+
lines.splice(insertAt, 0, guard);
|
|
7803
|
+
return lines.join("\n");
|
|
7804
|
+
}
|
|
7746
7805
|
function resolveRunnerOptions() {
|
|
7747
7806
|
const baseUrl = resolveOpenCloudBaseUrl();
|
|
7748
7807
|
const maxRetries = resolveOcaleMaxRetries();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@isentinel/jest-roblox",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
4
4
|
"description": "Jest-compatible CLI for running roblox-ts tests via Roblox Open Cloud",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jest",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"!dist/**/*.tsbuildinfo"
|
|
49
49
|
],
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@bedrock-rbx/ocale": "0.1.0
|
|
51
|
+
"@bedrock-rbx/ocale": "0.1.0",
|
|
52
52
|
"@jridgewell/trace-mapping": "0.3.31",
|
|
53
53
|
"arktype": "2.2.0",
|
|
54
54
|
"c12": "4.0.0-beta.5",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@isentinel/eslint-config": "6.0.0-beta.3",
|
|
70
|
-
"@isentinel/roblox-ts": "4.0.
|
|
70
|
+
"@isentinel/roblox-ts": "4.0.11",
|
|
71
71
|
"@isentinel/tsconfig": "1.2.0",
|
|
72
72
|
"@isentinel/weld": "0.2.0",
|
|
73
73
|
"@oxc-project/types": "0.123.0",
|