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

推荐订阅源

博客园 - 叶小钗
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Microsoft Security Blog
Microsoft Security Blog
罗磊的独立博客
大猫的无限游戏
大猫的无限游戏
美团技术团队
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
aimingoo的专栏
aimingoo的专栏
腾讯CDC
WordPress大学
WordPress大学
Apple Machine Learning Research
Apple Machine Learning Research
F
Fortinet All Blogs
G
Google Developers Blog
MongoDB | Blog
MongoDB | Blog
Microsoft Azure Blog
Microsoft Azure Blog
小众软件
小众软件
Engineering at Meta
Engineering at Meta
博客园_首页
B
Blog RSS Feed
D
Docker
M
MIT News - Artificial intelligence
爱范儿
爱范儿
I
InfoQ

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
fix(release): tolerate npm propagation after publish · op...
vincentkoc · 2026-06-16 · via Recent Commits to openclaw:main

@@ -39,6 +39,7 @@ export type NpmViewFields = {

3939

version?: string;

4040

distTagVersion?: string;

4141

integrity?: string;

42+

tarball?: string;

4243

};

43444445

type WorkflowRunSummary = {

@@ -52,6 +53,10 @@ const DEFAULT_REPO = "openclaw/openclaw";

5253

const DEFAULT_CLAWHUB_REGISTRY = "https://clawhub.ai";

5354

const CLAWHUB_REQUEST_TIMEOUT_MS = 20_000;

5455

const CLAWHUB_RESPONSE_BODY_MAX_BYTES = 1024 * 1024;

56+

// Trusted publish can finish before npm registry metadata converges. Keep the

57+

// verifier on the same release train instead of forcing a republish/correction.

58+

const NPM_VIEW_ATTEMPTS = 30;

59+

const NPM_VIEW_RETRY_MAX_DELAY_MS = 10_000;

55605661

function isRecord(value: unknown): value is JsonRecord {

5762

return typeof value === "object" && value !== null && !Array.isArray(value);

@@ -83,6 +88,35 @@ function runCommandInherited(command: string, args: string[]): void {

8388

});

8489

}

859091+

export async function runNpmViewWithRetry(

92+

args: string[],

93+

options: {

94+

attempts?: number;

95+

delay?: (delayMs: number) => Promise<void>;

96+

run?: (args: string[]) => string;

97+

} = {},

98+

): Promise<string> {

99+

const attempts = options.attempts ?? NPM_VIEW_ATTEMPTS;

100+

const delay =

101+

options.delay ??

102+

((delayMs: number) => new Promise((resolveDelay) => setTimeout(resolveDelay, delayMs)));

103+

const run = options.run ?? ((npmArgs: string[]) => runCommand("npm", npmArgs));

104+

let lastError: unknown;

105+106+

for (let attempt = 1; attempt <= attempts; attempt += 1) {

107+

try {

108+

return run([...args, "--prefer-online"]);

109+

} catch (error) {

110+

lastError = error;

111+

}

112+

if (attempt < attempts) {

113+

await delay(Math.min(attempt * 1000, NPM_VIEW_RETRY_MAX_DELAY_MS));

114+

}

115+

}

116+117+

throw lastError;

118+

}

119+86120

function parseJson(raw: string, label: string): unknown {

87121

try {

88122

return JSON.parse(raw) as unknown;

@@ -99,6 +133,7 @@ export function parseNpmViewFields(raw: string, distTag: string): NpmViewFields

99133

version: readString(parsed[0]),

100134

distTagVersion: readString(parsed[1]),

101135

integrity: readString(parsed[2]),

136+

tarball: readString(parsed[3]),

102137

};

103138

}

104139

if (!isRecord(parsed)) {

@@ -110,6 +145,7 @@ export function parseNpmViewFields(raw: string, distTag: string): NpmViewFields

110145

version: readString(parsed.version),

111146

distTagVersion: readString(parsed[`dist-tags.${distTag}`]) ?? readString(distTags?.[distTag]),

112147

integrity: readString(parsed["dist.integrity"]) ?? readString(dist?.integrity),

148+

tarball: readString(parsed["dist.tarball"]) ?? readString(dist?.tarball),

113149

};

114150

}

115151

@@ -269,13 +305,18 @@ async function fetchStatusWithRetry(url: string, method: "GET" | "HEAD"): Promis

269305

return response.status;

270306

}

271307272-

function verifyNpmPackage(packageName: string, version: string, distTag: string): NpmViewFields {

273-

const raw = runCommand("npm", [

308+

async function verifyNpmPackage(

309+

packageName: string,

310+

version: string,

311+

distTag: string,

312+

): Promise<NpmViewFields> {

313+

const raw = await runNpmViewWithRetry([

274314

"view",

275315

`${packageName}@${version}`,

276316

"version",

277317

`dist-tags.${distTag}`,

278318

"dist.integrity",

319+

"dist.tarball",

279320

"--json",

280321

]);

281322

const fields = parseNpmViewFields(raw, distTag);

@@ -292,6 +333,9 @@ function verifyNpmPackage(packageName: string, version: string, distTag: string)

292333

if (fields.integrity === undefined) {

293334

throw new Error(`${packageName}: npm dist.integrity missing for ${version}.`);

294335

}

336+

if (fields.tarball === undefined) {

337+

throw new Error(`${packageName}: npm dist.tarball missing for ${version}.`);

338+

}

295339

return fields;

296340

}

297341

@@ -500,7 +544,7 @@ export async function verifyBetaRelease(

500544

lines.push(`GitHub release OK: ${releaseUrl}`);

501545

}

502546503-

const openclawNpm = verifyNpmPackage("openclaw", args.version, args.distTag);

547+

const openclawNpm = await verifyNpmPackage("openclaw", args.version, args.distTag);

504548

lines.push(`openclaw npm OK: ${args.version} (${args.distTag})`);

505549506550

if (!args.skipPostpublish) {

@@ -522,7 +566,7 @@ export async function verifyBetaRelease(

522566

packages: npmPlugins,

523567

});

524568

for (const plugin of npmPlugins) {

525-

verifyNpmPackage(plugin.packageName, args.version, args.distTag);

569+

await verifyNpmPackage(plugin.packageName, args.version, args.distTag);

526570

}

527571

lines.push(`plugin npm OK: ${npmPlugins.length}`);

528572

@@ -644,6 +688,7 @@ export async function verifyBetaRelease(

644688

npmDistTag: args.distTag,

645689

pluginSelection: args.pluginSelection,

646690

openclawNpmIntegrity: openclawNpm.integrity,

691+

openclawNpmTarball: openclawNpm.tarball,

647692

githubReleaseUrl: releaseUrl ?? null,

648693

pluginNpmPackageCount: npmPlugins.length,

649694

clawHubPackageCount: clawHubPlugins.length,