---
title: "Run tests in CI/CD with the ktm CLI"
description: Run Kapptivate tests from your pipeline with stable exit codes, JUnit output, and native GitHub Actions annotations.
sidebarTitle: "CI/CD"
lastUpdated: "2026-09-23"
---

> **For AI agents:** the complete documentation index is at [llms.txt](/llms.txt). Append `.md` to any page URL for its markdown version.

`ktm` is built for pipelines. The pattern is always the same: build a campaign, run it, publish the results. The CLI returns JSON, writes JUnit XML, and exits non-zero when tests fail, so your pipeline reacts automatically.

## Pipeline examples

<Tabs>
  <Tab title="GitHub Actions">

```yaml
name: Kapptivate Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install ktm
        run: curl -fsSL https://artefacts.kapptivate.com/ktm/install.sh | bash

      - name: Build campaign
        env:
          KAPPTIVATE_API_KEY: ${{ secrets.KAPPTIVATE_API_KEY }}
        run: |
          ktm ci build \
            --test-ids 16480,16838 \
            --product acme~web --variant "API:Staging" > campaign.json

      - name: Run tests
        env:
          KAPPTIVATE_API_KEY: ${{ secrets.KAPPTIVATE_API_KEY }}
        run: |
          ktm ci run \
            --test-config-path campaign.json \
            --junit-file results.xml \
            --output-file summary.json

      - name: Upload results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-results
          path: |
            results.xml
            summary.json
```

  </Tab>
  <Tab title="GitLab CI">

```yaml
stages: [test]

kapptivate-tests:
  stage: test
  image: ubuntu:24.04
  before_script:
    - apt-get update && apt-get install -y --no-install-recommends curl ca-certificates
    - curl -fsSL https://artefacts.kapptivate.com/ktm/install.sh | bash
  script:
    - ktm ci build --test-ids 16480,16838 --product acme~web --variant "API:Staging" > campaign.json
    - ktm ci run --test-config-path campaign.json --junit-file results.xml --output-file summary.json
  artifacts:
    when: always
    paths:
      - results.xml
      - summary.json
    reports:
      junit: results.xml
```

  </Tab>
</Tabs>

For GitLab, add `KAPPTIVATE_API_KEY` as a masked CI/CD variable in your project settings (Settings > CI/CD > Variables), the same way GitHub Actions uses `secrets.KAPPTIVATE_API_KEY`.

### Native GitHub integration

When `GITHUB_ACTIONS=true` (set automatically), `ktm` produces native output with no extra configuration:

- It emits `::notice` and `::error` annotations that appear on the run and on pull requests.
- It appends a results table to the job summary.

The JSON summary is suppressed on stdout in that mode, so pass `--output-file summary.json` to keep it as a file.

## Other platforms

For Jenkins and other runners, the pattern is the same: install `ktm`, set `KAPPTIVATE_API_KEY`, then call `ktm ci build` and `ktm ci run`. Commit your campaign JSON or test configs to the repo and point `ktm ci run --test-config-dir ./tests/` at them.

## Exit codes

The pipeline fails on any non-zero exit. Code `5` means tests ran but some failed (distinct from `1`, a general error). See [Configuration](/cli/configuration) for the full list.

## What's next?

<Columns cols={2}>
  <Card title="Command reference" icon="terminal" href="/cli/commands/overview">
    The `ci` commands and their flags.
  </Card>
  <Card title="Configuration" icon="gear" href="/cli/configuration">
    Exit codes, environment variables, and output formats.
  </Card>
</Columns>
