



















@@ -39,6 +39,7 @@ export type NpmViewFields = {
3939version?: string;
4040distTagVersion?: string;
4141integrity?: string;
42+tarball?: string;
4243};
43444445type WorkflowRunSummary = {
@@ -52,6 +53,10 @@ const DEFAULT_REPO = "openclaw/openclaw";
5253const DEFAULT_CLAWHUB_REGISTRY = "https://clawhub.ai";
5354const CLAWHUB_REQUEST_TIMEOUT_MS = 20_000;
5455const 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;
55605661function isRecord(value: unknown): value is JsonRecord {
5762return 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+86120function parseJson(raw: string, label: string): unknown {
87121try {
88122return JSON.parse(raw) as unknown;
@@ -99,6 +133,7 @@ export function parseNpmViewFields(raw: string, distTag: string): NpmViewFields
99133version: readString(parsed[0]),
100134distTagVersion: readString(parsed[1]),
101135integrity: readString(parsed[2]),
136+tarball: readString(parsed[3]),
102137};
103138}
104139if (!isRecord(parsed)) {
@@ -110,6 +145,7 @@ export function parseNpmViewFields(raw: string, distTag: string): NpmViewFields
110145version: readString(parsed.version),
111146distTagVersion: readString(parsed[`dist-tags.${distTag}`]) ?? readString(distTags?.[distTag]),
112147integrity: 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
269305return 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]);
281322const fields = parseNpmViewFields(raw, distTag);
@@ -292,6 +333,9 @@ function verifyNpmPackage(packageName: string, version: string, distTag: string)
292333if (fields.integrity === undefined) {
293334throw 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+}
295339return fields;
296340}
297341@@ -500,7 +544,7 @@ export async function verifyBetaRelease(
500544lines.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);
504548lines.push(`openclaw npm OK: ${args.version} (${args.distTag})`);
505549506550if (!args.skipPostpublish) {
@@ -522,7 +566,7 @@ export async function verifyBetaRelease(
522566packages: npmPlugins,
523567});
524568for (const plugin of npmPlugins) {
525-verifyNpmPackage(plugin.packageName, args.version, args.distTag);
569+await verifyNpmPackage(plugin.packageName, args.version, args.distTag);
526570}
527571lines.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,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。