Skip to main content

CI/CD Pipeline Integration

Run your TMS-integrated tests in CI/CD pipelines. This guide covers GitHub Actions, Jenkins, and GitLab CI with complete, copy-paste-ready configurations.

Overview

Running TMS-integrated tests in CI is straightforward:

  1. Set ProvaLab.io environment variables as secrets in your CI platform
  2. Install dependencies (including the ProvaLab.io SDK)
  3. Run tests exactly as you would locally

ProvaLab.io reporters detect the environment variables and report results automatically. No code changes needed beyond what you already have for local development.

Environment Variables

All CI platforms need these secrets configured:

VariableDescription
TMS_API_URLYour ProvaLab.io instance URL
TMS_API_KEYAPI key from ProvaLab.io Settings
TMS_ORGANIZATION_IDYour organization ID
TMS_PROJECT_IDYour project ID
TMS_ENVIRONMENTSet to ci or the branch name
Naming your CI test runs

Set TMS_TEST_RUN_NAME to include useful CI context:

TMS_TEST_RUN_NAME="CI: ${GITHUB_REF_NAME} #${GITHUB_RUN_NUMBER}"

This makes it easy to find CI runs in the ProvaLab.io dashboard.


GitHub Actions

Playwright + ProvaLab.io

.github/workflows/e2e-tests.yml
name: E2E Tests

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

env:
TMS_API_URL: ${{ secrets.TMS_API_URL }}
TMS_API_KEY: ${{ secrets.TMS_API_KEY }}
TMS_ORGANIZATION_ID: ${{ secrets.TMS_ORGANIZATION_ID }}
TMS_PROJECT_ID: ${{ secrets.TMS_PROJECT_ID }}
TMS_ENVIRONMENT: ci
TMS_TEST_RUN_NAME: "CI: ${{ github.ref_name }} #${{ github.run_number }}"

jobs:
playwright:
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- uses: actions/checkout@v4

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

- name: Install dependencies
run: npm ci

- name: Install Playwright browsers
run: npx playwright install --with-deps

- name: Run Playwright tests
run: npx playwright test

- name: Upload Playwright report
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30

Jest + ProvaLab.io

.github/workflows/unit-tests.yml
name: Unit Tests

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

env:
TMS_API_URL: ${{ secrets.TMS_API_URL }}
TMS_API_KEY: ${{ secrets.TMS_API_KEY }}
TMS_ORGANIZATION_ID: ${{ secrets.TMS_ORGANIZATION_ID }}
TMS_PROJECT_ID: ${{ secrets.TMS_PROJECT_ID }}
TMS_ENVIRONMENT: ci

jobs:
jest:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ['18', '20']

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run Jest tests
run: npx jest --ci --coverage

- name: Upload coverage
uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-node-${{ matrix.node-version }}
path: coverage/

Cypress + ProvaLab.io

.github/workflows/cypress-tests.yml
name: Cypress Tests

on:
push:
branches: [main]
pull_request:

env:
TMS_API_URL: ${{ secrets.TMS_API_URL }}
TMS_API_KEY: ${{ secrets.TMS_API_KEY }}
TMS_ORGANIZATION_ID: ${{ secrets.TMS_ORGANIZATION_ID }}
TMS_PROJECT_ID: ${{ secrets.TMS_PROJECT_ID }}
TMS_ENVIRONMENT: ci

jobs:
cypress:
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- uses: actions/checkout@v4

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

- name: Install dependencies
run: npm ci

- name: Run Cypress tests
uses: cypress-io/github-action@v6
with:
browser: chrome
headed: false

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

- name: Upload videos
uses: actions/upload-artifact@v4
if: always()
with:
name: cypress-videos
path: cypress/videos

pytest + ProvaLab.io

.github/workflows/python-tests.yml
name: Python Tests

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

env:
TMS_API_URL: ${{ secrets.TMS_API_URL }}
TMS_API_KEY: ${{ secrets.TMS_API_KEY }}
TMS_ORGANIZATION_ID: ${{ secrets.TMS_ORGANIZATION_ID }}
TMS_PROJECT_ID: ${{ secrets.TMS_PROJECT_ID }}

