






















@@ -7,7 +7,10 @@ import {
77} from "./changed-lanes.mjs";
88import { booleanFlag, parseFlagArgs, stringFlag } from "./lib/arg-utils.mjs";
99import { printTimingSummary } from "./lib/check-timing-summary.mjs";
10-import { resolveLocalHeavyCheckEnv } from "./lib/local-heavy-check-runtime.mjs";
10+import {
11+acquireLocalHeavyCheckLockSync,
12+resolveLocalHeavyCheckEnv,
13+} from "./lib/local-heavy-check-runtime.mjs";
1114import { runManagedCommand } from "./lib/managed-child-process.mjs";
1215import { createSparseTsgoSkipEnv } from "./lib/tsgo-sparse-guard.mjs";
1316import { isCiLikeEnv } from "./lib/vitest-local-scheduling.mjs";
@@ -17,8 +20,18 @@ export const CHANGED_CHECK_VITEST_NO_OUTPUT_TIMEOUT_MS = "600000";
1720const VITEST_NO_OUTPUT_TIMEOUT_ENV_KEY = "OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS";
1821const VITEST_NO_OUTPUT_RETRY_ENV_KEY = "OPENCLAW_VITEST_NO_OUTPUT_RETRY";
192220-export function createChangedCheckVitestEnv(baseEnv = process.env) {
23+export function createChangedCheckChildEnv(baseEnv = process.env) {
2124const resolvedBaseEnv = resolveLocalHeavyCheckEnv(baseEnv);
25+return {
26+ ...resolvedBaseEnv,
27+OPENCLAW_OXLINT_SKIP_LOCK: "1",
28+OPENCLAW_TEST_HEAVY_CHECK_LOCK_HELD: "1",
29+OPENCLAW_TSGO_HEAVY_CHECK_LOCK_HELD: "1",
30+};
31+}
32+33+export function createChangedCheckVitestEnv(baseEnv = process.env) {
34+const resolvedBaseEnv = createChangedCheckChildEnv(baseEnv);
2235const env = {
2336 ...resolvedBaseEnv,
2437[VITEST_NO_OUTPUT_TIMEOUT_ENV_KEY]:
@@ -48,7 +61,7 @@ export function createChangedCheckVitestEnv(baseEnv = process.env) {
48614962export function createChangedCheckPlan(result, options = {}) {
5063const commands = [];
51-const baseEnv = resolveLocalHeavyCheckEnv(options.env ?? process.env);
64+const baseEnv = createChangedCheckChildEnv(options.env ?? process.env);
5265const add = (name, args, env) => {
5366if (!commands.some((command) => command.name === name && sameArgs(command.args, args))) {
5467commands.push({ name, args, ...(env ? { env } : {}) });
@@ -164,79 +177,92 @@ export function createChangedCheckPlan(result, options = {}) {
164177165178export async function runChangedCheck(result, options = {}) {
166179const baseEnv = resolveLocalHeavyCheckEnv(options.env ?? process.env);
167-const plan = createChangedCheckPlan(result, { ...options, env: baseEnv });
168-printPlan(result, plan, options);
180+const childEnv = createChangedCheckChildEnv(baseEnv);
181+const plan = createChangedCheckPlan(result, { ...options, env: childEnv });
182+const releaseLock = options.dryRun
183+ ? () => {}
184+ : acquireLocalHeavyCheckLockSync({
185+cwd: process.cwd(),
186+env: baseEnv,
187+toolName: "check:changed",
188+});
169189170-if (options.dryRun) {
171-return 0;
172-}
190+try {
191+printPlan(result, plan, options);
173192174-const timings = [];
175-for (const command of plan.commands) {
176-const status = await runPnpm(command, timings);
177-if (status !== 0) {
178-printSummary(timings, options);
179-return status;
193+if (options.dryRun) {
194+return 0;
180195}
181-}
182196183-if (plan.runFullTests) {
184-const status = await runPnpm(
185-{ name: "tests all", args: ["test"], env: createChangedCheckVitestEnv() },
186-timings,
187-);
188-if (status !== 0) {
189-printSummary(timings, options);
190-return status;
191-}
192-} else if (plan.runChangedTestsBroad) {
193-const testArgs = options.explicitPaths
194- ? ["test"]
195- : ["test", "--changed", options.base ?? "origin/main"];
196-const status = await runPnpm(
197-{
198-name: options.explicitPaths ? "tests all" : "tests changed broad",
199-args: testArgs,
200-env: createChangedCheckVitestEnv(),
201-},
202-timings,
203-);
204-if (status !== 0) {
205-printSummary(timings, options);
206-return status;
197+const timings = [];
198+for (const command of plan.commands) {
199+const status = await runPnpm(command, timings);
200+if (status !== 0) {
201+printSummary(timings, options);
202+return status;
203+}
207204}
208-} else if (plan.testTargets.length > 0) {
209-const status = await runPnpm(
210-{
211-name: "tests changed",
212-args: ["test", ...plan.testTargets],
213-env: createChangedCheckVitestEnv(),
214-},
215-timings,
216-);
217-if (status !== 0) {
218-printSummary(timings, options);
219-return status;
205+206+if (plan.runFullTests) {
207+const status = await runPnpm(
208+{ name: "tests all", args: ["test"], env: createChangedCheckVitestEnv(childEnv) },
209+timings,
210+);
211+if (status !== 0) {
212+printSummary(timings, options);
213+return status;
214+}
215+} else if (plan.runChangedTestsBroad) {
216+const testArgs = options.explicitPaths
217+ ? ["test"]
218+ : ["test", "--changed", options.base ?? "origin/main"];
219+const status = await runPnpm(
220+{
221+name: options.explicitPaths ? "tests all" : "tests changed broad",
222+args: testArgs,
223+env: createChangedCheckVitestEnv(childEnv),
224+},
225+timings,
226+);
227+if (status !== 0) {
228+printSummary(timings, options);
229+return status;
230+}
231+} else if (plan.testTargets.length > 0) {
232+const status = await runPnpm(
233+{
234+name: "tests changed",
235+args: ["test", ...plan.testTargets],
236+env: createChangedCheckVitestEnv(childEnv),
237+},
238+timings,
239+);
240+if (status !== 0) {
241+printSummary(timings, options);
242+return status;
243+}
220244}
221-}
222245223-if (plan.runExtensionTests) {
224-const status = await runPnpm(
225-{
226-name: "tests extensions",
227-args: ["test:extensions"],
228-env: createChangedCheckVitestEnv(),
229-},
230-timings,
231-);
232-if (status !== 0) {
233-printSummary(timings, options);
234-return status;
246+if (plan.runExtensionTests) {
247+const status = await runPnpm(
248+{
249+name: "tests extensions",
250+args: ["test:extensions"],
251+env: createChangedCheckVitestEnv(childEnv),
252+},
253+timings,
254+);
255+if (status !== 0) {
256+printSummary(timings, options);
257+return status;
258+}
235259}
236-}
237260238-printSummary(timings, options);
239-return 0;
261+printSummary(timings, options);
262+return 0;
263+} finally {
264+releaseLock();
265+}
240266}
241267242268function sameArgs(left, right) {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。