dd-trace 6.7.0 → 6.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/ci/diagnose.js +27 -25
  2. package/ci/init.js +6 -6
  3. package/ci/runbook.md +114 -20
  4. package/ci/test-optimization-validation/approval-artifacts.js +36 -3
  5. package/ci/test-optimization-validation/approval.js +78 -22
  6. package/ci/test-optimization-validation/blocker-category.js +24 -0
  7. package/ci/test-optimization-validation/ci-discovery.js +23 -17
  8. package/ci/test-optimization-validation/ci-package-scripts.js +34 -6
  9. package/ci/test-optimization-validation/ci-remediation.js +1 -1
  10. package/ci/test-optimization-validation/cli.js +280 -52
  11. package/ci/test-optimization-validation/command-blocker.js +159 -20
  12. package/ci/test-optimization-validation/command-output-policy.js +14 -8
  13. package/ci/test-optimization-validation/command-runner.js +9 -7
  14. package/ci/test-optimization-validation/environment.js +4 -2
  15. package/ci/test-optimization-validation/executable.js +15 -13
  16. package/ci/test-optimization-validation/execution-lock.js +70 -0
  17. package/ci/test-optimization-validation/framework-adapters/cucumber-validation.json +3 -0
  18. package/ci/test-optimization-validation/framework-adapters/cucumber.js +657 -5
  19. package/ci/test-optimization-validation/framework-adapters/playwright.js +5 -5
  20. package/ci/test-optimization-validation/framework-adapters/vitest.js +517 -0
  21. package/ci/test-optimization-validation/generated-files.js +47 -37
  22. package/ci/test-optimization-validation/generated-test-contract.js +9 -7
  23. package/ci/test-optimization-validation/generated-verifier.js +24 -17
  24. package/ci/test-optimization-validation/literal-glob.js +52 -0
  25. package/ci/test-optimization-validation/manifest-loader.js +3 -0
  26. package/ci/test-optimization-validation/manifest-scaffold.js +301 -52
  27. package/ci/test-optimization-validation/manifest-schema.js +80 -17
  28. package/ci/test-optimization-validation/offline-fixtures.js +13 -4
  29. package/ci/test-optimization-validation/offline-output.js +6 -6
  30. package/ci/test-optimization-validation/package-check.js +94 -0
  31. package/ci/test-optimization-validation/plan-writer.js +183 -10
  32. package/ci/test-optimization-validation/preflight-runner.js +110 -31
  33. package/ci/test-optimization-validation/project-build-artifact.js +31 -0
  34. package/ci/test-optimization-validation/redaction.js +18 -27
  35. package/ci/test-optimization-validation/report-writer.js +182 -48
  36. package/ci/test-optimization-validation/result-semantics.js +20 -3
  37. package/ci/test-optimization-validation/runner-command.js +41 -21
  38. package/ci/test-optimization-validation/runner-contract.js +79 -43
  39. package/ci/test-optimization-validation/safe-files.js +4 -4
  40. package/ci/test-optimization-validation/scenarios/basic-reporting.js +60 -6
  41. package/ci/test-optimization-validation/scenarios/ci-wiring.js +141 -35
  42. package/ci/test-optimization-validation/scenarios/helpers.js +30 -6
  43. package/ci/test-optimization-validation/scenarios/test-management.js +2 -2
  44. package/ci/test-optimization-validation/static-diagnosis.js +10 -3
  45. package/ci/test-optimization-validation/test-output.js +2 -1
  46. package/ci/test-optimization-validation/validation-blocker.js +21 -0
  47. package/ci/vitest-no-worker-init-setup.mjs +377 -84
  48. package/index.d.ts +175 -14
  49. package/init.js +1 -17
  50. package/initialize.mjs +11 -0
  51. package/loader-hook.mjs +6 -4
  52. package/package.json +12 -4
  53. package/packages/datadog-core/src/utils/src/kebabcase.js +8 -2
  54. package/packages/datadog-core/src/utils/src/parse-tags.js +0 -1
  55. package/packages/datadog-esbuild/index.js +4 -2
  56. package/packages/datadog-esbuild/src/utils.js +17 -2
  57. package/packages/datadog-instrumentations/src/ai.js +61 -34
  58. package/packages/datadog-instrumentations/src/bluebird.js +6 -6
  59. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +85 -9
  60. package/packages/datadog-instrumentations/src/cucumber.js +131 -51
  61. package/packages/datadog-instrumentations/src/dns.js +21 -2
  62. package/packages/datadog-instrumentations/src/electron.js +1 -0
  63. package/packages/datadog-instrumentations/src/fastify.js +3 -1
  64. package/packages/datadog-instrumentations/src/grpc/client.js +4 -2
  65. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +3 -1
  66. package/packages/datadog-instrumentations/src/helpers/extract-package-and-module-path.js +10 -0
  67. package/packages/datadog-instrumentations/src/helpers/hook.js +19 -2
  68. package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
  69. package/packages/datadog-instrumentations/src/helpers/register.js +9 -3
  70. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +34 -9
  71. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  72. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +175 -0
  73. package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +20 -2
  74. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.js +32 -0
  75. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +61 -0
  76. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +50 -18
  77. package/packages/datadog-instrumentations/src/helpers/router-helper.js +38 -7
  78. package/packages/datadog-instrumentations/src/helpers/shared-utils.js +39 -0
  79. package/packages/datadog-instrumentations/src/http/client.js +1 -3
  80. package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +1 -1
  81. package/packages/datadog-instrumentations/src/jest.js +986 -246
  82. package/packages/datadog-instrumentations/src/mocha/common.js +1 -3
  83. package/packages/datadog-instrumentations/src/mocha/main.js +109 -51
  84. package/packages/datadog-instrumentations/src/mocha/utils.js +120 -32
  85. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +44 -0
  86. package/packages/datadog-instrumentations/src/mocha/worker.js +441 -43
  87. package/packages/datadog-instrumentations/src/moleculer/client.js +1 -1
  88. package/packages/datadog-instrumentations/src/mysql.js +1 -1
  89. package/packages/datadog-instrumentations/src/next.js +155 -23
  90. package/packages/datadog-instrumentations/src/openai.js +14 -0
  91. package/packages/datadog-instrumentations/src/pg.js +180 -6
  92. package/packages/datadog-instrumentations/src/playwright.js +176 -81
  93. package/packages/datadog-instrumentations/src/promise-js.js +4 -4
  94. package/packages/datadog-instrumentations/src/promise.js +3 -3
  95. package/packages/datadog-instrumentations/src/rhea.js +1 -1
  96. package/packages/datadog-instrumentations/src/router.js +195 -19
  97. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +567 -65
  98. package/packages/datadog-instrumentations/src/vitest-main.js +438 -54
  99. package/packages/datadog-instrumentations/src/vitest-util.js +42 -7
  100. package/packages/datadog-instrumentations/src/vitest-worker.js +234 -17
  101. package/packages/datadog-instrumentations/src/webdriverio.js +1090 -0
  102. package/packages/datadog-instrumentations/src/when.js +3 -3
  103. package/packages/datadog-instrumentations/src/ws.js +5 -1
  104. package/packages/datadog-plugin-aerospike/src/index.js +1 -3
  105. package/packages/datadog-plugin-amqplib/src/client.js +1 -1
  106. package/packages/datadog-plugin-amqplib/src/producer.js +1 -1
  107. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +59 -48
  108. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  109. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +2 -2
  110. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -3
  111. package/packages/datadog-plugin-azure-service-bus/src/producer.js +5 -3
  112. package/packages/datadog-plugin-bullmq/src/producer.js +3 -3
  113. package/packages/datadog-plugin-child_process/src/index.js +3 -3
  114. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -11
  115. package/packages/datadog-plugin-cucumber/src/index.js +5 -1
  116. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +50 -46
  117. package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -1
  118. package/packages/datadog-plugin-cypress/src/support.js +7 -4
  119. package/packages/datadog-plugin-electron/src/net.js +10 -4
  120. package/packages/datadog-plugin-fastify/src/tracing.js +1 -1
  121. package/packages/datadog-plugin-fs/src/index.js +0 -4
  122. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +14 -7
  123. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +19 -10
  124. package/packages/datadog-plugin-graphql/src/execute.js +1 -0
  125. package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -1
  126. package/packages/datadog-plugin-http/src/client.js +3 -2
  127. package/packages/datadog-plugin-http2/src/client.js +1 -1
  128. package/packages/datadog-plugin-jest/src/index.js +3 -21
  129. package/packages/datadog-plugin-jest/src/util.js +4 -1
  130. package/packages/datadog-plugin-kafkajs/src/producer.js +2 -1
  131. package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
  132. package/packages/datadog-plugin-mocha/src/index.js +342 -6
  133. package/packages/datadog-plugin-next/src/index.js +57 -9
  134. package/packages/datadog-plugin-openai/src/tracing.js +4 -0
  135. package/packages/datadog-plugin-pg/src/index.js +65 -1
  136. package/packages/datadog-plugin-playwright/src/index.js +1 -1
  137. package/packages/datadog-plugin-prisma/src/index.js +5 -1
  138. package/packages/datadog-plugin-rhea/src/consumer.js +16 -13
  139. package/packages/datadog-plugin-rhea/src/producer.js +1 -1
  140. package/packages/datadog-plugin-undici/src/index.js +2 -1
  141. package/packages/datadog-plugin-vitest/src/index.js +179 -18
  142. package/packages/datadog-shimmer/src/shimmer.js +6 -2
  143. package/packages/datadog-webpack/index.js +2 -2
  144. package/packages/dd-trace/src/aiguard/sdk.js +3 -0
  145. package/packages/dd-trace/src/appsec/{blocking.js → blocking/index.js} +26 -6
  146. package/packages/dd-trace/src/appsec/downstream_requests.js +1 -1
  147. package/packages/dd-trace/src/appsec/handlers/auth.js +62 -0
  148. package/packages/dd-trace/src/appsec/handlers/http-request.js +215 -0
  149. package/packages/dd-trace/src/appsec/handlers/http-response.js +78 -0
  150. package/packages/dd-trace/src/appsec/handlers/http-shared.js +24 -0
  151. package/packages/dd-trace/src/appsec/handlers/payments.js +104 -0
  152. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
  153. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-analyzer.js +1 -1
  154. package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +1 -1
  155. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
  156. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -3
  157. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +2 -2
  158. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +2 -2
  159. package/packages/dd-trace/src/appsec/index.js +48 -476
  160. package/packages/dd-trace/src/appsec/sdk/track_event.js +10 -1
  161. package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
  162. package/packages/dd-trace/src/ci-visibility/coverage-report-discovery.js +46 -14
  163. package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +89 -0
  164. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +7 -6
  165. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +29 -15
  166. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +19 -1
  167. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +25 -1
  168. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/webdriverio.js +26 -0
  169. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -1
  170. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +22 -7
  171. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -14
  172. package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -3
  173. package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +21 -5
  174. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +2 -2
  175. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +5 -1
  176. package/packages/dd-trace/src/config/defaults.js +14 -6
  177. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -2
  178. package/packages/dd-trace/src/config/helper.js +2 -0
  179. package/packages/dd-trace/src/config/index.js +31 -5
  180. package/packages/dd-trace/src/config/parsers.js +19 -1
  181. package/packages/dd-trace/src/config/remote_config.js +1 -1
  182. package/packages/dd-trace/src/config/supported-configurations.json +13 -6
  183. package/packages/dd-trace/src/datastreams/encoding.js +3 -4
  184. package/packages/dd-trace/src/debugger/devtools_client/log.js +2 -1
  185. package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +1 -4
  186. package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -2
  187. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +2 -2
  188. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +16 -2
  189. package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
  190. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
  191. package/packages/dd-trace/src/encode/tags-processors.js +2 -2
  192. package/packages/dd-trace/src/exporters/common/url.js +3 -5
  193. package/packages/dd-trace/src/exporters/electron/index.js +4 -1
  194. package/packages/dd-trace/src/external-logger/src/index.js +1 -2
  195. package/packages/dd-trace/src/flare/index.js +2 -2
  196. package/packages/dd-trace/src/guardrails/apply-pm2-env.js +16 -0
  197. package/packages/dd-trace/src/guardrails/log.js +1 -10
  198. package/packages/dd-trace/src/id.js +1 -1
  199. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -1
  200. package/packages/dd-trace/src/llmobs/eval-metric.js +249 -0
  201. package/packages/dd-trace/src/llmobs/experiments/client.js +4 -2
  202. package/packages/dd-trace/src/llmobs/experiments/dataset.js +66 -14
  203. package/packages/dd-trace/src/llmobs/experiments/experiment.js +289 -95
  204. package/packages/dd-trace/src/llmobs/experiments/index.js +66 -19
  205. package/packages/dd-trace/src/llmobs/experiments/noop.js +95 -10
  206. package/packages/dd-trace/src/llmobs/experiments/result.js +13 -2
  207. package/packages/dd-trace/src/llmobs/experiments/util.js +220 -0
  208. package/packages/dd-trace/src/llmobs/noop.js +2 -0
  209. package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +1 -1
  210. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
  211. package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +1 -1
  212. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +5 -5
  213. package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +1 -1
  214. package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
  215. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
  216. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
  217. package/packages/dd-trace/src/llmobs/sdk.js +152 -78
  218. package/packages/dd-trace/src/llmobs/span_processor.js +9 -7
  219. package/packages/dd-trace/src/llmobs/tagger.js +1 -2
  220. package/packages/dd-trace/src/llmobs/telemetry.js +18 -0
  221. package/packages/dd-trace/src/llmobs/writers/base.js +3 -0
  222. package/packages/dd-trace/src/llmobs/writers/spans.js +12 -6
  223. package/packages/dd-trace/src/llmobs/writers/util.js +2 -0
  224. package/packages/dd-trace/src/log/channels.js +1 -9
  225. package/packages/dd-trace/src/log/levels.js +12 -0
  226. package/packages/dd-trace/src/noop/proxy.js +2 -2
  227. package/packages/dd-trace/src/openfeature/writers/exposures.js +1 -1
  228. package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
  229. package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +1 -1
  230. package/packages/dd-trace/src/opentelemetry/metrics/meter.js +8 -4
  231. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
  232. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +3 -2
  233. package/packages/dd-trace/src/opentelemetry/span.js +4 -0
  234. package/packages/dd-trace/src/opentracing/span.js +1 -1
  235. package/packages/dd-trace/src/opentracing/span_context.js +1 -1
  236. package/packages/dd-trace/src/plugins/ci_plugin.js +124 -23
  237. package/packages/dd-trace/src/plugins/index.js +2 -0
  238. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  239. package/packages/dd-trace/src/plugins/tracing.js +1 -0
  240. package/packages/dd-trace/src/plugins/util/ci.js +13 -6
  241. package/packages/dd-trace/src/plugins/util/git.js +7 -5
  242. package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +3 -3
  243. package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
  244. package/packages/dd-trace/src/plugins/util/llm.js +2 -2
  245. package/packages/dd-trace/src/plugins/util/stacktrace.js +3 -0
  246. package/packages/dd-trace/src/plugins/util/tags.js +2 -0
  247. package/packages/dd-trace/src/plugins/util/test.js +356 -86
  248. package/packages/dd-trace/src/plugins/util/url.js +5 -5
  249. package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
  250. package/packages/dd-trace/src/plugins/util/web.js +24 -2
  251. package/packages/dd-trace/src/priority_sampler.js +6 -3
  252. package/packages/dd-trace/src/profiler.js +1 -1
  253. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +1 -1
  254. package/packages/dd-trace/src/profiling/profilers/events.js +2 -2
  255. package/packages/dd-trace/src/profiling/profilers/poisson.js +1 -1
  256. package/packages/dd-trace/src/profiling/profilers/shared.js +2 -2
  257. package/packages/dd-trace/src/proxy.js +1 -0
  258. package/packages/dd-trace/src/ritm.js +10 -20
  259. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +4 -2
  260. package/packages/dd-trace/src/sampling_rule.js +4 -2
  261. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +1 -1
  262. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +1 -1
  263. package/packages/dd-trace/src/startup-log.js +3 -0
  264. package/packages/dd-trace/src/telemetry/logs/index.js +3 -0
  265. package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -1
  266. package/packages/dd-trace/src/telemetry/telemetry.js +1 -1
  267. package/packages/dd-trace/src/util.js +16 -0
  268. package/vendor/dist/@apm-js-collab/code-transformer/index.js +12 -12
  269. package/vendor/dist/pprof-format/index.js +1 -1
  270. package/vendor/dist/source-map/index.js +1 -1
  271. package/version.js +10 -8
  272. /package/packages/dd-trace/src/appsec/{blocked_templates.js → blocking/templates.js} +0 -0
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const { BLOCKER_CATEGORIES, getBlockerDomain } = require('./blocker-category')
3
4
  const { getCommandBlocker } = require('./command-blocker')
