From 7632016d138c6cec2d6255bbf7fe3feedc9d26d7 Mon Sep 17 00:00:00 2001 From: Calvin Bayer Date: Thu, 2 Apr 2026 14:16:57 +0200 Subject: [PATCH 1/6] ci: use github action that installs datadog-ci binary instead of installing it via npx to prevent supply-chain attacks --- action.yaml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/action.yaml b/action.yaml index 5bf46826..477f026a 100644 --- a/action.yaml +++ b/action.yaml @@ -51,15 +51,13 @@ inputs: runs: using: "composite" steps: - - name: Install node - uses: actions/setup-node@v6 - with: - node-version: ${{ inputs.node-version }} + - name: Install datadog-ci + uses: DataDog/install-datadog-ci-github-action@7960c07e413c56665e12346b34eec80089a7260e # v1.0.2 - name: Upload the JUnit files shell: bash run: | - npx @datadog/datadog-ci@${{ inputs.datadog-ci-version}} junit upload \ + datadog-ci junit upload \ --max-concurrency ${{ inputs.concurrency }} \ ${{ inputs.logs == 'true' && '--logs' || '' }} \ ${{ inputs.auto-discovery == 'true' && '--auto-discovery' || '' }} \ From 513763fc2b1c7616d7374a85747a63812791e78f Mon Sep 17 00:00:00 2001 From: Calvin Bayer Date: Thu, 2 Apr 2026 14:24:50 +0200 Subject: [PATCH 2/6] chore: clean up unused inputs and pass version to install action - Remove unused node-version input parameter - Pass datadog-ci-version to install action's version parameter - Update datadog-ci-version default from "latest" to "v5" - Update README to reflect binary installation instead of npx - Remove node setup references from documentation This completes the transition from npx-based installation to using pre-built binaries, addressing the supply chain vulnerability in #49. Co-Authored-By: Claude Sonnet 4.5 --- README.md | 8 ++------ action.yaml | 10 ++++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 595c76f9..92c13d94 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,8 @@ # Datadog JUnitXML Upload Action -This action downloads the [datadog-ci](https://github.com/DataDog/datadog-ci) and uses it to upload JUnitXML files +This action installs a pre-built [datadog-ci](https://github.com/DataDog/datadog-ci) binary and uses it to upload JUnitXML files to the [Test Optimization product](https://docs.datadoghq.com/tests/). -This action sets up node and requires node `>=14`. You can configure a specific version of node to use. -Note that if you have set up another version already it will override it. - ## Usage ```yaml @@ -33,10 +30,9 @@ The action has the following options: | `auto-discovery` | Do a recursive search and automatic XML files discovery in the folders provided in `files` input (current folder if omitted). Search for filenames that match `*junit*.xml`, `*test*.xml`, `*TEST-*.xml`. | False | `true` | | `ignored-paths` | A comma-separated list of paths that are ignored when junit files auto-discovery is done. Glob patterns are supported. | False | | | `concurrency` | Controls the maximum number of concurrent file uploads | False | `20` | -| `node-version` | The node version to use to install the datadog-ci. It must be `>=14` | False | `20` | | `tags` | Optional extra tags to add to the tests formatted as a comma separated list of tags. Example: `foo:bar,data:dog` | False | | | `service` | Service name to use with the uploaded test results. | False | | | `env` | Optional environment to add to the tests | False | | | `logs` | When set to "true" enables forwarding content from the XML reports as Logs. The content inside ``, ``, and `` is collected as logs. Logs from elements inside a `` are automatically connected to the test. | False | | -| `datadog-ci-version` | Optionally pin the @datadog/datadog-ci version. | False | `latest` | +| `datadog-ci-version` | Version of datadog-ci to install. Use a major version like `v5` to get the latest release within that major version, or a specific tag like `v5.6.0` to pin. | False | `v5` | | `extra-args` | Extra args to be passed to the datadog-ci junit upload command. | False | | diff --git a/action.yaml b/action.yaml index 477f026a..757e47b3 100644 --- a/action.yaml +++ b/action.yaml @@ -24,10 +24,6 @@ inputs: required: true description: Controls the maximum number of concurrent file uploads. default: "20" - node-version: - required: true - description: The node version used to install datadog-ci - default: "20" tags: required: false description: Datadog tags to associate with the uploaded test results. @@ -42,8 +38,8 @@ inputs: description: Set to "true" to enable forwarding content from XML reports as logs. datadog-ci-version: required: false - description: The version of the @datadog/datadog-ci package to use. It defaults to the latest release (`latest`). - default: "latest" + description: Version of datadog-ci to install. Use a major version like `v5` to get the latest release within that major version, or a specific tag like `v5.6.0` to pin. + default: "v5" extra-args: default: "" description: Extra args to be passed to the datadog-ci cli. @@ -53,6 +49,8 @@ runs: steps: - name: Install datadog-ci uses: DataDog/install-datadog-ci-github-action@7960c07e413c56665e12346b34eec80089a7260e # v1.0.2 + with: + version: ${{ inputs.datadog-ci-version }} - name: Upload the JUnit files shell: bash From f6f9ab6708c48e5bea7d17daba678cc8fbf50aa3 Mon Sep 17 00:00:00 2001 From: Calvin Bayer Date: Thu, 2 Apr 2026 14:43:30 +0200 Subject: [PATCH 3/6] chore: add backwards compatibility for legacy npm semver syntax - Extract version translation logic to scripts/translate-version.sh - Support legacy npm semver syntax (^, ~, >=, latest, .x) with deprecation warnings - Update test.yaml to remove node-version parameter - Add test-legacy-version-syntax job to verify backwards compatibility - Update documentation to note legacy syntax is supported but deprecated The translation layer will be removed in v3.0.0. Users should migrate to: - Major versions: v5 or 5 - Exact versions: v5.10.0 or 5.10.0 Fixes #49 - Eliminates supply chain vulnerability from runtime npm installs Fixes #31 - Removes setup-node dependency entirely Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/test.yaml | 36 ++++++++++++++++++++++++++++++------ README.md | 2 +- action.yaml | 11 +++++++++-- scripts/translate-version.sh | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 9 deletions(-) create mode 100755 scripts/translate-version.sh diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9c3ccd15..0ee66325 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -10,9 +10,6 @@ on: jobs: test: - strategy: - matrix: - version: [14, 16, 18, 20, 22, 24, 25] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -24,17 +21,44 @@ jobs: files: '**/fixtures/**' service: junit-upload-github-action-tests env: ci - tags: "foo:bar,alpha:bravo,test.node.version:${{ matrix.version}}" - node-version: ${{ matrix.version}} + tags: "foo:bar,alpha:bravo" + - name: Check that test data can be queried + run: | + npm install @datadog/datadog-api-client + node ./check-junit-upload.js + env: + EXTRA_TAGS: "@foo:bar @alpha:bravo" + DD_API_KEY: ${{ secrets.DD_API_KEY_CI_VISIBILITY }} + DD_APP_KEY: ${{ secrets.DD_APP_KEY_CI_VISIBILITY }} + DD_SERVICE: junit-upload-github-action-tests + test-legacy-version-syntax: + runs-on: ubuntu-latest + strategy: + matrix: + # Test backwards compatibility with legacy npm semver syntax + version: ["latest", "^5.0.0", "~5.0.0", ">=5.0.0", "5.x"] + steps: + - uses: actions/checkout@v4 + - name: Upload reports using legacy version syntax + uses: ./ + with: + api_key: ${{secrets.DD_API_KEY_CI_VISIBILITY}} + logs: "true" + files: '**/fixtures/**' + service: junit-upload-github-action-tests + env: ci + tags: "foo:legacy,alpha:legacy,version.syntax:${{ matrix.version}}" + datadog-ci-version: ${{ matrix.version }} - name: Check that test data can be queried run: | npm install @datadog/datadog-api-client node ./check-junit-upload.js env: - EXTRA_TAGS: "@foo:bar @alpha:bravo @test.node.version:${{ matrix.version}}" + EXTRA_TAGS: "@foo:legacy @alpha:legacy @version.syntax:${{ matrix.version}}" DD_API_KEY: ${{ secrets.DD_API_KEY_CI_VISIBILITY }} DD_APP_KEY: ${{ secrets.DD_APP_KEY_CI_VISIBILITY }} DD_SERVICE: junit-upload-github-action-tests + test-older-datadog-ci-version: runs-on: ubuntu-latest steps: diff --git a/README.md b/README.md index 92c13d94..9238f6d7 100644 --- a/README.md +++ b/README.md @@ -34,5 +34,5 @@ The action has the following options: | `service` | Service name to use with the uploaded test results. | False | | | `env` | Optional environment to add to the tests | False | | | `logs` | When set to "true" enables forwarding content from the XML reports as Logs. The content inside ``, ``, and `` is collected as logs. Logs from elements inside a `` are automatically connected to the test. | False | | -| `datadog-ci-version` | Version of datadog-ci to install. Use a major version like `v5` to get the latest release within that major version, or a specific tag like `v5.6.0` to pin. | False | `v5` | +| `datadog-ci-version` | Version of datadog-ci to install. Use a major version like `v5` to get the latest release within that major version, or a specific tag like `v5.6.0` to pin. Legacy npm semver syntax (`^`, `~`, `>=`, `latest`) is still supported but deprecated. | False | `v5` | | `extra-args` | Extra args to be passed to the datadog-ci junit upload command. | False | | diff --git a/action.yaml b/action.yaml index 757e47b3..430418ac 100644 --- a/action.yaml +++ b/action.yaml @@ -38,7 +38,7 @@ inputs: description: Set to "true" to enable forwarding content from XML reports as logs. datadog-ci-version: required: false - description: Version of datadog-ci to install. Use a major version like `v5` to get the latest release within that major version, or a specific tag like `v5.6.0` to pin. + description: Version of datadog-ci to install. Use a major version like `v5` to get the latest release within that major version, or a specific tag like `v5.6.0` to pin. Legacy npm semver syntax (^, ~, >=, latest) is still supported but deprecated. default: "v5" extra-args: default: "" @@ -47,10 +47,17 @@ inputs: runs: using: "composite" steps: + - name: Translate version format (backwards compatibility) + id: translate-version + shell: bash + run: | + translated_version=$("${GITHUB_ACTION_PATH}/scripts/translate-version.sh" "${{ inputs.datadog-ci-version }}") + echo "version=${translated_version}" >> "$GITHUB_OUTPUT" + - name: Install datadog-ci uses: DataDog/install-datadog-ci-github-action@7960c07e413c56665e12346b34eec80089a7260e # v1.0.2 with: - version: ${{ inputs.datadog-ci-version }} + version: ${{ steps.translate-version.outputs.version }} - name: Upload the JUnit files shell: bash diff --git a/scripts/translate-version.sh b/scripts/translate-version.sh new file mode 100755 index 00000000..d13f8e15 --- /dev/null +++ b/scripts/translate-version.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# Translates legacy npm semver syntax to GitHub release tag format +# +# This script provides backwards compatibility for users still using npm-style +# version specifiers (^, ~, >=, latest, etc.) by translating them to equivalent +# GitHub release tags that the install action understands. +# +# TODO: Remove this script in the next major version (v3.0.0) +# Users should migrate to GitHub release tag syntax: v5, v5.10.0, etc. + +set -euo pipefail + +version="$1" + +# Translate legacy npm semver syntax to GitHub release tags +case "$version" in + latest) + echo "::warning::datadog-ci-version 'latest' is deprecated. Please use 'v5' or '5' instead. This will use 'v5'." >&2 + version="v5" + ;; + ^*|~*|'>='*|'<='*|'>'*|'<'*|*.x) + # Extract major version number from semver expressions + # Handles: ^5.10.0, ~5.10.0, >=5.10.0, >5.10.0, <6.0.0, <=5.10.0, 5.x + major=$(echo "$version" | grep -oE '[0-9]+' | head -1) + if [[ -n "$major" ]]; then + echo "::warning::npm semver syntax ('$version') is deprecated. Please use 'v${major}' or '${major}' instead. This will use 'v${major}'." >&2 + version="v${major}" + else + echo "::warning::Unable to parse version '$version'. Passing through as-is, but this may fail." >&2 + fi + ;; +esac + +echo "$version" From 126b11d254fb387c88a11364270d4e080522dad7 Mon Sep 17 00:00:00 2001 From: Calvin Bayer Date: Thu, 2 Apr 2026 14:46:15 +0200 Subject: [PATCH 4/6] docs: add TODO comment to remove backwards compatibility in v3.0.0 Co-Authored-By: Claude Sonnet 4.5 --- action.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/action.yaml b/action.yaml index 430418ac..3bd592a6 100644 --- a/action.yaml +++ b/action.yaml @@ -47,6 +47,8 @@ inputs: runs: using: "composite" steps: + # TODO: Remove this step in the next major version (v3.0.0) + # Users should migrate to GitHub release tag syntax: v5, v5.10.0, etc. - name: Translate version format (backwards compatibility) id: translate-version shell: bash From af23bf4251db646c6f605876c57a3c3216345c89 Mon Sep 17 00:00:00 2001 From: Calvin Bayer Date: Thu, 2 Apr 2026 14:51:03 +0200 Subject: [PATCH 5/6] fix: remove version tag from legacy syntax tests to avoid query issues Tags with special characters (>=, <, etc.) were being interpreted as operators by the Datadog API query, causing test validation to fail. Removed the version-specific tag since it's not needed for validation. Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/test.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 0ee66325..61002cb5 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -47,14 +47,14 @@ jobs: files: '**/fixtures/**' service: junit-upload-github-action-tests env: ci - tags: "foo:legacy,alpha:legacy,version.syntax:${{ matrix.version}}" + tags: "foo:legacy,alpha:legacy" datadog-ci-version: ${{ matrix.version }} - name: Check that test data can be queried run: | npm install @datadog/datadog-api-client node ./check-junit-upload.js env: - EXTRA_TAGS: "@foo:legacy @alpha:legacy @version.syntax:${{ matrix.version}}" + EXTRA_TAGS: "@foo:legacy @alpha:legacy" DD_API_KEY: ${{ secrets.DD_API_KEY_CI_VISIBILITY }} DD_APP_KEY: ${{ secrets.DD_APP_KEY_CI_VISIBILITY }} DD_SERVICE: junit-upload-github-action-tests From 70df82d2f8f54f8980df564c15ecc5e949cd8df0 Mon Sep 17 00:00:00 2001 From: Calvin Bayer Date: Thu, 2 Apr 2026 14:53:57 +0200 Subject: [PATCH 6/6] fix: sanitize version string for tags to avoid query issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a sanitization step that replaces special characters with safe equivalents before using them in tags: - ^ → caret- - ~ → tilde- - >= → gte- - > → gt- - <= → lte- - < → lt- This prevents the Datadog API from interpreting these characters as comparison operators in queries, while still allowing us to track which version syntax was used in each test run. Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/test.yaml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 61002cb5..d0b18664 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -39,6 +39,13 @@ jobs: version: ["latest", "^5.0.0", "~5.0.0", ">=5.0.0", "5.x"] steps: - uses: actions/checkout@v4 + - name: Sanitize version for tag + id: sanitize + run: | + version="${{ matrix.version }}" + # Replace special characters with safe equivalents for tags + safe_version=$(echo "$version" | sed 's/\^/caret-/g; s/~/tilde-/g; s/>=/gte-/g; s/>/gt-/g; s/<=/lte-/g; s/> "$GITHUB_OUTPUT" - name: Upload reports using legacy version syntax uses: ./ with: @@ -47,14 +54,14 @@ jobs: files: '**/fixtures/**' service: junit-upload-github-action-tests env: ci - tags: "foo:legacy,alpha:legacy" + tags: "foo:legacy,alpha:legacy,version.syntax:${{ steps.sanitize.outputs.safe_version }}" datadog-ci-version: ${{ matrix.version }} - name: Check that test data can be queried run: | npm install @datadog/datadog-api-client node ./check-junit-upload.js env: - EXTRA_TAGS: "@foo:legacy @alpha:legacy" + EXTRA_TAGS: "@foo:legacy @alpha:legacy @version.syntax:${{ steps.sanitize.outputs.safe_version }}" DD_API_KEY: ${{ secrets.DD_API_KEY_CI_VISIBILITY }} DD_APP_KEY: ${{ secrets.DD_APP_KEY_CI_VISIBILITY }} DD_SERVICE: junit-upload-github-action-tests