Skip to content
File

Blob: tests/worker/dispatch/shared/run-environment/pinned-checkout.fetch-strategy.test.ts

typescript501 lines
1import { describe, expect, it } from "vitest";
2 
3import { CommitSha, type CommitSha as CommitShaType } from "@/contracts";
4import { prepareExecutionEnvironment } from "@/worker/dispatch/shared/run-environment";
5 
6import {
7 INVALID_REPO_CONFIG,
8 createExecResult,
9 createHarness,
10 createLeaseStub,
11} from "../../../../helpers/run-environment";
12 
13const expectPinnedCheckoutFailure = async (
14 commitSha: CommitShaType,
15 options: {
16 projectIdValue: string;
17 runIdValue: string;
18 configContent?: string;
19 execImpl: (command: string, events: string[]) => ReturnType<typeof createExecResult>;
20 },
21) => {
22 const { context, events, projectId, recordRunResolvedCommit, runId, sandbox } = createHarness({
23 projectIdValue: options.projectIdValue,
24 runIdValue: options.runIdValue,
25 snapshotCommitSha: commitSha,
26 configContent: options.configContent ?? INVALID_REPO_CONFIG,
27 execImpl: (command) => options.execImpl(command, events),
28 });
29 
30 return {
31 context,
32 events,
33 projectId,
34 recordRunResolvedCommit,
35 runId,
36 sandbox,
37 };
38};
39 
40describe("run environment preparation", () => {
41 describe("pinned checkout fetch strategy", () => {
42 it("checks out a pinned commit without cloning against the branch ref", async () => {
43 const pinnedCommitSha = CommitSha.assertDecode("2222222222222222222222222222222222222222");
44 let catFileChecks = 0;
45 let checkedOutPinnedCommit = false;
46 
47 const { context, events, projectId, recordRunResolvedCommit, runId, sandbox } = await expectPinnedCheckoutFailure(
48 pinnedCommitSha,
49 {
50 projectIdValue: "prj_1111111111111111111111",
51 runIdValue: "run_1111111111111111111111",
52 execImpl: (command, events) => {
53 if (command.includes(" clone --branch ") || command.includes(" origin 'main'")) {
54 throw new Error(`Pinned checkout should not depend on branch refs: ${command}`);
55 }
56 
57 if (command.startsWith("git init ")) {
58 events.push("init");
59 return createExecResult();
60 }
61 
62 if (command.includes("remote add origin")) {
63 events.push("remote-add");
64 return createExecResult();
65 }
66 
67 if (command.includes("cat-file -e")) {
68 catFileChecks += 1;
69 events.push(`cat-file-${catFileChecks}`);
70 return createExecResult({
71 success: catFileChecks >= 2,
72 stderr: catFileChecks >= 2 ? "" : "fatal: Not a valid object name",
73 });
74 }
75 
76 if (command.includes(`fetch --depth=1 --update-shallow origin '${pinnedCommitSha}'`)) {
77 events.push("fetch-depth-1");
78 return createExecResult();
79 }
80 
81 if (command.includes("checkout --detach")) {
82 expect(command).toContain(pinnedCommitSha);
83 checkedOutPinnedCommit = true;
84 events.push("checkout-detached");
85 return createExecResult();
86 }
87 
88 if (command.includes("rev-parse HEAD")) {
89 events.push("rev-parse");
90 return createExecResult({
91 stdout: `${checkedOutPinnedCommit ? pinnedCommitSha : pinnedCommitSha}\n`,
92 });
93 }
94 
95 throw new Error(`Unexpected exec command: ${command}`);
96 },
97 },
98 );
99 
100 await expect(prepareExecutionEnvironment(context, createLeaseStub())).rejects.toThrow(
101 "Repository config is not valid YAML",
102 );
103 
104 expect(recordRunResolvedCommit).toHaveBeenCalledWith({
105 projectId,
106 runId,
107 commitSha: pinnedCommitSha,
108 });
109 expect(events).toContain("init");
110 expect(events).toContain("remote-add");
111 expect(events).toContain("fetch-depth-1");
112 expect(events.indexOf("cat-file-1")).toBeGreaterThan(events.indexOf("remote-add"));
113 expect(events.indexOf("fetch-depth-1")).toBeGreaterThan(events.indexOf("cat-file-1"));
114 expect(events.indexOf("cat-file-2")).toBeGreaterThan(events.indexOf("fetch-depth-1"));
115 expect(events.indexOf("checkout-detached")).toBeGreaterThan(events.indexOf("cat-file-2"));
116 expect(events.indexOf("record-run-resolved-commit")).toBeGreaterThan(events.indexOf("checkout-detached"));
117 expect(sandbox.deleteSession).toHaveBeenCalledWith("checkout-session");
118 expect(context.state.session).toBeNull();
119 });
120 
121 it("deepens the pinned checkout before falling back to broader fetches", async () => {
122 const rewrittenHeadSha = CommitSha.assertDecode("5555555555555555555555555555555555555555");
123 const pinnedCommitSha = CommitSha.assertDecode("6666666666666666666666666666666666666666");
124 const depthFetches: number[] = [];
125 let catFileChecks = 0;
126 let checkedOutPinnedCommit = false;
127 
128 const { context, events, projectId, recordRunResolvedCommit, runId, sandbox } = await expectPinnedCheckoutFailure(
129 pinnedCommitSha,
130 {
131 projectIdValue: "prj_3333333333333333333333",
132 runIdValue: "run_3333333333333333333333",
133 execImpl: (command, events) => {
134 if (command.includes(" clone --branch ") || command.includes(" origin 'main'")) {
135 throw new Error(`Pinned checkout should not depend on branch refs: ${command}`);
136 }
137 
138 if (command.startsWith("git init ")) {
139 events.push("init");
140 return createExecResult();
141 }
142 
143 if (command.includes("remote add origin")) {
144 events.push("remote-add");
145 return createExecResult();
146 }
147 
148 const depthMatch = command.match(/fetch --depth=(\d+)/u);
149 if (depthMatch) {
150 const depth = Number(depthMatch[1]);
151 depthFetches.push(depth);
152 events.push(`fetch-depth-${depth}`);
153 return createExecResult();
154 }
155 
156 if (command.includes(`fetch origin '${pinnedCommitSha}'`)) {
157 events.push("fetch-exact-sha");
158 return createExecResult();
159 }
160 
161 if (command.includes("cat-file -e")) {
162 catFileChecks += 1;
163 events.push(`cat-file-${catFileChecks}`);
164 return createExecResult({
165 success: depthFetches.includes(2),
166 stderr: depthFetches.includes(2) ? "" : "fatal: Not a valid object name",
167 });
168 }
169 
170 if (command.includes("rev-parse --is-shallow-repository")) {
171 events.push("check-shallow");
172 return createExecResult({
173 stdout: "true\n",
174 });
175 }
176 
177 if (command.includes("checkout --detach")) {
178 expect(command).toContain(pinnedCommitSha);
179 checkedOutPinnedCommit = true;
180 events.push("checkout-detached");
181 return createExecResult();
182 }
183 
184 if (command.includes("rev-parse HEAD")) {
185 events.push("rev-parse");
186 return createExecResult({
187 stdout: `${checkedOutPinnedCommit ? pinnedCommitSha : rewrittenHeadSha}\n`,
188 });
189 }
190 
191 throw new Error(`Unexpected exec command: ${command}`);
192 },
193 },
194 );
195 
196 await expect(prepareExecutionEnvironment(context, createLeaseStub())).rejects.toThrow(
197 "Repository config is not valid YAML",
198 );
199 
200 expect(recordRunResolvedCommit).toHaveBeenCalledWith({
201 projectId,
202 runId,
203 commitSha: pinnedCommitSha,
204 });
205 expect(depthFetches).toEqual([1, 2]);
206 expect(catFileChecks).toBe(3);
207 expect(events).not.toContain("fetch-exact-sha");
208 expect(events).not.toContain("fetch-unshallow");
209 expect(events.indexOf("fetch-depth-1")).toBeGreaterThan(events.indexOf("cat-file-1"));
210 expect(events.indexOf("cat-file-2")).toBeGreaterThan(events.indexOf("fetch-depth-1"));
211 expect(events.indexOf("fetch-depth-2")).toBeGreaterThan(events.indexOf("cat-file-2"));
212 expect(events.indexOf("cat-file-3")).toBeGreaterThan(events.indexOf("fetch-depth-2"));
213 expect(events.indexOf("checkout-detached")).toBeGreaterThan(events.indexOf("cat-file-3"));
214 expect(sandbox.deleteSession).toHaveBeenCalledWith("checkout-session");
215 expect(context.state.session).toBeNull();
216 });
217 
218 it("fetches the pinned commit by SHA when depth probes do not find it", async () => {
219 const rewrittenHeadSha = CommitSha.assertDecode("7777777777777777777777777777777777777777");
220 const pinnedCommitSha = CommitSha.assertDecode("8888888888888888888888888888888888888888");
221 const depthFetches: number[] = [];
222 let catFileChecks = 0;
223 let checkedOutPinnedCommit = false;
224 
225 const { context, events, projectId, recordRunResolvedCommit, runId, sandbox } = await expectPinnedCheckoutFailure(
226 pinnedCommitSha,
227 {
228 projectIdValue: "prj_4444444444444444444444",
229 runIdValue: "run_4444444444444444444444",
230 execImpl: (command, events) => {
231 if (command.includes(" clone --branch ") || command.includes(" origin 'main'")) {
232 throw new Error(`Pinned checkout should not depend on branch refs: ${command}`);
233 }
234 
235 if (command.startsWith("git init ")) {
236 events.push("init");
237 return createExecResult();
238 }
239 
240 if (command.includes("remote add origin")) {
241 events.push("remote-add");
242 return createExecResult();
243 }
244 
245 const depthMatch = command.match(/fetch --depth=(\d+)/u);
246 if (depthMatch) {
247 const depth = Number(depthMatch[1]);
248 depthFetches.push(depth);
249 events.push(`fetch-depth-${depth}`);
250 return createExecResult();
251 }
252 
253 if (command.includes(`fetch origin '${pinnedCommitSha}'`)) {
254 events.push("fetch-exact-sha");
255 return createExecResult();
256 }
257 
258 if (command.includes("fetch --unshallow")) {
259 events.push("fetch-unshallow");
260 return createExecResult();
261 }
262 
263 if (command.includes("cat-file -e")) {
264 catFileChecks += 1;
265 events.push(`cat-file-${catFileChecks}`);
266 return createExecResult({
267 success: events.includes("fetch-exact-sha"),
268 stderr: events.includes("fetch-exact-sha") ? "" : "fatal: Not a valid object name",
269 });
270 }
271 
272 if (command.includes("rev-parse --is-shallow-repository")) {
273 events.push("check-shallow");
274 return createExecResult({
275 stdout: "true\n",
276 });
277 }
278 
279 if (command.includes("checkout --detach")) {
280 expect(command).toContain(pinnedCommitSha);
281 checkedOutPinnedCommit = true;
282 events.push("checkout-detached");
283 return createExecResult();
284 }
285 
286 if (command.includes("rev-parse HEAD")) {
287 events.push("rev-parse");
288 return createExecResult({
289 stdout: `${checkedOutPinnedCommit ? pinnedCommitSha : rewrittenHeadSha}\n`,
290 });
291 }
292 
293 throw new Error(`Unexpected exec command: ${command}`);
294 },
295 },
296 );
297 
298 await expect(prepareExecutionEnvironment(context, createLeaseStub())).rejects.toThrow(
299 "Repository config is not valid YAML",
300 );
301 
302 expect(recordRunResolvedCommit).toHaveBeenCalledWith({
303 projectId,
304 runId,
305 commitSha: pinnedCommitSha,
306 });
307 expect(depthFetches).toEqual([1, 2, 4, 8, 16, 32, 64]);
308 expect(catFileChecks).toBe(9);
309 expect(events.indexOf("fetch-exact-sha")).toBeGreaterThan(events.indexOf("cat-file-8"));
310 expect(events.indexOf("cat-file-9")).toBeGreaterThan(events.indexOf("fetch-exact-sha"));
311 expect(events.indexOf("checkout-detached")).toBeGreaterThan(events.indexOf("cat-file-9"));
312 expect(events).not.toContain("fetch-unshallow");
313 expect(sandbox.deleteSession).toHaveBeenCalledWith("checkout-session");
314 expect(context.state.session).toBeNull();
315 });
316 
317 it("unshallows pinned history only as a last resort after exact-SHA fetches", async () => {
318 const rewrittenHeadSha = CommitSha.assertDecode("9999999999999999999999999999999999999999");
319 const pinnedCommitSha = CommitSha.assertDecode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
320 const depthFetches: number[] = [];
321 let catFileChecks = 0;
322 let checkedOutPinnedCommit = false;
323 
324 const { context, events, projectId, recordRunResolvedCommit, runId, sandbox } = await expectPinnedCheckoutFailure(
325 pinnedCommitSha,
326 {
327 projectIdValue: "prj_5555555555555555555555",
328 runIdValue: "run_5555555555555555555555",
329 execImpl: (command, events) => {
330 if (command.includes(" clone --branch ") || command.includes(" origin 'main'")) {
331 throw new Error(`Pinned checkout should not depend on branch refs: ${command}`);
332 }
333 
334 if (command.startsWith("git init ")) {
335 events.push("init");
336 return createExecResult();
337 }
338 
339 if (command.includes("remote add origin")) {
340 events.push("remote-add");
341 return createExecResult();
342 }
343 
344 const depthMatch = command.match(/fetch --depth=(\d+)/u);
345 if (depthMatch) {
346 const depth = Number(depthMatch[1]);
347 depthFetches.push(depth);
348 events.push(`fetch-depth-${depth}`);
349 return createExecResult();
350 }
351 
352 if (command.includes(`fetch origin '${pinnedCommitSha}'`)) {
353 events.push("fetch-exact-sha");
354 return createExecResult();
355 }
356 
357 if (command.includes("fetch --unshallow --update-shallow origin")) {
358 events.push("fetch-unshallow");
359 return createExecResult();
360 }
361 
362 if (command.includes("cat-file -e")) {
363 catFileChecks += 1;
364 events.push(`cat-file-${catFileChecks}`);
365 return createExecResult({
366 success: events.includes("fetch-unshallow"),
367 stderr: events.includes("fetch-unshallow") ? "" : "fatal: Not a valid object name",
368 });
369 }
370 
371 if (command.includes("rev-parse --is-shallow-repository")) {
372 events.push("check-shallow");
373 return createExecResult({
374 stdout: "true\n",
375 });
376 }
377 
378 if (command.includes("checkout --detach")) {
379 expect(command).toContain(pinnedCommitSha);
380 checkedOutPinnedCommit = true;
381 events.push("checkout-detached");
382 return createExecResult();
383 }
384 
385 if (command.includes("rev-parse HEAD")) {
386 events.push("rev-parse");
387 return createExecResult({
388 stdout: `${checkedOutPinnedCommit ? pinnedCommitSha : rewrittenHeadSha}\n`,
389 });
390 }
391 
392 throw new Error(`Unexpected exec command: ${command}`);
393 },
394 },
395 );
396 
397 await expect(prepareExecutionEnvironment(context, createLeaseStub())).rejects.toThrow(
398 "Repository config is not valid YAML",
399 );
400 
401 expect(recordRunResolvedCommit).toHaveBeenCalledWith({
402 projectId,
403 runId,
404 commitSha: pinnedCommitSha,
405 });
406 expect(depthFetches).toEqual([1, 2, 4, 8, 16, 32, 64]);
407 expect(catFileChecks).toBe(10);
408 expect(events.indexOf("fetch-exact-sha")).toBeGreaterThan(events.indexOf("cat-file-8"));
409 expect(events.indexOf("cat-file-9")).toBeGreaterThan(events.indexOf("fetch-exact-sha"));
410 expect(events.indexOf("fetch-unshallow")).toBeGreaterThan(events.indexOf("cat-file-9"));
411 expect(events.indexOf("cat-file-10")).toBeGreaterThan(events.indexOf("fetch-unshallow"));
412 expect(events.indexOf("checkout-detached")).toBeGreaterThan(events.indexOf("cat-file-10"));
413 expect(sandbox.deleteSession).toHaveBeenCalledWith("checkout-session");
414 expect(context.state.session).toBeNull();
415 });
416 
417 it("falls back to a non-shallow exact-SHA fetch when shallow requests are unsupported", async () => {
418 const rewrittenHeadSha = CommitSha.assertDecode("dddddddddddddddddddddddddddddddddddddddd");
419 const pinnedCommitSha = CommitSha.assertDecode("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
420 let catFileChecks = 0;
421 let checkedOutPinnedCommit = false;
422 
423 const { context, events, projectId, recordRunResolvedCommit, runId, sandbox } = await expectPinnedCheckoutFailure(
424 pinnedCommitSha,
425 {
426 projectIdValue: "prj_6666666666666666666666",
427 runIdValue: "run_6666666666666666666666",
428 execImpl: (command, events) => {
429 if (command.includes(" clone --branch ") || command.includes(" origin 'main'")) {
430 throw new Error(`Pinned checkout should not depend on branch refs: ${command}`);
431 }
432 
433 if (command.startsWith("git init ")) {
434 events.push("init");
435 return createExecResult();
436 }
437 
438 if (command.includes("remote add origin")) {
439 events.push("remote-add");
440 return createExecResult();
441 }
442 
443 if (command.includes("cat-file -e")) {
444 catFileChecks += 1;
445 events.push(`cat-file-${catFileChecks}`);
446 return createExecResult({
447 success: events.includes("fetch-exact-sha"),
448 stderr: events.includes("fetch-exact-sha") ? "" : "fatal: Not a valid object name",
449 });
450 }
451 
452 if (command.includes(`fetch --depth=1 --update-shallow origin '${pinnedCommitSha}'`)) {
453 events.push("fetch-depth-1");
454 return createExecResult({
455 success: false,
456 stderr: "fatal: Server does not support shallow requests",
457 });
458 }
459 
460 if (command.includes(`fetch origin '${pinnedCommitSha}'`)) {
461 events.push("fetch-exact-sha");
462 return createExecResult();
463 }
464 
465 if (command.includes("checkout --detach")) {
466 expect(command).toContain(pinnedCommitSha);
467 checkedOutPinnedCommit = true;
468 events.push("checkout-detached");
469 return createExecResult();
470 }
471 
472 if (command.includes("rev-parse HEAD")) {
473 events.push("rev-parse");
474 return createExecResult({
475 stdout: `${checkedOutPinnedCommit ? pinnedCommitSha : rewrittenHeadSha}\n`,
476 });
477 }
478 
479 throw new Error(`Unexpected exec command: ${command}`);
480 },
481 },
482 );
483 
484 await expect(prepareExecutionEnvironment(context, createLeaseStub())).rejects.toThrow(
485 "Repository config is not valid YAML",
486 );
487 
488 expect(recordRunResolvedCommit).toHaveBeenCalledWith({
489 projectId,
490 runId,
491 commitSha: pinnedCommitSha,
492 });
493 expect(events.indexOf("fetch-exact-sha")).toBeGreaterThan(events.indexOf("fetch-depth-1"));
494 expect(events.indexOf("cat-file-2")).toBeGreaterThan(events.indexOf("fetch-exact-sha"));
495 expect(events.indexOf("checkout-detached")).toBeGreaterThan(events.indexOf("cat-file-2"));
496 expect(sandbox.deleteSession).toHaveBeenCalledWith("checkout-session");
497 expect(context.state.session).toBeNull();
498 });
499 });
500});