mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
188 lines
4.9 KiB
JavaScript
188 lines
4.9 KiB
JavaScript
import { execFileSync } from "node:child_process";
|
|
import { join, resolve } from "node:path";
|
|
import { cpSync, existsSync, mkdtempSync, rmSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
|
|
const repo = process.env.GITHUB_REPOSITORY ?? "block/sprout";
|
|
const version = requireVersionEnv();
|
|
const versionTag = `desktop/v${version}`;
|
|
const latestTag = "sprout-desktop-latest";
|
|
const dryRun = process.env.DRY_RUN === "true" || process.env.DRY_RUN === "1";
|
|
|
|
const dmgName = `Sprout_${version}_aarch64.dmg`;
|
|
const latestAssetName = "Sprout-latest-aarch64.dmg";
|
|
|
|
const defaultDmgDirs = [
|
|
"src-tauri/target/aarch64-apple-darwin/release/bundle/dmg",
|
|
"src-tauri/target/release/bundle/dmg",
|
|
];
|
|
const dmgDir = resolve(
|
|
process.cwd(),
|
|
process.env.DMG_BUNDLE_DIR ??
|
|
defaultDmgDirs.find((dir) =>
|
|
existsSync(resolve(process.cwd(), dir, dmgName)),
|
|
) ??
|
|
defaultDmgDirs[0],
|
|
);
|
|
const dmgPath = join(dmgDir, dmgName);
|
|
|
|
function requireVersionEnv() {
|
|
const v = process.env.VERSION;
|
|
if (!v || !v.trim()) {
|
|
throw new Error(
|
|
"VERSION env var is required. CI sets this from the git tag; for local use, run: VERSION=x.y.z pnpm run release:dmg:publish",
|
|
);
|
|
}
|
|
return v.trim();
|
|
}
|
|
|
|
function quote(arg) {
|
|
if (/^[a-zA-Z0-9._:/=-]+$/.test(arg)) return arg;
|
|
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
}
|
|
|
|
function runGh(args, options = {}) {
|
|
return execFileSync("gh", args, options);
|
|
}
|
|
|
|
function releaseExists(tag) {
|
|
try {
|
|
runGh(["release", "view", tag, "--repo", repo], { stdio: "ignore" });
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function ensureRelease(tag, { title, prerelease }) {
|
|
if (releaseExists(tag)) {
|
|
return;
|
|
}
|
|
|
|
const args = [
|
|
"release",
|
|
"create",
|
|
tag,
|
|
"--repo",
|
|
repo,
|
|
"--title",
|
|
title,
|
|
"--notes",
|
|
"Automated release placeholder.",
|
|
];
|
|
if (prerelease) {
|
|
args.push("--prerelease");
|
|
}
|
|
|
|
runGh(args, { stdio: "inherit" });
|
|
}
|
|
|
|
function readReleaseAssets(tag) {
|
|
const assetsRaw = runGh(
|
|
[
|
|
"release",
|
|
"view",
|
|
tag,
|
|
"--repo",
|
|
repo,
|
|
"--json",
|
|
"assets",
|
|
"--jq",
|
|
".assets[].name",
|
|
],
|
|
{ encoding: "utf-8" },
|
|
);
|
|
return assetsRaw
|
|
.split("\n")
|
|
.map((line) => line.trim())
|
|
.filter((line) => line.length > 0);
|
|
}
|
|
|
|
function assetUrl(tag, name) {
|
|
return `https://github.com/${repo}/releases/download/${tag}/${encodeURIComponent(name)}`;
|
|
}
|
|
|
|
function main() {
|
|
if (!existsSync(dmgPath)) {
|
|
throw new Error(`Missing DMG artifact: ${dmgPath}`);
|
|
}
|
|
|
|
const stageDir = mkdtempSync(join(tmpdir(), "sprout-release-dmg-"));
|
|
const latestAliasPath = join(stageDir, latestAssetName);
|
|
|
|
try {
|
|
cpSync(dmgPath, latestAliasPath);
|
|
|
|
const uploadVersionedArgs = [
|
|
"release",
|
|
"upload",
|
|
versionTag,
|
|
dmgPath,
|
|
"--repo",
|
|
repo,
|
|
"--clobber",
|
|
];
|
|
const uploadLatestArgs = [
|
|
"release",
|
|
"upload",
|
|
latestTag,
|
|
latestAliasPath,
|
|
"--repo",
|
|
repo,
|
|
"--clobber",
|
|
];
|
|
|
|
console.log(`Preparing DMG upload for ${repo}`);
|
|
console.log(`- version tag: ${versionTag}`);
|
|
console.log(`- latest tag: ${latestTag}`);
|
|
console.log(`- versioned asset: ${dmgName}`);
|
|
console.log(`- latest alias: ${latestAssetName}`);
|
|
|
|
if (dryRun) {
|
|
console.log("DRY_RUN enabled. Skipping upload.");
|
|
console.log(`gh release view ${quote(versionTag)} --repo ${quote(repo)}`);
|
|
console.log(
|
|
`gh release view ${quote(latestTag)} --repo ${quote(repo)} || gh release create ${quote(latestTag)} --repo ${quote(repo)} --title ${quote("Sprout Desktop Latest")} --notes ${quote("Automated release placeholder.")}`,
|
|
);
|
|
console.log(`gh ${uploadVersionedArgs.map(quote).join(" ")}`);
|
|
console.log(`gh ${uploadLatestArgs.map(quote).join(" ")}`);
|
|
console.log(`Versioned URL: ${assetUrl(versionTag, dmgName)}`);
|
|
console.log(`Channel URL: ${assetUrl(latestTag, latestAssetName)}`);
|
|
return;
|
|
}
|
|
|
|
ensureRelease(versionTag, {
|
|
title: `Sprout v${version}`,
|
|
prerelease: false,
|
|
});
|
|
ensureRelease(latestTag, {
|
|
title: "Sprout Desktop Latest",
|
|
prerelease: false,
|
|
});
|
|
|
|
runGh(uploadVersionedArgs, { stdio: "inherit" });
|
|
runGh(uploadLatestArgs, { stdio: "inherit" });
|
|
|
|
const versionAssets = readReleaseAssets(versionTag);
|
|
const latestAssets = readReleaseAssets(latestTag);
|
|
if (!versionAssets.includes(dmgName)) {
|
|
throw new Error(
|
|
`Release ${versionTag} is missing versioned asset ${dmgName} after upload`,
|
|
);
|
|
}
|
|
if (!latestAssets.includes(latestAssetName)) {
|
|
throw new Error(
|
|
`Release ${latestTag} is missing latest alias asset ${latestAssetName} after upload`,
|
|
);
|
|
}
|
|
|
|
console.log("GitHub DMG assets verified.");
|
|
console.log(`Versioned URL: ${assetUrl(versionTag, dmgName)}`);
|
|
console.log(`Channel URL: ${assetUrl(latestTag, latestAssetName)}`);
|
|
} finally {
|
|
rmSync(stageDir, { recursive: true, force: true });
|
|
}
|
|
}
|
|
|
|
main();
|