jobs:
pytest:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install tms-plugin

- name: Run pytest with TMS
run: pytest tests/ -v --tms-enable --tms-environment=ci

Java (Maven) + ProvaLab.io

.github/workflows/java-tests.yml
name: Java Tests

on:
push:
branches: [main]
pull_request:

env:
TMS_API_URL: ${{ secrets.TMS_API_URL }}
TMS_API_KEY: ${{ secrets.TMS_API_KEY }}
TMS_ORGANIZATION_ID: ${{ secrets.TMS_ORGANIZATION_ID }}
TMS_PROJECT_ID: ${{ secrets.TMS_PROJECT_ID }}
TMS_ENVIRONMENT: ci

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
cache: 'maven'

- name: Run tests
run: mvn test -B

Setting up GitHub Secrets

  1. Go to your repository on GitHub
  2. Navigate to Settings > Secrets and variables > Actions
  3. Click New repository secret for each:
Secret NameValue
TMS_API_URLhttps://tms.yourcompany.com
TMS_API_KEYYour API key
TMS_ORGANIZATION_IDYour organization ID (number)
TMS_PROJECT_IDYour project ID (number)
Organization-level secrets

If multiple repositories need ProvaLab.io access, set secrets at the GitHub Organization level (Organization Settings > Secrets) so all repos inherit them.


Jenkins

Declarative Pipeline

Jenkinsfile
pipeline {
agent any

environment {
TMS_API_URL = credentials('tms-api-url')
TMS_API_KEY = credentials('tms-api-key')
TMS_ORGANIZATION_ID = credentials('tms-org-id')
TMS_PROJECT_ID = credentials('tms-project-id')
TMS_ENVIRONMENT = 'ci'
TMS_TEST_RUN_NAME = "Jenkins: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
}

stages {
stage('Install') {
steps {
sh 'npm ci'
}
}

stage('Unit Tests') {
steps {
sh 'npx jest --ci'
}
}

stage('E2E Tests') {
steps {
sh 'npx playwright install --with-deps'
sh 'npx playwright test'
}
post {
always {
archiveArtifacts artifacts: 'playwright-report/**', allowEmptyArchive: true
}
}
}
}

post {
always {
junit '**/test-results/*.xml'
}
}
}

Parallel E2E Tests

Jenkinsfile
pipeline {
agent any

environment {
TMS_API_URL = credentials('tms-api-url')
TMS_API_KEY = credentials('tms-api-key')
TMS_ORGANIZATION_ID = credentials('tms-org-id')
TMS_PROJECT_ID = credentials('tms-project-id')
TMS_ENVIRONMENT = 'ci'
}

stages {
stage('Install') {
steps {
sh 'npm ci'
sh 'npx playwright install --with-deps'
}
}

stage('E2E Tests') {
parallel {
stage('Playwright - Chrome') {
environment {
TMS_TEST_RUN_NAME = "Jenkins Playwright Chrome #${env.BUILD_NUMBER}"
}
steps {
sh 'npx playwright test --project=chromium'
}
}
stage('Cypress - Chrome') {
environment {
TMS_TEST_RUN_NAME = "Jenkins Cypress Chrome #${env.BUILD_NUMBER}"
}
steps {
sh 'npx cypress run --browser chrome'
}
}
}
}
}
}

Setting up Jenkins Credentials

  1. Go to Jenkins > Manage Jenkins > Manage Credentials
  2. Add credentials (type: Secret text) for each:
    • tms-api-url
    • tms-api-key
    • tms-org-id
    • tms-project-id

GitLab CI

Basic Configuration

.gitlab-ci.yml
variables:
TMS_API_URL: $TMS_API_URL
TMS_API_KEY: $TMS_API_KEY
TMS_ORGANIZATION_ID: $TMS_ORGANIZATION_ID
TMS_PROJECT_ID: $TMS_PROJECT_ID
TMS_ENVIRONMENT: ci

stages:
- test

