improve(ci): shorten complete lint and typecheck jobs (#154150)

* ci: reuse typecheck state and bound lint programs

* test: align compiler and code mode fixtures with current contracts
This commit is contained in:
Peter Steinberger 2026-09-21 10:11:25 -07:00 • committed by GitHub
parent 00ec0fbca4
commit 55ed23f278
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 307 additions and 23 deletions

View file

@ -3939,6 +3939,16 @@ jobs:
install-bun: "false"
dependency-cache: ${{ vars.OPENCLAW_CI_RUNNER_BACKEND != 'github' && runner.environment == 'self-hosted' && github.event_name != 'workflow_dispatch' && github.repository == 'openclaw/openclaw' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'openclaw/openclaw') && 'true' || 'false' }}
- name: Restore test-type incremental state
id: test-type-cache
if: matrix.task == 'test-types' && needs.preflight.outputs.cache_mode != 'off' && needs.preflight.outputs.frozen_target != 'true'
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .artifacts/tsgo-cache
key: ${{ runner.os }}-${{ runner.arch }}-tsgo-v1-${{ matrix.task }}-${{ hashFiles('pnpm-lock.yaml', 'tsconfig*.json', 'test/tsconfig/*.json', 'scripts/run-tsgo*', 'scripts/lib/local-check-runtime.mts') }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-${{ runner.arch }}-tsgo-v1-${{ matrix.task }}-${{ hashFiles('pnpm-lock.yaml', 'tsconfig*.json', 'test/tsconfig/*.json', 'scripts/run-tsgo*', 'scripts/lib/local-check-runtime.mts') }}-
- name: Compute extension boundary input fingerprint
id: extension-boundary-inputs
if: matrix.task == 'lint'
@ -4279,6 +4289,14 @@ jobs:
;;
esac
- name: Save test-type incremental state
if: success() && matrix.task == 'test-types' && needs.preflight.outputs.cache_write_allowed == 'true' && needs.preflight.outputs.cache_mode != 'off' && needs.preflight.outputs.frozen_target != 'true' && steps.test-type-cache.outputs.cache-hit != 'true'
continue-on-error: true
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .artifacts/tsgo-cache
key: ${{ steps.test-type-cache.outputs.cache-primary-key }}
# Keep five core stripes; the runner isolates large targets into serial child processes.
# Ordinary hybrid runs serialize the stripes across two hosted jobs.
# GitHub, frozen and manual runs retain five jobs. All-Blacksmith keeps one lint job.
@ -4371,7 +4389,7 @@ jobs:
done
# Pair four original core stripes; check-test-types owns the fifth and its tail.
# Each stripe retains fresh compiler processes and its two-child limit;
# Each row retains fresh compiler processes and its two-child limit;
# all-Blacksmith mode uses one 16-vCPU test-types job for the full workload.
check-test-types-hosted-core-shard:
permissions:
@ -4396,7 +4414,19 @@ jobs:
install-bun: "false"
dependency-cache: ${{ vars.OPENCLAW_CI_RUNNER_BACKEND != 'github' && runner.environment == 'self-hosted' && github.event_name != 'workflow_dispatch' && github.repository == 'openclaw/openclaw' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'openclaw/openclaw') && 'true' || 'false' }}
- name: Restore core test-type incremental state
id: test-type-cache
if: needs.preflight.outputs.cache_mode != 'off' && needs.preflight.outputs.frozen_target != 'true'
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .artifacts/tsgo-cache
key: ${{ runner.os }}-${{ runner.arch }}-tsgo-v1-core-${{ matrix.stripe }}-${{ hashFiles('pnpm-lock.yaml', 'tsconfig*.json', 'test/tsconfig/*.json', 'scripts/run-tsgo*', 'scripts/lib/local-check-runtime.mts') }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-${{ runner.arch }}-tsgo-v1-core-${{ matrix.stripe }}-${{ hashFiles('pnpm-lock.yaml', 'tsconfig*.json', 'test/tsconfig/*.json', 'scripts/run-tsgo*', 'scripts/lib/local-check-runtime.mts') }}-
- name: Run hosted core test-types stripe
env:
FROZEN_TARGET: ${{ needs.preflight.outputs.frozen_target }}
shell: bash
run: |
set -euo pipefail
@ -4406,9 +4436,24 @@ jobs:
echo "[skip] target does not support core test-type stripes"
exit 0
fi
for stripe in "$((2 * ${{ matrix.stripe }} - 1))" "$((2 * ${{ matrix.stripe }}))"; do
node scripts/run-tsgo-core-test-shards.mjs --stripe "$stripe/5" --concurrency 2
done
first="$((2 * ${{ matrix.stripe }} - 1))"
last="$((2 * ${{ matrix.stripe }}))"
if [ "$FROZEN_TARGET" = "true" ]; then
for stripe in "$first" "$last"; do
node scripts/run-tsgo-core-test-shards.mjs --stripe "$stripe/5" --concurrency 2
done
else
# One queue fills an idle slot across the former stripe barrier.
node scripts/run-tsgo-core-test-shards.mjs --stripe "$first-$last/5" --concurrency 2
fi
- name: Save core test-type incremental state
if: success() && needs.preflight.outputs.cache_write_allowed == 'true' && needs.preflight.outputs.cache_mode != 'off' && needs.preflight.outputs.frozen_target != 'true' && steps.test-type-cache.outputs.cache-hit != 'true'
continue-on-error: true
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .artifacts/tsgo-cache
key: ${{ steps.test-type-cache.outputs.cache-primary-key }}
check-additional-shard:
permissions:

View file

@ -17,7 +17,7 @@ Docs-only `main` pushes skip CI and cache warming. The cache warmer publishes de
Core-test-only PRs use targeted type checks only when every selected test exists in the checkout. Deleting a core test keeps the full type-check plan, including the existing core stripes on GitHub and hybrid profiles.
Core lint includes `src/**/*.test-support.cjs` in type-aware checks through the bounded `src/tsconfig.json` discovery project. Other source files retain the root TypeScript project; unrelated JavaScript files are not added to this test-support project.
Core lint discovers separate source and UI TypeScript projects, retaining shared ambient declarations and imported dependencies. The source project also includes `src/**/*.test-support.cjs`; unrelated JavaScript files are not added as roots. See [local checks](/ci/local-proof#local-equivalents).
Android native resource preparation uses the Mermaid renderer's filtered dependency install, including optional build tooling. Pnpm retains root dependencies but omits unrelated plugin packages; Gradle still builds the assets and runs the selected native tests and lint. Historical targets keep their compatibility path.

View file

@ -24,6 +24,25 @@ local runs, Windows, explicit plugin stripes, and explicit serial selections kee
eight-directory chunks. Explicit split-core and parallel execution selections
remain unchanged.
Oxlint's type-aware backend discovers `src/tsconfig.json` and `ui/tsconfig.json`
separately. Both inherit the root compiler options, include shared ambient
declarations, and follow imported dependencies. Every existing lint target and
rule still runs, including source CommonJS test preloads. The CLI `--tsconfig`
option controls import resolution; it does not replace these discovery projects.
Current CI core-test rows combine their paired stripes into one queue of fresh
compiler processes, with the same two-child limit. Each independent graph runs
in incremental project mode: solution-build mode can miss an added root whose
timestamp predates restored build information. Frozen targets keep their
original stripe invocations. Per-graph elapsed times appear in the job log.
The test-type jobs restore their own `.artifacts/tsgo-cache` state across runs.
Cache keys separate compiler/dependency/configuration versions and CI rows;
the compiler still validates every selected graph after a hit. Pull requests
only restore state, while the existing trusted cache writer policy controls
publication after successful checks. Cache-off and frozen-target runs retain
their original behavior. Lint programs do not share these compiler caches.
Oxlint keeps `eslint/no-redeclare` enabled for JavaScript. For `.ts`, `.tsx`,
`.mts`, and `.cts`, `tsgo` owns declaration validity, including intentional
type/value pairs with the same public name. `eslint/no-var` remains enabled

View file

@ -147,16 +147,24 @@ export function selectTsgoCoreTestShards(
export function selectTsgoCoreTestStripe(
stripeSpec: string,
): readonly { name: string; config: string }[] | undefined {
const match = /^([1-9]\d*)\/([1-9]\d*)$/u.exec(stripeSpec);
const match = /^([1-9]\d*)(?:-([1-9]\d*))?\/([1-9]\d*)$/u.exec(stripeSpec);
if (!match) {
return undefined;
}
const stripe = Number(match[1]);
const stripeCount = Number(match[2]);
if (stripe > stripeCount) {
const lastStripe = Number(match[2] ?? match[1]);
const stripeCount = Number(match[3]);
if (
![stripe, lastStripe, stripeCount].every(Number.isSafeInteger) ||
stripe > lastStripe ||
lastStripe > stripeCount
) {
return undefined;
}
return TSGO_CORE_TEST_SHARDS.filter((_, index) => index % stripeCount === stripe - 1);
return TSGO_CORE_TEST_SHARDS.filter((_, index) => {
const owner = (index % stripeCount) + 1;
return owner >= stripe && owner <= lastStripe;
});
}
export function findTsgoCoreTestShardViolations(params: {

View file

@ -26,7 +26,9 @@ function runShard(config: string, env: NodeJS.ProcessEnv): Promise<number> {
shell: false,
args: distArtifactEntryArgs(
path.join(repoRoot, "scripts/run-tsgo.mts"),
["-b", config, "--builders", "1"],
// These graphs have no project references. Project mode rechecks root
// membership even when a restored build-info file is newer than a new root.
["-p", config, "--incremental"],
{ native: true },
),
cwd: repoRoot,
@ -54,10 +56,14 @@ async function runTsgoCoreTestShards(
if (!shard || failureCode !== 0) {
return;
}
const startedAt = performance.now();
const code = await runShard(shard.config, env).catch((error: unknown) => {
failureCode = 1;
throw error;
});
console.error(
`[tsgo:${shard.name}] ${code === 0 ? "passed" : `failed (exit ${code})`} in ${((performance.now() - startedAt) / 1000).toFixed(1)}s`,
);
if (code !== 0 && failureCode === 0) {
failureCode = code;
}
@ -142,7 +148,7 @@ if (isDirectRunUrl(process.argv[1], import.meta.url)) {
const stripeSpec = process.argv[stripeFlagIndex + 1] ?? "";
shards = selectTsgoCoreTestStripe(stripeSpec);
if (!shards) {
console.error(`Invalid core test stripe (expected i/n): ${stripeSpec}`);
console.error(`Invalid core test stripe (expected i/n or first-last/n): ${stripeSpec}`);
process.exit(1);
}
} else {

View file

@ -3,6 +3,21 @@
"compilerOptions": {
"allowJs": true
},
// Oxlint discovers this project for CommonJS test preloads; other sources use the root project.
"include": ["**/*.test-support.cjs"]
// Keep lint's source graph separate from UI and plugins, including shared ambient types.
"include": [
"**/*.ts",
"**/*.tsx",
"**/*.mts",
"**/*.cts",
"**/*.test-support.cjs",
"../packages/**/*.d.ts",
"../packages/**/*.d.mts",
"../packages/**/*.d.cts",
"../ui/**/*.d.ts",
"../ui/**/*.d.mts",
"../ui/**/*.d.cts",
"../extensions/**/*.d.ts",
"../extensions/**/*.d.mts",
"../extensions/**/*.d.cts"
]
}

View file

@ -206,6 +206,7 @@ function evaluateWorkflowExpression(
);
return runInNewContext(evaluableSource, {
always: () => true,
success: () => !context.failed && !context.cancelled,
failure: () => context.failed ?? false,
cancelled: () => context.cancelled ?? false,
// GitHub expression builtins the runner-routing clauses use.
@ -2191,7 +2192,8 @@ function runCheckShardFixture(options: {
`import { appendFileSync } from "node:fs";
const args = process.argv.slice(2);
appendFileSync(process.env.TYPE_CALLS, [process.env.TYPE_ROW, process.env.OPENCLAW_LOCAL_CHECK ?? "<unset>", "node " + args.join(" ")].join("\\t") + "\\n");
if (args[args.indexOf("--stripe") + 1] === process.env.FAIL_TYPE_STRIPE) process.exit(17);
const stripe = args[args.indexOf("--stripe") + 1];
if (stripe === process.env.FAIL_TYPE_STRIPE || stripe?.replace(/-\\d+\\//, "/") === process.env.FAIL_TYPE_STRIPE) process.exit(17);
`,
);
}
@ -12948,6 +12950,61 @@ printf '%s\n' "\${CURL_SUCCESS_IP:-203.0.113.7}"
}
});
it("reuses isolated test-type caches without bypassing compilation or cache authority", () => {
const workflow = readCiWorkflow();
for (const [jobId, runName] of [
["check-shard", "Run check shard"],
["check-test-types-hosted-core-shard", "Run hosted core test-types stripe"],
] as const) {
const steps = workflow.jobs[jobId].steps as WorkflowStep[];
const restore = expectDefined(
steps.find((step) => step.id === "test-type-cache"),
`${jobId} compiler cache`,
);
const save = expectDefined(
steps.find(
(step) => step.name?.startsWith("Save") && step.with?.path === ".artifacts/tsgo-cache",
),
`${jobId} compiler cache writer`,
);
const run = expectDefined(
steps.find((step) => step.name === runName),
`${jobId} compiler`,
);
expect(steps.indexOf(restore)).toBeLessThan(steps.indexOf(run));
expect(steps.indexOf(save)).toBeGreaterThan(steps.indexOf(run));
expect(run.if).toBeUndefined();
expect(run.run).not.toContain("cache-hit");
expect(restore.with?.path).toBe(".artifacts/tsgo-cache");
expect(restore.with?.key).toContain("pnpm-lock.yaml");
expect(restore.with?.key).toContain("test/tsconfig/*.json");
expect(restore.with?.key).toContain(
jobId === "check-shard" ? "matrix.task" : "matrix.stripe",
);
expect(save.with?.key).toBe("${{ steps.test-type-cache.outputs.cache-primary-key }}");
for (const [cacheMode, writable, frozen, failed, canRestore, canSave] of [
["restore", false, false, false, true, false],
["restore", true, false, false, true, true],
["off", true, false, false, false, false],
["restore", true, true, false, false, false],
["restore", true, false, true, true, false],
] as const) {
const context: Parameters<typeof evaluateWorkflowExpression>[1] = {
eventName: writable ? "push" : "pull_request",
repository: "openclaw/openclaw",
runAttempt: 1,
frozenTarget: frozen,
failed,
matrix: { task: "test-types", stripe: 1 },
preflightOutputs: { cache_mode: cacheMode, cache_write_allowed: String(writable) },
steps: { "test-type-cache": { outputs: { "cache-hit": "false" } } },
};
expect(evaluateWorkflowExpression("${{ " + restore.if + " }}", context)).toBe(canRestore);
expect(evaluateWorkflowExpression("${{ " + save.if + " }}", context)).toBe(canSave);
}
}
});
it.each([
["hybrid", "pull_request", false, true, true, true],
["github", "workflow_dispatch", false, true, true, true],
@ -12976,7 +13033,11 @@ printf '%s\n' "\${CURL_SUCCESS_IP:-203.0.113.7}"
.filter((call) => call.row === row.name)
.map((call) => call.command.split(" ")[2]),
),
).toEqual([["1/5", "2/5"], ["3/5", "4/5"], ["5/5"]]);
).toEqual(
frozenTarget
? [["1/5", "2/5"], ["3/5", "4/5"], ["5/5"]]
: [["1-2/5"], ["3-4/5"], ["5/5"]],
);
for (const call of stripes) {
const args = call.command.split(" ").slice(1);
expect(args).toEqual(["--stripe", expect.any(String), "--concurrency", "2"]);
@ -13006,7 +13067,7 @@ printf '%s\n' "\${CURL_SUCCESS_IP:-203.0.113.7}"
expect(result.rows.filter((row) => row.status === 0)).toHaveLength(2);
expect(
result.typeCalls.filter((call) => call.row === failed[0]!.name).map((call) => call.command),
).toEqual([`node --stripe ${failStripe} --concurrency 2`]);
).toEqual([`node --stripe ${failStripe === "1/5" ? "1-2/5" : failStripe} --concurrency 2`]);
});
it.each(["main", "trunk/release"])(

View file

@ -372,7 +372,7 @@ describe("native check launchers in paths with spaces", () => {
);
expect(child.argv).toEqual(
compiler
? ["-b", TSGO_CORE_TEST_SHARDS[0].config, "--builders", "1"]
? ["-p", TSGO_CORE_TEST_SHARDS[0].config, "--incremental"]
: ["--mode=package-boundary"],
);
const lock = resolveDistArtifactLockPath(root);

View file

@ -939,8 +939,9 @@ describe("mock OpenAI response markers", () => {
}
});
it("resumes the MCP Code Mode fixture until the latest result completes", async () => {
await withMockServer(mockOpenAiPath, {}, async (baseUrl) => {
it.each(["current", "legacy"])("resumes the MCP Code Mode fixture (%s catalog)", async (mode) => {
const env = { OPENCLAW_FROZEN_TARGET_MCP_CODE_MODE_CATALOG_MODE: mode };
await withMockServer(mockOpenAiPath, env, async (baseUrl) => {
const input: Record<string, unknown>[] = [
{ content: "mcp code mode api file qa check", role: "user" },
];
@ -963,9 +964,13 @@ describe("mock OpenAI response markers", () => {
};
const first = await request();
expect(first.output?.[0]).toMatchObject({ name: "exec", type: "function_call" });
expect(JSON.parse(first.output[0].arguments)).toEqual({
const execArguments = JSON.parse(first.output[0].arguments);
expect(execArguments).toEqual({
code: expect.stringContaining('MCP.fixture.lookupNote({ id: "alpha" })'),
});
expect(execArguments.code).toContain(
mode === "legacy" ? "ALL_TOOLS.some(" : "catalog.all().some(",
);
for (const reason of ["pending_tools", "yield"]) {
input.push({

View file

@ -531,7 +531,6 @@ describe("MCP code-mode gateway Docker client result validation", () => {
id: "mcp-code-mode-exec",
name: "exec",
arguments: {
language: "javascript",
code: 'return await MCP.fixture.lookupNote({ id: "alpha" });',
},
},

View file

@ -362,6 +362,99 @@ describe("oxlint config", () => {
);
});
it("keeps source and UI lint projects bounded with imported and ambient types", () => {
const tempRoot = fs.realpathSync(createTempDir("openclaw-oxlint-core-projects-"));
for (const file of [
".oxlintrc.json",
"tsconfig.json",
"src/tsconfig.json",
"ui/tsconfig.json",
]) {
if (fs.existsSync(file)) {
const target = path.join(tempRoot, file);
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.copyFileSync(file, target);
}
}
fs.symlinkSync(path.resolve("node_modules"), path.join(tempRoot, "node_modules"), "junction");
const source = [
'import { work } from "../packages/imported.js";',
"work(); fromCore(); fromUi(); fromPackage(); fromPlugin(); fromMts(); fromCts();",
].join("\n");
for (const [file, content] of Object.entries({
"src/owner.ts": source,
"ui/owner.ts": source,
"packages/imported.ts": "export function work(): Promise<void> { return Promise.resolve(); }",
"src/contracts.d.ts": "declare function fromCore(): Promise<void>;",
"ui/contracts.d.ts": "declare function fromUi(): Promise<void>;",
"packages/contracts.d.ts": "declare function fromPackage(): Promise<void>;",
"extensions/contracts.d.ts": "declare function fromPlugin(): Promise<void>;",
"packages/contracts.d.mts":
"export {}; declare global { function fromMts(): Promise<void>; }",
"packages/contracts.d.cts":
"export {}; declare global { function fromCts(): Promise<void>; }",
})) {
const target = path.join(tempRoot, file);
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.writeFileSync(target, content);
}
const selected = ["src/owner.ts", "ui/owner.ts"];
const result = spawnSync(
process.execPath,
[
path.resolve("node_modules/oxlint/bin/oxlint"),
"--type-aware",
"--format",
"json",
"--threads=1",
...selected,
],
{
cwd: tempRoot,
encoding: "utf8",
timeout: 10_000,
env: {
...process.env,
OXC_LOG: "debug",
GOMAXPROCS: "2",
OXLINT_TSGOLINT_PATH: path.resolve(
"node_modules/.bin",
process.platform === "win32" ? "tsgolint.CMD" : "tsgolint",
),
},
},
);
expect(result.error).toBeUndefined();
expect(result.status, result.stderr).toBe(1);
const report = JSON.parse(result.stdout) as {
diagnostics: Array<{ filename: string; code: string }>;
};
for (const file of selected) {
expect(
report.diagnostics
.filter((diagnostic) => diagnostic.filename.replaceAll("\\", "/") === file)
.map((diagnostic) => diagnostic.code),
).toEqual(Array.from({ length: 7 }, () => "typescript(no-floating-promises)"));
const owner = path.dirname(file);
expect(result.stderr.replaceAll("\\", "/")).toContain(
`Got tsconfig for file ${path.join(tempRoot, file).replaceAll("\\", "/")}: ${path.join(tempRoot, owner, "tsconfig.json").replaceAll("\\", "/")}`,
);
const project = spawnSync(
process.execPath,
[
path.resolve("node_modules/typescript-native/bin/tsc"),
"--showConfig",
"-p",
`${owner}/tsconfig.json`,
],
{ cwd: tempRoot, encoding: "utf8", timeout: 10_000 },
);
expect(project.status, project.stdout + project.stderr).toBe(0);
const parsed = JSON.parse(project.stdout) as { files: string[] };
expect(parsed.files).not.toContain(`../${owner === "src" ? "ui" : "src"}/owner.ts`);
}
});
it("checks unbound methods in TypeScript and CommonJS source test support", () => {
const tempRoot = fs.realpathSync(createTempDir("openclaw-oxlint-source-support-"));
for (const file of [".oxlintrc.json", "tsconfig.json", "src/tsconfig.json"]) {

View file

@ -36,6 +36,7 @@ describe("tsgo core test shards", () => {
throw new Error(`Could not parse ${config}`);
}
expect(parsed.errors, config).toEqual([]);
expect(parsed.projectReferences ?? [], config).toEqual([]);
return parsed.fileNames
.filter((file) => /\.test\.tsx?$/u.test(file))
.map((file) => path.relative(process.cwd(), file).replaceAll(path.sep, "/"));
@ -108,6 +109,19 @@ describe("tsgo core test shards", () => {
expect(selectTsgoCoreTestStripe("0/2")).toBeUndefined();
expect(selectTsgoCoreTestStripe("3/2")).toBeUndefined();
expect(selectTsgoCoreTestStripe("src")).toBeUndefined();
expect(selectTsgoCoreTestStripe("2-1/5")).toBeUndefined();
expect(selectTsgoCoreTestStripe("1-6/5")).toBeUndefined();
const paired = ["1-2/5", "3-4/5", "5/5"].flatMap(
(stripe) => selectTsgoCoreTestStripe(stripe) ?? [],
);
expect(paired.map((shard) => shard.name).toSorted()).toEqual(
TSGO_CORE_TEST_SHARDS.map((shard) => shard.name).toSorted(),
);
expect(selectTsgoCoreTestStripe("1-2/5")).toEqual(
TSGO_CORE_TEST_SHARDS.filter((shard) =>
["1/5", "2/5"].some((stripe) => selectTsgoCoreTestStripe(stripe)?.includes(shard)),
),
);
});
it("accepts an exact once-only partition within the root budget", () => {
@ -398,9 +412,10 @@ process.exit(result.status??1);
expect(calls.filter((args) => args.includes("--listFilesOnly"))).toHaveLength(
TSGO_CORE_GRAPHS.length,
);
// Discovery and diagnostic checks both use project mode.
const builds = calls
.filter((args) => args.includes("-b"))
.map((args) => args[args.indexOf("-b") + 1]);
.filter((args) => !args.includes("--listFilesOnly") && !args.includes("--showConfig"))
.map((args) => args[args.indexOf("-p") + 1]);
return { result, builds };
};
const initial = await check();

18
ui/tsconfig.json Normal file
View file

@ -0,0 +1,18 @@
{
"extends": "../tsconfig.json",
"include": [
"**/*.ts",
"**/*.tsx",
"**/*.mts",
"**/*.cts",
"../src/**/*.d.ts",
"../src/**/*.d.mts",
"../src/**/*.d.cts",
"../packages/**/*.d.ts",
"../packages/**/*.d.mts",
"../packages/**/*.d.cts",
"../extensions/**/*.d.ts",
"../extensions/**/*.d.mts",
"../extensions/**/*.d.cts"
]
}