From b3a16f543720f777ae71b2a53cdaa37809d2ee0d Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 16 Apr 2026 17:37:54 -0700 Subject: [PATCH 1/3] fix: repair Windows release manifest publishing Co-authored-by: codex --- .github/workflows/release.yml | 2 +- scripts/release-smoke.ts | 95 ++++++++++++++++++++++++++++++++--- 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cd7387e966..83931a822d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -367,7 +367,7 @@ jobs: run: | shopt -s nullglob found_windows_manifest=false - for x64_manifest in release-assets/*-win-x64.yml; do + for x64_manifest in release-assets/latest*-win-x64.yml; do arm64_manifest="${x64_manifest/-x64.yml/-arm64.yml}" output_manifest="${x64_manifest/-win-x64.yml/.yml}" if [[ ! -f "$arm64_manifest" ]]; then diff --git a/scripts/release-smoke.ts b/scripts/release-smoke.ts index 9c4a415106..a5d6521c4e 100644 --- a/scripts/release-smoke.ts +++ b/scripts/release-smoke.ts @@ -1,5 +1,13 @@ import { execFileSync } from "node:child_process"; -import { cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { + cpSync, + existsSync, + mkdirSync, + mkdtempSync, + readFileSync, + rmSync, + writeFileSync, +} from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; @@ -112,12 +120,46 @@ releaseDate: '2026-03-08T10:36:07.540Z' return { arm64Path, x64Path }; } +function writeWindowsBuilderDebugFixtures(targetRoot: string): { + arm64Path: string; + x64Path: string; +} { + const assetDirectory = resolve(targetRoot, "release-assets"); + mkdirSync(assetDirectory, { recursive: true }); + + const arm64Path = resolve(assetDirectory, "builder-debug-win-arm64.yml"); + const x64Path = resolve(assetDirectory, "builder-debug-win-x64.yml"); + const debugFixture = `arm64: + firstOrDefaultFilePatterns: + - '**/*' +nsis: + script: |- + !include "example.nsh" +`; + + writeFileSync(arm64Path, debugFixture); + writeFileSync(x64Path, debugFixture); + + return { arm64Path, x64Path }; +} function assertContains(haystack: string, needle: string, message: string): void { if (!haystack.includes(needle)) { throw new Error(message); } } +function assertExists(path: string, message: string): void { + if (!existsSync(path)) { + throw new Error(message); + } +} + +function assertMissing(path: string, message: string): void { + if (existsSync(path)) { + throw new Error(message); + } +} + const tempRoot = mkdtempSync(join(tmpdir(), "t3-release-smoke-")); try { @@ -212,14 +254,38 @@ try { ); const { arm64Path: winArm64Path, x64Path: winX64Path } = writeWindowsManifestFixtures(tempRoot); + const mergedWindowsManifestPath = resolve(tempRoot, "release-assets/latest.yml"); + const { arm64Path: winDebugArm64Path, x64Path: winDebugX64Path } = + writeWindowsBuilderDebugFixtures(tempRoot); execFileSync( - process.execPath, + "bash", [ - resolve(repoRoot, "scripts/merge-update-manifests.ts"), - "--platform", - "win", - winArm64Path, - winX64Path, + "-lc", + ` + release_assets_dir=${JSON.stringify(resolve(tempRoot, "release-assets"))} + shopt -s nullglob + found_windows_manifest=false + for x64_manifest in "$release_assets_dir"/latest*-win-x64.yml; do + arm64_manifest="\${x64_manifest/-x64.yml/-arm64.yml}" + output_manifest="\${x64_manifest/-win-x64.yml/.yml}" + if [[ ! -f "$arm64_manifest" ]]; then + echo "Missing matching arm64 Windows manifest for $x64_manifest" >&2 + exit 1 + fi + + found_windows_manifest=true + node ${JSON.stringify(resolve(repoRoot, "scripts/merge-update-manifests.ts"))} --platform win \ + "$arm64_manifest" \ + "$x64_manifest" \ + "$output_manifest" + rm -f "$arm64_manifest" "$x64_manifest" + done + + if [[ "$found_windows_manifest" != true ]]; then + echo "No Windows updater manifests found to merge." >&2 + exit 1 + fi + `, ], { cwd: repoRoot, @@ -227,7 +293,7 @@ try { }, ); - const mergedWindowsManifest = readFileSync(winArm64Path, "utf8"); + const mergedWindowsManifest = readFileSync(mergedWindowsManifestPath, "utf8"); assertContains( mergedWindowsManifest, "T3-Code-9.9.9-smoke.0-arm64.exe", @@ -238,6 +304,19 @@ try { "T3-Code-9.9.9-smoke.0-x64.exe", "Merged Windows manifest is missing the x64 asset.", ); + assertMissing( + winArm64Path, + "Windows release smoke unexpectedly kept the arm64 updater manifest.", + ); + assertMissing(winX64Path, "Windows release smoke unexpectedly kept the x64 updater manifest."); + assertExists( + winDebugArm64Path, + "Windows release smoke unexpectedly removed the arm64 builder debug fixture.", + ); + assertExists( + winDebugX64Path, + "Windows release smoke unexpectedly removed the x64 builder debug fixture.", + ); console.log("Release smoke checks passed."); } finally { From 8938f0c5677f253ae10a2f55186a4261495b4a44 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 16 Apr 2026 17:49:37 -0700 Subject: [PATCH 2/3] fix: include nightly Windows release manifests Co-authored-by: codex --- .github/workflows/release.yml | 2 +- scripts/release-smoke.ts | 38 ++++++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 83931a822d..6c61844691 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -367,7 +367,7 @@ jobs: run: | shopt -s nullglob found_windows_manifest=false - for x64_manifest in release-assets/latest*-win-x64.yml; do + for x64_manifest in release-assets/latest*-win-x64.yml release-assets/nightly*-win-x64.yml; do arm64_manifest="${x64_manifest/-x64.yml/-arm64.yml}" output_manifest="${x64_manifest/-win-x64.yml/.yml}" if [[ ! -f "$arm64_manifest" ]]; then diff --git a/scripts/release-smoke.ts b/scripts/release-smoke.ts index a5d6521c4e..b624c35bf3 100644 --- a/scripts/release-smoke.ts +++ b/scripts/release-smoke.ts @@ -78,12 +78,15 @@ releaseDate: '2026-03-08T10:36:07.540Z' return { arm64Path, x64Path }; } -function writeWindowsManifestFixtures(targetRoot: string): { arm64Path: string; x64Path: string } { +function writeWindowsManifestFixtures( + targetRoot: string, + channel: "latest" | "nightly", +): { arm64Path: string; x64Path: string } { const assetDirectory = resolve(targetRoot, "release-assets"); mkdirSync(assetDirectory, { recursive: true }); - const arm64Path = resolve(assetDirectory, "latest-win-arm64.yml"); - const x64Path = resolve(assetDirectory, "latest-win-x64.yml"); + const arm64Path = resolve(assetDirectory, `${channel}-win-arm64.yml`); + const x64Path = resolve(assetDirectory, `${channel}-win-x64.yml`); writeFileSync( arm64Path, @@ -253,8 +256,14 @@ try { "Merged manifest is missing the x64 asset.", ); - const { arm64Path: winArm64Path, x64Path: winX64Path } = writeWindowsManifestFixtures(tempRoot); + const { arm64Path: winArm64Path, x64Path: winX64Path } = writeWindowsManifestFixtures( + tempRoot, + "latest", + ); const mergedWindowsManifestPath = resolve(tempRoot, "release-assets/latest.yml"); + const { arm64Path: nightlyWinArm64Path, x64Path: nightlyWinX64Path } = + writeWindowsManifestFixtures(tempRoot, "nightly"); + const mergedNightlyWindowsManifestPath = resolve(tempRoot, "release-assets/nightly.yml"); const { arm64Path: winDebugArm64Path, x64Path: winDebugX64Path } = writeWindowsBuilderDebugFixtures(tempRoot); execFileSync( @@ -265,7 +274,7 @@ try { release_assets_dir=${JSON.stringify(resolve(tempRoot, "release-assets"))} shopt -s nullglob found_windows_manifest=false - for x64_manifest in "$release_assets_dir"/latest*-win-x64.yml; do + for x64_manifest in "$release_assets_dir"/latest*-win-x64.yml "$release_assets_dir"/nightly*-win-x64.yml; do arm64_manifest="\${x64_manifest/-x64.yml/-arm64.yml}" output_manifest="\${x64_manifest/-win-x64.yml/.yml}" if [[ ! -f "$arm64_manifest" ]]; then @@ -304,11 +313,30 @@ try { "T3-Code-9.9.9-smoke.0-x64.exe", "Merged Windows manifest is missing the x64 asset.", ); + const mergedNightlyWindowsManifest = readFileSync(mergedNightlyWindowsManifestPath, "utf8"); + assertContains( + mergedNightlyWindowsManifest, + "T3-Code-9.9.9-smoke.0-arm64.exe", + "Merged nightly Windows manifest is missing the arm64 asset.", + ); + assertContains( + mergedNightlyWindowsManifest, + "T3-Code-9.9.9-smoke.0-x64.exe", + "Merged nightly Windows manifest is missing the x64 asset.", + ); assertMissing( winArm64Path, "Windows release smoke unexpectedly kept the arm64 updater manifest.", ); assertMissing(winX64Path, "Windows release smoke unexpectedly kept the x64 updater manifest."); + assertMissing( + nightlyWinArm64Path, + "Windows release smoke unexpectedly kept the nightly arm64 updater manifest.", + ); + assertMissing( + nightlyWinX64Path, + "Windows release smoke unexpectedly kept the nightly x64 updater manifest.", + ); assertExists( winDebugArm64Path, "Windows release smoke unexpectedly removed the arm64 builder debug fixture.", From 98ef886feb0c442e92351117e6bd1ab60ec184bc Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 16 Apr 2026 17:51:49 -0700 Subject: [PATCH 3/3] refactor: generalize Windows manifest merging Co-authored-by: codex --- .github/workflows/release.yml | 6 +++++- scripts/release-smoke.ts | 30 ++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6c61844691..857d951d75 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -367,7 +367,11 @@ jobs: run: | shopt -s nullglob found_windows_manifest=false - for x64_manifest in release-assets/latest*-win-x64.yml release-assets/nightly*-win-x64.yml; do + for x64_manifest in release-assets/*-win-x64.yml; do + if [[ "$(basename "$x64_manifest")" == builder-debug-* ]]; then + continue + fi + arm64_manifest="${x64_manifest/-x64.yml/-arm64.yml}" output_manifest="${x64_manifest/-win-x64.yml/.yml}" if [[ ! -f "$arm64_manifest" ]]; then diff --git a/scripts/release-smoke.ts b/scripts/release-smoke.ts index b624c35bf3..0d95b4945d 100644 --- a/scripts/release-smoke.ts +++ b/scripts/release-smoke.ts @@ -80,7 +80,7 @@ releaseDate: '2026-03-08T10:36:07.540Z' function writeWindowsManifestFixtures( targetRoot: string, - channel: "latest" | "nightly", + channel: string, ): { arm64Path: string; x64Path: string } { const assetDirectory = resolve(targetRoot, "release-assets"); mkdirSync(assetDirectory, { recursive: true }); @@ -264,6 +264,9 @@ try { const { arm64Path: nightlyWinArm64Path, x64Path: nightlyWinX64Path } = writeWindowsManifestFixtures(tempRoot, "nightly"); const mergedNightlyWindowsManifestPath = resolve(tempRoot, "release-assets/nightly.yml"); + const { arm64Path: previewWinArm64Path, x64Path: previewWinX64Path } = + writeWindowsManifestFixtures(tempRoot, "preview"); + const mergedPreviewWindowsManifestPath = resolve(tempRoot, "release-assets/preview.yml"); const { arm64Path: winDebugArm64Path, x64Path: winDebugX64Path } = writeWindowsBuilderDebugFixtures(tempRoot); execFileSync( @@ -274,7 +277,11 @@ try { release_assets_dir=${JSON.stringify(resolve(tempRoot, "release-assets"))} shopt -s nullglob found_windows_manifest=false - for x64_manifest in "$release_assets_dir"/latest*-win-x64.yml "$release_assets_dir"/nightly*-win-x64.yml; do + for x64_manifest in "$release_assets_dir"/*-win-x64.yml; do + if [[ "$(basename "$x64_manifest")" == builder-debug-* ]]; then + continue + fi + arm64_manifest="\${x64_manifest/-x64.yml/-arm64.yml}" output_manifest="\${x64_manifest/-win-x64.yml/.yml}" if [[ ! -f "$arm64_manifest" ]]; then @@ -324,6 +331,17 @@ try { "T3-Code-9.9.9-smoke.0-x64.exe", "Merged nightly Windows manifest is missing the x64 asset.", ); + const mergedPreviewWindowsManifest = readFileSync(mergedPreviewWindowsManifestPath, "utf8"); + assertContains( + mergedPreviewWindowsManifest, + "T3-Code-9.9.9-smoke.0-arm64.exe", + "Merged preview Windows manifest is missing the arm64 asset.", + ); + assertContains( + mergedPreviewWindowsManifest, + "T3-Code-9.9.9-smoke.0-x64.exe", + "Merged preview Windows manifest is missing the x64 asset.", + ); assertMissing( winArm64Path, "Windows release smoke unexpectedly kept the arm64 updater manifest.", @@ -337,6 +355,14 @@ try { nightlyWinX64Path, "Windows release smoke unexpectedly kept the nightly x64 updater manifest.", ); + assertMissing( + previewWinArm64Path, + "Windows release smoke unexpectedly kept the preview arm64 updater manifest.", + ); + assertMissing( + previewWinX64Path, + "Windows release smoke unexpectedly kept the preview x64 updater manifest.", + ); assertExists( winDebugArm64Path, "Windows release smoke unexpectedly removed the arm64 builder debug fixture.",