@qawolf/ci-sdk 2.1.0 → 2.5.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 +15 -0
- package/dist/index.cjs +401 -184
- package/dist/index.cjs.map +7 -1
- package/dist/index.d.ts +4 -534
- package/dist/index.js +376 -182
- package/dist/index.js.map +7 -1
- package/dist/lib/api/ci-greenlight-bug-data.d.ts +67 -0
- package/dist/lib/api/ci-greenlight.d.ts +76 -0
- package/dist/lib/api/generate-signed-url-for-run-inputs-executables.d.ts +4 -0
- package/dist/lib/api/generate-signed-url-for-team-storage.d.ts +4 -0
- package/dist/lib/api/index.d.ts +2 -0
- package/dist/lib/api/log.d.ts +6 -0
- package/dist/lib/api/signed-url.d.ts +11 -0
- package/dist/lib/api-types.d.ts +5 -0
- package/dist/lib/other.d.ts +5 -0
- package/dist/lib/sdk/defaults/fetch.d.ts +1 -0
- package/dist/lib/sdk/defaults/log.d.ts +2 -0
- package/dist/lib/sdk/defaults/serviceBase.d.ts +1 -0
- package/dist/lib/sdk/defaults/userAgent.d.ts +1 -0
- package/dist/lib/sdk/dependencies.d.ts +7 -0
- package/dist/lib/sdk/domain/attemptDeploy/deployConfig.d.ts +37 -0
- package/dist/lib/sdk/domain/attemptDeploy/deploySuccessWireResponse.d.ts +39 -0
- package/dist/lib/sdk/domain/attemptDeploy/handleSuccessResponse.d.ts +3 -0
- package/dist/lib/sdk/domain/attemptDeploy/index.d.ts +4 -0
- package/dist/lib/sdk/domain/attemptDeploy/mapDeploySuccessResponse.d.ts +3 -0
- package/dist/lib/sdk/domain/attemptDeploy/parseDeploySuccessWireResponse.d.ts +2 -0
- package/dist/lib/sdk/domain/attemptDeploy/types.d.ts +129 -0
- package/dist/lib/sdk/domain/generateSignedUrls/generate-signed-url-for-run-inputs-executables.d.ts +4 -0
- package/dist/lib/sdk/domain/generateSignedUrls/generate-signed-url-for-team-storage.d.ts +16 -0
- package/dist/lib/sdk/domain/generateSignedUrls/types.d.ts +28 -0
- package/dist/lib/sdk/domain/notifyTerminatedEphemeralEnvironment/index.d.ts +4 -0
- package/dist/lib/sdk/domain/notifyTerminatedEphemeralEnvironment/types.d.ts +48 -0
- package/dist/lib/sdk/domain/pollCiGreenlight/buildCompletedRunResult.d.ts +8 -0
- package/dist/lib/sdk/domain/pollCiGreenlight/consts.d.ts +7 -0
- package/dist/lib/sdk/domain/pollCiGreenlight/index.d.ts +4 -0
- package/dist/lib/sdk/domain/pollCiGreenlight/iterator.d.ts +43 -0
- package/dist/lib/sdk/domain/pollCiGreenlight/logging.d.ts +25 -0
- package/dist/lib/sdk/domain/pollCiGreenlight/mapIteratorAbortToGreenlightStatus.d.ts +7 -0
- package/dist/lib/sdk/domain/pollCiGreenlight/types.d.ts +145 -0
- package/dist/lib/sdk/index.d.ts +26 -0
- package/package.json +13 -12
- package/dist/index.d.cts +0 -534
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* Built with @qawolf/platform-builder@1.2.2 */
|
|
2
|
+
"use strict";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
7
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// src/index.ts
|
|
23
|
+
var index_exports = {};
|
|
24
|
+
__export(index_exports, {
|
|
25
|
+
makeQaWolfSdk: () => makeQaWolfSdk
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
5
28
|
|
|
6
29
|
// src/lib/other.ts
|
|
7
30
|
function sleep(ms) {
|
|
@@ -14,10 +37,7 @@ function pluralize(count) {
|
|
|
14
37
|
__name(pluralize, "pluralize");
|
|
15
38
|
var buildFetchWithTimeout = /* @__PURE__ */ __name((fetch, defaultTimeoutMs) => async (...args) => {
|
|
16
39
|
const signal = args[1]?.signal ?? AbortSignal.timeout(defaultTimeoutMs);
|
|
17
|
-
return fetch(args[0], {
|
|
18
|
-
...args[1],
|
|
19
|
-
signal
|
|
20
|
-
});
|
|
40
|
+
return fetch(args[0], { ...args[1], signal });
|
|
21
41
|
}, "buildFetchWithTimeout");
|
|
22
42
|
|
|
23
43
|
// src/lib/sdk/defaults/fetch.ts
|
|
@@ -41,13 +61,61 @@ var defaultServiceBase = "https://app.qawolf.com/";
|
|
|
41
61
|
|
|
42
62
|
// package.json
|
|
43
63
|
var package_default = {
|
|
44
|
-
|
|
64
|
+
name: "@qawolf/ci-sdk",
|
|
65
|
+
version: "2.5.0",
|
|
66
|
+
private: false,
|
|
67
|
+
description: "A simple SDK for interacting with QAWolf in CI scripts.",
|
|
68
|
+
keywords: [],
|
|
69
|
+
license: "MIT",
|
|
70
|
+
author: "Jules Sam. Randolph<jules@qawolf.com>",
|
|
71
|
+
files: [
|
|
72
|
+
"/dist",
|
|
73
|
+
"/README.md"
|
|
74
|
+
],
|
|
75
|
+
type: "module",
|
|
76
|
+
sideEffects: false,
|
|
77
|
+
exports: {
|
|
78
|
+
".": {
|
|
79
|
+
types: "./dist/index.d.ts",
|
|
80
|
+
require: "./dist/index.cjs",
|
|
81
|
+
import: "./dist/index.js",
|
|
82
|
+
default: "./dist/index.js"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
scripts: {
|
|
86
|
+
build: "platform-builder --config platformBuilder.config.ts --config platformBuilder.cjs.config.ts",
|
|
87
|
+
"lint:ci": "npm run lint:first-half; FIRST_HALF_EXIT=$?; npm run lint:second-half && exit $FIRST_HALF_EXIT",
|
|
88
|
+
"lint:dev": "npm run lint:first-half",
|
|
89
|
+
"lint:first-half": "eslint . --fix --quiet && oxfmt --write .",
|
|
90
|
+
"lint:second-half": "dpdm --exit-code circular:1 --no-tree --no-warning --transform --include='.*' --exclude='/(dist|node_modules)/' '**/*'",
|
|
91
|
+
prepublishOnly: "nx run ci-sdk:build",
|
|
92
|
+
test: 'NODE_OPTIONS="--experimental-vm-modules" NODE_NO_WARNINGS=1 jest',
|
|
93
|
+
"tsc:check": "tsc --noEmit"
|
|
94
|
+
},
|
|
95
|
+
dependencies: {
|
|
96
|
+
"@qawolf/ci-utils": "^1.1.2",
|
|
97
|
+
"@sinonjs/fake-timers": "^10.3.0",
|
|
98
|
+
tslib: "^2.6.2"
|
|
99
|
+
},
|
|
100
|
+
devDependencies: {
|
|
101
|
+
"@qawolf/platform-builder": "^1.2.2",
|
|
102
|
+
tsx: "^4.19.4",
|
|
103
|
+
typescript: "^5.9.3"
|
|
104
|
+
},
|
|
105
|
+
engines: {
|
|
106
|
+
node: ">=20"
|
|
107
|
+
}
|
|
108
|
+
};
|
|
45
109
|
|
|
46
110
|
// src/lib/sdk/defaults/userAgent.ts
|
|
47
111
|
var defaultUserAgent = `ci-sdk/${package_default.version}`;
|
|
48
112
|
|
|
49
113
|
// src/lib/api/log.ts
|
|
50
|
-
async function logFetchError({
|
|
114
|
+
async function logFetchError({
|
|
115
|
+
log,
|
|
116
|
+
methodName,
|
|
117
|
+
response
|
|
118
|
+
}) {
|
|
51
119
|
if (response.ok) return;
|
|
52
120
|
const { eventId, failureMessage } = await (async () => {
|
|
53
121
|
try {
|
|
@@ -72,7 +140,9 @@ async function logFetchError({ log, methodName, response }) {
|
|
|
72
140
|
const eventIdSuffix = eventId ? ` (Event ID: ${eventId})` : "";
|
|
73
141
|
const messageSuffix = failureMessage ? `: ${failureMessage}` : "";
|
|
74
142
|
const statusText = response.status >= 500 ? "Server Error" : response.statusText || "Unknown Error";
|
|
75
|
-
log.error(
|
|
143
|
+
log.error(
|
|
144
|
+
`\u274C [${methodName}] ${response.status} ${statusText}${eventIdSuffix}${messageSuffix}`
|
|
145
|
+
);
|
|
76
146
|
}
|
|
77
147
|
__name(logFetchError, "logFetchError");
|
|
78
148
|
|
|
@@ -82,6 +152,7 @@ async function handleSuccessResponse(data, log) {
|
|
|
82
152
|
const skippedTriggers = data.skippedTriggers ?? [];
|
|
83
153
|
const skippedDeployment = data.skippedDeployment;
|
|
84
154
|
const isPreviewDeployment = environment && !environment.isStatic;
|
|
155
|
+
if (data.warning) log.warn(`\u26A0\uFE0F ${data.warning}`);
|
|
85
156
|
if (environment) {
|
|
86
157
|
const logPrefix = environment.isStatic ? "Static environment" : "Preview environment";
|
|
87
158
|
log.info(`${logPrefix}: ${environment.alias} (id: ${environment.id})`);
|
|
@@ -89,13 +160,13 @@ async function handleSuccessResponse(data, log) {
|
|
|
89
160
|
if (results.length === 0) {
|
|
90
161
|
const skipMessages = [
|
|
91
162
|
...skippedTriggers.map((trigger) => trigger.message),
|
|
92
|
-
...skippedDeployment ? [
|
|
93
|
-
skippedDeployment.message
|
|
94
|
-
] : []
|
|
163
|
+
...skippedDeployment ? [skippedDeployment.message] : []
|
|
95
164
|
];
|
|
96
165
|
const skipDetail = skipMessages.length > 0 ? ` ${skipMessages.join(" ")}` : "";
|
|
97
166
|
if (isPreviewDeployment) {
|
|
98
|
-
log.info(
|
|
167
|
+
log.info(
|
|
168
|
+
`\u2705 Deployment notification was successful. No run was created for this deployment.${skipDetail}`
|
|
169
|
+
);
|
|
99
170
|
return {
|
|
100
171
|
environmentId: environment.id,
|
|
101
172
|
outcome: "success",
|
|
@@ -110,7 +181,9 @@ async function handleSuccessResponse(data, log) {
|
|
|
110
181
|
skippedTriggers
|
|
111
182
|
};
|
|
112
183
|
}
|
|
113
|
-
log.warn(
|
|
184
|
+
log.warn(
|
|
185
|
+
skippedDeployment ? `\u26A0\uFE0F No run was created for this deployment.${skipDetail}` : `\u26A0\uFE0F No trigger matched the request. Please make sure there is at least one active test in the QA Wolf environment, or contact support.`
|
|
186
|
+
);
|
|
114
187
|
return {
|
|
115
188
|
outcome: "skipped",
|
|
116
189
|
skippedDeployment
|
|
@@ -118,45 +191,43 @@ async function handleSuccessResponse(data, log) {
|
|
|
118
191
|
}
|
|
119
192
|
if (!environment) {
|
|
120
193
|
log.error(`\u{1F6AB} No environment matched the request. Please contact support.`);
|
|
121
|
-
return {
|
|
122
|
-
failReason: "no-environment",
|
|
123
|
-
outcome: "failed"
|
|
124
|
-
};
|
|
194
|
+
return { failReason: "no-environment", outcome: "failed" };
|
|
125
195
|
}
|
|
126
196
|
const unrecognizedResult = results.find((result) => "unrecognized" in result);
|
|
127
197
|
if (unrecognizedResult) {
|
|
128
|
-
log.error(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
};
|
|
198
|
+
log.error(
|
|
199
|
+
`\u{1F6AB} The deployment response contained an unrecognized result. Please upgrade @qawolf/ci-sdk.`
|
|
200
|
+
);
|
|
201
|
+
return { failReason: "unknown-result", outcome: "failed" };
|
|
133
202
|
}
|
|
134
203
|
const failedTrigger = results.find((result) => "failureReason" in result);
|
|
135
204
|
if (failedTrigger) {
|
|
136
|
-
log.error(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
};
|
|
205
|
+
log.error(
|
|
206
|
+
`\u{1F6AB} Run could not be created. Reason: "${failedTrigger.failureMessage ?? failedTrigger.failureReason}". Please contact support.`
|
|
207
|
+
);
|
|
208
|
+
return { failReason: "run-could-not-be-created", outcome: "failed" };
|
|
141
209
|
}
|
|
142
210
|
const duplicateSuite = results.find((result) => "duplicateSuiteId" in result);
|
|
143
211
|
if (duplicateSuite) {
|
|
144
|
-
log.info(
|
|
212
|
+
log.info(
|
|
213
|
+
`\u2705 Deployment notification was successful. Previous run ID: ${duplicateSuite.duplicateSuiteId} already exists for this deployment.`
|
|
214
|
+
);
|
|
145
215
|
return {
|
|
146
216
|
environmentId: environment.id,
|
|
147
217
|
outcome: "success",
|
|
148
218
|
runId: duplicateSuite.duplicateSuiteId
|
|
149
219
|
};
|
|
150
220
|
}
|
|
151
|
-
const successfulTrigger = results.find(
|
|
221
|
+
const successfulTrigger = results.find(
|
|
222
|
+
(result) => "createdSuiteId" in result
|
|
223
|
+
);
|
|
152
224
|
if (!successfulTrigger) {
|
|
153
225
|
log.error(`\u{1F6AB} Run could not be created. Please contact support.`);
|
|
154
|
-
return {
|
|
155
|
-
failReason: "run-could-not-be-created",
|
|
156
|
-
outcome: "failed"
|
|
157
|
-
};
|
|
226
|
+
return { failReason: "run-could-not-be-created", outcome: "failed" };
|
|
158
227
|
}
|
|
159
|
-
log.info(
|
|
228
|
+
log.info(
|
|
229
|
+
`\u2705 Deployment notification was successful. Run created with ID: ${successfulTrigger.createdSuiteId}`
|
|
230
|
+
);
|
|
160
231
|
return {
|
|
161
232
|
environmentId: environment.id,
|
|
162
233
|
outcome: "success",
|
|
@@ -167,29 +238,28 @@ __name(handleSuccessResponse, "handleSuccessResponse");
|
|
|
167
238
|
|
|
168
239
|
// src/lib/sdk/domain/attemptDeploy/mapDeploySuccessResponse.ts
|
|
169
240
|
function mapSuiteResult(result) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
241
|
+
switch (result.outcome) {
|
|
242
|
+
case "created":
|
|
243
|
+
return {
|
|
244
|
+
createdSuiteId: result.created_suite_id,
|
|
245
|
+
triggerId: result.trigger_id
|
|
246
|
+
};
|
|
247
|
+
case "failed":
|
|
248
|
+
return {
|
|
249
|
+
failureCode: result.failure_code,
|
|
250
|
+
failureMessage: result.failure_message,
|
|
251
|
+
failureReason: result.failure_reason,
|
|
252
|
+
triggerId: result.trigger_id
|
|
253
|
+
};
|
|
254
|
+
case "skipped":
|
|
255
|
+
return {
|
|
256
|
+
duplicateSuiteId: result.duplicate_suite_id,
|
|
257
|
+
skipReason: result.skip_reason,
|
|
258
|
+
triggerId: result.trigger_id
|
|
259
|
+
};
|
|
260
|
+
default:
|
|
261
|
+
return { triggerId: result.trigger_id, unrecognized: true };
|
|
188
262
|
}
|
|
189
|
-
return {
|
|
190
|
-
triggerId: result.trigger_id,
|
|
191
|
-
unrecognized: true
|
|
192
|
-
};
|
|
193
263
|
}
|
|
194
264
|
__name(mapSuiteResult, "mapSuiteResult");
|
|
195
265
|
function mapDeploySuccessResponse(wire) {
|
|
@@ -205,7 +275,8 @@ function mapDeploySuccessResponse(wire) {
|
|
|
205
275
|
message: trigger.message,
|
|
206
276
|
reason: trigger.reason,
|
|
207
277
|
triggerId: trigger.trigger_id
|
|
208
|
-
}))
|
|
278
|
+
})),
|
|
279
|
+
warning: wire.warning
|
|
209
280
|
};
|
|
210
281
|
}
|
|
211
282
|
__name(mapDeploySuccessResponse, "mapDeploySuccessResponse");
|
|
@@ -215,22 +286,32 @@ function isRecord(value) {
|
|
|
215
286
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
216
287
|
}
|
|
217
288
|
__name(isRecord, "isRecord");
|
|
289
|
+
function isOptionalString(value) {
|
|
290
|
+
return value === void 0 || typeof value === "string";
|
|
291
|
+
}
|
|
292
|
+
__name(isOptionalString, "isOptionalString");
|
|
218
293
|
function isWireSuiteResult(value) {
|
|
219
294
|
if (!isRecord(value)) return false;
|
|
220
295
|
if (typeof value.trigger_id !== "string") return false;
|
|
221
|
-
if (
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
296
|
+
if (!isOptionalString(value.outcome)) return false;
|
|
297
|
+
switch (value.outcome) {
|
|
298
|
+
case "created":
|
|
299
|
+
return typeof value.created_suite_id === "string";
|
|
300
|
+
case "failed":
|
|
301
|
+
return typeof value.failure_reason === "string" && isOptionalString(value.failure_code) && isOptionalString(value.failure_message);
|
|
302
|
+
case "skipped":
|
|
303
|
+
return typeof value.duplicate_suite_id === "string" && typeof value.skip_reason === "string";
|
|
304
|
+
default:
|
|
305
|
+
return true;
|
|
225
306
|
}
|
|
226
|
-
return true;
|
|
227
307
|
}
|
|
228
308
|
__name(isWireSuiteResult, "isWireSuiteResult");
|
|
229
309
|
function isEnvironment(value) {
|
|
230
310
|
if (!isRecord(value)) return false;
|
|
231
311
|
if (typeof value.id !== "string") return false;
|
|
232
312
|
if (typeof value.isStatic !== "boolean") return false;
|
|
233
|
-
if (value.alias !== void 0 && typeof value.alias !== "string")
|
|
313
|
+
if (value.alias !== void 0 && typeof value.alias !== "string")
|
|
314
|
+
return false;
|
|
234
315
|
return true;
|
|
235
316
|
}
|
|
236
317
|
__name(isEnvironment, "isEnvironment");
|
|
@@ -246,10 +327,15 @@ function isSkippedTrigger(value) {
|
|
|
246
327
|
__name(isSkippedTrigger, "isSkippedTrigger");
|
|
247
328
|
function isDeploySuccessWireResponse(value) {
|
|
248
329
|
if (!isRecord(value)) return false;
|
|
249
|
-
if (value.environment !== void 0 && !isEnvironment(value.environment))
|
|
250
|
-
|
|
251
|
-
if (value.
|
|
252
|
-
|
|
330
|
+
if (value.environment !== void 0 && !isEnvironment(value.environment))
|
|
331
|
+
return false;
|
|
332
|
+
if (!Array.isArray(value.results) || !value.results.every(isWireSuiteResult))
|
|
333
|
+
return false;
|
|
334
|
+
if (value.skipped_deployment !== void 0 && !isSkippedDeployment(value.skipped_deployment))
|
|
335
|
+
return false;
|
|
336
|
+
if (value.skipped_triggers !== void 0 && (!Array.isArray(value.skipped_triggers) || !value.skipped_triggers.every(isSkippedTrigger)))
|
|
337
|
+
return false;
|
|
338
|
+
if (!isOptionalString(value.warning)) return false;
|
|
253
339
|
return true;
|
|
254
340
|
}
|
|
255
341
|
__name(isDeploySuccessWireResponse, "isDeploySuccessWireResponse");
|
|
@@ -264,34 +350,38 @@ async function attemptNotifyDeploy(deps, apiConfig, config) {
|
|
|
264
350
|
let response;
|
|
265
351
|
let bodyText;
|
|
266
352
|
try {
|
|
267
|
-
response = await localFetch(
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
353
|
+
response = await localFetch(
|
|
354
|
+
new URL("/api/webhooks/deploy_success", apiConfig.serviceBase),
|
|
355
|
+
{
|
|
356
|
+
body: JSON.stringify({
|
|
357
|
+
branch: config.branch,
|
|
358
|
+
commit_url: config.commitUrl,
|
|
359
|
+
deduplication_key: config.deduplicationKey,
|
|
360
|
+
deployment_type: config.deploymentType,
|
|
361
|
+
deployment_url: config.deploymentUrl,
|
|
362
|
+
..."ephemeralEnvironment" in config ? {
|
|
363
|
+
ephemeral_environment: config.ephemeralEnvironment
|
|
364
|
+
} : "hostingService" in config && {
|
|
365
|
+
hosting_service: config.hostingService,
|
|
366
|
+
merge_request_number: config.hostingService === "GitLab" ? config.mergeRequestNumber : void 0,
|
|
367
|
+
pull_request_number: config.hostingService === "GitHub" ? config.pullRequestNumber : void 0,
|
|
368
|
+
repository: config.repository
|
|
369
|
+
},
|
|
370
|
+
sha: config.sha,
|
|
371
|
+
variables: config.variables,
|
|
372
|
+
workspaceId: config.workspaceId
|
|
373
|
+
}),
|
|
374
|
+
headers: {
|
|
375
|
+
Authorization: `Bearer ${apiConfig.apiKey}`,
|
|
376
|
+
"Content-Type": "application/json",
|
|
377
|
+
"User-Agent": apiConfig.userAgent
|
|
281
378
|
},
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
"User-Agent": apiConfig.userAgent
|
|
289
|
-
},
|
|
290
|
-
method: "POST",
|
|
291
|
-
// Override default timeout to 5 minutes. This gives extra room
|
|
292
|
-
// for both (1) waiting for reconciliation (2) creating the run.
|
|
293
|
-
signal: AbortSignal.timeout(5 * 60 * 1e3)
|
|
294
|
-
});
|
|
379
|
+
method: "POST",
|
|
380
|
+
// Override default timeout to 5 minutes. This gives extra room
|
|
381
|
+
// for both (1) waiting for reconciliation (2) creating the run.
|
|
382
|
+
signal: AbortSignal.timeout(5 * 60 * 1e3)
|
|
383
|
+
}
|
|
384
|
+
);
|
|
295
385
|
if (!response.ok) return handleErrorResponse(response, log);
|
|
296
386
|
bodyText = await response.text();
|
|
297
387
|
} catch {
|
|
@@ -310,7 +400,10 @@ async function attemptNotifyDeploy(deps, apiConfig, config) {
|
|
|
310
400
|
}
|
|
311
401
|
const wire = parseDeploySuccessWireResponse(rawBody);
|
|
312
402
|
if (wire === "invalid") {
|
|
313
|
-
return abortInvalidResponseBody(
|
|
403
|
+
return abortInvalidResponseBody(
|
|
404
|
+
log,
|
|
405
|
+
"the response body did not match the expected shape"
|
|
406
|
+
);
|
|
314
407
|
}
|
|
315
408
|
const data = mapDeploySuccessResponse(wire);
|
|
316
409
|
return handleSuccessResponse(data, log);
|
|
@@ -346,17 +439,45 @@ async function handleErrorResponse(response, log) {
|
|
|
346
439
|
}
|
|
347
440
|
__name(handleErrorResponse, "handleErrorResponse");
|
|
348
441
|
|
|
442
|
+
// src/lib/api/signed-url.ts
|
|
443
|
+
var signedUrlPaths = {
|
|
444
|
+
runInputsExecutables: "/api/v0/run-inputs-executables-signed-urls",
|
|
445
|
+
teamStorage: "/api/v0/team-storage-signed-url"
|
|
446
|
+
};
|
|
447
|
+
function buildSignedUrl({
|
|
448
|
+
destinationFilePath,
|
|
449
|
+
endpoint,
|
|
450
|
+
serviceBase,
|
|
451
|
+
workspaceId
|
|
452
|
+
}) {
|
|
453
|
+
const url = new URL(signedUrlPaths[endpoint], serviceBase);
|
|
454
|
+
if (destinationFilePath !== void 0)
|
|
455
|
+
url.searchParams.set("file", destinationFilePath);
|
|
456
|
+
if (workspaceId !== void 0)
|
|
457
|
+
url.searchParams.set("workspaceId", workspaceId);
|
|
458
|
+
return url;
|
|
459
|
+
}
|
|
460
|
+
__name(buildSignedUrl, "buildSignedUrl");
|
|
461
|
+
|
|
349
462
|
// src/lib/api/generate-signed-url-for-run-inputs-executables.ts
|
|
350
|
-
async function callGenerateSignedUrlForRunInputsExecutablesStorage({ apiKey, serviceBase, userAgent }, { destinationFilePath }, { fetch: localFetch, log }) {
|
|
463
|
+
async function callGenerateSignedUrlForRunInputsExecutablesStorage({ apiKey, serviceBase, userAgent }, { destinationFilePath, workspaceId }, { fetch: localFetch, log }) {
|
|
351
464
|
try {
|
|
352
|
-
const response = await localFetch(
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
465
|
+
const response = await localFetch(
|
|
466
|
+
buildSignedUrl({
|
|
467
|
+
destinationFilePath,
|
|
468
|
+
endpoint: "runInputsExecutables",
|
|
469
|
+
serviceBase,
|
|
470
|
+
workspaceId
|
|
471
|
+
}),
|
|
472
|
+
{
|
|
473
|
+
headers: {
|
|
474
|
+
Authorization: `Bearer ${apiKey}`,
|
|
475
|
+
"Content-Type": "application/json",
|
|
476
|
+
"User-Agent": userAgent
|
|
477
|
+
},
|
|
478
|
+
method: "GET"
|
|
479
|
+
}
|
|
480
|
+
);
|
|
360
481
|
if (response.status === 200) {
|
|
361
482
|
const json = await response.json();
|
|
362
483
|
return {
|
|
@@ -397,18 +518,28 @@ async function generateSignedUrlForRunInputsExecutablesStorage(deps, apiConfig,
|
|
|
397
518
|
success: false
|
|
398
519
|
};
|
|
399
520
|
}
|
|
400
|
-
const responseState = await callGenerateSignedUrlForRunInputsExecutablesStorage(
|
|
521
|
+
const responseState = await callGenerateSignedUrlForRunInputsExecutablesStorage(
|
|
522
|
+
apiConfig,
|
|
523
|
+
config,
|
|
524
|
+
deps
|
|
525
|
+
);
|
|
401
526
|
if (!responseState.success) {
|
|
402
527
|
let abortReason = "XXX-other-http-code";
|
|
403
528
|
if (responseState.httpStatus >= 500) {
|
|
404
529
|
abortReason = "5XX-server-error";
|
|
405
|
-
log.error(
|
|
530
|
+
log.error(
|
|
531
|
+
`\u{1F6AB} Unrecoverable error (status ${responseState.httpStatus}) when generating signed upload url: aborting.`
|
|
532
|
+
);
|
|
406
533
|
} else {
|
|
407
534
|
if (responseState.httpStatus === 400) abortReason = "400-invalid-request";
|
|
408
|
-
else if (responseState.httpStatus === 401)
|
|
535
|
+
else if (responseState.httpStatus === 401)
|
|
536
|
+
abortReason = "401-invalid-credentials";
|
|
409
537
|
else if (responseState.httpStatus === 403) abortReason = "403-forbidden";
|
|
410
|
-
else if (responseState.httpStatus === 0)
|
|
411
|
-
|
|
538
|
+
else if (responseState.httpStatus === 0)
|
|
539
|
+
abortReason = "client-network-error";
|
|
540
|
+
log.error(
|
|
541
|
+
`\u{1F6AB} Unrecoverable error (status ${responseState.httpStatus}) when generating signed upload url: ${responseState.errorMessage ? `${responseState.errorMessage}.` : ""} aborting.`
|
|
542
|
+
);
|
|
412
543
|
}
|
|
413
544
|
return {
|
|
414
545
|
abortReason,
|
|
@@ -427,16 +558,24 @@ async function generateSignedUrlForRunInputsExecutablesStorage(deps, apiConfig,
|
|
|
427
558
|
__name(generateSignedUrlForRunInputsExecutablesStorage, "generateSignedUrlForRunInputsExecutablesStorage");
|
|
428
559
|
|
|
429
560
|
// src/lib/api/generate-signed-url-for-team-storage.ts
|
|
430
|
-
async function callGenerateSignedUrlForTempTeamStorage({ apiKey, serviceBase, userAgent }, { destinationFilePath }, { fetch: localFetch, log }) {
|
|
561
|
+
async function callGenerateSignedUrlForTempTeamStorage({ apiKey, serviceBase, userAgent }, { destinationFilePath, workspaceId }, { fetch: localFetch, log }) {
|
|
431
562
|
try {
|
|
432
|
-
const response = await localFetch(
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
563
|
+
const response = await localFetch(
|
|
564
|
+
buildSignedUrl({
|
|
565
|
+
destinationFilePath,
|
|
566
|
+
endpoint: "teamStorage",
|
|
567
|
+
serviceBase,
|
|
568
|
+
workspaceId
|
|
569
|
+
}),
|
|
570
|
+
{
|
|
571
|
+
headers: {
|
|
572
|
+
Authorization: `Bearer ${apiKey}`,
|
|
573
|
+
"Content-Type": "application/json",
|
|
574
|
+
"User-Agent": userAgent
|
|
575
|
+
},
|
|
576
|
+
method: "GET"
|
|
577
|
+
}
|
|
578
|
+
);
|
|
440
579
|
if (response.status === 200) {
|
|
441
580
|
const json = await response.json();
|
|
442
581
|
return {
|
|
@@ -477,18 +616,28 @@ async function generateSignedUrlForTempTeamStorage(deps, apiConfig, config) {
|
|
|
477
616
|
success: false
|
|
478
617
|
};
|
|
479
618
|
}
|
|
480
|
-
const responseState = await callGenerateSignedUrlForTempTeamStorage(
|
|
619
|
+
const responseState = await callGenerateSignedUrlForTempTeamStorage(
|
|
620
|
+
apiConfig,
|
|
621
|
+
config,
|
|
622
|
+
deps
|
|
623
|
+
);
|
|
481
624
|
if (!responseState.success) {
|
|
482
625
|
let abortReason = "XXX-other-http-code";
|
|
483
626
|
if (responseState.httpStatus >= 500) {
|
|
484
627
|
abortReason = "5XX-server-error";
|
|
485
|
-
log.error(
|
|
628
|
+
log.error(
|
|
629
|
+
`\u{1F6AB} Unrecoverable error (status ${responseState.httpStatus}) when generating signed upload url: aborting.`
|
|
630
|
+
);
|
|
486
631
|
} else {
|
|
487
632
|
if (responseState.httpStatus === 400) abortReason = "400-invalid-request";
|
|
488
|
-
else if (responseState.httpStatus === 401)
|
|
633
|
+
else if (responseState.httpStatus === 401)
|
|
634
|
+
abortReason = "401-invalid-credentials";
|
|
489
635
|
else if (responseState.httpStatus === 403) abortReason = "403-forbidden";
|
|
490
|
-
else if (responseState.httpStatus === 0)
|
|
491
|
-
|
|
636
|
+
else if (responseState.httpStatus === 0)
|
|
637
|
+
abortReason = "client-network-error";
|
|
638
|
+
log.error(
|
|
639
|
+
`\u{1F6AB} Unrecoverable error (status ${responseState.httpStatus}) when generating signed upload url: ${responseState.errorMessage ? `${responseState.errorMessage}.` : ""} aborting.`
|
|
640
|
+
);
|
|
492
641
|
}
|
|
493
642
|
return {
|
|
494
643
|
abortReason,
|
|
@@ -510,21 +659,22 @@ __name(generateSignedUrlForTempTeamStorage, "generateSignedUrlForTempTeamStorage
|
|
|
510
659
|
var notifyTerminatedEphemeralEnvironment = /* @__PURE__ */ __name(async (deps, apiConfig, config) => {
|
|
511
660
|
const { fetch: localFetch, log } = deps;
|
|
512
661
|
try {
|
|
513
|
-
const response = await localFetch(
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
662
|
+
const response = await localFetch(
|
|
663
|
+
new URL("/api/webhooks/environment_terminated", apiConfig.serviceBase),
|
|
664
|
+
{
|
|
665
|
+
body: JSON.stringify(config),
|
|
666
|
+
headers: {
|
|
667
|
+
Authorization: `Bearer ${apiConfig.apiKey}`,
|
|
668
|
+
"Content-Type": "application/json",
|
|
669
|
+
"User-Agent": apiConfig.userAgent
|
|
670
|
+
},
|
|
671
|
+
method: "POST"
|
|
672
|
+
}
|
|
673
|
+
);
|
|
522
674
|
if (!response.ok) return handleErrorResponse2(response, log);
|
|
523
|
-
const { environmentId } = await response.json();
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
outcome: "success"
|
|
527
|
-
};
|
|
675
|
+
const { environmentId, warning } = await response.json();
|
|
676
|
+
if (warning) log.warn(`\u26A0\uFE0F ${warning}`);
|
|
677
|
+
return { environmentId, outcome: "success" };
|
|
528
678
|
} catch {
|
|
529
679
|
log.error(`\u{1F6AB} Network error from terminate_preview_environment, aborting.`);
|
|
530
680
|
return {
|
|
@@ -557,14 +707,9 @@ __name(handleErrorResponse2, "handleErrorResponse");
|
|
|
557
707
|
|
|
558
708
|
// src/lib/sdk/domain/pollCiGreenlight/buildCompletedRunResult.ts
|
|
559
709
|
function buildCompletedRunResult(status) {
|
|
560
|
-
if (status.greenlight)
|
|
561
|
-
greenlightStatus: status,
|
|
562
|
-
|
|
563
|
-
};
|
|
564
|
-
else return {
|
|
565
|
-
greenlightStatus: status,
|
|
566
|
-
outcome: "failed"
|
|
567
|
-
};
|
|
710
|
+
if (status.greenlight)
|
|
711
|
+
return { greenlightStatus: status, outcome: "success" };
|
|
712
|
+
else return { greenlightStatus: status, outcome: "failed" };
|
|
568
713
|
}
|
|
569
714
|
__name(buildCompletedRunResult, "buildCompletedRunResult");
|
|
570
715
|
|
|
@@ -573,20 +718,32 @@ var pollCiGreenlightDefaults = {
|
|
|
573
718
|
abortOnSuperseded: false,
|
|
574
719
|
maxRetries: 10,
|
|
575
720
|
pollTimeout: 120 * 60 * 1e3,
|
|
721
|
+
// 2 hours
|
|
576
722
|
retryInterval: 10 * 1e3,
|
|
723
|
+
// 10 seconds
|
|
577
724
|
runInProgressInterval: 30 * 1e3,
|
|
725
|
+
// 30 seconds
|
|
578
726
|
runUnderReviewInterval: 60 * 1e3
|
|
727
|
+
// 60 seconds
|
|
579
728
|
};
|
|
580
729
|
|
|
581
730
|
// src/lib/api/ci-greenlight.ts
|
|
582
|
-
async function fetchCiGreenlightStatus({ apiKey, serviceBase, userAgent }, {
|
|
731
|
+
async function fetchCiGreenlightStatus({ apiKey, serviceBase, userAgent }, {
|
|
732
|
+
runId
|
|
733
|
+
}, { fetch: localFetch, log }) {
|
|
583
734
|
try {
|
|
584
|
-
const resp = await localFetch(
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
735
|
+
const resp = await localFetch(
|
|
736
|
+
new URL(
|
|
737
|
+
`/api/v0/ci-greenlight/${encodeURIComponent(runId)}`,
|
|
738
|
+
serviceBase
|
|
739
|
+
),
|
|
740
|
+
{
|
|
741
|
+
headers: {
|
|
742
|
+
Authorization: `Bearer ${apiKey}`,
|
|
743
|
+
"User-Agent": userAgent
|
|
744
|
+
}
|
|
588
745
|
}
|
|
589
|
-
|
|
746
|
+
);
|
|
590
747
|
if (resp.ok) {
|
|
591
748
|
const greenlightStatus = await resp.json();
|
|
592
749
|
return {
|
|
@@ -636,14 +793,22 @@ __name(fetchCiGreenlightStatus, "fetchCiGreenlightStatus");
|
|
|
636
793
|
// src/lib/sdk/domain/pollCiGreenlight/iterator.ts
|
|
637
794
|
async function* makePollCiGreenlightStatusIterator(deps, apiConfig, { runId, ...pollConfig }) {
|
|
638
795
|
const { log } = deps;
|
|
639
|
-
const {
|
|
796
|
+
const {
|
|
797
|
+
maxRetries = pollCiGreenlightDefaults.maxRetries,
|
|
798
|
+
pollTimeout = pollCiGreenlightDefaults.pollTimeout,
|
|
799
|
+
retryInterval = pollCiGreenlightDefaults.retryInterval,
|
|
800
|
+
runInProgressInterval = pollCiGreenlightDefaults.runInProgressInterval,
|
|
801
|
+
runUnderReviewInterval = pollCiGreenlightDefaults.runUnderReviewInterval
|
|
802
|
+
} = pollConfig;
|
|
640
803
|
let retries = 0;
|
|
641
804
|
let previousStatus = void 0;
|
|
642
805
|
const startedAt = Date.now();
|
|
643
806
|
while (Date.now() - startedAt <= pollTimeout) {
|
|
644
|
-
const responseState = await fetchCiGreenlightStatus(
|
|
645
|
-
|
|
646
|
-
|
|
807
|
+
const responseState = await fetchCiGreenlightStatus(
|
|
808
|
+
apiConfig,
|
|
809
|
+
{ runId },
|
|
810
|
+
deps
|
|
811
|
+
);
|
|
647
812
|
const elapsedMs = Date.now() - startedAt;
|
|
648
813
|
if (!responseState.ok && !responseState.canRetry) {
|
|
649
814
|
yield {
|
|
@@ -690,7 +855,8 @@ async function* makePollCiGreenlightStatusIterator(deps, apiConfig, { runId, ...
|
|
|
690
855
|
}
|
|
691
856
|
const retryLabel = `${httpStatus ? ` (status ${httpStatus})` : ""}, will try again... (${retries}/${maxRetries})`;
|
|
692
857
|
if (errorType === "network") log.warn(`\u274C Network error${retryLabel}`);
|
|
693
|
-
else if (errorType === "not-found")
|
|
858
|
+
else if (errorType === "not-found")
|
|
859
|
+
log.info(`\u23F3 Run not found${retryLabel}`);
|
|
694
860
|
else if (errorType === "server") log.warn(`\u274C Server error${retryLabel}`);
|
|
695
861
|
await sleep(retryInterval);
|
|
696
862
|
continue;
|
|
@@ -727,7 +893,9 @@ async function* makePollCiGreenlightStatusIterator(deps, apiConfig, { runId, ...
|
|
|
727
893
|
await sleep(runUnderReviewInterval);
|
|
728
894
|
break;
|
|
729
895
|
default:
|
|
730
|
-
throw Error(
|
|
896
|
+
throw Error(
|
|
897
|
+
`Unexpected run stage: ${greenlightStatus}`
|
|
898
|
+
);
|
|
731
899
|
}
|
|
732
900
|
}
|
|
733
901
|
yield {
|
|
@@ -744,12 +912,19 @@ __name(makePollCiGreenlightStatusIterator, "makePollCiGreenlightStatusIterator")
|
|
|
744
912
|
function buildSuccessLogMessage(status) {
|
|
745
913
|
const { nonBlockingBugsCount, relevantRunUrl } = status;
|
|
746
914
|
const urlInfo = `See ${relevantRunUrl}`;
|
|
747
|
-
return `\u2705 Run passed and no blocking bugs found${nonBlockingBugsCount > 0 ? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(
|
|
915
|
+
return `\u2705 Run passed and no blocking bugs found${nonBlockingBugsCount > 0 ? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(
|
|
916
|
+
nonBlockingBugsCount
|
|
917
|
+
)} found` : ""}.
|
|
748
918
|
${urlInfo}`;
|
|
749
919
|
}
|
|
750
920
|
__name(buildSuccessLogMessage, "buildSuccessLogMessage");
|
|
751
921
|
function buildFailedLogMessage(status) {
|
|
752
|
-
const {
|
|
922
|
+
const {
|
|
923
|
+
blockingBugsCount,
|
|
924
|
+
nonBlockingBugsCount,
|
|
925
|
+
relevantRunWithBugsUrl,
|
|
926
|
+
reproducedBugs
|
|
927
|
+
} = status;
|
|
753
928
|
const blockingBugUrls = reproducedBugs.filter((bug) => bug.isBlocking).map((bug) => bug.applicationUrl);
|
|
754
929
|
const nonBlockingBugUrls = reproducedBugs.filter((bug) => !bug.isBlocking).map((bug) => bug.applicationUrl);
|
|
755
930
|
const blockingBugList = blockingBugUrls.map((url) => `
|
|
@@ -759,7 +934,11 @@ function buildFailedLogMessage(status) {
|
|
|
759
934
|
const bugsListInText = `${blockingBugUrls.length > 0 ? `
|
|
760
935
|
BLOCKING BUGS:${blockingBugList}` : ""}${nonBlockingBugUrls.length > 0 ? `
|
|
761
936
|
NON BLOCKING BUGS:${nonBlockingBugList}` : ""}`;
|
|
762
|
-
return `\u274C Run failed and ${blockingBugsCount} blocking bug${pluralize(
|
|
937
|
+
return `\u274C Run failed and ${blockingBugsCount} blocking bug${pluralize(
|
|
938
|
+
blockingBugsCount
|
|
939
|
+
)} found${nonBlockingBugsCount ? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(
|
|
940
|
+
nonBlockingBugsCount
|
|
941
|
+
)}` : ""}.
|
|
763
942
|
See ${relevantRunWithBugsUrl}
|
|
764
943
|
You may review the priority of certain bugs to mark these non-blocking and retry the job.
|
|
765
944
|
` + bugsListInText;
|
|
@@ -790,7 +969,9 @@ ${urlInfo}`;
|
|
|
790
969
|
case "underReview":
|
|
791
970
|
return `\u{1F575}\uFE0F Run is under review... ${urlInfo}`;
|
|
792
971
|
case "completed":
|
|
793
|
-
throw Error(
|
|
972
|
+
throw Error(
|
|
973
|
+
"buildRunStageLogMessage should not be called for completed stage"
|
|
974
|
+
);
|
|
794
975
|
default:
|
|
795
976
|
throw Error(`Unexpected run stage: ${runStage}`);
|
|
796
977
|
}
|
|
@@ -803,21 +984,27 @@ function mapIteratorAbortToGreenlightStatus(iteration, pollTimeout, deps) {
|
|
|
803
984
|
const { abortReason, httpStatus } = iteration;
|
|
804
985
|
switch (abortReason) {
|
|
805
986
|
case "4XX-client-error":
|
|
806
|
-
log.error(
|
|
987
|
+
log.error(
|
|
988
|
+
`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`
|
|
989
|
+
);
|
|
807
990
|
return {
|
|
808
991
|
abortReason,
|
|
809
992
|
httpStatus,
|
|
810
993
|
outcome: "aborted"
|
|
811
994
|
};
|
|
812
995
|
case "5XX-server-error":
|
|
813
|
-
log.error(
|
|
996
|
+
log.error(
|
|
997
|
+
`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`
|
|
998
|
+
);
|
|
814
999
|
return {
|
|
815
1000
|
abortReason,
|
|
816
1001
|
httpStatus,
|
|
817
1002
|
outcome: "aborted"
|
|
818
1003
|
};
|
|
819
1004
|
case "404-run-not-found":
|
|
820
|
-
log.error(
|
|
1005
|
+
log.error(
|
|
1006
|
+
`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`
|
|
1007
|
+
);
|
|
821
1008
|
return {
|
|
822
1009
|
abortReason,
|
|
823
1010
|
httpStatus,
|
|
@@ -845,7 +1032,9 @@ function mapIteratorAbortToGreenlightStatus(iteration, pollTimeout, deps) {
|
|
|
845
1032
|
outcome: "aborted"
|
|
846
1033
|
};
|
|
847
1034
|
case "XXX-other-http-code":
|
|
848
|
-
log.error(
|
|
1035
|
+
log.error(
|
|
1036
|
+
`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`
|
|
1037
|
+
);
|
|
849
1038
|
return {
|
|
850
1039
|
abortReason,
|
|
851
1040
|
httpStatus,
|
|
@@ -858,15 +1047,23 @@ function mapIteratorAbortToGreenlightStatus(iteration, pollTimeout, deps) {
|
|
|
858
1047
|
__name(mapIteratorAbortToGreenlightStatus, "mapIteratorAbortToGreenlightStatus");
|
|
859
1048
|
|
|
860
1049
|
// src/lib/sdk/domain/pollCiGreenlight/index.ts
|
|
861
|
-
async function pollCiGreenlightStatus(deps, apiConfig, {
|
|
1050
|
+
async function pollCiGreenlightStatus(deps, apiConfig, {
|
|
1051
|
+
onRunStageChanged = /* @__PURE__ */ __name(() => void 0, "onRunStageChanged"),
|
|
1052
|
+
runId,
|
|
1053
|
+
...pollConfig
|
|
1054
|
+
}) {
|
|
862
1055
|
const { log } = deps;
|
|
863
|
-
const {
|
|
1056
|
+
const {
|
|
1057
|
+
abortOnSuperseded = pollCiGreenlightDefaults.abortOnSuperseded,
|
|
1058
|
+
pollTimeout = pollCiGreenlightDefaults.pollTimeout
|
|
1059
|
+
} = pollConfig;
|
|
864
1060
|
const iterator = makePollCiGreenlightStatusIterator(deps, apiConfig, {
|
|
865
1061
|
runId,
|
|
866
1062
|
...pollConfig
|
|
867
1063
|
});
|
|
868
1064
|
for await (const lastPoll of iterator) {
|
|
869
|
-
if (lastPoll.isAborted)
|
|
1065
|
+
if (lastPoll.isAborted)
|
|
1066
|
+
return mapIteratorAbortToGreenlightStatus(lastPoll, pollTimeout, deps);
|
|
870
1067
|
const { previousStatus, stageChanged, status } = lastPoll;
|
|
871
1068
|
if (stageChanged) {
|
|
872
1069
|
try {
|
|
@@ -879,7 +1076,10 @@ async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged = /*
|
|
|
879
1076
|
const isSuperseded = rootRunId !== relevantRunId;
|
|
880
1077
|
const shouldAbortOnSuperseded = isSuperseded && abortOnSuperseded;
|
|
881
1078
|
if (shouldAbortOnSuperseded) {
|
|
882
|
-
const message = buildSupersededAbortLogMessage(
|
|
1079
|
+
const message = buildSupersededAbortLogMessage(
|
|
1080
|
+
rootRunUrl,
|
|
1081
|
+
relevantRunUrl
|
|
1082
|
+
);
|
|
883
1083
|
log.warn(message);
|
|
884
1084
|
return {
|
|
885
1085
|
abortReason: "superseded-run",
|
|
@@ -888,7 +1088,10 @@ async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged = /*
|
|
|
888
1088
|
};
|
|
889
1089
|
}
|
|
890
1090
|
if (isSuperseded) {
|
|
891
|
-
const message = buildSupersededContinueLogMessage(
|
|
1091
|
+
const message = buildSupersededContinueLogMessage(
|
|
1092
|
+
rootRunUrl,
|
|
1093
|
+
relevantRunUrl
|
|
1094
|
+
);
|
|
892
1095
|
log.info(message);
|
|
893
1096
|
}
|
|
894
1097
|
switch (runStage) {
|
|
@@ -928,10 +1131,19 @@ async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged = /*
|
|
|
928
1131
|
__name(pollCiGreenlightStatus, "pollCiGreenlightStatus");
|
|
929
1132
|
|
|
930
1133
|
// src/lib/sdk/index.ts
|
|
931
|
-
function makeQaWolfSdk({
|
|
1134
|
+
function makeQaWolfSdk({
|
|
1135
|
+
apiKey,
|
|
1136
|
+
serviceBase = defaultServiceBase,
|
|
1137
|
+
userAgent = defaultUserAgent
|
|
1138
|
+
}, {
|
|
1139
|
+
fetch = defaultFetch,
|
|
1140
|
+
log = defaultLogDriver
|
|
1141
|
+
} = {}) {
|
|
932
1142
|
if (typeof fetch !== "function") {
|
|
933
|
-
throw Error(
|
|
934
|
-
|
|
1143
|
+
throw Error(
|
|
1144
|
+
`QA Wolf CI-SDK requires fetch to be defined. Make sure you are using NodeJS 18+, OR pass a fetch polyfill to the makeQaWolfSdk function.
|
|
1145
|
+
We recommend 'undici' package for that purpose. See the Requirement section of our README for more guidance.`
|
|
1146
|
+
);
|
|
935
1147
|
}
|
|
936
1148
|
const deps = {
|
|
937
1149
|
// Versions of fetch may have different default timeouts. For consistency, we explicitly set it to 2 minutes here.
|
|
@@ -940,22 +1152,27 @@ We recommend 'undici' package for that purpose. See the Requirement section of o
|
|
|
940
1152
|
fetch: buildFetchWithTimeout(fetch, 12e4),
|
|
941
1153
|
log
|
|
942
1154
|
};
|
|
943
|
-
const apiConfig = {
|
|
944
|
-
apiKey,
|
|
945
|
-
serviceBase,
|
|
946
|
-
userAgent
|
|
947
|
-
};
|
|
1155
|
+
const apiConfig = { apiKey, serviceBase, userAgent };
|
|
948
1156
|
return {
|
|
949
1157
|
attemptNotifyDeploy: attemptNotifyDeploy.bind(null, deps, apiConfig),
|
|
950
|
-
generateSignedUrlForRunInputsExecutablesStorage: generateSignedUrlForRunInputsExecutablesStorage.bind(
|
|
1158
|
+
generateSignedUrlForRunInputsExecutablesStorage: generateSignedUrlForRunInputsExecutablesStorage.bind(
|
|
1159
|
+
null,
|
|
1160
|
+
deps,
|
|
1161
|
+
apiConfig
|
|
1162
|
+
),
|
|
951
1163
|
generateSignedUrlForTempTeamStorage: generateSignedUrlForTempTeamStorage.bind(null, deps, apiConfig),
|
|
952
|
-
makePollCiGreenlightStatusIterator: makePollCiGreenlightStatusIterator.bind(
|
|
1164
|
+
makePollCiGreenlightStatusIterator: makePollCiGreenlightStatusIterator.bind(
|
|
1165
|
+
null,
|
|
1166
|
+
deps,
|
|
1167
|
+
apiConfig
|
|
1168
|
+
),
|
|
953
1169
|
notifyTerminatedEphemeralEnvironment: notifyTerminatedEphemeralEnvironment.bind(null, deps, apiConfig),
|
|
954
1170
|
pollCiGreenlightStatus: pollCiGreenlightStatus.bind(null, deps, apiConfig)
|
|
955
1171
|
};
|
|
956
1172
|
}
|
|
957
1173
|
__name(makeQaWolfSdk, "makeQaWolfSdk");
|
|
958
|
-
|
|
959
|
-
exports
|
|
1174
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1175
|
+
0 && (module.exports = {
|
|
1176
|
+
makeQaWolfSdk
|
|
1177
|
+
});
|
|
960
1178
|
//# sourceMappingURL=index.cjs.map
|
|
961
|
-
//# sourceMappingURL=index.cjs.map
|