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.
- package/ci/diagnose.js +27 -25
- package/ci/init.js +6 -6
- package/ci/runbook.md +114 -20
- package/ci/test-optimization-validation/approval-artifacts.js +36 -3
- package/ci/test-optimization-validation/approval.js +78 -22
- package/ci/test-optimization-validation/blocker-category.js +24 -0
- package/ci/test-optimization-validation/ci-discovery.js +23 -17
- package/ci/test-optimization-validation/ci-package-scripts.js +34 -6
- package/ci/test-optimization-validation/ci-remediation.js +1 -1
- package/ci/test-optimization-validation/cli.js +280 -52
- package/ci/test-optimization-validation/command-blocker.js +159 -20
- package/ci/test-optimization-validation/command-output-policy.js +14 -8
- package/ci/test-optimization-validation/command-runner.js +9 -7
- package/ci/test-optimization-validation/environment.js +4 -2
- package/ci/test-optimization-validation/executable.js +15 -13
- package/ci/test-optimization-validation/execution-lock.js +70 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber-validation.json +3 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +657 -5
- package/ci/test-optimization-validation/framework-adapters/playwright.js +5 -5
- package/ci/test-optimization-validation/framework-adapters/vitest.js +517 -0
- package/ci/test-optimization-validation/generated-files.js +47 -37
- package/ci/test-optimization-validation/generated-test-contract.js +9 -7
- package/ci/test-optimization-validation/generated-verifier.js +24 -17
- package/ci/test-optimization-validation/literal-glob.js +52 -0
- package/ci/test-optimization-validation/manifest-loader.js +3 -0
- package/ci/test-optimization-validation/manifest-scaffold.js +301 -52
- package/ci/test-optimization-validation/manifest-schema.js +80 -17
- package/ci/test-optimization-validation/offline-fixtures.js +13 -4
- package/ci/test-optimization-validation/offline-output.js +6 -6
- package/ci/test-optimization-validation/package-check.js +94 -0
- package/ci/test-optimization-validation/plan-writer.js +183 -10
- package/ci/test-optimization-validation/preflight-runner.js +110 -31
- package/ci/test-optimization-validation/project-build-artifact.js +31 -0
- package/ci/test-optimization-validation/redaction.js +18 -27
- package/ci/test-optimization-validation/report-writer.js +182 -48
- package/ci/test-optimization-validation/result-semantics.js +20 -3
- package/ci/test-optimization-validation/runner-command.js +41 -21
- package/ci/test-optimization-validation/runner-contract.js +79 -43
- package/ci/test-optimization-validation/safe-files.js +4 -4
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +60 -6
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +141 -35
- package/ci/test-optimization-validation/scenarios/helpers.js +30 -6
- package/ci/test-optimization-validation/scenarios/test-management.js +2 -2
- package/ci/test-optimization-validation/static-diagnosis.js +10 -3
- package/ci/test-optimization-validation/test-output.js +2 -1
- package/ci/test-optimization-validation/validation-blocker.js +21 -0
- package/ci/vitest-no-worker-init-setup.mjs +377 -84
- package/index.d.ts +175 -14
- package/init.js +1 -17
- package/initialize.mjs +11 -0
- package/loader-hook.mjs +6 -4
- package/package.json +12 -4
- package/packages/datadog-core/src/utils/src/kebabcase.js +8 -2
- package/packages/datadog-core/src/utils/src/parse-tags.js +0 -1
- package/packages/datadog-esbuild/index.js +4 -2
- package/packages/datadog-esbuild/src/utils.js +17 -2
- package/packages/datadog-instrumentations/src/ai.js +61 -34
- package/packages/datadog-instrumentations/src/bluebird.js +6 -6
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +85 -9
- package/packages/datadog-instrumentations/src/cucumber.js +131 -51
- package/packages/datadog-instrumentations/src/dns.js +21 -2
- package/packages/datadog-instrumentations/src/electron.js +1 -0
- package/packages/datadog-instrumentations/src/fastify.js +3 -1
- package/packages/datadog-instrumentations/src/grpc/client.js +4 -2
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +3 -1
- package/packages/datadog-instrumentations/src/helpers/extract-package-and-module-path.js +10 -0
- package/packages/datadog-instrumentations/src/helpers/hook.js +19 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +9 -3
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +34 -9
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +175 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +20 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.js +32 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +61 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +50 -18
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +38 -7
- package/packages/datadog-instrumentations/src/helpers/shared-utils.js +39 -0
- package/packages/datadog-instrumentations/src/http/client.js +1 -3
- package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +986 -246
- package/packages/datadog-instrumentations/src/mocha/common.js +1 -3
- package/packages/datadog-instrumentations/src/mocha/main.js +109 -51
- package/packages/datadog-instrumentations/src/mocha/utils.js +120 -32
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +44 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +441 -43
- package/packages/datadog-instrumentations/src/moleculer/client.js +1 -1
- package/packages/datadog-instrumentations/src/mysql.js +1 -1
- package/packages/datadog-instrumentations/src/next.js +155 -23
- package/packages/datadog-instrumentations/src/openai.js +14 -0
- package/packages/datadog-instrumentations/src/pg.js +180 -6
- package/packages/datadog-instrumentations/src/playwright.js +176 -81
- package/packages/datadog-instrumentations/src/promise-js.js +4 -4
- package/packages/datadog-instrumentations/src/promise.js +3 -3
- package/packages/datadog-instrumentations/src/rhea.js +1 -1
- package/packages/datadog-instrumentations/src/router.js +195 -19
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +567 -65
- package/packages/datadog-instrumentations/src/vitest-main.js +438 -54
- package/packages/datadog-instrumentations/src/vitest-util.js +42 -7
- package/packages/datadog-instrumentations/src/vitest-worker.js +234 -17
- package/packages/datadog-instrumentations/src/webdriverio.js +1090 -0
- package/packages/datadog-instrumentations/src/when.js +3 -3
- package/packages/datadog-instrumentations/src/ws.js +5 -1
- package/packages/datadog-plugin-aerospike/src/index.js +1 -3
- package/packages/datadog-plugin-amqplib/src/client.js +1 -1
- package/packages/datadog-plugin-amqplib/src/producer.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +59 -48
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
- package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +2 -2
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -3
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +5 -3
- package/packages/datadog-plugin-bullmq/src/producer.js +3 -3
- package/packages/datadog-plugin-child_process/src/index.js +3 -3
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -11
- package/packages/datadog-plugin-cucumber/src/index.js +5 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +50 -46
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -1
- package/packages/datadog-plugin-cypress/src/support.js +7 -4
- package/packages/datadog-plugin-electron/src/net.js +10 -4
- package/packages/datadog-plugin-fastify/src/tracing.js +1 -1
- package/packages/datadog-plugin-fs/src/index.js +0 -4
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +14 -7
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +19 -10
- package/packages/datadog-plugin-graphql/src/execute.js +1 -0
- package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +3 -2
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +3 -21
- package/packages/datadog-plugin-jest/src/util.js +4 -1
- package/packages/datadog-plugin-kafkajs/src/producer.js +2 -1
- package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +342 -6
- package/packages/datadog-plugin-next/src/index.js +57 -9
- package/packages/datadog-plugin-openai/src/tracing.js +4 -0
- package/packages/datadog-plugin-pg/src/index.js +65 -1
- package/packages/datadog-plugin-playwright/src/index.js +1 -1
- package/packages/datadog-plugin-prisma/src/index.js +5 -1
- package/packages/datadog-plugin-rhea/src/consumer.js +16 -13
- package/packages/datadog-plugin-rhea/src/producer.js +1 -1
- package/packages/datadog-plugin-undici/src/index.js +2 -1
- package/packages/datadog-plugin-vitest/src/index.js +179 -18
- package/packages/datadog-shimmer/src/shimmer.js +6 -2
- package/packages/datadog-webpack/index.js +2 -2
- package/packages/dd-trace/src/aiguard/sdk.js +3 -0
- package/packages/dd-trace/src/appsec/{blocking.js → blocking/index.js} +26 -6
- package/packages/dd-trace/src/appsec/downstream_requests.js +1 -1
- package/packages/dd-trace/src/appsec/handlers/auth.js +62 -0
- package/packages/dd-trace/src/appsec/handlers/http-request.js +215 -0
- package/packages/dd-trace/src/appsec/handlers/http-response.js +78 -0
- package/packages/dd-trace/src/appsec/handlers/http-shared.js +24 -0
- package/packages/dd-trace/src/appsec/handlers/payments.js +104 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +2 -2
- package/packages/dd-trace/src/appsec/index.js +48 -476
- package/packages/dd-trace/src/appsec/sdk/track_event.js +10 -1
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
- package/packages/dd-trace/src/ci-visibility/coverage-report-discovery.js +46 -14
- package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +89 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +7 -6
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +29 -15
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +19 -1
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +25 -1
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/webdriverio.js +26 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +22 -7
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -14
- package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -3
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +21 -5
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +2 -2
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +5 -1
- package/packages/dd-trace/src/config/defaults.js +14 -6
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -2
- package/packages/dd-trace/src/config/helper.js +2 -0
- package/packages/dd-trace/src/config/index.js +31 -5
- package/packages/dd-trace/src/config/parsers.js +19 -1
- package/packages/dd-trace/src/config/remote_config.js +1 -1
- package/packages/dd-trace/src/config/supported-configurations.json +13 -6
- package/packages/dd-trace/src/datastreams/encoding.js +3 -4
- package/packages/dd-trace/src/debugger/devtools_client/log.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +1 -4
- package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +16 -2
- package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
- package/packages/dd-trace/src/encode/tags-processors.js +2 -2
- package/packages/dd-trace/src/exporters/common/url.js +3 -5
- package/packages/dd-trace/src/exporters/electron/index.js +4 -1
- package/packages/dd-trace/src/external-logger/src/index.js +1 -2
- package/packages/dd-trace/src/flare/index.js +2 -2
- package/packages/dd-trace/src/guardrails/apply-pm2-env.js +16 -0
- package/packages/dd-trace/src/guardrails/log.js +1 -10
- package/packages/dd-trace/src/id.js +1 -1
- package/packages/dd-trace/src/llmobs/constants/tags.js +1 -1
- package/packages/dd-trace/src/llmobs/eval-metric.js +249 -0
- package/packages/dd-trace/src/llmobs/experiments/client.js +4 -2
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +66 -14
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +289 -95
- package/packages/dd-trace/src/llmobs/experiments/index.js +66 -19
- package/packages/dd-trace/src/llmobs/experiments/noop.js +95 -10
- package/packages/dd-trace/src/llmobs/experiments/result.js +13 -2
- package/packages/dd-trace/src/llmobs/experiments/util.js +220 -0
- package/packages/dd-trace/src/llmobs/noop.js +2 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +5 -5
- package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +152 -78
- package/packages/dd-trace/src/llmobs/span_processor.js +9 -7
- package/packages/dd-trace/src/llmobs/tagger.js +1 -2
- package/packages/dd-trace/src/llmobs/telemetry.js +18 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +3 -0
- package/packages/dd-trace/src/llmobs/writers/spans.js +12 -6
- package/packages/dd-trace/src/llmobs/writers/util.js +2 -0
- package/packages/dd-trace/src/log/channels.js +1 -9
- package/packages/dd-trace/src/log/levels.js +12 -0
- package/packages/dd-trace/src/noop/proxy.js +2 -2
- package/packages/dd-trace/src/openfeature/writers/exposures.js +1 -1
- package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/meter.js +8 -4
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +3 -2
- package/packages/dd-trace/src/opentelemetry/span.js +4 -0
- package/packages/dd-trace/src/opentracing/span.js +1 -1
- package/packages/dd-trace/src/opentracing/span_context.js +1 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +124 -23
- package/packages/dd-trace/src/plugins/index.js +2 -0
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/tracing.js +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +13 -6
- package/packages/dd-trace/src/plugins/util/git.js +7 -5
- package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +3 -3
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
- package/packages/dd-trace/src/plugins/util/llm.js +2 -2
- package/packages/dd-trace/src/plugins/util/stacktrace.js +3 -0
- package/packages/dd-trace/src/plugins/util/tags.js +2 -0
- package/packages/dd-trace/src/plugins/util/test.js +356 -86
- package/packages/dd-trace/src/plugins/util/url.js +5 -5
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
- package/packages/dd-trace/src/plugins/util/web.js +24 -2
- package/packages/dd-trace/src/priority_sampler.js +6 -3
- package/packages/dd-trace/src/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/events.js +2 -2
- package/packages/dd-trace/src/profiling/profilers/poisson.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/shared.js +2 -2
- package/packages/dd-trace/src/proxy.js +1 -0
- package/packages/dd-trace/src/ritm.js +10 -20
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +4 -2
- package/packages/dd-trace/src/sampling_rule.js +4 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +1 -1
- package/packages/dd-trace/src/startup-log.js +3 -0
- package/packages/dd-trace/src/telemetry/logs/index.js +3 -0
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -1
- package/packages/dd-trace/src/telemetry/telemetry.js +1 -1
- package/packages/dd-trace/src/util.js +16 -0
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +12 -12
- package/vendor/dist/pprof-format/index.js +1 -1
- package/vendor/dist/source-map/index.js +1 -1
- package/version.js +10 -8
- /package/packages/dd-trace/src/appsec/{blocked_templates.js → blocking/templates.js} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
const path = require('path')
|
|
3
|
+
const fs = require('node:fs')
|
|
4
|
+
const path = require('node:path')
|
|
5
5
|
|
|
6
6
|
const {
|
|
7
7
|
MAX_GENERATED_FILES,
|
|
@@ -91,14 +91,16 @@ function cleanupGeneratedFiles (manifest, { keep = false } = {}) {
|
|
|
91
91
|
filesRemoved: 0,
|
|
92
92
|
filesRetained: 0,
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
if (manifest.frameworks) {
|
|
95
|
+
for (const framework of manifest.frameworks) {
|
|
96
|
+
const strategy = framework.generatedTestStrategy
|
|
97
|
+
addCleanupOutcome(
|
|
98
|
+
outcome,
|
|
99
|
+
cleanupPaths(getSafeCleanupPaths(framework, strategy, { includeGeneratedFiles: true })),
|
|
100
|
+
'files'
|
|
101
|
+
)
|
|
102
|
+
addCleanupOutcome(outcome, cleanupCreatedDirectories(framework.project.root), 'directories')
|
|
103
|
+
}
|
|
102
104
|
}
|
|
103
105
|
outcome.status = outcome.filesRetained > 0 || outcome.directoriesRetained > 0
|
|
104
106
|
? 'incomplete'
|
|
@@ -132,7 +134,7 @@ function getMissingDirectories (root, directory) {
|
|
|
132
134
|
function cleanupCreatedDirectories (root) {
|
|
133
135
|
const outcome = { removed: 0, retained: 0 }
|
|
134
136
|
const resolvedRoot = path.resolve(root)
|
|
135
|
-
const directories = [...createdGeneratedDirectories
|
|
137
|
+
const directories = [...createdGeneratedDirectories]
|
|
136
138
|
.filter(([directory]) => isPathInside(resolvedRoot, directory))
|
|
137
139
|
.sort(([left], [right]) => right.length - left.length)
|
|
138
140
|
|
|
@@ -168,13 +170,15 @@ function initializeRuntimeCleanupFiles (framework, strategy) {
|
|
|
168
170
|
if (initializedCleanupStrategies.has(strategy)) return
|
|
169
171
|
|
|
170
172
|
const generatedFiles = new Set((strategy.files || []).map(file => validateGeneratedFilePath(framework, file.path)))
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
if (strategy.cleanupPaths) {
|
|
174
|
+
for (const cleanupPath of strategy.cleanupPaths) {
|
|
175
|
+
const filename = validateCleanupPath(framework, cleanupPath)
|
|
176
|
+
if (generatedFiles.has(filename) || isDirectory(filename) || !isNamespacedRuntimeFile(filename)) continue
|
|
177
|
+
if (fs.existsSync(filename)) {
|
|
178
|
+
throw new Error(`Refusing to delete pre-existing generated validation runtime file: ${filename}`)
|
|
179
|
+
}
|
|
180
|
+
authorizedRuntimeCleanupFiles.set(filename, authorizePathForCleanup(framework.project.root, filename))
|
|
176
181
|
}
|
|
177
|
-
authorizedRuntimeCleanupFiles.set(filename, authorizePathForCleanup(framework.project.root, filename))
|
|
178
182
|
}
|
|
179
183
|
initializedCleanupStrategies.add(strategy)
|
|
180
184
|
}
|
|
@@ -183,20 +187,24 @@ function getSafeCleanupPaths (framework, strategy, { includeGeneratedFiles }) {
|
|
|
183
187
|
if (!strategy) return []
|
|
184
188
|
|
|
185
189
|
const generatedFiles = new Set()
|
|
186
|
-
|
|
187
|
-
|
|
190
|
+
if (strategy.files) {
|
|
191
|
+
for (const file of strategy.files) {
|
|
192
|
+
generatedFiles.add(validateGeneratedFilePath(framework, file.path))
|
|
193
|
+
}
|
|
188
194
|
}
|
|
189
195
|
|
|
190
196
|
const cleanupPaths = []
|
|
191
|
-
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
|
|
197
|
+
if (strategy.cleanupPaths) {
|
|
198
|
+
for (const cleanupPath of strategy.cleanupPaths) {
|
|
199
|
+
const filename = validateCleanupPath(framework, cleanupPath)
|
|
200
|
+
if (generatedFiles.has(filename)) {
|
|
201
|
+
if (includeGeneratedFiles && writtenGeneratedFiles.has(filename)) cleanupPaths.push(filename)
|
|
202
|
+
continue
|
|
203
|
+
}
|
|
197
204
|
|
|
198
|
-
|
|
199
|
-
|
|
205
|
+
if (authorizedRuntimeCleanupFiles.has(filename)) {
|
|
206
|
+
cleanupPaths.push(filename)
|
|
207
|
+
}
|
|
200
208
|
}
|
|
201
209
|
}
|
|
202
210
|
|
|
@@ -251,7 +259,7 @@ function forgetWrittenGeneratedFiles (filenames) {
|
|
|
251
259
|
function authorizePathForCleanup (root, filename) {
|
|
252
260
|
const lexicalRoot = path.resolve(root)
|
|
253
261
|
const physicalRoot = fs.realpathSync(lexicalRoot)
|
|
254
|
-
const rootStat = fs.statSync(physicalRoot)
|
|
262
|
+
const rootStat = fs.statSync(physicalRoot, { bigint: true })
|
|
255
263
|
const authorization = {
|
|
256
264
|
lexicalRoot,
|
|
257
265
|
physicalRoot,
|
|
@@ -264,10 +272,12 @@ function authorizePathForCleanup (root, filename) {
|
|
|
264
272
|
}
|
|
265
273
|
|
|
266
274
|
function pinRuntimeCleanupParents (strategy) {
|
|
267
|
-
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
|
|
275
|
+
if (strategy.cleanupPaths) {
|
|
276
|
+
for (const cleanupPath of strategy.cleanupPaths) {
|
|
277
|
+
const authorization = authorizedRuntimeCleanupFiles.get(path.resolve(cleanupPath))
|
|
278
|
+
if (authorization && authorization.physicalParent === undefined) {
|
|
279
|
+
pinCleanupParent(authorization, cleanupPath)
|
|
280
|
+
}
|
|
271
281
|
}
|
|
272
282
|
}
|
|
273
283
|
}
|
|
@@ -276,7 +286,7 @@ function pinCleanupParent (authorization, filename) {
|
|
|
276
286
|
try {
|
|
277
287
|
const physicalParent = fs.realpathSync(path.dirname(filename))
|
|
278
288
|
if (!isPathInside(authorization.physicalRoot, physicalParent)) return
|
|
279
|
-
const parentStat = fs.statSync(physicalParent)
|
|
289
|
+
const parentStat = fs.statSync(physicalParent, { bigint: true })
|
|
280
290
|
authorization.physicalParent = physicalParent
|
|
281
291
|
authorization.parentDevice = parentStat.dev
|
|
282
292
|
authorization.parentInode = parentStat.ino
|
|
@@ -285,7 +295,7 @@ function pinCleanupParent (authorization, filename) {
|
|
|
285
295
|
|
|
286
296
|
function pinCleanupTarget (authorization, filename) {
|
|
287
297
|
try {
|
|
288
|
-
const targetStat = fs.lstatSync(filename)
|
|
298
|
+
const targetStat = fs.lstatSync(filename, { bigint: true })
|
|
289
299
|
authorization.targetDevice = targetStat.dev
|
|
290
300
|
authorization.targetInode = targetStat.ino
|
|
291
301
|
} catch {}
|
|
@@ -294,7 +304,7 @@ function pinCleanupTarget (authorization, filename) {
|
|
|
294
304
|
function isCleanupAuthorizationValid (filename, authorization) {
|
|
295
305
|
try {
|
|
296
306
|
const currentPhysicalRoot = fs.realpathSync(authorization.lexicalRoot)
|
|
297
|
-
const rootStat = fs.statSync(currentPhysicalRoot)
|
|
307
|
+
const rootStat = fs.statSync(currentPhysicalRoot, { bigint: true })
|
|
298
308
|
if (currentPhysicalRoot !== authorization.physicalRoot ||
|
|
299
309
|
rootStat.dev !== authorization.rootDevice || rootStat.ino !== authorization.rootInode) {
|
|
300
310
|
return false
|
|
@@ -302,14 +312,14 @@ function isCleanupAuthorizationValid (filename, authorization) {
|
|
|
302
312
|
|
|
303
313
|
if (authorization.physicalParent === undefined) return false
|
|
304
314
|
const physicalParent = fs.realpathSync(path.dirname(filename))
|
|
305
|
-
const parentStat = fs.statSync(physicalParent)
|
|
315
|
+
const parentStat = fs.statSync(physicalParent, { bigint: true })
|
|
306
316
|
if (physicalParent !== authorization.physicalParent ||
|
|
307
317
|
parentStat.dev !== authorization.parentDevice || parentStat.ino !== authorization.parentInode) {
|
|
308
318
|
return false
|
|
309
319
|
}
|
|
310
320
|
|
|
311
321
|
if (authorization.targetDevice !== undefined) {
|
|
312
|
-
const targetStat = fs.lstatSync(filename)
|
|
322
|
+
const targetStat = fs.lstatSync(filename, { bigint: true })
|
|
313
323
|
if (targetStat.dev !== authorization.targetDevice || targetStat.ino !== authorization.targetInode) {
|
|
314
324
|
return false
|
|
315
325
|
}
|
|
@@ -79,7 +79,7 @@ function getGeneratedTestContent ({ framework, moduleSystem, scenarioId, stateFi
|
|
|
79
79
|
const requireCall = 'require'
|
|
80
80
|
imports.push(moduleSystem === 'esm'
|
|
81
81
|
? "import { describe, expect, test } from '@jest/globals'"
|
|
82
|
-
: `const
|
|
82
|
+
: `const jestGlobals = ${requireCall}('@jest/globals')`)
|
|
83
83
|
}
|
|
84
84
|
if (framework === 'vitest' && moduleSystem === 'esm') {
|
|
85
85
|
imports.push("import { describe, expect, it } from 'vitest'")
|
|
@@ -97,8 +97,12 @@ function getGeneratedTestContent ({ framework, moduleSystem, scenarioId, stateFi
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
const
|
|
101
|
-
const
|
|
100
|
+
const commonJsJest = framework === 'jest' && moduleSystem === 'commonjs'
|
|
101
|
+
const assertion = framework === 'mocha'
|
|
102
|
+
? 'assert.equal(1, 1)'
|
|
103
|
+
: `${commonJsJest ? 'jestGlobals.' : ''}expect(true).toBe(true)`
|
|
104
|
+
const testFunction = framework === 'jest' ? `${commonJsJest ? 'jestGlobals.' : ''}test` : 'it'
|
|
105
|
+
const describeFunction = commonJsJest ? 'jestGlobals.describe' : 'describe'
|
|
102
106
|
const body = scenarioId === 'atr-fail-once'
|
|
103
107
|
? getAtrBody({ moduleSystem, assertion, stateFile })
|
|
104
108
|
: ` ${assertion}`
|
|
@@ -106,7 +110,7 @@ function getGeneratedTestContent ({ framework, moduleSystem, scenarioId, stateFi
|
|
|
106
110
|
return [
|
|
107
111
|
...imports,
|
|
108
112
|
imports.length > 0 ? '' : undefined,
|
|
109
|
-
|
|
113
|
+
`${describeFunction}('dd-test-optimization-validation', () => {`,
|
|
110
114
|
` ${testFunction}('${scenario.testName}', () => {`,
|
|
111
115
|
body,
|
|
112
116
|
' })',
|
|
@@ -192,9 +196,7 @@ function getGeneratedTestContractError (framework) {
|
|
|
192
196
|
if (!cleanupPaths.has(path.normalize(stepsFile))) {
|
|
193
197
|
return 'must include the isolated Cucumber step definitions in cleanupPaths.'
|
|
194
198
|
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (framework.framework === 'playwright') {
|
|
199
|
+
} else if (framework.framework === 'playwright') {
|
|
198
200
|
const configPath = playwrightAdapter.getGeneratedConfigPath(strategy.testDirectory)
|
|
199
201
|
const config = files.find(file => path.normalize(file.path) === path.normalize(configPath))
|
|
200
202
|
if (config?.contentLines?.join('\n') !== playwrightAdapter.getGeneratedConfigContent()) {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const fs = require('node:fs')
|
|
4
4
|
const path = require('node:path')
|
|
5
5
|
|
|
6
|
+
const { BLOCKER_CATEGORIES, getBlockerDomain } = require('./blocker-category')
|
|
6
7
|
const { getCommandBlocker } = require('./command-blocker')
|
|
7
8
|
const { runCommand, serializeDisplayCommand } = require('./command-runner')
|
|
8
9
|
const {
|
|
@@ -12,6 +13,7 @@ const {
|
|
|
12
13
|
const { getGeneratedCommand } = require('./runner-command')
|
|
13
14
|
const { frameworkOutDir } = require('./scenarios/helpers')
|
|
14
15
|
const { getObservedTestCount } = require('./test-output')
|
|
16
|
+
const { getValidationBlockerEvidence } = require('./validation-blocker')
|
|
15
17
|
|
|
16
18
|
const GENERATED_SCENARIO_BY_FEATURE = {
|
|
17
19
|
efd: 'basic-pass',
|
|
@@ -103,15 +105,16 @@ async function verifyGeneratedTestStrategy ({ framework, out, options }) {
|
|
|
103
105
|
return { ok: true }
|
|
104
106
|
} catch (error) {
|
|
105
107
|
cleanupGeneratedRuntimeFiles(framework)
|
|
108
|
+
const blockerEvidence = getValidationBlockerEvidence(error)
|
|
106
109
|
return {
|
|
107
110
|
ok: false,
|
|
108
111
|
failure: {
|
|
109
112
|
frameworkId: framework.id,
|
|
110
113
|
scenario: 'generated-test-verification',
|
|
111
|
-
status: 'error',
|
|
114
|
+
status: blockerEvidence ? 'blocked' : 'error',
|
|
112
115
|
diagnosis: 'The validator could not run the temporary validation test as expected. No advanced-feature ' +
|
|
113
116
|
`conclusion was reached: ${error.message || error}`,
|
|
114
|
-
evidence,
|
|
117
|
+
evidence: { ...evidence, ...blockerEvidence },
|
|
115
118
|
artifacts,
|
|
116
119
|
},
|
|
117
120
|
}
|
|
@@ -153,14 +156,12 @@ function getVerificationFailure (framework, evidence, artifacts, scenario, resul
|
|
|
153
156
|
const commandFailure = getCommandBlocker(result, {
|
|
154
157
|
browserRequired: framework.browserRequired,
|
|
155
158
|
framework: framework.framework,
|
|
159
|
+
packageJson: framework.project.packageJson,
|
|
156
160
|
testsRan: Number.isInteger(observedTestCount) && observedTestCount > 0,
|
|
157
161
|
})
|
|
158
162
|
if (commandFailure) {
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
: commandFailure.localRuntimeBlocked
|
|
162
|
-
? 'local_runtime'
|
|
163
|
-
: 'project_setup'
|
|
163
|
+
const blockerCategory = commandFailure.blockerCategory
|
|
164
|
+
const domain = getBlockerDomain(blockerCategory)
|
|
164
165
|
return {
|
|
165
166
|
ok: false,
|
|
166
167
|
failure: {
|
|
@@ -168,7 +169,7 @@ function getVerificationFailure (framework, evidence, artifacts, scenario, resul
|
|
|
168
169
|
scenario: 'generated-test-verification',
|
|
169
170
|
status: 'blocked',
|
|
170
171
|
diagnosis: `${commandFailure.summary} Advanced-feature validation could not start reliably.`,
|
|
171
|
-
evidence: { ...evidence, commandFailure, domain, validationIncomplete: true },
|
|
172
|
+
evidence: { ...evidence, blockerCategory, commandFailure, domain, validationIncomplete: true },
|
|
172
173
|
artifacts,
|
|
173
174
|
},
|
|
174
175
|
}
|
|
@@ -189,7 +190,11 @@ function getVerificationFailure (framework, evidence, artifacts, scenario, resul
|
|
|
189
190
|
scenario: 'generated-test-verification',
|
|
190
191
|
status: 'error',
|
|
191
192
|
diagnosis: `Temporary validation test "${scenario.id}" ${reason}. No advanced-feature conclusion was reached.`,
|
|
192
|
-
evidence
|
|
193
|
+
evidence: {
|
|
194
|
+
...evidence,
|
|
195
|
+
blockerCategory: BLOCKER_CATEGORIES.VALIDATOR_LIMITATION,
|
|
196
|
+
validationIncomplete: true,
|
|
197
|
+
},
|
|
193
198
|
artifacts,
|
|
194
199
|
},
|
|
195
200
|
}
|
|
@@ -204,14 +209,16 @@ function getVerificationFailure (framework, evidence, artifacts, scenario, resul
|
|
|
204
209
|
function getGeneratedRuntimeFileStatus (strategy) {
|
|
205
210
|
const generatedFiles = new Set((strategy.files || []).map(file => path.resolve(file.path)))
|
|
206
211
|
let expectsRuntimeFile = false
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
212
|
+
if (strategy.cleanupPaths) {
|
|
213
|
+
for (const cleanupPath of strategy.cleanupPaths) {
|
|
214
|
+
const filename = path.resolve(cleanupPath)
|
|
215
|
+
if (generatedFiles.has(filename)) continue
|
|
216
|
+
expectsRuntimeFile = true
|
|
217
|
+
try {
|
|
218
|
+
const stat = fs.lstatSync(filename)
|
|
219
|
+
if (!stat.isSymbolicLink() && stat.isFile()) return true
|
|
220
|
+
} catch {}
|
|
221
|
+
}
|
|
215
222
|
}
|
|
216
223
|
return expectsRuntimeFile ? false : undefined
|
|
217
224
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// Dynamic extglobs, negation, character classes, and malformed braces fail closed.
|
|
4
|
+
function matchesLiteralGlob (filename, pattern) {
|
|
5
|
+
const source = String(pattern || '').replaceAll('\\', '/').replace(/^\.\//, '')
|
|
6
|
+
if (!source || /[!()[\]]/.test(source)) return false
|
|
7
|
+
|
|
8
|
+
let expression = '^'
|
|
9
|
+
for (let index = 0; index < source.length; index++) {
|
|
10
|
+
const character = source[index]
|
|
11
|
+
if (character === '*') {
|
|
12
|
+
if (source[index + 1] === '*') {
|
|
13
|
+
index++
|
|
14
|
+
if (source[index + 1] === '/') {
|
|
15
|
+
index++
|
|
16
|
+
expression += '(?:.*/)?'
|
|
17
|
+
} else {
|
|
18
|
+
expression += '.*'
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
expression += '[^/]*'
|
|
22
|
+
}
|
|
23
|
+
continue
|
|
24
|
+
}
|
|
25
|
+
if (character === '?') {
|
|
26
|
+
expression += '[^/]'
|
|
27
|
+
continue
|
|
28
|
+
}
|
|
29
|
+
if (character === '{') {
|
|
30
|
+
const end = source.indexOf('}', index + 1)
|
|
31
|
+
if (end === -1) return false
|
|
32
|
+
const alternatives = source.slice(index + 1, end).split(',')
|
|
33
|
+
if (alternatives.length < 2 || alternatives.some(value => !/^[A-Za-z0-9._-]+$/.test(value))) return false
|
|
34
|
+
expression += `(?:${alternatives.map(escapeRegExp).join('|')})`
|
|
35
|
+
// eslint-disable-next-line sonarjs/updated-loop-counter
|
|
36
|
+
index = end
|
|
37
|
+
continue
|
|
38
|
+
}
|
|
39
|
+
expression += escapeRegExp(character)
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
return new RegExp(`${expression}$`).test(String(filename).replaceAll('\\', '/').replaceAll(/^\.\//g, ''))
|
|
43
|
+
} catch {
|
|
44
|
+
return false
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function escapeRegExp (value) {
|
|
49
|
+
return value.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = { matchesLiteralGlob }
|
|
@@ -81,6 +81,9 @@ function getManifestPaths (manifest) {
|
|
|
81
81
|
[`${prefix}.ciWiring.configFile`, framework.ciWiring?.configFile],
|
|
82
82
|
[`${prefix}.ciWiring.workingDirectory`, framework.ciWiring?.workingDirectory]
|
|
83
83
|
)
|
|
84
|
+
for (const [index, fallback] of (framework.validation?.fallbackTests || []).entries()) {
|
|
85
|
+
paths.push([`${prefix}.validation.fallbackTests[${index}].testFile`, fallback.testFile])
|
|
86
|
+
}
|
|
84
87
|
for (const [index, configFile] of (framework.project?.configFiles || []).entries()) {
|
|
85
88
|
paths.push([`${prefix}.project.configFiles[${index}]`, configFile])
|
|
86
89
|
}
|