Testdriver:Ci Cd logo

Testdriver:Ci Cd

Organization
testdriverai
testdriver:ci-cd

Run TestDriver tests in CI/CD with parallel execution and cross-platform support

Overview

Publishertestdriverai
Repositorytestdriverai
Skill nametestdriver:ci-cd
Stars
465
Forks
39
Bundled files
Instructions only
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by testdriverai on GitHub. Read the source before you install it.

Installation

Install the Testdriver:Ci Cd AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/testdriverai/testdriverai/tree/main/ai/skills/testdriver-ci-cd
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/testdriverai/testdriverai.git /tmp/testdriverai
mkdir -p .claude/skills
cp -r /tmp/testdriverai/ai/skills/testdriver-ci-cd .claude/skills/testdriverai-testdriver-ci-cd
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Testdriver:Ci Cd in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Testdriver:Ci Cd on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Testdriver:Ci Cd is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

TestDriver integrates with the common CI providers. It lets you do automated end-to-end tests on each push and pull request.

Authentication

On GitHub Actions, use OIDC through the published testdriverai/action. Then there is no TD_API_KEY secret to store, copy, or change. The action shows that the workflow runs in your org. TestDriver changes that proof for your team's key at run time. See the GitHub Actions tab below.

For other CI providers (or self-hosted runners without OIDC), use a stored API key from console.testdriver.ai/settings. Add it as a TD_API_KEY secret in the settings of your CI provider.

CI Provider Examples

