Files
AgentCompany/scripts/generate-landing-release-links.mjs
T
2026-04-04 12:03:50 -04:00

241 lines
6.9 KiB
JavaScript

import { readdir, readFile, writeFile } from "node:fs/promises";
import { existsSync } from "node:fs";
import { join } from "node:path";
const rootDir = process.cwd();
const localReleaseDir = join(rootDir, "local-release");
const outputPath = join(rootDir, "landing", "components", "release-links.generated.ts");
async function loadEnvFile(filePath) {
if (!existsSync(filePath)) return;
const content = await readFile(filePath, "utf8");
for (const rawLine of content.split(/\r?\n/)) {
const line = rawLine.trim();
if (!line || line.startsWith("#")) continue;
const separatorIndex = line.indexOf("=");
if (separatorIndex <= 0) continue;
const key = line.slice(0, separatorIndex).trim();
if (!key || process.env[key]) continue;
const rawValue = line.slice(separatorIndex + 1).trim();
if (!rawValue) continue;
process.env[key] = rawValue.replace(/^['"]|['"]$/g, "");
}
}
function normalizeBaseUrl(url) {
return url.replace(/\/+$/, "");
}
function normalizePathSegment(pathValue) {
return pathValue.replace(/^\/+|\/+$/g, "");
}
function resolveUpdateBaseUrl() {
const explicit = process.env.AGENTCOMPANY_UPDATE_URL?.trim();
if (explicit) return normalizeBaseUrl(explicit);
const publicBaseUrl =
process.env.AGENTCOMPANY_R2_PUBLIC_URL?.trim() ||
process.env.R2_PUBLIC_BASE_URL?.trim();
const prefix = process.env.AGENTCOMPANY_RELEASE_PREFIX?.trim() || "AC";
if (!publicBaseUrl) {
throw new Error("Missing AGENTCOMPANY_UPDATE_URL / R2 public URL while generating landing release links.");
}
const normalizedBase = normalizeBaseUrl(publicBaseUrl);
const normalizedPrefix = normalizePathSegment(prefix);
return `${normalizedBase}/${normalizedPrefix}`;
}
function ensureSingle(files, predicate, label) {
const matches = files.filter(predicate);
if (matches.length !== 1) {
throw new Error(`Expected exactly one ${label} artifact, found ${matches.length}: ${matches.join(", ")}`);
}
return matches[0];
}
function extractVersion(fileNames) {
const versions = new Set(
fileNames
.map((fileName) => fileName.match(/(\d+\.\d+\.\d+)/)?.[1] ?? null)
.filter(Boolean),
);
if (versions.size !== 1) {
throw new Error(`Expected exactly one release version across artifacts, found: ${[...versions].join(", ")}`);
}
return [...versions][0];
}
function urlFor(baseUrl, fileName) {
return `${baseUrl}/${encodeURIComponent(fileName)}`;
}
async function main() {
await loadEnvFile(join(rootDir, ".env.release.local"));
await loadEnvFile(join(rootDir, ".env.release"));
if (!existsSync(localReleaseDir)) {
throw new Error(`Local release directory not found: ${localReleaseDir}`);
}
const baseUrl = resolveUpdateBaseUrl();
const macFiles = (await readdir(join(localReleaseDir, "mac"))).filter((name) => !name.startsWith("."));
const winFiles = (await readdir(join(localReleaseDir, "win"))).filter((name) => !name.startsWith("."));
const linuxFiles = (await readdir(join(localReleaseDir, "linux"))).filter((name) => !name.startsWith("."));
const macArm64Dmg = ensureSingle(macFiles, (name) => name.endsWith(".dmg") && name.includes("arm64"), "macOS Apple Silicon .dmg");
const macIntelDmg = ensureSingle(macFiles, (name) => name.endsWith(".dmg") && !name.includes("arm64"), "macOS Intel .dmg");
const windowsUniversalInstaller = ensureSingle(
winFiles,
(name) => name.endsWith(".exe") && name.includes("Setup"),
"Windows universal installer",
);
const linuxX64AppImage = ensureSingle(
linuxFiles,
(name) => name.endsWith(".AppImage") && !name.includes("arm64"),
"Linux x64 AppImage",
);
const linuxArm64AppImage = ensureSingle(
linuxFiles,
(name) => name.endsWith(".AppImage") && name.includes("arm64"),
"Linux arm64 AppImage",
);
const linuxX64Deb = ensureSingle(
linuxFiles,
(name) => name.endsWith(".deb") && name.includes("amd64"),
"Linux x64 .deb",
);
const linuxArm64Deb = ensureSingle(
linuxFiles,
(name) => name.endsWith(".deb") && name.includes("arm64"),
"Linux arm64 .deb",
);
const linuxX64Rpm = ensureSingle(
linuxFiles,
(name) => name.endsWith(".rpm") && (name.includes("x86_64") || name.includes("amd64")),
"Linux x64 .rpm",
);
const linuxArm64Rpm = ensureSingle(
linuxFiles,
(name) => name.endsWith(".rpm") && (name.includes("aarch64") || name.includes("arm64")),
"Linux arm64 .rpm",
);
const version = extractVersion([
macArm64Dmg,
macIntelDmg,
windowsUniversalInstaller,
linuxX64AppImage,
linuxArm64AppImage,
linuxX64Deb,
linuxArm64Deb,
linuxX64Rpm,
linuxArm64Rpm,
]);
const content = `export type PlatformDownloadAsset = {
id: string;
label: string;
href: string;
note: string;
};
export type PlatformDownload = {
id: "macos" | "windows" | "linux";
title: string;
note: string;
assets: PlatformDownloadAsset[];
};
export const releaseVersion = "${version}";
export const platformDownloads: PlatformDownload[] = [
{
id: "macos",
title: "macOS",
note: "Signed + notarized DMG builds",
assets: [
{
id: "macos-arm64-dmg",
label: "Apple Silicon DMG",
href: "${urlFor(baseUrl, macArm64Dmg)}",
note: "arm64",
},
{
id: "macos-x64-dmg",
label: "Intel Mac DMG",
href: "${urlFor(baseUrl, macIntelDmg)}",
note: "x64",
},
],
},
{
id: "windows",
title: "Windows",
note: "NSIS installer builds",
assets: [
{
id: "windows-universal-installer",
label: "Windows Universal Installer",
href: "${urlFor(baseUrl, windowsUniversalInstaller)}",
note: "arm64 + x64 + ia32",
},
],
},
{
id: "linux",
title: "Linux",
note: "AppImage, DEB, and RPM builds",
assets: [
{
id: "linux-x64-appimage",
label: "Linux x64 AppImage",
href: "${urlFor(baseUrl, linuxX64AppImage)}",
note: "x64",
},
{
id: "linux-x64-deb",
label: "Linux x64 DEB",
href: "${urlFor(baseUrl, linuxX64Deb)}",
note: "x64",
},
{
id: "linux-x64-rpm",
label: "Linux x64 RPM",
href: "${urlFor(baseUrl, linuxX64Rpm)}",
note: "x64",
},
{
id: "linux-arm64-appimage",
label: "Linux ARM64 AppImage",
href: "${urlFor(baseUrl, linuxArm64AppImage)}",
note: "arm64",
},
{
id: "linux-arm64-deb",
label: "Linux ARM64 DEB",
href: "${urlFor(baseUrl, linuxArm64Deb)}",
note: "arm64",
},
{
id: "linux-arm64-rpm",
label: "Linux ARM64 RPM",
href: "${urlFor(baseUrl, linuxArm64Rpm)}",
note: "arm64",
},
],
},
];
`;
await writeFile(outputPath, content, "utf8");
console.log(`[generate-landing-release-links] wrote ${outputPath}`);
console.log(`[generate-landing-release-links] version ${version}`);
}
await main();