Skip to main content
@qawolf/ci-sdk is a TypeScript package for notifying QA Wolf of a deploy from your CI pipeline and gating the pipeline on the result. It calls the same public API the Webhook page documents, with typed inputs taken from the published API contract. SDK functions do not throw. Each returns a result object with an outcome field, and your pipeline branches on it to decide whether the step passes or fails. The guide for wiring it into a pipeline is Node.js SDK. This page is the function-by-function reference. This page documents 3.3.0. deployment.reportStatus and deployment.waitForVerdict need 3.1.0 or later, so a pipeline on an earlier version has only the legacy functions and upgrades before wiring one up.

Installation

Requires Node.js 24.14.1 or later, below 25. The package is published as ESM only: import it with import, or from CommonJS with await import("@qawolf/ci-sdk"). require("@qawolf/ci-sdk") does not resolve.

makeQaWolfSdk

The entry point for every function. Pass your API key to initialize.

Options

A second argument injects dependencies. Each is optional: Returns an object with these functions:
  • deployment.reportStatus — reports a deployment. A deployment’s first success report is what evaluates triggers and starts a run.
  • deployment.waitForVerdict — blocks until QA Wolf can say whether the deployment’s tests passed.
  • notifyTerminatedEphemeralEnvironment — tells QA Wolf an ephemeral environment is gone.
  • generateSignedUrlForRunInputsExecutablesStorage and generateSignedUrlForTempTeamStorage — signed upload URLs for files a run needs.
  • attemptNotifyDeploy, pollCiGreenlightStatus and makePollCiGreenlightStatusIterator — the legacy functions. They report through the deploy_success webhook, which triggers do not see.
detectProviderDeploymentId is a standalone export rather than a method; see below.

API keys and workspaceId

Every call acts on exactly one workspace.
  • A workspace API key belongs to one workspace. deployment.reportStatus still requires workspaceId, and it has to name that workspace; naming another fails with unauthorized.
  • An organization API key or a user API key can reach several workspaces, so workspaceId picks one.
Find the id under Workspace Settings → API Keys. The legacy functions and the signed URL functions take workspaceId as an optional field; see each function for what happens when it is omitted.

deployment.reportStatus

Reports a deployment to QA Wolf through the public deployment.reportStatus API. The parameters are the API’s own input, so Webhook and Deployments describe how each field is read. Example:

Parameters

The input is validated strictly: a field the contract does not know, or environment carrying both id and name, is an invalid-request. ReportDeploymentParams is the exported type.
Send environment.ephemeral: true for every preview deploy. A report that omits it is accepted and creates a permanent environment, one per pull request, that is never torn down.

Result

Branch on outcome: The response carries the deployment only, never the resulting runs. deployment.waitForVerdict is how a pipeline learns what the runs decided.
outcome: "reported" means QA Wolf recorded the deployment, not that a trigger matched it. Whether a run starts is decided afterwards, by your triggers.

detectProviderDeploymentId

Composes a providerDeploymentId from the variables your CI system already sets. The id is distinct for every job definition and every re-run, so a retried job or a second job deploying alongside the first gets its own deployment rather than reporting into one whose first success already evaluated triggers. Example:

Options

Result

The helper is optional. providerDeploymentId is always required on the report, and any value that changes on every re-run and differs between concurrent deploys works.

deployment.waitForVerdict

Blocks until QA Wolf can say whether a deployment’s tests passed. Give it the deployment.id the report returned; resolving that to the runs the triggers created, and those runs to a status, happens inside. Example:
Set timeout below your CI job’s own time limit. When the job’s limit fires first, the job is killed with no run link and no explanation. When timeout fires first, the result is timed-out with the stage, the elapsed time and every run URL the wait knew about.

Options

Every field except deploymentId is optional. Durations are in milliseconds. The stages onProgress receives, in order:
  • waiting-for-evaluation — QA Wolf has not yet evaluated the deployment’s triggers.
  • waiting-for-run — triggers matched and at least one is still creating a run. Carries matchedTriggerCount.
  • waiting-for-verdict — every run is known and at least one is still executing. Carries runs.

Result

