Files
openchamber/packages/electron/scripts/finalize-latest-yml.mjs
T
Howon LeeandBohdan Triapitsyn 09f0c64839 feat: add Windows ARM64 support with x64-baseline CLI workaround (#2537)
* feat: add Windows ARM64 support with x64-baseline CLI workaround

Windows ARM64 native opencode.exe fails with a Bun FFI/TinyCC dlopen
error (anomalyco/opencode#19130). As a temporary workaround:

- Bundle x64-baseline OpenCode CLI on ARM64 instead of native ARM64
  (prepare-opencode-cli.mjs, env-runtime.js)
- Disable OpenCode self-upgrade on ARM64 in server, VS Code, and UI
  (upgrade-capability.js, opencode-upgrade-runtime.ts, useUIStore.ts,
  OpenCodeCliSettings.tsx, search.ts, SettingsView.tsx, platform.ts)
- Add ARM64 Windows cross-compile builds to release and smoke workflows
  (release.yml, release-desktop-smoke.yml)
- Refactor Windows latest.yml to use combine-electron-manifests pattern
  matching macOS, since two arches now produce per-arch manifests

The CI ARM64 build itself is permanent; only the x64-baseline CLI
bundling and upgrade disablement are temporary and should be reverted
when the upstream issue is resolved.

* fix(desktop): select Windows updater by architecture

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-07-30 20:07:08 +03:00

105 lines
3.4 KiB
JavaScript

#!/usr/bin/env node
import fs from 'node:fs/promises';
import path from 'node:path';
const dir = process.env.LATEST_YML_DIR;
const repo = process.env.GH_REPO;
const version = process.env.OPENCHAMBER_VERSION;
if (!dir) throw new Error('LATEST_YML_DIR is required');
if (!repo) throw new Error('GH_REPO is required');
if (!version) throw new Error('OPENCHAMBER_VERSION is required');
const parse = (content) => {
const lines = content.split('\n');
let releaseDate = '';
let parsedVersion = '';
const files = [];
let current;
const flush = () => {
if (current?.url && current?.sha512 && current?.size) {
files.push(current);
}
current = undefined;
};
for (const line of lines) {
const trimmed = line.trim();
const indented = line.startsWith(' ') || line.startsWith(' -');
if (line.startsWith('version:')) {
parsedVersion = line.slice('version:'.length).trim();
} else if (line.startsWith('releaseDate:')) {
releaseDate = line.slice('releaseDate:'.length).trim().replace(/^'|'$/g, '');
} else if (trimmed.startsWith('- url:')) {
flush();
current = { url: trimmed.slice('- url:'.length).trim() };
} else if (indented && current && trimmed.startsWith('sha512:')) {
current.sha512 = trimmed.slice('sha512:'.length).trim();
} else if (indented && current && trimmed.startsWith('size:')) {
current.size = Number(trimmed.slice('size:'.length).trim());
} else if (indented && current && trimmed.startsWith('blockMapSize:')) {
current.blockMapSize = Number(trimmed.slice('blockMapSize:'.length).trim());
} else if (!indented && current) {
flush();
}
}
flush();
return { version: parsedVersion, releaseDate, files };
};
const serialize = (data) => {
const lines = [`version: ${data.version}`, 'files:'];
for (const file of data.files) {
lines.push(` - url: ${file.url}`);
lines.push(` sha512: ${file.sha512}`);
lines.push(` size: ${file.size}`);
if (file.blockMapSize) {
lines.push(` blockMapSize: ${file.blockMapSize}`);
}
}
lines.push(`releaseDate: '${data.releaseDate}'`);
return `${lines.join('\n')}\n`;
};
const read = async (subdir, filename) => {
const filePath = path.join(dir, subdir, filename);
try {
return parse(await fs.readFile(filePath, 'utf8'));
} catch {
return null;
}
};
const output = {};
const winX64 = await read('latest-yml-x86_64-pc-windows-msvc', 'latest.yml');
const winArm64 = await read('latest-yml-aarch64-pc-windows-msvc', 'latest.yml');
if (!winX64 || !winArm64) {
throw new Error('Both x64 and arm64 Windows update manifests are required');
}
output['latest.yml'] = serialize(winX64);
output['latest-arm64.yml'] = serialize(winArm64);
const macX64 = await read('latest-yml-x86_64-apple-darwin', 'latest-mac.yml');
const macArm64 = await read('latest-yml-aarch64-apple-darwin', 'latest-mac.yml');
if (macX64 || macArm64) {
const base = macArm64 || macX64;
output['latest-mac.yml'] = serialize({
version: base.version,
files: [...(macArm64?.files || []), ...(macX64?.files || [])],
releaseDate: base.releaseDate,
});
}
const tag = `v${version}`;
const tmp = process.env.RUNNER_TEMP || '/tmp';
for (const [filename, content] of Object.entries(output)) {
const outputPath = path.join(tmp, filename);
await fs.writeFile(outputPath, content);
console.log(`prepared ${outputPath} for upload to ${repo} release ${tag}`);
}
console.log('finalized latest yml files');