Skip to content

Commit e0a4fa4

Browse files
merge: integrate upstream main into fork
2 parents 5e4f2f6 + 0bdf33a commit e0a4fa4

2,309 files changed

Lines changed: 51288 additions & 318089 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/scripts/check-nightly-release.test.cjs‎

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,6 @@ for (const releaseChannel of ["stable", "nightly"]) {
6161
);
6262
assert.equal(calls.length, 0);
6363
});
64-
65-
test(`allows a manual ${releaseChannel} release from main`, async () => {
66-
const { options, calls } = releaseSourceFixture();
67-
await assertReleaseSource({ ...options, releaseChannel });
68-
assert.equal(calls[0].basehead, "candidate...main");
69-
});
7064
}
7165

7266
for (const comparisonStatus of ["behind", "diverged"]) {
@@ -79,13 +73,6 @@ for (const comparisonStatus of ["behind", "diverged"]) {
7973
});
8074
}
8175

82-
test("accepts a release commit already contained in main", async () => {
83-
for (const comparisonStatus of ["ahead", "identical"]) {
84-
const { options } = releaseSourceFixture({ comparisonStatus, eventName: "push" });
85-
await assertCommitOnDefaultBranch({ ...options, sha: "release-commit" });
86-
}
87-
});
88-
8976
function fixture({ releases = [nightly(7)], comparisonStatus = "ahead" } = {}) {
9077
const calls = [];
9178
return {
@@ -119,26 +106,6 @@ test("releases the first nightly when no nightly is published", async () => {
119106
assert.equal(await shouldReleaseNightly(options), true);
120107
});
121108

122-
test("waits six hours after publication, including manual nightlies", async () => {
123-
for (const age of [0, 3, 6 - 1 / 3600]) {
124-
const { options, calls } = fixture({ releases: [nightly(age)] });
125-
assert.equal(await shouldReleaseNightly(options), false);
126-
assert.equal(calls.length, 0);
127-
}
128-
});
129-
130-
test("releases new commits at six hours and after an idle period", async () => {
131-
for (const age of [6, 7, 24]) {
132-
const { options } = fixture({ releases: [nightly(age)] });
133-
assert.equal(await shouldReleaseNightly(options), true);
134-
}
135-
});
136-
137-
test("skips unchanged commits after the gap", async () => {
138-
const { options } = fixture({ comparisonStatus: "identical" });
139-
assert.equal(await shouldReleaseNightly(options), false);
140-
});
141-
142109
test("uses publication time, not release order or the tagged commit date", async () => {
143110
const { options } = fixture({
144111
releases: [nightly(10), nightly(1), nightly(20, { tag_name: "nightly-v0.9.0" })],
@@ -153,13 +120,6 @@ test("ignores stable releases and drafts when checking the gap", async () => {
153120
assert.equal(await shouldReleaseNightly(options), true);
154121
});
155122

156-
test("compares against the published tag, including legacy nightly tags", async () => {
157-
const tag = "nightly-v0.9.0";
158-
const { options, calls } = fixture({ releases: [nightly(7, { tag_name: tag })] });
159-
assert.equal(await shouldReleaseNightly(options), true);
160-
assert.equal(calls[0].basehead, `${tag}...new`);
161-
});
162-
163123
test("fails instead of releasing when GitHub cannot supply release state", async () => {
164124
const { options } = fixture();
165125
options.github.paginate = async () => {
@@ -211,8 +171,3 @@ test("stable releases derive the version from legacy nightly tags", async () =>
211171
});
212172
assert.equal((await resolveLatestNightlyCommit(options)).version, "0.9.0");
213173
});
214-
215-
test("stable releases fail without a published nightly", async () => {
216-
const { options } = nightlyCommitFixture({ releases: [nightly(0, { tag_name: "v1.0.0" })] });
217-
await assert.rejects(resolveLatestNightlyCommit(options), /No published nightly/);
218-
});

‎.github/scripts/ci-changes.cjs‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
// node ci-changes.cjs --paths <file> --full run every Linux job, gate only the macOS lint
66
// node ci-changes.cjs changed paths unknown: run everything
77
//
8+
// scripts/check-changed.ts requires the same decisions so local runs match CI.
9+
//
810
// Every changed path maps to workspace packages, which then pull in their
911
// dependents from package.json. A path this file does not recognize runs
1012
// everything, so a new root file or directory can only cost minutes.
@@ -201,4 +203,6 @@ function main() {
201203
for (const [key, value] of Object.entries(outputs)) console.log(`${key}=${value}`);
202204
}
203205

204-
main();
206+
module.exports = { readWorkspace, decide };
207+
208+
if (require.main === module) main();

‎.github/scripts/ci-changes.d.cts‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
interface WorkspacePackage {
2+
readonly name: string;
3+
readonly dir: string;
4+
readonly hasTest: boolean;
5+
readonly deps: ReadonlyArray<string>;
6+
}
7+
8+
export function readWorkspace(): Array<WorkspacePackage>;
9+
10+
export function decide(
11+
files: ReadonlyArray<string> | null,
12+
packages: ReadonlyArray<WorkspacePackage>,
13+
full: boolean,
14+
): {
15+
affected: Array<string>;
16+
outputs: {
17+
typecheck: boolean;
18+
build: boolean;
19+
test: boolean;
20+
test_packages: string;
21+
test_web: boolean;
22+
test_server: boolean;
23+
rust: boolean;
24+
release_smoke: boolean;
25+
mobile_native: boolean;
26+
};
27+
};

‎.github/scripts/thread-transfer-report.test.cjs‎

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ const assert = require("node:assert/strict");
22
const test = require("node:test");
33

44
const {
5-
renderComment,
65
resolve,
76
upsertCommentForCurrentHead,
87
validateResult,
@@ -53,39 +52,6 @@ test("validates the fixed artifact schema", () => {
5352
);
5453
});
5554

56-
test("renders baseline, impact, ceiling, and ceiling changes", () => {
57-
const baseline = result();
58-
const current = result({ measuredTurnWebSocketWireBytes: 260_000 });
59-
current.providers.codex.ceiling = {
60-
...current.providers.codex.ceiling,
61-
measuredTurnWebSocketWireBytes: 330_000,
62-
};
63-
const comment = renderComment({
64-
current,
65-
baseline,
66-
currentRun: {
67-
sha: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
68-
conclusion: "success",
69-
url: "https://github.com/pingdotgg/t3code/actions/runs/2",
70-
},
71-
baselineRun: {
72-
sha: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
73-
matchesBase: true,
74-
url: "https://github.com/pingdotgg/t3code/actions/runs/1",
75-
},
76-
});
77-
78-
assert.match(comment, /Main baseline \| This PR \| Impact \| PR ceiling/);
79-
assert.match(comment, /\+9\.8 KiB \(\+4\.0%\)/);
80-
assert.match(comment, /This PR changes transfer ceilings/);
81-
assert.match(comment, /312\.5 KiB → 322\.3 KiB/);
82-
assert.match(comment, /<!-- t3-thread-transfer-report -->/);
83-
assert.match(
84-
comment,
85-
/<!-- t3-thread-transfer-result-sha:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb -->/,
86-
);
87-
});
88-
8955
test("resolves a fallback PR with a redacted head repo and exact main baseline", async () => {
9056
const outputs = {};
9157
const listWorkflowRunArtifacts = () => {};
@@ -373,21 +339,3 @@ test("preserves a successful result when a same-SHA rerun has no artifact", asyn
373339
assert.equal(published, true);
374340
assert.equal(updatedComment, false);
375341
});
376-
377-
test("accepts V2 without comparing it to the V1 scenario", () => {
378-
const current = result();
379-
current.scenario.id = "thread-transfer-v2";
380-
current.providers.codex.ceiling = { ...current.providers.codex.ceiling, totalWireBytes: 3000000 };
381-
assert.equal(validateResult(current), current);
382-
const comment = renderComment({
383-
current,
384-
baseline: result(),
385-
currentRun: { sha: "bbbbbbbb", conclusion: "success", url: "https://example.com/current" },
386-
baselineRun: { sha: "aaaaaaaa", matchesBase: true, url: "https://example.com/baseline" },
387-
});
388-
assert.match(comment, /fixture changed/);
389-
assert.doesNotMatch(comment, /This PR changes transfer ceilings/);
390-
assert.doesNotMatch(comment, /[+-]\d+\.\d+%/);
391-
current.scenario.id = "unrecognized";
392-
assert.throws(() => validateResult(current), /not supported/);
393-
});
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
const assert = require("node:assert/strict");
2+
const { spawnSync } = require("node:child_process");
3+
const { mkdtempSync, readFileSync, rmSync, existsSync } = require("node:fs");
4+
const { tmpdir } = require("node:os");
5+
const { join } = require("node:path");
6+
const { test } = require("node:test");
7+
8+
const release = readFileSync(join(__dirname, "../workflows/release.yml"), "utf8");
9+
const preview = readFileSync(join(__dirname, "../workflows/web-preview.yml"), "utf8");
10+
const stepPattern =
11+
/ name: (?:Build staged deployment|Deploy preview)\n shell: bash\n run: \|\n((?: .*\n|\n)+)/g;
12+
const steps = [
13+
...Array.from(release.matchAll(stepPattern), (match, index) => [
14+
index === 0 ? "hosted web" : "marketing",
15+
match[1],
16+
]),
17+
...Array.from(preview.matchAll(stepPattern), (match) => ["web preview", match[1]]),
18+
];
19+
assert.equal(steps.length, 3, "Expected both release steps and the preview step");
20+
21+
const url = "https://t3code-fixture-pinglabs.vercel.app";
22+
const warning = 'Error while parsing config file: "/runner/t3code/pnpm-lock.yaml"';
23+
24+
function runStep(script, stdout, exitCode = 0) {
25+
const directory = mkdtempSync(join(tmpdir(), "t3-vercel-output-"));
26+
const outputFile = join(directory, "output");
27+
try {
28+
const result = spawnSync(
29+
"bash",
30+
[
31+
"-c",
32+
'vp() { printf "%s\\n" "$FIXTURE_STDOUT"; return "$FIXTURE_EXIT"; }\n' +
33+
'curl() { printf \'{"id":"fixture-project"}\\n\'; }\n' +
34+
script.replace(/^ /gm, "").replace(/\$\{\{.*?\}\}/g, "fixture"),
35+
],
36+
{
37+
encoding: "utf8",
38+
env: {
39+
PATH: process.env.PATH,
40+
VERCEL_TOKEN: "fixture-token",
41+
VERCEL_ORG_ID: "fixture-org",
42+
VERCEL_PROJECT_ID: "fixture-project",
43+
GITHUB_OUTPUT: outputFile,
44+
FIXTURE_STDOUT: stdout,
45+
FIXTURE_EXIT: String(exitCode),
46+
},
47+
},
48+
);
49+
assert.ifError(result.error);
50+
return {
51+
...result,
52+
output: existsSync(outputFile) ? readFileSync(outputFile, "utf8") : "",
53+
};
54+
} finally {
55+
rmSync(directory, { recursive: true, force: true });
56+
}
57+
}
58+
59+
for (const [name, script] of steps) {
60+
for (const [label, stdout] of [
61+
["plain URL", url],
62+
["lockfile warning", `${warning}\n${url}`],
63+
["trailing diagnostic", `${url}\nDone`],
64+
]) {
65+
test(`${name}: saves one deployment URL after ${label}`, () => {
66+
const result = runStep(script, stdout);
67+
assert.equal(result.status, 0, result.stderr);
68+
assert.deepEqual(
69+
result.output.split("\n").filter((line) => !line.startsWith("project_id=")),
70+
[`deployment_url=${url}`, ""],
71+
);
72+
});
73+
}
74+
75+
for (const [label, stdout, exitCode] of [
76+
["missing URL", warning, 0],
77+
["invalid URL", "https://example.invalid/deployment", 0],
78+
["multiple URLs", `${url}\nhttps://other.vercel.app`, 0],
79+
["failed deployment", url, 1],
80+
]) {
81+
test(`${name}: rejects ${label} without saving output`, () => {
82+
const result = runStep(script, stdout, exitCode);
83+
assert.notEqual(result.status, 0);
84+
assert.equal(result.output, "");
85+
});
86+
}
87+
}

‎.github/workflows/ci.yml‎

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ jobs:
8383
- name: Setup Vite+
8484
uses: ./.github/actions/setup-ci-deps
8585

86+
# electron's install.js (run by ensure:electron) reads this cache before it
87+
# downloads from GitHub. The key changes only with the Electron version.
88+
- name: Cache Electron download
89+
uses: actions/cache@v6
90+
with:
91+
path: ~/.cache/electron
92+
key: electron-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('node_modules/.pnpm/electron@*/node_modules/electron/package.json') }}
93+
8694
- name: Ensure Electron runtime is installed
8795
run: vp run --filter @t3tools/desktop ensure:electron
8896

@@ -132,6 +140,14 @@ jobs:
132140
- name: Setup Vite+
133141
uses: ./.github/actions/setup-ci-deps
134142

143+
# electron's install.js (run by ensure:electron) reads this cache before it
144+
# downloads from GitHub. The key changes only with the Electron version.
145+
- name: Cache Electron download
146+
uses: actions/cache@v6
147+
with:
148+
path: ~/.cache/electron
149+
key: electron-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('node_modules/.pnpm/electron@*/node_modules/electron/package.json') }}
150+
135151
- name: Ensure Electron runtime is installed
136152
id: electron
137153
run: vp run --filter @t3tools/desktop ensure:electron
@@ -222,14 +238,22 @@ jobs:
222238
- name: Setup Vite+
223239
uses: ./.github/actions/setup-ci-deps
224240

241+
# electron's install.js (run by ensure:electron) reads this cache before it
242+
# downloads from GitHub. The key changes only with the Electron version.
243+
- name: Cache Electron download
244+
uses: actions/cache@v6
245+
with:
246+
path: ~/.cache/electron
247+
key: electron-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('node_modules/.pnpm/electron@*/node_modules/electron/package.json') }}
248+
225249
- name: Ensure Electron runtime is installed
226250
run: vp run --filter @t3tools/desktop ensure:electron
227251

228252
- name: Test preview artifact validation
229253
run: python3 -B .github/scripts/stage-preview-bundle.test.py
230254

231255
- name: Test release checks
232-
run: node --test .github/scripts/check-nightly-release.test.cjs
256+
run: node --test .github/scripts/check-nightly-release.test.cjs .github/scripts/vercel-deployment-output.test.cjs
233257

234258
- name: Finish installing browser secret helper build libraries
235259
timeout-minutes: 5
@@ -252,6 +276,7 @@ jobs:
252276
253277
# The web suite is the largest outside the server. In the shared Test job it
254278
# started last and ran alone for about 40s after everything else finished.
279+
# release.yml mirrors this test, test_web, and test_server split.
255280
test_web:
256281
name: Test Web
257282
needs: changes

‎.github/workflows/cursor-hygiene-webhook.yml‎

Lines changed: 0 additions & 52 deletions
This file was deleted.

0 commit comments

Comments
 (0)