@qawolf/ci-sdk 0.10.2 → 0.11.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/CHANGELOG.md +21 -0
- package/README.md +23 -3
- package/dist/cjs/lib/sdk/domain/attempt-deploy.js +14 -9
- package/dist/cjs/lib/sdk/domain/poll-ci-greenlight.js +13 -13
- package/dist/cjs/lib/sdk/index.js +4 -5
- package/dist/esm/lib/sdk/domain/attempt-deploy.js +12 -7
- package/dist/esm/lib/sdk/domain/poll-ci-greenlight.js +13 -13
- package/dist/esm/lib/sdk/index.js +4 -5
- package/dist/types/lib/api/ci-greenlight.d.ts +53 -0
- package/dist/types/lib/sdk/dependencies.d.ts +0 -18
- package/dist/types/lib/sdk/domain/attempt-deploy.d.ts +18 -1
- package/dist/types/lib/sdk/domain/poll-ci-greenlight.d.ts +23 -1
- package/dist/types/lib/sdk/index.d.ts +3 -3
- package/package.json +1 -1
- package/dist/cjs/lib/sdk/job/default.js +0 -11
- package/dist/esm/lib/sdk/job/default.js +0 -8
- package/dist/types/lib/sdk/job/default.d.ts +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
# v0.11.0
|
|
2
|
+
|
|
3
|
+
- Support `reproducedBugs` field from CI-greenlight API.
|
|
4
|
+
|
|
5
|
+
> :warning: These are the last breaking changes brought to the 0.x major version.
|
|
6
|
+
> These are being introduced while the SDK hasn't been advertised to the public yet.
|
|
7
|
+
> Future changes will follow the SemVer versioning scheme.
|
|
8
|
+
|
|
9
|
+
BREAKING CHANGES:
|
|
10
|
+
|
|
11
|
+
- `pollCiGreenlightStatus` and `attemptNotifyDeploy` now return a "result" object
|
|
12
|
+
with an `outcome` field that can be either `"success"`, `"failed"` or `"aborted"`,
|
|
13
|
+
instead of exiting the process with a non-zero code. This will provide more
|
|
14
|
+
flexibility to the user to decide how to handle the outcome.
|
|
15
|
+
|
|
16
|
+
# v0.10.3
|
|
17
|
+
|
|
18
|
+
BREAKING CHANGES:
|
|
19
|
+
|
|
20
|
+
- Renamed `attemptDeploy` to `attemptNotifyDeploy`.
|
|
21
|
+
|
|
1
22
|
# v0.10.2
|
|
2
23
|
|
|
3
24
|
- Avoid logging dots after URL names in the logs. Dots can confuse terminal
|
package/README.md
CHANGED
|
@@ -8,6 +8,13 @@
|
|
|
8
8
|
This package provides a TypeScript (CSM and ESM compatible) SDK
|
|
9
9
|
to interact with the QAWolf Customer-facing API.
|
|
10
10
|
|
|
11
|
+
It exposes two functions associated with the two central endpoints, showcased in
|
|
12
|
+
the examples below.
|
|
13
|
+
|
|
14
|
+
Note that these functions do not throw. They yield a result object that
|
|
15
|
+
contains the outcome of the operation. This outcome should be scrutinized
|
|
16
|
+
to determine the status of your CI/CD step/job/action.
|
|
17
|
+
|
|
11
18
|
## Example: Trigger Run on Deployment
|
|
12
19
|
|
|
13
20
|
```ts
|
|
@@ -26,12 +33,17 @@ const deployConfig: DeployConfig = {
|
|
|
26
33
|
variables: undefined,
|
|
27
34
|
};
|
|
28
35
|
|
|
29
|
-
const {
|
|
36
|
+
const { attemptNotifyDeploy } = makeQaWolfSdk({
|
|
30
37
|
apiKey: "qawolf_xxxxx",
|
|
31
38
|
});
|
|
32
39
|
|
|
33
40
|
(async () => {
|
|
34
|
-
const
|
|
41
|
+
const result = await attemptNotifyDeploy(deployConfig);
|
|
42
|
+
if (result.outcome !== "success") {
|
|
43
|
+
// Fail the job.
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
const runId = result.runId;
|
|
35
47
|
// Store the runId as an output of the job to be used in a CI-greenlight job.
|
|
36
48
|
// This will depend on the CI platform you are using.
|
|
37
49
|
})();
|
|
@@ -48,7 +60,7 @@ const { pollCiGreenlightStatus } = makeQaWolfSdk({
|
|
|
48
60
|
|
|
49
61
|
(async () => {
|
|
50
62
|
// Retrieve runId from the previous job.
|
|
51
|
-
await pollCiGreenlightStatus({
|
|
63
|
+
const { outcome } = await pollCiGreenlightStatus({
|
|
52
64
|
runId,
|
|
53
65
|
// Optional: Callback to be called when the run stage changes.
|
|
54
66
|
// See https://qawolf.notion.site/dc42843313c246c8bf2a3a314ceb2c61 for
|
|
@@ -57,6 +69,14 @@ const { pollCiGreenlightStatus } = makeQaWolfSdk({
|
|
|
57
69
|
console.log(current, previous);
|
|
58
70
|
},
|
|
59
71
|
});
|
|
72
|
+
if (outcome !== "success") {
|
|
73
|
+
// Fail the job.
|
|
74
|
+
// This will depend on the CI platform you are using.
|
|
75
|
+
// You can also distinguish between "failed" and "aborted" outcomes.
|
|
76
|
+
// Only "failed" outcome indicates bugs were found.
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
// Continue CI.
|
|
60
80
|
})();
|
|
61
81
|
```
|
|
62
82
|
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.attemptNotifyDeploy = void 0;
|
|
4
4
|
const deploy_js_1 = require("../../api/deploy.js");
|
|
5
5
|
const utils_js_1 = require("../../utils.js");
|
|
6
|
-
async function
|
|
7
|
-
const {
|
|
6
|
+
async function attemptNotifyDeploy(deps, apiConfig, config) {
|
|
7
|
+
const { log } = deps;
|
|
8
8
|
const responseState = await (0, deploy_js_1.postDeploySuccess)(apiConfig, config, deps);
|
|
9
9
|
if (!responseState.success) {
|
|
10
10
|
if (responseState.failureReason === "no-matched-trigger") {
|
|
11
|
-
log.error(`🚫 No trigger matched the request
|
|
11
|
+
log.error(`🚫 No trigger matched the request. Please contact support.`);
|
|
12
|
+
return { outcome: "failed" };
|
|
12
13
|
}
|
|
13
14
|
else if (responseState.failureReason === "run-could-not-be-created") {
|
|
14
|
-
log.error(`🚫 Run could not be created
|
|
15
|
+
log.error(`🚫 Run could not be created. Reason: "${responseState.details}". Please contact support.`);
|
|
16
|
+
return { outcome: "failed" };
|
|
15
17
|
}
|
|
16
|
-
|
|
18
|
+
if (responseState.failureReason === "network-error")
|
|
17
19
|
log.error(`🚫 Network error from deploy_success, aborting.`);
|
|
18
20
|
else if (responseState.failureReason === "server-error")
|
|
19
21
|
log.error(`🚫 Server error from deploy_success (status ${responseState.httpStatus}), aborting. Please contact support.`);
|
|
@@ -29,9 +31,12 @@ async function attemptDeploy(deps, apiConfig, config) {
|
|
|
29
31
|
else {
|
|
30
32
|
(0, utils_js_1.assertType)(responseState);
|
|
31
33
|
}
|
|
32
|
-
return
|
|
34
|
+
return { outcome: "aborted" };
|
|
33
35
|
}
|
|
34
36
|
log.info(`✅ Run created with ID: ${responseState.runId}`);
|
|
35
|
-
return
|
|
37
|
+
return {
|
|
38
|
+
outcome: "success",
|
|
39
|
+
runId: responseState.runId,
|
|
40
|
+
};
|
|
36
41
|
}
|
|
37
|
-
exports.
|
|
42
|
+
exports.attemptNotifyDeploy = attemptNotifyDeploy;
|
|
@@ -11,7 +11,7 @@ const safeDefaults = {
|
|
|
11
11
|
};
|
|
12
12
|
async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChanged: onRunStageChanged = () => void 0, ...pollConfig }) {
|
|
13
13
|
let retries = 0;
|
|
14
|
-
const {
|
|
14
|
+
const { log } = deps;
|
|
15
15
|
const { maxRetries = safeDefaults.maxRetries, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, } = pollConfig;
|
|
16
16
|
let currentStatus = undefined;
|
|
17
17
|
while (true) {
|
|
@@ -20,25 +20,25 @@ async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChange
|
|
|
20
20
|
}, deps);
|
|
21
21
|
if (!responseState.ok && !responseState.canRetry) {
|
|
22
22
|
log.error(`🚫 Unrecoverable error (status ${responseState.httpStatus}) from CI greenlight, aborting.`);
|
|
23
|
-
return
|
|
23
|
+
return { outcome: "aborted" };
|
|
24
24
|
}
|
|
25
25
|
if (!responseState.ok) {
|
|
26
26
|
// This is a non-OK retryable status.
|
|
27
27
|
retries += 1;
|
|
28
28
|
if (retries > maxRetries) {
|
|
29
|
-
log.error(`🚫 Unrecoverable error
|
|
30
|
-
? `(status ${responseState.httpStatus})`
|
|
29
|
+
log.error(`🚫 Unrecoverable error${responseState.httpStatus
|
|
30
|
+
? ` (status ${responseState.httpStatus})`
|
|
31
31
|
: ""} from CI greenlight, aborting after ${maxRetries} attempts.`);
|
|
32
|
-
return
|
|
32
|
+
return { outcome: "aborted" };
|
|
33
33
|
}
|
|
34
34
|
const { errorType, httpStatus } = responseState;
|
|
35
|
-
const retryLabel = `${httpStatus ? `(status ${httpStatus})` : ""}, will try again... (${retries}/${maxRetries})`;
|
|
35
|
+
const retryLabel = `${httpStatus ? ` (status ${httpStatus})` : ""}, will try again... (${retries}/${maxRetries})`;
|
|
36
36
|
if (errorType === "network")
|
|
37
|
-
log.warn(`❌ Network error
|
|
37
|
+
log.warn(`❌ Network error${retryLabel}`);
|
|
38
38
|
else if (errorType === "not-found")
|
|
39
|
-
log.info(`⏳ Run not found
|
|
39
|
+
log.info(`⏳ Run not found${retryLabel}`);
|
|
40
40
|
else if (errorType === "server")
|
|
41
|
-
log.warn(`❌ Server error
|
|
41
|
+
log.warn(`❌ Server error${retryLabel}`);
|
|
42
42
|
await (0, utils_js_1.sleep)(retryInterval);
|
|
43
43
|
continue;
|
|
44
44
|
}
|
|
@@ -74,10 +74,10 @@ async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChange
|
|
|
74
74
|
? `\nNON BLOCKING BUGS:${nonBlockingBugList}`
|
|
75
75
|
: ""}`;
|
|
76
76
|
if (greenlight) {
|
|
77
|
-
log.info(`✅ Run passed and no blocking bugs found
|
|
77
|
+
log.info(`✅ Run passed and no blocking bugs found${nonBlockingBugsCount > 0
|
|
78
78
|
? ` and ${nonBlockingBugsCount} non-blocking bug${(0, utils_js_1.pluralize)(nonBlockingBugsCount)} found`
|
|
79
79
|
: ""}.\n${urlInfo}`);
|
|
80
|
-
return;
|
|
80
|
+
return { outcome: "success", greenlightStatus };
|
|
81
81
|
}
|
|
82
82
|
else {
|
|
83
83
|
log.warn(`❌ Run failed and ${blockingBugsCount} blocking bug${(0, utils_js_1.pluralize)(blockingBugsCount)} found${nonBlockingBugsCount
|
|
@@ -85,7 +85,7 @@ async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChange
|
|
|
85
85
|
: ""}.\nSee ${relevantRunWithBugsUrl}\n` +
|
|
86
86
|
"You may review the priority of certain bugs to mark these non-blocking and retry the job.\n" +
|
|
87
87
|
bugsListInText);
|
|
88
|
-
return
|
|
88
|
+
return { outcome: "failed", greenlightStatus };
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
if (runStage === "initializing") {
|
|
@@ -98,7 +98,7 @@ async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChange
|
|
|
98
98
|
}
|
|
99
99
|
else if (runStage === "canceled") {
|
|
100
100
|
log.info(`🚫 Run was canceled. Aborting... Please contact support.\n${urlInfo}`);
|
|
101
|
-
return
|
|
101
|
+
return { outcome: "aborted" };
|
|
102
102
|
}
|
|
103
103
|
else
|
|
104
104
|
throw new Error(`Unexpected run stage: ${runStage}`);
|
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.makeQaWolfSdk = void 0;
|
|
4
4
|
const attempt_deploy_js_1 = require("./domain/attempt-deploy.js");
|
|
5
|
-
const default_js_1 = require("./
|
|
6
|
-
const default_js_2 = require("./log/default.js");
|
|
5
|
+
const default_js_1 = require("./log/default.js");
|
|
7
6
|
const poll_ci_greenlight_js_1 = require("./domain/poll-ci-greenlight.js");
|
|
8
|
-
function makeQaWolfSdk({ apiKey, serviceBase = "https://app.qawolf.com/", }, {
|
|
9
|
-
const deps = {
|
|
7
|
+
function makeQaWolfSdk({ apiKey, serviceBase = "https://app.qawolf.com/", }, { log = default_js_1.defaultLogDriver, fetch = globalThis.fetch, } = {}) {
|
|
8
|
+
const deps = { log, fetch };
|
|
10
9
|
const apiConfig = { apiKey, serviceBase };
|
|
11
10
|
return {
|
|
12
|
-
|
|
11
|
+
attemptNotifyDeploy: attempt_deploy_js_1.attemptNotifyDeploy.bind(null, deps, apiConfig),
|
|
13
12
|
pollCiGreenlightStatus: poll_ci_greenlight_js_1.pollCiGreenlightStatus.bind(null, deps, apiConfig),
|
|
14
13
|
};
|
|
15
14
|
}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { postDeploySuccess } from "../../api/deploy.js";
|
|
2
2
|
import { assertType } from "../../utils.js";
|
|
3
|
-
export async function
|
|
4
|
-
const {
|
|
3
|
+
export async function attemptNotifyDeploy(deps, apiConfig, config) {
|
|
4
|
+
const { log } = deps;
|
|
5
5
|
const responseState = await postDeploySuccess(apiConfig, config, deps);
|
|
6
6
|
if (!responseState.success) {
|
|
7
7
|
if (responseState.failureReason === "no-matched-trigger") {
|
|
8
|
-
log.error(`🚫 No trigger matched the request
|
|
8
|
+
log.error(`🚫 No trigger matched the request. Please contact support.`);
|
|
9
|
+
return { outcome: "failed" };
|
|
9
10
|
}
|
|
10
11
|
else if (responseState.failureReason === "run-could-not-be-created") {
|
|
11
|
-
log.error(`🚫 Run could not be created
|
|
12
|
+
log.error(`🚫 Run could not be created. Reason: "${responseState.details}". Please contact support.`);
|
|
13
|
+
return { outcome: "failed" };
|
|
12
14
|
}
|
|
13
|
-
|
|
15
|
+
if (responseState.failureReason === "network-error")
|
|
14
16
|
log.error(`🚫 Network error from deploy_success, aborting.`);
|
|
15
17
|
else if (responseState.failureReason === "server-error")
|
|
16
18
|
log.error(`🚫 Server error from deploy_success (status ${responseState.httpStatus}), aborting. Please contact support.`);
|
|
@@ -26,8 +28,11 @@ export async function attemptDeploy(deps, apiConfig, config) {
|
|
|
26
28
|
else {
|
|
27
29
|
assertType(responseState);
|
|
28
30
|
}
|
|
29
|
-
return
|
|
31
|
+
return { outcome: "aborted" };
|
|
30
32
|
}
|
|
31
33
|
log.info(`✅ Run created with ID: ${responseState.runId}`);
|
|
32
|
-
return
|
|
34
|
+
return {
|
|
35
|
+
outcome: "success",
|
|
36
|
+
runId: responseState.runId,
|
|
37
|
+
};
|
|
33
38
|
}
|
|
@@ -8,7 +8,7 @@ const safeDefaults = {
|
|
|
8
8
|
};
|
|
9
9
|
export async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChanged: onRunStageChanged = () => void 0, ...pollConfig }) {
|
|
10
10
|
let retries = 0;
|
|
11
|
-
const {
|
|
11
|
+
const { log } = deps;
|
|
12
12
|
const { maxRetries = safeDefaults.maxRetries, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, } = pollConfig;
|
|
13
13
|
let currentStatus = undefined;
|
|
14
14
|
while (true) {
|
|
@@ -17,25 +17,25 @@ export async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStag
|
|
|
17
17
|
}, deps);
|
|
18
18
|
if (!responseState.ok && !responseState.canRetry) {
|
|
19
19
|
log.error(`🚫 Unrecoverable error (status ${responseState.httpStatus}) from CI greenlight, aborting.`);
|
|
20
|
-
return
|
|
20
|
+
return { outcome: "aborted" };
|
|
21
21
|
}
|
|
22
22
|
if (!responseState.ok) {
|
|
23
23
|
// This is a non-OK retryable status.
|
|
24
24
|
retries += 1;
|
|
25
25
|
if (retries > maxRetries) {
|
|
26
|
-
log.error(`🚫 Unrecoverable error
|
|
27
|
-
? `(status ${responseState.httpStatus})`
|
|
26
|
+
log.error(`🚫 Unrecoverable error${responseState.httpStatus
|
|
27
|
+
? ` (status ${responseState.httpStatus})`
|
|
28
28
|
: ""} from CI greenlight, aborting after ${maxRetries} attempts.`);
|
|
29
|
-
return
|
|
29
|
+
return { outcome: "aborted" };
|
|
30
30
|
}
|
|
31
31
|
const { errorType, httpStatus } = responseState;
|
|
32
|
-
const retryLabel = `${httpStatus ? `(status ${httpStatus})` : ""}, will try again... (${retries}/${maxRetries})`;
|
|
32
|
+
const retryLabel = `${httpStatus ? ` (status ${httpStatus})` : ""}, will try again... (${retries}/${maxRetries})`;
|
|
33
33
|
if (errorType === "network")
|
|
34
|
-
log.warn(`❌ Network error
|
|
34
|
+
log.warn(`❌ Network error${retryLabel}`);
|
|
35
35
|
else if (errorType === "not-found")
|
|
36
|
-
log.info(`⏳ Run not found
|
|
36
|
+
log.info(`⏳ Run not found${retryLabel}`);
|
|
37
37
|
else if (errorType === "server")
|
|
38
|
-
log.warn(`❌ Server error
|
|
38
|
+
log.warn(`❌ Server error${retryLabel}`);
|
|
39
39
|
await sleep(retryInterval);
|
|
40
40
|
continue;
|
|
41
41
|
}
|
|
@@ -71,10 +71,10 @@ export async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStag
|
|
|
71
71
|
? `\nNON BLOCKING BUGS:${nonBlockingBugList}`
|
|
72
72
|
: ""}`;
|
|
73
73
|
if (greenlight) {
|
|
74
|
-
log.info(`✅ Run passed and no blocking bugs found
|
|
74
|
+
log.info(`✅ Run passed and no blocking bugs found${nonBlockingBugsCount > 0
|
|
75
75
|
? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(nonBlockingBugsCount)} found`
|
|
76
76
|
: ""}.\n${urlInfo}`);
|
|
77
|
-
return;
|
|
77
|
+
return { outcome: "success", greenlightStatus };
|
|
78
78
|
}
|
|
79
79
|
else {
|
|
80
80
|
log.warn(`❌ Run failed and ${blockingBugsCount} blocking bug${pluralize(blockingBugsCount)} found${nonBlockingBugsCount
|
|
@@ -82,7 +82,7 @@ export async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStag
|
|
|
82
82
|
: ""}.\nSee ${relevantRunWithBugsUrl}\n` +
|
|
83
83
|
"You may review the priority of certain bugs to mark these non-blocking and retry the job.\n" +
|
|
84
84
|
bugsListInText);
|
|
85
|
-
return
|
|
85
|
+
return { outcome: "failed", greenlightStatus };
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
if (runStage === "initializing") {
|
|
@@ -95,7 +95,7 @@ export async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStag
|
|
|
95
95
|
}
|
|
96
96
|
else if (runStage === "canceled") {
|
|
97
97
|
log.info(`🚫 Run was canceled. Aborting... Please contact support.\n${urlInfo}`);
|
|
98
|
-
return
|
|
98
|
+
return { outcome: "aborted" };
|
|
99
99
|
}
|
|
100
100
|
else
|
|
101
101
|
throw new Error(`Unexpected run stage: ${runStage}`);
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { defaultJobDriver } from "./job/default.js";
|
|
1
|
+
import { attemptNotifyDeploy } from "./domain/attempt-deploy.js";
|
|
3
2
|
import { defaultLogDriver } from "./log/default.js";
|
|
4
3
|
import { pollCiGreenlightStatus } from "./domain/poll-ci-greenlight.js";
|
|
5
|
-
export function makeQaWolfSdk({ apiKey, serviceBase = "https://app.qawolf.com/", }, {
|
|
6
|
-
const deps = {
|
|
4
|
+
export function makeQaWolfSdk({ apiKey, serviceBase = "https://app.qawolf.com/", }, { log = defaultLogDriver, fetch = globalThis.fetch, } = {}) {
|
|
5
|
+
const deps = { log, fetch };
|
|
7
6
|
const apiConfig = { apiKey, serviceBase };
|
|
8
7
|
return {
|
|
9
|
-
|
|
8
|
+
attemptNotifyDeploy: attemptNotifyDeploy.bind(null, deps, apiConfig),
|
|
10
9
|
pollCiGreenlightStatus: pollCiGreenlightStatus.bind(null, deps, apiConfig),
|
|
11
10
|
};
|
|
12
11
|
}
|
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
import { ApiConfig } from "../api-types.js";
|
|
2
2
|
import { SdkDependencies } from "../sdk/dependencies.js";
|
|
3
|
+
export type CiGreenlightBugDetails = {
|
|
4
|
+
/**
|
|
5
|
+
* The URL of this BR in the QAWolf application.
|
|
6
|
+
*/
|
|
7
|
+
applicationUrl: string;
|
|
8
|
+
/**
|
|
9
|
+
* If this bug report is linked to an external issue, it will
|
|
10
|
+
* show up here.
|
|
11
|
+
*/
|
|
12
|
+
externalIssue: {
|
|
13
|
+
/**
|
|
14
|
+
* The URL of the external issue in the external platform
|
|
15
|
+
* application.
|
|
16
|
+
*/
|
|
17
|
+
applicationUrl: string;
|
|
18
|
+
/**
|
|
19
|
+
* The ID of this issue in the external platform.
|
|
20
|
+
*/
|
|
21
|
+
externalIssueId: string;
|
|
22
|
+
/**
|
|
23
|
+
* Lowercase platform name (e.g. "jira").
|
|
24
|
+
*/
|
|
25
|
+
platform: string;
|
|
26
|
+
} | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* True if the bug is blocking.
|
|
29
|
+
*/
|
|
30
|
+
isBlocking: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* True if the bug has been found in this run.
|
|
33
|
+
*/
|
|
34
|
+
isNew: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* The name of this bug.
|
|
37
|
+
*/
|
|
38
|
+
name: string;
|
|
39
|
+
/**
|
|
40
|
+
* The bug number.
|
|
41
|
+
*/
|
|
42
|
+
number: number;
|
|
43
|
+
/**
|
|
44
|
+
* The priority of this bug.
|
|
45
|
+
*/
|
|
46
|
+
priority: "medium" | "unprioritized" | "low" | "high" | "urgent";
|
|
47
|
+
};
|
|
48
|
+
export type CiGreenlightCompletedSuiteDetails = {
|
|
49
|
+
blockingBugsCount: number;
|
|
50
|
+
blockingBugUrls: string[];
|
|
51
|
+
nonBlockingBugsCount: number;
|
|
52
|
+
nonBlockingBugUrls: string[];
|
|
53
|
+
reproducedBugs: CiGreenlightBugDetails[];
|
|
54
|
+
};
|
|
3
55
|
export type CiGreenlightStatusBase = {
|
|
4
56
|
relevantRunId: string;
|
|
5
57
|
relevantRunUrl: string;
|
|
@@ -21,6 +73,7 @@ export type CiGreenlightStatus = CiGreenlightStatusBase & ({
|
|
|
21
73
|
nonBlockingBugsCount: number;
|
|
22
74
|
nonBlockingBugUrls: string[];
|
|
23
75
|
runStage: "completed";
|
|
76
|
+
reproducedBugs: CiGreenlightBugDetails[];
|
|
24
77
|
} | {
|
|
25
78
|
greenlight: false;
|
|
26
79
|
runStage: "initializing" | "underReview" | "canceled";
|
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
export interface JobDriver {
|
|
2
|
-
/**
|
|
3
|
-
* Called only when job completed and failed.
|
|
4
|
-
* **This method must exit the process or throw**.
|
|
5
|
-
*/
|
|
6
|
-
fail(): Promise<never>;
|
|
7
|
-
/**
|
|
8
|
-
* Called anywhere the job cannot continue and has to
|
|
9
|
-
* be aborted. **This method must exit the process or throw**.
|
|
10
|
-
*
|
|
11
|
-
* The main difference with "fail" is its semantics. For
|
|
12
|
-
* jobs performing tests, "fail" is called when the job
|
|
13
|
-
* completed and the tests yield a negative result.
|
|
14
|
-
* "abort" is called when the job could not complete.
|
|
15
|
-
*/
|
|
16
|
-
abort(): Promise<never>;
|
|
17
|
-
}
|
|
18
1
|
export interface LogDriver {
|
|
19
2
|
info(...messages: unknown[]): void;
|
|
20
3
|
warn(...messages: unknown[]): void;
|
|
@@ -22,7 +5,6 @@ export interface LogDriver {
|
|
|
22
5
|
}
|
|
23
6
|
export type FetchDriver = typeof fetch;
|
|
24
7
|
export type SdkDependencies = {
|
|
25
|
-
job: JobDriver;
|
|
26
8
|
log: LogDriver;
|
|
27
9
|
fetch: FetchDriver;
|
|
28
10
|
};
|
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
import { DeployConfig } from "../../api/deploy.js";
|
|
2
2
|
import { SdkDependencies } from "../dependencies.js";
|
|
3
3
|
import { ApiConfig } from "../../api-types.js";
|
|
4
|
-
export
|
|
4
|
+
export type NotifyDeployStatus = {
|
|
5
|
+
/**
|
|
6
|
+
* A run was successfully created.
|
|
7
|
+
*/
|
|
8
|
+
outcome: "success";
|
|
9
|
+
runId: string;
|
|
10
|
+
} | {
|
|
11
|
+
/**
|
|
12
|
+
* A run could not be created.
|
|
13
|
+
*/
|
|
14
|
+
outcome: "failed";
|
|
15
|
+
} | {
|
|
16
|
+
/**
|
|
17
|
+
* An unrecoverable error occurred.
|
|
18
|
+
*/
|
|
19
|
+
outcome: "aborted";
|
|
20
|
+
};
|
|
21
|
+
export declare function attemptNotifyDeploy(deps: SdkDependencies, apiConfig: ApiConfig, config: Partial<DeployConfig>): Promise<NotifyDeployStatus>;
|
|
@@ -7,6 +7,28 @@ export type PollConfig = {
|
|
|
7
7
|
runInProgressInterval: number;
|
|
8
8
|
runUnderReviewInterval: number;
|
|
9
9
|
};
|
|
10
|
+
export type PollCiGreenlightStatus = {
|
|
11
|
+
/**
|
|
12
|
+
* No blocking bugs were found in the run.
|
|
13
|
+
*/
|
|
14
|
+
outcome: "success";
|
|
15
|
+
greenlightStatus: Extract<CiGreenlightStatus, {
|
|
16
|
+
runStage: "completed";
|
|
17
|
+
}>;
|
|
18
|
+
} | {
|
|
19
|
+
/**
|
|
20
|
+
* Blocking bugs were found in the run.
|
|
21
|
+
*/
|
|
22
|
+
outcome: "failed";
|
|
23
|
+
greenlightStatus: Extract<CiGreenlightStatus, {
|
|
24
|
+
runStage: "completed";
|
|
25
|
+
}>;
|
|
26
|
+
} | {
|
|
27
|
+
/**
|
|
28
|
+
* The run was aborted due to an unrecoverable error.
|
|
29
|
+
*/
|
|
30
|
+
outcome: "aborted";
|
|
31
|
+
};
|
|
10
32
|
export type PollCiGreenlightParams = {
|
|
11
33
|
runId: string;
|
|
12
34
|
/**
|
|
@@ -14,4 +36,4 @@ export type PollCiGreenlightParams = {
|
|
|
14
36
|
*/
|
|
15
37
|
onRunStageChanged?: (current: CiGreenlightStatus, previous: CiGreenlightStatus | undefined) => unknown | Promise<unknown>;
|
|
16
38
|
} & Partial<PollConfig>;
|
|
17
|
-
export declare function pollCiGreenlightStatus(deps: SdkDependencies, apiConfig: ApiConfig, { runId, onRunStageChanged: onRunStageChanged, ...pollConfig }: PollCiGreenlightParams): Promise<
|
|
39
|
+
export declare function pollCiGreenlightStatus(deps: SdkDependencies, apiConfig: ApiConfig, { runId, onRunStageChanged: onRunStageChanged, ...pollConfig }: PollCiGreenlightParams): Promise<PollCiGreenlightStatus>;
|
|
@@ -2,7 +2,7 @@ import { SdkDependencies } from "./dependencies.js";
|
|
|
2
2
|
export declare function makeQaWolfSdk({ apiKey, serviceBase, }: {
|
|
3
3
|
apiKey: string;
|
|
4
4
|
serviceBase?: string;
|
|
5
|
-
}, {
|
|
6
|
-
|
|
7
|
-
pollCiGreenlightStatus: (args_0: import("./domain/poll-ci-greenlight.js").PollCiGreenlightParams) => Promise<
|
|
5
|
+
}, { log, fetch, }?: Partial<SdkDependencies>): {
|
|
6
|
+
attemptNotifyDeploy: (config: Partial<import("../api/deploy.js").DeployConfig>) => Promise<import("./domain/attempt-deploy.js").NotifyDeployStatus>;
|
|
7
|
+
pollCiGreenlightStatus: (args_0: import("./domain/poll-ci-greenlight.js").PollCiGreenlightParams) => Promise<import("./domain/poll-ci-greenlight.js").PollCiGreenlightStatus>;
|
|
8
8
|
};
|
package/package.json
CHANGED