The plan job chooses the CI node count and emits a matrix; the run job downloads
the artifacts and executes only the files assigned to its CI node. Each matrix
job is one CI node, and matrix.ci_node_index is passed to
ddtest run --ci-node.
name: CI with DDTest
on: [push]
env:
DD_TEST_OPTIMIZATION_RUNNER_PLATFORM: ruby
DD_TEST_OPTIMIZATION_RUNNER_FRAMEWORK: rspec
DD_TEST_OPTIMIZATION_RUNNER_MIN_PARALLELISM: 1
DD_TEST_OPTIMIZATION_RUNNER_MAX_PARALLELISM: 8
jobs:
dd_plan:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.dd_plan.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- name: Download ddtest binary
run: |
mkdir -p bin
gh release download --repo DataDog/ddtest --pattern "ddtest-linux-amd64" --dir bin
mv bin/ddtest-linux-amd64 bin/ddtest
chmod +x bin/ddtest
env:
GH_TOKEN: ${{ github.token }}
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Configure Datadog Test Optimization
uses: datadog/test-visibility-github-action@v2
with:
languages: ruby
api_key: ${{ secrets.DD_API_KEY }}
site: datadoghq.com
- id: dd_plan
name: Plan test execution with DDTest
run: bin/ddtest plan
- uses: actions/upload-artifact@v4
with:
name: dd-artifacts
path: .testoptimization
include-hidden-files: true
dd_test:
runs-on: ubuntu-latest
needs: [dd_plan]
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.dd_plan.outputs.matrix) }}
steps:
- uses: actions/checkout@v4
- name: Download ddtest binary
run: |
mkdir -p bin
gh release download --repo DataDog/ddtest --pattern "ddtest-linux-amd64" --dir bin
mv bin/ddtest-linux-amd64 bin/ddtest
chmod +x bin/ddtest
env:
GH_TOKEN: ${{ github.token }}
- uses: actions/download-artifact@v4
with:
name: dd-artifacts
path: .testoptimization
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Configure Datadog Test Optimization
uses: datadog/test-visibility-github-action@v2
with:
languages: ruby
api_key: ${{ secrets.DD_API_KEY }}
site: datadoghq.com
- name: Run tests
run: bin/ddtest run --ci-node ${{ matrix.ci_node_index }}DDTest automatically writes the matrix file at .testoptimization/github/config
that looks like:
matrix={"include":[{"ci_node_index":0,"ci_node_total":3},{"ci_node_index":1,"ci_node_total":3},{"ci_node_index":2,"ci_node_total":3}]}
In GitHub Actions, ddtest plan also writes this matrix to $GITHUB_OUTPUT, so
the plan step can expose it directly as steps.dd_plan.outputs.matrix.
Use the same plan/test job structure for Python projects, but configure the runner and setup steps for pytest:
env:
DD_TEST_OPTIMIZATION_RUNNER_PLATFORM: python
DD_TEST_OPTIMIZATION_RUNNER_FRAMEWORK: pytest
DD_TEST_OPTIMIZATION_RUNNER_MIN_PARALLELISM: 1
DD_TEST_OPTIMIZATION_RUNNER_MAX_PARALLELISM: 8Replace each Ruby setup step with Python dependency installation:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
- name: Install Python dependencies
run: python -m pip install -r requirements.txt "ddtrace>=4.11.0" pytestConfigure Datadog Test Optimization for Python:
- name: Configure Datadog Test Optimization
uses: datadog/test-visibility-github-action@v2
with:
languages: python
api_key: ${{ secrets.DD_API_KEY }}
site: datadoghq.comThe ddtest plan and ddtest run --ci-node ${{ matrix.ci_node_index }}
commands can stay the same when the platform and framework are provided through
the environment.
Use the same plan/test job structure for JavaScript projects, but configure the runner and setup steps for Jest:
env:
DD_TEST_OPTIMIZATION_RUNNER_PLATFORM: javascript
DD_TEST_OPTIMIZATION_RUNNER_FRAMEWORK: jest
DD_TEST_OPTIMIZATION_RUNNER_MIN_PARALLELISM: 1
DD_TEST_OPTIMIZATION_RUNNER_MAX_PARALLELISM: 8Replace each Ruby setup step with Node.js dependency installation:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
- name: Install JavaScript dependencies
run: npm ciIn the run job, configure Datadog Test Optimization for JavaScript:
- name: Configure Datadog Test Optimization
uses: datadog/test-visibility-github-action@v3
with:
languages: js
api_key: ${{ secrets.DD_API_KEY }}
site: datadoghq.comThe action installs dd-trace outside the project and exports its absolute
preload path as DD_TRACE_PACKAGE. DDTest adds the preload automatically unless
NODE_OPTIONS already contains a Datadog CI require. The plan job does not need
the tracer or the action; supply its Datadog credentials directly:
- id: dd_plan
name: Plan test execution with DDTest
run: bin/ddtest plan
env:
DD_API_KEY: ${{ secrets.DD_API_KEY }}
DD_SITE: datadoghq.com
- name: Run tests
run: bin/ddtest run --ci-node ${{ matrix.ci_node_index }}Include the action configuration step in the run job after installing the
project's dependencies and before ddtest run. DDTest validates the selected
preload for execution and excludes it from discovery processes. The project
does not need a dd-trace dependency
or NODE_PATH. For Mocha, set the framework to mocha and pass a
--command that invokes Mocha directly if the project needs custom flags.