@@ -179,22 +179,36 @@ function sleep(ms) {
179179 } ) ;
180180}
181181
182+ function nextRetryDelay ( attempt , attempts , delayMs , options ) {
183+ if ( attempt >= attempts ) return null ;
184+ if ( options . deadline === undefined ) return delayMs ;
185+
186+ const now = options . now || Date . now ;
187+ const remainingMs = options . deadline - now ( ) ;
188+ if ( remainingMs <= 0 ) return null ;
189+ return Math . min ( delayMs , remainingMs ) ;
190+ }
191+
182192async function waitForNpmLatest ( name , expectedVersion , options = { } ) {
183193 const attempts =
184194 options . attempts || Number ( process . env . RELEASE_ASSERT_ATTEMPTS || DEFAULT_ATTEMPTS ) ;
185195 const delayMs =
186196 options . delayMs || Number ( process . env . RELEASE_ASSERT_DELAY_MS || DEFAULT_DELAY_MS ) ;
197+ const wait = options . sleep || sleep ;
187198
188199 let latest = null ;
189200 for ( let attempt = 1 ; attempt <= attempts ; attempt += 1 ) {
190201 latest = npmLatest ( name ) ;
191202 if ( latest === expectedVersion ) return latest ;
192203
193- if ( attempt < attempts ) {
204+ const retryDelay = nextRetryDelay ( attempt , attempts , delayMs , options ) ;
205+ if ( retryDelay !== null ) {
194206 console . log (
195207 `npm latest for ${ name } is ${ latest } ; waiting for ${ expectedVersion } (${ attempt } /${ attempts } )`
196208 ) ;
197- await sleep ( delayMs ) ;
209+ await wait ( retryDelay ) ;
210+ } else {
211+ break ;
198212 }
199213 }
200214
@@ -208,23 +222,28 @@ async function waitForPublishedArtifact(label, check, options = {}) {
208222 options . delayMs || Number ( process . env . RELEASE_ASSERT_DELAY_MS || DEFAULT_DELAY_MS ) ;
209223 const wait = options . sleep || sleep ;
210224 let lastError = null ;
225+ let attemptsMade = 0 ;
211226
212227 for ( let attempt = 1 ; attempt <= attempts ; attempt += 1 ) {
228+ attemptsMade = attempt ;
213229 try {
214230 return await check ( ) ;
215231 } catch ( error ) {
216232 lastError = error ;
217- if ( attempt < attempts ) {
233+ const retryDelay = nextRetryDelay ( attempt , attempts , delayMs , options ) ;
234+ if ( retryDelay !== null ) {
218235 console . log (
219236 `${ label } is not ready: ${ error . message } ; retrying (${ attempt } /${ attempts } )`
220237 ) ;
221- await wait ( delayMs ) ;
238+ await wait ( retryDelay ) ;
239+ } else {
240+ break ;
222241 }
223242 }
224243 }
225244
226245 throw new Error (
227- `${ label } did not become ready after ${ attempts } attempts: ${ lastError ?. message || 'unknown error' } `
246+ `${ label } did not become ready after ${ attemptsMade } attempts: ${ lastError ?. message || 'unknown error' } `
228247 ) ;
229248}
230249
@@ -245,40 +264,61 @@ async function main() {
245264
246265 console . log ( `tags on HEAD: ${ headTags . join ( ', ' ) || '(none)' } ` ) ;
247266 const expectedVersion = expectedTag . slice ( 1 ) ;
248- const latest = await waitForNpmLatest ( name , expectedVersion ) ;
267+ const retryAttempts = Number ( process . env . RELEASE_ASSERT_ATTEMPTS || DEFAULT_ATTEMPTS ) ;
268+ const retryDelayMs = Number ( process . env . RELEASE_ASSERT_DELAY_MS || DEFAULT_DELAY_MS ) ;
269+ const retryOptions = {
270+ attempts : retryAttempts ,
271+ delayMs : retryDelayMs ,
272+ deadline : Date . now ( ) + retryAttempts * retryDelayMs ,
273+ } ;
274+ const latest = await waitForNpmLatest ( name , expectedVersion , retryOptions ) ;
249275
250276 console . log ( `npm latest for ${ name } : ${ latest } ` ) ;
251277
252278 const expectedCommit = run ( 'git' , [ 'rev-parse' , 'HEAD' ] ) ;
253- const metadata = await waitForPublishedArtifact ( 'npm release metadata' , ( ) => {
254- const result = npmReleaseMetadata ( name , expectedVersion ) ;
255- if ( result . version !== expectedVersion ) {
256- throw new Error ( `npm metadata returned ${ result . version } ; expected ${ expectedVersion } ` ) ;
257- }
258- if ( result . gitHead !== expectedCommit ) {
259- throw new Error ( `npm gitHead ${ result . gitHead || '(missing)' } does not match HEAD` ) ;
260- }
261- if ( ! result [ 'dist.attestations' ] ?. url ) {
262- throw new Error ( 'npm attestation URL is missing' ) ;
263- }
264- return result ;
265- } ) ;
279+ const metadata = await waitForPublishedArtifact (
280+ 'npm release metadata' ,
281+ ( ) => {
282+ const result = npmReleaseMetadata ( name , expectedVersion ) ;
283+ if ( result . version !== expectedVersion ) {
284+ throw new Error ( `npm metadata returned ${ result . version } ; expected ${ expectedVersion } ` ) ;
285+ }
286+ if ( result . gitHead !== expectedCommit ) {
287+ throw new Error ( `npm gitHead ${ result . gitHead || '(missing)' } does not match HEAD` ) ;
288+ }
289+ if ( ! result [ 'dist.attestations' ] ?. url ) {
290+ throw new Error ( 'npm attestation URL is missing' ) ;
291+ }
292+ return result ;
293+ } ,
294+ retryOptions
295+ ) ;
266296
267- await waitForPublishedArtifact ( 'npm provenance' , async ( ) => {
268- const attestations = await httpsJson ( metadata [ 'dist.attestations' ] . url ) ;
269- verifyProvenance ( provenanceStatement ( attestations ) , expectedCommit ) ;
270- } ) ;
297+ await waitForPublishedArtifact (
298+ 'npm provenance' ,
299+ async ( ) => {
300+ const attestations = await httpsJson ( metadata [ 'dist.attestations' ] . url ) ;
301+ verifyProvenance ( provenanceStatement ( attestations ) , expectedCommit ) ;
302+ } ,
303+ retryOptions
304+ ) ;
271305
272- await waitForPublishedArtifact ( 'GitHub Release' , ( ) => {
273- const release = githubRelease ( expectedTag ) ;
274- if ( release . tagName !== expectedTag ) {
275- throw new Error ( `GitHub Release tag ${ release . tagName } does not match ${ expectedTag } ` ) ;
276- }
277- verifyCuratedNotes ( expectedTag , release ) ;
278- } ) ;
306+ await waitForPublishedArtifact (
307+ 'GitHub Release' ,
308+ ( ) => {
309+ const release = githubRelease ( expectedTag ) ;
310+ if ( release . tagName !== expectedTag ) {
311+ throw new Error ( `GitHub Release tag ${ release . tagName } does not match ${ expectedTag } ` ) ;
312+ }
313+ verifyCuratedNotes ( expectedTag , release ) ;
314+ } ,
315+ retryOptions
316+ ) ;
279317
280- await waitForPublishedArtifact ( 'installed CLI' , ( ) =>
281- verifyInstalledCli ( name , expectedVersion )
318+ await waitForPublishedArtifact (
319+ 'installed CLI' ,
320+ ( ) => verifyInstalledCli ( name , expectedVersion ) ,
321+ retryOptions
282322 ) ;
283323
284324 console . log ( `Release publication verified: ${ name } @${ latest } ` ) ;
0 commit comments