Branch on outcome: not-tested is a separate answer from passed. A deployment no trigger matched was not tested, which is a different fact from tests passing, and your pipeline decides what it is worth. reason is "no-trigger-matched" when every trigger was evaluated and none matched, or "no-run-created" when a trigger matched and something stopped it from creating a run; each entry in triggers then carries triggerName, a message for the log and, for no-run-created, a stable reason code to branch on. superseded is what a cancel-in-progress pipeline looks like from the older job: the newer deployment’s job carries the verdict. Reserve a distinct exit code for it when your CI should treat the job as skipped rather than failed. Each entry in runs: DeploymentVerdict, VerdictRun, VerdictStage, TriggerNote and NotTestedReason are the exported types. The same shape is published as deploymentVerdictSchema in @qawolf/api-contracts.

notifyTerminatedEphemeralEnvironment

Tells QA Wolf that an ephemeral environment has been terminated. QA Wolf stops the runs targeting it and promotes any flow changes to the base environment. See webhooks/environment_terminated for the underlying endpoint. With a connected GitHub or GitLab integration, QA Wolf hears about the pull request closing from the code host, and this call is redundant. Example:

Input fields

Pass exactly one of the following to identify the environment: environmentAlias and deploymentUrl also take workspaceId. It is optional; an organization or user key that omits it acts on the organization’s first-created workspace, and the result carries a warning naming it. NotifyTerminatedEphemeralEnvironmentInput is the exported type.

Result fields

generateSignedUrlForRunInputsExecutablesStorage

Generates a signed URL for uploading a run input executable (APK, AAB, DEB, IPA, ZIP, CSV, PDF) to QA Wolf. See v0/run-inputs-executables-signed-urls for the underlying endpoint, and Mobile build testing for the pipeline it belongs to. Example:

Input fields

Response fields

A failed request from this function reports abortReason: "client-network-error" and httpStatus: 0 whatever the real status was. The SDK logs the real status on the line above, so read the log rather than branching on abortReason. A 400 from an organization or user key most often means workspaceId was not sent.
generateSignedUrlForTempTeamStorage takes the same input and returns the same fields, for files that are not executables.

Legacy functions

attemptNotifyDeploy and pollCiGreenlightStatus report through the legacy deploy_success webhook, which feeds legacy triggers only. A trigger never sees a deployment they send. They were deprecated in 3.1.0 and are still exported in 3.3.0: legacy describes the path they report through, not an old version of the package. They keep working unchanged, print no warning, and have no removal date. A new integration uses deployment.reportStatus and deployment.waitForVerdict.
Moving a pipeline off them: deploymentType becomes environment.name; branch and sha move into metadata; providerDeploymentId is new and required, and subsumes deduplicationKey; hostingService disappears, since the code host comes from your integration; variables becomes environmentVariables. There is no skipped outcome, because whether a trigger matched is not known at report time; deployment.waitForVerdict answers not-tested instead.

attemptNotifyDeploy

Notifies QA Wolf of a successful deployment through webhooks/deploy_success. Example:

DeployConfig fields

DeployConfig is a union of GitHubDeployConfig, GitLabDeployConfig and EphemeralDeployConfig. Every field is declared on the type, so pass undefined for the ones you do not use.

Result fields

pollCiGreenlightStatus

Polls v0/ci-greenlight for a run id until the run completes. The run id comes from attemptNotifyDeploy, so this function only works for pipelines on the legacy path. Example:

Options

Result fields

makePollCiGreenlightStatusIterator

An async generator over the same poll, for a pipeline that needs to stop early on its own criteria. Takes the same options as pollCiGreenlightStatus except onRunStageChanged. Example:
Each iteration is either a status update or an abort:
Handle every run stage in the switch. The default: status.runStage satisfies never arm makes TypeScript error when a stage is added and the code does not handle it, instead of silently passing the job.

Versioning

The package follows SemVer.
  • Depend on it with the ^ range operator. Patch and minor releases do not introduce breaking changes.
  • A major version bump marks a breaking change, announced in advance.
  • Only top-level exports are covered. New fields in response types, and changes to log output, are not breaking changes.
Minimum versions for the functions on this page: The changelog is in the package’s README on npm.
Last modified on September 16, 2026