@qawolf/ci-sdk
Advanced tools
Comparing version 0.12.1 to 0.13.0
@@ -6,2 +6,4 @@ "use strict"; | ||
const ci_greenlight_js_1 = require("../../api/ci-greenlight.js"); | ||
// If you change these values, make sure you update the JSDoc | ||
// comments in the PollConfig type. | ||
const safeDefaults = { | ||
@@ -12,2 +14,3 @@ maxRetries: 10, | ||
runUnderReviewInterval: 60 * 1000, | ||
pollTimeout: 120 * 60 * 1000, | ||
}; | ||
@@ -17,5 +20,7 @@ async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChanged: onRunStageChanged = () => void 0, ...pollConfig }) { | ||
const { log } = deps; | ||
const { maxRetries = safeDefaults.maxRetries, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, } = pollConfig; | ||
const { maxRetries = safeDefaults.maxRetries, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, pollTimeout = safeDefaults.pollTimeout, } = pollConfig; | ||
let currentStatus = undefined; | ||
while (true) { | ||
const startedAt = Date.now(); | ||
let hasTimedOut = false; | ||
while (!(hasTimedOut = Date.now() - startedAt > pollTimeout)) { | ||
const responseState = await (0, ci_greenlight_js_1.fetchCiGreenlightStatus)(apiConfig, { | ||
@@ -26,3 +31,7 @@ runId, | ||
log.error(`š« Unrecoverable error (status ${responseState.httpStatus}) from CI greenlight, aborting.`); | ||
return { outcome: "aborted" }; | ||
return { | ||
outcome: "aborted", | ||
abortReason: "4XX-client-error", | ||
httpStatus: responseState.httpStatus, | ||
}; | ||
} | ||
@@ -36,3 +45,20 @@ if (!responseState.ok) { | ||
: ""} from CI greenlight, aborting after ${maxRetries} attempts.`); | ||
return { outcome: "aborted" }; | ||
if (responseState.errorType === "network") | ||
return { | ||
outcome: "aborted", | ||
abortReason: "network-error", | ||
httpStatus: undefined, | ||
}; | ||
let abortReason = "XXX-other-http-code"; | ||
if (responseState.errorType === "not-found") | ||
abortReason = "404-run-not-found"; | ||
else if (responseState.errorType === "server") | ||
abortReason = "5XX-server-error"; | ||
else | ||
(0, utils_js_1.assertType)(responseState); | ||
return { | ||
outcome: "aborted", | ||
abortReason, | ||
httpStatus: responseState.httpStatus, | ||
}; | ||
} | ||
@@ -96,2 +122,19 @@ const { errorType, httpStatus } = responseState; | ||
} | ||
if (runStage === "canceled") { | ||
log.info(`š« Run was canceled. Aborting... Please contact support.\n${urlInfo}`); | ||
return { | ||
outcome: "aborted", | ||
abortReason: "run-canceled", | ||
httpStatus: undefined, | ||
}; | ||
} | ||
// Non-terminal run stages | ||
if (hasTimedOut) { | ||
log.warn(`ā Poll timed out after ${pollTimeout / 1000}s. Aborting...`); | ||
return { | ||
outcome: "aborted", | ||
abortReason: "poll-timed-out", | ||
httpStatus: undefined, | ||
}; | ||
} | ||
if (runStage === "initializing") { | ||
@@ -105,10 +148,14 @@ log.info(`ā³ Run is in progress... ${urlInfo}`); | ||
} | ||
else if (runStage === "canceled") { | ||
log.info(`š« Run was canceled. Aborting... Please contact support.\n${urlInfo}`); | ||
return { outcome: "aborted" }; | ||
else { | ||
(0, utils_js_1.assertType)(runStage); | ||
throw new Error(`Unexpected run stage: ${runStage}`); | ||
} | ||
else | ||
throw new Error(`Unexpected run stage: ${runStage}`); | ||
} | ||
log.warn(`ā Poll timed out after ${pollTimeout / 1000}s. Aborting...`); | ||
return { | ||
outcome: "aborted", | ||
abortReason: "poll-timed-out", | ||
httpStatus: undefined, | ||
}; | ||
} | ||
exports.pollCiGreenlightStatus = pollCiGreenlightStatus; |
@@ -1,3 +0,5 @@ | ||
import { sleep, pluralize } from "../../utils.js"; | ||
import { sleep, pluralize, assertType } from "../../utils.js"; | ||
import { fetchCiGreenlightStatus, } from "../../api/ci-greenlight.js"; | ||
// If you change these values, make sure you update the JSDoc | ||
// comments in the PollConfig type. | ||
const safeDefaults = { | ||
@@ -8,2 +10,3 @@ maxRetries: 10, | ||
runUnderReviewInterval: 60 * 1000, | ||
pollTimeout: 120 * 60 * 1000, | ||
}; | ||
@@ -13,5 +16,7 @@ export async function pollCiGreenlightStatus(deps, apiConfig, { runId, onRunStageChanged: onRunStageChanged = () => void 0, ...pollConfig }) { | ||
const { log } = deps; | ||
const { maxRetries = safeDefaults.maxRetries, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, } = pollConfig; | ||
const { maxRetries = safeDefaults.maxRetries, retryInterval = safeDefaults.retryInterval, runInProgressInterval = safeDefaults.runInProgressInterval, runUnderReviewInterval = safeDefaults.runUnderReviewInterval, pollTimeout = safeDefaults.pollTimeout, } = pollConfig; | ||
let currentStatus = undefined; | ||
while (true) { | ||
const startedAt = Date.now(); | ||
let hasTimedOut = false; | ||
while (!(hasTimedOut = Date.now() - startedAt > pollTimeout)) { | ||
const responseState = await fetchCiGreenlightStatus(apiConfig, { | ||
@@ -22,3 +27,7 @@ runId, | ||
log.error(`š« Unrecoverable error (status ${responseState.httpStatus}) from CI greenlight, aborting.`); | ||
return { outcome: "aborted" }; | ||
return { | ||
outcome: "aborted", | ||
abortReason: "4XX-client-error", | ||
httpStatus: responseState.httpStatus, | ||
}; | ||
} | ||
@@ -32,3 +41,20 @@ if (!responseState.ok) { | ||
: ""} from CI greenlight, aborting after ${maxRetries} attempts.`); | ||
return { outcome: "aborted" }; | ||
if (responseState.errorType === "network") | ||
return { | ||
outcome: "aborted", | ||
abortReason: "network-error", | ||
httpStatus: undefined, | ||
}; | ||
let abortReason = "XXX-other-http-code"; | ||
if (responseState.errorType === "not-found") | ||
abortReason = "404-run-not-found"; | ||
else if (responseState.errorType === "server") | ||
abortReason = "5XX-server-error"; | ||
else | ||
assertType(responseState); | ||
return { | ||
outcome: "aborted", | ||
abortReason, | ||
httpStatus: responseState.httpStatus, | ||
}; | ||
} | ||
@@ -92,2 +118,19 @@ const { errorType, httpStatus } = responseState; | ||
} | ||
if (runStage === "canceled") { | ||
log.info(`š« Run was canceled. Aborting... Please contact support.\n${urlInfo}`); | ||
return { | ||
outcome: "aborted", | ||
abortReason: "run-canceled", | ||
httpStatus: undefined, | ||
}; | ||
} | ||
// Non-terminal run stages | ||
if (hasTimedOut) { | ||
log.warn(`ā Poll timed out after ${pollTimeout / 1000}s. Aborting...`); | ||
return { | ||
outcome: "aborted", | ||
abortReason: "poll-timed-out", | ||
httpStatus: undefined, | ||
}; | ||
} | ||
if (runStage === "initializing") { | ||
@@ -101,9 +144,13 @@ log.info(`ā³ Run is in progress... ${urlInfo}`); | ||
} | ||
else if (runStage === "canceled") { | ||
log.info(`š« Run was canceled. Aborting... Please contact support.\n${urlInfo}`); | ||
return { outcome: "aborted" }; | ||
else { | ||
assertType(runStage); | ||
throw new Error(`Unexpected run stage: ${runStage}`); | ||
} | ||
else | ||
throw new Error(`Unexpected run stage: ${runStage}`); | ||
} | ||
log.warn(`ā Poll timed out after ${pollTimeout / 1000}s. Aborting...`); | ||
return { | ||
outcome: "aborted", | ||
abortReason: "poll-timed-out", | ||
httpStatus: undefined, | ||
}; | ||
} |
@@ -5,7 +5,36 @@ import { CiGreenlightStatus } from "../../api/ci-greenlight.js"; | ||
export type PollConfig = { | ||
/** | ||
* Maximum number of network operations retries before aborting the job. | ||
* | ||
* @default 10 | ||
*/ | ||
maxRetries: number; | ||
/** | ||
* Interval in milliseconds between network operations retries. | ||
* | ||
* @default 10 seconds | ||
*/ | ||
retryInterval: number; | ||
/** | ||
* Interval in milliseconds between polling for a run in progress. | ||
* | ||
* @default 30 seconds | ||
*/ | ||
runInProgressInterval: number; | ||
/** | ||
* Interval in milliseconds between polling for a run under review. | ||
* | ||
* @default 60 minutes | ||
*/ | ||
runUnderReviewInterval: number; | ||
/** | ||
* Timeout in milliseconds before aborting this polling operation. | ||
* | ||
* @default 120 minutes | ||
*/ | ||
pollTimeout: number; | ||
}; | ||
export type HttpRelatedAbortReason = "4XX-client-error" | "404-run-not-found" | "5XX-server-error" | "XXX-other-http-code"; | ||
export type NonHttpRelatedAbortReason = "poll-timed-out" | "run-canceled" | "network-error"; | ||
export type AbortReason = NonHttpRelatedAbortReason | HttpRelatedAbortReason; | ||
export type PollCiGreenlightStatus = { | ||
@@ -32,2 +61,11 @@ /** | ||
outcome: "aborted"; | ||
abortReason: HttpRelatedAbortReason; | ||
httpStatus: number; | ||
} | { | ||
/** | ||
* The run was aborted due to an unrecoverable error. | ||
*/ | ||
outcome: "aborted"; | ||
abortReason: NonHttpRelatedAbortReason; | ||
httpStatus: undefined; | ||
}; | ||
@@ -34,0 +72,0 @@ export type PollCiGreenlightParams = { |
{ | ||
"name": "@qawolf/ci-sdk", | ||
"version": "0.12.1", | ||
"version": "0.13.0", | ||
"description": "A simple SDK for interacting with QAWolf in CI scripts.", | ||
@@ -5,0 +5,0 @@ "type": "module", |
@@ -104,2 +104,9 @@ # QAWolf CI SDK | ||
## v0.13.0 | ||
- New `pollTimeout` parameter for `pollCiGreenlightStatus` to allow for a custom | ||
timeout in milliseconds for the polling operation. It now defaults to two hours. | ||
- New `abortReason` and `httpStatus` fields added to the `PollCiGreenlightStatus` type | ||
with `"aborted"` outcome to provide more context on why the poll was aborted. | ||
## v0.12.1 | ||
@@ -106,0 +113,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
48480
1090
160