Skip to main content
Integrating Doc Detective into your CI/CD pipeline ensures your documentation stays accurate with every code change. This guide covers setup for popular CI/CD platforms.

Why Test Docs in CI/CD?

Automated documentation testing provides:
  • Catch errors early: Find broken instructions before they reach users
  • Prevent regressions: Ensure updates don’t break existing documentation
  • Enforce quality: Make documentation testing part of your definition of done
  • Save time: Automatically test across multiple platforms and browsers

Quick Start

Doc Detective works in any CI/CD environment that can run Node.js:
1

Install Node.js

Ensure Node.js 18 or later is available in your CI environment.
2

Install Doc Detective

npm install --save-dev doc-detective
Or use npx without installation:
npx doc-detective
3

Run tests

npx doc-detective --config .doc-detective.json
4

Check exit code

Doc Detective exits with code 1 if tests fail, failing your CI build.

GitHub Actions

Basic Workflow

Create .github/workflows/test-docs.yml:
name: Test Documentation

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

jobs:
  test-docs:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      
      - name: Install dependencies
        run: npm install
      
      - name: Run Doc Detective
        run: npx doc-detective --config .doc-detective.json

Multi-Platform Testing

Test across Windows, macOS, and Linux:
name: Test Documentation

on: [push, pull_request]

jobs:
  test-docs:
    runs-on: ${{ matrix.os }}
    
    strategy:
      fail-fast: false
      matrix:
        os:
          - ubuntu-latest
          - windows-latest
          - macos-latest
        node:
          - 18
          - 20
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm install
      
      - name: Run Doc Detective
        run: npx doc-detective

With Test Reports

Save and upload test results:
name: Test Documentation

on: [push, pull_request]

jobs:
  test-docs:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      
      - name: Install dependencies
        run: npm install
      
      - name: Run Doc Detective
        run: npx doc-detective --config .doc-detective.ci.json
      
      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-results
          path: test-results.json
      
      - name: Upload screenshots
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: screenshots
          path: screenshots/
With config file .doc-detective.ci.json:
{
  "input": ["./docs"],
  "output": "test-results.json",
  "recursive": true,
  "runOn": [
    {
      "platforms": ["windows", "mac", "linux"],
      "browsers": [
        {
          "name": "firefox",
          "headless": true
        }
      ]
    }
  ]
}

Using the Doc Detective Action

Use the official GitHub Action:
name: Test Documentation

on: [push, pull_request]

jobs:
  test-docs:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: doc-detective/github-action@latest
        with:
          config: ./.doc-detective.json
          input: ./docs
          exit_on_fail: true

GitLab CI/CD

Create .gitlab-ci.yml:
stages:
  - test

test-docs:
  stage: test
  image: node:20
  
  before_script:
    - npm install
  
  script:
    - npx doc-detective --config .doc-detective.json
  
  artifacts:
    when: always
    paths:
      - test-results.json
    reports:
      junit: test-results.json
  
  only:
    - branches
    - merge_requests

Multi-Platform on GitLab

stages:
  - test

test-docs-linux:
  stage: test
  image: node:20
  tags:
    - linux
  script:
    - npm install
    - npx doc-detective
  only:
    - branches

test-docs-windows:
  stage: test
  tags:
    - windows
  before_script:
    - npm install
  script:
    - npx doc-detective
  only:
    - branches

test-docs-macos:
  stage: test
  tags:
    - macos
  before_script:
    - npm install
  script:
    - npx doc-detective
  only:
    - branches

Jenkins

Create a Jenkinsfile:
pipeline {
  agent any
  
  tools {
    nodejs 'Node 20'
  }
  
  stages {
    stage('Install') {
      steps {
        sh 'npm install'
      }
    }
    
    stage('Test Documentation') {
      steps {
        sh 'npx doc-detective --config .doc-detective.json'
      }
    }
  }
  
  post {
    always {
      archiveArtifacts artifacts: 'test-results.json', allowEmptyArchive: true
      archiveArtifacts artifacts: 'screenshots/**/*.png', allowEmptyArchive: true
    }
  }
}

Multi-Platform Jenkins

pipeline {
  agent none
  
  stages {
    stage('Test Documentation') {
      matrix {
        axes {
          axis {
            name 'PLATFORM'
            values 'linux', 'windows', 'macos'
          }
        }
        
        agent {
          label "${PLATFORM}"
        }
        
        stages {
          stage('Install') {
            steps {
              sh 'npm install'
            }
          }
          
          stage('Test') {
            steps {
              sh 'npx doc-detective'
            }
          }
        }
      }
    }
  }
}

CircleCI

Create .circleci/config.yml:
version: 2.1

jobs:
  test-docs:
    docker:
      - image: cimg/node:20.0
    
    steps:
      - checkout
      
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "package-lock.json" }}
            - v1-dependencies-
      
      - run:
          name: Install dependencies
          command: npm install
      
      - save_cache:
          paths:
            - node_modules
          key: v1-dependencies-{{ checksum "package-lock.json" }}
      
      - run:
          name: Run Doc Detective
          command: npx doc-detective --config .doc-detective.json
      
      - store_artifacts:
          path: test-results.json
          destination: test-results
      
      - store_artifacts:
          path: screenshots
          destination: screenshots

workflows:
  version: 2
  test:
    jobs:
      - test-docs

Azure Pipelines

Create azure-pipelines.yml:
trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

