diff --git a/integration-tests/init.spec.js b/integration-tests/init.spec.js index dd091b63be3..d9df9164c8c 100644 --- a/integration-tests/init.spec.js +++ b/integration-tests/init.spec.js @@ -1,5 +1,6 @@ 'use strict' +const assert = require('assert') const semver = require('semver') const { runAndCheckWithTelemetry: testFile, @@ -99,70 +100,98 @@ function testRuntimeVersionChecks (arg, filename) { } } - if (!currentVersionIsSupported) { - context('when node version is less than engines field', () => { - useEnv({ NODE_OPTIONS }) + let pkgPath + let pkgStr - it('should not initialize the tracer', () => doTest('false\n', [])) + before(() => { + pkgPath = `${sandboxCwd()}/node_modules/dd-trace/package.json` + pkgStr = fs.readFileSync(pkgPath, 'utf8') + }) - context('with DD_INJECTION_ENABLED', () => { - useEnv({ DD_INJECTION_ENABLED }) + after(() => { + fs.writeFileSync(pkgPath, pkgStr) + }) - context('without debug', () => { - it('should not initialize the tracer', () => doTest('false\n', telemetryAbort)) + it('should be able to use the engines field', () => { + const engines = require(`${sandboxCwd()}/node_modules/dd-trace/package.json`).engines.node - it('should initialize the tracer, if DD_INJECT_FORCE', () => doTestForced('true\n', telemetryForced)) - }) + assert.match(engines, /^>=[\d]+(\.[\d]+){0,2} <[\d]+(\.[\d]+){0,2}?/) + }) - context('with debug', () => { - useEnv({ DD_TRACE_DEBUG }) + context('when node version is out of range of the engines field', () => { + useEnv({ NODE_OPTIONS }) + + before(() => { + const pkg = JSON.parse(pkgStr) + pkg.engines.node = '>=0 <0' + fs.writeFileSync(pkgPath, JSON.stringify(pkg)) + }) - it('should not initialize the tracer', () => - doTest(`Aborting application instrumentation due to incompatible_runtime. + it('should not initialize the tracer', () => doTest('false\n', [])) + + context('with DD_INJECTION_ENABLED', () => { + useEnv({ DD_INJECTION_ENABLED }) + + context('without debug', () => { + it('should not initialize the tracer', () => doTest('false\n', telemetryAbort)) + + it('should initialize the tracer, if DD_INJECT_FORCE', () => doTestForced('true\n', telemetryForced)) + }) + + context('with debug', () => { + useEnv({ DD_TRACE_DEBUG }) + + it('should not initialize the tracer', () => + doTest(`Aborting application instrumentation due to incompatible_runtime. Found incompatible runtime Node.js ${process.versions.node}, Supported runtimes: Node.js \ ->=18. +>=0 <0. false `, telemetryAbort)) - it('should initialize the tracer, if DD_INJECT_FORCE', () => - doTestForced(`Aborting application instrumentation due to incompatible_runtime. + it('should initialize the tracer, if DD_INJECT_FORCE', () => + doTestForced(`Aborting application instrumentation due to incompatible_runtime. Found incompatible runtime Node.js ${process.versions.node}, Supported runtimes: Node.js \ ->=18. +>=0 <0. DD_INJECT_FORCE enabled, allowing unsupported runtimes and continuing. Application instrumentation bootstrapping complete true `, telemetryForced)) - }) }) }) - } else { - context('when node version is more than engines field', () => { - useEnv({ NODE_OPTIONS }) + }) + + context('when node version is in range of the engines field', () => { + useEnv({ NODE_OPTIONS }) + + before(() => { + const pkg = JSON.parse(pkgStr) + pkg.engines.node = '>=0 <1000' + fs.writeFileSync(pkgPath, JSON.stringify(pkg)) + }) - it('should initialize the tracer, if no DD_INJECTION_ENABLED', () => doTest('true\n', [], 'manual')) + it('should initialize the tracer, if no DD_INJECTION_ENABLED', () => doTest('true\n', [], 'manual')) - context('with DD_INJECTION_ENABLED', () => { - useEnv({ DD_INJECTION_ENABLED }) + context('with DD_INJECTION_ENABLED', () => { + useEnv({ DD_INJECTION_ENABLED }) - context('without debug', () => { - it('should initialize the tracer', () => doTest('true\n', telemetryGood, 'ssi')) + context('without debug', () => { + it('should initialize the tracer', () => doTest('true\n', telemetryGood, 'ssi')) - it('should initialize the tracer, if DD_INJECT_FORCE', () => - doTestForced('true\n', telemetryGood, 'ssi')) - }) + it('should initialize the tracer, if DD_INJECT_FORCE', () => + doTestForced('true\n', telemetryGood, 'ssi')) + }) - context('with debug', () => { - useEnv({ DD_TRACE_DEBUG }) + context('with debug', () => { + useEnv({ DD_TRACE_DEBUG }) - it('should initialize the tracer', () => - doTest('Application instrumentation bootstrapping complete\ntrue\n', telemetryGood, 'ssi')) + it('should initialize the tracer', () => + doTest('Application instrumentation bootstrapping complete\ntrue\n', telemetryGood, 'ssi')) - it('should initialize the tracer, if DD_INJECT_FORCE', () => - doTestForced('Application instrumentation bootstrapping complete\ntrue\n', telemetryGood, 'ssi')) - }) + it('should initialize the tracer, if DD_INJECT_FORCE', () => + doTestForced('Application instrumentation bootstrapping complete\ntrue\n', telemetryGood, 'ssi')) }) }) - } + }) }) } diff --git a/package.json b/package.json index c8c406857fc..c389ee084e7 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ }, "homepage": "https://github.com/DataDog/dd-trace-js#readme", "engines": { - "node": ">=18" + "node": ">=18 <26" }, "files": [ "ci/**/*", diff --git a/packages/dd-trace/src/guardrails/index.js b/packages/dd-trace/src/guardrails/index.js index 9379d042c0e..c8f82fd1038 100644 --- a/packages/dd-trace/src/guardrails/index.js +++ b/packages/dd-trace/src/guardrails/index.js @@ -14,7 +14,9 @@ function guard (fn) { var clobberBailout = false var forced = isTrue(process.env.DD_INJECT_FORCE) var engines = require('../../../../package.json').engines - var minMajor = parseInt(engines.node.replace(/[^0-9]/g, '')) + var versions = engines.node.match(/[\d.]+/g) + var minMajor = versions[0].split('.')[0] + var maxMajor = versions[1].split('.')[0] var version = process.versions.node if (process.env.DD_INJECTION_ENABLED) { @@ -40,7 +42,7 @@ function guard (fn) { // If the runtime doesn't match the engines field in package.json, then we // should not initialize the tracer. - if (!clobberBailout && NODE_MAJOR < minMajor) { + if (!clobberBailout && (NODE_MAJOR < minMajor || NODE_MAJOR > maxMajor)) { initBailout = true telemetry([ { name: 'abort', tags: ['reason:incompatible_runtime'] },