> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usetusk.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# CI/CD Setup

> Run Tusk Drift's API tests in your CI/CD pipeline

Run your Tusk Drift test suite against commits in pull requests to catch API regressions before they reach production.

To do this, you'll create a CI workflow file that runs your tests on every pull request. For GitHub Actions, you can use the `Use-Tusk/drift-action` action to handle CLI installation and test execution.

## Prerequisites

Before setting up Tusk Drift in CI/CD, ensure you have:

* Completed [local setup](/api-tests/installation) with recording and replay working
* Completed Cloud setup (i.e., ran `tusk drift setup --skip-to-cloud`)
* Obtained your [Tusk API key](https://app.usetusk.ai/app/settings/api-keys)

## Quick Start

1. Add `TUSK_API_KEY` to your repository secrets (GitHub) or CI/CD variables (GitLab)
2. Create a workflow file:
   * **GitHub**: `.github/workflows/tusk-drift.yml`
   * **GitLab**: `.gitlab-ci.yml`
3. Configure it to run tests:
   * **GitHub**: use [`Use-Tusk/drift-action`](https://github.com/Use-Tusk/drift-action)
   * **GitLab**: install the CLI and run `tusk run` directly
     (see full examples below)

## Complete Workflow Example

<Tabs>
  <Tab title="GitHub Actions">
    Create `.github/workflows/tusk-drift.yml`:

    ```yaml theme={null}
    name: Tusk Drift

    on:
      pull_request:
        paths:
          - "backend/**"
      # Push to main is required for --validate-suite-if-default-branch
      # to validate and promote draft tests to the suite
      push:
        branches:
          - main

    jobs:
      tusk-drift:
        runs-on: ubuntu-latest

        steps:
          # 1. Checkout your repository
          - name: Checkout
            uses: actions/checkout@v4

          # 2. Set up your runtime (Node.js example - adapt for your stack)
          - name: Set Node.js v22
            uses: actions/setup-node@v4
            with:
              node-version: 22.16.0

          # 3. Install dependencies and set up your service
          # Add any steps needed for your service to start successfully:
          # - Install dependencies
          # - Run database migrations
          # - Build/compile your code, etc
          - name: Install dependencies
            run: npm ci
            working-directory: ./backend

          # 4. Run Tusk Drift tests (installs CLI + runs tests)
          # The action internally runs:
          # tusk run -c -p --ci --validate-suite-if-default-branch
          - name: Run Tusk Drift
            uses: Use-Tusk/drift-action@v1
            with:
              working-directory: ./backend
              # GitHub Action cache to load Cloud traces faster
              cache-key: ${{ runner.os }}-tusk-drift-${{ hashFiles('backend/.tusk/config.yaml') }}
              api-key: ${{ secrets.TUSK_API_KEY }}
    ```
  </Tab>

  <Tab title="GitLab CI">
    Add to your `.gitlab-ci.yml`:

    ```yaml theme={null}
    tusk-drift:
      stage: test
      image: node:22

      before_script:
        # 1. Install dependencies and set up your service
        # Add any steps needed for your service to start successfully:
        # - Install dependencies
        # - Run database migrations
        # - Build/compile your code, etc
        - cd backend
        - npm ci

        # 2. Install Tusk Drift CLI
        - curl -fsSL https://cli.usetusk.ai/install.sh | sh
        - tusk --version

      script:
        # 3. Run Tusk Drift tests
        # The CLI automatically detects commit SHA, MR number, and branch
        # from GitLab CI environment variables
        - tusk run -c -p --ci --validate-suite-if-default-branch

      rules:
        # Run on merge requests
        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
          changes:
            - backend/**
        # Run on pushes to default branch (required for --validate-suite-if-default-branch)
        - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

      variables:
        TUSK_API_KEY: $TUSK_API_KEY
    ```
  </Tab>

  <Tab title="Other CI providers">
    For CI providers other than GitHub Actions and GitLab CI (for example,
    CircleCI, Buildkite, Jenkins, Azure DevOps), include these pieces:

    1. Repository checkout

    2. Runtime + service setup, e.g.:
       * Install dependencies
       * Build/compile your service

    3. Install Tusk CLI:

       ```bash theme={null}
       curl -fsSL https://cli.usetusk.ai/install.sh | sh
       ```

    4. Run Tusk in CI mode and pass CI metadata explicitly:

       ```bash theme={null}
       tusk run -c -p --ci --validate-suite-if-default-branch \
         --commit-sha "$CI_COMMIT_SHA" \
         --pr-number "$CI_PR_NUMBER" \
         --branch "$CI_BRANCH_NAME" \
         --external-check-run-id "$CI_CHECK_RUN_ID"
       ```

    Notes:

    * `--commit-sha`, `--pr-number`, and `--branch` are required in CI mode if
      your provider is not auto-detected.
    * `--external-check-run-id` is optional but recommended when your provider
      has a stable job/check identifier.
    * `--pr-number` must be a numeric pull/merge request number.
    * Keep `TUSK_API_KEY` available as a secret environment variable.
  </Tab>
</Tabs>

<Info>
  The Tusk CLI automatically starts your service using the command defined in
  `.tusk/config.yaml`. In GitHub Actions, [`Use-Tusk/drift-action`](https://github.com/Use-Tusk/drift-action)
  handles CLI installation and running tests, but your workflow still needs to
  ensure service prerequisites are ready beforehand (e.g., `npm ci`, build steps)
  so the service can start successfully.
</Info>

## Workflow Triggers Explained

Your workflow should trigger on both pull/merge requests and pushes to the default branch:

<Tabs>
  <Tab title="GitHub Actions">
    * **`pull_request`**: Runs tests on PR branches, reports deviations, blocks
      merging if unintended deviations found - **`push` to main**: Required for
      `--validate-suite-if-default-branch` to promote passing draft tests to the
      suite
  </Tab>

  <Tab title="GitLab CI">
    * **`$CI_PIPELINE_SOURCE == "merge_request_event"`**: Runs tests on MR
      branches, reports deviations, blocks merging if unintended deviations found
    * **`$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH`**: Required for
      `--validate-suite-if-default-branch` to promote passing draft tests to the
      suite
  </Tab>

  <Tab title="Other CI providers">
    * **Pull/merge request pipeline trigger**: Runs drift tests on proposed changes.
    * **Push trigger on default branch**: Required for
      `--validate-suite-if-default-branch` to validate and promote draft tests.
  </Tab>
</Tabs>

<Warning>
  If you only trigger on pull/merge requests, draft tests will never be promoted
  to your test suite. Always include a trigger for pushes to your default
  branch.
</Warning>

## Path Filtering

Use path filtering to only run Tusk Drift when relevant files change:

<Tabs>
  <Tab title="GitHub Actions">
    ```yaml theme={null}
    on:
      pull_request:
        paths:
          - "backend/**"       # Your service directory
          - ".tusk/**"         # Tusk configuration
    ```
  </Tab>

  <Tab title="GitLab CI">
    ```yaml theme={null}
    rules:
      - if: $CI_PIPELINE_SOURCE == "merge_request_event"
        changes:
          - backend/**         # Your service directory
          - .tusk/**           # Tusk configuration
    ```
  </Tab>
</Tabs>

## CLI Flags Reference

### Common Flags for CI

| Flag                                 | Description                                                      |
| ------------------------------------ | ---------------------------------------------------------------- |
| `-c, --cloud`                        | Load tests from Tusk Drift Cloud instead of local `.tusk/traces` |
| `-p, --print`                        | Non-interactive output mode (required for CI environments)       |
| `--ci`                               | Create a Tusk Drift run and upload results to Cloud              |
| `--validate-suite-if-default-branch` | On default branch, validate and promote draft tests to the suite |
| `--enable-service-logs`              | Save service logs to `.tusk/logs`, helpful while debugging       |

For the full list of options, run `tusk run --help`.

## Environment Variables

### Required

| Variable       | Description                                                               |
| -------------- | ------------------------------------------------------------------------- |
| `TUSK_API_KEY` | API key for Tusk Drift Cloud authentication. Add this to your CI secrets. |

### Auto-Detected Variables

The CLI auto-detects these in **GitHub Actions** and **GitLab CI**:

* **Commit SHA** - from `GITHUB_SHA`, `CI_COMMIT_SHA`, etc.
* **PR/MR number** - from `GITHUB_REF`, `CI_MERGE_REQUEST_IID`, etc.
* **Branch name** - from `GITHUB_HEAD_REF`, `CI_COMMIT_REF_NAME`, etc.
* **Check run ID** - for GitHub status updates

For other CI providers, pass metadata with flags in your `tusk run` command:
`--commit-sha`, `--pr-number`, `--branch`, and optionally
`--external-check-run-id`.

## Troubleshooting

<AccordionGroup>
  <Accordion title="My draft tests are not being promoted">
    If tests remain in "Draft" and aren't moving to "In Suite":

    1. Ensure your workflow triggers on `push` to the default branch (e.g., `main`)
    2. Verify `--validate-suite-if-default-branch` flag is included
    3. Check that tests pass on the default branch
  </Accordion>

  <Accordion title="My service won't start in CI">
    Check for these gotchas:

    * Ensure you have completed [local setup](/api-tests/installation) with recording and replay working
    * Verify `working-directory` points to the correct path
    * Ensure all dependencies are installed before running `tusk run`

    You can enable service logs for debugging: `--enable-service-logs` (saves service/SDK logs to `.tusk/logs`)
  </Accordion>
</AccordionGroup>
