This guide is for teams that do not use Fastlane or want a single, flexible way to upload mobile builds and trigger test runs from any CI system. Use the QA Wolf CI SDK if your mobile builds are produced directly in CI scripts; you want the same integration approach for mobile and web testing; you are not using GitHub Actions or prefer not to rely on prebuilt actions; or you need fine-grained control over when artifacts are uploaded and runs are triggered. This guide assumes only that your CI system can run Node.js.
Mobile build artifacts must follow consistent naming conventions so QA Wolf can correctly associate each build with the right environment and make failures easier to diagnose.The artifact name is used to identify:
If this step completes successfully, the artifact is uploaded and available for test runs.Full implementationThe following example includes both artifact upload and deploy notification in a single script.
Javascript
import { type DeployConfig, makeQaWolfSdk } from "@qawolf/ci-sdk";import fs from "fs/promises";import path from "path";const { generateSignedUrlForRunInputsExecutablesStorage, attemptNotifyDeploy } = makeQaWolfSdk({ apiKey: "qawolf_xxxxx", });(async () => { const playgroundFileLocation = await uploadRunArtifact("/FileLocation"); if (playgroundFileLocation) { const deployConfig: DeployConfig = { branch: undefined, commitUrl: undefined, deduplicationKey: undefined, deploymentType: undefined, deploymentUrl: undefined, ephemeralEnvironment: undefined, hostingService: undefined, sha: undefined, variables: { RUN_INPUT_PATH: playgroundFileLocation, // for mobile apps, the team may request that you use a different // variable name here, such as ANDROID_APP }, }; const result = await attemptNotifyDeploy(deployConfig); if (result.outcome !== "success") { // Fail the job. process.exit(1); } const runId = result.runId; }})();async function uploadRunArtifact(filePath: string): Promise<string> { const fileName = path.basename(filePath); const signedUrlResponse = await generateSignedUrlForRunInputsExecutablesStorage({ // for mobile apps, we prefer static filenames based on the environment name // for example, use `app_staging.apk` for the Staging environment destinationFilePath: fileName, }); if ( signedUrlResponse?.success && signedUrlResponse.playgroundFileLocation && signedUrlResponse.uploadUrl ) { const fileBuffer = await fs.readFile(filePath); const url = signedUrlResponse.uploadUrl; try { const response = await fetch(url, { method: "PUT", body: fileBuffer, headers: { "Content-Type": "application/octet-stream", }, }); if (!response.ok) { return ""; } } catch (error) { return ""; } // for mobile apps, we request that you include this prefix path // return `/home/wolf/run-inputs-executables/${signedUrlResponse.playgroundFileLocation}`; // for other apps return signedUrlResponse.playgroundFileLocation; } return "";}
If uploads succeed but no runs start: Mobile triggers may not yet be enabled. Contact QA Wolf to complete platform configuration.
If the artifact is not found during execution: Verify that the artifact basename matches your naming conventions, and the returned path is used when triggering the run.
If you see authentication errors: Verify that QAWOLF_API_KEY is configured correctly in your CI environment.
If you encounter Node.js errors: Ensure Node.js 18 or later is available in the CI job.