Common Patterns
These patterns apply to every CI system. The platform recipes below differ only in how they pass in the secrets.-
Always pass
--headless. CI runners have no display. -
Always set
--timeout <seconds>, so a hung run cannot block the pipeline. -
Authenticate with
--usernameand--access-keyfrom CI secrets. Do not callkane-cli loginin CI: that flow opens a browser for OAuth and will not work on a runner. -
Provide a start URL. A CI run cannot prompt for input. If the objective names no site, no
--urlflag is passed, and nodefault_urlis configured, the run fails fast instead of waiting. The simplest fix is to start the objective with the site (“Go to https://… and …”) or pass--url <url>. To start from the browser’s current page on purpose, add--allow-missing-url. See Default start URL. -
Load test data with
--variables-file <path>. Commit the file to your repo without secret values, or generate it before the step, filling values from CI secrets. A{{name}}with no value does not change the exit code on its own. Kane CLI warns before the browser starts and then types the name as written. If a step fails because of that literal text, the job fails as usual. The warning is awarningline on stdout withcode: "unresolved_variables". If a missing value should block the pipeline, fail the step when that line appears. -
Project and folder are optional. To file uploads under a specific Test Manager project or folder, set them in advance with
kane-cli config project <id>andkane-cli config folder <id>. Find the IDs withkane-cli projects listandkane-cli folders list. If you skip this, Kane CLI picks a default project and folder on the first run and reports which ones it chose. See Test Manager Integration. -
Check the exit code. In short:
0passed,1failed,2error,3timeout or cancellation. The full mapping is in Exit Codes. -
Archive the evidence pack. Name a
kane-cli runwith--name <name>, and Kane CLI copies its sealed evidence pack into.testmuai/evidence/in the workspace.testmd runandtestrun runalways write their pack there. Archive that folder as a CI artifact. Without--name, a single run keeps its pack only in its session folder under~/.testmuai/kaneai/sessions/, outside the workspace. -
Run whole suites with one command. If your repo has committed
_test.mdtests, prefer onetestruninvocation over a shell loop:The suite runs as one execution, with one exit code (0all passed,1any failure,2invalid plan,3cancelled) and one sealed evidence pack. Archive.testmuai/evidence/*.evidenceas a CI artifact so anyone can open it in the viewer. See Batch Runs (testrun). -
Run the suite on the cloud grid when your runner cannot.
kane-cli testrun run … --remoteturns the suite into one HyperExecute job. The grid supplies Chrome on a macOS runner, or a virtual Android emulator or iOS simulator for mobile_test.mdtests, so your runner needs no Chrome, Xcode, or Android Studio.--parallel Nspreads the tests across N grid runners. The recordings and the evidence pack come back to your checkout, just as if the suite had run on your machine.This requires a plan with HyperExecute macOS runners. Web and mobile tests must go in separate runs. Choose devices withkane-cli devices list --target emulator|simulator --remote, and allow a timeout of about 10 minutes. See Remote Runs.
KANE_CLI_CDP_TIMEOUT_MS: how long each launch attempt waits for Chrome to be ready. Default30000.KANE_CLI_CDP_RETRIES: how many times to retry the launch after the first attempt. Default2.
KANE_CLI_CHROME_PATH. See Chrome environment variables.
Authentication in CI/CD
Pass credentials directly on the run command using environment variables from your secrets store:Exit Codes
CI/CD Checklist
- Always use
--headlessand--agent: no display server in CI - Set
--timeout: prevents pipeline hangs (e.g.--timeout 300) - Set
--max-steps: caps run length (e.g.--max-steps 50) - Use
--variables-file: load test data from a committed config file - Store credentials as secrets: never hardcode in pipeline files
Platform Guides
- GitHub Actions
- GitLab CI
- Jenkins
- Bitbucket Pipelines
- Docker / Generic
Store To run your committed tests instead, replace In this workflow,
LT_USERNAME and LT_ACCESS_KEY as repository secrets under Settings > Secrets and variables > Actions.Use the official action. The Kane CLI repository ships a GitHub Action, LambdaTest/kane-cli/integrations/github-action/kane-cli-browser-run@main. In one step, it sets up Node.js, Chrome, and Kane CLI on the runner, signs in, and runs either one plain-English objective or every committed _test.md file that matches a glob as one testrun suite, in headless Chrome. It uploads the sealed evidence pack as an artifact kept for 30 days, links it to the hosted evidence viewer, writes the results to the job summary, posts the verdict as a pull request comment, and fails the check on any non-zero exit.objective with test-files: "tests/**/*_test.md", and set parallel for more Chrome workers. @main tracks the latest action. Pin a release tag of the kane-cli repository for a fixed version. Pull requests from forks get a read-only token, so the action skips the comment there. All inputs, outputs, and example workflows are in the action’s README.Or call Kane CLI yourself. This workflow installs Chrome and Kane CLI, runs one objective, and uploads the evidence:--name puts the run’s sealed evidence pack in .testmuai/evidence/, where the upload step finds it. When the job runs saved tests with testmd run or testrun run, **/output-*/Result.md adds each test’s report, which names the step that failed and why. include-hidden-files: true is required, because upload-artifact skips files inside folders whose names start with a dot, such as .testmuai/.Running Multiple Tests
Run several tests and fail the pipeline if any fail:Variables in CI/CD
Commit a non-secret variables file to your repo, and inject secrets at runtime:A shared context store in CI
When your team shares the context graph through a shared location, your pipeline can use the same store. Clone it once, pull before each run, and push the facts the run produced afterwards. The sync commands never call the agent and never spend credits. The run between them,kane-cli context extract below, is an ordinary extraction and consumes credits like any other.
-
Authenticate without a person. The method depends on the location:
- GitHub over HTTPS: set
KANE_SYNC_GIT_TOKENfrom a CI secret. Use a repository-scoped personal access token with Contents read and write, or a GitHub App installation token. A workflow’s ownGITHUB_TOKENreaches only the workflow’s repository, so a separate context repository needs its own token. - GitHub over SSH: an SSH deploy key on the context repository works without a token. Kane CLI never answers an SSH prompt, so the runner must have the key loaded and the host key already accepted (
ssh-keyscan github.com >> ~/.ssh/known_hosts). - For either GitHub option, repository rules must also allow the scratch reference that the connection check pushes under
refs/kane/probe/. See Three kinds of location. - S3-compatible storage: set
KANE_SYNC_S3_ACCESS_KEY_IDandKANE_SYNC_S3_SECRET_ACCESS_KEY.
- GitHub over HTTPS: set
-
Use
--mode agentfor structured output, and read the exit code:0: done.3: a person has to decide. The runner’s store is behind or has diverged, or a rebase stopped on decisions.2: a precondition failed. The location cannot be reached, keys are missing, or a rebase is still open.
-
Do not answer decisions blindly. When a rebase stops on a decision, the job stops too. Save the output of
kane-cli context sync status origin --jsonas a build artifact. It reports what is waiting, but a later job cannot replay it on its own, because answers must go to the store that holds the open rebase. The follow-up job must run on the same persisted.context/, such as a workspace or cache that survives between jobs. There, a person or an agent answers withkane-cli context sync origin --answer <id>=<choice>.keep-theirswrites nothing, but it is still a choice: the local change stays in the backup. The full contract is in Agents and CI. -
Keep
.context/out of version control. The store is never merged with git. It is shared through the location instead.