steps:
  - task: NodeTool@0
    inputs:
      versionSpec: '20.x'
    displayName: 'Install Node.js'
  
  - script: |
      npm install
    displayName: 'Install dependencies'
  
  - script: |
      npx doc-detective --config .doc-detective.json
    displayName: 'Run Doc Detective'
  
  - task: PublishBuildArtifacts@1
    condition: always()
    inputs:
      pathToPublish: 'test-results.json'
      artifactName: 'test-results'
    displayName: 'Publish test results'

Multi-Platform Azure

trigger:
  - main

strategy:
  matrix:
    linux:
      imageName: 'ubuntu-latest'
    mac:
      imageName: 'macos-latest'
    windows:
      imageName: 'windows-latest'

pool:
  vmImage: $(imageName)

steps:
  - task: NodeTool@0
    inputs:
      versionSpec: '20.x'
  
  - script: npm install
    displayName: 'Install dependencies'
  
  - script: npx doc-detective
    displayName: 'Run Doc Detective'

Travis CI

Create .travis.yml:
language: node_js

node_js:
  - '20'

install:
  - npm install

script:
  - npx doc-detective --config .doc-detective.json

after_script:
  - if [ -f test-results.json ]; then cat test-results.json; fi

os:
  - linux
  - osx
  - windows

Docker

Use the Doc Detective Docker image:
FROM node:20-alpine

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

CMD ["npx", "doc-detective"]
In your CI pipeline:
test-docs:
  stage: test
  image: doc-detective/doc-detective:latest
  script:
    - doc-detective --config .doc-detective.json

Configuration for CI/CD

Create a CI-specific configuration .doc-detective.ci.json:
{
  "input": ["./docs"],
  "output": "./test-results.json",
  "recursive": true,
  "logLevel": "info",
  "runOn": [
    {
      "platforms": ["windows", "mac", "linux"],
      "browsers": [
        {
          "name": "firefox",
          "headless": true
        }
      ]
    }
  ]
}
Always use headless: true for browsers in CI/CD environments. Most CI runners don’t have displays, and headless mode ensures tests run correctly.

Environment Variables

Use environment variables for sensitive data:
1

Create .env file

API_KEY=your-secret-key
API_URL=https://api.example.com
USERNAME=[email protected]
PASSWORD=secure-password
2

Add to .gitignore

echo ".env" >> .gitignore
3

Configure CI secrets

Add environment variables to your CI platform:
  • GitHub Actions: Settings → Secrets and variables → Actions
  • GitLab CI: Settings → CI/CD → Variables
  • Jenkins: Credentials → Add credentials
4

Load in tests

{
  "steps": [
    {
      "action": "setVariables",
      "path": ".env"
    },
    {
      "action": "httpRequest",
      "url": "$API_URL/endpoint",
      "headers": {
        "Authorization": "Bearer $API_KEY"
      }
    }
  ]
}

Handling Test Failures

Fail Fast

Stop immediately on first failure:
strategy:
  fail-fast: true

Continue on Failure

Run all tests even if some fail:
strategy:
  fail-fast: false

Conditional Steps

- name: Upload screenshots on failure
  if: failure()
  uses: actions/upload-artifact@v4
  with:
    name: failure-screenshots
    path: screenshots/

Notifications

Slack Notifications

- name: Notify Slack on failure
  if: failure()
  uses: slackapi/slack-github-action@v1
  with:
    webhook-url: ${{ secrets.SLACK_WEBHOOK }}
    payload: |
      {
        "text": "Documentation tests failed in ${{ github.repository }}"
      }

Email Notifications

Most CI platforms support email notifications natively. Configure in your platform settings.

Best Practices

Use headless mode

Always set headless: true for CI environments.

Cache dependencies

Cache node_modules to speed up builds.

Save artifacts

Upload test results and screenshots for debugging.

Test on PRs

Run tests on pull requests before merging.

Matrix builds

Test across platforms and Node versions.

Separate config

Use .doc-detective.ci.json for CI-specific settings.

Secure secrets

Never commit credentials. Use CI secret management.

Monitor duration

Set timeouts to prevent hanging builds.

Troubleshooting

  • Verify Node.js version matches locally
  • Check environment variables are set correctly
  • Ensure browser is installed in CI environment
  • Add more wait time for slower CI runners
  • Check file paths are correct for CI OS
  • Use headless: true mode
  • Verify browser is installed
  • Check for display/X11 issues on Linux
  • Use Docker image with browsers pre-installed
  • Increase step timeouts in config
  • Add explicit wait steps
  • Check network access in CI environment
  • Verify API endpoints are accessible from CI
  • Check artifact paths exist
  • Verify output path in config
  • Use if: always() to upload on failure
  • Check CI platform artifact size limits

Example: Complete GitHub Actions Workflow

name: Documentation Testing

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 0 * * *'  # Daily at midnight

jobs:
  test-docs:
    runs-on: ${{ matrix.os }}
    
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node: [18, 20]
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run Doc Detective
        env:
          API_KEY: ${{ secrets.API_KEY }}
          API_URL: ${{ secrets.API_URL }}
        run: npx doc-detective --config .doc-detective.ci.json
      
      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-results-${{ matrix.os }}-node${{ matrix.node }}
          path: test-results.json
      
      - name: Upload screenshots on failure
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: screenshots-${{ matrix.os }}-node${{ matrix.node }}
          path: screenshots/
      
      - name: Comment on PR
        if: failure() && github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: '❌ Documentation tests failed. Check the artifacts for details.'
            })

Next Steps

Configuration

Optimize your CI/CD configuration

Contexts

Learn about multi-platform testing

Writing Tests

Create comprehensive test suites

GitHub Action

Use the official Doc Detective Action

Build docs developers (and LLMs) love