@qawolf/ci-sdk 2.2.0 → 2.6.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 +24 -0
- package/dist/index.cjs +396 -202
- package/dist/index.cjs.map +7 -1
- package/dist/index.d.ts +4 -557
- package/dist/index.js +371 -200
- 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 +27 -0
- package/dist/lib/sdk/domain/pollCiGreenlight/mapIteratorAbortToGreenlightStatus.d.ts +7 -0
- package/dist/lib/sdk/domain/pollCiGreenlight/types.d.ts +156 -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.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* Built with @qawolf/platform-builder@1.2.2 */
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
4
|
|
|
@@ -12,10 +13,7 @@ function pluralize(count) {
|
|
|
12
13
|
__name(pluralize, "pluralize");
|
|
13
14
|
var buildFetchWithTimeout = /* @__PURE__ */ __name((fetch, defaultTimeoutMs) => async (...args) => {
|
|
14
15
|
const signal = args[1]?.signal ?? AbortSignal.timeout(defaultTimeoutMs);
|
|
15
|
-
return fetch(args[0], {
|
|
16
|
-
...args[1],
|
|
17
|
-
signal
|
|
18
|
-
});
|
|
16
|
+
return fetch(args[0], { ...args[1], signal });
|
|
19
17
|
}, "buildFetchWithTimeout");
|
|
20
18
|
|
|
21
19
|
// src/lib/sdk/defaults/fetch.ts
|
|
@@ -39,13 +37,61 @@ var defaultServiceBase = "https://app.qawolf.com/";
|
|
|
39
37
|
|
|
40
38
|
// package.json
|
|
41
39
|
var package_default = {
|
|
42
|
-
|
|
40
|
+
name: "@qawolf/ci-sdk",
|
|
41
|
+
version: "2.6.0",
|
|
42
|
+
private: false,
|
|
43
|
+
description: "A simple SDK for interacting with QAWolf in CI scripts.",
|
|
44
|
+
keywords: [],
|
|
45
|
+
license: "MIT",
|
|
46
|
+
author: "Jules Sam. Randolph<jules@qawolf.com>",
|
|
47
|
+
files: [
|
|
48
|
+
"/dist",
|
|
49
|
+
"/README.md"
|
|
50
|
+
],
|
|
51
|
+
type: "module",
|
|
52
|
+
sideEffects: false,
|
|
53
|
+
exports: {
|
|
54
|
+
".": {
|
|
55
|
+
types: "./dist/index.d.ts",
|
|
56
|
+
require: "./dist/index.cjs",
|
|
57
|
+
import: "./dist/index.js",
|
|
58
|
+
default: "./dist/index.js"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
scripts: {
|
|
62
|
+
build: "platform-builder --config platformBuilder.config.ts --config platformBuilder.cjs.config.ts",
|
|
63
|
+
"lint:ci": "npm run lint:first-half; FIRST_HALF_EXIT=$?; npm run lint:second-half && exit $FIRST_HALF_EXIT",
|
|
64
|
+
"lint:dev": "npm run lint:first-half",
|
|
65
|
+
"lint:first-half": "eslint . --fix --quiet && oxfmt --write .",
|
|
66
|
+
"lint:second-half": "dpdm --exit-code circular:1 --no-tree --no-warning --transform --include='.*' --exclude='/(dist|node_modules)/' '**/*'",
|
|
67
|
+
prepublishOnly: "nx run ci-sdk:build",
|
|
68
|
+
test: 'NODE_OPTIONS="--experimental-vm-modules" NODE_NO_WARNINGS=1 jest',
|
|
69
|
+
"tsc:check": "tsc --noEmit"
|
|
70
|
+
},
|
|
71
|
+
dependencies: {
|
|
72
|
+
"@qawolf/ci-utils": "^1.1.2",
|
|
73
|
+
"@sinonjs/fake-timers": "^10.3.0",
|
|
74
|
+
tslib: "^2.6.2"
|
|
75
|
+
},
|
|
76
|
+
devDependencies: {
|
|
77
|
+
"@qawolf/platform-builder": "^1.2.2",
|
|
78
|
+
tsx: "^4.19.4",
|
|
79
|
+
typescript: "^5.9.3"
|
|
80
|
+
},
|
|
81
|
+
engines: {
|
|
82
|
+
node: ">=20"
|
|
83
|
+
}
|
|
84
|
+
};
|
|
43
85
|
|
|
44
86
|
// src/lib/sdk/defaults/userAgent.ts
|
|
45
87
|
var defaultUserAgent = `ci-sdk/${package_default.version}`;
|
|
46
88
|
|
|
47
89
|
// src/lib/api/log.ts
|
|
48
|
-
async function logFetchError({
|
|
90
|
+
async function logFetchError({
|
|
91
|
+
log,
|
|
92
|
+
methodName,
|
|
93
|
+
response
|
|
94
|
+
}) {
|
|
49
95
|
if (response.ok) return;
|
|
50
96
|
const { eventId, failureMessage } = await (async () => {
|
|
51
97
|
try {
|
|
@@ -70,7 +116,9 @@ async function logFetchError({ log, methodName, response }) {
|
|
|
70
116
|
const eventIdSuffix = eventId ? ` (Event ID: ${eventId})` : "";
|
|
71
117
|
const messageSuffix = failureMessage ? `: ${failureMessage}` : "";
|
|
72
118
|
const statusText = response.status >= 500 ? "Server Error" : response.statusText || "Unknown Error";
|
|
73
|
-
log.error(
|
|
119
|
+
log.error(
|
|
120
|
+
`\u274C [${methodName}] ${response.status} ${statusText}${eventIdSuffix}${messageSuffix}`
|
|
121
|
+
);
|
|
74
122
|
}
|
|
75
123
|
__name(logFetchError, "logFetchError");
|
|
76
124
|
|
|
@@ -80,6 +128,7 @@ async function handleSuccessResponse(data, log) {
|
|
|
80
128
|
const skippedTriggers = data.skippedTriggers ?? [];
|
|
81
129
|
const skippedDeployment = data.skippedDeployment;
|
|
82
130
|
const isPreviewDeployment = environment && !environment.isStatic;
|
|
131
|
+
if (data.warning) log.warn(`\u26A0\uFE0F ${data.warning}`);
|
|
83
132
|
if (environment) {
|
|
84
133
|
const logPrefix = environment.isStatic ? "Static environment" : "Preview environment";
|
|
85
134
|
log.info(`${logPrefix}: ${environment.alias} (id: ${environment.id})`);
|
|
@@ -87,13 +136,13 @@ async function handleSuccessResponse(data, log) {
|
|
|
87
136
|
if (results.length === 0) {
|
|
88
137
|
const skipMessages = [
|
|
89
138
|
...skippedTriggers.map((trigger) => trigger.message),
|
|
90
|
-
...skippedDeployment ? [
|
|
91
|
-
skippedDeployment.message
|
|
92
|
-
] : []
|
|
139
|
+
...skippedDeployment ? [skippedDeployment.message] : []
|
|
93
140
|
];
|
|
94
141
|
const skipDetail = skipMessages.length > 0 ? ` ${skipMessages.join(" ")}` : "";
|
|
95
142
|
if (isPreviewDeployment) {
|
|
96
|
-
log.info(
|
|
143
|
+
log.info(
|
|
144
|
+
`\u2705 Deployment notification was successful. No run was created for this deployment.${skipDetail}`
|
|
145
|
+
);
|
|
97
146
|
return {
|
|
98
147
|
environmentId: environment.id,
|
|
99
148
|
outcome: "success",
|
|
@@ -108,7 +157,9 @@ async function handleSuccessResponse(data, log) {
|
|
|
108
157
|
skippedTriggers
|
|
109
158
|
};
|
|
110
159
|
}
|
|
111
|
-
log.warn(
|
|
160
|
+
log.warn(
|
|
161
|
+
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.`
|
|
162
|
+
);
|
|
112
163
|
return {
|
|
113
164
|
outcome: "skipped",
|
|
114
165
|
skippedDeployment
|
|
@@ -116,45 +167,43 @@ async function handleSuccessResponse(data, log) {
|
|
|
116
167
|
}
|
|
117
168
|
if (!environment) {
|
|
118
169
|
log.error(`\u{1F6AB} No environment matched the request. Please contact support.`);
|
|
119
|
-
return {
|
|
120
|
-
failReason: "no-environment",
|
|
121
|
-
outcome: "failed"
|
|
122
|
-
};
|
|
170
|
+
return { failReason: "no-environment", outcome: "failed" };
|
|
123
171
|
}
|
|
124
172
|
const unrecognizedResult = results.find((result) => "unrecognized" in result);
|
|
125
173
|
if (unrecognizedResult) {
|
|
126
|
-
log.error(
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
};
|
|
174
|
+
log.error(
|
|
175
|
+
`\u{1F6AB} The deployment response contained an unrecognized result. Please upgrade @qawolf/ci-sdk.`
|
|
176
|
+
);
|
|
177
|
+
return { failReason: "unknown-result", outcome: "failed" };
|
|
131
178
|
}
|
|
132
179
|
const failedTrigger = results.find((result) => "failureReason" in result);
|
|
133
180
|
if (failedTrigger) {
|
|
134
|
-
log.error(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
};
|
|
181
|
+
log.error(
|
|
182
|
+
`\u{1F6AB} Run could not be created. Reason: "${failedTrigger.failureMessage ?? failedTrigger.failureReason}". Please contact support.`
|
|
183
|
+
);
|
|
184
|
+
return { failReason: "run-could-not-be-created", outcome: "failed" };
|
|
139
185
|
}
|
|
140
186
|
const duplicateSuite = results.find((result) => "duplicateSuiteId" in result);
|
|
141
187
|
if (duplicateSuite) {
|
|
142
|
-
log.info(
|
|
188
|
+
log.info(
|
|
189
|
+
`\u2705 Deployment notification was successful. Previous run ID: ${duplicateSuite.duplicateSuiteId} already exists for this deployment.`
|
|
190
|
+
);
|
|
143
191
|
return {
|
|
144
192
|
environmentId: environment.id,
|
|
145
193
|
outcome: "success",
|
|
146
194
|
runId: duplicateSuite.duplicateSuiteId
|
|
147
195
|
};
|
|
148
196
|
}
|
|
149
|
-
const successfulTrigger = results.find(
|
|
197
|
+
const successfulTrigger = results.find(
|
|
198
|
+
(result) => "createdSuiteId" in result
|
|
199
|
+
);
|
|
150
200
|
if (!successfulTrigger) {
|
|
151
201
|
log.error(`\u{1F6AB} Run could not be created. Please contact support.`);
|
|
152
|
-
return {
|
|
153
|
-
failReason: "run-could-not-be-created",
|
|
154
|
-
outcome: "failed"
|
|
155
|
-
};
|
|
202
|
+
return { failReason: "run-could-not-be-created", outcome: "failed" };
|
|
156
203
|
}
|
|
157
|
-
log.info(
|
|
204
|
+
log.info(
|
|
205
|
+
`\u2705 Deployment notification was successful. Run created with ID: ${successfulTrigger.createdSuiteId}`
|
|
206
|
+
);
|
|
158
207
|
return {
|
|
159
208
|
environmentId: environment.id,
|
|
160
209
|
outcome: "success",
|
|
@@ -165,29 +214,28 @@ __name(handleSuccessResponse, "handleSuccessResponse");
|
|
|
165
214
|
|
|
166
215
|
// src/lib/sdk/domain/attemptDeploy/mapDeploySuccessResponse.ts
|
|
167
216
|
function mapSuiteResult(result) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
217
|
+
switch (result.outcome) {
|
|
218
|
+
case "created":
|
|
219
|
+
return {
|
|
220
|
+
createdSuiteId: result.created_suite_id,
|
|
221
|
+
triggerId: result.trigger_id
|
|
222
|
+
};
|
|
223
|
+
case "failed":
|
|
224
|
+
return {
|
|
225
|
+
failureCode: result.failure_code,
|
|
226
|
+
failureMessage: result.failure_message,
|
|
227
|
+
failureReason: result.failure_reason,
|
|
228
|
+
triggerId: result.trigger_id
|
|
229
|
+
};
|
|
230
|
+
case "skipped":
|
|
231
|
+
return {
|
|
232
|
+
duplicateSuiteId: result.duplicate_suite_id,
|
|
233
|
+
skipReason: result.skip_reason,
|
|
234
|
+
triggerId: result.trigger_id
|
|
235
|
+
};
|
|
236
|
+
default:
|
|
237
|
+
return { triggerId: result.trigger_id, unrecognized: true };
|
|
186
238
|
}
|
|
187
|
-
return {
|
|
188
|
-
triggerId: result.trigger_id,
|
|
189
|
-
unrecognized: true
|
|
190
|
-
};
|
|
191
239
|
}
|
|
192
240
|
__name(mapSuiteResult, "mapSuiteResult");
|
|
193
241
|
function mapDeploySuccessResponse(wire) {
|
|
@@ -203,7 +251,8 @@ function mapDeploySuccessResponse(wire) {
|
|
|
203
251
|
message: trigger.message,
|
|
204
252
|
reason: trigger.reason,
|
|
205
253
|
triggerId: trigger.trigger_id
|
|
206
|
-
}))
|
|
254
|
+
})),
|
|
255
|
+
warning: wire.warning
|
|
207
256
|
};
|
|
208
257
|
}
|
|
209
258
|
__name(mapDeploySuccessResponse, "mapDeploySuccessResponse");
|
|
@@ -213,22 +262,32 @@ function isRecord(value) {
|
|
|
213
262
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
214
263
|
}
|
|
215
264
|
__name(isRecord, "isRecord");
|
|
265
|
+
function isOptionalString(value) {
|
|
266
|
+
return value === void 0 || typeof value === "string";
|
|
267
|
+
}
|
|
268
|
+
__name(isOptionalString, "isOptionalString");
|
|
216
269
|
function isWireSuiteResult(value) {
|
|
217
270
|
if (!isRecord(value)) return false;
|
|
218
271
|
if (typeof value.trigger_id !== "string") return false;
|
|
219
|
-
if (
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
272
|
+
if (!isOptionalString(value.outcome)) return false;
|
|
273
|
+
switch (value.outcome) {
|
|
274
|
+
case "created":
|
|
275
|
+
return typeof value.created_suite_id === "string";
|
|
276
|
+
case "failed":
|
|
277
|
+
return typeof value.failure_reason === "string" && isOptionalString(value.failure_code) && isOptionalString(value.failure_message);
|
|
278
|
+
case "skipped":
|
|
279
|
+
return typeof value.duplicate_suite_id === "string" && typeof value.skip_reason === "string";
|
|
280
|
+
default:
|
|
281
|
+
return true;
|
|
223
282
|
}
|
|
224
|
-
return true;
|
|
225
283
|
}
|
|
226
284
|
__name(isWireSuiteResult, "isWireSuiteResult");
|
|
227
285
|
function isEnvironment(value) {
|
|
228
286
|
if (!isRecord(value)) return false;
|
|
229
287
|
if (typeof value.id !== "string") return false;
|
|
230
288
|
if (typeof value.isStatic !== "boolean") return false;
|
|
231
|
-
if (value.alias !== void 0 && typeof value.alias !== "string")
|
|
289
|
+
if (value.alias !== void 0 && typeof value.alias !== "string")
|
|
290
|
+
return false;
|
|
232
291
|
return true;
|
|
233
292
|
}
|
|
234
293
|
__name(isEnvironment, "isEnvironment");
|
|
@@ -244,10 +303,15 @@ function isSkippedTrigger(value) {
|
|
|
244
303
|
__name(isSkippedTrigger, "isSkippedTrigger");
|
|
245
304
|
function isDeploySuccessWireResponse(value) {
|
|
246
305
|
if (!isRecord(value)) return false;
|
|
247
|
-
if (value.environment !== void 0 && !isEnvironment(value.environment))
|
|
248
|
-
|
|
249
|
-
if (value.
|
|
250
|
-
|
|
306
|
+
if (value.environment !== void 0 && !isEnvironment(value.environment))
|
|
307
|
+
return false;
|
|
308
|
+
if (!Array.isArray(value.results) || !value.results.every(isWireSuiteResult))
|
|
309
|
+
return false;
|
|
310
|
+
if (value.skipped_deployment !== void 0 && !isSkippedDeployment(value.skipped_deployment))
|
|
311
|
+
return false;
|
|
312
|
+
if (value.skipped_triggers !== void 0 && (!Array.isArray(value.skipped_triggers) || !value.skipped_triggers.every(isSkippedTrigger)))
|
|
313
|
+
return false;
|
|
314
|
+
if (!isOptionalString(value.warning)) return false;
|
|
251
315
|
return true;
|
|
252
316
|
}
|
|
253
317
|
__name(isDeploySuccessWireResponse, "isDeploySuccessWireResponse");
|
|
@@ -262,35 +326,38 @@ async function attemptNotifyDeploy(deps, apiConfig, config) {
|
|
|
262
326
|
let response;
|
|
263
327
|
let bodyText;
|
|
264
328
|
try {
|
|
265
|
-
response = await localFetch(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
329
|
+
response = await localFetch(
|
|
330
|
+
new URL("/api/webhooks/deploy_success", apiConfig.serviceBase),
|
|
331
|
+
{
|
|
332
|
+
body: JSON.stringify({
|
|
333
|
+
branch: config.branch,
|
|
334
|
+
commit_url: config.commitUrl,
|
|
335
|
+
deduplication_key: config.deduplicationKey,
|
|
336
|
+
deployment_type: config.deploymentType,
|
|
337
|
+
deployment_url: config.deploymentUrl,
|
|
338
|
+
..."ephemeralEnvironment" in config ? {
|
|
339
|
+
ephemeral_environment: config.ephemeralEnvironment
|
|
340
|
+
} : "hostingService" in config && {
|
|
341
|
+
hosting_service: config.hostingService,
|
|
342
|
+
merge_request_number: config.hostingService === "GitLab" ? config.mergeRequestNumber : void 0,
|
|
343
|
+
pull_request_number: config.hostingService === "GitHub" ? config.pullRequestNumber : void 0,
|
|
344
|
+
repository: config.repository
|
|
345
|
+
},
|
|
346
|
+
sha: config.sha,
|
|
347
|
+
variables: config.variables,
|
|
348
|
+
workspaceId: config.workspaceId
|
|
349
|
+
}),
|
|
350
|
+
headers: {
|
|
351
|
+
Authorization: `Bearer ${apiConfig.apiKey}`,
|
|
352
|
+
"Content-Type": "application/json",
|
|
353
|
+
"User-Agent": apiConfig.userAgent
|
|
279
354
|
},
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
"Content-Type": "application/json",
|
|
287
|
-
"User-Agent": apiConfig.userAgent
|
|
288
|
-
},
|
|
289
|
-
method: "POST",
|
|
290
|
-
// Override default timeout to 5 minutes. This gives extra room
|
|
291
|
-
// for both (1) waiting for reconciliation (2) creating the run.
|
|
292
|
-
signal: AbortSignal.timeout(5 * 60 * 1e3)
|
|
293
|
-
});
|
|
355
|
+
method: "POST",
|
|
356
|
+
// Override default timeout to 5 minutes. This gives extra room
|
|
357
|
+
// for both (1) waiting for reconciliation (2) creating the run.
|
|
358
|
+
signal: AbortSignal.timeout(5 * 60 * 1e3)
|
|
359
|
+
}
|
|
360
|
+
);
|
|
294
361
|
if (!response.ok) return handleErrorResponse(response, log);
|
|
295
362
|
bodyText = await response.text();
|
|
296
363
|
} catch {
|
|
@@ -309,7 +376,10 @@ async function attemptNotifyDeploy(deps, apiConfig, config) {
|
|
|
309
376
|
}
|
|
310
377
|
const wire = parseDeploySuccessWireResponse(rawBody);
|
|
311
378
|
if (wire === "invalid") {
|
|
312
|
-
return abortInvalidResponseBody(
|
|
379
|
+
return abortInvalidResponseBody(
|
|
380
|
+
log,
|
|
381
|
+
"the response body did not match the expected shape"
|
|
382
|
+
);
|
|
313
383
|
}
|
|
314
384
|
const data = mapDeploySuccessResponse(wire);
|
|
315
385
|
return handleSuccessResponse(data, log);
|
|
@@ -350,10 +420,17 @@ var signedUrlPaths = {
|
|
|
350
420
|
runInputsExecutables: "/api/v0/run-inputs-executables-signed-urls",
|
|
351
421
|
teamStorage: "/api/v0/team-storage-signed-url"
|
|
352
422
|
};
|
|
353
|
-
function buildSignedUrl({
|
|
423
|
+
function buildSignedUrl({
|
|
424
|
+
destinationFilePath,
|
|
425
|
+
endpoint,
|
|
426
|
+
serviceBase,
|
|
427
|
+
workspaceId
|
|
428
|
+
}) {
|
|
354
429
|
const url = new URL(signedUrlPaths[endpoint], serviceBase);
|
|
355
|
-
if (destinationFilePath !== void 0)
|
|
356
|
-
|
|
430
|
+
if (destinationFilePath !== void 0)
|
|
431
|
+
url.searchParams.set("file", destinationFilePath);
|
|
432
|
+
if (workspaceId !== void 0)
|
|
433
|
+
url.searchParams.set("workspaceId", workspaceId);
|
|
357
434
|
return url;
|
|
358
435
|
}
|
|
359
436
|
__name(buildSignedUrl, "buildSignedUrl");
|
|
@@ -361,19 +438,22 @@ __name(buildSignedUrl, "buildSignedUrl");
|
|
|
361
438
|
// src/lib/api/generate-signed-url-for-run-inputs-executables.ts
|
|
362
439
|
async function callGenerateSignedUrlForRunInputsExecutablesStorage({ apiKey, serviceBase, userAgent }, { destinationFilePath, workspaceId }, { fetch: localFetch, log }) {
|
|
363
440
|
try {
|
|
364
|
-
const response = await localFetch(
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
441
|
+
const response = await localFetch(
|
|
442
|
+
buildSignedUrl({
|
|
443
|
+
destinationFilePath,
|
|
444
|
+
endpoint: "runInputsExecutables",
|
|
445
|
+
serviceBase,
|
|
446
|
+
workspaceId
|
|
447
|
+
}),
|
|
448
|
+
{
|
|
449
|
+
headers: {
|
|
450
|
+
Authorization: `Bearer ${apiKey}`,
|
|
451
|
+
"Content-Type": "application/json",
|
|
452
|
+
"User-Agent": userAgent
|
|
453
|
+
},
|
|
454
|
+
method: "GET"
|
|
455
|
+
}
|
|
456
|
+
);
|
|
377
457
|
if (response.status === 200) {
|
|
378
458
|
const json = await response.json();
|
|
379
459
|
return {
|
|
@@ -414,18 +494,28 @@ async function generateSignedUrlForRunInputsExecutablesStorage(deps, apiConfig,
|
|
|
414
494
|
success: false
|
|
415
495
|
};
|
|
416
496
|
}
|
|
417
|
-
const responseState = await callGenerateSignedUrlForRunInputsExecutablesStorage(
|
|
497
|
+
const responseState = await callGenerateSignedUrlForRunInputsExecutablesStorage(
|
|
498
|
+
apiConfig,
|
|
499
|
+
config,
|
|
500
|
+
deps
|
|
501
|
+
);
|
|
418
502
|
if (!responseState.success) {
|
|
419
503
|
let abortReason = "XXX-other-http-code";
|
|
420
504
|
if (responseState.httpStatus >= 500) {
|
|
421
505
|
abortReason = "5XX-server-error";
|
|
422
|
-
log.error(
|
|
506
|
+
log.error(
|
|
507
|
+
`\u{1F6AB} Unrecoverable error (status ${responseState.httpStatus}) when generating signed upload url: aborting.`
|
|
508
|
+
);
|
|
423
509
|
} else {
|
|
424
510
|
if (responseState.httpStatus === 400) abortReason = "400-invalid-request";
|
|
425
|
-
else if (responseState.httpStatus === 401)
|
|
511
|
+
else if (responseState.httpStatus === 401)
|
|
512
|
+
abortReason = "401-invalid-credentials";
|
|
426
513
|
else if (responseState.httpStatus === 403) abortReason = "403-forbidden";
|
|
427
|
-
else if (responseState.httpStatus === 0)
|
|
428
|
-
|
|
514
|
+
else if (responseState.httpStatus === 0)
|
|
515
|
+
abortReason = "client-network-error";
|
|
516
|
+
log.error(
|
|
517
|
+
`\u{1F6AB} Unrecoverable error (status ${responseState.httpStatus}) when generating signed upload url: ${responseState.errorMessage ? `${responseState.errorMessage}.` : ""} aborting.`
|
|
518
|
+
);
|
|
429
519
|
}
|
|
430
520
|
return {
|
|
431
521
|
abortReason,
|
|
@@ -446,19 +536,22 @@ __name(generateSignedUrlForRunInputsExecutablesStorage, "generateSignedUrlForRun
|
|
|
446
536
|
// src/lib/api/generate-signed-url-for-team-storage.ts
|
|
447
537
|
async function callGenerateSignedUrlForTempTeamStorage({ apiKey, serviceBase, userAgent }, { destinationFilePath, workspaceId }, { fetch: localFetch, log }) {
|
|
448
538
|
try {
|
|
449
|
-
const response = await localFetch(
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
539
|
+
const response = await localFetch(
|
|
540
|
+
buildSignedUrl({
|
|
541
|
+
destinationFilePath,
|
|
542
|
+
endpoint: "teamStorage",
|
|
543
|
+
serviceBase,
|
|
544
|
+
workspaceId
|
|
545
|
+
}),
|
|
546
|
+
{
|
|
547
|
+
headers: {
|
|
548
|
+
Authorization: `Bearer ${apiKey}`,
|
|
549
|
+
"Content-Type": "application/json",
|
|
550
|
+
"User-Agent": userAgent
|
|
551
|
+
},
|
|
552
|
+
method: "GET"
|
|
553
|
+
}
|
|
554
|
+
);
|
|
462
555
|
if (response.status === 200) {
|
|
463
556
|
const json = await response.json();
|
|
464
557
|
return {
|
|
@@ -499,18 +592,28 @@ async function generateSignedUrlForTempTeamStorage(deps, apiConfig, config) {
|
|
|
499
592
|
success: false
|
|
500
593
|
};
|
|
501
594
|
}
|
|
502
|
-
const responseState = await callGenerateSignedUrlForTempTeamStorage(
|
|
595
|
+
const responseState = await callGenerateSignedUrlForTempTeamStorage(
|
|
596
|
+
apiConfig,
|
|
597
|
+
config,
|
|
598
|
+
deps
|
|
599
|
+
);
|
|
503
600
|
if (!responseState.success) {
|
|
504
601
|
let abortReason = "XXX-other-http-code";
|
|
505
602
|
if (responseState.httpStatus >= 500) {
|
|
506
603
|
abortReason = "5XX-server-error";
|
|
507
|
-
log.error(
|
|
604
|
+
log.error(
|
|
605
|
+
`\u{1F6AB} Unrecoverable error (status ${responseState.httpStatus}) when generating signed upload url: aborting.`
|
|
606
|
+
);
|
|
508
607
|
} else {
|
|
509
608
|
if (responseState.httpStatus === 400) abortReason = "400-invalid-request";
|
|
510
|
-
else if (responseState.httpStatus === 401)
|
|
609
|
+
else if (responseState.httpStatus === 401)
|
|
610
|
+
abortReason = "401-invalid-credentials";
|
|
511
611
|
else if (responseState.httpStatus === 403) abortReason = "403-forbidden";
|
|
512
|
-
else if (responseState.httpStatus === 0)
|
|
513
|
-
|
|
612
|
+
else if (responseState.httpStatus === 0)
|
|
613
|
+
abortReason = "client-network-error";
|
|
614
|
+
log.error(
|
|
615
|
+
`\u{1F6AB} Unrecoverable error (status ${responseState.httpStatus}) when generating signed upload url: ${responseState.errorMessage ? `${responseState.errorMessage}.` : ""} aborting.`
|
|
616
|
+
);
|
|
514
617
|
}
|
|
515
618
|
return {
|
|
516
619
|
abortReason,
|
|
@@ -532,21 +635,22 @@ __name(generateSignedUrlForTempTeamStorage, "generateSignedUrlForTempTeamStorage
|
|
|
532
635
|
var notifyTerminatedEphemeralEnvironment = /* @__PURE__ */ __name(async (deps, apiConfig, config) => {
|
|
533
636
|
const { fetch: localFetch, log } = deps;
|
|
534
637
|
try {
|
|
535
|
-
const response = await localFetch(
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
638
|
+
const response = await localFetch(
|
|
639
|
+
new URL("/api/webhooks/environment_terminated", apiConfig.serviceBase),
|
|
640
|
+
{
|
|
641
|
+
body: JSON.stringify(config),
|
|
642
|
+
headers: {
|
|
643
|
+
Authorization: `Bearer ${apiConfig.apiKey}`,
|
|
644
|
+
"Content-Type": "application/json",
|
|
645
|
+
"User-Agent": apiConfig.userAgent
|
|
646
|
+
},
|
|
647
|
+
method: "POST"
|
|
648
|
+
}
|
|
649
|
+
);
|
|
544
650
|
if (!response.ok) return handleErrorResponse2(response, log);
|
|
545
|
-
const { environmentId } = await response.json();
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
outcome: "success"
|
|
549
|
-
};
|
|
651
|
+
const { environmentId, warning } = await response.json();
|
|
652
|
+
if (warning) log.warn(`\u26A0\uFE0F ${warning}`);
|
|
653
|
+
return { environmentId, outcome: "success" };
|
|
550
654
|
} catch {
|
|
551
655
|
log.error(`\u{1F6AB} Network error from terminate_preview_environment, aborting.`);
|
|
552
656
|
return {
|
|
@@ -579,14 +683,9 @@ __name(handleErrorResponse2, "handleErrorResponse");
|
|
|
579
683
|
|
|
580
684
|
// src/lib/sdk/domain/pollCiGreenlight/buildCompletedRunResult.ts
|
|
581
685
|
function buildCompletedRunResult(status) {
|
|
582
|
-
if (status.greenlight)
|
|
583
|
-
greenlightStatus: status,
|
|
584
|
-
|
|
585
|
-
};
|
|
586
|
-
else return {
|
|
587
|
-
greenlightStatus: status,
|
|
588
|
-
outcome: "failed"
|
|
589
|
-
};
|
|
686
|
+
if (status.greenlight)
|
|
687
|
+
return { greenlightStatus: status, outcome: "success" };
|
|
688
|
+
else return { greenlightStatus: status, outcome: "failed" };
|
|
590
689
|
}
|
|
591
690
|
__name(buildCompletedRunResult, "buildCompletedRunResult");
|
|
592
691
|
|
|
@@ -595,20 +694,32 @@ var pollCiGreenlightDefaults = {
|
|
|
595
694
|
abortOnSuperseded: false,
|
|
596
695
|
maxRetries: 10,
|
|
597
696
|
pollTimeout: 120 * 60 * 1e3,
|
|
697
|
+
// 2 hours
|
|
598
698
|
retryInterval: 10 * 1e3,
|
|
699
|
+
// 10 seconds
|
|
599
700
|
runInProgressInterval: 30 * 1e3,
|
|
701
|
+
// 30 seconds
|
|
600
702
|
runUnderReviewInterval: 60 * 1e3
|
|
703
|
+
// 60 seconds
|
|
601
704
|
};
|
|
602
705
|
|
|
603
706
|
// src/lib/api/ci-greenlight.ts
|
|
604
|
-
async function fetchCiGreenlightStatus({ apiKey, serviceBase, userAgent }, {
|
|
707
|
+
async function fetchCiGreenlightStatus({ apiKey, serviceBase, userAgent }, {
|
|
708
|
+
runId
|
|
709
|
+
}, { fetch: localFetch, log }) {
|
|
605
710
|
try {
|
|
606
|
-
const resp = await localFetch(
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
711
|
+
const resp = await localFetch(
|
|
712
|
+
new URL(
|
|
713
|
+
`/api/v0/ci-greenlight/${encodeURIComponent(runId)}`,
|
|
714
|
+
serviceBase
|
|
715
|
+
),
|
|
716
|
+
{
|
|
717
|
+
headers: {
|
|
718
|
+
Authorization: `Bearer ${apiKey}`,
|
|
719
|
+
"User-Agent": userAgent
|
|
720
|
+
}
|
|
610
721
|
}
|
|
611
|
-
|
|
722
|
+
);
|
|
612
723
|
if (resp.ok) {
|
|
613
724
|
const greenlightStatus = await resp.json();
|
|
614
725
|
return {
|
|
@@ -658,14 +769,22 @@ __name(fetchCiGreenlightStatus, "fetchCiGreenlightStatus");
|
|
|
658
769
|
// src/lib/sdk/domain/pollCiGreenlight/iterator.ts
|
|
659
770
|
async function* makePollCiGreenlightStatusIterator(deps, apiConfig, { runId, ...pollConfig }) {
|
|
660
771
|
const { log } = deps;
|
|
661
|
-
const {
|
|
772
|
+
const {
|
|
773
|
+
maxRetries = pollCiGreenlightDefaults.maxRetries,
|
|
774
|
+
pollTimeout = pollCiGreenlightDefaults.pollTimeout,
|
|
775
|
+
retryInterval = pollCiGreenlightDefaults.retryInterval,
|
|
776
|
+
runInProgressInterval = pollCiGreenlightDefaults.runInProgressInterval,
|
|
777
|
+
runUnderReviewInterval = pollCiGreenlightDefaults.runUnderReviewInterval
|
|
778
|
+
} = pollConfig;
|
|
662
779
|
let retries = 0;
|
|
663
780
|
let previousStatus = void 0;
|
|
664
781
|
const startedAt = Date.now();
|
|
665
782
|
while (Date.now() - startedAt <= pollTimeout) {
|
|
666
|
-
const responseState = await fetchCiGreenlightStatus(
|
|
667
|
-
|
|
668
|
-
|
|
783
|
+
const responseState = await fetchCiGreenlightStatus(
|
|
784
|
+
apiConfig,
|
|
785
|
+
{ runId },
|
|
786
|
+
deps
|
|
787
|
+
);
|
|
669
788
|
const elapsedMs = Date.now() - startedAt;
|
|
670
789
|
if (!responseState.ok && !responseState.canRetry) {
|
|
671
790
|
yield {
|
|
@@ -712,7 +831,8 @@ async function* makePollCiGreenlightStatusIterator(deps, apiConfig, { runId, ...
|
|
|
712
831
|
}
|
|
713
832
|
const retryLabel = `${httpStatus ? ` (status ${httpStatus})` : ""}, will try again... (${retries}/${maxRetries})`;
|
|
714
833
|
if (errorType === "network") log.warn(`\u274C Network error${retryLabel}`);
|
|
715
|
-
else if (errorType === "not-found")
|
|
834
|
+
else if (errorType === "not-found")
|
|
835
|
+
log.info(`\u23F3 Run not found${retryLabel}`);
|
|
716
836
|
else if (errorType === "server") log.warn(`\u274C Server error${retryLabel}`);
|
|
717
837
|
await sleep(retryInterval);
|
|
718
838
|
continue;
|
|
@@ -736,7 +856,9 @@ async function* makePollCiGreenlightStatusIterator(deps, apiConfig, { runId, ...
|
|
|
736
856
|
abortReason: "run-canceled",
|
|
737
857
|
elapsedMs,
|
|
738
858
|
httpStatus: void 0,
|
|
739
|
-
isAborted: true
|
|
859
|
+
isAborted: true,
|
|
860
|
+
message: greenlightStatus.message,
|
|
861
|
+
reason: greenlightStatus.reason
|
|
740
862
|
};
|
|
741
863
|
return;
|
|
742
864
|
}
|
|
@@ -749,7 +871,9 @@ async function* makePollCiGreenlightStatusIterator(deps, apiConfig, { runId, ...
|
|
|
749
871
|
await sleep(runUnderReviewInterval);
|
|
750
872
|
break;
|
|
751
873
|
default:
|
|
752
|
-
throw Error(
|
|
874
|
+
throw Error(
|
|
875
|
+
`Unexpected run stage: ${greenlightStatus}`
|
|
876
|
+
);
|
|
753
877
|
}
|
|
754
878
|
}
|
|
755
879
|
yield {
|
|
@@ -766,12 +890,19 @@ __name(makePollCiGreenlightStatusIterator, "makePollCiGreenlightStatusIterator")
|
|
|
766
890
|
function buildSuccessLogMessage(status) {
|
|
767
891
|
const { nonBlockingBugsCount, relevantRunUrl } = status;
|
|
768
892
|
const urlInfo = `See ${relevantRunUrl}`;
|
|
769
|
-
return `\u2705 Run passed and no blocking bugs found${nonBlockingBugsCount > 0 ? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(
|
|
893
|
+
return `\u2705 Run passed and no blocking bugs found${nonBlockingBugsCount > 0 ? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(
|
|
894
|
+
nonBlockingBugsCount
|
|
895
|
+
)} found` : ""}.
|
|
770
896
|
${urlInfo}`;
|
|
771
897
|
}
|
|
772
898
|
__name(buildSuccessLogMessage, "buildSuccessLogMessage");
|
|
773
899
|
function buildFailedLogMessage(status) {
|
|
774
|
-
const {
|
|
900
|
+
const {
|
|
901
|
+
blockingBugsCount,
|
|
902
|
+
nonBlockingBugsCount,
|
|
903
|
+
relevantRunWithBugsUrl,
|
|
904
|
+
reproducedBugs
|
|
905
|
+
} = status;
|
|
775
906
|
const blockingBugUrls = reproducedBugs.filter((bug) => bug.isBlocking).map((bug) => bug.applicationUrl);
|
|
776
907
|
const nonBlockingBugUrls = reproducedBugs.filter((bug) => !bug.isBlocking).map((bug) => bug.applicationUrl);
|
|
777
908
|
const blockingBugList = blockingBugUrls.map((url) => `
|
|
@@ -781,7 +912,11 @@ function buildFailedLogMessage(status) {
|
|
|
781
912
|
const bugsListInText = `${blockingBugUrls.length > 0 ? `
|
|
782
913
|
BLOCKING BUGS:${blockingBugList}` : ""}${nonBlockingBugUrls.length > 0 ? `
|
|
783
914
|
NON BLOCKING BUGS:${nonBlockingBugList}` : ""}`;
|
|
784
|
-
return `\u274C Run failed and ${blockingBugsCount} blocking bug${pluralize(
|
|
915
|
+
return `\u274C Run failed and ${blockingBugsCount} blocking bug${pluralize(
|
|
916
|
+
blockingBugsCount
|
|
917
|
+
)} found${nonBlockingBugsCount ? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(
|
|
918
|
+
nonBlockingBugsCount
|
|
919
|
+
)}` : ""}.
|
|
785
920
|
See ${relevantRunWithBugsUrl}
|
|
786
921
|
You may review the priority of certain bugs to mark these non-blocking and retry the job.
|
|
787
922
|
` + bugsListInText;
|
|
@@ -801,18 +936,17 @@ function buildSupersededContinueLogMessage(rootRunUrl, relevantRunUrl) {
|
|
|
801
936
|
return `Root run was superseded:${supersedingDetails}`;
|
|
802
937
|
}
|
|
803
938
|
__name(buildSupersededContinueLogMessage, "buildSupersededContinueLogMessage");
|
|
804
|
-
function buildRunStageLogMessage(
|
|
939
|
+
function buildRunStageLogMessage(status) {
|
|
940
|
+
const { relevantRunUrl, runStage } = status;
|
|
805
941
|
const urlInfo = `See ${relevantRunUrl}`;
|
|
806
942
|
switch (runStage) {
|
|
807
943
|
case "canceled":
|
|
808
|
-
return `\u{1F6AB} Run was canceled. Aborting... Please contact support.
|
|
944
|
+
return `\u{1F6AB} Run was canceled. ${status.message || "Aborting... Please contact support."}
|
|
809
945
|
${urlInfo}`;
|
|
810
946
|
case "initializing":
|
|
811
947
|
return `\u23F3 Run is in progress... ${urlInfo}`;
|
|
812
948
|
case "underReview":
|
|
813
949
|
return `\u{1F575}\uFE0F Run is under review... ${urlInfo}`;
|
|
814
|
-
case "completed":
|
|
815
|
-
throw Error("buildRunStageLogMessage should not be called for completed stage");
|
|
816
950
|
default:
|
|
817
951
|
throw Error(`Unexpected run stage: ${runStage}`);
|
|
818
952
|
}
|
|
@@ -825,21 +959,27 @@ function mapIteratorAbortToGreenlightStatus(iteration, pollTimeout, deps) {
|
|
|
825
959
|
const { abortReason, httpStatus } = iteration;
|
|
826
960
|
switch (abortReason) {
|
|
827
961
|
case "4XX-client-error":
|
|
828
|
-
log.error(
|
|
962
|
+
log.error(
|
|
963
|
+
`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`
|
|
964
|
+
);
|
|
829
965
|
return {
|
|
830
966
|
abortReason,
|
|
831
967
|
httpStatus,
|
|
832
968
|
outcome: "aborted"
|
|
833
969
|
};
|
|
834
970
|
case "5XX-server-error":
|
|
835
|
-
log.error(
|
|
971
|
+
log.error(
|
|
972
|
+
`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`
|
|
973
|
+
);
|
|
836
974
|
return {
|
|
837
975
|
abortReason,
|
|
838
976
|
httpStatus,
|
|
839
977
|
outcome: "aborted"
|
|
840
978
|
};
|
|
841
979
|
case "404-run-not-found":
|
|
842
|
-
log.error(
|
|
980
|
+
log.error(
|
|
981
|
+
`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`
|
|
982
|
+
);
|
|
843
983
|
return {
|
|
844
984
|
abortReason,
|
|
845
985
|
httpStatus,
|
|
@@ -860,14 +1000,18 @@ function mapIteratorAbortToGreenlightStatus(iteration, pollTimeout, deps) {
|
|
|
860
1000
|
outcome: "aborted"
|
|
861
1001
|
};
|
|
862
1002
|
case "run-canceled":
|
|
863
|
-
log.info(
|
|
1003
|
+
log.info(
|
|
1004
|
+
iteration.message ? `Run was canceled. ${iteration.message}` : `Run was canceled`
|
|
1005
|
+
);
|
|
864
1006
|
return {
|
|
865
1007
|
abortReason,
|
|
866
1008
|
httpStatus: void 0,
|
|
867
1009
|
outcome: "aborted"
|
|
868
1010
|
};
|
|
869
1011
|
case "XXX-other-http-code":
|
|
870
|
-
log.error(
|
|
1012
|
+
log.error(
|
|
1013
|
+
`\u{1F6AB} Unrecoverable error (status ${httpStatus}) from CI greenlight, aborting.`
|
|
1014
|
+
);
|
|
871
1015
|
return {
|
|
872
1016
|
abortReason,
|
|
873
1017
|
httpStatus,
|
|
@@ -880,15 +1024,23 @@ function mapIteratorAbortToGreenlightStatus(iteration, pollTimeout, deps) {
|
|
|
880
1024
|
__name(mapIteratorAbortToGreenlightStatus, "mapIteratorAbortToGreenlightStatus");
|
|
881
1025
|
|
|
882
1026
|
// src/lib/sdk/domain/pollCiGreenlight/index.ts
|
|
883
|
-
async function pollCiGreenlightStatus(deps, apiConfig, {
|
|
1027
|
+
async function pollCiGreenlightStatus(deps, apiConfig, {
|
|
1028
|
+
onRunStageChanged = /* @__PURE__ */ __name(() => void 0, "onRunStageChanged"),
|
|
1029
|
+
runId,
|
|
1030
|
+
...pollConfig
|
|
1031
|
+
}) {
|
|
884
1032
|
const { log } = deps;
|
|
885
|
-
const {
|
|
1033
|
+
const {
|
|
1034
|
+
abortOnSuperseded = pollCiGreenlightDefaults.abortOnSuperseded,
|
|
1035
|
+
pollTimeout = pollCiGreenlightDefaults.pollTimeout
|
|
1036
|
+
} = pollConfig;
|
|
886
1037
|
const iterator = makePollCiGreenlightStatusIterator(deps, apiConfig, {
|
|
887
1038
|
runId,
|
|
888
1039
|
...pollConfig
|
|
889
1040
|
});
|
|
890
1041
|
for await (const lastPoll of iterator) {
|
|
891
|
-
if (lastPoll.isAborted)
|
|
1042
|
+
if (lastPoll.isAborted)
|
|
1043
|
+
return mapIteratorAbortToGreenlightStatus(lastPoll, pollTimeout, deps);
|
|
892
1044
|
const { previousStatus, stageChanged, status } = lastPoll;
|
|
893
1045
|
if (stageChanged) {
|
|
894
1046
|
try {
|
|
@@ -901,7 +1053,10 @@ async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged = /*
|
|
|
901
1053
|
const isSuperseded = rootRunId !== relevantRunId;
|
|
902
1054
|
const shouldAbortOnSuperseded = isSuperseded && abortOnSuperseded;
|
|
903
1055
|
if (shouldAbortOnSuperseded) {
|
|
904
|
-
const message = buildSupersededAbortLogMessage(
|
|
1056
|
+
const message = buildSupersededAbortLogMessage(
|
|
1057
|
+
rootRunUrl,
|
|
1058
|
+
relevantRunUrl
|
|
1059
|
+
);
|
|
905
1060
|
log.warn(message);
|
|
906
1061
|
return {
|
|
907
1062
|
abortReason: "superseded-run",
|
|
@@ -910,14 +1065,17 @@ async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged = /*
|
|
|
910
1065
|
};
|
|
911
1066
|
}
|
|
912
1067
|
if (isSuperseded) {
|
|
913
|
-
const message = buildSupersededContinueLogMessage(
|
|
1068
|
+
const message = buildSupersededContinueLogMessage(
|
|
1069
|
+
rootRunUrl,
|
|
1070
|
+
relevantRunUrl
|
|
1071
|
+
);
|
|
914
1072
|
log.info(message);
|
|
915
1073
|
}
|
|
916
1074
|
switch (runStage) {
|
|
917
1075
|
case "canceled":
|
|
918
1076
|
case "initializing":
|
|
919
1077
|
case "underReview": {
|
|
920
|
-
log.info(buildRunStageLogMessage(
|
|
1078
|
+
log.info(buildRunStageLogMessage(status));
|
|
921
1079
|
break;
|
|
922
1080
|
}
|
|
923
1081
|
case "completed": {
|
|
@@ -950,10 +1108,19 @@ async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged = /*
|
|
|
950
1108
|
__name(pollCiGreenlightStatus, "pollCiGreenlightStatus");
|
|
951
1109
|
|
|
952
1110
|
// src/lib/sdk/index.ts
|
|
953
|
-
function makeQaWolfSdk({
|
|
1111
|
+
function makeQaWolfSdk({
|
|
1112
|
+
apiKey,
|
|
1113
|
+
serviceBase = defaultServiceBase,
|
|
1114
|
+
userAgent = defaultUserAgent
|
|
1115
|
+
}, {
|
|
1116
|
+
fetch = defaultFetch,
|
|
1117
|
+
log = defaultLogDriver
|
|
1118
|
+
} = {}) {
|
|
954
1119
|
if (typeof fetch !== "function") {
|
|
955
|
-
throw Error(
|
|
956
|
-
|
|
1120
|
+
throw Error(
|
|
1121
|
+
`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.
|
|
1122
|
+
We recommend 'undici' package for that purpose. See the Requirement section of our README for more guidance.`
|
|
1123
|
+
);
|
|
957
1124
|
}
|
|
958
1125
|
const deps = {
|
|
959
1126
|
// Versions of fetch may have different default timeouts. For consistency, we explicitly set it to 2 minutes here.
|
|
@@ -962,22 +1129,26 @@ We recommend 'undici' package for that purpose. See the Requirement section of o
|
|
|
962
1129
|
fetch: buildFetchWithTimeout(fetch, 12e4),
|
|
963
1130
|
log
|
|
964
1131
|
};
|
|
965
|
-
const apiConfig = {
|
|
966
|
-
apiKey,
|
|
967
|
-
serviceBase,
|
|
968
|
-
userAgent
|
|
969
|
-
};
|
|
1132
|
+
const apiConfig = { apiKey, serviceBase, userAgent };
|
|
970
1133
|
return {
|
|
971
1134
|
attemptNotifyDeploy: attemptNotifyDeploy.bind(null, deps, apiConfig),
|
|
972
|
-
generateSignedUrlForRunInputsExecutablesStorage: generateSignedUrlForRunInputsExecutablesStorage.bind(
|
|
1135
|
+
generateSignedUrlForRunInputsExecutablesStorage: generateSignedUrlForRunInputsExecutablesStorage.bind(
|
|
1136
|
+
null,
|
|
1137
|
+
deps,
|
|
1138
|
+
apiConfig
|
|
1139
|
+
),
|
|
973
1140
|
generateSignedUrlForTempTeamStorage: generateSignedUrlForTempTeamStorage.bind(null, deps, apiConfig),
|
|
974
|
-
makePollCiGreenlightStatusIterator: makePollCiGreenlightStatusIterator.bind(
|
|
1141
|
+
makePollCiGreenlightStatusIterator: makePollCiGreenlightStatusIterator.bind(
|
|
1142
|
+
null,
|
|
1143
|
+
deps,
|
|
1144
|
+
apiConfig
|
|
1145
|
+
),
|
|
975
1146
|
notifyTerminatedEphemeralEnvironment: notifyTerminatedEphemeralEnvironment.bind(null, deps, apiConfig),
|
|
976
1147
|
pollCiGreenlightStatus: pollCiGreenlightStatus.bind(null, deps, apiConfig)
|
|
977
1148
|
};
|
|
978
1149
|
}
|
|
979
1150
|
__name(makeQaWolfSdk, "makeQaWolfSdk");
|
|
980
|
-
|
|
981
|
-
|
|
1151
|
+
export {
|
|
1152
|
+
makeQaWolfSdk
|
|
1153
|
+
};
|
|
982
1154
|
//# sourceMappingURL=index.js.map
|
|
983
|
-
//# sourceMappingURL=index.js.map
|