unit-tests:
stage: test
image: node:20
script:
- npm ci
- npx jest --ci
artifacts:
when: always
reports:
junit: test-results/junit.xml

e2e-tests:
stage: test
image: mcr.microsoft.com/playwright:v1.42.0-jammy
script:
- npm ci
- npx playwright test
artifacts:
when: always
paths:
- playwright-report/
expire_in: 30 days

python-tests:
stage: test
image: python:3.11
script:
- pip install -r requirements.txt
- pip install tms-plugin
- pytest tests/ -v --tms-enable --tms-environment=ci

Parallel E2E Tests

.gitlab-ci.yml
e2e-playwright:
stage: test
image: mcr.microsoft.com/playwright:v1.42.0-jammy
variables:
TMS_TEST_RUN_NAME: "GitLab Playwright #$CI_PIPELINE_IID"
parallel:
matrix:
- PROJECT: [chromium, firefox, webkit]
script:
- npm ci
- npx playwright test --project=$PROJECT
artifacts:
when: always
paths:
- playwright-report/

e2e-cypress:
stage: test
image: cypress/browsers:latest
variables:
TMS_TEST_RUN_NAME: "GitLab Cypress #$CI_PIPELINE_IID"
script:
- npm ci
- npx cypress run --browser chrome
artifacts:
when: on_failure
paths:
- cypress/screenshots/
- cypress/videos/

Setting up GitLab CI/CD Variables

  1. Go to your GitLab project
  2. Navigate to Settings > CI/CD > Variables
  3. Click Add variable for each:
KeyValueOptions
TMS_API_URLhttps://tms.yourcompany.comProtected
TMS_API_KEYYour API keyProtected, Masked
TMS_ORGANIZATION_IDYour org IDProtected
TMS_PROJECT_IDYour project IDProtected
Mark sensitive values as "Masked"

Always mask TMS_API_KEY so it doesn't appear in CI logs.


Best Practices

Use descriptive test run names

Include CI context in the run name so you can trace runs back to specific builds:

# GitHub Actions
TMS_TEST_RUN_NAME="CI: ${GITHUB_REF_NAME} #${GITHUB_RUN_NUMBER}"

# Jenkins
TMS_TEST_RUN_NAME="Jenkins: ${JOB_NAME} #${BUILD_NUMBER}"

# GitLab CI
TMS_TEST_RUN_NAME="GitLab: ${CI_COMMIT_REF_NAME} #${CI_PIPELINE_IID}"

Tag the environment

Always set TMS_ENVIRONMENT to distinguish CI runs from local development:

TMS_ENVIRONMENT=ci

Don't let ProvaLab.io failures break your build

ProvaLab.io reporter SDKs are designed to fail gracefully. If ProvaLab.io is unreachable, tests still run normally. However, you can explicitly disable ProvaLab.io if needed:

TMS_DISABLED=true   # Skip all ProvaLab.io reporting

Separate test runs for different suites

If you run multiple test suites in a single CI pipeline, each suite automatically creates its own ProvaLab.io test run. Use TMS_TEST_RUN_NAME to differentiate them:

- name: Run unit tests
env:
TMS_TEST_RUN_NAME: "Unit Tests #${{ github.run_number }}"
run: npx jest

- name: Run E2E tests
env:
TMS_TEST_RUN_NAME: "E2E Tests #${{ github.run_number }}"
run: npx playwright test

Verify It Works

  1. Configure secrets in your CI platform
  2. Add or update your CI configuration file
  3. Push a commit to trigger the pipeline
  4. Check the CI logs for the ProvaLab.io banner (Test Run ID)
  5. Open ProvaLab.io and verify the test run appears with environment tag "ci"
Common issues
  • "Not configured" in CI logs: Secrets are not being passed to the job. Check that variable names match exactly
  • Results appearing as "local" not "ci": Make sure TMS_ENVIRONMENT=ci is set
  • Multiple runs created: This is expected if you run multiple test commands. Each creates its own ProvaLab.io test run
  • API key exposed in logs: Mark TMS_API_KEY as a secret/masked variable in your CI platform