diff --git a/.github/actions/node/setup/action.yml b/.github/actions/node/setup/action.yml index 745c7ba6fd..ef54965603 100644 --- a/.github/actions/node/setup/action.yml +++ b/.github/actions/node/setup/action.yml @@ -27,8 +27,10 @@ runs: } case "$VERSION" in eol) version=16 ;; - oldest) oldest_major=$(awk '/"node"/{match($0,/[0-9]+/);print substr($0,RSTART,RLENGTH);exit}' package.json) - version=$(node_version "$oldest_major") ;; + # Pinned to 18 rather than derived from package.json engines.node: CI keeps testing the + # oldest version we still exercise (18) even though the shipped engines floor is now >=22. + # See the Widen engines.node for CI step below, which restores >=18 on the 18/20 legs. + oldest) version=$(node_version 18) ;; maintenance) version=$(node_version 20) ;; active) version=$(node_version 24) ;; latest) version=${LATEST_VERSION:-$(node_version 26)} @@ -44,6 +46,22 @@ runs: node-version: ${{ steps.node-version.outputs.version }} registry-url: ${{ inputs.registry-url || 'https://registry.npmjs.org' }} + # The shipped package.json pins engines.node to the supported runtime range, but CI keeps + # running the full suite on Node 18/20. Widen the field to >=18 for this checkout so the + # runtime guard and the withVersions test helper don't bail and silently skip those jobs. + # Gate on the major so this never runs on the ancient runtimes the guardrails-unsupported + # job installs (those must keep seeing the shipped >=22 so the guard aborts), and so the + # script is only ever parsed by a Node version new enough to run it. + - name: Widen engines.node for CI + shell: bash + run: | + MAJOR=$(node -e "process.stdout.write(String(parseInt(process.versions.node)))") + if [ "$MAJOR" = "18" ] || [ "$MAJOR" = "20" ]; then + node scripts/ci/widen-engines-for-ci.js + else + echo "Leaving engines.node unchanged on Node $(node -v) (only widened on Node 18/20)." + fi + # Persist the resolved version so subsequent runs within this 60-minute window can reuse it. - name: Save resolved version if: steps.node-version-cache.outputs.cache-hit != 'true' diff --git a/scripts/ci/widen-engines-for-ci.js b/scripts/ci/widen-engines-for-ci.js new file mode 100644 index 0000000000..375f7e5d32 --- /dev/null +++ b/scripts/ci/widen-engines-for-ci.js @@ -0,0 +1,35 @@ +#!/usr/bin/env node + +'use strict' + +// CI-only helper. The shipped package.json pins `engines.node` to the supported +// runtime range (`>=22`), but CI still runs the full suite on Node 18 and 20 to +// keep those jobs exercising real tests. The runtime guard +// (packages/dd-trace/src/guardrails/index.js) and the `withVersions` test helper +// both read `engines.node` and bail when the running major is below it, which would +// silently skip every suite on those majors. Widening the field to `>=18` for the +// CI checkout keeps those jobs honest without touching what we publish. +// +// The node/setup action gates this step so it only runs on the supported majors the +// `>=22` bump newly excludes (18 and 20); it is never invoked on the ancient runtimes +// the `integration-guardrails-unsupported` job installs, which must keep seeing the +// shipped `>=22` so the guard aborts. + +const fs = require('node:fs') +const path = require('node:path') + +const CI_MIN_NODE = '>=18' + +const packageJsonPath = path.join(__dirname, '..', '..', 'package.json') +const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) + +const before = pkg.engines.node +if (before === CI_MIN_NODE) return + +pkg.engines.node = CI_MIN_NODE +const after = pkg.engines.node + +fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n') + +// eslint-disable-next-line no-console +console.log(`Widened engines.node for CI: ${before} -> ${after}`)