4
5
  const { runCommand, serializeDisplayCommand } = require('./command-runner')
5
6
  const { getBasicCommand } = require('./runner-command')
@@ -17,12 +18,81 @@ const { getObservedTestCount } = require('./test-output')
17
18
  * @returns {Promise<{ok: boolean, failure?: object, preflight: object}>} preflight outcome
18
19
  */
19
20
  async function runFrameworkPreflight ({ framework, out, options }) {
20
- const command = getBasicCommand(framework)
21
- const outDir = frameworkOutDir(out, framework, 'preflight')
21
+ const candidates = [
22
+ {
23
+ localSocketRequired: framework.localSocketRequired,
24
+ testFile: framework.validation.testFile,
25
+ },
26
+ ...(framework.validation.fallbackTests || []),
27
+ ]
28
+ const attempts = []
29
+ let last
30
+
31
+ for (const [index, candidate] of candidates.entries()) {
32
+ // Fallbacks are ordered and later candidates must not run after one succeeds.
33
+ // eslint-disable-next-line no-await-in-loop
34
+ const attempt = await runCandidate({ framework, index, options, out, testFile: candidate.testFile })
35
+ attempts.push(attempt.preflight)
36
+ last = attempt
37
+ if (!attempt.ok) {
38
+ if (isSharedCandidateBlocker(attempt.commandFailure, framework)) break
39
+ continue
40
+ }
41
+
42
+ framework.validation.testFile = candidate.testFile
43
+ const preflight = { ...attempt.preflight, attempts, selectedTestFile: candidate.testFile }
44
+ framework.preflight = preflight
45
+ return { ok: true, preflight }
46
+ }
47
+
48
+ const { commandFailure, observedTestCount, preflight, result } = last
49
+ const completePreflight = {
50
+ ...preflight,
51
+ attempts,
52
+ selectedTestFile: undefined,
53
+ }
54
+ framework.preflight = completePreflight
55
+ const blockerCategory = commandFailure?.blockerCategory ||
56
+ (observedTestCount === 0
57
+ ? BLOCKER_CATEGORIES.VALIDATOR_LIMITATION
58
+ : BLOCKER_CATEGORIES.CLEAN_TEST_FAILED)
59
+ const domain = getBlockerDomain(blockerCategory)
60
+ const diagnosis = getFailureDiagnosis(
61
+ result,
62
+ observedTestCount,
63
+ commandFailure,
64
+ preflight.diagnosticSummary,
65
+ framework
66
+ )
67
+ return {
68
+ ok: false,
69
+ preflight: completePreflight,
70
+ failure: {
71
+ frameworkId: framework.id,
72
+ scenario: 'basic-reporting',
73
+ status: 'blocked',
74
+ diagnosis,
75
+ evidence: {
76
+ blockerCategory,
77
+ commandFailure,
78
+ domain,
79
+ recommendation: commandFailure?.recommendation ||
80
+ `Resolve the selected project test failure before retrying validation: ${diagnosis}`,
81
+ validationIncomplete: true,
82
+ },
83
+ artifacts: Object.values(result.artifacts),
84
+ },
85
+ }
86
+ }
87
+
88
+ async function runCandidate ({ framework, index, options, out, testFile }) {
89
+ const suffix = index === 0 ? '' : `-fallback-${index}`
90
+ const command = getBasicCommand(framework, testFile)
91
+ const outDir = frameworkOutDir(out, framework, `preflight${suffix}`)
22
92
  const result = await runCommand(command, {
23
93
  artifactRoot: out,
24
94
  envMode: 'clean',
25
- label: `${framework.id}:preflight`,
95
+ label: `${framework.id}:preflight${suffix}`,
26
96
  outDir,
27
97
  repositoryRoot: options.repositoryRoot,
28
98
  requireExecutableApproval: options.requireExecutableApproval,
@@ -32,12 +102,13 @@ async function runFrameworkPreflight ({ framework, out, options }) {
32
102
  const commandFailure = getCommandBlocker(result, {
33
103
  browserRequired: framework.browserRequired,
34
104
  framework: framework.framework,
105
+ packageJson: framework.project.packageJson,
35
106
  testsRan: Number.isInteger(observedTestCount) && observedTestCount > 0,
36
107
  })
37
108
  const preflight = {
38
109
  command: serializeDisplayCommand(command),
39
110
  diagnosticSummary: findInterestingLines(`${result.stdout}\n${result.stderr}`, [
40
- /\b(?:Abort trap|Cannot find|Error|ERR_[A-Z_]+|Failed to|Received signal|SIGABRT)\b/i,
111
+ /\b(?:Abort trap|Cannot find|Error|TypeError|ReferenceError|RangeError|SyntaxError|ERR_[A-Z_]+|FAIL|Failed to|No tests found|Received signal|SIGABRT)\b/i,
41
112
  ], 4),
42
113
  durationMs: result.durationMs,
43
114
  exitCode: result.exitCode,
@@ -49,35 +120,16 @@ async function runFrameworkPreflight ({ framework, out, options }) {
49
120
  source: 'validator',
50
121
  stderrSummary: summarizeTestOutput('', result.stderr).join('\n'),
51
122
  stdoutSummary: summarizeTestOutput(result.stdout).join('\n'),
123
+ testFile,
52
124
  timedOut: result.timedOut,
53
125
  ...(commandFailure ? { commandFailure } : {}),
54
126
  }
55
- framework.preflight = preflight
56
-
57
- if (!result.timedOut && result.exitCode === 0 && observedTestCount !== 0) {
58
- return { ok: true, preflight }
59
- }
60
-
61
- const domain = commandFailure?.blockedByExecutionEnvironment
62
- ? 'execution_environment'
63
- : commandFailure?.localRuntimeBlocked
64
- ? 'local_runtime'
65
- : 'project_setup'
66
127
  return {
67
- ok: false,
128
+ commandFailure,
129
+ observedTestCount,
130
+ ok: !result.timedOut && result.exitCode === 0 && observedTestCount !== 0,
68
131
  preflight,
69
- failure: {
70
- frameworkId: framework.id,
71
- scenario: 'basic-reporting',
72
- status: 'blocked',
73
- diagnosis: getFailureDiagnosis(result, observedTestCount, commandFailure),
74
- evidence: {
75
- commandFailure,
76
- domain,
77
- validationIncomplete: true,
78
- },
79
- artifacts: Object.values(result.artifacts),
80
- },
132
+ result,
81
133
  }
82
134
  }
83
135
 
@@ -87,11 +139,17 @@ async function runFrameworkPreflight ({ framework, out, options }) {
87
139
  * @param {object} result command result
88
140
  * @param {number|null} observedTestCount parsed test count
89
141
  * @param {object|undefined} commandFailure classified blocker
142
+ * @param {string[]} diagnosticSummary bounded diagnostic lines
143
+ * @param {object} framework framework manifest entry
90
144
  * @returns {string} customer-facing diagnosis
91
145
  */
92
- function getFailureDiagnosis (result, observedTestCount, commandFailure) {
146
+ function getFailureDiagnosis (result, observedTestCount, commandFailure, diagnosticSummary, framework) {
147
+ const sharedPrerequisite = !commandFailure && framework.allCandidatesRequireLocalSocket
148
+ ? ' Every approved candidate appears to require localhost, so retry in the project environment where its ' +
149
+ 'listener-based tests normally pass.'
150
+ : ''
93
151
  if (commandFailure?.summary) {
94
- return `${commandFailure.summary} Basic Reporting could not be tested reliably.`
152
+ return `${commandFailure.summary} Basic Reporting could not be tested reliably.${sharedPrerequisite}`
95
153
  }
96
154
  if (result.timedOut) {
97
155
  return 'The direct representative test exceeded its approved timeout. Basic Reporting could not be tested ' +
@@ -101,8 +159,29 @@ function getFailureDiagnosis (result, observedTestCount, commandFailure) {
101
159
  return 'The direct runner completed without reporting a test. The selected file may require project wrapper or ' +
102
160
  'configuration semantics, so Basic Reporting remains incomplete.'
103
161
  }
162
+ if (diagnosticSummary.length > 0) {
163
+ return `The direct representative test exited ${result.exitCode} without Datadog initialization. ` +
164
+ `The first reported issue was: ${diagnosticSummary[0]}${sharedPrerequisite}`
165
+ }
104
166
  return `The direct representative test exited ${result.exitCode} without Datadog initialization. Fix or prepare ` +
105
- 'that test normally, then create a fresh validation plan.'
167
+ `that test normally, then create a fresh validation plan.${sharedPrerequisite}`
168
+ }
169
+
170
+ // Do not try fallbacks when every disclosed candidate shares the same prerequisite.
171
+ function isSharedCandidateBlocker (commandFailure, framework) {
172
+ if (!commandFailure) return false
173
+ if (commandFailure.kind === 'local-test-socket-blocked') {
174
+ return framework.allCandidatesRequireLocalSocket === true
175
+ }
176
+ return commandFailure.kind.endsWith('-browser-launch-blocked') ||
177
+ [
178
+ 'cucumber-browser-missing',
179
+ 'cypress-runtime-missing',
180
+ 'playwright-browser-missing',
181
+ 'project-command-environment-missing',
182
+ 'test-runner-command-missing',
183
+ 'vitest-browser-provider-missing',
184
+ ].includes(commandFailure.kind)
106
185
  }
107
186
 
108
187
  module.exports = { runFrameworkPreflight }
@@ -0,0 +1,31 @@
1
+ 'use strict'
2
+
3
+ const path = require('node:path')
4
+
5
+ const BUILD_DIRECTORY_PATTERN = /(?:^|\/)(?:build|dist|generated)(?:\/|$)/
6
+ const WINDOWS_ABSOLUTE_PATH_PATTERN = /^[A-Za-z]:\//
7
+
8
+ // Bare package subpaths and node_modules paths belong to dependencies, not to the customer project.
9
+ function isProjectBuildArtifactPath (filename, projectRoot, baseDirectory = projectRoot) {
10
+ const normalized = String(filename).replaceAll('\\', '/')
11
+ if (!BUILD_DIRECTORY_PATTERN.test(normalized) ||
12
+ /(?:^|\/)node_modules(?:\/|$)/.test(normalized)) return false
13
+
14
+ const relativePath = normalized.startsWith('./') || normalized.startsWith('../')
15
+ if ((!relativePath && !normalized.startsWith('/') && !WINDOWS_ABSOLUTE_PATH_PATTERN.test(normalized)) ||
16
+ typeof projectRoot !== 'string') return false
17
+
18
+ const normalizedRoot = projectRoot.replaceAll('\\', '/')
19
+ const windowsPath = WINDOWS_ABSOLUTE_PATH_PATTERN.test(normalized)
20
+ const windowsRoot = WINDOWS_ABSOLUTE_PATH_PATTERN.test(normalizedRoot)
21
+ if (windowsPath !== windowsRoot && windowsPath) return false
22
+ const pathApi = windowsRoot ? path.win32 : path.posix
23
+ const root = pathApi.resolve(normalizedRoot)
24
+ const candidate = relativePath
25
+ ? pathApi.resolve(String(baseDirectory).replaceAll('\\', '/'), normalized)
26
+ : pathApi.resolve(normalized)
27
+ const relative = pathApi.relative(root, candidate)
28
+ return relative === '' || (!relative.startsWith('..') && !pathApi.isAbsolute(relative))
29
+ }
30
+
31
+ module.exports = { isProjectBuildArtifactPath }
@@ -13,7 +13,6 @@ const SECRET_NAME_SOURCE = [
13
13
  'PASSPHRASE',
14
14
  'CREDENTIAL',
15
15
  'PRIVATE_?KEY',
16
- 'CLIENT_?SECRET',
17
16
  'ACCESS_?KEY',
18
17
  'COOKIE',
19
18
  ].join('|')
@@ -22,23 +21,18 @@ const EXACT_SECRET_ASSIGNMENT_NAME_SOURCE = [
22
21
  'AUTH',
23
22
  'AUTHORIZATION',
24
23
  'PASS',
25
- 'SET-COOKIE',
26
24
  'PAT',
27
25
  'JWT',
28
26
  'WEBHOOK(?:_URL)?',
29
27
  ].join('|')
30
- const SECRET_NAME_CHARS = '[A-Za-z0-9_.-]'
28
+ // Every pattern built from these name sources carries the `i` flag; the classes list uppercase only.
29
+ const SECRET_NAME_CHARS = '[A-Z0-9_.-]'
31
30
  const SECRET_ASSIGNMENT_NAME_SOURCE = [
32
- `(?:${EXACT_SECRET_ASSIGNMENT_NAME_SOURCE})`,
33
- `[A-Za-z_]${SECRET_NAME_CHARS}*(?:${SECRET_NAME_SOURCE})${SECRET_NAME_CHARS}*`,
34
- `[A-Za-z_]${SECRET_NAME_CHARS}*[-_]PASS`,
35
- `[A-Za-z_]${SECRET_NAME_CHARS}*[-_]AUTH(?:ORIZATION)?`,
36
- `[A-Za-z_]${SECRET_NAME_CHARS}*[-_](?:PAT|JWT|WEBHOOK(?:_URL)?)`,
37
- 'PASS',
38
- 'AUTH',
39
- 'AUTHORIZATION',
40
- 'COOKIE',
41
- 'SET-COOKIE',
31
+ EXACT_SECRET_ASSIGNMENT_NAME_SOURCE,
32
+ `[A-Z_]${SECRET_NAME_CHARS}*(?:${SECRET_NAME_SOURCE})${SECRET_NAME_CHARS}*`,
33
+ `[A-Z_]${SECRET_NAME_CHARS}*[-_]PASS`,
34
+ `[A-Z_]${SECRET_NAME_CHARS}*[-_]AUTH(?:ORIZATION)?`,
35
+ `[A-Z_]${SECRET_NAME_CHARS}*[-_](?:PAT|JWT|WEBHOOK(?:_URL)?)`,
42
36
  ].join('|')
43
37
  const SECRET_FLAG_SOURCE = [
44
38
  'api-key',
@@ -54,7 +48,7 @@ const SECRET_FLAG_SOURCE = [
54
48
  'auth',
55
49
  ].join('|')
56
50
  const SECRET_VALUE_SOURCE = String.raw`("[^"]*"|'[^']*'|[^\s,;]+)`
57
- const SENSITIVE_NAME_PATTERN = new RegExp(`(?:${SECRET_NAME_SOURCE})`, 'i')
51
+ const SENSITIVE_NAME_PATTERN = new RegExp(SECRET_NAME_SOURCE, 'i')
58
52
  const SENSITIVE_AUTH_NAME_PATTERN = /(?:^|_)AUTH(?:ORIZATION)?(?:_|$)/i
59
53
  const SENSITIVE_COOKIE_NAME_PATTERN = /(?:^|_)SET_?COOKIE(?:_|$)|(?:^|_)COOKIE(?:_|$)/i
60
54
  const SENSITIVE_PASS_NAME_PATTERN = /(?:^|_)PASS(?:_|$)/i
@@ -64,16 +58,16 @@ const SECRET_ASSIGNMENT_PATTERN = new RegExp(
64
58
  'gi'
65
59
  )
66
60
  const SECRET_FLAG_PATTERN = new RegExp(
67
- String.raw`(--(?:${SECRET_FLAG_SOURCE})(?:-[A-Za-z0-9]+)*)(=|\s+)` + SECRET_VALUE_SOURCE,
61
+ String.raw`(--(?:${SECRET_FLAG_SOURCE})(?:-[A-Z0-9]+)*)(=|\s+)` + SECRET_VALUE_SOURCE,
68
62
  'gi'
69
63
  )
70
64
  const SECRET_FLAG_NAME_PATTERN = new RegExp(
71
- `^--(?:${SECRET_FLAG_SOURCE})(?:-[A-Za-z0-9]+)*$`,
65
+ `^--(?:${SECRET_FLAG_SOURCE})(?:-[A-Z0-9]+)*$`,
72
66
  'i'
73
67
  )
74
68
  const AUTH_HEADER_PATTERN = /\b(Bearer)\s+([^\s'",}\]]+)/gi
75
69
  const AUTH_SCHEME_ASSIGNMENT_QUOTED_PATTERN = new RegExp(
76
- String.raw`\b(${SECRET_ASSIGNMENT_NAME_SOURCE})\s*=\s*(["'])(?:Bearer|Basic)\s+.*?\2`,
70
+ String.raw`\b(${SECRET_ASSIGNMENT_NAME_SOURCE})\s*=\s*(["'])(?:Bearer|Basic)\s.*?\2`,
77
71
  'gi'
78
72
  )
79
73
  const AUTH_SCHEME_ASSIGNMENT_PATTERN = new RegExp(
@@ -83,7 +77,7 @@ const AUTH_SCHEME_ASSIGNMENT_PATTERN = new RegExp(
83
77
  const DEFAULT_IGNORABLE_PATTERN = /\p{Default_Ignorable_Code_Point}/gu
84
78
  const DEFAULT_IGNORABLE_TEST_PATTERN = /\p{Default_Ignorable_Code_Point}/u
85
79
  const CONTROL_CHARACTER_TEST_PATTERN = /\p{Cc}/u
86
- const UNSAFE_CONTROL_SOURCE = String.raw`[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]`
80
+ const UNSAFE_CONTROL_SOURCE = String.raw`[\u0000-\u0008\v\f\u000E-\u001F\u007F-\u009F]`
87
81
  const UNSAFE_CONTROL_PATTERN = new RegExp(UNSAFE_CONTROL_SOURCE, 'g')
88
82
  const UNSAFE_CONTROL_TEST_PATTERN = new RegExp(UNSAFE_CONTROL_SOURCE)
89
83
  const PRIVATE_KEY_BLOCK_PATTERN =
@@ -92,10 +86,10 @@ const JWT_VALUE_PATTERN = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9
92
86
  const KNOWN_TOKEN_VALUE_PATTERN =
93
87
  /\b(?:gh[pousr]_[A-Za-z0-9_]{20,}|github_pat_[A-Za-z0-9_]{20,}|glpat-[A-Za-z0-9_-]{20,}|xox[baprs]-[A-Za-z0-9-]{20,})\b/g
94
88
  const SECRET_HEADER_ENV_NAME_SOURCE = [
95
- `(?:${SECRET_NAME_SOURCE}|PAT|JWT|WEBHOOK(?:_URL)?)`,
96
- `[A-Za-z_]${SECRET_NAME_CHARS}*(?:${SECRET_NAME_SOURCE})${SECRET_NAME_CHARS}*`,
97
- `[A-Za-z_]${SECRET_NAME_CHARS}*[-_]AUTH(?:ORIZATION)?`,
98
- `[A-Za-z_]${SECRET_NAME_CHARS}*[-_](?:PAT|JWT|WEBHOOK(?:_URL)?)`,
89
+ `${SECRET_NAME_SOURCE}|PAT|JWT|WEBHOOK(?:_URL)?`,
90
+ `[A-Z_]${SECRET_NAME_CHARS}*(?:${SECRET_NAME_SOURCE})${SECRET_NAME_CHARS}*`,
91
+ `[A-Z_]${SECRET_NAME_CHARS}*[-_]AUTH(?:ORIZATION)?`,
92
+ `[A-Z_]${SECRET_NAME_CHARS}*[-_](?:PAT|JWT|WEBHOOK(?:_URL)?)`,
99
93
  ].join('|')
100
94
  const SECRET_HEADER_NAME_SOURCE = [
101
95
  'dd-api-key',
@@ -103,16 +97,13 @@ const SECRET_HEADER_NAME_SOURCE = [
103
97
  'api-key',
104
98
  'authorization',
105
99
  'proxy-authorization',
106
- 'token',
107
- 'cookie',
108
- 'set-cookie',
109
100
  SECRET_HEADER_ENV_NAME_SOURCE,
110
101
  ].join('|')
111
102
  const SECRET_HEADER_PATTERN = new RegExp(
112
- String.raw`\b((?:${SECRET_HEADER_NAME_SOURCE}))\s*:\s*("[^"]*"|'[^']*'|[^\r\n,}]+)`,
103
+ String.raw`\b(${SECRET_HEADER_NAME_SOURCE})\s*:\s*("[^"]*"|'[^']*'|[^\r\n,}]+)`,
113
104
  'gi'
114
105
  )
115
- const URL_CREDENTIAL_PATTERN = /([a-z][a-z0-9+.-]*:\/\/)([^@\s/]+)(@)/gi
106
+ const URL_CREDENTIAL_PATTERN = /(?<![a-z0-9+.-])([a-z][a-z0-9+.-]*:\/\/)([^@\s/]+)(@)/gi
116
107
  const GITHUB_SECRET_REFERENCE_PATTERN =
117
108
  /(?:\b[A-Za-z_][A-Za-z0-9_.-]*\s*[:=]\s*)?\$\{\{\s*secrets\.([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g
118
109
  const SAFE_REFERENCE_MARKER_PATTERN = /DDCIVARREF([0-9]+)X/g