Vendor OpenClaw source as Adolf fork baseline
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
This commit is contained in:
279
scripts/full-release-validation-at-sha.mjs
Executable file
279
scripts/full-release-validation-at-sha.mjs
Executable file
@@ -0,0 +1,279 @@
|
||||
#!/usr/bin/env node
|
||||
// Dispatches full release validation against a temporary SHA-pinned branch.
|
||||
import { execFileSync, spawnSync } from "node:child_process";
|
||||
import { pathToFileURL } from "node:url";
|
||||
|
||||
const WORKFLOW = "full-release-validation.yml";
|
||||
const DEFAULT_INPUTS = {
|
||||
provider: "openai",
|
||||
mode: "both",
|
||||
release_profile: "full",
|
||||
rerun_group: "all",
|
||||
};
|
||||
|
||||
function usage() {
|
||||
console.error(`Usage: node scripts/full-release-validation-at-sha.mjs [--sha <sha>] [--branch <name>] [--keep-branch] [--dry-run] [-- -f key=value ...]
|
||||
|
||||
Creates a temporary remote branch pinned to the target commit, dispatches Full
|
||||
Release Validation from that branch, watches the parent run, verifies all child
|
||||
workflow head SHAs match, then deletes the temporary branch by default.`);
|
||||
}
|
||||
|
||||
function run(command, args, options = {}) {
|
||||
if (options.dryRun) {
|
||||
console.log(["+", command, ...args].join(" "));
|
||||
return "";
|
||||
}
|
||||
const output = execFileSync(command, args, {
|
||||
encoding: "utf8",
|
||||
stdio: options.stdio ?? ["ignore", "pipe", "inherit"],
|
||||
});
|
||||
return typeof output === "string" ? output.trim() : "";
|
||||
}
|
||||
|
||||
function runStatus(command, args, options = {}) {
|
||||
if (options.dryRun) {
|
||||
console.log(["+", command, ...args].join(" "));
|
||||
return { status: 0, stdout: "" };
|
||||
}
|
||||
return spawnSync(command, args, {
|
||||
encoding: "utf8",
|
||||
stdio: options.stdio ?? ["ignore", "pipe", "inherit"],
|
||||
});
|
||||
}
|
||||
|
||||
function readOptionValue(argv, index, optionName) {
|
||||
const value = argv[index + 1];
|
||||
if (value === undefined || value === "" || value.startsWith("-")) {
|
||||
throw new Error(`${optionName} requires a value`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export function parseArgs(argv) {
|
||||
const args = {
|
||||
sha: "",
|
||||
branch: "",
|
||||
keepBranch: false,
|
||||
dryRun: false,
|
||||
inputs: { ...DEFAULT_INPUTS },
|
||||
};
|
||||
|
||||
for (let i = 0; i < argv.length; i += 1) {
|
||||
const arg = argv[i];
|
||||
if (arg === "--help" || arg === "-h") {
|
||||
usage();
|
||||
process.exit(0);
|
||||
}
|
||||
if (arg === "--sha") {
|
||||
args.sha = readOptionValue(argv, i, arg);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
if (arg === "--branch") {
|
||||
args.branch = readOptionValue(argv, i, arg);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
if (arg === "--keep-branch") {
|
||||
args.keepBranch = true;
|
||||
continue;
|
||||
}
|
||||
if (arg === "--dry-run") {
|
||||
args.dryRun = true;
|
||||
continue;
|
||||
}
|
||||
if (arg === "--") {
|
||||
for (const extra of argv.slice(i + 1)) {
|
||||
const assignment = extra.startsWith("-f") ? extra.slice(2).trim() : extra;
|
||||
const [key, ...valueParts] = assignment.split("=");
|
||||
if (!key || valueParts.length === 0) {
|
||||
throw new Error(`Unsupported extra argument after --: ${extra}`);
|
||||
}
|
||||
args.inputs[key] = valueParts.join("=");
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (arg === "-f") {
|
||||
const assignment = readOptionValue(argv, i, arg);
|
||||
i += 1;
|
||||
const [key, ...valueParts] = assignment.split("=");
|
||||
if (!key || valueParts.length === 0) {
|
||||
throw new Error(`Invalid -f assignment: ${assignment}`);
|
||||
}
|
||||
args.inputs[key] = valueParts.join("=");
|
||||
continue;
|
||||
}
|
||||
if (arg.startsWith("-f") && arg.includes("=")) {
|
||||
const assignment = arg.slice(2).trim();
|
||||
const [key, ...valueParts] = assignment.split("=");
|
||||
if (!key || valueParts.length === 0) {
|
||||
throw new Error(`Invalid -f assignment: ${arg}`);
|
||||
}
|
||||
args.inputs[key] = valueParts.join("=");
|
||||
continue;
|
||||
}
|
||||
throw new Error(`Unknown argument: ${arg}`);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
function sanitizeBranchPart(value) {
|
||||
return value
|
||||
.replace(/[^A-Za-z0-9._/-]+/g, "-")
|
||||
.replace(/\/+/g, "/")
|
||||
.replace(/^[/.-]+|[/.-]+$/g, "")
|
||||
.slice(0, 80);
|
||||
}
|
||||
|
||||
function resolveSha(requestedSha) {
|
||||
const rev = requestedSha || "HEAD";
|
||||
return run("git", ["rev-parse", "--verify", `${rev}^{commit}`], { dryRun: false });
|
||||
}
|
||||
|
||||
function collectRunId(dispatchOutput) {
|
||||
const match = dispatchOutput.match(/actions\/runs\/(\d+)/);
|
||||
return match?.[1] ?? "";
|
||||
}
|
||||
|
||||
function findLatestRunId(branch, sha) {
|
||||
const json = run("gh", [
|
||||
"run",
|
||||
"list",
|
||||
"--workflow",
|
||||
WORKFLOW,
|
||||
"--branch",
|
||||
branch,
|
||||
"--event",
|
||||
"workflow_dispatch",
|
||||
"--limit",
|
||||
"20",
|
||||
"--json",
|
||||
"databaseId,headSha,createdAt",
|
||||
]);
|
||||
const runs = JSON.parse(json);
|
||||
const match = runs.find((runItem) => runItem.headSha === sha);
|
||||
return match?.databaseId ? String(match.databaseId) : "";
|
||||
}
|
||||
|
||||
function childRunIds(parentRunId) {
|
||||
const jobsJson = run("gh", ["run", "view", parentRunId, "--json", "jobs"]);
|
||||
const jobs = JSON.parse(jobsJson).jobs ?? [];
|
||||
const summaryJob = jobs.find((job) => job.name === "Verify full validation");
|
||||
if (!summaryJob?.databaseId) {
|
||||
return [];
|
||||
}
|
||||
const log = run("gh", [
|
||||
"run",
|
||||
"view",
|
||||
parentRunId,
|
||||
"--job",
|
||||
String(summaryJob.databaseId),
|
||||
"--log",
|
||||
]);
|
||||
return [...new Set([...log.matchAll(/actions\/runs\/(\d+)/g)].map((match) => match[1]))];
|
||||
}
|
||||
|
||||
function verifyChildHeads(parentRunId, sha) {
|
||||
const ids = childRunIds(parentRunId);
|
||||
if (ids.length === 0) {
|
||||
throw new Error(
|
||||
`Could not find child workflow run ids in parent verifier logs for ${parentRunId}.`,
|
||||
);
|
||||
}
|
||||
|
||||
let failed = false;
|
||||
for (const id of ids) {
|
||||
const json = run("gh", ["run", "view", id, "--json", "name,status,conclusion,headSha,url"]);
|
||||
const child = JSON.parse(json);
|
||||
const ok =
|
||||
child.headSha === sha && child.status === "completed" && child.conclusion === "success";
|
||||
console.log(
|
||||
`${ok ? "ok" : "bad"} ${child.name} ${child.status}/${child.conclusion} ${child.headSha} ${child.url}`,
|
||||
);
|
||||
failed ||= !ok;
|
||||
}
|
||||
if (failed) {
|
||||
throw new Error(`One or more child workflows failed or did not run at ${sha}.`);
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
const args = parseArgs(process.argv.slice(2));
|
||||
const sha = resolveSha(args.sha);
|
||||
const shortSha = sha.slice(0, 12);
|
||||
const branch = sanitizeBranchPart(args.branch || `release-ci/${shortSha}-${Date.now()}`);
|
||||
const remoteBranchRef = `refs/heads/${branch}`;
|
||||
const dispatchInputs = { ref: sha, ...args.inputs };
|
||||
|
||||
console.log(`Target SHA: ${sha}`);
|
||||
console.log(`Temporary workflow ref: ${branch}`);
|
||||
|
||||
run("git", ["push", "origin", `${sha}:${remoteBranchRef}`], {
|
||||
dryRun: args.dryRun,
|
||||
stdio: "inherit",
|
||||
});
|
||||
|
||||
let parentRunId;
|
||||
try {
|
||||
const dispatchArgs = ["workflow", "run", WORKFLOW, "--ref", branch];
|
||||
for (const [key, value] of Object.entries(dispatchInputs)) {
|
||||
dispatchArgs.push("-f", `${key}=${value}`);
|
||||
}
|
||||
|
||||
const dispatchOutput = run("gh", dispatchArgs, { dryRun: args.dryRun });
|
||||
if (dispatchOutput) {
|
||||
console.log(dispatchOutput);
|
||||
}
|
||||
parentRunId = collectRunId(dispatchOutput);
|
||||
if (!parentRunId && !args.dryRun) {
|
||||
for (let attempt = 0; attempt < 60; attempt += 1) {
|
||||
parentRunId = findLatestRunId(branch, sha);
|
||||
if (parentRunId) {
|
||||
break;
|
||||
}
|
||||
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 5000);
|
||||
}
|
||||
}
|
||||
if (!parentRunId) {
|
||||
if (args.dryRun) {
|
||||
return;
|
||||
}
|
||||
throw new Error("Could not determine Full Release Validation run id.");
|
||||
}
|
||||
|
||||
console.log(`Parent run: https://github.com/openclaw/openclaw/actions/runs/${parentRunId}`);
|
||||
const watch = runStatus(
|
||||
"gh",
|
||||
["run", "watch", parentRunId, "--exit-status", "--interval", "30"],
|
||||
{
|
||||
stdio: "inherit",
|
||||
},
|
||||
);
|
||||
if (watch.status !== 0) {
|
||||
throw new Error(
|
||||
`Full Release Validation failed: https://github.com/openclaw/openclaw/actions/runs/${parentRunId}`,
|
||||
);
|
||||
}
|
||||
verifyChildHeads(parentRunId, sha);
|
||||
} finally {
|
||||
if (!args.keepBranch) {
|
||||
run("git", ["push", "origin", `:${remoteBranchRef}`], {
|
||||
dryRun: args.dryRun,
|
||||
stdio: "inherit",
|
||||
});
|
||||
} else {
|
||||
console.log(`Kept ${remoteBranchRef}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
||||
try {
|
||||
main();
|
||||
} catch (error) {
|
||||
console.error(error instanceof Error ? error.message : String(error));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user