History

Bring CI under two minutes

Rhys Sullivan committed 2 months ago

Commit 012f1271 parent cb317864 files · +33 −13Browse files

Unified · Split

4 files
  1. .github/workflows/ci.yml +11 −2
  2. e2e/scripts/ci-shard-durations.ts +1 −1
  3. e2e/scripts/ci-shard.test.ts +17 −7
  4. e2e/scripts/ci-shard.ts +4 −3
.github/workflows/ci.yml+11−2
@@ -201,7 +201,16 @@ jobs: · 200 unmodified lines
201201 # durations plus a conservative weight for new tests. Extra shards
202202 # keep each hermetic stack below the PGlite lifetime failure window.
203203 - { target: cloud, shard-index: 1, shard-name: 1of16 }
204− - { target: cloud, shard-index: 2, shard-name: 2of16 }
204+ # This shard owns the intentional 65-second human-delay approval
205+ # scenario. Extra CPU cannot shorten that assertion, but it does keep
206+ # dependency linking and the cloud stack's startup outside the
207+ # remaining two-minute wall-clock budget.
208+ - {
209+ target: cloud,
210+ shard-index: 2,
211+ shard-name: 2of16,
212+ runner: blacksmith-8vcpu-ubuntu-2404,
213+ }
205214 - { target: cloud, shard-index: 3, shard-name: 3of16 }
206215 - { target: cloud, shard-index: 4, shard-name: 4of16 }
207216 - { target: cloud, shard-index: 5, shard-name: 5of16 }
@@ -231,7 +240,7 @@ jobs: · 23 unmodified lines
231240 # lane from the two-minute critical path.
232241 - { target: local, shard-index: 1, shard-name: 1of2 }
233242 - { target: local, shard-index: 2, shard-name: 2of2 }
234− runs-on: blacksmith-4vcpu-ubuntu-2404
243+ runs-on: ${{ matrix.runner || 'blacksmith-4vcpu-ubuntu-2404' }}
235244 timeout-minutes: 30
236245 steps:
237246 - uses: actions/checkout@v4
e2e/scripts/ci-shard-durations.ts+1−1
@@ -43,7 +43,7 @@ export const OBSERVED_TEST_DURATIONS_MS: Readonly< · 42 unmodified lines
4343 "scenarios/connect-handoff-session.test.ts": 10_296,
4444 "scenarios/connect-handoff.test.ts": 7_519,
4545 "scenarios/connection-remove-confirm.test.ts": 5_197,
46− "scenarios/google-health-checks.test.ts": 20_737,
46+ "scenarios/google-health-checks.test.ts": 39_421,
4747 "scenarios/google-photos-preset-ui.test.ts": 5_696,
4848 "scenarios/graphql-introspection-health.test.ts": 12_617,
4949 "scenarios/health-checks-ui.test.ts": 71_165,
e2e/scripts/ci-shard.test.ts+17−7
@@ -113,17 +113,27 @@ describe("CI shard planning", () => { · 112 unmodified lines
113113 );
114114
115115 for (const target of CI_TARGETS) {
116− const entries = workflow
117− .split("\n")
118− .filter((line) => line.includes(`{ target: ${target}, shard-index:`));
119− const indexes = entries.map((line) => {
120− const match = /shard-index: (\d+)/.exec(line);
121− return match?.[1];
122− });
116+ const entries = workflow.matchAll(
117+ new RegExp(`-\\s*\\{[^}]*target:\\s*${target},[^}]*shard-index:\\s*(\\d+)`, "g"),
118+ );
119+ const indexes = [...entries].map((entry) => entry[1]);
123120
124121 expect(indexes).toEqual(
125122 Array.from({ length: CI_SHARD_COUNTS[target] }, (_, index) => String(index + 1)),
126123 );
127124 }
125+
126+ const cloudPlan = await planTargetShards(
127+ "cloud",
128+ fileURLToPath(new URL("..", import.meta.url)),
129+ );
130+ const approvalShard = cloudPlan.find((shard) =>
131+ shard.files.includes("scenarios/artifact-approval.test.ts"),
132+ );
133+ expect(approvalShard?.files).toEqual(["scenarios/artifact-approval.test.ts"]);
134+ const acceleratedEntry = new RegExp(
135+ `-\\s*\\{[^}]*target:\\s*cloud,[^}]*shard-index:\\s*${approvalShard?.index},[^}]*runner:\\s*blacksmith-8vcpu-ubuntu-2404`,
136+ );
137+ expect(workflow).toMatch(acceleratedEntry);
128138 });
129139 });
e2e/scripts/ci-shard.ts+4−3
@@ -60,9 +60,10 @@ const testDirectories: Readonly<Record<CiTarget, readonly string[]>> = { · 59 unmodified lines
6060 local: ["local"],
6161 };
6262
63−// A file this long already consumes most of the two-minute budget after the
64−// target stack boots. Keep it alone instead of balancing unrelated work onto it.
65−const ISOLATED_TEST_DURATION_MS = 45_000;
63+// A file this long already consumes most of the two-minute budget after
64+// dependency linking, target startup, and Vitest global setup. Keep it alone
65+// instead of balancing unrelated work onto it.
66+const ISOLATED_TEST_DURATION_MS = 35_000;
6667
6768 const comparePaths = (left: string, right: string): number =>
6869 left < right ? -1 : left > right ? 1 : 0;