@qawolf/ci-sdk 1.3.2 → 2.0.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 +18 -1
- package/dist/index.cjs +126 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +100 -31
- package/dist/index.d.ts +100 -31
- package/dist/index.js +126 -65
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
package/dist/index.d.ts
CHANGED
|
@@ -63,26 +63,10 @@ type CiGreenlightBugData = {
|
|
|
63
63
|
* The count of blocking bugs reproduced in the run.
|
|
64
64
|
*/
|
|
65
65
|
blockingBugsCount: number;
|
|
66
|
-
/**
|
|
67
|
-
* The URLs of the blocking bugs.
|
|
68
|
-
*
|
|
69
|
-
* @deprecated This field will be removed in the next major version.
|
|
70
|
-
* Prefer using `reproducedBugs` filtered by `isBlocking: true`, reading
|
|
71
|
-
* the `applicationUrl` field.
|
|
72
|
-
*/
|
|
73
|
-
blockingBugUrls: string[];
|
|
74
66
|
/**
|
|
75
67
|
* The count of non-blocking bugs reproduced in the run.
|
|
76
68
|
*/
|
|
77
69
|
nonBlockingBugsCount: number;
|
|
78
|
-
/**
|
|
79
|
-
* The URLs of the non-blocking bugs.
|
|
80
|
-
*
|
|
81
|
-
* @deprecated This field will be removed in the next major version.
|
|
82
|
-
* Prefer using `reproducedBugs` filtered by `isBlocking: false`, reading
|
|
83
|
-
* the `applicationUrl` field.
|
|
84
|
-
*/
|
|
85
|
-
nonBlockingBugUrls: string[];
|
|
86
70
|
/**
|
|
87
71
|
* Blocking bugs that were not reproduced in this run, but are still
|
|
88
72
|
* opened in the run environment. This may happen when the run only covers a
|
|
@@ -91,15 +75,20 @@ type CiGreenlightBugData = {
|
|
|
91
75
|
otherBlockingBugsInEnvironment: CiGreenlightBugDetails[];
|
|
92
76
|
/**
|
|
93
77
|
* Bugs that were reproduced in this run. This includes newly found bugs.
|
|
78
|
+
* Filter by `isBlocking` and read `applicationUrl` for blocking /
|
|
79
|
+
* non-blocking bug URLs.
|
|
94
80
|
*/
|
|
95
81
|
reproducedBugs: CiGreenlightBugDetails[];
|
|
96
82
|
};
|
|
83
|
+
|
|
97
84
|
type CiGreenlightStatusBase = {
|
|
98
85
|
relevantRunId: string;
|
|
99
86
|
relevantRunUrl: string;
|
|
100
|
-
relevantRunWithBugsUrl: string;
|
|
101
87
|
rootRunId: string;
|
|
102
88
|
rootRunUrl: string;
|
|
89
|
+
};
|
|
90
|
+
type CiGreenlightStatusExtended = {
|
|
91
|
+
relevantRunWithBugsUrl: string;
|
|
103
92
|
workflowsDisabledAfterRunCount: number;
|
|
104
93
|
workflowsInRunCount: number;
|
|
105
94
|
workflowsUnderInvestigationCount: number;
|
|
@@ -111,13 +100,26 @@ type CiGreenlightStatusBase = {
|
|
|
111
100
|
type CiGreenlightStatus = CiGreenlightStatusBase & (({
|
|
112
101
|
greenlight: boolean;
|
|
113
102
|
runStage: "completed";
|
|
114
|
-
} & CiGreenlightBugData) | ({
|
|
103
|
+
} & CiGreenlightBugData & CiGreenlightStatusExtended) | ({
|
|
115
104
|
greenlight: false;
|
|
116
105
|
runStage: "underReview";
|
|
117
|
-
} & CiGreenlightBugData) | {
|
|
106
|
+
} & CiGreenlightBugData & CiGreenlightStatusExtended) | ({
|
|
118
107
|
greenlight: false;
|
|
119
|
-
runStage: "initializing"
|
|
120
|
-
})
|
|
108
|
+
runStage: "initializing";
|
|
109
|
+
} & Partial<CiGreenlightStatusExtended>) | ({
|
|
110
|
+
greenlight: false;
|
|
111
|
+
/**
|
|
112
|
+
* Human-readable copy explaining why the run was canceled, when the
|
|
113
|
+
* server provides it.
|
|
114
|
+
*/
|
|
115
|
+
message?: string;
|
|
116
|
+
/**
|
|
117
|
+
* Stable, machine-readable code for why the run was canceled, when the
|
|
118
|
+
* server provides it. Treat as an open set of values.
|
|
119
|
+
*/
|
|
120
|
+
reason?: string;
|
|
121
|
+
runStage: "canceled";
|
|
122
|
+
} & Partial<CiGreenlightStatusExtended>));
|
|
121
123
|
|
|
122
124
|
type GenerateSignedUrlStatus = {
|
|
123
125
|
fileLocation?: string;
|
|
@@ -142,10 +144,41 @@ type GenerateSignedUrlResponse = {
|
|
|
142
144
|
success: boolean;
|
|
143
145
|
};
|
|
144
146
|
|
|
147
|
+
type WireSuiteResult = {
|
|
148
|
+
created_suite_id: string;
|
|
149
|
+
trigger_id: string;
|
|
150
|
+
} | {
|
|
151
|
+
failure_reason: string;
|
|
152
|
+
trigger_id: string;
|
|
153
|
+
} | {
|
|
154
|
+
duplicate_suite_id: string;
|
|
155
|
+
skip_reason: string;
|
|
156
|
+
trigger_id: string;
|
|
157
|
+
};
|
|
158
|
+
type DeploySuccessWireResponse = {
|
|
159
|
+
environment: {
|
|
160
|
+
alias?: string;
|
|
161
|
+
id: string;
|
|
162
|
+
isStatic: boolean;
|
|
163
|
+
} | undefined;
|
|
164
|
+
results: WireSuiteResult[];
|
|
165
|
+
skipped_deployment?: {
|
|
166
|
+
message: string;
|
|
167
|
+
reason: string;
|
|
168
|
+
};
|
|
169
|
+
skipped_triggers?: {
|
|
170
|
+
environment_id: string;
|
|
171
|
+
message: string;
|
|
172
|
+
reason: string;
|
|
173
|
+
trigger_id: string;
|
|
174
|
+
}[];
|
|
175
|
+
};
|
|
176
|
+
|
|
145
177
|
/**
|
|
146
178
|
* Refer to our official documentation for more information:
|
|
147
179
|
* https://qawolf.notion.site/dd72e46ceb7f451dae4e9ef06f64a2cc
|
|
148
180
|
*/
|
|
181
|
+
|
|
149
182
|
type BaseDeployConfig = {
|
|
150
183
|
branch: string | undefined;
|
|
151
184
|
commitUrl: string | undefined;
|
|
@@ -177,19 +210,29 @@ type EphemeralDeployConfig = BaseDeployConfig & {
|
|
|
177
210
|
};
|
|
178
211
|
type DeployConfig = GitHubDeployConfig | GitLabDeployConfig | EphemeralDeployConfig;
|
|
179
212
|
type DeploySuccessSuiteCreatedResult = {
|
|
180
|
-
|
|
181
|
-
|
|
213
|
+
createdSuiteId: string;
|
|
214
|
+
triggerId: string;
|
|
182
215
|
};
|
|
183
216
|
type DeploySuccessSuiteCreationFailureResult = {
|
|
184
|
-
|
|
185
|
-
|
|
217
|
+
failureReason: string;
|
|
218
|
+
triggerId: string;
|
|
186
219
|
};
|
|
187
220
|
type DeploySuccessSuiteAlreadyExistsResult = {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
221
|
+
duplicateSuiteId: string;
|
|
222
|
+
skipReason: string;
|
|
223
|
+
triggerId: string;
|
|
191
224
|
};
|
|
192
225
|
type DeploySuccessSuiteResult = DeploySuccessSuiteCreatedResult | DeploySuccessSuiteCreationFailureResult | DeploySuccessSuiteAlreadyExistsResult;
|
|
226
|
+
type DeploySuccessSkippedTrigger = {
|
|
227
|
+
environmentId: string;
|
|
228
|
+
message: string;
|
|
229
|
+
reason: string;
|
|
230
|
+
triggerId: string;
|
|
231
|
+
};
|
|
232
|
+
type DeploySuccessDeploymentSkipped = {
|
|
233
|
+
message: string;
|
|
234
|
+
reason: string;
|
|
235
|
+
};
|
|
193
236
|
type DeployStatus = {
|
|
194
237
|
environment: {
|
|
195
238
|
alias?: string;
|
|
@@ -197,6 +240,8 @@ type DeployStatus = {
|
|
|
197
240
|
isStatic: boolean;
|
|
198
241
|
} | undefined;
|
|
199
242
|
results: Array<DeploySuccessSuiteResult>;
|
|
243
|
+
skippedDeployment?: DeploySuccessDeploymentSkipped;
|
|
244
|
+
skippedTriggers?: DeploySuccessSkippedTrigger[];
|
|
200
245
|
};
|
|
201
246
|
type DeployStatusSuccessResponse = {
|
|
202
247
|
data: DeployStatus;
|
|
@@ -209,7 +254,6 @@ type DeployStatusErrorResponse = {
|
|
|
209
254
|
status: number | undefined;
|
|
210
255
|
};
|
|
211
256
|
type DeployStatusResponse = DeployStatusSuccessResponse | DeployStatusErrorResponse;
|
|
212
|
-
type AttemptDeployFailedReason = "no-matched-trigger" | "no-environment" | "run-could-not-be-created" | "duplicate-suite";
|
|
213
257
|
type AttemptDeployHttpAbortReason = "4XX-client-error" | "401-unauthorized" | "403-forbidden" | "5XX-server-error" | "network-error";
|
|
214
258
|
type AttemptDeployNonHttpAbortReason = "network-error";
|
|
215
259
|
type AttemptDeployAbortReason = AttemptDeployHttpAbortReason | AttemptDeployNonHttpAbortReason;
|
|
@@ -227,7 +271,29 @@ type NotifyDeployStatus = {
|
|
|
227
271
|
*/
|
|
228
272
|
runId: string | undefined;
|
|
229
273
|
} | {
|
|
230
|
-
|
|
274
|
+
/**
|
|
275
|
+
* One or more triggers matched the deployment but could not run (e.g. the
|
|
276
|
+
* environment was still syncing). A precondition was not met, so this is a
|
|
277
|
+
* failure rather than a skip: retrying once the environment is ready may
|
|
278
|
+
* create a run.
|
|
279
|
+
*/
|
|
280
|
+
failReason: "trigger-skipped";
|
|
281
|
+
outcome: "failed";
|
|
282
|
+
skippedTriggers: DeploySuccessSkippedTrigger[];
|
|
283
|
+
} | {
|
|
284
|
+
/**
|
|
285
|
+
* No trigger matched the deployment. This is deterministic given the
|
|
286
|
+
* current configuration (repeating the request with the same config
|
|
287
|
+
* yields the same result), so it is a skip rather than a failure, and the
|
|
288
|
+
* caller should not treat it as an error. `skippedDeployment` carries the
|
|
289
|
+
* server's reason when it provided one (undefined on older servers or the
|
|
290
|
+
* legacy arm); there is no separate SDK-level reason code, since
|
|
291
|
+
* `outcome: "skipped"` only ever means no trigger matched.
|
|
292
|
+
*/
|
|
293
|
+
outcome: "skipped";
|
|
294
|
+
skippedDeployment: DeploySuccessDeploymentSkipped | undefined;
|
|
295
|
+
} | {
|
|
296
|
+
failReason: "no-environment" | "run-could-not-be-created";
|
|
231
297
|
/**
|
|
232
298
|
* A run could not be created.
|
|
233
299
|
*/
|
|
@@ -247,6 +313,9 @@ type NotifyDeployStatus = {
|
|
|
247
313
|
*/
|
|
248
314
|
outcome: "aborted";
|
|
249
315
|
};
|
|
316
|
+
type AttemptDeployFailedReason = Extract<NotifyDeployStatus, {
|
|
317
|
+
outcome: "failed";
|
|
318
|
+
}>["failReason"];
|
|
250
319
|
|
|
251
320
|
type NotifyTerminatedEphemeralEnvironmentInput = {
|
|
252
321
|
environmentId: string;
|
|
@@ -455,4 +524,4 @@ declare function makeQaWolfSdk({ apiKey, serviceBase, userAgent, }: {
|
|
|
455
524
|
pollCiGreenlightStatus: (args_0: PollCiGreenlightParams) => Promise<PollCiGreenlightStatus>;
|
|
456
525
|
};
|
|
457
526
|
|
|
458
|
-
export { type AttemptDeployAbortReason, type AttemptDeployFailedReason, type AttemptDeployHttpAbortReason, type AttemptDeployNonHttpAbortReason, type CiGreenlightStatus, type CiGreenlightStatusBase, type DeployConfig, type DeployStatus, type DeployStatusErrorResponse, type DeployStatusResponse, type DeployStatusSuccessResponse, type DeploySuccessSuiteAlreadyExistsResult, type DeploySuccessSuiteCreatedResult, type DeploySuccessSuiteCreationFailureResult, type DeploySuccessSuiteResult, type EphemeralDeployConfig, type FetchDriver, type GenerateSignedUrlAbortReason$1 as GenerateSignedUrlAbortReason, type GenerateSignedUrlConfig, type GenerateSignedUrlResponse, type GenerateSignedUrlStatus, type GitHubDeployConfig, type GitLabDeployConfig, type MakePollCiGreenlightStatusIteratorParams, type NotifyDeployStatus, type NotifyTerminatedEphemeralEnvironmentAbortReason, type NotifyTerminatedEphemeralEnvironmentFailedReason, type NotifyTerminatedEphemeralEnvironmentHttpAbortReason, type NotifyTerminatedEphemeralEnvironmentInput, type NotifyTerminatedEphemeralEnvironmentNonHttpAbortReason, type NotifyTerminatedEphemeralEnvironmentResult, type PollCiGreenlightAbortReason, type PollCiGreenlightHttpAbortReason, type PollCiGreenlightIteration, type PollCiGreenlightIteratorHttpAborted, type PollCiGreenlightIteratorNonHttpAborted, type PollCiGreenlightNonHttpAbortReason, type PollCiGreenlightParams, type PollCiGreenlightPollConfig, type PollCiGreenlightStatus, type PollCiGreenlightStatusIteration, type SdkDependencies, type TerminatedEphemeralEnvironmentSuccessResult, attemptNotifyDeploy, makeQaWolfSdk };
|
|
527
|
+
export { type AttemptDeployAbortReason, type AttemptDeployFailedReason, type AttemptDeployHttpAbortReason, type AttemptDeployNonHttpAbortReason, type CiGreenlightStatus, type CiGreenlightStatusBase, type DeployConfig, type DeployStatus, type DeployStatusErrorResponse, type DeployStatusResponse, type DeployStatusSuccessResponse, type DeploySuccessDeploymentSkipped, type DeploySuccessSkippedTrigger, type DeploySuccessSuiteAlreadyExistsResult, type DeploySuccessSuiteCreatedResult, type DeploySuccessSuiteCreationFailureResult, type DeploySuccessSuiteResult, type DeploySuccessWireResponse, type EphemeralDeployConfig, type FetchDriver, type GenerateSignedUrlAbortReason$1 as GenerateSignedUrlAbortReason, type GenerateSignedUrlConfig, type GenerateSignedUrlResponse, type GenerateSignedUrlStatus, type GitHubDeployConfig, type GitLabDeployConfig, type MakePollCiGreenlightStatusIteratorParams, type NotifyDeployStatus, type NotifyTerminatedEphemeralEnvironmentAbortReason, type NotifyTerminatedEphemeralEnvironmentFailedReason, type NotifyTerminatedEphemeralEnvironmentHttpAbortReason, type NotifyTerminatedEphemeralEnvironmentInput, type NotifyTerminatedEphemeralEnvironmentNonHttpAbortReason, type NotifyTerminatedEphemeralEnvironmentResult, type PollCiGreenlightAbortReason, type PollCiGreenlightHttpAbortReason, type PollCiGreenlightIteration, type PollCiGreenlightIteratorHttpAborted, type PollCiGreenlightIteratorNonHttpAborted, type PollCiGreenlightNonHttpAbortReason, type PollCiGreenlightParams, type PollCiGreenlightPollConfig, type PollCiGreenlightStatus, type PollCiGreenlightStatusIteration, type SdkDependencies, type TerminatedEphemeralEnvironmentSuccessResult, attemptNotifyDeploy, makeQaWolfSdk };
|
package/dist/index.js
CHANGED
|
@@ -39,7 +39,7 @@ var defaultServiceBase = "https://app.qawolf.com/";
|
|
|
39
39
|
|
|
40
40
|
// package.json
|
|
41
41
|
var package_default = {
|
|
42
|
-
version: "
|
|
42
|
+
version: "2.0.0"};
|
|
43
43
|
|
|
44
44
|
// src/lib/sdk/defaults/userAgent.ts
|
|
45
45
|
var defaultUserAgent = `ci-sdk/${package_default.version}`;
|
|
@@ -74,6 +74,126 @@ async function logFetchError({ log, methodName, response }) {
|
|
|
74
74
|
}
|
|
75
75
|
__name(logFetchError, "logFetchError");
|
|
76
76
|
|
|
77
|
+
// src/lib/sdk/domain/attemptDeploy/handleSuccessResponse.ts
|
|
78
|
+
async function handleSuccessResponse(data, log) {
|
|
79
|
+
const { environment, results } = data;
|
|
80
|
+
const skippedTriggers = data.skippedTriggers ?? [];
|
|
81
|
+
const skippedDeployment = data.skippedDeployment;
|
|
82
|
+
const isPreviewDeployment = environment && !environment.isStatic;
|
|
83
|
+
if (environment) {
|
|
84
|
+
const logPrefix = environment.isStatic ? "Static environment" : "Preview environment";
|
|
85
|
+
log.info(`${logPrefix}: ${environment.alias} (id: ${environment.id})`);
|
|
86
|
+
}
|
|
87
|
+
if (results.length === 0) {
|
|
88
|
+
const skipMessages = [
|
|
89
|
+
...skippedTriggers.map((trigger) => trigger.message),
|
|
90
|
+
...skippedDeployment ? [
|
|
91
|
+
skippedDeployment.message
|
|
92
|
+
] : []
|
|
93
|
+
];
|
|
94
|
+
const skipDetail = skipMessages.length > 0 ? ` ${skipMessages.join(" ")}` : "";
|
|
95
|
+
if (isPreviewDeployment) {
|
|
96
|
+
log.info(`\u2705 Deployment notification was successful. No run was created for this deployment.${skipDetail}`);
|
|
97
|
+
return {
|
|
98
|
+
environmentId: environment.id,
|
|
99
|
+
outcome: "success",
|
|
100
|
+
runId: void 0
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (skippedTriggers.length > 0) {
|
|
104
|
+
log.error(`\u{1F6AB} No run was created for this deployment.${skipDetail}`);
|
|
105
|
+
return {
|
|
106
|
+
failReason: "trigger-skipped",
|
|
107
|
+
outcome: "failed",
|
|
108
|
+
skippedTriggers
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
log.warn(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.`);
|
|
112
|
+
return {
|
|
113
|
+
outcome: "skipped",
|
|
114
|
+
skippedDeployment
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (!environment) {
|
|
118
|
+
log.error(`\u{1F6AB} No environment matched the request. Please contact support.`);
|
|
119
|
+
return {
|
|
120
|
+
failReason: "no-environment",
|
|
121
|
+
outcome: "failed"
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const failedTrigger = results.find((result) => "failureReason" in result);
|
|
125
|
+
if (failedTrigger) {
|
|
126
|
+
log.error(`\u{1F6AB} Run could not be created. Reason: "${failedTrigger.failureReason}". Please contact support.`);
|
|
127
|
+
return {
|
|
128
|
+
failReason: "run-could-not-be-created",
|
|
129
|
+
outcome: "failed"
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const duplicateSuite = results.find((result) => "duplicateSuiteId" in result);
|
|
133
|
+
if (duplicateSuite) {
|
|
134
|
+
log.info(`\u2705 Deployment notification was successful. Previous run ID: ${duplicateSuite.duplicateSuiteId} already exists for this deployment.`);
|
|
135
|
+
return {
|
|
136
|
+
environmentId: environment.id,
|
|
137
|
+
outcome: "success",
|
|
138
|
+
runId: duplicateSuite.duplicateSuiteId
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const successfulTrigger = results.find((result) => "createdSuiteId" in result);
|
|
142
|
+
if (!successfulTrigger) {
|
|
143
|
+
log.error(`\u{1F6AB} Run could not be created. Please contact support.`);
|
|
144
|
+
return {
|
|
145
|
+
failReason: "run-could-not-be-created",
|
|
146
|
+
outcome: "failed"
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
log.info(`\u2705 Deployment notification was successful. Run created with ID: ${successfulTrigger.createdSuiteId}`);
|
|
150
|
+
return {
|
|
151
|
+
environmentId: environment.id,
|
|
152
|
+
outcome: "success",
|
|
153
|
+
runId: successfulTrigger.createdSuiteId
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
__name(handleSuccessResponse, "handleSuccessResponse");
|
|
157
|
+
|
|
158
|
+
// src/lib/sdk/domain/attemptDeploy/mapDeploySuccessResponse.ts
|
|
159
|
+
function mapSuiteResult(result) {
|
|
160
|
+
if ("created_suite_id" in result) {
|
|
161
|
+
return {
|
|
162
|
+
createdSuiteId: result.created_suite_id,
|
|
163
|
+
triggerId: result.trigger_id
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
if ("failure_reason" in result) {
|
|
167
|
+
return {
|
|
168
|
+
failureReason: result.failure_reason,
|
|
169
|
+
triggerId: result.trigger_id
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
duplicateSuiteId: result.duplicate_suite_id,
|
|
174
|
+
skipReason: result.skip_reason,
|
|
175
|
+
triggerId: result.trigger_id
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
__name(mapSuiteResult, "mapSuiteResult");
|
|
179
|
+
function mapDeploySuccessResponse(wire) {
|
|
180
|
+
return {
|
|
181
|
+
environment: wire.environment,
|
|
182
|
+
results: wire.results.map(mapSuiteResult),
|
|
183
|
+
skippedDeployment: wire.skipped_deployment && {
|
|
184
|
+
message: wire.skipped_deployment.message,
|
|
185
|
+
reason: wire.skipped_deployment.reason
|
|
186
|
+
},
|
|
187
|
+
skippedTriggers: wire.skipped_triggers?.map((trigger) => ({
|
|
188
|
+
environmentId: trigger.environment_id,
|
|
189
|
+
message: trigger.message,
|
|
190
|
+
reason: trigger.reason,
|
|
191
|
+
triggerId: trigger.trigger_id
|
|
192
|
+
}))
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
__name(mapDeploySuccessResponse, "mapDeploySuccessResponse");
|
|
196
|
+
|
|
77
197
|
// src/lib/sdk/domain/attemptDeploy/index.ts
|
|
78
198
|
async function attemptNotifyDeploy(deps, apiConfig, config) {
|
|
79
199
|
const { fetch: localFetch, log } = deps;
|
|
@@ -107,7 +227,8 @@ async function attemptNotifyDeploy(deps, apiConfig, config) {
|
|
|
107
227
|
signal: AbortSignal.timeout(5 * 60 * 1e3)
|
|
108
228
|
});
|
|
109
229
|
if (!response.ok) return handleErrorResponse(response, log);
|
|
110
|
-
const
|
|
230
|
+
const wire = await response.json();
|
|
231
|
+
const data = mapDeploySuccessResponse(wire);
|
|
111
232
|
return handleSuccessResponse(data, log);
|
|
112
233
|
} catch {
|
|
113
234
|
log.error(`\u{1F6AB} Network error from deploy_success, aborting.`);
|
|
@@ -139,68 +260,6 @@ async function handleErrorResponse(response, log) {
|
|
|
139
260
|
};
|
|
140
261
|
}
|
|
141
262
|
__name(handleErrorResponse, "handleErrorResponse");
|
|
142
|
-
async function handleSuccessResponse(data, log) {
|
|
143
|
-
const { environment, results } = data;
|
|
144
|
-
const isPreviewDeployment = environment && !environment.isStatic;
|
|
145
|
-
if (environment) {
|
|
146
|
-
const logPrefix = environment.isStatic ? "Static environment" : "Preview environment";
|
|
147
|
-
log.info(`${logPrefix}: ${environment.alias} (id: ${environment.id})`);
|
|
148
|
-
}
|
|
149
|
-
if (results.length === 0) {
|
|
150
|
-
if (isPreviewDeployment) {
|
|
151
|
-
log.info(`\u2705 Deployment notification was successful. No run was created for this deployment.`);
|
|
152
|
-
return {
|
|
153
|
-
environmentId: environment.id,
|
|
154
|
-
outcome: "success",
|
|
155
|
-
runId: void 0
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
log.error(`\u{1F6AB} No trigger matched the request. Please make sure there is at least one active test in the QA Wolf environment, or contact support.`);
|
|
159
|
-
return {
|
|
160
|
-
failReason: "no-matched-trigger",
|
|
161
|
-
outcome: "failed"
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
if (!environment) {
|
|
165
|
-
log.error(`\u{1F6AB} No environment matched the request. Please contact support.`);
|
|
166
|
-
return {
|
|
167
|
-
failReason: "no-environment",
|
|
168
|
-
outcome: "failed"
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
const failedTrigger = results.find((t) => "failure_reason" in t);
|
|
172
|
-
if (failedTrigger) {
|
|
173
|
-
log.error(`\u{1F6AB} Run could not be created. Reason: "${failedTrigger.failure_reason}". Please contact support.`);
|
|
174
|
-
return {
|
|
175
|
-
failReason: "run-could-not-be-created",
|
|
176
|
-
outcome: "failed"
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
const duplicateSuite = results.find((t) => "duplicate_suite_id" in t);
|
|
180
|
-
if (duplicateSuite) {
|
|
181
|
-
log.info(`\u2705 Deployment notification was successful. Previous run ID: ${duplicateSuite.duplicate_suite_id} already exists for this deployment.`);
|
|
182
|
-
return {
|
|
183
|
-
environmentId: environment.id,
|
|
184
|
-
outcome: "success",
|
|
185
|
-
runId: duplicateSuite.duplicate_suite_id
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
const successfulTrigger = results.find((t) => "created_suite_id" in t);
|
|
189
|
-
if (!successfulTrigger) {
|
|
190
|
-
log.error(`\u{1F6AB} No trigger matched the request. Please contact support.`);
|
|
191
|
-
return {
|
|
192
|
-
failReason: "no-matched-trigger",
|
|
193
|
-
outcome: "failed"
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
log.info(`\u2705 Deployment notification was successful. Run created with ID: ${successfulTrigger.created_suite_id}`);
|
|
197
|
-
return {
|
|
198
|
-
environmentId: environment.id,
|
|
199
|
-
outcome: "success",
|
|
200
|
-
runId: successfulTrigger.created_suite_id
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
__name(handleSuccessResponse, "handleSuccessResponse");
|
|
204
263
|
|
|
205
264
|
// src/lib/api/generate-signed-url-for-run-inputs-executables.ts
|
|
206
265
|
async function callGenerateSignedUrlForRunInputsExecutablesStorage({ apiKey, serviceBase, userAgent }, { destinationFilePath }, { fetch: localFetch, log }) {
|
|
@@ -605,7 +664,9 @@ ${urlInfo}`;
|
|
|
605
664
|
}
|
|
606
665
|
__name(buildSuccessLogMessage, "buildSuccessLogMessage");
|
|
607
666
|
function buildFailedLogMessage(status) {
|
|
608
|
-
const { blockingBugsCount,
|
|
667
|
+
const { blockingBugsCount, nonBlockingBugsCount, relevantRunWithBugsUrl, reproducedBugs } = status;
|
|
668
|
+
const blockingBugUrls = reproducedBugs.filter((bug) => bug.isBlocking).map((bug) => bug.applicationUrl);
|
|
669
|
+
const nonBlockingBugUrls = reproducedBugs.filter((bug) => !bug.isBlocking).map((bug) => bug.applicationUrl);
|
|
609
670
|
const blockingBugList = blockingBugUrls.map((url) => `
|
|
610
671
|
\u2022 ${url}`).join("");
|
|
611
672
|
const nonBlockingBugList = nonBlockingBugUrls.map((url) => `
|