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