@qawolf/ci-sdk 0.12.1 → 0.14.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 CHANGED
@@ -101,6 +101,19 @@ an up-to-date API usage version.
101
101
 
102
102
  # Changelog
103
103
 
104
+ ## v0.14.0
105
+
106
+ - New `failReason`, `abortReason` and `httpStatus` fields added to the `attemptNotifyDeploy`
107
+ function result object to provide more context on why the operation failed or was aborted.
108
+ - Exported missing TypeScript typings describing result objects and fields for both functions.
109
+
110
+ ## v0.13.0
111
+
112
+ - New `pollTimeout` parameter for `pollCiGreenlightStatus` to allow for a custom
113
+ timeout in milliseconds for the polling operation. It now defaults to two hours.
114
+ - New `abortReason` and `httpStatus` fields added to the `PollCiGreenlightStatus` type
115
+ with `"aborted"` outcome to provide more context on why the poll was aborted.
116
+
104
117
  ## v0.12.1
105
118
 
106
119
  - Export dependencies types from root module.
@@ -131,7 +144,7 @@ BREAKING CHANGES:
131
144
 
132
145
  BREAKING CHANGES:
133
146
 
134
- - Renamed `attemptDeploy` to `attemptNotifyDeploy`.
147
+ - Renamed `attemptDeploy` to `attemptNotifyDeploy` .
135
148
 
136
149
  ## v0.10.2
137
150
 
