@qawolf/ci-sdk 1.1.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +178 -0
- package/dist/index.cjs +323 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +104 -2
- package/dist/index.d.ts +104 -2
- package/dist/index.js +323 -102
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -38,7 +38,7 @@ var defaultServiceBase = "https://app.qawolf.com/";
|
|
|
38
38
|
|
|
39
39
|
// package.json
|
|
40
40
|
var package_default = {
|
|
41
|
-
version: "1.
|
|
41
|
+
version: "1.3.0"};
|
|
42
42
|
|
|
43
43
|
// src/lib/sdk/defaults/userAgent.ts
|
|
44
44
|
var defaultUserAgent = `ci-sdk/${package_default.version}`;
|
|
@@ -105,7 +105,7 @@ async function attemptNotifyDeploy(deps, apiConfig, config) {
|
|
|
105
105
|
if (!response.ok) return handleErrorResponse(response, log);
|
|
106
106
|
const data = await response.json();
|
|
107
107
|
return handleSuccessResponse(data, log);
|
|
108
|
-
} catch
|
|
108
|
+
} catch {
|
|
109
109
|
log.error(`\u{1F6AB} Network error from deploy_success, aborting.`);
|
|
110
110
|
return {
|
|
111
111
|
abortReason: "network-error",
|
|
@@ -229,7 +229,7 @@ async function callGenerateSignedUrlForRunInputsExecutablesStorage({ apiKey, ser
|
|
|
229
229
|
httpStatus: response.status,
|
|
230
230
|
success: false
|
|
231
231
|
};
|
|
232
|
-
} catch
|
|
232
|
+
} catch {
|
|
233
233
|
return {
|
|
234
234
|
errorMessage: "Network error, aborting request to generate signed URL",
|
|
235
235
|
httpStatus: 0,
|
|
@@ -309,7 +309,7 @@ async function callGenerateSignedUrlForTempTeamStorage({ apiKey, serviceBase, us
|
|
|
309
309
|
httpStatus: response.status,
|
|
310
310
|
success: false
|
|
311
311
|
};
|
|
312
|
-
} catch
|
|
312
|
+
} catch {
|
|
313
313
|
return {
|
|
314
314
|
errorMessage: "Network error, aborting request to generate signed URL",
|
|
315
315
|
httpStatus: 0,
|
|
@@ -358,6 +358,78 @@ async function generateSignedUrlForTempTeamStorage(deps, apiConfig, config) {
|
|
|
358
358
|
}
|
|
359
359
|
__name(generateSignedUrlForTempTeamStorage, "generateSignedUrlForTempTeamStorage");
|
|
360
360
|
|
|
361
|
+
// src/lib/sdk/domain/notifyTerminatedEphemeralEnvironment/index.ts
|
|
362
|
+
var notifyTerminatedEphemeralEnvironment = /* @__PURE__ */ __name(async (deps, apiConfig, config) => {
|
|
363
|
+
const { fetch: localFetch, log } = deps;
|
|
364
|
+
try {
|
|
365
|
+
const response = await localFetch(new URL("/api/webhooks/environment_terminated", apiConfig.serviceBase), {
|
|
366
|
+
body: JSON.stringify(config),
|
|
367
|
+
headers: {
|
|
368
|
+
Authorization: `Bearer ${apiConfig.apiKey}`,
|
|
369
|
+
"Content-Type": "application/json",
|
|
370
|
+
"User-Agent": apiConfig.userAgent
|
|
371
|
+
},
|
|
372
|
+
method: "POST"
|
|
373
|
+
});
|
|
374
|
+
if (!response.ok) return handleErrorResponse2(response, log);
|
|
375
|
+
const { environmentId } = await response.json();
|
|
376
|
+
return {
|
|
377
|
+
environmentId,
|
|
378
|
+
outcome: "success"
|
|
379
|
+
};
|
|
380
|
+
} catch {
|
|
381
|
+
log.error(`\u{1F6AB} Network error from terminate_preview_environment, aborting.`);
|
|
382
|
+
return {
|
|
383
|
+
abortReason: "network-error",
|
|
384
|
+
outcome: "aborted"
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
}, "notifyTerminatedEphemeralEnvironment");
|
|
388
|
+
async function handleErrorResponse2(response, log) {
|
|
389
|
+
const status = response.status;
|
|
390
|
+
let abortReason;
|
|
391
|
+
if (status === void 0) abortReason = "network-error";
|
|
392
|
+
else if (status === 401) abortReason = "401-unauthorized";
|
|
393
|
+
else if (status === 403) abortReason = "403-forbidden";
|
|
394
|
+
else if (status === 409) abortReason = "409-conflict";
|
|
395
|
+
else if (status >= 500) abortReason = "5XX-server-error";
|
|
396
|
+
else abortReason = "4XX-client-error";
|
|
397
|
+
await logFetchError({
|
|
398
|
+
log,
|
|
399
|
+
methodName: "notifyTerminatedEphemeralEnvironment",
|
|
400
|
+
response
|
|
401
|
+
});
|
|
402
|
+
return {
|
|
403
|
+
abortReason,
|
|
404
|
+
httpStatus: status,
|
|
405
|
+
outcome: "aborted"
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
__name(handleErrorResponse2, "handleErrorResponse");
|
|
409
|
+
|
|
410
|
+
// src/lib/sdk/domain/pollCiGreenlight/buildCompletedRunResult.ts
|
|
411
|
+
function buildCompletedRunResult(status) {
|
|
412
|
+
if (status.greenlight) return {
|
|
413
|
+
greenlightStatus: status,
|
|
414
|
+
outcome: "success"
|
|
415
|
+
};
|
|
416
|
+
else return {
|
|
417
|
+
greenlightStatus: status,
|
|
418
|
+
outcome: "failed"
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
__name(buildCompletedRunResult, "buildCompletedRunResult");
|
|
422
|
+
|
|
423
|
+
// src/lib/sdk/domain/pollCiGreenlight/consts.ts
|
|
424
|
+
var pollCiGreenlightDefaults = {
|
|
425
|
+
abortOnSuperseded: false,
|
|
426
|
+
maxRetries: 10,
|
|
427
|
+
pollTimeout: 120 * 60 * 1e3,
|
|
428
|
+
retryInterval: 10 * 1e3,
|
|
429
|
+
runInProgressInterval: 30 * 1e3,
|
|
430
|
+
runUnderReviewInterval: 60 * 1e3
|
|
431
|
+
};
|
|
432
|
+
|
|
361
433
|
// src/lib/api/ci-greenlight.ts
|
|
362
434
|
async function fetchCiGreenlightStatus({ apiKey, serviceBase, userAgent }, { runId }, { fetch: localFetch, log }) {
|
|
363
435
|
try {
|
|
@@ -402,7 +474,7 @@ async function fetchCiGreenlightStatus({ apiKey, serviceBase, userAgent }, { run
|
|
|
402
474
|
httpStatus: resp.status,
|
|
403
475
|
ok: false
|
|
404
476
|
};
|
|
405
|
-
} catch
|
|
477
|
+
} catch {
|
|
406
478
|
return {
|
|
407
479
|
canRetry: true,
|
|
408
480
|
errorType: "network",
|
|
@@ -413,56 +485,61 @@ async function fetchCiGreenlightStatus({ apiKey, serviceBase, userAgent }, { run
|
|
|
413
485
|
}
|
|
414
486
|
__name(fetchCiGreenlightStatus, "fetchCiGreenlightStatus");
|
|
415
487
|
|
|
416
|
-
// src/lib/sdk/domain/
|
|
417
|
-
|
|
418
|
-
abortOnSuperseded: false,
|
|
419
|
-
maxRetries: 10,
|
|
420
|
-
pollTimeout: 120 * 60 * 1e3,
|
|
421
|
-
retryInterval: 10 * 1e3,
|
|
422
|
-
runInProgressInterval: 30 * 1e3,
|
|
423
|
-
runUnderReviewInterval: 60 * 1e3
|
|
424
|
-
};
|
|
425
|
-
async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged = /* @__PURE__ */ __name(() => void 0, "onRunStageChanged"), runId, ...pollConfig }) {
|
|
426
|
-
let retries = 0;
|
|
488
|
+
// src/lib/sdk/domain/pollCiGreenlight/iterator.ts
|
|
489
|
+
async function* makePollCiGreenlightStatusIterator(deps, apiConfig, { runId, ...pollConfig }) {
|
|
427
490
|
const { log } = deps;
|
|
428
|
-
const {
|
|
429
|
-
let
|
|
491
|
+
const { maxRetries = pollCiGreenlightDefaults.maxRetries, pollTimeout = pollCiGreenlightDefaults.pollTimeout, retryInterval = pollCiGreenlightDefaults.retryInterval, runInProgressInterval = pollCiGreenlightDefaults.runInProgressInterval, runUnderReviewInterval = pollCiGreenlightDefaults.runUnderReviewInterval } = pollConfig;
|
|
492
|
+
let retries = 0;
|
|
493
|
+
let previousStatus = void 0;
|
|
430
494
|
const startedAt = Date.now();
|
|
431
|
-
|
|
432
|
-
while (!(hasTimedOut = Date.now() - startedAt > pollTimeout)) {
|
|
495
|
+
while (Date.now() - startedAt <= pollTimeout) {
|
|
433
496
|
const responseState = await fetchCiGreenlightStatus(apiConfig, {
|
|
434
497
|
runId
|
|
435
498
|
}, deps);
|
|
499
|
+
const elapsedMs = Date.now() - startedAt;
|
|
436
500
|
if (!responseState.ok && !responseState.canRetry) {
|
|
437
|
-
|
|
438
|
-
return {
|
|
501
|
+
yield {
|
|
439
502
|
abortReason: "4XX-client-error",
|
|
503
|
+
elapsedMs,
|
|
440
504
|
httpStatus: responseState.httpStatus,
|
|
441
|
-
|
|
505
|
+
isAborted: true
|
|
442
506
|
};
|
|
507
|
+
return;
|
|
443
508
|
}
|
|
444
509
|
if (!responseState.ok) {
|
|
445
510
|
retries += 1;
|
|
511
|
+
const { errorType, httpStatus } = responseState;
|
|
446
512
|
if (retries > maxRetries) {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
513
|
+
switch (errorType) {
|
|
514
|
+
case "network":
|
|
515
|
+
yield {
|
|
516
|
+
abortReason: "network-error",
|
|
517
|
+
elapsedMs,
|
|
518
|
+
httpStatus: void 0,
|
|
519
|
+
isAborted: true
|
|
520
|
+
};
|
|
521
|
+
break;
|
|
522
|
+
case "not-found":
|
|
523
|
+
yield {
|
|
524
|
+
abortReason: "404-run-not-found",
|
|
525
|
+
elapsedMs,
|
|
526
|
+
httpStatus: httpStatus ?? 404,
|
|
527
|
+
isAborted: true
|
|
528
|
+
};
|
|
529
|
+
break;
|
|
530
|
+
case "server":
|
|
531
|
+
yield {
|
|
532
|
+
abortReason: "5XX-server-error",
|
|
533
|
+
elapsedMs,
|
|
534
|
+
httpStatus: httpStatus ?? 500,
|
|
535
|
+
isAborted: true
|
|
536
|
+
};
|
|
537
|
+
break;
|
|
538
|
+
default:
|
|
539
|
+
throw Error(`Unexpected error type: ${errorType}`);
|
|
454
540
|
}
|
|
455
|
-
|
|
456
|
-
if (responseState.errorType === "not-found") abortReason = "404-run-not-found";
|
|
457
|
-
else if (responseState.errorType === "server") abortReason = "5XX-server-error";
|
|
458
|
-
else ;
|
|
459
|
-
return {
|
|
460
|
-
abortReason,
|
|
461
|
-
httpStatus: responseState.httpStatus,
|
|
462
|
-
outcome: "aborted"
|
|
463
|
-
};
|
|
541
|
+
return;
|
|
464
542
|
}
|
|
465
|
-
const { errorType, httpStatus } = responseState;
|
|
466
543
|
const retryLabel = `${httpStatus ? ` (status ${httpStatus})` : ""}, will try again... (${retries}/${maxRetries})`;
|
|
467
544
|
if (errorType === "network") log.warn(`\u274C Network error${retryLabel}`);
|
|
468
545
|
else if (errorType === "not-found") log.info(`\u23F3 Run not found${retryLabel}`);
|
|
@@ -472,89 +549,231 @@ async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged = /*
|
|
|
472
549
|
}
|
|
473
550
|
retries = 0;
|
|
474
551
|
const { greenlightStatus } = responseState;
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
log.warn(`\u274C Aborting due to superseded run (option 'abortOnSuperseded' is enabled).${supersedingDetails}`);
|
|
492
|
-
return {
|
|
493
|
-
abortReason: "superseded-run",
|
|
552
|
+
const stageChanged = !previousStatus || previousStatus.runStage !== greenlightStatus.runStage;
|
|
553
|
+
const isFailedTerminalStage = greenlightStatus.runStage === "canceled" || greenlightStatus.runStage === "completed" && greenlightStatus.greenlight === false;
|
|
554
|
+
yield {
|
|
555
|
+
elapsedMs,
|
|
556
|
+
isAborted: false,
|
|
557
|
+
isFailedTerminalStage,
|
|
558
|
+
previousStatus,
|
|
559
|
+
stageChanged,
|
|
560
|
+
status: greenlightStatus
|
|
561
|
+
};
|
|
562
|
+
previousStatus = greenlightStatus;
|
|
563
|
+
switch (greenlightStatus.runStage) {
|
|
564
|
+
case "canceled": {
|
|
565
|
+
yield {
|
|
566
|
+
abortReason: "run-canceled",
|
|
567
|
+
elapsedMs,
|
|
494
568
|
httpStatus: void 0,
|
|
495
|
-
|
|
569
|
+
isAborted: true
|
|
496
570
|
};
|
|
571
|
+
return;
|
|
497
572
|
}
|
|
498
|
-
|
|
573
|
+
case "completed":
|
|
574
|
+
return;
|
|
575
|
+
case "initializing":
|
|
576
|
+
await sleep(runInProgressInterval);
|
|
577
|
+
break;
|
|
578
|
+
case "underReview":
|
|
579
|
+
await sleep(runUnderReviewInterval);
|
|
580
|
+
break;
|
|
581
|
+
default:
|
|
582
|
+
throw Error(`Unexpected run stage: ${greenlightStatus}`);
|
|
499
583
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
584
|
+
}
|
|
585
|
+
yield {
|
|
586
|
+
abortReason: "poll-timed-out",
|
|
587
|
+
elapsedMs: Date.now() - startedAt,
|
|
588
|
+
httpStatus: void 0,
|
|
589
|
+
isAborted: true
|
|
590
|
+
};
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
__name(makePollCiGreenlightStatusIterator, "makePollCiGreenlightStatusIterator");
|
|
594
|
+
|
|
595
|
+
// src/lib/sdk/domain/pollCiGreenlight/logging.ts
|
|
596
|
+
function buildSuccessLogMessage(status) {
|
|
597
|
+
const { nonBlockingBugsCount, relevantRunUrl } = status;
|
|
598
|
+
const urlInfo = `See ${relevantRunUrl}`;
|
|
599
|
+
return `\u2705 Run passed and no blocking bugs found${nonBlockingBugsCount > 0 ? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(nonBlockingBugsCount)} found` : ""}.
|
|
600
|
+
${urlInfo}`;
|
|
601
|
+
}
|
|
602
|
+
__name(buildSuccessLogMessage, "buildSuccessLogMessage");
|
|
603
|
+
function buildFailedLogMessage(status) {
|
|
604
|
+
const { blockingBugsCount, blockingBugUrls = [], nonBlockingBugsCount, nonBlockingBugUrls = [], relevantRunWithBugsUrl } = status;
|
|
605
|
+
const blockingBugList = blockingBugUrls.map((url) => `
|
|
503
606
|
\u2022 ${url}`).join("");
|
|
504
|
-
|
|
607
|
+
const nonBlockingBugList = nonBlockingBugUrls.map((url) => `
|
|
505
608
|
\u2022 ${url}`).join("");
|
|
506
|
-
|
|
609
|
+
const bugsListInText = `${blockingBugUrls.length > 0 ? `
|
|
507
610
|
BLOCKING BUGS:${blockingBugList}` : ""}${nonBlockingBugUrls.length > 0 ? `
|
|
508
611
|
NON BLOCKING BUGS:${nonBlockingBugList}` : ""}`;
|
|
509
|
-
|
|
510
|
-
log.info(`\u2705 Run passed and no blocking bugs found${nonBlockingBugsCount > 0 ? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(nonBlockingBugsCount)} found` : ""}.
|
|
511
|
-
${urlInfo}`);
|
|
512
|
-
return {
|
|
513
|
-
greenlightStatus,
|
|
514
|
-
outcome: "success"
|
|
515
|
-
};
|
|
516
|
-
} else {
|
|
517
|
-
log.warn(`\u274C Run failed and ${blockingBugsCount} blocking bug${pluralize(blockingBugsCount)} found${nonBlockingBugsCount ? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(nonBlockingBugsCount)}` : ""}.
|
|
612
|
+
return `\u274C Run failed and ${blockingBugsCount} blocking bug${pluralize(blockingBugsCount)} found${nonBlockingBugsCount ? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(nonBlockingBugsCount)}` : ""}.
|
|
518
613
|
See ${relevantRunWithBugsUrl}
|
|
519
614
|
You may review the priority of certain bugs to mark these non-blocking and retry the job.
|
|
520
|
-
` + bugsListInText
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
615
|
+
` + bugsListInText;
|
|
616
|
+
}
|
|
617
|
+
__name(buildFailedLogMessage, "buildFailedLogMessage");
|
|
618
|
+
function buildSupersededAbortLogMessage(rootRunUrl, relevantRunUrl) {
|
|
619
|
+
const supersedingDetails = `
|
|
620
|
+
- Root: ${rootRunUrl}
|
|
621
|
+
- Superseding: ${relevantRunUrl}`;
|
|
622
|
+
return `\u274C Aborting due to superseded run (option 'abortOnSuperseded' is enabled).${supersedingDetails}`;
|
|
623
|
+
}
|
|
624
|
+
__name(buildSupersededAbortLogMessage, "buildSupersededAbortLogMessage");
|
|
625
|
+
function buildSupersededContinueLogMessage(rootRunUrl, relevantRunUrl) {
|
|
626
|
+
const supersedingDetails = `
|
|
627
|
+
- Root: ${rootRunUrl}
|
|
628
|
+
- Superseding: ${relevantRunUrl}`;
|
|
629
|
+
return `Root run was superseded:${supersedingDetails}`;
|
|
630
|
+
}
|
|
631
|
+
__name(buildSupersededContinueLogMessage, "buildSupersededContinueLogMessage");
|
|
632
|
+
function buildRunStageLogMessage(runStage, relevantRunUrl) {
|
|
633
|
+
const urlInfo = `See ${relevantRunUrl}`;
|
|
634
|
+
switch (runStage) {
|
|
635
|
+
case "canceled":
|
|
636
|
+
return `\u{1F6AB} Run was canceled. Aborting... Please contact support.
|
|
637
|
+
${urlInfo}`;
|
|
638
|
+
case "initializing":
|
|
639
|
+
return `\u23F3 Run is in progress... ${urlInfo}`;
|
|
640
|
+
case "underReview":
|
|
641
|
+
return `\u{1F575}\uFE0F Run is under review... ${urlInfo}`;
|
|
642
|
+
case "completed":
|
|
643
|
+
throw Error("buildRunStageLogMessage should not be called for completed stage");
|
|
644
|
+
default:
|
|
645
|
+
throw Error(`Unexpected run stage: ${runStage}`);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
__name(buildRunStageLogMessage, "buildRunStageLogMessage");
|
|
649
|
+
|
|
650
|
+
// src/lib/sdk/domain/pollCiGreenlight/mapIteratorAbortToGreenlightStatus.ts
|
|
651
|
+
function mapIteratorAbortToGreenlightStatus(iteration, pollTimeout, deps) {
|
|
652
|
+
const { log } = deps;
|
|
653
|
+
const { abortReason, httpStatus } = iteration;
|
|
654
|
+
switch (abortReason) {
|
|
655
|
+
case "4XX-client-error":
|
|
656
|
+
log.error(`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`);
|
|
657
|
+
return {
|
|
658
|
+
abortReason,
|
|
659
|
+
httpStatus,
|
|
660
|
+
outcome: "aborted"
|
|
661
|
+
};
|
|
662
|
+
case "5XX-server-error":
|
|
663
|
+
log.error(`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`);
|
|
530
664
|
return {
|
|
531
|
-
abortReason
|
|
665
|
+
abortReason,
|
|
666
|
+
httpStatus,
|
|
667
|
+
outcome: "aborted"
|
|
668
|
+
};
|
|
669
|
+
case "404-run-not-found":
|
|
670
|
+
log.error(`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`);
|
|
671
|
+
return {
|
|
672
|
+
abortReason,
|
|
673
|
+
httpStatus,
|
|
674
|
+
outcome: "aborted"
|
|
675
|
+
};
|
|
676
|
+
case "network-error":
|
|
677
|
+
log.error(`\u{1F6AB} Unrecoverable network error from CI greenlight, aborting.`);
|
|
678
|
+
return {
|
|
679
|
+
abortReason,
|
|
532
680
|
httpStatus: void 0,
|
|
533
681
|
outcome: "aborted"
|
|
534
682
|
};
|
|
683
|
+
case "poll-timed-out":
|
|
684
|
+
log.warn(`\u274C Poll timed out after ${pollTimeout / 1e3}s`);
|
|
685
|
+
return {
|
|
686
|
+
abortReason,
|
|
687
|
+
httpStatus: void 0,
|
|
688
|
+
outcome: "aborted"
|
|
689
|
+
};
|
|
690
|
+
case "run-canceled":
|
|
691
|
+
log.info(`Run was canceled`);
|
|
692
|
+
return {
|
|
693
|
+
abortReason,
|
|
694
|
+
httpStatus: void 0,
|
|
695
|
+
outcome: "aborted"
|
|
696
|
+
};
|
|
697
|
+
case "XXX-other-http-code":
|
|
698
|
+
log.error(`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`);
|
|
699
|
+
return {
|
|
700
|
+
abortReason,
|
|
701
|
+
httpStatus,
|
|
702
|
+
outcome: "aborted"
|
|
703
|
+
};
|
|
704
|
+
default:
|
|
705
|
+
throw Error(`Unexpected abort reason: ${abortReason}`);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
__name(mapIteratorAbortToGreenlightStatus, "mapIteratorAbortToGreenlightStatus");
|
|
709
|
+
|
|
710
|
+
// src/lib/sdk/domain/pollCiGreenlight/index.ts
|
|
711
|
+
async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged = /* @__PURE__ */ __name(() => void 0, "onRunStageChanged"), runId, ...pollConfig }) {
|
|
712
|
+
const { log } = deps;
|
|
713
|
+
const { abortOnSuperseded = pollCiGreenlightDefaults.abortOnSuperseded, pollTimeout = pollCiGreenlightDefaults.pollTimeout } = pollConfig;
|
|
714
|
+
const iterator = makePollCiGreenlightStatusIterator(deps, apiConfig, {
|
|
715
|
+
runId,
|
|
716
|
+
...pollConfig
|
|
717
|
+
});
|
|
718
|
+
for await (const lastPoll of iterator) {
|
|
719
|
+
if (lastPoll.isAborted) return mapIteratorAbortToGreenlightStatus(lastPoll, pollTimeout, deps);
|
|
720
|
+
const { previousStatus, stageChanged, status } = lastPoll;
|
|
721
|
+
if (stageChanged) {
|
|
722
|
+
try {
|
|
723
|
+
await onRunStageChanged(status, previousStatus);
|
|
724
|
+
} catch (e) {
|
|
725
|
+
log.error(`Error in onRunStageChanged callback`, e);
|
|
726
|
+
}
|
|
535
727
|
}
|
|
536
|
-
|
|
537
|
-
|
|
728
|
+
const { relevantRunId, relevantRunUrl, rootRunId, rootRunUrl, runStage } = status;
|
|
729
|
+
const isSuperseded = rootRunId !== relevantRunId;
|
|
730
|
+
const shouldAbortOnSuperseded = isSuperseded && abortOnSuperseded;
|
|
731
|
+
if (shouldAbortOnSuperseded) {
|
|
732
|
+
const message = buildSupersededAbortLogMessage(rootRunUrl, relevantRunUrl);
|
|
733
|
+
log.warn(message);
|
|
538
734
|
return {
|
|
539
|
-
abortReason: "
|
|
735
|
+
abortReason: "superseded-run",
|
|
540
736
|
httpStatus: void 0,
|
|
541
737
|
outcome: "aborted"
|
|
542
738
|
};
|
|
543
739
|
}
|
|
544
|
-
if (
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
740
|
+
if (isSuperseded) {
|
|
741
|
+
const message = buildSupersededContinueLogMessage(rootRunUrl, relevantRunUrl);
|
|
742
|
+
log.info(message);
|
|
743
|
+
}
|
|
744
|
+
switch (runStage) {
|
|
745
|
+
case "canceled":
|
|
746
|
+
case "initializing":
|
|
747
|
+
case "underReview": {
|
|
748
|
+
log.info(buildRunStageLogMessage(runStage, relevantRunUrl));
|
|
749
|
+
break;
|
|
750
|
+
}
|
|
751
|
+
case "completed": {
|
|
752
|
+
const result = buildCompletedRunResult(status);
|
|
753
|
+
switch (result.outcome) {
|
|
754
|
+
case "aborted": {
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
case "failed": {
|
|
758
|
+
const message = buildFailedLogMessage(status);
|
|
759
|
+
log.warn(message);
|
|
760
|
+
break;
|
|
761
|
+
}
|
|
762
|
+
case "success": {
|
|
763
|
+
const message = buildSuccessLogMessage(status);
|
|
764
|
+
log.info(message);
|
|
765
|
+
break;
|
|
766
|
+
}
|
|
767
|
+
default:
|
|
768
|
+
throw Error(`Unexpected outcome: ${result}`);
|
|
769
|
+
}
|
|
770
|
+
return result;
|
|
771
|
+
}
|
|
772
|
+
default:
|
|
773
|
+
throw Error(`Unexpected run stage: ${runStage}`);
|
|
774
|
+
}
|
|
551
775
|
}
|
|
552
|
-
|
|
553
|
-
return {
|
|
554
|
-
abortReason: "poll-timed-out",
|
|
555
|
-
httpStatus: void 0,
|
|
556
|
-
outcome: "aborted"
|
|
557
|
-
};
|
|
776
|
+
throw Error("Iterator ended unexpectedly");
|
|
558
777
|
}
|
|
559
778
|
__name(pollCiGreenlightStatus, "pollCiGreenlightStatus");
|
|
560
779
|
|
|
@@ -580,6 +799,8 @@ We recommend 'undici' package for that purpose. See the Requirement section of o
|
|
|
580
799
|
attemptNotifyDeploy: attemptNotifyDeploy.bind(null, deps, apiConfig),
|
|
581
800
|
generateSignedUrlForRunInputsExecutablesStorage: generateSignedUrlForRunInputsExecutablesStorage.bind(null, deps, apiConfig),
|
|
582
801
|
generateSignedUrlForTempTeamStorage: generateSignedUrlForTempTeamStorage.bind(null, deps, apiConfig),
|
|
802
|
+
makePollCiGreenlightStatusIterator: makePollCiGreenlightStatusIterator.bind(null, deps, apiConfig),
|
|
803
|
+
notifyTerminatedEphemeralEnvironment: notifyTerminatedEphemeralEnvironment.bind(null, deps, apiConfig),
|
|
583
804
|
pollCiGreenlightStatus: pollCiGreenlightStatus.bind(null, deps, apiConfig)
|
|
584
805
|
};
|
|
585
806
|
}
|