@qawolf/ci-sdk 3.0.0 → 3.2.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 +338 -10
- package/dist/index.d.ts +1 -0
- package/dist/index.js +644 -4
- package/dist/index.js.map +4 -4
- package/dist/lib/sdk/defaults/clock.d.ts +2 -0
- package/dist/lib/sdk/dependencies.d.ts +9 -0
- package/dist/lib/sdk/domain/attemptDeploy/index.d.ts +4 -0
- package/dist/lib/sdk/domain/detectProviderDeploymentId/index.d.ts +49 -0
- package/dist/lib/sdk/domain/pollCiGreenlight/index.d.ts +4 -0
- package/dist/lib/sdk/domain/reportDeployment/index.d.ts +4 -0
- package/dist/lib/sdk/domain/reportDeployment/types.d.ts +50 -0
- package/dist/lib/sdk/domain/waitForVerdict/awaitRuns.d.ts +14 -0
- package/dist/lib/sdk/domain/waitForVerdict/awaitVerdict.d.ts +12 -0
- package/dist/lib/sdk/domain/waitForVerdict/consts.d.ts +13 -0
- package/dist/lib/sdk/domain/waitForVerdict/failures.d.ts +14 -0
- package/dist/lib/sdk/domain/waitForVerdict/index.d.ts +12 -0
- package/dist/lib/sdk/domain/waitForVerdict/logVerdict.d.ts +3 -0
- package/dist/lib/sdk/domain/waitForVerdict/poll.d.ts +20 -0
- package/dist/lib/sdk/domain/waitForVerdict/progress.d.ts +7 -0
- package/dist/lib/sdk/domain/waitForVerdict/readEvaluations.d.ts +20 -0
- package/dist/lib/sdk/domain/waitForVerdict/testHarness.d.ts +53 -0
- package/dist/lib/sdk/domain/waitForVerdict/types.d.ts +48 -0
- package/dist/lib/sdk/index.d.ts +130 -1
- package/dist/lib/sdk/publicApi/callContract.d.ts +39 -0
- package/package.json +6 -4
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { ApiConfig } from "../../../api-types.js";
|
|
2
2
|
import type { SdkDependencies } from "../../dependencies.js";
|
|
3
3
|
import type { PollCiGreenlightParams, PollCiGreenlightStatus } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated Polls a run id that only `attemptNotifyDeploy` returns, so it
|
|
6
|
+
* keeps the pipeline on the legacy `deploy_success` webhook.
|
|
7
|
+
*/
|
|
4
8
|
export declare function pollCiGreenlightStatus(deps: SdkDependencies, apiConfig: ApiConfig, { onRunStageChanged, runId, ...pollConfig }: PollCiGreenlightParams): Promise<PollCiGreenlightStatus>;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ApiConfig } from "../../../api-types.js";
|
|
2
|
+
import type { SdkDependencies } from "../../dependencies.js";
|
|
3
|
+
import type { ReportDeploymentParams, ReportDeploymentResult } from "./types.js";
|
|
4
|
+
export declare function reportDeployment(deps: SdkDependencies, apiConfig: ApiConfig, params: ReportDeploymentParams): Promise<ReportDeploymentResult>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { PublicApiInput, PublicApiOutput, publicContractsV1 } from "@qawolf/api-contracts";
|
|
2
|
+
export type ReportDeploymentParams = PublicApiInput<typeof publicContractsV1.deployment.reportStatus>;
|
|
3
|
+
/**
|
|
4
|
+
* The deployment the report created or updated, exactly as the
|
|
5
|
+
* `deployment.reportStatus` contract describes it.
|
|
6
|
+
*/
|
|
7
|
+
export type ReportedDeployment = PublicApiOutput<typeof publicContractsV1.deployment.reportStatus>["deployment"];
|
|
8
|
+
export type ReportDeploymentResult = {
|
|
9
|
+
deployment: ReportedDeployment;
|
|
10
|
+
outcome: "reported";
|
|
11
|
+
}
|
|
12
|
+
/** The report did not satisfy the contract. HTTP 400. */
|
|
13
|
+
| {
|
|
14
|
+
message: string | undefined;
|
|
15
|
+
outcome: "invalid-request";
|
|
16
|
+
}
|
|
17
|
+
/** The API key is unknown, or may not act on this workspace. HTTP 401 and 403. */
|
|
18
|
+
| {
|
|
19
|
+
message: string | undefined;
|
|
20
|
+
outcome: "unauthorized";
|
|
21
|
+
}
|
|
22
|
+
/** The workspace or environment named in the report does not exist. HTTP 404. */
|
|
23
|
+
| {
|
|
24
|
+
message: string | undefined;
|
|
25
|
+
outcome: "not-found";
|
|
26
|
+
}
|
|
27
|
+
/** The providerDeploymentId is already bound to a different environment. HTTP 409. */
|
|
28
|
+
| {
|
|
29
|
+
message: string | undefined;
|
|
30
|
+
outcome: "conflict";
|
|
31
|
+
}
|
|
32
|
+
/** QA Wolf failed to record the report; retrying is reasonable. HTTP 5XX. */
|
|
33
|
+
| {
|
|
34
|
+
httpStatus: number;
|
|
35
|
+
outcome: "server-error";
|
|
36
|
+
}
|
|
37
|
+
/** A status this SDK version does not map, carrying what the server sent. */
|
|
38
|
+
| {
|
|
39
|
+
httpStatus: number;
|
|
40
|
+
message: string | undefined;
|
|
41
|
+
outcome: "unexpected-status";
|
|
42
|
+
}
|
|
43
|
+
/** The request never reached QA Wolf, or the connection dropped. */
|
|
44
|
+
| {
|
|
45
|
+
outcome: "network-error";
|
|
46
|
+
}
|
|
47
|
+
/** The server answered 2xx with a body the contract's output rejects. */
|
|
48
|
+
| {
|
|
49
|
+
outcome: "invalid-response-body";
|
|
50
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DeploymentVerdict, MatchedRun, WaitContext } from "./types.js";
|
|
2
|
+
export type RunsFound = {
|
|
3
|
+
kind: "runs";
|
|
4
|
+
runs: MatchedRun[];
|
|
5
|
+
};
|
|
6
|
+
type Phase = DeploymentVerdict | RunsFound;
|
|
7
|
+
/**
|
|
8
|
+
* Polls the deployment's trigger evaluations until they name the runs that
|
|
9
|
+
* answer for it, or until it is clear nothing will run. Bounded by
|
|
10
|
+
* `runAppearanceTimeout`: a trigger that never resolves does not hold up the
|
|
11
|
+
* runs that did start.
|
|
12
|
+
*/
|
|
13
|
+
export declare function awaitRuns(ctx: WaitContext): Promise<Phase>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DeploymentVerdict, MatchedRun, VerdictRun, WaitContext } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The whole-deployment answer: one failing run fails the deployment, and a
|
|
4
|
+
* cancellation means QA Wolf reached no verdict rather than that it passed.
|
|
5
|
+
*
|
|
6
|
+
* A deployment is expected to resolve to exactly one run; the fold over several
|
|
7
|
+
* is a guard, so that a violation of that expectation cannot be reported as
|
|
8
|
+
* passing. It assumes superseded runs have already been resolved away to the
|
|
9
|
+
* run that replaced them, because an abandoned run can itself report failed.
|
|
10
|
+
*/
|
|
11
|
+
export declare function aggregateRuns(deploymentId: string, runs: VerdictRun[]): DeploymentVerdict;
|
|
12
|
+
export declare function awaitVerdict(ctx: WaitContext, matched: MatchedRun[]): Promise<DeploymentVerdict>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If you change these, update the JSDoc on `WaitForVerdictConfig` with them.
|
|
3
|
+
* The whole-operation budget matches the legacy `pollCiGreenlightStatus`
|
|
4
|
+
* `pollTimeout`, so moving off that function does not also move the default.
|
|
5
|
+
*/
|
|
6
|
+
export declare const waitForVerdictDefaults: {
|
|
7
|
+
maxRetries: number;
|
|
8
|
+
retryInterval: number;
|
|
9
|
+
runAppearanceTimeout: number;
|
|
10
|
+
runPollInterval: number;
|
|
11
|
+
timeout: number;
|
|
12
|
+
triggerPollInterval: number;
|
|
13
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PublicApiCallFailure } from "../../publicApi/callContract.js";
|
|
2
|
+
import type { DeploymentVerdict } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* How the wait should answer a failed call: retry it until the budget runs
|
|
5
|
+
* out, or stop on a refusal that retrying cannot change.
|
|
6
|
+
*/
|
|
7
|
+
export type FailureHandling = {
|
|
8
|
+
exhaustedVerdict: DeploymentVerdict;
|
|
9
|
+
kind: "retry";
|
|
10
|
+
} | {
|
|
11
|
+
kind: "stop";
|
|
12
|
+
verdict: DeploymentVerdict;
|
|
13
|
+
};
|
|
14
|
+
export declare function handleCallFailure(failure: PublicApiCallFailure, deploymentId: string): FailureHandling;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ApiConfig } from "../../../api-types.js";
|
|
2
|
+
import type { SdkDependencies } from "../../dependencies.js";
|
|
3
|
+
import type { DeploymentVerdict, WaitForVerdictParams } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Blocks until QA Wolf can say whether a deployment's tests passed.
|
|
6
|
+
*
|
|
7
|
+
* It takes only the deployment id the report gave back: resolving that to the
|
|
8
|
+
* runs its triggers created, and those runs to a status, stays inside. Nothing
|
|
9
|
+
* throws — a refusal, a dead network, a cancellation and an exhausted budget
|
|
10
|
+
* are all arms of the returned verdict.
|
|
11
|
+
*/
|
|
12
|
+
export declare function waitForVerdict(deps: SdkDependencies, apiConfig: ApiConfig, { deploymentId, maxRetries, onProgress, retryInterval, runAppearanceTimeout, runPollInterval, signal, timeout, triggerPollInterval, }: WaitForVerdictParams): Promise<DeploymentVerdict>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PublicApiCallResult } from "../../publicApi/callContract.js";
|
|
2
|
+
import type { DeploymentVerdict, WaitContext } from "./types.js";
|
|
3
|
+
export type PollStep<Result> = {
|
|
4
|
+
intervalMs: number;
|
|
5
|
+
kind: "continue";
|
|
6
|
+
} | {
|
|
7
|
+
kind: "done";
|
|
8
|
+
result: Result;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Repeats one public API call until it answers something terminal, the caller
|
|
12
|
+
* hangs up, or the deadline passes. Nothing here throws: a refusal, a dead
|
|
13
|
+
* network and an exhausted budget are all verdicts the caller receives.
|
|
14
|
+
*/
|
|
15
|
+
export declare function pollUntil<Data, Result>(ctx: WaitContext, { deadlineAt, onData, onDeadline, request, }: {
|
|
16
|
+
deadlineAt: number;
|
|
17
|
+
onData: (data: Data) => Promise<PollStep<Result>>;
|
|
18
|
+
onDeadline: () => DeploymentVerdict | Result;
|
|
19
|
+
request: () => Promise<PublicApiCallResult<Data>>;
|
|
20
|
+
}): Promise<DeploymentVerdict | Result>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { VerdictStage, WaitContext } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Reports a stage once, when it differs from the one before it. The log line
|
|
4
|
+
* is the identity of a stage, so a run that keeps executing does not repeat
|
|
5
|
+
* itself in the build log.
|
|
6
|
+
*/
|
|
7
|
+
export declare function reportStage(ctx: WaitContext, previousDescription: string | undefined, stage: VerdictStage): Promise<string>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PublicApiOutput, publicContractsV1 } from "@qawolf/api-contracts";
|
|
2
|
+
import type { MatchedRun, NotTestedReason, TriggerNote } from "./types.js";
|
|
3
|
+
export type TriggerEvaluations = PublicApiOutput<typeof publicContractsV1.deployment.listTriggerEvaluations>;
|
|
4
|
+
export type EvaluationReading = {
|
|
5
|
+
kind: "not-evaluated";
|
|
6
|
+
}
|
|
7
|
+
/** Some trigger is still creating a run; `runs` are the ones already known. */
|
|
8
|
+
| {
|
|
9
|
+
kind: "awaiting-run";
|
|
10
|
+
matchedTriggerCount: number;
|
|
11
|
+
runs: MatchedRun[];
|
|
12
|
+
} | {
|
|
13
|
+
kind: "runs";
|
|
14
|
+
runs: MatchedRun[];
|
|
15
|
+
} | {
|
|
16
|
+
kind: "not-tested";
|
|
17
|
+
reason: NotTestedReason;
|
|
18
|
+
triggers: TriggerNote[];
|
|
19
|
+
};
|
|
20
|
+
export declare function readEvaluations(evaluations: TriggerEvaluations): EvaluationReading;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { ApiConfig } from "../../../api-types.js";
|
|
2
|
+
import type { SdkDependencies } from "../../dependencies.js";
|
|
3
|
+
export type Reply = {
|
|
4
|
+
body: unknown;
|
|
5
|
+
status: number;
|
|
6
|
+
} | {
|
|
7
|
+
kind: "network-error";
|
|
8
|
+
};
|
|
9
|
+
export declare function ok(payload: unknown): Reply;
|
|
10
|
+
export declare function httpError(status: number, message: string): Reply;
|
|
11
|
+
export declare const networkError: Reply;
|
|
12
|
+
export declare function evaluated(evaluations: unknown[]): Reply;
|
|
13
|
+
export declare const notEvaluated: Reply;
|
|
14
|
+
export declare function matchedTrigger(run: unknown, triggerName?: string): unknown;
|
|
15
|
+
export declare function unmatchedTrigger(reason: string, triggerName?: string): {
|
|
16
|
+
triggerName: string;
|
|
17
|
+
verdict: {
|
|
18
|
+
conditionSets: {
|
|
19
|
+
conditions: {
|
|
20
|
+
kind: string;
|
|
21
|
+
outcome: string;
|
|
22
|
+
reason: string;
|
|
23
|
+
}[];
|
|
24
|
+
outcome: string;
|
|
25
|
+
}[];
|
|
26
|
+
outcome: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export declare function runPayload({ blockingBugCount, runId, status, }: {
|
|
30
|
+
blockingBugCount?: number;
|
|
31
|
+
runId?: string;
|
|
32
|
+
status: string;
|
|
33
|
+
}): unknown;
|
|
34
|
+
/**
|
|
35
|
+
* A fetch that answers each contract from its own queue, holding on the last
|
|
36
|
+
* reply once a queue runs out, plus a clock that only moves when the SDK
|
|
37
|
+
* sleeps. Together they let a test walk a two-hour poll in milliseconds and
|
|
38
|
+
* count exactly how many times the SDK asked. `runs` is one queue shared by
|
|
39
|
+
* every run, or a queue per requested run id when a test needs to tell two
|
|
40
|
+
* runs apart.
|
|
41
|
+
*/
|
|
42
|
+
export declare function makeHarness({ evaluations, runs, }: {
|
|
43
|
+
evaluations?: Reply[];
|
|
44
|
+
runs?: Record<string, Reply[]> | Reply[];
|
|
45
|
+
}): {
|
|
46
|
+
apiConfig: ApiConfig;
|
|
47
|
+
calls: {
|
|
48
|
+
evaluations: number;
|
|
49
|
+
runs: number;
|
|
50
|
+
};
|
|
51
|
+
deps: SdkDependencies;
|
|
52
|
+
fetch: import("jest-mock").Mock<(url: unknown, init: unknown) => Promise<Response>>;
|
|
53
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { DeploymentVerdict, NotTestedReason, TriggerNote, VerdictRun, VerdictStage } from "@qawolf/api-contracts";
|
|
2
|
+
import type { ApiConfig } from "../../../api-types.js";
|
|
3
|
+
import type { SdkDependencies } from "../../dependencies.js";
|
|
4
|
+
export type { DeploymentVerdict, NotTestedReason, TriggerNote, VerdictRun, VerdictStage, };
|
|
5
|
+
export type WaitForVerdictConfig = {
|
|
6
|
+
/** Network and server-error retries before giving up. @default 10 */
|
|
7
|
+
maxRetries: number;
|
|
8
|
+
/** Fired on every stage change, for CI logs. */
|
|
9
|
+
onProgress: (stage: VerdictStage) => unknown | Promise<unknown>;
|
|
10
|
+
/** Between retries of a failed call. @default 10s */
|
|
11
|
+
retryInterval: number;
|
|
12
|
+
/**
|
|
13
|
+
* Give up if no trigger has produced a run by then. Runs that did appear are
|
|
14
|
+
* still waited on. @default 5min
|
|
15
|
+
*/
|
|
16
|
+
runAppearanceTimeout: number;
|
|
17
|
+
/** Between polls while a run executes. @default 30s */
|
|
18
|
+
runPollInterval: number;
|
|
19
|
+
/** Cancels the wait; yields `outcome: "canceled-by-caller"`. */
|
|
20
|
+
signal: AbortSignal;
|
|
21
|
+
/**
|
|
22
|
+
* Whole-operation budget. Set it below the CI job's own ceiling, so the wait
|
|
23
|
+
* ends with a run URL and a stage instead of the job being killed.
|
|
24
|
+
* @default 2h
|
|
25
|
+
*/
|
|
26
|
+
timeout: number;
|
|
27
|
+
/** Between polls while a trigger is still producing a run. @default 3s */
|
|
28
|
+
triggerPollInterval: number;
|
|
29
|
+
};
|
|
30
|
+
export type WaitForVerdictParams = {
|
|
31
|
+
deploymentId: string;
|
|
32
|
+
} & Partial<WaitForVerdictConfig>;
|
|
33
|
+
export type ResolvedWaitConfig = Omit<WaitForVerdictConfig, "onProgress" | "signal"> & {
|
|
34
|
+
onProgress: ((stage: VerdictStage) => unknown | Promise<unknown>) | undefined;
|
|
35
|
+
signal: AbortSignal | undefined;
|
|
36
|
+
};
|
|
37
|
+
export type WaitContext = {
|
|
38
|
+
apiConfig: ApiConfig;
|
|
39
|
+
config: ResolvedWaitConfig;
|
|
40
|
+
deploymentId: string;
|
|
41
|
+
deps: SdkDependencies;
|
|
42
|
+
startedAt: number;
|
|
43
|
+
};
|
|
44
|
+
/** A run one trigger created, before its status is known. */
|
|
45
|
+
export type MatchedRun = {
|
|
46
|
+
runId: string;
|
|
47
|
+
triggerName: string;
|
|
48
|
+
};
|
package/dist/lib/sdk/index.d.ts
CHANGED
|
@@ -3,8 +3,131 @@ export declare function makeQaWolfSdk({ apiKey, serviceBase, userAgent, }: {
|
|
|
3
3
|
apiKey: string;
|
|
4
4
|
serviceBase?: string;
|
|
5
5
|
userAgent?: string;
|
|
6
|
-
}, { fetch, log, }?: Partial<SdkDependencies>): {
|
|
6
|
+
}, { clock, fetch, log, }?: Partial<SdkDependencies>): {
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated Reports through the legacy `deploy_success` webhook, which
|
|
9
|
+
* triggers do not see. Use `deployment.reportStatus` instead.
|
|
10
|
+
*/
|
|
7
11
|
attemptNotifyDeploy: (config: Partial<import("./domain/attemptDeploy/deployConfig.js").DeployConfig>) => Promise<import("./domain/attemptDeploy/types.js").NotifyDeployStatus>;
|
|
12
|
+
deployment: {
|
|
13
|
+
reportStatus: (params: {
|
|
14
|
+
providerDeploymentId: string;
|
|
15
|
+
status: "success" | "pending" | "failure" | "inactive";
|
|
16
|
+
workspaceId: string;
|
|
17
|
+
deployTarget?: string | undefined;
|
|
18
|
+
environment?: {
|
|
19
|
+
id: string;
|
|
20
|
+
} | {
|
|
21
|
+
name: string;
|
|
22
|
+
baseEphemeralEnvironment?: string | undefined;
|
|
23
|
+
ephemeral?: boolean | undefined;
|
|
24
|
+
} | undefined;
|
|
25
|
+
environmentVariables?: Record<string, string> | undefined;
|
|
26
|
+
metadata?: {
|
|
27
|
+
commitAuthorName?: string | undefined;
|
|
28
|
+
commitMessage?: string | undefined;
|
|
29
|
+
commitSha?: string | undefined;
|
|
30
|
+
commitUrl?: string | undefined;
|
|
31
|
+
pullRequestNumber?: number | undefined;
|
|
32
|
+
ref?: string | undefined;
|
|
33
|
+
repository?: string | undefined;
|
|
34
|
+
} | undefined;
|
|
35
|
+
service?: string | undefined;
|
|
36
|
+
}) => Promise<import("./domain/reportDeployment/types.js").ReportDeploymentResult>;
|
|
37
|
+
waitForVerdict: (args_0: import("./domain/waitForVerdict/types.js").WaitForVerdictParams) => Promise<{
|
|
38
|
+
deploymentId: string;
|
|
39
|
+
outcome: "passed";
|
|
40
|
+
runs: {
|
|
41
|
+
blockingBugCount: number;
|
|
42
|
+
runId: string;
|
|
43
|
+
runUrl: string;
|
|
44
|
+
status: "canceled" | "failed" | "passed" | "queued" | "running";
|
|
45
|
+
triggerName: string;
|
|
46
|
+
}[];
|
|
47
|
+
} | {
|
|
48
|
+
blockingBugCount: number;
|
|
49
|
+
deploymentId: string;
|
|
50
|
+
outcome: "failed";
|
|
51
|
+
runs: {
|
|
52
|
+
blockingBugCount: number;
|
|
53
|
+
runId: string;
|
|
54
|
+
runUrl: string;
|
|
55
|
+
status: "canceled" | "failed" | "passed" | "queued" | "running";
|
|
56
|
+
triggerName: string;
|
|
57
|
+
}[];
|
|
58
|
+
} | {
|
|
59
|
+
deploymentId: string;
|
|
60
|
+
outcome: "not-tested";
|
|
61
|
+
reason: "no-trigger-matched" | "no-run-created";
|
|
62
|
+
triggers: {
|
|
63
|
+
message: string;
|
|
64
|
+
triggerName: string;
|
|
65
|
+
reason?: "skipped" | "billing-prevented" | "branch-still-syncing" | "deployment-no-longer-live" | "duplicate-run" | "environment-not-linked-to-branch" | "environment-not-ready" | "environment-terminated" | "internal-error" | "low-risk-change" | "no-flows-to-run" | "no-matching-trigger" | "no-pull-request" | "no-relevant-flows" | "rate-limited" | "run-not-created" | "test-configuration-error" | "trigger-not-found" | "workspace-inactive" | "workspace-not-ready" | undefined;
|
|
66
|
+
}[];
|
|
67
|
+
} | {
|
|
68
|
+
deploymentId: string;
|
|
69
|
+
outcome: "run-canceled";
|
|
70
|
+
runs: {
|
|
71
|
+
blockingBugCount: number;
|
|
72
|
+
runId: string;
|
|
73
|
+
runUrl: string;
|
|
74
|
+
status: "canceled" | "failed" | "passed" | "queued" | "running";
|
|
75
|
+
triggerName: string;
|
|
76
|
+
}[];
|
|
77
|
+
} | {
|
|
78
|
+
deploymentId: string;
|
|
79
|
+
elapsedMs: number;
|
|
80
|
+
lastStage: {
|
|
81
|
+
stage: "waiting-for-evaluation";
|
|
82
|
+
} | {
|
|
83
|
+
matchedTriggerCount: number;
|
|
84
|
+
stage: "waiting-for-run";
|
|
85
|
+
} | {
|
|
86
|
+
runs: {
|
|
87
|
+
blockingBugCount: number;
|
|
88
|
+
runId: string;
|
|
89
|
+
runUrl: string;
|
|
90
|
+
status: "canceled" | "failed" | "passed" | "queued" | "running";
|
|
91
|
+
triggerName: string;
|
|
92
|
+
}[];
|
|
93
|
+
stage: "waiting-for-verdict";
|
|
94
|
+
};
|
|
95
|
+
outcome: "timed-out";
|
|
96
|
+
runs: {
|
|
97
|
+
blockingBugCount: number;
|
|
98
|
+
runId: string;
|
|
99
|
+
runUrl: string;
|
|
100
|
+
status: "canceled" | "failed" | "passed" | "queued" | "running";
|
|
101
|
+
triggerName: string;
|
|
102
|
+
}[];
|
|
103
|
+
} | {
|
|
104
|
+
deploymentId: string;
|
|
105
|
+
outcome: "canceled-by-caller";
|
|
106
|
+
} | {
|
|
107
|
+
deploymentId: string;
|
|
108
|
+
outcome: "unauthorized";
|
|
109
|
+
message?: string | undefined;
|
|
110
|
+
} | {
|
|
111
|
+
deploymentId: string;
|
|
112
|
+
outcome: "not-found";
|
|
113
|
+
message?: string | undefined;
|
|
114
|
+
} | {
|
|
115
|
+
deploymentId: string;
|
|
116
|
+
httpStatus: number;
|
|
117
|
+
outcome: "server-error";
|
|
118
|
+
} | {
|
|
119
|
+
deploymentId: string;
|
|
120
|
+
httpStatus: number;
|
|
121
|
+
outcome: "unexpected-status";
|
|
122
|
+
message?: string | undefined;
|
|
123
|
+
} | {
|
|
124
|
+
deploymentId: string;
|
|
125
|
+
outcome: "network-error";
|
|
126
|
+
} | {
|
|
127
|
+
deploymentId: string;
|
|
128
|
+
outcome: "invalid-response-body";
|
|
129
|
+
}>;
|
|
130
|
+
};
|
|
8
131
|
generateSignedUrlForRunInputsExecutablesStorage: (config: import("./domain/generateSignedUrls/types.js").GenerateSignedUrlConfig) => Promise<import("./domain/generateSignedUrls/types.js").GenerateSignedUrlStatus>;
|
|
9
132
|
generateSignedUrlForTempTeamStorage: (config: import("./domain/generateSignedUrls/types.js").GenerateSignedUrlConfig) => Promise<{
|
|
10
133
|
fileLocation?: string;
|
|
@@ -19,9 +142,15 @@ export declare function makeQaWolfSdk({ apiKey, serviceBase, userAgent, }: {
|
|
|
19
142
|
}>;
|
|
20
143
|
makePollCiGreenlightStatusIterator: (args_0: import("./domain/pollCiGreenlight/types.js").MakePollCiGreenlightStatusIteratorParams) => AsyncGenerator<import("./domain/pollCiGreenlight/types.js").PollCiGreenlightIteration, void, unknown>;
|
|
21
144
|
notifyTerminatedEphemeralEnvironment: (config: import("./domain/notifyTerminatedEphemeralEnvironment/types.js").NotifyTerminatedEphemeralEnvironmentInput) => Promise<import("./domain/notifyTerminatedEphemeralEnvironment/types.js").NotifyTerminatedEphemeralEnvironmentResult>;
|
|
145
|
+
/**
|
|
146
|
+
* @deprecated Polls a run id that only `attemptNotifyDeploy` returns, so it
|
|
147
|
+
* keeps the pipeline on the legacy `deploy_success` webhook.
|
|
148
|
+
*/
|
|
22
149
|
pollCiGreenlightStatus: (args_0: import("./domain/pollCiGreenlight/types.js").PollCiGreenlightParams) => Promise<import("./domain/pollCiGreenlight/types.js").PollCiGreenlightStatus>;
|
|
23
150
|
};
|
|
24
151
|
export type * from "./domain/attemptDeploy/index.js";
|
|
25
152
|
export type * from "./domain/generateSignedUrls/types.js";
|
|
26
153
|
export type * from "./domain/notifyTerminatedEphemeralEnvironment/types.js";
|
|
27
154
|
export type * from "./domain/pollCiGreenlight/types.js";
|
|
155
|
+
export type * from "./domain/reportDeployment/types.js";
|
|
156
|
+
export type * from "./domain/waitForVerdict/types.js";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { ApiConfig } from "../../api-types.js";
|
|
3
|
+
import type { SdkDependencies } from "../dependencies.js";
|
|
4
|
+
/**
|
|
5
|
+
* The structural shape of a `@qawolf/api-contracts` contract. Declared here
|
|
6
|
+
* because the package exports the contracts but not the type describing them.
|
|
7
|
+
*/
|
|
8
|
+
export type PublicApiContract<InputData = unknown, OutputData = unknown> = {
|
|
9
|
+
input: z.ZodType<unknown, InputData>;
|
|
10
|
+
name: string;
|
|
11
|
+
output: z.ZodType<OutputData>;
|
|
12
|
+
};
|
|
13
|
+
export type PublicApiCallFailure = {
|
|
14
|
+
/** The QA Wolf incident id to quote to support, when the server sent one. */
|
|
15
|
+
eventId: string | undefined;
|
|
16
|
+
httpStatus: number;
|
|
17
|
+
/** The server's explanation of the refusal, when it sent one. */
|
|
18
|
+
message: string | undefined;
|
|
19
|
+
outcome: "http-error";
|
|
20
|
+
} | {
|
|
21
|
+
outcome: "network-error";
|
|
22
|
+
}
|
|
23
|
+
/** The server answered 2xx with a body the contract's output rejects. */
|
|
24
|
+
| {
|
|
25
|
+
outcome: "invalid-response-body";
|
|
26
|
+
};
|
|
27
|
+
export type PublicApiCallResult<Data> = {
|
|
28
|
+
data: Data;
|
|
29
|
+
outcome: "ok";
|
|
30
|
+
} | PublicApiCallFailure;
|
|
31
|
+
/**
|
|
32
|
+
* Calls one public API contract and validates the answer with that contract's
|
|
33
|
+
* own output schema, so a caller reads the contract's types rather than a
|
|
34
|
+
* hand-written copy of them.
|
|
35
|
+
*/
|
|
36
|
+
export declare function callPublicContract<InputData, OutputData>({ fetch: localFetch, log }: SdkDependencies, apiConfig: ApiConfig, { contract, input, }: {
|
|
37
|
+
contract: PublicApiContract<InputData, OutputData>;
|
|
38
|
+
input: InputData;
|
|
39
|
+
}): Promise<PublicApiCallResult<OutputData>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qawolf/ci-sdk",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A simple SDK for interacting with QAWolf in CI scripts.",
|
|
6
6
|
"keywords": [],
|
|
@@ -23,18 +23,20 @@
|
|
|
23
23
|
"lint:ci": "npm run lint:first-half; FIRST_HALF_EXIT=$?; npm run lint:second-half && exit $FIRST_HALF_EXIT",
|
|
24
24
|
"lint:dev": "npm run lint:first-half",
|
|
25
25
|
"lint:first-half": "oxlint . --fix --quiet --report-unused-disable-directives --type-aware && oxfmt --write .",
|
|
26
|
-
"lint:second-half": "
|
|
26
|
+
"lint:second-half": "rev-dep config run",
|
|
27
27
|
"prepublishOnly": "nx run ci-sdk:build",
|
|
28
28
|
"test": "NODE_OPTIONS=\"--experimental-vm-modules\" NODE_NO_WARNINGS=1 jest",
|
|
29
29
|
"tsc:check": "tsc --noEmit"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
+
"@qawolf/api-contracts": ">=0.71.0",
|
|
32
33
|
"@qawolf/ci-utils": "^2.0.0",
|
|
33
34
|
"@sinonjs/fake-timers": "^10.3.0",
|
|
34
|
-
"tslib": "^2.6.2"
|
|
35
|
+
"tslib": "^2.6.2",
|
|
36
|
+
"zod": "^4.1.11"
|
|
35
37
|
},
|
|
36
38
|
"devDependencies": {
|
|
37
|
-
"@qawolf/platform-builder": "^1.2.
|
|
39
|
+
"@qawolf/platform-builder": "^1.2.7",
|
|
38
40
|
"tsx": "^4.19.4",
|
|
39
41
|
"typescript": "^5.9.3"
|
|
40
42
|
},
|