@qawolf/ci-sdk
Advanced tools
Comparing version 0.18.0 to 0.20.0
@@ -48,3 +48,3 @@ import { type ApiConfig } from "../api-types"; | ||
}; | ||
export type CiGreenlightCompletedSuiteDetails = { | ||
export type CiGreenlightBugData = { | ||
blockingBugsCount: number; | ||
@@ -56,2 +56,6 @@ blockingBugUrls: string[]; | ||
}; | ||
/** | ||
* @deprecated This type will be removed in the next major version. Use `CiGreenlightBugData` instead. | ||
*/ | ||
export type CiGreenlightCompletedSuiteDetails = CiGreenlightBugData; | ||
export type CiGreenlightStatusBase = { | ||
@@ -71,12 +75,10 @@ relevantRunId: string; | ||
*/ | ||
export type CiGreenlightStatus = CiGreenlightStatusBase & ({ | ||
blockingBugsCount: number; | ||
blockingBugUrls: string[]; | ||
export type CiGreenlightStatus = CiGreenlightStatusBase & (({ | ||
greenlight: boolean; | ||
nonBlockingBugsCount: number; | ||
nonBlockingBugUrls: string[]; | ||
reproducedBugs: CiGreenlightBugDetails[]; | ||
runStage: "completed"; | ||
} | { | ||
} & CiGreenlightBugData) | ({ | ||
greenlight: false; | ||
runStage: "underReview"; | ||
} & CiGreenlightBugData) | { | ||
greenlight: false; | ||
runStage: "initializing" | "underReview" | "canceled"; | ||
@@ -83,0 +85,0 @@ }); |
@@ -5,3 +5,3 @@ import { type ApiConfig } from "../api-types"; | ||
export interface NotifyVCSBranchBuildDeployedMutationInput { | ||
baseEnvironmentAlias: string; | ||
baseEnvironmentAlias: string | undefined; | ||
concurrencyLimit: number | undefined; | ||
@@ -8,0 +8,0 @@ headEnvironmentAlias: string; |
@@ -10,3 +10,3 @@ "use strict"; | ||
$headEnvironmentVariablesJson: String!, | ||
$baseEnvironmentAlias: String!, | ||
$baseEnvironmentAlias: String, | ||
$headEnvironmentAlias: String!, | ||
@@ -44,3 +44,3 @@ $concurrencyLimit: Int, | ||
variables: { | ||
baseEnvironmentAlias, | ||
baseEnvironmentAlias: baseEnvironmentAlias ?? null, | ||
concurrencyLimit: concurrencyLimit ?? null, | ||
@@ -47,0 +47,0 @@ headEnvironmentAlias, |
@@ -5,3 +5,3 @@ import { type ApiConfig } from "../api-types"; | ||
export interface NotifyVCSBranchMergeCompletedMutationInput { | ||
baseEnvironmentAlias: string; | ||
baseEnvironmentAlias: string | undefined; | ||
headEnvironmentAlias: string; | ||
@@ -8,0 +8,0 @@ } |
@@ -7,3 +7,3 @@ "use strict"; | ||
const mutationGql = ` | ||
mutation NotifyVCSBranchMergeCompleted($baseEnvironmentAlias: String!, $headEnvironmentAlias: String!) { | ||
mutation NotifyVCSBranchMergeCompleted($baseEnvironmentAlias: String, $headEnvironmentAlias: String!) { | ||
${mutationName}(baseEnvironmentAlias: $baseEnvironmentAlias, headEnvironmentAlias: $headEnvironmentAlias) { | ||
@@ -22,3 +22,3 @@ outcome | ||
variables: { | ||
baseEnvironmentAlias, | ||
baseEnvironmentAlias: baseEnvironmentAlias ?? null, | ||
headEnvironmentAlias, | ||
@@ -25,0 +25,0 @@ }, |
@@ -6,2 +6,8 @@ import { type CiGreenlightStatus } from "../../api/ci-greenlight"; | ||
/** | ||
* If true, the job will be aborted when a superseding run is detected. | ||
* | ||
* @default false | ||
*/ | ||
abortOnSuperseded: boolean; | ||
/** | ||
* Maximum number of network operations retries before aborting the job. | ||
@@ -38,3 +44,3 @@ * | ||
export type PollCiGreenlightHttpAbortReason = "4XX-client-error" | "404-run-not-found" | "5XX-server-error" | "XXX-other-http-code"; | ||
export type PollCiGreenlightNonHttpAbortReason = "poll-timed-out" | "run-canceled" | "network-error"; | ||
export type PollCiGreenlightNonHttpAbortReason = "poll-timed-out" | "run-canceled" | "network-error" | "superseded-run"; | ||
export type PollCiGreenlightAbortReason = PollCiGreenlightNonHttpAbortReason | PollCiGreenlightHttpAbortReason; | ||
@@ -41,0 +47,0 @@ export type PollCiGreenlightStatus = { |
@@ -9,2 +9,3 @@ "use strict"; | ||
const safeDefaults = { | ||
abortOnSuperseded: false, | ||
maxRetries: 10, | ||
@@ -19,3 +20,3 @@ pollTimeout: 120 * 60 * 1000, | ||
const { log } = deps; | ||
const { maxRetries = safeDefaults.maxRetries, pollTimeout = safeDefaults.pollTimeout, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, } = pollConfig; | ||
const { abortOnSuperseded = safeDefaults.abortOnSuperseded, maxRetries = safeDefaults.maxRetries, pollTimeout = safeDefaults.pollTimeout, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, } = pollConfig; | ||
let currentStatus = undefined; | ||
@@ -89,5 +90,14 @@ const startedAt = Date.now(); | ||
if (rootRunId !== relevantRunId) { | ||
log.info(`Root run was superseded: | ||
const supersedingDetails = ` | ||
- Root: ${rootRunUrl} | ||
- Superseding: ${relevantRunUrl}`); | ||
- Superseding: ${relevantRunUrl}`; | ||
if (abortOnSuperseded) { | ||
log.warn(`❌ Aborting due to superseded run (option 'abortOnSuperseded' is enabled).${supersedingDetails}`); | ||
return { | ||
abortReason: "superseded-run", | ||
httpStatus: undefined, | ||
outcome: "aborted", | ||
}; | ||
} | ||
log.info(`Root run was superseded:${supersedingDetails}`); | ||
} | ||
@@ -146,3 +156,2 @@ if (runStage === "completed") { | ||
else { | ||
(0, utils_1.assertType)(runStage); | ||
throw new Error(`Unexpected run stage: ${runStage}`); | ||
@@ -149,0 +158,0 @@ } |
@@ -8,4 +8,4 @@ import { type SdkDependencies } from "../../dependencies"; | ||
export type { NotifyBuildDeployedInput, NotifyBuildDeployedResult, } from "./notify-vcs-branch-build-deployed"; | ||
export type { NotifyVCSBranchMergeCanceledInput, NotifyMergeCanceledResult, } from "./notify-vcs-branch-merge-canceled"; | ||
export type { NotifyVCSBranchMergeCompletedInput, NotifyMergeCompletedResult, } from "./notify-vcs-branch-merge-completed"; | ||
export type { NotifyMergeCanceledResult, NotifyVCSBranchMergeCanceledInput, } from "./notify-vcs-branch-merge-canceled"; | ||
export type { NotifyMergeCompletedResult, NotifyVCSBranchMergeCompletedInput, } from "./notify-vcs-branch-merge-completed"; | ||
export declare function makeVCSBranchTestingSDK({ apiKey, serviceBase, }: { | ||
@@ -12,0 +12,0 @@ apiKey: string; |
@@ -14,8 +14,3 @@ "use strict"; | ||
if (baseEnvironmentAlias === undefined) { | ||
log.error(`❌ [notifyVCSBranchBuildDeployed] Could not find a base environment for VCS branch '${baseVcsBranch}'. Make sure you provide ` + | ||
"a mapping for this base branch in the 'baseEnvironmentsMapping' field."); | ||
return { | ||
abortReason: "missing-vcs-branch-to-environment-alias-mapping", | ||
outcome: "aborted", | ||
}; | ||
log.info(`ℹ️ [notifyVCSBranchBuildDeployed] Could not find a base environment for VCS branch '${baseVcsBranch}'. Fall back to use the default base environment`); | ||
} | ||
@@ -22,0 +17,0 @@ let finalConcurrencyLimit = concurrencyLimit; |
@@ -14,8 +14,3 @@ "use strict"; | ||
if (baseEnvironmentAlias === undefined) { | ||
log.error(`❌ [notifyVCSBranchMergeCompleted] Could not find a base environment for VCS branch '${vcsBaseBranch}'. Make sure you provide ` + | ||
"a mapping for this base branch in the 'baseEnvironmentsMapping' field."); | ||
return { | ||
abortReason: "missing-vcs-branch-to-environment-alias-mapping", | ||
outcome: "aborted", | ||
}; | ||
log.info(`ℹ️ [notifyVCSBranchMergeCompleted] Could not find a base environment for VCS branch '${vcsBaseBranch}'. Fall back to use the default base environment`); | ||
} | ||
@@ -22,0 +17,0 @@ const resp = await (0, notify_vcs_branch_merge_completed_mutation_1.callNotifyVCSBranchMergeCompletedMutation)(deps, apiConfig, { |
@@ -0,1 +1,2 @@ | ||
import FakeTimers from "@sinonjs/fake-timers"; | ||
import { type CiGreenlightStatusBase } from "../lib/api/ci-greenlight"; | ||
@@ -35,2 +36,9 @@ export declare function makeVCSBranchTestingSDKForTest({ apiKey }: { | ||
export declare function buildCiGreenlightStatusBase(): CiGreenlightStatusBase; | ||
export declare function setupTests(): { | ||
clock: FakeTimers.InstalledClock; | ||
runGraphQLAssertions: ({ fetchMock, method, }: { | ||
fetchMock: ReturnType<typeof makeVCSBranchTestingSDKForTest>["fetch"]; | ||
method: () => Promise<unknown>; | ||
}) => void; | ||
}; | ||
//# sourceMappingURL=test-lib.d.ts.map |
@@ -7,3 +7,7 @@ "use strict"; | ||
exports.buildCiGreenlightStatusBase = buildCiGreenlightStatusBase; | ||
exports.setupTests = setupTests; | ||
const tslib_1 = require("tslib"); | ||
/* eslint-disable jest/no-export */ | ||
const globals_1 = require("@jest/globals"); | ||
const fake_timers_1 = tslib_1.__importDefault(require("@sinonjs/fake-timers")); | ||
const vcsBranchTesting_1 = require("../lib/sdk/domain/vcsBranchTesting"); | ||
@@ -65,2 +69,80 @@ const index_1 = require("../lib/sdk/index"); | ||
} | ||
function setupTests() { | ||
const clock = fake_timers_1.default.install(); | ||
function runGraphQLAssertions({ fetchMock, method, }) { | ||
afterEach(() => globals_1.jest.resetAllMocks()); | ||
it("should handle retries with GraphQL server-error", async () => { | ||
fetchMock.mockImplementation(async () => { | ||
return buildResponse({ | ||
errors: [ | ||
{ | ||
extensions: [{ code: "INTERNAL" }], | ||
message: "INTERNAL", | ||
}, | ||
], | ||
}); | ||
}); | ||
const expectedValue = { | ||
abortReason: "server-error", | ||
outcome: "aborted", | ||
}; | ||
const promise = method(); | ||
// This will run all pending timers, handy to speedup retry testing. | ||
clock.runAllAsync(); | ||
await expect(promise).resolves.toEqual(expectedValue); | ||
// 1 retry = 2 attempts | ||
expect(fetchMock).toHaveBeenCalledTimes(2); | ||
}); | ||
it("should handle retries with network errors", async () => { | ||
fetchMock.mockRejectedValue(new Error("network error")); | ||
const expectedValue = { | ||
abortReason: "network-error", | ||
outcome: "aborted", | ||
}; | ||
const promise = method(); | ||
// This will run all pending timers, handy to speedup retry testing. | ||
clock.runAllAsync(); | ||
await expect(promise).resolves.toEqual(expectedValue); | ||
// 1 retry = 2 attempts | ||
expect(fetchMock).toHaveBeenCalledTimes(2); | ||
}); | ||
it("should handle GraphQL unauthenticated error", async () => { | ||
fetchMock.mockResolvedValueOnce(buildResponse({ | ||
errors: [ | ||
{ | ||
extensions: [{ code: "UNAUTHENTICATED" }], | ||
message: "UNAUTHENTICATED", | ||
}, | ||
], | ||
})); | ||
const expectedValue = { | ||
abortReason: "unauthenticated", | ||
outcome: "aborted", | ||
}; | ||
await expect(method()).resolves.toEqual(expectedValue); | ||
}); | ||
it("should handle GraphQL forbidden error", async () => { | ||
fetchMock.mockResolvedValueOnce(buildResponse({ | ||
errors: [ | ||
{ | ||
extensions: [{ code: "FORBIDDEN" }], | ||
message: "FORBIDDEN", | ||
}, | ||
], | ||
})); | ||
const expectedValue = { | ||
abortReason: "forbidden", | ||
outcome: "aborted", | ||
}; | ||
await expect(method()).resolves.toEqual(expectedValue); | ||
}); | ||
} | ||
afterAll(() => { | ||
clock.uninstall(); | ||
}); | ||
return { | ||
clock, | ||
runGraphQLAssertions, | ||
}; | ||
} | ||
//# sourceMappingURL=test-lib.js.map |
@@ -1,3 +0,19 @@ | ||
export * from "./lib/sdk/index.js"; | ||
export * from "./lib/sdk/dependencies.js"; | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./lib/sdk/index.js"), exports); | ||
__exportStar(require("./lib/sdk/dependencies.js"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,3 @@ | ||
export {}; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
//# sourceMappingURL=api-types.js.map |
@@ -48,3 +48,3 @@ import { type ApiConfig } from "../api-types"; | ||
}; | ||
export type CiGreenlightCompletedSuiteDetails = { | ||
export type CiGreenlightBugData = { | ||
blockingBugsCount: number; | ||
@@ -56,2 +56,6 @@ blockingBugUrls: string[]; | ||
}; | ||
/** | ||
* @deprecated This type will be removed in the next major version. Use `CiGreenlightBugData` instead. | ||
*/ | ||
export type CiGreenlightCompletedSuiteDetails = CiGreenlightBugData; | ||
export type CiGreenlightStatusBase = { | ||
@@ -71,12 +75,10 @@ relevantRunId: string; | ||
*/ | ||
export type CiGreenlightStatus = CiGreenlightStatusBase & ({ | ||
blockingBugsCount: number; | ||
blockingBugUrls: string[]; | ||
export type CiGreenlightStatus = CiGreenlightStatusBase & (({ | ||
greenlight: boolean; | ||
nonBlockingBugsCount: number; | ||
nonBlockingBugUrls: string[]; | ||
reproducedBugs: CiGreenlightBugDetails[]; | ||
runStage: "completed"; | ||
} | { | ||
} & CiGreenlightBugData) | ({ | ||
greenlight: false; | ||
runStage: "underReview"; | ||
} & CiGreenlightBugData) | { | ||
greenlight: false; | ||
runStage: "initializing" | "underReview" | "canceled"; | ||
@@ -83,0 +85,0 @@ }); |
@@ -1,2 +0,5 @@ | ||
export async function fetchCiGreenlightStatus({ apiKey, serviceBase }, { runId, }, { fetch: localFetch }) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.fetchCiGreenlightStatus = fetchCiGreenlightStatus; | ||
async function fetchCiGreenlightStatus({ apiKey, serviceBase }, { runId, }, { fetch: localFetch }) { | ||
try { | ||
@@ -3,0 +6,0 @@ const resp = await localFetch(new URL(`/api/v0/ci-greenlight/${encodeURIComponent(runId)}`, serviceBase), { |
@@ -1,2 +0,5 @@ | ||
export async function postDeploySuccess({ apiKey, serviceBase }, { branch, commitUrl, deduplicationKey, deploymentType, deploymentUrl, hostingService, sha, variables, }, { fetch: localFetch }) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.postDeploySuccess = postDeploySuccess; | ||
async function postDeploySuccess({ apiKey, serviceBase }, { branch, commitUrl, deduplicationKey, deploymentType, deploymentUrl, hostingService, sha, variables, }, { fetch: localFetch }) { | ||
try { | ||
@@ -3,0 +6,0 @@ const response = await localFetch(new URL("/api/webhooks/deploy_success", serviceBase), { |
@@ -1,2 +0,5 @@ | ||
export async function callGenerateSignedUrlForRunInputsExecutablesStorage({ apiKey, serviceBase }, { destinationFilePath }, { fetch: localFetch }) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.callGenerateSignedUrlForRunInputsExecutablesStorage = callGenerateSignedUrlForRunInputsExecutablesStorage; | ||
async function callGenerateSignedUrlForRunInputsExecutablesStorage({ apiKey, serviceBase }, { destinationFilePath }, { fetch: localFetch }) { | ||
try { | ||
@@ -3,0 +6,0 @@ const response = await localFetch(new URL(`${serviceBase}/api/v0/run-inputs-executables-signed-urls?file=${destinationFilePath}`), { |
@@ -1,2 +0,5 @@ | ||
export async function callGenerateSignedUrlForTempTeamStorage({ apiKey, serviceBase }, { destinationFilePath }, { fetch: localFetch }) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.callGenerateSignedUrlForTempTeamStorage = callGenerateSignedUrlForTempTeamStorage; | ||
async function callGenerateSignedUrlForTempTeamStorage({ apiKey, serviceBase }, { destinationFilePath }, { fetch: localFetch }) { | ||
try { | ||
@@ -3,0 +6,0 @@ const response = await localFetch(new URL(`${serviceBase}/api/v0/team-storage-signed-url?file=${destinationFilePath}`), { |
@@ -0,1 +1,4 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.qawolfGraphql = qawolfGraphql; | ||
class GraphQLBadResponseError extends Error { | ||
@@ -7,3 +10,3 @@ constructor(message) { | ||
} | ||
export async function qawolfGraphql({ apiConfig: { apiKey, serviceBase }, deps: { fetch: localFetch, log }, name, query: queryGql, variables, }) { | ||
async function qawolfGraphql({ apiConfig: { apiKey, serviceBase }, deps: { fetch: localFetch, log }, name, query: queryGql, variables, }) { | ||
try { | ||
@@ -10,0 +13,0 @@ const response = await localFetch(new URL(`/api/graphql`, serviceBase), { |
@@ -1,4 +0,20 @@ | ||
export * from "./ci-greenlight.js"; | ||
export * from "./deploy.js"; | ||
export * from "./generate-signed-url-for-team-storage.js"; | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./ci-greenlight.js"), exports); | ||
__exportStar(require("./deploy.js"), exports); | ||
__exportStar(require("./generate-signed-url-for-team-storage.js"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -5,3 +5,3 @@ import { type ApiConfig } from "../api-types"; | ||
export interface NotifyVCSBranchBuildDeployedMutationInput { | ||
baseEnvironmentAlias: string; | ||
baseEnvironmentAlias: string | undefined; | ||
concurrencyLimit: number | undefined; | ||
@@ -8,0 +8,0 @@ headEnvironmentAlias: string; |
@@ -1,2 +0,5 @@ | ||
import { qawolfGraphql } from "./graphql"; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.callNotifyVCSBranchBuildDeployedMutation = callNotifyVCSBranchBuildDeployedMutation; | ||
const graphql_1 = require("./graphql"); | ||
const mutationName = "notifyVCSBranchBuildDeployed"; | ||
@@ -7,3 +10,3 @@ const mutationGql = ` | ||
$headEnvironmentVariablesJson: String!, | ||
$baseEnvironmentAlias: String!, | ||
$baseEnvironmentAlias: String, | ||
$headEnvironmentAlias: String!, | ||
@@ -34,4 +37,4 @@ $concurrencyLimit: Int, | ||
}`; | ||
export async function callNotifyVCSBranchBuildDeployedMutation(deps, apiConfig, { baseEnvironmentAlias, concurrencyLimit, headEnvironmentAlias, headEnvironmentName, headEnvironmentVariables, headVcsBranch, headVcsCommitId, headVcsCommitUrl, pullOrMergeRequestNumber, }) { | ||
return qawolfGraphql({ | ||
async function callNotifyVCSBranchBuildDeployedMutation(deps, apiConfig, { baseEnvironmentAlias, concurrencyLimit, headEnvironmentAlias, headEnvironmentName, headEnvironmentVariables, headVcsBranch, headVcsCommitId, headVcsCommitUrl, pullOrMergeRequestNumber, }) { | ||
return (0, graphql_1.qawolfGraphql)({ | ||
apiConfig, | ||
@@ -42,3 +45,3 @@ deps, | ||
variables: { | ||
baseEnvironmentAlias, | ||
baseEnvironmentAlias: baseEnvironmentAlias ?? null, | ||
concurrencyLimit: concurrencyLimit ?? null, | ||
@@ -45,0 +48,0 @@ headEnvironmentAlias, |
@@ -1,2 +0,5 @@ | ||
import { qawolfGraphql } from "./graphql"; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.callNotifyVCSBranchMergeCanceledMutation = callNotifyVCSBranchMergeCanceledMutation; | ||
const graphql_1 = require("./graphql"); | ||
const mutationName = "notifyVCSBranchMergeCanceled"; | ||
@@ -11,4 +14,4 @@ const mutationGql = ` | ||
}`; | ||
export async function callNotifyVCSBranchMergeCanceledMutation(deps, apiConfig, { headEnvironmentAlias }) { | ||
return qawolfGraphql({ | ||
async function callNotifyVCSBranchMergeCanceledMutation(deps, apiConfig, { headEnvironmentAlias }) { | ||
return (0, graphql_1.qawolfGraphql)({ | ||
apiConfig, | ||
@@ -15,0 +18,0 @@ deps, |
@@ -5,3 +5,3 @@ import { type ApiConfig } from "../api-types"; | ||
export interface NotifyVCSBranchMergeCompletedMutationInput { | ||
baseEnvironmentAlias: string; | ||
baseEnvironmentAlias: string | undefined; | ||
headEnvironmentAlias: string; | ||
@@ -8,0 +8,0 @@ } |
@@ -1,5 +0,8 @@ | ||
import { qawolfGraphql } from "./graphql"; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.callNotifyVCSBranchMergeCompletedMutation = callNotifyVCSBranchMergeCompletedMutation; | ||
const graphql_1 = require("./graphql"); | ||
const mutationName = "notifyVCSBranchMergeCompleted"; | ||
const mutationGql = ` | ||
mutation NotifyVCSBranchMergeCompleted($baseEnvironmentAlias: String!, $headEnvironmentAlias: String!) { | ||
mutation NotifyVCSBranchMergeCompleted($baseEnvironmentAlias: String, $headEnvironmentAlias: String!) { | ||
${mutationName}(baseEnvironmentAlias: $baseEnvironmentAlias, headEnvironmentAlias: $headEnvironmentAlias) { | ||
@@ -11,4 +14,4 @@ outcome | ||
}`; | ||
export async function callNotifyVCSBranchMergeCompletedMutation(deps, apiConfig, { baseEnvironmentAlias, headEnvironmentAlias, }) { | ||
return qawolfGraphql({ | ||
async function callNotifyVCSBranchMergeCompletedMutation(deps, apiConfig, { baseEnvironmentAlias, headEnvironmentAlias, }) { | ||
return (0, graphql_1.qawolfGraphql)({ | ||
apiConfig, | ||
@@ -19,3 +22,3 @@ deps, | ||
variables: { | ||
baseEnvironmentAlias, | ||
baseEnvironmentAlias: baseEnvironmentAlias ?? null, | ||
headEnvironmentAlias, | ||
@@ -22,0 +25,0 @@ }, |
@@ -1,2 +0,5 @@ | ||
export const defaultFetch = globalThis.fetch; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.defaultFetch = void 0; | ||
exports.defaultFetch = globalThis.fetch; | ||
//# sourceMappingURL=fetch.js.map |
@@ -1,2 +0,5 @@ | ||
export const defaultLogDriver = { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.defaultLogDriver = void 0; | ||
exports.defaultLogDriver = { | ||
error(message, error) { | ||
@@ -3,0 +6,0 @@ console.error(message, error); |
@@ -1,2 +0,5 @@ | ||
export const defaultServiceBase = "https://app.qawolf.com/"; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.defaultServiceBase = void 0; | ||
exports.defaultServiceBase = "https://app.qawolf.com/"; | ||
//# sourceMappingURL=serviceBase.js.map |
@@ -1,2 +0,3 @@ | ||
export {}; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
//# sourceMappingURL=dependencies.js.map |
@@ -1,6 +0,9 @@ | ||
import { postDeploySuccess } from "../../api/deploy"; | ||
import { assertType } from "../../utils"; | ||
export async function attemptNotifyDeploy(deps, apiConfig, config) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.attemptNotifyDeploy = attemptNotifyDeploy; | ||
const deploy_1 = require("../../api/deploy"); | ||
const utils_1 = require("../../utils"); | ||
async function attemptNotifyDeploy(deps, apiConfig, config) { | ||
const { log } = deps; | ||
const responseState = await postDeploySuccess(apiConfig, config, deps); | ||
const responseState = await (0, deploy_1.postDeploySuccess)(apiConfig, config, deps); | ||
if (!responseState.success) { | ||
@@ -29,3 +32,3 @@ if (responseState.failureReason === "no-matched-trigger") { | ||
else { | ||
assertType(responseState); | ||
(0, utils_1.assertType)(responseState); | ||
} | ||
@@ -32,0 +35,0 @@ if (responseState.failureReason === "network-error") { |
@@ -1,3 +0,6 @@ | ||
import { callGenerateSignedUrlForRunInputsExecutablesStorage } from "../../../api/generate-signed-url-for-run-inputs-executables"; | ||
export async function generateSignedUrlForRunInputsExecutablesStorage(deps, apiConfig, config) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.generateSignedUrlForRunInputsExecutablesStorage = generateSignedUrlForRunInputsExecutablesStorage; | ||
const generate_signed_url_for_run_inputs_executables_1 = require("../../../api/generate-signed-url-for-run-inputs-executables"); | ||
async function generateSignedUrlForRunInputsExecutablesStorage(deps, apiConfig, config) { | ||
const { log } = deps; | ||
@@ -11,3 +14,3 @@ if (!config.destinationFilePath) { | ||
} | ||
const responseState = await callGenerateSignedUrlForRunInputsExecutablesStorage(apiConfig, config, deps); | ||
const responseState = await (0, generate_signed_url_for_run_inputs_executables_1.callGenerateSignedUrlForRunInputsExecutablesStorage)(apiConfig, config, deps); | ||
if (!responseState.success) { | ||
@@ -14,0 +17,0 @@ let abortReason = "XXX-other-http-code"; |
@@ -1,3 +0,6 @@ | ||
import { callGenerateSignedUrlForTempTeamStorage } from "../../../api/generate-signed-url-for-team-storage"; | ||
export async function generateSignedUrlForTempTeamStorage(deps, apiConfig, config) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.generateSignedUrlForTempTeamStorage = generateSignedUrlForTempTeamStorage; | ||
const generate_signed_url_for_team_storage_1 = require("../../../api/generate-signed-url-for-team-storage"); | ||
async function generateSignedUrlForTempTeamStorage(deps, apiConfig, config) { | ||
const { log } = deps; | ||
@@ -11,3 +14,3 @@ if (!config.destinationFilePath) { | ||
} | ||
const responseState = await callGenerateSignedUrlForTempTeamStorage(apiConfig, config, deps); | ||
const responseState = await (0, generate_signed_url_for_team_storage_1.callGenerateSignedUrlForTempTeamStorage)(apiConfig, config, deps); | ||
if (!responseState.success) { | ||
@@ -14,0 +17,0 @@ let abortReason = "XXX-other-http-code"; |
@@ -1,2 +0,3 @@ | ||
export {}; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
//# sourceMappingURL=types.js.map |
@@ -1,5 +0,8 @@ | ||
export const qawolfBaseUrl = "https://app.qawolf.com"; | ||
export const qawolfGraphQLEndpoint = `${qawolfBaseUrl}/api/graphql`; | ||
export const qawolfDeploySuccessEndpoint = `${qawolfBaseUrl}/api/webhooks/deploy_success`; | ||
export const previewDeploymentType = "qawolf-preview"; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.previewDeploymentType = exports.qawolfDeploySuccessEndpoint = exports.qawolfGraphQLEndpoint = exports.qawolfBaseUrl = void 0; | ||
exports.qawolfBaseUrl = "https://app.qawolf.com"; | ||
exports.qawolfGraphQLEndpoint = `${exports.qawolfBaseUrl}/api/graphql`; | ||
exports.qawolfDeploySuccessEndpoint = `${exports.qawolfBaseUrl}/api/webhooks/deploy_success`; | ||
exports.previewDeploymentType = "qawolf-preview"; | ||
//# sourceMappingURL=constants.js.map |
@@ -1,10 +0,13 @@ | ||
import { createEnvironmentVariables } from "./createEnvironmentVariables"; | ||
import { findOrCreateEnvironment } from "./findOrCreateEnvironment"; | ||
import { findOrCreateTrigger } from "./findOrCreateTrigger"; | ||
import { findRepositoryIdByName } from "./findRepositoryIdByName"; | ||
import { getEnvironmentVariablesFromEnvironment } from "./getEnvironmentVariablesFromEnvironment"; | ||
import { getTagsFromGenericTriggerInEnvironment } from "./getTagsFromEnvironment"; | ||
export const createEnvironmentAction = async (deps, apiConfig, { baseEnvironmentId, branch, deploymentUrl, headRepoFullName, pr, qaWolfTeamId, variables, }) => { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createEnvironmentAction = void 0; | ||
const createEnvironmentVariables_1 = require("./createEnvironmentVariables"); | ||
const findOrCreateEnvironment_1 = require("./findOrCreateEnvironment"); | ||
const findOrCreateTrigger_1 = require("./findOrCreateTrigger"); | ||
const findRepositoryIdByName_1 = require("./findRepositoryIdByName"); | ||
const getEnvironmentVariablesFromEnvironment_1 = require("./getEnvironmentVariablesFromEnvironment"); | ||
const getTagsFromEnvironment_1 = require("./getTagsFromEnvironment"); | ||
const createEnvironmentAction = async (deps, apiConfig, { baseEnvironmentId, branch, deploymentUrl, headRepoFullName, pr, qaWolfTeamId, variables, }) => { | ||
deps.log.info("Creating environment for pull request..."); | ||
const environmentId = await findOrCreateEnvironment(deps, apiConfig, { | ||
const environmentId = await (0, findOrCreateEnvironment_1.findOrCreateEnvironment)(deps, apiConfig, { | ||
baseEnvironmentId, | ||
@@ -17,3 +20,3 @@ branch, | ||
const baseEnvironmentVariablesJSON = baseEnvironmentId | ||
? await getEnvironmentVariablesFromEnvironment(deps, apiConfig, { | ||
? await (0, getEnvironmentVariablesFromEnvironment_1.getEnvironmentVariablesFromEnvironment)(deps, apiConfig, { | ||
environmentId: baseEnvironmentId, | ||
@@ -32,3 +35,3 @@ }) | ||
deps.log.info("Creating environment variables..."); | ||
await createEnvironmentVariables(deps, apiConfig, { | ||
await (0, createEnvironmentVariables_1.createEnvironmentVariables)(deps, apiConfig, { | ||
environmentId, | ||
@@ -39,3 +42,3 @@ variables: combinedEnvironmentVariables, | ||
deps.log.info("Retrieving repository ID..."); | ||
const repositoryId = await findRepositoryIdByName(deps, apiConfig, { | ||
const repositoryId = await (0, findRepositoryIdByName_1.findRepositoryIdByName)(deps, apiConfig, { | ||
headRepoFullName, | ||
@@ -47,3 +50,3 @@ }); | ||
const tags = baseEnvironmentId | ||
? await getTagsFromGenericTriggerInEnvironment(deps, apiConfig, { | ||
? await (0, getTagsFromEnvironment_1.getTagsFromGenericTriggerInEnvironment)(deps, apiConfig, { | ||
environmentId: baseEnvironmentId, | ||
@@ -54,3 +57,3 @@ }) | ||
deps.log.info("Creating trigger for deployment..."); | ||
await findOrCreateTrigger(deps, apiConfig, { | ||
await (0, findOrCreateTrigger_1.findOrCreateTrigger)(deps, apiConfig, { | ||
branch, | ||
@@ -64,2 +67,3 @@ environmentId, | ||
}; | ||
exports.createEnvironmentAction = createEnvironmentAction; | ||
//# sourceMappingURL=createEnvironmentAction.js.map |
@@ -1,6 +0,9 @@ | ||
import { qawolfGraphQLEndpoint } from "./constants"; | ||
export async function createEnvironmentVariables(deps, apiConfig, { environmentId, variables, }) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createEnvironmentVariables = createEnvironmentVariables; | ||
const constants_1 = require("./constants"); | ||
async function createEnvironmentVariables(deps, apiConfig, { environmentId, variables, }) { | ||
const environmentVariableRequests = Object.keys(variables).map(async (key) => { | ||
const value = variables[key]; | ||
return deps.fetch(qawolfGraphQLEndpoint, { | ||
return deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -7,0 +10,0 @@ query: ` |
@@ -1,4 +0,7 @@ | ||
import { qawolfGraphQLEndpoint } from "./constants"; | ||
export async function deleteEnvironment(deps, apiConfig, { environmentId, }) { | ||
await deps.fetch(qawolfGraphQLEndpoint, { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.deleteEnvironment = deleteEnvironment; | ||
const constants_1 = require("./constants"); | ||
async function deleteEnvironment(deps, apiConfig, { environmentId, }) { | ||
await deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -5,0 +8,0 @@ query: ` |
@@ -1,9 +0,13 @@ | ||
import { deleteEnvironment } from "./deleteEnvironment"; | ||
import { getEnvironmentIdForBranch } from "./getEnvironmentIdForBranch"; | ||
export const deleteEnvironmentAction = async (deps, apiConfig, { branch, }) => { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.deleteEnvironmentAction = void 0; | ||
const deleteEnvironment_1 = require("./deleteEnvironment"); | ||
const getEnvironmentIdForBranch_1 = require("./getEnvironmentIdForBranch"); | ||
const deleteEnvironmentAction = async (deps, apiConfig, { branch, }) => { | ||
deps.log.info("Retrieving environment ID for deletion..."); | ||
const environmentId = await getEnvironmentIdForBranch(deps, apiConfig, branch); | ||
const environmentId = await (0, getEnvironmentIdForBranch_1.getEnvironmentIdForBranch)(deps, apiConfig, branch); | ||
deps.log.info(`Deleting environment with ID: ${environmentId}`); | ||
await deleteEnvironment(deps, apiConfig, { environmentId }); | ||
await (0, deleteEnvironment_1.deleteEnvironment)(deps, apiConfig, { environmentId }); | ||
}; | ||
exports.deleteEnvironmentAction = deleteEnvironmentAction; | ||
//# sourceMappingURL=deleteEnvironmentAction.js.map |
@@ -1,4 +0,7 @@ | ||
import { qawolfGraphQLEndpoint } from "./constants"; | ||
export async function findOrCreateEnvironment(deps, apiConfig, { baseEnvironmentId, branch, pr, qaWolfTeamId, }) { | ||
const retrievalResponse = await deps.fetch(qawolfGraphQLEndpoint, { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.findOrCreateEnvironment = findOrCreateEnvironment; | ||
const constants_1 = require("./constants"); | ||
async function findOrCreateEnvironment(deps, apiConfig, { baseEnvironmentId, branch, pr, qaWolfTeamId, }) { | ||
const retrievalResponse = await deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -37,3 +40,3 @@ query: ` | ||
} | ||
const creationResponse = await deps.fetch(qawolfGraphQLEndpoint, { | ||
const creationResponse = await deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -65,3 +68,3 @@ operationName: "createEnvironment", | ||
} | ||
const multiBranchResponse = await deps.fetch(qawolfGraphQLEndpoint, { | ||
const multiBranchResponse = await deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -93,3 +96,3 @@ query: ` | ||
} | ||
const sourceEnvironmentResponse = await deps.fetch(qawolfGraphQLEndpoint, { | ||
const sourceEnvironmentResponse = await deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -123,3 +126,3 @@ query: ` | ||
deps.log.info(`Promoting workflows from branch ${baseBranchId} to ${targetBranchId}`); | ||
const promotionResponse = await deps.fetch(qawolfGraphQLEndpoint, { | ||
const promotionResponse = await deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -126,0 +129,0 @@ query: ` |
@@ -1,6 +0,9 @@ | ||
import { previewDeploymentType, qawolfGraphQLEndpoint } from "./constants"; | ||
export async function findOrCreateTrigger(deps, apiConfig, args) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.findOrCreateTrigger = findOrCreateTrigger; | ||
const constants_1 = require("./constants"); | ||
async function findOrCreateTrigger(deps, apiConfig, args) { | ||
const { branch, environmentId, pr, qaWolfTeamId, repositoryId, tags } = args; | ||
const triggerName = `Deployments of ${pr ? `PR #${pr.number} - ${pr.title}` : `branch ${branch}`}`; | ||
const retrievalResponse = await deps.fetch(qawolfGraphQLEndpoint, { | ||
const retrievalResponse = await deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -38,3 +41,3 @@ query: `query getTriggersForBranch($where: TriggerWhereInput) { | ||
} | ||
const creationResponse = await deps.fetch(qawolfGraphQLEndpoint, { | ||
const creationResponse = await deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -71,3 +74,3 @@ operationName: "createTrigger", | ||
deploymentBranches: branch, | ||
deploymentEnvironment: previewDeploymentType, | ||
deploymentEnvironment: constants_1.previewDeploymentType, | ||
deploymentProvider: "generic", | ||
@@ -74,0 +77,0 @@ environmentId, |
@@ -1,4 +0,7 @@ | ||
import { qawolfGraphQLEndpoint } from "./constants"; | ||
export async function findRepositoryIdByName(deps, apiConfig, { headRepoFullName, }) { | ||
const response = await deps.fetch(qawolfGraphQLEndpoint, { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.findRepositoryIdByName = findRepositoryIdByName; | ||
const constants_1 = require("./constants"); | ||
async function findRepositoryIdByName(deps, apiConfig, { headRepoFullName, }) { | ||
const response = await deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -5,0 +8,0 @@ query: ` |
@@ -1,4 +0,7 @@ | ||
import { qawolfGraphQLEndpoint } from "./constants"; | ||
export async function getEnvironmentIdForBranch(deps, apiConfig, branch) { | ||
const response = await deps.fetch(qawolfGraphQLEndpoint, { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getEnvironmentIdForBranch = getEnvironmentIdForBranch; | ||
const constants_1 = require("./constants"); | ||
async function getEnvironmentIdForBranch(deps, apiConfig, branch) { | ||
const response = await deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -5,0 +8,0 @@ query: ` |
@@ -1,4 +0,7 @@ | ||
import { qawolfGraphQLEndpoint } from "./constants"; | ||
export async function getEnvironmentVariablesFromEnvironment(deps, apiConfig, { environmentId, }) { | ||
const retrievalResponse = await deps.fetch(qawolfGraphQLEndpoint, { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getEnvironmentVariablesFromEnvironment = getEnvironmentVariablesFromEnvironment; | ||
const constants_1 = require("./constants"); | ||
async function getEnvironmentVariablesFromEnvironment(deps, apiConfig, { environmentId, }) { | ||
const retrievalResponse = await deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -5,0 +8,0 @@ query: ` |
@@ -1,4 +0,7 @@ | ||
import { qawolfGraphQLEndpoint } from "./constants"; | ||
export async function getTagsFromGenericTriggerInEnvironment(deps, apiConfig, { environmentId, }) { | ||
const retrievalResponse = await deps.fetch(qawolfGraphQLEndpoint, { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getTagsFromGenericTriggerInEnvironment = getTagsFromGenericTriggerInEnvironment; | ||
const constants_1 = require("./constants"); | ||
async function getTagsFromGenericTriggerInEnvironment(deps, apiConfig, { environmentId, }) { | ||
const retrievalResponse = await deps.fetch(constants_1.qawolfGraphQLEndpoint, { | ||
body: JSON.stringify({ | ||
@@ -5,0 +8,0 @@ query: ` |
@@ -1,7 +0,11 @@ | ||
import { attemptNotifyDeploy } from "../attempt-deploy"; | ||
import { previewDeploymentType } from "./constants"; | ||
import { createEnvironmentAction as createEnvironment } from "./createEnvironmentAction"; | ||
import { deleteEnvironmentAction } from "./deleteEnvironmentAction"; | ||
export async function testPreview(deps, apiConfig, config) { | ||
await createEnvironment(deps, apiConfig, { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.testPreview = testPreview; | ||
exports.removeEnvironment = removeEnvironment; | ||
const attempt_deploy_1 = require("../attempt-deploy"); | ||
const constants_1 = require("./constants"); | ||
const createEnvironmentAction_1 = require("./createEnvironmentAction"); | ||
const deleteEnvironmentAction_1 = require("./deleteEnvironmentAction"); | ||
async function testPreview(deps, apiConfig, config) { | ||
await (0, createEnvironmentAction_1.createEnvironmentAction)(deps, apiConfig, { | ||
baseEnvironmentId: config.baseEnvironmentId, | ||
@@ -15,6 +19,6 @@ branch: config.branch, | ||
}); | ||
return attemptNotifyDeploy(deps, apiConfig, { | ||
return (0, attempt_deploy_1.attemptNotifyDeploy)(deps, apiConfig, { | ||
branch: config.branch, | ||
commitUrl: config.commitUrl, | ||
deploymentType: previewDeploymentType, | ||
deploymentType: constants_1.previewDeploymentType, | ||
deploymentUrl: config.deploymentUrl, | ||
@@ -25,5 +29,5 @@ sha: config.sha, | ||
} | ||
export async function removeEnvironment(deps, apiConfig, config) { | ||
await deleteEnvironmentAction(deps, apiConfig, config); | ||
async function removeEnvironment(deps, apiConfig, config) { | ||
await (0, deleteEnvironmentAction_1.deleteEnvironmentAction)(deps, apiConfig, config); | ||
} | ||
//# sourceMappingURL=index.js.map |
@@ -6,2 +6,8 @@ import { type CiGreenlightStatus } from "../../api/ci-greenlight"; | ||
/** | ||
* If true, the job will be aborted when a superseding run is detected. | ||
* | ||
* @default false | ||
*/ | ||
abortOnSuperseded: boolean; | ||
/** | ||
* Maximum number of network operations retries before aborting the job. | ||
@@ -38,3 +44,3 @@ * | ||
export type PollCiGreenlightHttpAbortReason = "4XX-client-error" | "404-run-not-found" | "5XX-server-error" | "XXX-other-http-code"; | ||
export type PollCiGreenlightNonHttpAbortReason = "poll-timed-out" | "run-canceled" | "network-error"; | ||
export type PollCiGreenlightNonHttpAbortReason = "poll-timed-out" | "run-canceled" | "network-error" | "superseded-run"; | ||
export type PollCiGreenlightAbortReason = PollCiGreenlightNonHttpAbortReason | PollCiGreenlightHttpAbortReason; | ||
@@ -41,0 +47,0 @@ export type PollCiGreenlightStatus = { |
@@ -1,6 +0,10 @@ | ||
import { fetchCiGreenlightStatus, } from "../../api/ci-greenlight"; | ||
import { assertType, pluralize, sleep } from "../../utils"; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.pollCiGreenlightStatus = pollCiGreenlightStatus; | ||
const ci_greenlight_1 = require("../../api/ci-greenlight"); | ||
const utils_1 = require("../../utils"); | ||
// If you change these values, make sure you update the JSDoc | ||
// comments in the PollConfig type. | ||
const safeDefaults = { | ||
abortOnSuperseded: false, | ||
maxRetries: 10, | ||
@@ -12,6 +16,6 @@ pollTimeout: 120 * 60 * 1000, | ||
}; | ||
export async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged: onRunStageChanged = () => void 0, runId, ...pollConfig }) { | ||
async function pollCiGreenlightStatus(deps, apiConfig, { onRunStageChanged: onRunStageChanged = () => void 0, runId, ...pollConfig }) { | ||
let retries = 0; | ||
const { log } = deps; | ||
const { maxRetries = safeDefaults.maxRetries, pollTimeout = safeDefaults.pollTimeout, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, } = pollConfig; | ||
const { abortOnSuperseded = safeDefaults.abortOnSuperseded, maxRetries = safeDefaults.maxRetries, pollTimeout = safeDefaults.pollTimeout, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, } = pollConfig; | ||
let currentStatus = undefined; | ||
@@ -21,3 +25,3 @@ const startedAt = Date.now(); | ||
while (!(hasTimedOut = Date.now() - startedAt > pollTimeout)) { | ||
const responseState = await fetchCiGreenlightStatus(apiConfig, { | ||
const responseState = await (0, ci_greenlight_1.fetchCiGreenlightStatus)(apiConfig, { | ||
runId, | ||
@@ -52,3 +56,3 @@ }, deps); | ||
else | ||
assertType(responseState); | ||
(0, utils_1.assertType)(responseState); | ||
return { | ||
@@ -68,3 +72,3 @@ abortReason, | ||
log.warn(`❌ Server error${retryLabel}`); | ||
await sleep(retryInterval); | ||
await (0, utils_1.sleep)(retryInterval); | ||
continue; | ||
@@ -88,5 +92,14 @@ } | ||
if (rootRunId !== relevantRunId) { | ||
log.info(`Root run was superseded: | ||
const supersedingDetails = ` | ||
- Root: ${rootRunUrl} | ||
- Superseding: ${relevantRunUrl}`); | ||
- Superseding: ${relevantRunUrl}`; | ||
if (abortOnSuperseded) { | ||
log.warn(`❌ Aborting due to superseded run (option 'abortOnSuperseded' is enabled).${supersedingDetails}`); | ||
return { | ||
abortReason: "superseded-run", | ||
httpStatus: undefined, | ||
outcome: "aborted", | ||
}; | ||
} | ||
log.info(`Root run was superseded:${supersedingDetails}`); | ||
} | ||
@@ -106,3 +119,3 @@ if (runStage === "completed") { | ||
log.info(`✅ Run passed and no blocking bugs found${nonBlockingBugsCount > 0 | ||
? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(nonBlockingBugsCount)} found` | ||
? ` and ${nonBlockingBugsCount} non-blocking bug${(0, utils_1.pluralize)(nonBlockingBugsCount)} found` | ||
: ""}.\n${urlInfo}`); | ||
@@ -112,4 +125,4 @@ return { greenlightStatus, outcome: "success" }; | ||
else { | ||
log.warn(`❌ Run failed and ${blockingBugsCount} blocking bug${pluralize(blockingBugsCount)} found${nonBlockingBugsCount | ||
? ` and ${nonBlockingBugsCount} non-blocking bug${pluralize(nonBlockingBugsCount)}` | ||
log.warn(`❌ Run failed and ${blockingBugsCount} blocking bug${(0, utils_1.pluralize)(blockingBugsCount)} found${nonBlockingBugsCount | ||
? ` and ${nonBlockingBugsCount} non-blocking bug${(0, utils_1.pluralize)(nonBlockingBugsCount)}` | ||
: ""}.\nSee ${relevantRunWithBugsUrl}\n` + | ||
@@ -140,10 +153,9 @@ "You may review the priority of certain bugs to mark these non-blocking and retry the job.\n" + | ||
log.info(`⏳ Run is in progress... ${urlInfo}`); | ||
await sleep(runInProgressInterval); | ||
await (0, utils_1.sleep)(runInProgressInterval); | ||
} | ||
else if (runStage === "underReview") { | ||
log.info(`🕵️ Run is under review... ${urlInfo}`); | ||
await sleep(runUnderReviewInterval); | ||
await (0, utils_1.sleep)(runUnderReviewInterval); | ||
} | ||
else { | ||
assertType(runStage); | ||
throw new Error(`Unexpected run stage: ${runStage}`); | ||
@@ -150,0 +162,0 @@ } |
@@ -8,4 +8,4 @@ import { type SdkDependencies } from "../../dependencies"; | ||
export type { NotifyBuildDeployedInput, NotifyBuildDeployedResult, } from "./notify-vcs-branch-build-deployed"; | ||
export type { NotifyVCSBranchMergeCanceledInput, NotifyMergeCanceledResult, } from "./notify-vcs-branch-merge-canceled"; | ||
export type { NotifyVCSBranchMergeCompletedInput, NotifyMergeCompletedResult, } from "./notify-vcs-branch-merge-completed"; | ||
export type { NotifyMergeCanceledResult, NotifyVCSBranchMergeCanceledInput, } from "./notify-vcs-branch-merge-canceled"; | ||
export type { NotifyMergeCompletedResult, NotifyVCSBranchMergeCompletedInput, } from "./notify-vcs-branch-merge-completed"; | ||
export declare function makeVCSBranchTestingSDK({ apiKey, serviceBase, }: { | ||
@@ -12,0 +12,0 @@ apiKey: string; |
@@ -1,18 +0,35 @@ | ||
import { defaultFetch } from "../../defaults/fetch"; | ||
import { defaultLogDriver } from "../../defaults/log"; | ||
import { defaultServiceBase } from "../../defaults/serviceBase"; | ||
import { notifyVCSBranchBuildDeployed, } from "./notify-vcs-branch-build-deployed"; | ||
import { notifyVCSBranchMergeCanceled, } from "./notify-vcs-branch-merge-canceled"; | ||
import { notifyVCSBranchMergeCompleted, } from "./notify-vcs-branch-merge-completed"; | ||
export * from "./types"; | ||
export * from "./lib/aliases"; | ||
export function makeVCSBranchTestingSDK({ apiKey, serviceBase = defaultServiceBase, }, { fetch = defaultFetch, log = defaultLogDriver, } = {}) { | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.makeVCSBranchTestingSDK = makeVCSBranchTestingSDK; | ||
const fetch_1 = require("../../defaults/fetch"); | ||
const log_1 = require("../../defaults/log"); | ||
const serviceBase_1 = require("../../defaults/serviceBase"); | ||
const notify_vcs_branch_build_deployed_1 = require("./notify-vcs-branch-build-deployed"); | ||
const notify_vcs_branch_merge_canceled_1 = require("./notify-vcs-branch-merge-canceled"); | ||
const notify_vcs_branch_merge_completed_1 = require("./notify-vcs-branch-merge-completed"); | ||
__exportStar(require("./types"), exports); | ||
__exportStar(require("./lib/aliases"), exports); | ||
function makeVCSBranchTestingSDK({ apiKey, serviceBase = serviceBase_1.defaultServiceBase, }, { fetch = fetch_1.defaultFetch, log = log_1.defaultLogDriver, } = {}) { | ||
const deps = { fetch, log }; | ||
const apiConfig = { apiKey, serviceBase }; | ||
return { | ||
notifyVCSBranchBuildDeployed: notifyVCSBranchBuildDeployed.bind(null, deps, apiConfig), | ||
notifyVCSBranchMergeCanceled: notifyVCSBranchMergeCanceled.bind(null, deps, apiConfig), | ||
notifyVCSBranchMergeCompleted: notifyVCSBranchMergeCompleted.bind(null, deps, apiConfig), | ||
notifyVCSBranchBuildDeployed: notify_vcs_branch_build_deployed_1.notifyVCSBranchBuildDeployed.bind(null, deps, apiConfig), | ||
notifyVCSBranchMergeCanceled: notify_vcs_branch_merge_canceled_1.notifyVCSBranchMergeCanceled.bind(null, deps, apiConfig), | ||
notifyVCSBranchMergeCompleted: notify_vcs_branch_merge_completed_1.notifyVCSBranchMergeCompleted.bind(null, deps, apiConfig), | ||
}; | ||
} | ||
//# sourceMappingURL=index.js.map |
@@ -1,6 +0,13 @@ | ||
import slugify from "slugify"; | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.pullRequestDetailsToEnvironmentAlias = pullRequestDetailsToEnvironmentAlias; | ||
exports.arbitraryStringToEnvironmentAlias = arbitraryStringToEnvironmentAlias; | ||
const slugify_1 = __importDefault(require("slugify")); | ||
/** | ||
* Creates a compliant environment alias from pull request details. | ||
*/ | ||
export function pullRequestDetailsToEnvironmentAlias({ codeHostingServiceOrganization, codeHostingServiceRepositoryName, pullRequestIdentifier, }) { | ||
function pullRequestDetailsToEnvironmentAlias({ codeHostingServiceOrganization, codeHostingServiceRepositoryName, pullRequestIdentifier, }) { | ||
return arbitraryStringToEnvironmentAlias(`${codeHostingServiceOrganization}-${codeHostingServiceRepositoryName}-pr-${pullRequestIdentifier}`); | ||
@@ -11,5 +18,5 @@ } | ||
*/ | ||
export function arbitraryStringToEnvironmentAlias(arbitraryString) { | ||
return slugify(arbitraryString, { lower: true }); | ||
function arbitraryStringToEnvironmentAlias(arbitraryString) { | ||
return (0, slugify_1.default)(arbitraryString, { lower: true }); | ||
} | ||
//# sourceMappingURL=aliases.js.map |
@@ -1,3 +0,6 @@ | ||
import { assertType } from "../../../../utils"; | ||
export function domainFailureToAbortResult({ log, methodName, result, }) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.domainFailureToAbortResult = domainFailureToAbortResult; | ||
const utils_1 = require("../../../../utils"); | ||
function domainFailureToAbortResult({ log, methodName, result, }) { | ||
switch (result.failureCode) { | ||
@@ -47,3 +50,3 @@ case "run-creation-failed": | ||
default: | ||
assertType(result.failureCode); | ||
(0, utils_1.assertType)(result.failureCode); | ||
throw new Error(`[${methodName}] Unreachable code detected. This is a bug.`); | ||
@@ -50,0 +53,0 @@ } |
@@ -1,3 +0,6 @@ | ||
import { assertType } from "../../../../utils"; | ||
export function graphQLErrorToAbortResult({ graphQLPayload, log, methodName, }) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.graphQLErrorToAbortResult = graphQLErrorToAbortResult; | ||
const utils_1 = require("../../../../utils"); | ||
function graphQLErrorToAbortResult({ graphQLPayload, log, methodName, }) { | ||
switch (graphQLPayload.errorCode) { | ||
@@ -20,3 +23,3 @@ case "forbidden": | ||
default: | ||
assertType(graphQLPayload.errorCode); | ||
(0, utils_1.assertType)(graphQLPayload.errorCode); | ||
throw new Error("Unreachable code detected. This is a bug."); | ||
@@ -23,0 +26,0 @@ } |
@@ -1,3 +0,6 @@ | ||
import { getBackoffMs, sleep } from "../../../../utils"; | ||
export async function retryWithExponentialBackoff({ log, maxRetries, methodName, retriableAbortReasons, runOnce, }) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.retryWithExponentialBackoff = retryWithExponentialBackoff; | ||
const utils_1 = require("../../../../utils"); | ||
async function retryWithExponentialBackoff({ log, maxRetries, methodName, retriableAbortReasons, runOnce, }) { | ||
let attemptNumber = 0; | ||
@@ -18,8 +21,8 @@ let result; | ||
// Else, backoff and retry | ||
const backoffMs = getBackoffMs(attemptNumber); | ||
const backoffMs = (0, utils_1.getBackoffMs)(attemptNumber); | ||
const secondsApproximation = (backoffMs / 1000).toFixed(1); | ||
log.warn(`⏳ [${methodName}] Retrying in ${secondsApproximation} seconds.`); | ||
await sleep(backoffMs); | ||
await (0, utils_1.sleep)(backoffMs); | ||
} while (true); | ||
} | ||
//# sourceMappingURL=retry.js.map |
@@ -1,6 +0,9 @@ | ||
import { callNotifyVCSBranchBuildDeployedMutation } from "../../../api/notify-vcs-branch-build-deployed-mutation"; | ||
import { assertType } from "../../../utils"; | ||
import { domainFailureToAbortResult } from "./lib/domain-failure"; | ||
import { graphQLErrorToAbortResult } from "./lib/graphql-error"; | ||
import { retryWithExponentialBackoff } from "./lib/retry"; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.notifyVCSBranchBuildDeployed = notifyVCSBranchBuildDeployed; | ||
const notify_vcs_branch_build_deployed_mutation_1 = require("../../../api/notify-vcs-branch-build-deployed-mutation"); | ||
const utils_1 = require("../../../utils"); | ||
const domain_failure_1 = require("./lib/domain-failure"); | ||
const graphql_error_1 = require("./lib/graphql-error"); | ||
const retry_1 = require("./lib/retry"); | ||
async function runNotifyVCSBranchBuildDeployedOnce(deps, apiConfig, input) { | ||
@@ -11,8 +14,3 @@ const { baseEnvironmentsMapping, baseVcsBranch, concurrencyLimit, headEnvironmentAlias, headEnvironmentName, headEnvironmentVariables, headVcsBranch, headVcsCommitId, headVcsCommitUrl, pullOrMergeRequestNumber, } = input; | ||
if (baseEnvironmentAlias === undefined) { | ||
log.error(`❌ [notifyVCSBranchBuildDeployed] Could not find a base environment for VCS branch '${baseVcsBranch}'. Make sure you provide ` + | ||
"a mapping for this base branch in the 'baseEnvironmentsMapping' field."); | ||
return { | ||
abortReason: "missing-vcs-branch-to-environment-alias-mapping", | ||
outcome: "aborted", | ||
}; | ||
log.info(`ℹ️ [notifyVCSBranchBuildDeployed] Could not find a base environment for VCS branch '${baseVcsBranch}'. Fall back to use the default base environment`); | ||
} | ||
@@ -39,3 +37,3 @@ let finalConcurrencyLimit = concurrencyLimit; | ||
} | ||
const resp = await callNotifyVCSBranchBuildDeployedMutation(deps, apiConfig, { | ||
const resp = await (0, notify_vcs_branch_build_deployed_mutation_1.callNotifyVCSBranchBuildDeployedMutation)(deps, apiConfig, { | ||
baseEnvironmentAlias, | ||
@@ -52,3 +50,3 @@ concurrencyLimit: finalConcurrencyLimit, | ||
if (resp.isGqlError) { | ||
return graphQLErrorToAbortResult({ | ||
return (0, graphql_error_1.graphQLErrorToAbortResult)({ | ||
graphQLPayload: resp, | ||
@@ -71,4 +69,4 @@ log, | ||
} | ||
assertType(result.outcome); | ||
return domainFailureToAbortResult({ | ||
(0, utils_1.assertType)(result.outcome); | ||
return (0, domain_failure_1.domainFailureToAbortResult)({ | ||
log, | ||
@@ -79,5 +77,5 @@ methodName: "notifyVCSBranchBuildDeployed", | ||
} | ||
export async function notifyVCSBranchBuildDeployed(deps, apiConfig, input) { | ||
async function notifyVCSBranchBuildDeployed(deps, apiConfig, input) { | ||
const { maxRetries = 10 } = input; | ||
return retryWithExponentialBackoff({ | ||
return (0, retry_1.retryWithExponentialBackoff)({ | ||
log: deps.log, | ||
@@ -84,0 +82,0 @@ maxRetries, |
@@ -1,14 +0,17 @@ | ||
import { callNotifyVCSBranchMergeCanceledMutation } from "../../../api/notify-vcs-branch-merge-canceled-mutation"; | ||
import { assertType } from "../../../utils"; | ||
import { domainFailureToAbortResult } from "./lib/domain-failure"; | ||
import { graphQLErrorToAbortResult } from "./lib/graphql-error"; | ||
import { retryWithExponentialBackoff } from "./lib/retry"; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.notifyVCSBranchMergeCanceled = notifyVCSBranchMergeCanceled; | ||
const notify_vcs_branch_merge_canceled_mutation_1 = require("../../../api/notify-vcs-branch-merge-canceled-mutation"); | ||
const utils_1 = require("../../../utils"); | ||
const domain_failure_1 = require("./lib/domain-failure"); | ||
const graphql_error_1 = require("./lib/graphql-error"); | ||
const retry_1 = require("./lib/retry"); | ||
async function runNotifyVCSMergeCanceledOnce(deps, apiConfig, input) { | ||
const log = deps.log; | ||
const { headEnvironmentAlias } = input; | ||
const resp = await callNotifyVCSBranchMergeCanceledMutation(deps, apiConfig, { | ||
const resp = await (0, notify_vcs_branch_merge_canceled_mutation_1.callNotifyVCSBranchMergeCanceledMutation)(deps, apiConfig, { | ||
headEnvironmentAlias, | ||
}); | ||
if (resp.isGqlError) { | ||
return graphQLErrorToAbortResult({ | ||
return (0, graphql_error_1.graphQLErrorToAbortResult)({ | ||
graphQLPayload: resp, | ||
@@ -26,4 +29,4 @@ log, | ||
} | ||
assertType(result.outcome); | ||
return domainFailureToAbortResult({ | ||
(0, utils_1.assertType)(result.outcome); | ||
return (0, domain_failure_1.domainFailureToAbortResult)({ | ||
log, | ||
@@ -34,5 +37,5 @@ methodName: "notifyVCSBranchMergeCanceled", | ||
} | ||
export async function notifyVCSBranchMergeCanceled(deps, apiConfig, input) { | ||
async function notifyVCSBranchMergeCanceled(deps, apiConfig, input) { | ||
const { maxRetries = 10 } = input; | ||
return retryWithExponentialBackoff({ | ||
return (0, retry_1.retryWithExponentialBackoff)({ | ||
log: deps.log, | ||
@@ -39,0 +42,0 @@ maxRetries, |
@@ -1,6 +0,9 @@ | ||
import { callNotifyVCSBranchMergeCompletedMutation } from "../../../api/notify-vcs-branch-merge-completed-mutation"; | ||
import { assertType } from "../../../utils"; | ||
import { domainFailureToAbortResult } from "./lib/domain-failure"; | ||
import { graphQLErrorToAbortResult } from "./lib/graphql-error"; | ||
import { retryWithExponentialBackoff } from "./lib/retry"; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.notifyVCSBranchMergeCompleted = notifyVCSBranchMergeCompleted; | ||
const notify_vcs_branch_merge_completed_mutation_1 = require("../../../api/notify-vcs-branch-merge-completed-mutation"); | ||
const utils_1 = require("../../../utils"); | ||
const domain_failure_1 = require("./lib/domain-failure"); | ||
const graphql_error_1 = require("./lib/graphql-error"); | ||
const retry_1 = require("./lib/retry"); | ||
async function runNotifyVCSBranchMergeCompletedOnce(deps, apiConfig, input) { | ||
@@ -11,10 +14,5 @@ const log = deps.log; | ||
if (baseEnvironmentAlias === undefined) { | ||
log.error(`❌ [notifyVCSBranchMergeCompleted] Could not find a base environment for VCS branch '${vcsBaseBranch}'. Make sure you provide ` + | ||
"a mapping for this base branch in the 'baseEnvironmentsMapping' field."); | ||
return { | ||
abortReason: "missing-vcs-branch-to-environment-alias-mapping", | ||
outcome: "aborted", | ||
}; | ||
log.info(`ℹ️ [notifyVCSBranchMergeCompleted] Could not find a base environment for VCS branch '${vcsBaseBranch}'. Fall back to use the default base environment`); | ||
} | ||
const resp = await callNotifyVCSBranchMergeCompletedMutation(deps, apiConfig, { | ||
const resp = await (0, notify_vcs_branch_merge_completed_mutation_1.callNotifyVCSBranchMergeCompletedMutation)(deps, apiConfig, { | ||
baseEnvironmentAlias, | ||
@@ -24,3 +22,3 @@ headEnvironmentAlias: input.headEnvironmentAlias, | ||
if (resp.isGqlError) { | ||
return graphQLErrorToAbortResult({ | ||
return (0, graphql_error_1.graphQLErrorToAbortResult)({ | ||
graphQLPayload: resp, | ||
@@ -38,4 +36,4 @@ log, | ||
} | ||
assertType(result.outcome); | ||
return domainFailureToAbortResult({ | ||
(0, utils_1.assertType)(result.outcome); | ||
return (0, domain_failure_1.domainFailureToAbortResult)({ | ||
log, | ||
@@ -46,5 +44,5 @@ methodName: "notifyVCSBranchMergeCompleted", | ||
} | ||
export async function notifyVCSBranchMergeCompleted(deps, apiConfig, input) { | ||
async function notifyVCSBranchMergeCompleted(deps, apiConfig, input) { | ||
const { maxRetries = 10 } = input; | ||
return retryWithExponentialBackoff({ | ||
return (0, retry_1.retryWithExponentialBackoff)({ | ||
log: deps.log, | ||
@@ -51,0 +49,0 @@ maxRetries, |
@@ -1,2 +0,3 @@ | ||
export {}; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
//# sourceMappingURL=types.js.map |
@@ -1,12 +0,29 @@ | ||
import { buildFetchWithTimeout } from "../utils"; | ||
import { defaultFetch } from "./defaults/fetch"; | ||
import { defaultLogDriver } from "./defaults/log"; | ||
import { defaultServiceBase } from "./defaults/serviceBase"; | ||
import { attemptNotifyDeploy } from "./domain/attempt-deploy"; | ||
import { generateSignedUrlForRunInputsExecutablesStorage } from "./domain/generateSignedUrls/generate-signed-url-for-run-inputs-executables"; | ||
import { generateSignedUrlForTempTeamStorage } from "./domain/generateSignedUrls/generate-signed-url-for-team-storage"; | ||
import { removeEnvironment, testPreview, } from "./domain/legacy_previewTesting/index"; | ||
import { pollCiGreenlightStatus } from "./domain/poll-ci-greenlight"; | ||
import { makeVCSBranchTestingSDK } from "./domain/vcsBranchTesting"; | ||
export function makeQaWolfSdk({ apiKey, serviceBase = defaultServiceBase, }, { fetch = defaultFetch, log = defaultLogDriver, } = {}) { | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.makeQaWolfSdk = makeQaWolfSdk; | ||
const utils_1 = require("../utils"); | ||
const fetch_1 = require("./defaults/fetch"); | ||
const log_1 = require("./defaults/log"); | ||
const serviceBase_1 = require("./defaults/serviceBase"); | ||
const attempt_deploy_1 = require("./domain/attempt-deploy"); | ||
const generate_signed_url_for_run_inputs_executables_1 = require("./domain/generateSignedUrls/generate-signed-url-for-run-inputs-executables"); | ||
const generate_signed_url_for_team_storage_1 = require("./domain/generateSignedUrls/generate-signed-url-for-team-storage"); | ||
const index_1 = require("./domain/legacy_previewTesting/index"); | ||
const poll_ci_greenlight_1 = require("./domain/poll-ci-greenlight"); | ||
const vcsBranchTesting_1 = require("./domain/vcsBranchTesting"); | ||
function makeQaWolfSdk({ apiKey, serviceBase = serviceBase_1.defaultServiceBase, }, { fetch = fetch_1.defaultFetch, log = log_1.defaultLogDriver, } = {}) { | ||
if (typeof fetch !== "function") { | ||
@@ -18,3 +35,3 @@ throw new Error(`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. | ||
// Versions of fetch may have different default timeouts. For consistency, we explicitly set it to 60 seconds here. | ||
fetch: buildFetchWithTimeout(fetch, 60000), | ||
fetch: (0, utils_1.buildFetchWithTimeout)(fetch, 60000), | ||
log, | ||
@@ -24,18 +41,18 @@ }; | ||
return { | ||
attemptNotifyDeploy: attemptNotifyDeploy.bind(null, deps, apiConfig), | ||
attemptNotifyDeploy: attempt_deploy_1.attemptNotifyDeploy.bind(null, deps, apiConfig), | ||
/** | ||
* @deprecated Use `experimental_vcsBranchTesting` instead. | ||
*/ | ||
experimental_removeEnvironment: removeEnvironment.bind(null, deps, apiConfig), | ||
experimental_removeEnvironment: index_1.removeEnvironment.bind(null, deps, apiConfig), | ||
/** | ||
* @deprecated Use `experimental_vcsBranchTesting` instead. | ||
*/ | ||
experimental_testPreview: testPreview.bind(null, deps, apiConfig), | ||
experimental_vcsBranchTesting: makeVCSBranchTestingSDK(apiConfig, deps), | ||
generateSignedUrlForRunInputsExecutablesStorage: generateSignedUrlForRunInputsExecutablesStorage.bind(null, deps, apiConfig), | ||
generateSignedUrlForTempTeamStorage: generateSignedUrlForTempTeamStorage.bind(null, deps, apiConfig), | ||
pollCiGreenlightStatus: pollCiGreenlightStatus.bind(null, deps, apiConfig), | ||
experimental_testPreview: index_1.testPreview.bind(null, deps, apiConfig), | ||
experimental_vcsBranchTesting: (0, vcsBranchTesting_1.makeVCSBranchTestingSDK)(apiConfig, deps), | ||
generateSignedUrlForRunInputsExecutablesStorage: generate_signed_url_for_run_inputs_executables_1.generateSignedUrlForRunInputsExecutablesStorage.bind(null, deps, apiConfig), | ||
generateSignedUrlForTempTeamStorage: generate_signed_url_for_team_storage_1.generateSignedUrlForTempTeamStorage.bind(null, deps, apiConfig), | ||
pollCiGreenlightStatus: poll_ci_greenlight_1.pollCiGreenlightStatus.bind(null, deps, apiConfig), | ||
}; | ||
} | ||
export * from "./domain/vcsBranchTesting/index"; | ||
__exportStar(require("./domain/vcsBranchTesting/index"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -1,5 +0,12 @@ | ||
export function sleep(ms) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.buildFetchWithTimeout = void 0; | ||
exports.sleep = sleep; | ||
exports.pluralize = pluralize; | ||
exports.assertType = assertType; | ||
exports.getBackoffMs = getBackoffMs; | ||
function sleep(ms) { | ||
return new Promise((resolve) => setTimeout(resolve, ms)); | ||
} | ||
export function pluralize(count) { | ||
function pluralize(count) { | ||
return count === 1 ? "" : "s"; | ||
@@ -10,9 +17,10 @@ } | ||
*/ | ||
export function assertType(_value) { | ||
function assertType(_value) { | ||
// noop | ||
} | ||
export function getBackoffMs(attemptNumber, minWaitMs = 1000, maxWaitMs = 10000) { | ||
function getBackoffMs(attemptNumber, minWaitMs = 1000, maxWaitMs = 10000) { | ||
return Math.min(maxWaitMs, minWaitMs * 1.2 ** attemptNumber); | ||
} | ||
export const buildFetchWithTimeout = (fetch, timeout) => async (...args) => fetch(args[0], { ...args[1], signal: AbortSignal.timeout(timeout) }); | ||
const buildFetchWithTimeout = (fetch, timeout) => async (...args) => fetch(args[0], { ...args[1], signal: AbortSignal.timeout(timeout) }); | ||
exports.buildFetchWithTimeout = buildFetchWithTimeout; | ||
//# sourceMappingURL=utils.js.map |
@@ -0,1 +1,2 @@ | ||
import FakeTimers from "@sinonjs/fake-timers"; | ||
import { type CiGreenlightStatusBase } from "../lib/api/ci-greenlight"; | ||
@@ -35,2 +36,9 @@ export declare function makeVCSBranchTestingSDKForTest({ apiKey }: { | ||
export declare function buildCiGreenlightStatusBase(): CiGreenlightStatusBase; | ||
export declare function setupTests(): { | ||
clock: FakeTimers.InstalledClock; | ||
runGraphQLAssertions: ({ fetchMock, method, }: { | ||
fetchMock: ReturnType<typeof makeVCSBranchTestingSDKForTest>["fetch"]; | ||
method: () => Promise<unknown>; | ||
}) => void; | ||
}; | ||
//# sourceMappingURL=test-lib.d.ts.map |
@@ -1,4 +0,16 @@ | ||
import { jest } from "@jest/globals"; | ||
import { makeVCSBranchTestingSDK } from "../lib/sdk/domain/vcsBranchTesting"; | ||
import { makeQaWolfSdk } from "../lib/sdk/index"; | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.makeVCSBranchTestingSDKForTest = makeVCSBranchTestingSDKForTest; | ||
exports.makeQaWolfSdkForTest = makeQaWolfSdkForTest; | ||
exports.buildResponse = buildResponse; | ||
exports.buildCiGreenlightStatusBase = buildCiGreenlightStatusBase; | ||
exports.setupTests = setupTests; | ||
/* eslint-disable jest/no-export */ | ||
const globals_1 = require("@jest/globals"); | ||
const fake_timers_1 = __importDefault(require("@sinonjs/fake-timers")); | ||
const vcsBranchTesting_1 = require("../lib/sdk/domain/vcsBranchTesting"); | ||
const index_1 = require("../lib/sdk/index"); | ||
const localDummyServiceBase = "http://localhost:80/"; | ||
@@ -10,8 +22,8 @@ const testLogger = { | ||
}; | ||
export function makeVCSBranchTestingSDKForTest({ apiKey }) { | ||
function makeVCSBranchTestingSDKForTest({ apiKey }) { | ||
// Can be used for mocking fetch | ||
const fetch = jest.fn(() => Promise.resolve(buildResponse({}))); | ||
const fetch = globals_1.jest.fn(() => Promise.resolve(buildResponse({}))); | ||
return { | ||
fetch, | ||
sdk: makeVCSBranchTestingSDK({ | ||
sdk: (0, vcsBranchTesting_1.makeVCSBranchTestingSDK)({ | ||
apiKey, | ||
@@ -25,8 +37,8 @@ serviceBase: localDummyServiceBase, | ||
} | ||
export function makeQaWolfSdkForTest({ apiKey }) { | ||
function makeQaWolfSdkForTest({ apiKey }) { | ||
// Can be used for mocking fetch | ||
const fetch = jest.fn(() => Promise.resolve(buildResponse({}))); | ||
const fetch = globals_1.jest.fn(() => Promise.resolve(buildResponse({}))); | ||
return { | ||
fetch, | ||
sdk: makeQaWolfSdk({ | ||
sdk: (0, index_1.makeQaWolfSdk)({ | ||
apiKey, | ||
@@ -40,3 +52,3 @@ serviceBase: localDummyServiceBase, | ||
} | ||
export function buildResponse(response, status = 200) { | ||
function buildResponse(response, status = 200) { | ||
return new Response(JSON.stringify(response), { | ||
@@ -49,3 +61,3 @@ headers: { | ||
} | ||
export function buildCiGreenlightStatusBase() { | ||
function buildCiGreenlightStatusBase() { | ||
return { | ||
@@ -62,2 +74,80 @@ relevantRunId: "foo", | ||
} | ||
function setupTests() { | ||
const clock = fake_timers_1.default.install(); | ||
function runGraphQLAssertions({ fetchMock, method, }) { | ||
afterEach(() => globals_1.jest.resetAllMocks()); | ||
it("should handle retries with GraphQL server-error", async () => { | ||
fetchMock.mockImplementation(async () => { | ||
return buildResponse({ | ||
errors: [ | ||
{ | ||
extensions: [{ code: "INTERNAL" }], | ||
message: "INTERNAL", | ||
}, | ||
], | ||
}); | ||
}); | ||
const expectedValue = { | ||
abortReason: "server-error", | ||
outcome: "aborted", | ||
}; | ||
const promise = method(); | ||
// This will run all pending timers, handy to speedup retry testing. | ||
clock.runAllAsync(); | ||
await expect(promise).resolves.toEqual(expectedValue); | ||
// 1 retry = 2 attempts | ||
expect(fetchMock).toHaveBeenCalledTimes(2); | ||
}); | ||
it("should handle retries with network errors", async () => { | ||
fetchMock.mockRejectedValue(new Error("network error")); | ||
const expectedValue = { | ||
abortReason: "network-error", | ||
outcome: "aborted", | ||
}; | ||
const promise = method(); | ||
// This will run all pending timers, handy to speedup retry testing. | ||
clock.runAllAsync(); | ||
await expect(promise).resolves.toEqual(expectedValue); | ||
// 1 retry = 2 attempts | ||
expect(fetchMock).toHaveBeenCalledTimes(2); | ||
}); | ||
it("should handle GraphQL unauthenticated error", async () => { | ||
fetchMock.mockResolvedValueOnce(buildResponse({ | ||
errors: [ | ||
{ | ||
extensions: [{ code: "UNAUTHENTICATED" }], | ||
message: "UNAUTHENTICATED", | ||
}, | ||
], | ||
})); | ||
const expectedValue = { | ||
abortReason: "unauthenticated", | ||
outcome: "aborted", | ||
}; | ||
await expect(method()).resolves.toEqual(expectedValue); | ||
}); | ||
it("should handle GraphQL forbidden error", async () => { | ||
fetchMock.mockResolvedValueOnce(buildResponse({ | ||
errors: [ | ||
{ | ||
extensions: [{ code: "FORBIDDEN" }], | ||
message: "FORBIDDEN", | ||
}, | ||
], | ||
})); | ||
const expectedValue = { | ||
abortReason: "forbidden", | ||
outcome: "aborted", | ||
}; | ||
await expect(method()).resolves.toEqual(expectedValue); | ||
}); | ||
} | ||
afterAll(() => { | ||
clock.uninstall(); | ||
}); | ||
return { | ||
clock, | ||
runGraphQLAssertions, | ||
}; | ||
} | ||
//# sourceMappingURL=test-lib.js.map |
@@ -48,3 +48,3 @@ import { type ApiConfig } from "../api-types"; | ||
}; | ||
export type CiGreenlightCompletedSuiteDetails = { | ||
export type CiGreenlightBugData = { | ||
blockingBugsCount: number; | ||
@@ -56,2 +56,6 @@ blockingBugUrls: string[]; | ||
}; | ||
/** | ||
* @deprecated This type will be removed in the next major version. Use `CiGreenlightBugData` instead. | ||
*/ | ||
export type CiGreenlightCompletedSuiteDetails = CiGreenlightBugData; | ||
export type CiGreenlightStatusBase = { | ||
@@ -71,12 +75,10 @@ relevantRunId: string; | ||
*/ | ||
export type CiGreenlightStatus = CiGreenlightStatusBase & ({ | ||
blockingBugsCount: number; | ||
blockingBugUrls: string[]; | ||
export type CiGreenlightStatus = CiGreenlightStatusBase & (({ | ||
greenlight: boolean; | ||
nonBlockingBugsCount: number; | ||
nonBlockingBugUrls: string[]; | ||
reproducedBugs: CiGreenlightBugDetails[]; | ||
runStage: "completed"; | ||
} | { | ||
} & CiGreenlightBugData) | ({ | ||
greenlight: false; | ||
runStage: "underReview"; | ||
} & CiGreenlightBugData) | { | ||
greenlight: false; | ||
runStage: "initializing" | "underReview" | "canceled"; | ||
@@ -83,0 +85,0 @@ }); |
@@ -5,3 +5,3 @@ import { type ApiConfig } from "../api-types"; | ||
export interface NotifyVCSBranchBuildDeployedMutationInput { | ||
baseEnvironmentAlias: string; | ||
baseEnvironmentAlias: string | undefined; | ||
concurrencyLimit: number | undefined; | ||
@@ -8,0 +8,0 @@ headEnvironmentAlias: string; |
@@ -5,3 +5,3 @@ import { type ApiConfig } from "../api-types"; | ||
export interface NotifyVCSBranchMergeCompletedMutationInput { | ||
baseEnvironmentAlias: string; | ||
baseEnvironmentAlias: string | undefined; | ||
headEnvironmentAlias: string; | ||
@@ -8,0 +8,0 @@ } |
@@ -6,2 +6,8 @@ import { type CiGreenlightStatus } from "../../api/ci-greenlight"; | ||
/** | ||
* If true, the job will be aborted when a superseding run is detected. | ||
* | ||
* @default false | ||
*/ | ||
abortOnSuperseded: boolean; | ||
/** | ||
* Maximum number of network operations retries before aborting the job. | ||
@@ -38,3 +44,3 @@ * | ||
export type PollCiGreenlightHttpAbortReason = "4XX-client-error" | "404-run-not-found" | "5XX-server-error" | "XXX-other-http-code"; | ||
export type PollCiGreenlightNonHttpAbortReason = "poll-timed-out" | "run-canceled" | "network-error"; | ||
export type PollCiGreenlightNonHttpAbortReason = "poll-timed-out" | "run-canceled" | "network-error" | "superseded-run"; | ||
export type PollCiGreenlightAbortReason = PollCiGreenlightNonHttpAbortReason | PollCiGreenlightHttpAbortReason; | ||
@@ -41,0 +47,0 @@ export type PollCiGreenlightStatus = { |
@@ -8,4 +8,4 @@ import { type SdkDependencies } from "../../dependencies"; | ||
export type { NotifyBuildDeployedInput, NotifyBuildDeployedResult, } from "./notify-vcs-branch-build-deployed"; | ||
export type { NotifyVCSBranchMergeCanceledInput, NotifyMergeCanceledResult, } from "./notify-vcs-branch-merge-canceled"; | ||
export type { NotifyVCSBranchMergeCompletedInput, NotifyMergeCompletedResult, } from "./notify-vcs-branch-merge-completed"; | ||
export type { NotifyMergeCanceledResult, NotifyVCSBranchMergeCanceledInput, } from "./notify-vcs-branch-merge-canceled"; | ||
export type { NotifyMergeCompletedResult, NotifyVCSBranchMergeCompletedInput, } from "./notify-vcs-branch-merge-completed"; | ||
export declare function makeVCSBranchTestingSDK({ apiKey, serviceBase, }: { | ||
@@ -12,0 +12,0 @@ apiKey: string; |
@@ -0,1 +1,2 @@ | ||
import FakeTimers from "@sinonjs/fake-timers"; | ||
import { type CiGreenlightStatusBase } from "../lib/api/ci-greenlight"; | ||
@@ -35,2 +36,9 @@ export declare function makeVCSBranchTestingSDKForTest({ apiKey }: { | ||
export declare function buildCiGreenlightStatusBase(): CiGreenlightStatusBase; | ||
export declare function setupTests(): { | ||
clock: FakeTimers.InstalledClock; | ||
runGraphQLAssertions: ({ fetchMock, method, }: { | ||
fetchMock: ReturnType<typeof makeVCSBranchTestingSDKForTest>["fetch"]; | ||
method: () => Promise<unknown>; | ||
}) => void; | ||
}; | ||
//# sourceMappingURL=test-lib.d.ts.map |
{ | ||
"name": "@qawolf/ci-sdk", | ||
"version": "0.18.0", | ||
"version": "0.20.0", | ||
"description": "A simple SDK for interacting with QAWolf in CI scripts.", | ||
@@ -5,0 +5,0 @@ "type": "commonjs", |
@@ -76,2 +76,5 @@ # QAWolf CI SDK | ||
}, | ||
// Optional: Defaults to false. When set to true, the polling operation | ||
// will abort when the run is superseded. | ||
abortOnSuperseded: false, | ||
}); | ||
@@ -380,13 +383,21 @@ if (outcome !== "success") { | ||
## v0.20.0 | ||
- In `pollCiGreenlightStatus`, bug data fields are now available in the `"underReview"` run stage. | ||
## v0.19.0 | ||
- Add `abortOnSuperseded` option to `pollCiGreenlightStatus` to allow for aborting the polling operation when the run is superseded. | ||
## v0.18.0 | ||
- Add generateSignedUrlForRunInputsExecutablesStorage function to generate a signed url used to upload files to the Run Inputs Executables bucket. | ||
- Add `generateSignedUrlForRunInputsExecutablesStorage` function to generate a signed url used to upload files to the Run Inputs Executables bucket. | ||
## v0.17.1 | ||
- Add detailed feedback when generateSignedUrlForTempTeamStorage fails. | ||
- Add detailed feedback when `generateSignedUrlForTempTeamStorage` fails. | ||
## v0.17.0 | ||
- Add generateSignedUrlForTempTeamStorage function to be used in customer's CI pipeline. | ||
- Add `generateSignedUrlForTempTeamStorage` function to be used in customer's CI pipeline. | ||
@@ -396,3 +407,3 @@ ## v0.16.0 | ||
- Document experimental VCS Branch/PR Testing features. | ||
- Deprecate `experimental_testPreview` and `experimental_removeEnvironment`. These methods will be removed in the next release. | ||
- Deprecate `experimental_testPreview` and `experimental_removeEnvironment`. These methods will be removed in an upcoming release. | ||
@@ -399,0 +410,0 @@ ## v0.15.8 |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
489757
6489
497