@@ -35,6 +35,7 @@ async function fetchCiGreenlightStatus({ serviceBase, apiKey }, { runId, }, { fe
35
35
  return {
36
36
  canRetry: false,
37
37
  httpStatus: resp.status,
38
+ errorType: "client",
38
39
  ok: false,
39
40
  };
40
41
  }
@@ -49,27 +49,27 @@ async function postDeploySuccess({ apiKey, serviceBase }, { branch, commitUrl, d
49
49
  else {
50
50
  if (response.status >= 500) {
51
51
  return {
52
- failureReason: "server-error",
52
+ failureReason: "5XX-server-error",
53
53
  httpStatus: response.status,
54
54
  success: false,
55
55
  };
56
56
  }
57
57
  if (response.status === 401) {
58
58
  return {
59
- failureReason: "unauthorized",
59
+ failureReason: "401-unauthorized",
60
60
  httpStatus: response.status,
61
61
  success: false,
62
62
  };
63
63
  }
64
64
  if (response.status === 403) {
65
65
  return {
66
- failureReason: "forbidden",
66
+ failureReason: "403-forbidden",
67
67
  httpStatus: response.status,
68
68
  success: false,
69
69
  };
70
70
  }
71
71
  return {
72
- failureReason: "unrecoverable-error",
72
+ failureReason: "4XX-client-error",
73
73
  httpStatus: response.status,
74
74
  success: false,
75
75
  };
@@ -9,29 +9,40 @@ async function attemptNotifyDeploy(deps, apiConfig, config) {
9
9
  if (!responseState.success) {
10
10
  if (responseState.failureReason === "no-matched-trigger") {
11
11
  log.error(`🚫 No trigger matched the request. Please contact support.`);
12
- return { outcome: "failed" };
12
+ return { outcome: "failed", failReason: "no-matched-trigger" };
13
13
  }
14
14
  else if (responseState.failureReason === "run-could-not-be-created") {
15
15
  log.error(`🚫 Run could not be created. Reason: "${responseState.details}". Please contact support.`);
16
- return { outcome: "failed" };
16
+ return { outcome: "failed", failReason: "run-could-not-be-created" };
17
17
  }
18
18
  if (responseState.failureReason === "network-error")
19
19
  log.error(`🚫 Network error from deploy_success, aborting.`);
20
- else if (responseState.failureReason === "server-error")
20
+ else if (responseState.failureReason === "5XX-server-error")
21
21
  log.error(`🚫 Server error from deploy_success (status ${responseState.httpStatus}), aborting. Please contact support.`);
22
- else if (responseState.failureReason === "unrecoverable-error") {
22
+ else if (responseState.failureReason === "4XX-client-error") {
23
23
  log.error(`🚫 Unrecoverable error from deploy_success (status ${responseState.httpStatus}), aborting. Please contact support.`);
24
24
  }
25
- else if (responseState.failureReason === "forbidden") {
25
+ else if (responseState.failureReason === "403-forbidden") {
26
26
  log.error(`🚫 Forbidden error from deploy_success (status ${responseState.httpStatus}), aborting. Please contact support.`);
27
27
  }
28
- else if (responseState.failureReason === "unauthorized") {
28
+ else if (responseState.failureReason === "401-unauthorized") {
29
29
  log.error(`🚫 Unauthorized error from deploy_success (status ${responseState.httpStatus}), aborting. Please contact support.`);
30
30
  }
31
31
  else {
32
32
  (0, utils_js_1.assertType)(responseState);
33
33
  }
34
- return { outcome: "aborted" };
34
+ if (responseState.failureReason === "network-error") {
35
+ return {
36
+ outcome: "aborted",
37
+ abortReason: "network-error",
38
+ httpStatus: undefined,
39
+ };
40
+ }
41
+ return {
42
+ outcome: "aborted",
43
+ abortReason: responseState.failureReason,
44
+ httpStatus: responseState.httpStatus,
45
+ };
35
46
  }
36
47
  log.info(`✅ Run created with ID: ${responseState.runId}`);
37
48
  return {
@@ -3,24 +3,33 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.pollCiGreenlightStatus = void 0;
4
4
  const utils_js_1 = require("../../utils.js");
5
5
  const ci_greenlight_js_1 = require("../../api/ci-greenlight.js");
6
+ // If you change these values, make sure you update the JSDoc
7
+ // comments in the PollConfig type.
6
8
  const safeDefaults = {
7
9
  maxRetries: 10,
8
10
  retryInterval: 10 * 1000,
9
11
  runInProgressInterval: 30 * 1000,
10
12
  runUnderReviewInterval: 60 * 1000,
13
+ pollTimeout: 120 * 60 * 1000,
11
14
  };
12
15
  async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChanged: onRunStageChanged = () => void 0, ...pollConfig }) {
13
16
  let retries = 0;
14
17
  const { log } = deps;
15
- const { maxRetries = safeDefaults.maxRetries, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, } = pollConfig;
18
+ const { maxRetries = safeDefaults.maxRetries, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, pollTimeout = safeDefaults.pollTimeout, } = pollConfig;
16
19
  let currentStatus = undefined;
17
- while (true) {
20
+ const startedAt = Date.now();
21
+ let hasTimedOut = false;
22
+ while (!(hasTimedOut = Date.now() - startedAt > pollTimeout)) {
18
23
  const responseState = await (0, ci_greenlight_js_1.fetchCiGreenlightStatus)(apiConfig, {
19
24
  runId,
20
25
  }, deps);
21
26
  if (!responseState.ok && !responseState.canRetry) {
22
27
  log.error(`🚫 Unrecoverable error (status ${responseState.httpStatus}) from CI greenlight, aborting.`);
23
- return { outcome: "aborted" };
28
+ return {
29
+ outcome: "aborted",
30
+ abortReason: "4XX-client-error",
31
+ httpStatus: responseState.httpStatus,
32
+ };
24
33
  }
25
34
  if (!responseState.ok) {
26
35
  // This is a non-OK retryable status.
@@ -29,7 +38,24 @@ async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChange
29
38
  log.error(`🚫 Unrecoverable error${responseState.httpStatus
30
39
  ? ` (status ${responseState.httpStatus})`
31
40
  : ""} from CI greenlight, aborting after ${maxRetries} attempts.`);
32
- return { outcome: "aborted" };
41
+ if (responseState.errorType === "network")
42
+ return {
43
+ outcome: "aborted",
44
+ abortReason: "network-error",
45
+ httpStatus: undefined,
46
+ };
47
+ let abortReason = "XXX-other-http-code";
48
+ if (responseState.errorType === "not-found")
49
+ abortReason = "404-run-not-found";
50
+ else if (responseState.errorType === "server")
51
+ abortReason = "5XX-server-error";
52
+ else
53
+ (0, utils_js_1.assertType)(responseState);
54
+ return {
55
+ outcome: "aborted",
56
+ abortReason,
57
+ httpStatus: responseState.httpStatus,
58
+ };
33
59
  }
34
60
  const { errorType, httpStatus } = responseState;
35
61
  const retryLabel = `${httpStatus ? ` (status ${httpStatus})` : ""}, will try again... (${retries}/${maxRetries})`;
@@ -88,6 +114,23 @@ async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChange
88
114
  return { outcome: "failed", greenlightStatus };
89
115
  }
90
116
  }
117
+ if (runStage === "canceled") {
118
+ log.info(`🚫 Run was canceled. Aborting... Please contact support.\n${urlInfo}`);
119
+ return {
120
+ outcome: "aborted",
121
+ abortReason: "run-canceled",
122
+ httpStatus: undefined,
123
+ };
124
+ }
125
+ // Non-terminal run stages
126
+ if (hasTimedOut) {
127
+ log.warn(`❌ Poll timed out after ${pollTimeout / 1000}s. Aborting...`);
128
+ return {
129
+ outcome: "aborted",
130
+ abortReason: "poll-timed-out",
131
+ httpStatus: undefined,
132
+ };
133
+ }
91
134
  if (runStage === "initializing") {
92
135
  log.info(`⏳ Run is in progress... ${urlInfo}`);
93
136
  await (0, utils_js_1.sleep)(runInProgressInterval);
@@ -96,12 +139,16 @@ async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChange
96
139
  log.info(`🕵️ Run is under review... ${urlInfo}`);
97
140
  await (0, utils_js_1.sleep)(runUnderReviewInterval);
98
141
  }
99
- else if (runStage === "canceled") {
100
- log.info(`🚫 Run was canceled. Aborting... Please contact support.\n${urlInfo}`);
101
- return { outcome: "aborted" };
102
- }
103
- else
142
+ else {
143
+ (0, utils_js_1.assertType)(runStage);
104
144
  throw new Error(`Unexpected run stage: ${runStage}`);
145
+ }
105
146
  }
147
+ log.warn(`❌ Poll timed out after ${pollTimeout / 1000}s. Aborting...`);
148
+ return {
149
+ outcome: "aborted",
150
+ abortReason: "poll-timed-out",
151
+ httpStatus: undefined,
152
+ };
106
153
  }
107
154
  exports.pollCiGreenlightStatus = pollCiGreenlightStatus;
@@ -32,6 +32,7 @@ export async function fetchCiGreenlightStatus({ serviceBase, apiKey }, { runId,
32
32
  return {
33
33
  canRetry: false,
34
34
  httpStatus: resp.status,
35
+ errorType: "client",
35
36
  ok: false,
36
37
  };
37
38
  }
@@ -46,27 +46,27 @@ export async function postDeploySuccess({ apiKey, serviceBase }, { branch, commi
46
46
  else {
47
47
  if (response.status >= 500) {
48
48
  return {
49
- failureReason: "server-error",
49
+ failureReason: "5XX-server-error",
50
50
  httpStatus: response.status,
51
51
  success: false,
52
52
  };
53
53
  }
54
54
  if (response.status === 401) {
55
55
  return {
56
- failureReason: "unauthorized",
56
+ failureReason: "401-unauthorized",
57
57
  httpStatus: response.status,
58
58
  success: false,
59
59
  };
60
60
  }
61
61
  if (response.status === 403) {
62
62
  return {
63
- failureReason: "forbidden",
63
+ failureReason: "403-forbidden",
64
64
  httpStatus: response.status,
65
65
  success: false,
66
66
  };
67
67
  }
68
68
  return {
69
- failureReason: "unrecoverable-error",
69
+ failureReason: "4XX-client-error",
70
70
  httpStatus: response.status,
71
71
  success: false,
72
72
  };
@@ -6,29 +6,40 @@ export async function attemptNotifyDeploy(deps, apiConfig, config) {
6
6
  if (!responseState.success) {
7
7
  if (responseState.failureReason === "no-matched-trigger") {
8
8
  log.error(`🚫 No trigger matched the request. Please contact support.`);
9
- return { outcome: "failed" };
9
+ return { outcome: "failed", failReason: "no-matched-trigger" };
10
10
  }
11
11
  else if (responseState.failureReason === "run-could-not-be-created") {
12
12
  log.error(`🚫 Run could not be created. Reason: "${responseState.details}". Please contact support.`);
13
- return { outcome: "failed" };
13
+ return { outcome: "failed", failReason: "run-could-not-be-created" };
14
14
  }
15
15
  if (responseState.failureReason === "network-error")
16
16
  log.error(`🚫 Network error from deploy_success, aborting.`);
17
- else if (responseState.failureReason === "server-error")
17
+ else if (responseState.failureReason === "5XX-server-error")
18
18
  log.error(`🚫 Server error from deploy_success (status ${responseState.httpStatus}), aborting. Please contact support.`);
19
- else if (responseState.failureReason === "unrecoverable-error") {
19
+ else if (responseState.failureReason === "4XX-client-error") {
20
20
  log.error(`🚫 Unrecoverable error from deploy_success (status ${responseState.httpStatus}), aborting. Please contact support.`);
21
21
  }
22
- else if (responseState.failureReason === "forbidden") {
22
+ else if (responseState.failureReason === "403-forbidden") {
23
23
  log.error(`🚫 Forbidden error from deploy_success (status ${responseState.httpStatus}), aborting. Please contact support.`);
24
24
  }
25
- else if (responseState.failureReason === "unauthorized") {
25
+ else if (responseState.failureReason === "401-unauthorized") {
26
26
  log.error(`🚫 Unauthorized error from deploy_success (status ${responseState.httpStatus}), aborting. Please contact support.`);
27
27
  }
28
28
  else {
29
29
  assertType(responseState);
30
30
  }
31
- return { outcome: "aborted" };
31
+ if (responseState.failureReason === "network-error") {
32
+ return {
33
+ outcome: "aborted",
34
+ abortReason: "network-error",
35
+ httpStatus: undefined,
36
+ };
37
+ }
38
+ return {
39
+ outcome: "aborted",
40
+ abortReason: responseState.failureReason,
41
+ httpStatus: responseState.httpStatus,
42
+ };
32
43
  }
33
44
  log.info(`✅ Run created with ID: ${responseState.runId}`);
34
45
  return {
@@ -1,23 +1,32 @@
1
- import { sleep, pluralize } from "../../utils.js";
1
+ import { sleep, pluralize, assertType } from "../../utils.js";
2
2
  import { fetchCiGreenlightStatus, } from "../../api/ci-greenlight.js";
3
+ // If you change these values, make sure you update the JSDoc
4
+ // comments in the PollConfig type.
3
5
  const safeDefaults = {
4
6
  maxRetries: 10,
5
7
  retryInterval: 10 * 1000,
6
8
  runInProgressInterval: 30 * 1000,
7
9
  runUnderReviewInterval: 60 * 1000,
10
+ pollTimeout: 120 * 60 * 1000,
8
11
  };
9
12
  export async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChanged: onRunStageChanged = () => void 0, ...pollConfig }) {
10
13
  let retries = 0;
11
14
  const { log } = deps;
12
- const { maxRetries = safeDefaults.maxRetries, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, } = pollConfig;
15
+ const { maxRetries = safeDefaults.maxRetries, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, pollTimeout = safeDefaults.pollTimeout, } = pollConfig;
13
16
  let currentStatus = undefined;
14
- while (true) {
17
+ const startedAt = Date.now();
18
+ let hasTimedOut = false;
19
+ while (!(hasTimedOut = Date.now() - startedAt > pollTimeout)) {
15
20
  const responseState = await fetchCiGreenlightStatus(apiConfig, {
16
21
  runId,
17
22
  }, deps);
18
23
  if (!responseState.ok && !responseState.canRetry) {
19
24
  log.error(`🚫 Unrecoverable error (status ${responseState.httpStatus}) from CI greenlight, aborting.`);
20
- return { outcome: "aborted" };
25
+ return {
26
+ outcome: "aborted",
27
+ abortReason: "4XX-client-error",
28
+ httpStatus: responseState.httpStatus,
29
+ };
21
30
  }
22
31
  if (!responseState.ok) {
23
32
  // This is a non-OK retryable status.
@@ -26,7 +35,24 @@ export async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStag
26
35
  log.error(`🚫 Unrecoverable error${responseState.httpStatus
27
36
  ? ` (status ${responseState.httpStatus})`
28
37
  : ""} from CI greenlight, aborting after ${maxRetries} attempts.`);
29
- return { outcome: "aborted" };
38
+ if (responseState.errorType === "network")
39
+ return {
40
+ outcome: "aborted",
41
+ abortReason: "network-error",
42
+ httpStatus: undefined,
43
+ };
44
+ let abortReason = "XXX-other-http-code";
45
+ if (responseState.errorType === "not-found")
46
+ abortReason = "404-run-not-found";
47
+ else if (responseState.errorType === "server")
48
+ abortReason = "5XX-server-error";
49
+ else
50
+ assertType(responseState);
51
+ return {
52
+ outcome: "aborted",
53
+ abortReason,
54
+ httpStatus: responseState.httpStatus,
55
+ };
30
56
  }
31
57
  const { errorType, httpStatus } = responseState;
32
58
  const retryLabel = `${httpStatus ? ` (status ${httpStatus})` : ""}, will try again... (${retries}/${maxRetries})`;
@@ -85,6 +111,23 @@ export async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStag
85
111
  return { outcome: "failed", greenlightStatus };
86
112
  }
87
113
  }
114
+ if (runStage === "canceled") {
115
+ log.info(`🚫 Run was canceled. Aborting... Please contact support.\n${urlInfo}`);
116
+ return {
117
+ outcome: "aborted",
118
+ abortReason: "run-canceled",
119
+ httpStatus: undefined,
120
+ };
121
+ }
122
+ // Non-terminal run stages
123
+ if (hasTimedOut) {
124
+ log.warn(`❌ Poll timed out after ${pollTimeout / 1000}s. Aborting...`);
125
+ return {
126
+ outcome: "aborted",
127
+ abortReason: "poll-timed-out",
128
+ httpStatus: undefined,
129
+ };
130
+ }
88
131
  if (runStage === "initializing") {
89
132
  log.info(`⏳ Run is in progress... ${urlInfo}`);
90
133
  await sleep(runInProgressInterval);
@@ -93,11 +136,15 @@ export async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStag
93
136
  log.info(`🕵️ Run is under review... ${urlInfo}`);
94
137
  await sleep(runUnderReviewInterval);
95
138
  }
96
- else if (runStage === "canceled") {
97
- log.info(`🚫 Run was canceled. Aborting... Please contact support.\n${urlInfo}`);
98
- return { outcome: "aborted" };
99
- }
100
- else
139
+ else {
140
+ assertType(runStage);
101
141
  throw new Error(`Unexpected run stage: ${runStage}`);
142
+ }
102
143
  }
144
+ log.warn(`❌ Poll timed out after ${pollTimeout / 1000}s. Aborting...`);
145
+ return {
146
+ outcome: "aborted",
147
+ abortReason: "poll-timed-out",
148
+ httpStatus: undefined,
149
+ };
103
150
  }
@@ -101,9 +101,9 @@ export declare function fetchCiGreenlightStatus({ serviceBase, apiKey }: ApiConf
101
101
  } | {
102
102
  readonly canRetry: false;
103
103
  readonly httpStatus: number;
104
+ readonly errorType: "client";
104
105
  readonly ok: false;
105
106
  readonly greenlightStatus?: never;
106
- readonly errorType?: never;
107
107
  } | {
108
108
  readonly canRetry: true;
109
109
  readonly errorType: "network";
@@ -39,25 +39,25 @@ export declare function postDeploySuccess({ apiKey, serviceBase }: ApiConfig, {
39
39
  readonly details?: never;
40
40
  readonly httpStatus?: never;
41
41
  } | {
42
- readonly failureReason: "server-error";
42
+ readonly failureReason: "5XX-server-error";
43
43
  readonly httpStatus: number;
44
44
  readonly success: false;
45
45
  readonly details?: never;
46
46
  readonly runId?: never;
47
47
  } | {
48
- readonly failureReason: "unauthorized";
48
+ readonly failureReason: "401-unauthorized";
49
49
  readonly httpStatus: 401;
50
50
  readonly success: false;
51
51
  readonly details?: never;
52
52
  readonly runId?: never;
53
53
  } | {
54
- readonly failureReason: "forbidden";
54
+ readonly failureReason: "403-forbidden";
55
55
  readonly httpStatus: 403;
56
56
  readonly success: false;
57
57
  readonly details?: never;
58
58
  readonly runId?: never;
59
59
  } | {
60
- readonly failureReason: "unrecoverable-error";
60
+ readonly failureReason: "4XX-client-error";
61
61
  readonly httpStatus: number;
62
62
  readonly success: false;
63
63
  readonly details?: never;
@@ -1,6 +1,10 @@
1
1
  import { DeployConfig } from "../../api/deploy.js";
2
2
  import { SdkDependencies } from "../dependencies.js";
3
3
  import { ApiConfig } from "../../api-types.js";
4
+ export type AttemptDeployFailedReason = "no-matched-trigger" | "run-could-not-be-created";
5
+ export type AttemptDeployHttpAbortReason = "4XX-client-error" | "401-unauthorized" | "403-forbidden" | "5XX-server-error";
6
+ export type AttemptDeployNonHttpAbortReason = "network-error";
7
+ export type AttemptDeployAbortReason = AttemptDeployHttpAbortReason | AttemptDeployNonHttpAbortReason;
4
8
  export type NotifyDeployStatus = {
5
9
  /**
6
10
  * A run was successfully created.
@@ -12,10 +16,20 @@ export type NotifyDeployStatus = {
12
16
  * A run could not be created.
13
17
  */
14
18
  outcome: "failed";
19
+ failReason: AttemptDeployFailedReason;
15
20
  } | {
16
21
  /**
17
22
  * An unrecoverable error occurred.
18
23
  */
19
24
  outcome: "aborted";
25
+ abortReason: AttemptDeployNonHttpAbortReason;
26
+ httpStatus: undefined;
27
+ } | {
28
+ /**
29
+ * An unrecoverable HTTP error occurred.
30
+ */
31
+ outcome: "aborted";
32
+ abortReason: AttemptDeployHttpAbortReason;
33
+ httpStatus: number;
20
34
  };
21
35
  export declare function attemptNotifyDeploy(deps: SdkDependencies, apiConfig: ApiConfig, config: Partial<DeployConfig>): Promise<NotifyDeployStatus>;
@@ -1,12 +1,41 @@
1
1
  import { CiGreenlightStatus } from "../../api/ci-greenlight.js";
2
2
  import { ApiConfig } from "../../api-types.js";
3
3
  import { SdkDependencies } from "../dependencies.js";
4
- export type PollConfig = {
4
+ export type PollCiGreenlightPollConfig = {
5
+ /**
6
+ * Maximum number of network operations retries before aborting the job.
7
+ *
8
+ * @default 10
9
+ */
5
10
  maxRetries: number;
11
+ /**
12
+ * Interval in milliseconds between network operations retries.
13
+ *
14
+ * @default 10 seconds
15
+ */
6
16
  retryInterval: number;
17
+ /**
18
+ * Interval in milliseconds between polling for a run in progress.
19
+ *
20
+ * @default 30 seconds
21
+ */
7
22
  runInProgressInterval: number;
23
+ /**
24
+ * Interval in milliseconds between polling for a run under review.
25
+ *
26
+ * @default 60 minutes
27
+ */
8
28
  runUnderReviewInterval: number;
29
+ /**
30
+ * Timeout in milliseconds before aborting this polling operation.
31
+ *
32
+ * @default 120 minutes
33
+ */
34
+ pollTimeout: number;
9
35
  };
36
+ export type PollCiGreenlightHttpAbortReason = "4XX-client-error" | "404-run-not-found" | "5XX-server-error" | "XXX-other-http-code";
37
+ export type PollCiGreenlightNonHttpAbortReason = "poll-timed-out" | "run-canceled" | "network-error";
38
+ export type PollCiGreenlightAbortReason = PollCiGreenlightNonHttpAbortReason | PollCiGreenlightHttpAbortReason;
10
39
  export type PollCiGreenlightStatus = {
11
40
  /**
12
41
  * No blocking bugs were found in the run.
@@ -28,6 +57,15 @@ export type PollCiGreenlightStatus = {
28
57
  * The run was aborted due to an unrecoverable error.
29
58
  */
30
59
  outcome: "aborted";
60
+ abortReason: PollCiGreenlightHttpAbortReason;
61
+ httpStatus: number;
62
+ } | {
63
+ /**
64
+ * The run was aborted due to an unrecoverable error.
65
+ */
66
+ outcome: "aborted";
67
+ abortReason: PollCiGreenlightNonHttpAbortReason;
68
+ httpStatus: undefined;
31
69
  };
32
70
  export type PollCiGreenlightParams = {
33
71
  runId: string;
@@ -35,5 +73,5 @@ export type PollCiGreenlightParams = {
35
73
  * Callback to be called when the lifecycle stage of the run changes.
36
74
  */
37
75
  onRunStageChanged?: (current: CiGreenlightStatus, previous: CiGreenlightStatus | undefined) => unknown | Promise<unknown>;
38
- } & Partial<PollConfig>;
76
+ } & Partial<PollCiGreenlightPollConfig>;
39
77
  export declare function pollCiGreenlightStatus(deps: SdkDependencies, apiConfig: ApiConfig, { runId, onRunStageChanged: onRunStageChanged, ...pollConfig }: PollCiGreenlightParams): Promise<PollCiGreenlightStatus>;
@@ -6,3 +6,5 @@ export declare function makeQaWolfSdk({ apiKey, serviceBase, }: {
6
6
  attemptNotifyDeploy: (config: Partial<import("../api/deploy.js").DeployConfig>) => Promise<import("./domain/attempt-deploy.js").NotifyDeployStatus>;
7
7
  pollCiGreenlightStatus: (args_0: import("./domain/poll-ci-greenlight.js").PollCiGreenlightParams) => Promise<import("./domain/poll-ci-greenlight.js").PollCiGreenlightStatus>;
8
8
  };
9
+ export type * from "./domain/poll-ci-greenlight.js";
10
+ export type * from "./domain/attempt-deploy.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qawolf/ci-sdk",
3
- "version": "0.12.1",
3
+ "version": "0.14.0",
4
4
  "description": "A simple SDK for interacting with QAWolf in CI scripts.",
5
5
  "type": "module",
6
6
  "private": false,