nix-openclaw/scripts/select-openclaw-release.mjs
joshp123 8c6267b2c3 fix: decouple source and mac app release pins
Select the latest stable OpenClaw source release independently from the newest public macOS app artifact. Report app lag instead of skipping source releases without desktop assets, and teach yolo to materialize source/app pins separately.

Tests: bash -n scripts/update-pins.sh; node --check scripts/select-openclaw-release.mjs scripts/select-openclaw-release.test.mjs; node scripts/select-openclaw-release.test.mjs; GITHUB_ACTIONS=true scripts/update-pins.sh select; ruby -e 'require "yaml"; YAML.load_file(".github/workflows/yolo-update.yml")'; nix flake show --accept-flake-config --json; git diff --check
2026-05-05 18:22:33 +02:00

101 lines
2.5 KiB
JavaScript

#!/usr/bin/env node
import { pathToFileURL } from "node:url";
export function selectOpenClawRelease(releases) {
if (!Array.isArray(releases)) {
throw new Error("Expected a GitHub releases JSON array");
}
const stableReleases = releases.filter((release) => {
return release && release.draft !== true && release.prerelease !== true;
});
const latestStable = stableReleases[0] ?? null;
const latestStableSource = latestStable
? stableSourceSelection(latestStable)
: null;
const appLagStableReleases = [];
for (const release of stableReleases) {
const tagName = release.tag_name ?? release.tagName;
if (!tagName) {
appLagStableReleases.push({
tagName: null,
reason: "missing-tag",
});
continue;
}
const appAsset = (release.assets ?? []).find((asset) => {
const name = asset?.name;
return (
typeof name === "string" &&
/^OpenClaw-.*\.zip$/.test(name) &&
!/dSYM/i.test(name) &&
Boolean(asset?.browser_download_url)
);
});
if (!appAsset) {
appLagStableReleases.push({
tagName,
reason: "missing-macos-zip",
});
continue;
}
return {
latestStable: latestStableSource
? { tagName: latestStableSource.tagName }
: null,
latestStableSource,
latestMacAppStable: {
tagName,
releaseVersion: tagName.replace(/^v/, ""),
appAssetName: appAsset.name,
appUrl: appAsset.browser_download_url,
},
appLagStableReleases,
};
}
return {
latestStable: latestStableSource
? { tagName: latestStableSource.tagName }
: null,
latestStableSource,
latestMacAppStable: null,
appLagStableReleases,
};
}
function stableSourceSelection(release) {
const tagName = release.tag_name ?? release.tagName;
if (!tagName) {
return null;
}
return {
tagName,
releaseVersion: tagName.replace(/^v/, ""),
};
}
function readStdin() {
return new Promise((resolve, reject) => {
let data = "";
process.stdin.setEncoding("utf8");
process.stdin.on("data", (chunk) => {
data += chunk;
});
process.stdin.on("end", () => resolve(data));
process.stdin.on("error", reject);
});
}
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
const input = await readStdin();
const releases = JSON.parse(input);
const selection = selectOpenClawRelease(releases);
process.stdout.write(`${JSON.stringify(selection, null, 2)}\n`);
}