@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/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.1.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 (error) {
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 (e) {
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 (e) {
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 (e) {
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/poll-ci-greenlight.ts
415
- var safeDefaults = {
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 { abortOnSuperseded = safeDefaults.abortOnSuperseded, maxRetries = safeDefaults.maxRetries, pollTimeout = safeDefaults.pollTimeout, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval } = pollConfig;
427
- let currentStatus = void 0;
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
- let hasTimedOut = false;
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
- log.error(`\u{1F6AB} Unrecoverable error (status ${responseState.httpStatus}) from CI greenlight, aborting.`);
436
- return {
499
+ yield {
437
500
  abortReason: "4XX-client-error",
501
+ elapsedMs,
438
502
  httpStatus: responseState.httpStatus,
439
- outcome: "aborted"
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
- log.error(`\u{1F6AB} Unrecoverable error${responseState.httpStatus ? ` (status ${responseState.httpStatus})` : ""} from CI greenlight, aborting after ${maxRetries} attempts.`);
446
- if (responseState.errorType === "network") {
447
- return {
448
- abortReason: "network-error",
449
- httpStatus: void 0,
450
- outcome: "aborted"
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
- let abortReason = "XXX-other-http-code";
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 previousStatus = currentStatus;
474
- currentStatus = greenlightStatus;
475
- if (!previousStatus || previousStatus.runStage !== greenlightStatus.runStage) {
476
- try {
477
- await onRunStageChanged(greenlightStatus, previousStatus);
478
- } catch (e) {
479
- log.error(`Error in onRunStageChanged callback`, e);
480
- }
481
- }
482
- const urlInfo = `See ${greenlightStatus.relevantRunUrl}`;
483
- const { greenlight, relevantRunId, relevantRunUrl, relevantRunWithBugsUrl, rootRunId, rootRunUrl, runStage } = greenlightStatus;
484
- if (rootRunId !== relevantRunId) {
485
- const supersedingDetails = `
486
- - Root: ${rootRunUrl}
487
- - Superseding: ${relevantRunUrl}`;
488
- if (abortOnSuperseded) {
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
- outcome: "aborted"
567
+ isAborted: true
494
568
  };
569
+ return;
495
570
  }
496
- log.info(`Root run was superseded:${supersedingDetails}`);
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
- if (runStage === "completed") {
499
- const { blockingBugsCount, blockingBugUrls = [], nonBlockingBugsCount, nonBlockingBugUrls = [] } = greenlightStatus;
500
- const blockingBugList = blockingBugUrls.map((url) => `
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
- const nonBlockingBugList = nonBlockingBugUrls.map((url) => `
605
+ const nonBlockingBugList = nonBlockingBugUrls.map((url) => `
503
606
  \u2022 ${url}`).join("");
504
- const bugsListInText = `${blockingBugUrls.length > 0 ? `
607
+ const bugsListInText = `${blockingBugUrls.length > 0 ? `
505
608
  BLOCKING BUGS:${blockingBugList}` : ""}${nonBlockingBugUrls.length > 0 ? `
506
609
  NON BLOCKING BUGS:${nonBlockingBugList}` : ""}`;
507
- if (greenlight) {
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
- return {
520
- greenlightStatus,
521
- outcome: "failed"
522
- };
523
- }
524
- }
525
- if (runStage === "canceled") {
526
- log.info(`\u{1F6AB} Run was canceled. Aborting... Please contact support.
527
- ${urlInfo}`);
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: "run-canceled",
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
- if (hasTimedOut) {
535
- log.warn(`\u274C Poll timed out after ${pollTimeout / 1e3}s. Aborting...`);
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: "poll-timed-out",
733
+ abortReason: "superseded-run",
538
734
  httpStatus: void 0,
539
735
  outcome: "aborted"
540
736
  };
541
737
  }
542
- if (runStage === "initializing") {
543
- log.info(`\u23F3 Run is in progress... ${urlInfo}`);
544
- await sleep(runInProgressInterval);
545
- } else if (runStage === "underReview") {
546
- log.info(`\u{1F575}\uFE0F Run is under review... ${urlInfo}`);
547
- await sleep(runUnderReviewInterval);
548
- } else throw Error(`Unexpected run stage: ${runStage}`);
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
- log.warn(`\u274C Poll timed out after ${pollTimeout / 1e3}s. Aborting...`);
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
  }