@qawolf/ci-sdk 2.2.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 +13 -0
- package/dist/index.cjs +389 -196
- package/dist/index.cjs.map +7 -1
- package/dist/index.d.ts +4 -557
- package/dist/index.js +364 -194
- 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 +8 -7
- package/dist/index.d.cts +0 -557
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,35 +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
|
-
"Content-Type": "application/json",
|
|
289
|
-
"User-Agent": apiConfig.userAgent
|
|
290
|
-
},
|
|
291
|
-
method: "POST",
|
|
292
|
-
// Override default timeout to 5 minutes. This gives extra room
|
|
293
|
-
// for both (1) waiting for reconciliation (2) creating the run.
|
|
294
|
-
signal: AbortSignal.timeout(5 * 60 * 1e3)
|
|
295
|
-
});
|
|
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
|
+
);
|
|
296
385
|
if (!response.ok) return handleErrorResponse(response, log);
|
|
297
386
|
bodyText = await response.text();
|
|
298
387
|
} catch {
|
|
@@ -311,7 +400,10 @@ async function attemptNotifyDeploy(deps, apiConfig, config) {
|
|
|
311
400
|
}
|
|
312
401
|
const wire = parseDeploySuccessWireResponse(rawBody);
|
|
313
402
|
if (wire === "invalid") {
|
|
314
|
-
return abortInvalidResponseBody(
|
|
403
|
+
return abortInvalidResponseBody(
|
|
404
|
+
log,
|
|
405
|
+
"the response body did not match the expected shape"
|
|
406
|
+
);
|
|
315
407
|
}
|
|
316
408
|
const data = mapDeploySuccessResponse(wire);
|
|
317
409
|
return handleSuccessResponse(data, log);
|
|
@@ -352,10 +444,17 @@ var signedUrlPaths = {
|
|
|
352
444
|
runInputsExecutables: "/api/v0/run-inputs-executables-signed-urls",
|
|
353
445
|
teamStorage: "/api/v0/team-storage-signed-url"
|
|
354
446
|
};
|
|
355
|
-
function buildSignedUrl({
|
|
447
|
+
function buildSignedUrl({
|
|
448
|
+
destinationFilePath,
|
|
449
|
+
endpoint,
|
|
450
|
+
serviceBase,
|
|
451
|
+
workspaceId
|
|
452
|
+
}) {
|
|
356
453
|
const url = new URL(signedUrlPaths[endpoint], serviceBase);
|
|
357
|
-
if (destinationFilePath !== void 0)
|
|
358
|
-
|
|
454
|
+
if (destinationFilePath !== void 0)
|
|
455
|
+
url.searchParams.set("file", destinationFilePath);
|
|
456
|
+
if (workspaceId !== void 0)
|
|
457
|
+
url.searchParams.set("workspaceId", workspaceId);
|
|
359
458
|
return url;
|
|
360
459
|
}
|
|
361
460
|
__name(buildSignedUrl, "buildSignedUrl");
|
|
@@ -363,19 +462,22 @@ __name(buildSignedUrl, "buildSignedUrl");
|
|
|
363
462
|
// src/lib/api/generate-signed-url-for-run-inputs-executables.ts
|
|
364
463
|
async function callGenerateSignedUrlForRunInputsExecutablesStorage({ apiKey, serviceBase, userAgent }, { destinationFilePath, workspaceId }, { fetch: localFetch, log }) {
|
|
365
464
|
try {
|
|
366
|
-
const response = await localFetch(
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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
|
+
);
|
|
379
481
|
if (response.status === 200) {
|
|
380
482
|
const json = await response.json();
|
|
381
483
|
return {
|
|
@@ -416,18 +518,28 @@ async function generateSignedUrlForRunInputsExecutablesStorage(deps, apiConfig,
|
|
|
416
518
|
success: false
|
|
417
519
|
};
|
|
418
520
|
}
|
|
419
|
-
const responseState = await callGenerateSignedUrlForRunInputsExecutablesStorage(
|
|
521
|
+
const responseState = await callGenerateSignedUrlForRunInputsExecutablesStorage(
|
|
522
|
+
apiConfig,
|
|
523
|
+
config,
|
|
524
|
+
deps
|
|
525
|
+
);
|
|
420
526
|
if (!responseState.success) {
|
|
421
527
|
let abortReason = "XXX-other-http-code";
|
|
422
528
|
if (responseState.httpStatus >= 500) {
|
|
423
529
|
abortReason = "5XX-server-error";
|
|
424
|
-
log.error(
|
|
530
|
+
log.error(
|
|
531
|
+
`\u{1F6AB} Unrecoverable error (status ${responseState.httpStatus}) when generating signed upload url: aborting.`
|
|
532
|
+
);
|
|
425
533
|
} else {
|
|
426
534
|
if (responseState.httpStatus === 400) abortReason = "400-invalid-request";
|
|
427
|
-
else if (responseState.httpStatus === 401)
|
|
535
|
+
else if (responseState.httpStatus === 401)
|
|
536
|
+
abortReason = "401-invalid-credentials";
|
|
428
537
|
else if (responseState.httpStatus === 403) abortReason = "403-forbidden";
|
|
429
|
-
else if (responseState.httpStatus === 0)
|
|
430
|
-
|
|
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
|
+
);
|
|
431
543
|
}
|
|
432
544
|
return {
|
|
433
545
|
abortReason,
|
|
@@ -448,19 +560,22 @@ __name(generateSignedUrlForRunInputsExecutablesStorage, "generateSignedUrlForRun
|
|
|
448
560
|
// src/lib/api/generate-signed-url-for-team-storage.ts
|
|
449
561
|
async function callGenerateSignedUrlForTempTeamStorage({ apiKey, serviceBase, userAgent }, { destinationFilePath, workspaceId }, { fetch: localFetch, log }) {
|
|
450
562
|
try {
|
|
451
|
-
const response = await localFetch(
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
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
|
+
);
|
|
464
579
|
if (response.status === 200) {
|
|
465
580
|
const json = await response.json();
|
|
466
581
|
return {
|
|
@@ -501,18 +616,28 @@ async function generateSignedUrlForTempTeamStorage(deps, apiConfig, config) {
|
|
|
501
616
|
success: false
|
|
502
617
|
};
|
|
503
618
|
}
|
|
504
|
-
const responseState = await callGenerateSignedUrlForTempTeamStorage(
|
|
619
|
+
const responseState = await callGenerateSignedUrlForTempTeamStorage(
|
|
620
|
+
apiConfig,
|
|
621
|
+
config,
|
|
622
|
+
deps
|
|
623
|
+
);
|
|
505
624
|
if (!responseState.success) {
|
|
506
625
|
let abortReason = "XXX-other-http-code";
|
|
507
626
|
if (responseState.httpStatus >= 500) {
|
|
508
627
|
abortReason = "5XX-server-error";
|
|
509
|
-
log.error(
|
|
628
|
+
log.error(
|
|
629
|
+
`\u{1F6AB} Unrecoverable error (status ${responseState.httpStatus}) when generating signed upload url: aborting.`
|
|
630
|
+
);
|
|
510
631
|
} else {
|
|
511
632
|
if (responseState.httpStatus === 400) abortReason = "400-invalid-request";
|
|
512
|
-
else if (responseState.httpStatus === 401)
|
|
633
|
+
else if (responseState.httpStatus === 401)
|
|
634
|
+
abortReason = "401-invalid-credentials";
|
|
513
635
|
else if (responseState.httpStatus === 403) abortReason = "403-forbidden";
|
|
514
|
-
else if (responseState.httpStatus === 0)
|
|
515
|
-
|
|
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
|
+
);
|
|
516
641
|
}
|
|
517
642
|
return {
|
|
518
643
|
abortReason,
|
|
@@ -534,21 +659,22 @@ __name(generateSignedUrlForTempTeamStorage, "generateSignedUrlForTempTeamStorage
|
|
|
534
659
|
var notifyTerminatedEphemeralEnvironment = /* @__PURE__ */ __name(async (deps, apiConfig, config) => {
|
|
535
660
|
const { fetch: localFetch, log } = deps;
|
|
536
661
|
try {
|
|
537
|
-
const response = await localFetch(
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
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
|
+
);
|
|
546
674
|
if (!response.ok) return handleErrorResponse2(response, log);
|
|
547
|
-
const { environmentId } = await response.json();
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
outcome: "success"
|
|
551
|
-
};
|
|
675
|
+
const { environmentId, warning } = await response.json();
|
|
676
|
+
if (warning) log.warn(`\u26A0\uFE0F ${warning}`);
|
|
677
|
+
return { environmentId, outcome: "success" };
|
|
552
678
|
} catch {
|
|
553
679
|
log.error(`\u{1F6AB} Network error from terminate_preview_environment, aborting.`);
|
|
554
680
|
return {
|
|
@@ -581,14 +707,9 @@ __name(handleErrorResponse2, "handleErrorResponse");
|
|
|
581
707
|
|
|
582
708
|
// src/lib/sdk/domain/pollCiGreenlight/buildCompletedRunResult.ts
|
|
583
709
|
function buildCompletedRunResult(status) {
|
|
584
|
-
if (status.greenlight)
|
|
585
|
-
greenlightStatus: status,
|
|
586
|
-
|
|
587
|
-
};
|
|
588
|
-
else return {
|
|
589
|
-
greenlightStatus: status,
|
|
590
|
-
outcome: "failed"
|
|
591
|
-
};
|
|
710
|
+
if (status.greenlight)
|
|
711
|
+
return { greenlightStatus: status, outcome: "success" };
|
|
712
|
+
else return { greenlightStatus: status, outcome: "failed" };
|
|
592
713
|
}
|
|
593
714
|
__name(buildCompletedRunResult, "buildCompletedRunResult");
|
|
594
715
|
|
|
@@ -597,20 +718,32 @@ var pollCiGreenlightDefaults = {
|
|
|
597
718
|
abortOnSuperseded: false,
|
|
598
719
|
maxRetries: 10,
|
|
599
720
|
pollTimeout: 120 * 60 * 1e3,
|
|
721
|
+
// 2 hours
|
|
600
722
|
retryInterval: 10 * 1e3,
|
|
723
|
+
// 10 seconds
|
|
601
724
|
runInProgressInterval: 30 * 1e3,
|
|
725
|
+
// 30 seconds
|
|
602
726
|
runUnderReviewInterval: 60 * 1e3
|
|
727
|
+
// 60 seconds
|
|
603
728
|
};
|
|
604
729
|
|
|
605
730
|
// src/lib/api/ci-greenlight.ts
|
|
606
|
-
async function fetchCiGreenlightStatus({ apiKey, serviceBase, userAgent }, {
|
|
731
|
+
async function fetchCiGreenlightStatus({ apiKey, serviceBase, userAgent }, {
|
|
732
|
+
runId
|
|
733
|
+
}, { fetch: localFetch, log }) {
|
|
607
734
|
try {
|
|
608
|
-
const resp = await localFetch(
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
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
|
+
}
|
|
612
745
|
}
|
|
613
|
-
|
|
746
|
+
);
|
|
614
747
|
if (resp.ok) {
|
|
615
748
|
const greenlightStatus = await resp.json();
|
|
616
749
|
return {
|
|
@@ -660,14 +793,22 @@ __name(fetchCiGreenlightStatus, "fetchCiGreenlightStatus");
|
|
|
660
793
|
// src/lib/sdk/domain/pollCiGreenlight/iterator.ts
|
|
661
794
|
async function* makePollCiGreenlightStatusIterator(deps, apiConfig, { runId, ...pollConfig }) {
|
|
662
795
|
const { log } = deps;
|
|
663
|
-
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;
|
|
664
803
|
let retries = 0;
|
|
665
804
|
let previousStatus = void 0;
|
|
666
805
|
const startedAt = Date.now();
|
|
667
806
|
while (Date.now() - startedAt <= pollTimeout) {
|
|
668
|
-
const responseState = await fetchCiGreenlightStatus(
|
|
669
|
-
|
|
670
|
-
|
|
807
|
+
const responseState = await fetchCiGreenlightStatus(
|
|
808
|
+
apiConfig,
|
|
809
|
+
{ runId },
|
|
810
|
+
deps
|
|
811
|
+
);
|
|
671
812
|
const elapsedMs = Date.now() - startedAt;
|
|
672
813
|
if (!responseState.ok && !responseState.canRetry) {
|
|
673
814
|
yield {
|
|
@@ -714,7 +855,8 @@ async function* makePollCiGreenlightStatusIterator(deps, apiConfig, { runId, ...
|
|
|
714
855
|
}
|
|
715
856
|
const retryLabel = `${httpStatus ? ` (status ${httpStatus})` : ""}, will try again... (${retries}/${maxRetries})`;
|
|
716
857
|
if (errorType === "network") log.warn(`\u274C Network error${retryLabel}`);
|
|
717
|
-
else if (errorType === "not-found")
|
|
858
|
+
else if (errorType === "not-found")
|
|
859
|
+
log.info(`\u23F3 Run not found${retryLabel}`);
|
|
718
860
|
else if (errorType === "server") log.warn(`\u274C Server error${retryLabel}`);
|
|
719
861
|
await sleep(retryInterval);
|
|
720
862
|
continue;
|
|
@@ -751,7 +893,9 @@ async function* makePollCiGreenlightStatusIterator(deps, apiConfig, { runId, ...
|
|
|
751
893
|
await sleep(runUnderReviewInterval);
|
|
752
894
|
break;
|
|
753
895
|
default:
|
|
754
|
-
throw Error(
|
|
896
|
+
throw Error(
|
|
897
|
+
`Unexpected run stage: ${greenlightStatus}`
|
|
898
|
+
);
|
|
755
899
|
}
|
|
756
900
|
}
|
|
757
901
|
yield {
|
|
@@ -768,12 +912,19 @@ __name(makePollCiGreenlightStatusIterator, "makePollCiGreenlightStatusIterator")
|
|
|
768
912
|
function buildSuccessLogMessage(status) {
|
|
769
913
|
const { nonBlockingBugsCount, relevantRunUrl } = status;
|
|
770
914
|
const urlInfo = `See ${relevantRunUrl}`;
|
|
771
|
-
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` : ""}.
|
|
772
918
|
${urlInfo}`;
|
|
773
919
|
}
|
|
774
920
|
__name(buildSuccessLogMessage, "buildSuccessLogMessage");
|
|
775
921
|
function buildFailedLogMessage(status) {
|
|
776
|
-
const {
|
|
922
|
+
const {
|
|
923
|
+
blockingBugsCount,
|
|
924
|
+
nonBlockingBugsCount,
|
|
925
|
+
relevantRunWithBugsUrl,
|
|
926
|
+
reproducedBugs
|
|
927
|
+
} = status;
|
|
777
928
|
const blockingBugUrls = reproducedBugs.filter((bug) => bug.isBlocking).map((bug) => bug.applicationUrl);
|
|
778
929
|
const nonBlockingBugUrls = reproducedBugs.filter((bug) => !bug.isBlocking).map((bug) => bug.applicationUrl);
|
|
779
930
|
const blockingBugList = blockingBugUrls.map((url) => `
|
|
@@ -783,7 +934,11 @@ function buildFailedLogMessage(status) {
|
|
|
783
934
|
const bugsListInText = `${blockingBugUrls.length > 0 ? `
|
|
784
935
|
BLOCKING BUGS:${blockingBugList}` : ""}${nonBlockingBugUrls.length > 0 ? `
|
|
785
936
|
NON BLOCKING BUGS:${nonBlockingBugList}` : ""}`;
|
|
786
|
-
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
|
+
)}` : ""}.
|
|
787
942
|
See ${relevantRunWithBugsUrl}
|
|
788
943
|
You may review the priority of certain bugs to mark these non-blocking and retry the job.
|
|
789
944
|
` + bugsListInText;
|
|
@@ -814,7 +969,9 @@ ${urlInfo}`;
|
|
|
814
969
|
case "underReview":
|
|
815
970
|
return `\u{1F575}\uFE0F Run is under review... ${urlInfo}`;
|
|
816
971
|
case "completed":
|
|
817
|
-
throw Error(
|
|
972
|
+
throw Error(
|
|
973
|
+
"buildRunStageLogMessage should not be called for completed stage"
|
|
974
|
+
);
|
|
818
975
|
default:
|
|
819
976
|
throw Error(`Unexpected run stage: ${runStage}`);
|
|
820
977
|
}
|
|
@@ -827,21 +984,27 @@ function mapIteratorAbortToGreenlightStatus(iteration, pollTimeout, deps) {
|
|
|
827
984
|
const { abortReason, httpStatus } = iteration;
|
|
828
985
|
switch (abortReason) {
|
|
829
986
|
case "4XX-client-error":
|
|
830
|
-
log.error(
|
|
987
|
+
log.error(
|
|
988
|
+
`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`
|
|
989
|
+
);
|
|
831
990
|
return {
|
|
832
991
|
abortReason,
|
|
833
992
|
httpStatus,
|
|
834
993
|
outcome: "aborted"
|
|
835
994
|
};
|
|
836
995
|
case "5XX-server-error":
|
|
837
|
-
log.error(
|
|
996
|
+
log.error(
|
|
997
|
+
`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`
|
|
998
|
+
);
|
|
838
999
|
return {
|
|
839
1000
|
abortReason,
|
|
840
1001
|
httpStatus,
|
|
841
1002
|
outcome: "aborted"
|
|
842
1003
|
};
|
|
843
1004
|
case "404-run-not-found":
|
|
844
|
-
log.error(
|
|
1005
|
+
log.error(
|
|
1006
|
+
`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`
|
|
1007
|
+
);
|
|
845
1008
|
return {
|
|
846
1009
|
abortReason,
|
|
847
1010
|
httpStatus,
|
|
@@ -869,7 +1032,9 @@ function mapIteratorAbortToGreenlightStatus(iteration, pollTimeout, deps) {
|
|
|
869
1032
|
outcome: "aborted"
|
|
870
1033
|
};
|
|
871
1034
|
case "XXX-other-http-code":
|
|
872
|
-
log.error(
|
|
1035
|
+
log.error(
|
|
1036
|
+
`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`
|
|
1037
|
+
);
|
|
873
1038
|
return {
|
|
874
1039
|
abortReason,
|
|
875
1040
|
httpStatus,
|
|
@@ -882,15 +1047,23 @@ function mapIteratorAbortToGreenlightStatus(iteration, pollTimeout, deps) {
|
|
|
882
1047
|
__name(mapIteratorAbortToGreenlightStatus, "mapIteratorAbortToGreenlightStatus");
|
|
883
1048
|
|
|
884
1049
|
// src/lib/sdk/domain/pollCiGreenlight/index.ts
|
|
885
|
-
async function pollCiGreenlightStatus(deps, apiConfig, {
|
|
1050
|
+
async function pollCiGreenlightStatus(deps, apiConfig, {
|
|
1051
|
+
onRunStageChanged = /* @__PURE__ */ __name(() => void 0, "onRunStageChanged"),
|
|
1052
|
+
runId,
|
|
1053
|
+
...pollConfig
|
|
1054
|
+
}) {
|
|
886
1055
|
const { log } = deps;
|
|
887
|
-
const {
|
|
1056
|
+
const {
|
|
1057
|
+
abortOnSuperseded = pollCiGreenlightDefaults.abortOnSuperseded,
|
|
1058
|
+
pollTimeout = pollCiGreenlightDefaults.pollTimeout
|
|
1059
|
+
} = pollConfig;
|
|
888
1060
|
const iterator = makePollCiGreenlightStatusIterator(deps, apiConfig, {
|
|
889
1061
|
runId,
|
|
890
1062
|
...pollConfig
|
|
891
1063
|
});
|
|
892
1064
|
for await (const lastPoll of iterator) {
|
|
893
|
-
if (lastPoll.isAborted)
|
|
1065
|
+
if (lastPoll.isAborted)
|
|
1066
|
+
return mapIteratorAbortToGreenlightStatus(lastPoll, pollTimeout, deps);
|
|
894
1067
|
const { previousStatus, stageChanged, status } = lastPoll;
|
|
895
1068
|
if (stageChanged) {
|
|
896
1069
|
try {
|
|
@@ -903,7 +1076,10 @@ async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged = /*
|
|
|
903
1076
|
const isSuperseded = rootRunId !== relevantRunId;
|
|
904
1077
|
const shouldAbortOnSuperseded = isSuperseded && abortOnSuperseded;
|
|
905
1078
|
if (shouldAbortOnSuperseded) {
|
|
906
|
-
const message = buildSupersededAbortLogMessage(
|
|
1079
|
+
const message = buildSupersededAbortLogMessage(
|
|
1080
|
+
rootRunUrl,
|
|
1081
|
+
relevantRunUrl
|
|
1082
|
+
);
|
|
907
1083
|
log.warn(message);
|
|
908
1084
|
return {
|
|
909
1085
|
abortReason: "superseded-run",
|
|
@@ -912,7 +1088,10 @@ async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged = /*
|
|
|
912
1088
|
};
|
|
913
1089
|
}
|
|
914
1090
|
if (isSuperseded) {
|
|
915
|
-
const message = buildSupersededContinueLogMessage(
|
|
1091
|
+
const message = buildSupersededContinueLogMessage(
|
|
1092
|
+
rootRunUrl,
|
|
1093
|
+
relevantRunUrl
|
|
1094
|
+
);
|
|
916
1095
|
log.info(message);
|
|
917
1096
|
}
|
|
918
1097
|
switch (runStage) {
|
|
@@ -952,10 +1131,19 @@ async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged = /*
|
|
|
952
1131
|
__name(pollCiGreenlightStatus, "pollCiGreenlightStatus");
|
|
953
1132
|
|
|
954
1133
|
// src/lib/sdk/index.ts
|
|
955
|
-
function makeQaWolfSdk({
|
|
1134
|
+
function makeQaWolfSdk({
|
|
1135
|
+
apiKey,
|
|
1136
|
+
serviceBase = defaultServiceBase,
|
|
1137
|
+
userAgent = defaultUserAgent
|
|
1138
|
+
}, {
|
|
1139
|
+
fetch = defaultFetch,
|
|
1140
|
+
log = defaultLogDriver
|
|
1141
|
+
} = {}) {
|
|
956
1142
|
if (typeof fetch !== "function") {
|
|
957
|
-
throw Error(
|
|
958
|
-
|
|
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
|
+
);
|
|
959
1147
|
}
|
|
960
1148
|
const deps = {
|
|
961
1149
|
// Versions of fetch may have different default timeouts. For consistency, we explicitly set it to 2 minutes here.
|
|
@@ -964,22 +1152,27 @@ We recommend 'undici' package for that purpose. See the Requirement section of o
|
|
|
964
1152
|
fetch: buildFetchWithTimeout(fetch, 12e4),
|
|
965
1153
|
log
|
|
966
1154
|
};
|
|
967
|
-
const apiConfig = {
|
|
968
|
-
apiKey,
|
|
969
|
-
serviceBase,
|
|
970
|
-
userAgent
|
|
971
|
-
};
|
|
1155
|
+
const apiConfig = { apiKey, serviceBase, userAgent };
|
|
972
1156
|
return {
|
|
973
1157
|
attemptNotifyDeploy: attemptNotifyDeploy.bind(null, deps, apiConfig),
|
|
974
|
-
generateSignedUrlForRunInputsExecutablesStorage: generateSignedUrlForRunInputsExecutablesStorage.bind(
|
|
1158
|
+
generateSignedUrlForRunInputsExecutablesStorage: generateSignedUrlForRunInputsExecutablesStorage.bind(
|
|
1159
|
+
null,
|
|
1160
|
+
deps,
|
|
1161
|
+
apiConfig
|
|
1162
|
+
),
|
|
975
1163
|
generateSignedUrlForTempTeamStorage: generateSignedUrlForTempTeamStorage.bind(null, deps, apiConfig),
|
|
976
|
-
makePollCiGreenlightStatusIterator: makePollCiGreenlightStatusIterator.bind(
|
|
1164
|
+
makePollCiGreenlightStatusIterator: makePollCiGreenlightStatusIterator.bind(
|
|
1165
|
+
null,
|
|
1166
|
+
deps,
|
|
1167
|
+
apiConfig
|
|
1168
|
+
),
|
|
977
1169
|
notifyTerminatedEphemeralEnvironment: notifyTerminatedEphemeralEnvironment.bind(null, deps, apiConfig),
|
|
978
1170
|
pollCiGreenlightStatus: pollCiGreenlightStatus.bind(null, deps, apiConfig)
|
|
979
1171
|
};
|
|
980
1172
|
}
|
|
981
1173
|
__name(makeQaWolfSdk, "makeQaWolfSdk");
|
|
982
|
-
|
|
983
|
-
exports
|
|
1174
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1175
|
+
0 && (module.exports = {
|
|
1176
|
+
makeQaWolfSdk
|
|
1177
|
+
});
|
|
984
1178
|
//# sourceMappingURL=index.cjs.map
|
|
985
|
-
//# sourceMappingURL=index.cjs.map
|