惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

雷峰网
雷峰网
WordPress大学
WordPress大学
MyScale Blog
MyScale Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
The Blog of Author Tim Ferriss
U
Unit 42
罗磊的独立博客
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
The Cloudflare Blog
aimingoo的专栏
aimingoo的专栏
Vercel News
Vercel News
N
Netflix TechBlog - Medium
H
Hackread – Cybersecurity News, Data Breaches, AI and More
云风的 BLOG
云风的 BLOG
Hugging Face - Blog
Hugging Face - Blog
大猫的无限游戏
大猫的无限游戏
F
Fortinet All Blogs
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
博客园 - 【当耐特】
H
Help Net Security
The GitHub Blog
The GitHub Blog

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
ci(release): harden candidate workflow dispatch lookup · ...
steipete · 2026-05-15 · via Recent Commits to openclaw:main

@@ -163,40 +163,57 @@ function gitRevParse(ref) {

163163

return run("git", ["rev-parse", ref], { capture: true }).trim();

164164

}

165165166-

function workflowRuns(repo) {

166+

function workflowRuns(repo, workflowFile) {

167167

return JSON.parse(

168168

run(

169169

"gh",

170170

[

171-

"run",

172-

"list",

173-

"--repo",

174-

repo,

175-

"--limit",

176-

"100",

177-

"--json",

178-

"databaseId,workflowName,event,createdAt",

171+

"api",

172+

`repos/${repo}/actions/workflows/${workflowFile}/runs?event=workflow_dispatch&per_page=100`,

173+

"--jq",

174+

".workflow_runs | map({databaseId:.id, workflowName:.name, event:.event, createdAt:.created_at})",

179175

],

180176

{ capture: true },

181177

),

182178

);

183179

}

184180185-

function beforeRunIds(repo, workflowName) {

186-

return new Set(

187-

workflowRuns(repo)

188-

.filter((run) => run.workflowName === workflowName && run.event === "workflow_dispatch")

189-

.map((run) => String(run.databaseId)),

190-

);

181+

function beforeRunIds(repo, workflowFile) {

182+

return new Set(workflowRuns(repo, workflowFile).map((run) => String(run.databaseId)));

183+

}

184+185+

function runAndEcho(command, args) {

186+

const result = spawnSync(command, args, {

187+

encoding: "utf8",

188+

stdio: ["ignore", "pipe", "pipe"],

189+

});

190+

if (result.stdout) {

191+

process.stdout.write(result.stdout);

192+

}

193+

if (result.stderr) {

194+

process.stderr.write(result.stderr);

195+

}

196+

if (result.status !== 0) {

197+

throw new Error(

198+

`${command} ${args.join(" ")} failed with ${result.status ?? result.signal}\n${

199+

result.stderr ?? ""

200+

}`,

201+

);

202+

}

203+

return `${result.stdout ?? ""}${result.stderr ?? ""}`;

204+

}

205+206+

export function parseRunIdFromDispatchOutput(output) {

207+

return output.match(/actions\/runs\/([0-9]+)/u)?.[1] ?? "";

191208

}

192209193210

async function wait(ms) {

194211

await new Promise((resolve) => setTimeout(resolve, ms));

195212

}

196213197-

async function findNewRunId(repo, workflowName, beforeIds) {

214+

async function findNewRunId(repo, workflowFile, workflowName, beforeIds) {

198215

for (let attempt = 0; attempt < 60; attempt += 1) {

199-

const match = workflowRuns(repo)

216+

const match = workflowRuns(repo, workflowFile)

200217

.filter(

201218

(run) =>

202219

run.workflowName === workflowName &&

@@ -217,7 +234,7 @@ function dispatchWorkflow(repo, workflowFile, workflowRef, fields) {

217234

for (const [key, value] of Object.entries(fields)) {

218235

args.push("-f", `${key}=${value}`);

219236

}

220-

run("gh", args);

237+

return parseRunIdFromDispatchOutput(runAndEcho("gh", args));

221238

}

222239223240

function runInfo(repo, runId) {

@@ -419,26 +436,32 @@ async function main() {

419436

const targetSha = gitRevParse(`${options.tag}^{}`);

420437421438

if (!options.fullReleaseRunId && !options.skipDispatch) {

422-

const before = beforeRunIds(options.repo, "Full Release Validation");

423-

dispatchWorkflow(options.repo, "full-release-validation.yml", options.workflowRef, {

439+

const workflowFile = "full-release-validation.yml";

440+

const before = beforeRunIds(options.repo, workflowFile);

441+

const dispatchedRunId = dispatchWorkflow(options.repo, workflowFile, options.workflowRef, {

424442

ref: options.tag,

425443

provider: options.provider,

426444

mode: options.mode,

427445

release_profile: options.releaseProfile,

428446

run_release_soak: options.releaseProfile === "full" ? "true" : "false",

429447

rerun_group: "all",

430448

});

431-

options.fullReleaseRunId = await findNewRunId(options.repo, "Full Release Validation", before);

449+

options.fullReleaseRunId =

450+

dispatchedRunId ||

451+

(await findNewRunId(options.repo, workflowFile, "Full Release Validation", before));

432452

}

433453434454

if (!options.npmPreflightRunId && !options.skipDispatch) {

435-

const before = beforeRunIds(options.repo, "OpenClaw NPM Release");

436-

dispatchWorkflow(options.repo, "openclaw-npm-release.yml", options.workflowRef, {

455+

const workflowFile = "openclaw-npm-release.yml";

456+

const before = beforeRunIds(options.repo, workflowFile);

457+

const dispatchedRunId = dispatchWorkflow(options.repo, workflowFile, options.workflowRef, {

437458

tag: options.tag,

438459

preflight_only: "true",

439460

npm_dist_tag: options.npmDistTag,

440461

});

441-

options.npmPreflightRunId = await findNewRunId(options.repo, "OpenClaw NPM Release", before);

462+

options.npmPreflightRunId =

463+

dispatchedRunId ||

464+

(await findNewRunId(options.repo, workflowFile, "OpenClaw NPM Release", before));

442465

}

443466444467

const fullRun = await waitForSuccessfulRun(options.repo, options.fullReleaseRunId, {