Use the published [`testdriverai/action`](https://github.com/testdriverai/action). It makes the OIDC token, changes it for your team's API key, and exports `TD_API_KEY` for the steps that come after. **There is no `TD_API_KEY` secret to store or change.**

<Note>
  Do this one time: authorize the [TestDriver GitHub App](https://console.testdriver.ai) for your org. Then the org → team binding exists. If your org authorized the App before OIDC support was available, authorize it again one time. If the App is not authorized, the action fails with a console link. (Or it uses the `api-key` secret if you give one.)
</Note>

```yaml .github/workflows/testdriver.yml
name: TestDriver Tests

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

jobs:
  test:
    runs-on: ubuntu-latest
    permissions:
      id-token: write   # REQUIRED to mint an OIDC token
      contents: read

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - run: npm ci

      - name: Authenticate to TestDriver
        uses: testdriverai/action@stable   # pin @stable / @canary / @test to your SDK channel
        with:
          api-key: ${{ secrets.TD_API_KEY }}   # optional fallback if OIDC isn't set up

      - name: Run TestDriver tests
        run: npx vitest run
```

### Stored-key fallback

Only if you can't use OIDC (e.g. self-hosted runners without an OIDC provider). Add the key as a secret and pass it via `env`:

1. Navigate to your GitHub repository
2. Go to **Settings** → **Secrets and variables** → **Actions**
3. Click **New repository secret**
4. Name: `TD_API_KEY`, Value: your API key
5. Click **Add secret**

### Basic Workflow

Create `.github/workflows/testdriver.yml`:

```yaml .github/workflows/testdriver.yml
name: TestDriver Tests

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

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      
      - run: npm ci
      
      - name: Run TestDriver tests
        env:
          TD_API_KEY: ${{ secrets.TD_API_KEY }}
        run: vitest --run
```

### Parallel Execution

Use matrix strategy to run tests in parallel:

```yaml .github/workflows/testdriver-parallel.yml
name: TestDriver Tests (Parallel)

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        shard: [1, 2, 3, 4]
    
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - name: Run tests (shard ${{ matrix.shard }}/4)
        env:
          TD_API_KEY: ${{ secrets.TD_API_KEY }}
        run: vitest --run --shard=${{ matrix.shard }}/4
```

### Multi-Platform Testing

```yaml .github/workflows/testdriver-multiplatform.yml
name: TestDriver Tests (Multi-Platform)

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        td-os: [linux, windows]
    
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - name: Run tests on ${{ matrix.td-os }}
        env:
          TD_API_KEY: ${{ secrets.TD_API_KEY }}
          TD_OS: ${{ matrix.td-os }}
        run: vitest --run
```
1. Go to your GitLab project
2. Navigate to **Settings** → **CI/CD** → **Variables**
3. Click **Add variable**
4. Key: `TD_API_KEY`, Value: your API key
5. Check **Mask variable** and click **Add variable**

### Basic Pipeline

Create `.gitlab-ci.yml`:

```yaml .gitlab-ci.yml
stages:
  - test

testdriver:
  stage: test
  image: node:20
  cache:
    paths:
      - node_modules/
  script:
    - npm ci
    - vitest --run
  variables:
    TD_API_KEY: $TD_API_KEY
```

### Parallel Execution

```yaml .gitlab-ci.yml
stages:
  - test

.testdriver-base:
  stage: test
  image: node:20
  cache:
    paths:
      - node_modules/
  before_script:
    - npm ci
  variables:
    TD_API_KEY: $TD_API_KEY

testdriver-shard-1:
  extends: .testdriver-base
  script:
    - vitest --run --shard=1/4

testdriver-shard-2:
  extends: .testdriver-base
  script:
    - vitest --run --shard=2/4

testdriver-shard-3:
  extends: .testdriver-base
  script:
    - vitest --run --shard=3/4

testdriver-shard-4:
  extends: .testdriver-base
  script:
    - vitest --run --shard=4/4
```

### Multi-Platform Testing

```yaml .gitlab-ci.yml
stages:
  - test

.testdriver-base:
  stage: test
  image: node:20
  cache:
    paths:
      - node_modules/
  before_script:
    - npm ci
  variables:
    TD_API_KEY: $TD_API_KEY

testdriver-linux:
  extends: .testdriver-base
  variables:
    TD_OS: linux
  script:
    - vitest --run

testdriver-windows:
  extends: .testdriver-base
  variables:
    TD_OS: windows
  script:
    - vitest --run
```
1. Go to your CircleCI project
2. Click **Project Settings** → **Environment Variables**
3. Click **Add Environment Variable**
4. Name: `TD_API_KEY`, Value: your API key

### Basic Config

Create `.circleci/config.yml`:

```yaml .circleci/config.yml
version: 2.1

jobs:
  test:
    docker:
      - image: cimg/node:20.0
    steps:
      - checkout
      - restore_cache:
          keys:
            - npm-deps-{{ checksum "package-lock.json" }}
      - run: npm ci
      - save_cache:
          key: npm-deps-{{ checksum "package-lock.json" }}
          paths:
            - node_modules
      - run:
          name: Run TestDriver tests
          command: vitest --run
          environment:
            TD_API_KEY: ${TD_API_KEY}

workflows:
  test:
    jobs:
      - test
```

### Parallel Execution

```yaml .circleci/config.yml
version: 2.1

jobs:
  test:
    docker:
      - image: cimg/node:20.0
    parallelism: 4
    steps:
      - checkout
      - restore_cache:
          keys:
            - npm-deps-{{ checksum "package-lock.json" }}
      - run: npm ci
      - save_cache:
          key: npm-deps-{{ checksum "package-lock.json" }}
          paths:
            - node_modules
      - run:
          name: Run TestDriver tests
          command: |
            vitest --run --shard=$((CIRCLE_NODE_INDEX + 1))/$CIRCLE_NODE_TOTAL
          environment:
            TD_API_KEY: ${TD_API_KEY}

workflows:
  test:
    jobs:
      - test
```

### Multi-Platform Testing

```yaml .circleci/config.yml
version: 2.1

jobs:
  test:
    docker:
      - image: cimg/node:20.0
    parameters:
      td-os:
        type: string
    steps:
      - checkout
      - run: npm ci
      - run:
          name: Run TestDriver tests on << parameters.td-os >>
          command: vitest --run
          environment:
            TD_API_KEY: ${TD_API_KEY}
            TD_OS: << parameters.td-os >>

workflows:
  test:
    jobs:
      - test:
          td-os: linux
      - test:
          td-os: windows
```
1. Go to your Azure DevOps project
2. Navigate to **Pipelines** → **Library** → **Variable groups**
3. Create a new variable group or edit existing
4. Add variable: `TD_API_KEY` with your API key
5. Click the lock icon to make it secret

### Basic Pipeline

Create `azure-pipelines.yml`:

```yaml azure-pipelines.yml
trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

steps:
  - task: NodeTool@0
    inputs:
      versionSpec: '20.x'
    displayName: 'Setup Node.js'

  - script: npm ci
    displayName: 'Install dependencies'

  - script: vitest --run
    displayName: 'Run TestDriver tests'
    env:
      TD_API_KEY: $(TD_API_KEY)
```

### Parallel Execution

```yaml azure-pipelines.yml
trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

strategy:
  matrix:
    shard1:
      SHARD: '1/4'
    shard2:
      SHARD: '2/4'
    shard3:
      SHARD: '3/4'
    shard4:
      SHARD: '4/4'

steps:
  - task: NodeTool@0
    inputs:
      versionSpec: '20.x'

  - script: npm ci
    displayName: 'Install dependencies'

  - script: vitest --run --shard=$(SHARD)
    displayName: 'Run TestDriver tests'
    env:
      TD_API_KEY: $(TD_API_KEY)
```

### Multi-Platform Testing

```yaml azure-pipelines.yml
trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

strategy:
  matrix:
    linux:
      TD_OS: 'linux'
    windows:
      TD_OS: 'windows'

steps:
  - task: NodeTool@0
    inputs:
      versionSpec: '20.x'

  - script: npm ci
    displayName: 'Install dependencies'

  - script: vitest --run
    displayName: 'Run TestDriver tests on $(TD_OS)'
    env:
      TD_API_KEY: $(TD_API_KEY)
      TD_OS: $(TD_OS)
```
1. Go to **Manage Jenkins** → **Credentials**
2. Select the appropriate domain
3. Click **Add Credentials**
4. Kind: **Secret text**
5. ID: `td-api-key`, Secret: your API key

### Basic Pipeline

Create `Jenkinsfile`:

```groovy Jenkinsfile
pipeline {
    agent {
        docker {
            image 'node:20'
        }
    }
    
    environment {
        TD_API_KEY = credentials('td-api-key')
    }
    
    stages {
        stage('Install') {
            steps {
                sh 'npm ci'
            }
        }
        
        stage('Test') {
            steps {
                sh 'vitest --run'
            }
        }
    }
}
```

### Parallel Execution

```groovy Jenkinsfile
pipeline {
    agent none
    
    environment {
        TD_API_KEY = credentials('td-api-key')
    }
    
    stages {
        stage('Test') {
            parallel {
                stage('Shard 1') {
                    agent { docker { image 'node:20' } }
                    steps {
                        sh 'npm ci'
                        sh 'vitest --run --shard=1/4'
                    }
                }
                stage('Shard 2') {
                    agent { docker { image 'node:20' } }
                    steps {
                        sh 'npm ci'
                        sh 'vitest --run --shard=2/4'
                    }
                }
                stage('Shard 3') {
                    agent { docker { image 'node:20' } }
                    steps {
                        sh 'npm ci'
                        sh 'vitest --run --shard=3/4'
                    }
                }
                stage('Shard 4') {
                    agent { docker { image 'node:20' } }
                    steps {
                        sh 'npm ci'
                        sh 'vitest --run --shard=4/4'
                    }
                }
            }
        }
    }
}
```

### Multi-Platform Testing

```groovy Jenkinsfile
pipeline {
    agent none
    
    environment {
        TD_API_KEY = credentials('td-api-key')
    }
    
    stages {
        stage('Test') {
            parallel {
                stage('Linux') {
                    agent { docker { image 'node:20' } }
                    environment {
                        TD_OS = 'linux'
                    }
                    steps {
                        sh 'npm ci'
                        sh 'vitest --run'
                    }
                }
                stage('Windows') {
                    agent { docker { image 'node:20' } }
                    environment {
                        TD_OS = 'windows'
                    }
                    steps {
                        sh 'npm ci'
                        sh 'vitest --run'
                    }
                }
            }
        }
    }
}
```

Reading Platform in Tests

When using multi-platform testing, read the TD_OS environment variable in your test:

javascript
import { describe, expect, it } from "vitest";
import { TestDriver } from "testdriverai/vitest/hooks";

describe("Cross-platform tests", () => {
  it("should work on both Linux and Windows", async (context) => {
    const os = process.env.TD_OS || 'linux';
    
    const testdriver = TestDriver(context, { 
      os: os  // 'linux' or 'windows'
    });
    
    await testdriver.provision.chrome({
      url: 'https://example.com',
    });

    const result = await testdriver.assert("the page loaded successfully");
    expect(result).toBeTruthy();
  });
});

Concurrency limits

Your plan allows a fixed number of sandboxes running at once. When a test asks for a sandbox and you're already at that limit, the request is queued rather than failed immediately: the SDK waits for a slot to free up, retrying every 10 seconds, then proceeds automatically once one opens. This is what lets a parallel CI matrix (many jobs starting at once) work on a plan with fewer slots than jobs — the extra jobs simply wait their turn instead of erroring.

By default the SDK waits up to 60 seconds for a slot before giving up with a concurrency-limit error. Control that ceiling with TD_CONCURRENCY_MAX_WAIT:

ValueBehavior
unsetWait up to 60 seconds (the default).
TD_CONCURRENCY_MAX_WAIT=300Wait up to 300 seconds (5 minutes) before giving up.
TD_CONCURRENCY_MAX_WAIT=0Don't queue — fail on the first denial.

The value is in seconds (fractional values are allowed and rounded to the nearest millisecond). Any invalid or negative value falls back to the 60-second default. The wait applies per sandbox request, across both the initial allocation and the realtime slot-approval handshake.

yaml
# Example: a large parallel matrix that may queue for a while.
# Give each job up to 5 minutes to acquire a slot before failing.
- name: Run TestDriver tests
  env:
    TD_API_KEY: ${{ secrets.TD_API_KEY }}
    TD_CONCURRENCY_MAX_WAIT: "300"
  run: npx vitest run

Viewing Results

All test runs are automatically recorded and visible in your TestDriver dashboard at console.testdriver.ai:

  • All test runs with pass/fail status
  • Video replays of each test
  • Error messages and screenshots on failure
  • Git commit and branch information
  • Duration trends over time

Frequently asked questions

What does the Testdriver:Ci Cd AI skill do?

Run TestDriver tests in CI/CD with parallel execution and cross-platform support

Why use Testdriver:Ci Cd on TypingMind?

Because you install it once and use it with any model. Testdriver:Ci Cd is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Testdriver:Ci Cd in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/testdriverai/testdriverai/tree/main/ai/skills/testdriver-ci-cd. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Testdriver:Ci Cd?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Testdriver:Ci Cd?

As many as you like. As long as a model supports skills, you can use Testdriver:Ci Cd with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Testdriver:Ci Cd AI skill free?

It is published on GitHub by testdriverai. Check the repository for licensing terms. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