dd-trace 6.9.0 → 6.10.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/vitest-no-worker-init-setup.mjs +112 -10
- package/index.d.ts +42 -0
- package/package.json +4 -3
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +111 -6
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +629 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +81 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +83 -1
- package/packages/datadog-instrumentations/src/jest.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -8
- package/packages/datadog-instrumentations/src/mysql.js +45 -15
- package/packages/datadog-instrumentations/src/mysql2.js +119 -18
- package/packages/datadog-instrumentations/src/path-to-regexp.js +67 -1
- package/packages/datadog-instrumentations/src/pg.js +116 -92
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +43 -4
- package/packages/datadog-instrumentations/src/vitest-main.js +169 -17
- package/packages/datadog-instrumentations/src/vitest-util.js +64 -5
- package/packages/datadog-instrumentations/src/vitest-worker.js +150 -25
- package/packages/datadog-instrumentations/src/webdriverio.js +31 -17
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/trace-checkpoint.js +12 -6
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -5
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -5
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +31 -17
- package/packages/datadog-plugin-jest/src/index.js +5 -4
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -2
- package/packages/datadog-plugin-kafkajs/src/utils.js +65 -7
- package/packages/datadog-plugin-mocha/src/index.js +550 -39
- package/packages/datadog-plugin-mysql/src/index.js +37 -0
- package/packages/datadog-plugin-next/src/index.js +1 -19
- package/packages/datadog-plugin-openai-agents/src/integration.js +278 -69
- package/packages/datadog-plugin-openai-agents/src/processor.js +16 -4
- package/packages/datadog-plugin-pg/src/index.js +1 -0
- package/packages/datadog-plugin-vitest/src/index.js +8 -20
- package/packages/datadog-plugin-ws/src/util.js +2 -1
- package/packages/dd-trace/src/appsec/api_security/normalized-route.js +453 -0
- package/packages/dd-trace/src/appsec/handlers/http-request.js +13 -0
- package/packages/dd-trace/src/carrier.js +356 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +3 -0
- package/packages/dd-trace/src/config/supported-configurations.json +10 -0
- package/packages/dd-trace/src/datastreams/context.js +6 -1
- package/packages/dd-trace/src/datastreams/manager.js +5 -1
- package/packages/dd-trace/src/datastreams/pathway.js +23 -22
- package/packages/dd-trace/src/datastreams/processor.js +3 -2
- package/packages/dd-trace/src/llmobs/constants/tags.js +5 -0
- package/packages/dd-trace/src/llmobs/index.js +34 -2
- package/packages/dd-trace/src/llmobs/span_processor.js +16 -0
- package/packages/dd-trace/src/llmobs/tagger.js +96 -0
- package/packages/dd-trace/src/llmobs/util.js +78 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +126 -120
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +4 -8
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/{datadog-plugin-jest/src/util.js → dd-trace/src/plugins/util/jest.js} +1 -62
- package/packages/dd-trace/src/plugins/util/test.js +84 -5
- package/packages/dd-trace/src/plugins/util/web.js +53 -2
|
@@ -4,6 +4,8 @@ const path = require('node:path')
|
|
|
4
4
|
const { fileURLToPath } = require('node:url')
|
|
5
5
|
const { MessagePort } = require('node:worker_threads')
|
|
6
6
|
|
|
7
|
+
const satisfies = require('../../../vendor/dist/semifies')
|
|
8
|
+
|
|
7
9
|
const shimmer = require('../../datadog-shimmer')
|
|
8
10
|
const log = require('../../dd-trace/src/log')
|
|
9
11
|
const { EMPTY_EFD_RETRY_POLICY } = require('../../dd-trace/src/ci-visibility/efd-retry-policy')
|
|
@@ -12,16 +14,19 @@ const {
|
|
|
12
14
|
VITEST_WORKER_COVERAGE_PAYLOAD_CODE,
|
|
13
15
|
VITEST_WORKER_LOGS_PAYLOAD_CODE,
|
|
14
16
|
VITEST_WORKER_TELEMETRY_PAYLOAD_CODE,
|
|
17
|
+
VITEST_WORKER_EFD_SUITE_ADMISSION_REQUEST_CODE,
|
|
18
|
+
VITEST_WORKER_EFD_SUITE_ADMISSION_RESPONSE_CODE,
|
|
15
19
|
collectTestOptimizationSummariesFromTraces,
|
|
20
|
+
getIsFaultyEarlyFlakeDetection,
|
|
16
21
|
logTestOptimizationSummary,
|
|
17
22
|
TEST_IMPACT_ANALYSIS_ALL_TESTS_SKIPPED_MESSAGE,
|
|
18
23
|
getTestOptimizationRequestResults,
|
|
19
24
|
getTestSuitePath,
|
|
20
25
|
isModifiedTest,
|
|
26
|
+
isMarkedAsUnskippable,
|
|
21
27
|
recordTestManagementExecution,
|
|
22
28
|
recordAttemptToFixExecution,
|
|
23
29
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
24
|
-
const { isMarkedAsUnskippable } = require('../../datadog-plugin-jest/src/util')
|
|
25
30
|
const { getChannelPromise } = require('./helpers/channel')
|
|
26
31
|
const { addHook, channel } = require('./helpers/instrument')
|
|
27
32
|
const noWorkerInit = require('./vitest-main-no-worker-init')
|
|
@@ -38,7 +43,6 @@ const {
|
|
|
38
43
|
testSessionConfigurationCh,
|
|
39
44
|
libraryConfigurationCh,
|
|
40
45
|
knownTestsCh,
|
|
41
|
-
isEarlyFlakeDetectionFaultyCh,
|
|
42
46
|
testManagementTestsCh,
|
|
43
47
|
modifiedFilesCh,
|
|
44
48
|
workerReportTraceCh,
|
|
@@ -50,6 +54,7 @@ const {
|
|
|
50
54
|
findExportByName,
|
|
51
55
|
getTypeTasks,
|
|
52
56
|
getWorkspaceProject,
|
|
57
|
+
parseProvidedContextValue,
|
|
53
58
|
setProvidedContext,
|
|
54
59
|
getVitestTestProperties,
|
|
55
60
|
} = require('./vitest-util')
|
|
@@ -66,6 +71,7 @@ let isFlakyTestRetriesEnabled = false
|
|
|
66
71
|
let flakyTestRetriesCount = 0
|
|
67
72
|
let isEarlyFlakeDetectionEnabled = false
|
|
68
73
|
let earlyFlakeDetectionRetryPolicy = EMPTY_EFD_RETRY_POLICY
|
|
74
|
+
let earlyFlakeDetectionFaultyThreshold = 0
|
|
69
75
|
let isEarlyFlakeDetectionFaulty = false
|
|
70
76
|
let isKnownTestsEnabled = false
|
|
71
77
|
let isTestManagementTestsEnabled = false
|
|
@@ -97,6 +103,10 @@ let hasRunnableSuites = false
|
|
|
97
103
|
let hasSelectedSuites = false
|
|
98
104
|
let itrCorrelationId
|
|
99
105
|
let tiaRepositoryRoot = process.cwd()
|
|
106
|
+
let activeNoWorkerInitState
|
|
107
|
+
let isEfdSuiteAdmissionEnabled = false
|
|
108
|
+
let maximumSuitesWithNewTests = 0
|
|
109
|
+
const suitesWithNewTests = new Set()
|
|
100
110
|
const tinyPoolClassWrappers = new WeakMap()
|
|
101
111
|
const itrSkippedSuitesCh = channel('ci:vitest:itr:skipped-suites')
|
|
102
112
|
const skippableSuitesCh = channel('ci:vitest:test-suite:skippable')
|
|
@@ -223,6 +233,100 @@ function getNormalizedTestSuitePath (testFilepath, repositoryRoot) {
|
|
|
223
233
|
return getTestSuitePath(realpath(testSuiteAbsolutePath), realpath(repositoryRoot))
|
|
224
234
|
}
|
|
225
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Resets suite-level EFD admission state between Vitest runs.
|
|
238
|
+
*
|
|
239
|
+
* @returns {void}
|
|
240
|
+
*/
|
|
241
|
+
function resetEfdSuiteTracker () {
|
|
242
|
+
activeNoWorkerInitState = undefined
|
|
243
|
+
isEfdSuiteAdmissionEnabled = false
|
|
244
|
+
maximumSuitesWithNewTests = 0
|
|
245
|
+
suitesWithNewTests.clear()
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Returns whether a Vitest pool has a transport for runtime EFD suite admission.
|
|
250
|
+
*
|
|
251
|
+
* @param {string|undefined} pool
|
|
252
|
+
* @returns {boolean}
|
|
253
|
+
*/
|
|
254
|
+
function isEfdSuiteAdmissionPool (pool) {
|
|
255
|
+
return pool === undefined || pool === 'forks' || pool === 'threads' || pool === 'browser'
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Returns whether Vitest exposes the worker transports used for runtime EFD suite admission.
|
|
260
|
+
*
|
|
261
|
+
* @param {string} frameworkVersion
|
|
262
|
+
* @param {object[]|undefined} testSpecifications
|
|
263
|
+
* @param {object} ctx
|
|
264
|
+
* @returns {boolean}
|
|
265
|
+
*/
|
|
266
|
+
function supportsEfdSuiteAdmission (frameworkVersion, testSpecifications, ctx) {
|
|
267
|
+
if (!satisfies(frameworkVersion, '>=4.0.0')) return false
|
|
268
|
+
const defaultPool = ctx?.config?.pool
|
|
269
|
+
if (!Array.isArray(testSpecifications) || testSpecifications.length === 0) {
|
|
270
|
+
return isEfdSuiteAdmissionPool(defaultPool)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
for (const testSpecification of testSpecifications) {
|
|
274
|
+
const pool = getTestSpecificationPool(testSpecification) || defaultPool
|
|
275
|
+
if (!isEfdSuiteAdmissionPool(pool)) return false
|
|
276
|
+
}
|
|
277
|
+
return true
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Configures the EFD threshold against the unique suites selected by Vitest.
|
|
282
|
+
*
|
|
283
|
+
* @param {string[]} testFilepaths
|
|
284
|
+
* @param {string} repositoryRoot
|
|
285
|
+
* @returns {void}
|
|
286
|
+
*/
|
|
287
|
+
function configureEfdSuiteTracker (testFilepaths, repositoryRoot) {
|
|
288
|
+
const testSuites = new Set()
|
|
289
|
+
for (const testFilepath of testFilepaths) {
|
|
290
|
+
testSuites.add(getNormalizedTestSuitePath(testFilepath, repositoryRoot))
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
maximumSuitesWithNewTests = Math.floor(Math.max(
|
|
294
|
+
earlyFlakeDetectionFaultyThreshold,
|
|
295
|
+
testSuites.size * earlyFlakeDetectionFaultyThreshold / 100
|
|
296
|
+
))
|
|
297
|
+
isEfdSuiteAdmissionEnabled = true
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Returns whether a suite may schedule EFD retries and records runnable suites with new tests.
|
|
302
|
+
*
|
|
303
|
+
* @param {string} testSuite
|
|
304
|
+
* @param {boolean} hasNewTest
|
|
305
|
+
* @returns {boolean}
|
|
306
|
+
*/
|
|
307
|
+
function reserveEarlyFlakeDetectionSuite (testSuite, hasNewTest) {
|
|
308
|
+
if (!isEfdSuiteAdmissionEnabled || typeof testSuite !== 'string') return false
|
|
309
|
+
if (isEarlyFlakeDetectionFaulty) return false
|
|
310
|
+
|
|
311
|
+
if (hasNewTest) {
|
|
312
|
+
suitesWithNewTests.add(testSuite)
|
|
313
|
+
if (suitesWithNewTests.size > maximumSuitesWithNewTests) {
|
|
314
|
+
isEarlyFlakeDetectionEnabled = false
|
|
315
|
+
isEarlyFlakeDetectionFaulty = true
|
|
316
|
+
if (activeNoWorkerInitState) {
|
|
317
|
+
activeNoWorkerInitState.isEarlyFlakeDetectionEnabled = false
|
|
318
|
+
activeNoWorkerInitState.isEarlyFlakeDetectionFaulty = true
|
|
319
|
+
}
|
|
320
|
+
log.warn(
|
|
321
|
+
'Early Flake Detection retries are disabled because the number of suites with new tests is too high.'
|
|
322
|
+
)
|
|
323
|
+
return false
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return true
|
|
328
|
+
}
|
|
329
|
+
|
|
226
330
|
function resetSuiteSkippingRunState () {
|
|
227
331
|
skippableSuites = []
|
|
228
332
|
resetAppliedSuiteSkippingState()
|
|
@@ -543,6 +647,7 @@ function resetLibraryConfig () {
|
|
|
543
647
|
flakyTestRetriesCount = 0
|
|
544
648
|
isEarlyFlakeDetectionEnabled = false
|
|
545
649
|
earlyFlakeDetectionRetryPolicy = EMPTY_EFD_RETRY_POLICY
|
|
650
|
+
earlyFlakeDetectionFaultyThreshold = 0
|
|
546
651
|
isEarlyFlakeDetectionFaulty = false
|
|
547
652
|
isDiEnabled = false
|
|
548
653
|
isKnownTestsEnabled = false
|
|
@@ -558,6 +663,7 @@ function applyLibraryConfig (libraryConfig) {
|
|
|
558
663
|
flakyTestRetriesCount = libraryConfig.flakyTestRetriesCount
|
|
559
664
|
isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
|
|
560
665
|
earlyFlakeDetectionRetryPolicy = libraryConfig.earlyFlakeDetectionRetryPolicy ?? EMPTY_EFD_RETRY_POLICY
|
|
666
|
+
earlyFlakeDetectionFaultyThreshold = libraryConfig.earlyFlakeDetectionFaultyThreshold ?? 0
|
|
561
667
|
isEarlyFlakeDetectionFaulty = false
|
|
562
668
|
isDiEnabled = libraryConfig.isDiEnabled
|
|
563
669
|
isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
|
|
@@ -573,6 +679,7 @@ function resetMainProcessProvidedContext (ctx) {
|
|
|
573
679
|
_ddIsDiEnabled: false,
|
|
574
680
|
_ddIsEarlyFlakeDetectionEnabled: false,
|
|
575
681
|
_ddEarlyFlakeDetectionRetryPolicy: EMPTY_EFD_RETRY_POLICY,
|
|
682
|
+
_ddIsEfdSuiteAdmissionEnabled: false,
|
|
576
683
|
_ddIsFlakyTestRetriesEnabled: false,
|
|
577
684
|
_ddFlakyTestRetriesCount: 0,
|
|
578
685
|
_ddFlakyTestRetriesIncludesUnnamedProject: false,
|
|
@@ -616,6 +723,7 @@ async function runMainProcessSetup (
|
|
|
616
723
|
}
|
|
617
724
|
|
|
618
725
|
resetSuiteSkippingRunState()
|
|
726
|
+
resetEfdSuiteTracker()
|
|
619
727
|
isVitestBrowserModeActive ||= shouldInstallBrowserReporter
|
|
620
728
|
isTestImpactAnalysisDisabled =
|
|
621
729
|
disableTestImpactAnalysis || shouldInstallNoWorkerInit || isVitestBrowserModeActive
|
|
@@ -732,21 +840,27 @@ async function runMainProcessSetup (
|
|
|
732
840
|
const currentTestFilepaths = await getCurrentTestFilepaths()
|
|
733
841
|
|
|
734
842
|
if (isValidKnownTests(knownTests)) {
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
testFilepaths: currentTestFilepaths,
|
|
738
|
-
onDone: (isFaulty) => {
|
|
739
|
-
isEarlyFlakeDetectionFaulty = isFaulty
|
|
740
|
-
},
|
|
741
|
-
})
|
|
742
|
-
if (isEarlyFlakeDetectionFaulty) {
|
|
743
|
-
isEarlyFlakeDetectionEnabled = false
|
|
744
|
-
log.warn('New test detection is disabled because the number of new tests is too high.')
|
|
843
|
+
if (!shouldInstallNoWorkerInit && supportsEfdSuiteAdmission(frameworkVersion, testSpecifications, ctx)) {
|
|
844
|
+
configureEfdSuiteTracker(currentTestFilepaths, repositoryRoot)
|
|
745
845
|
} else {
|
|
846
|
+
const projectSuites = currentTestFilepaths.map(testFilepath => getTestSuitePath(testFilepath, repositoryRoot))
|
|
847
|
+
isEarlyFlakeDetectionFaulty = getIsFaultyEarlyFlakeDetection(
|
|
848
|
+
projectSuites,
|
|
849
|
+
knownTests.vitest,
|
|
850
|
+
earlyFlakeDetectionFaultyThreshold
|
|
851
|
+
)
|
|
852
|
+
if (isEarlyFlakeDetectionFaulty) {
|
|
853
|
+
isEarlyFlakeDetectionEnabled = false
|
|
854
|
+
log.warn('New test detection is disabled because the number of new tests is too high.')
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
if (!isEarlyFlakeDetectionFaulty) {
|
|
746
859
|
knownTestsBySuite = knownTests.vitest
|
|
747
860
|
shouldSendTestProperties = true
|
|
748
861
|
if (!shouldInstallNoWorkerInit) {
|
|
749
862
|
setProvidedContext(ctx, {
|
|
863
|
+
_ddIsEfdSuiteAdmissionEnabled: isEfdSuiteAdmissionEnabled,
|
|
750
864
|
_ddIsKnownTestsEnabled: isKnownTestsEnabled,
|
|
751
865
|
_ddIsEarlyFlakeDetectionEnabled: isEarlyFlakeDetectionEnabled,
|
|
752
866
|
_ddEarlyFlakeDetectionRetryPolicy: earlyFlakeDetectionRetryPolicy,
|
|
@@ -821,6 +935,7 @@ async function runMainProcessSetup (
|
|
|
821
935
|
const reporterTestSpecifications = shouldInstallNoWorkerInit
|
|
822
936
|
? testSpecifications
|
|
823
937
|
: getBrowserTestSpecifications(testSpecifications)
|
|
938
|
+
activeNoWorkerInitState = getNoWorkerInitState()
|
|
824
939
|
noWorkerInit.configure(ctx, frameworkVersion, reporterTestSpecifications, {
|
|
825
940
|
knownTests,
|
|
826
941
|
knownTestsBySuite,
|
|
@@ -832,8 +947,9 @@ async function runMainProcessSetup (
|
|
|
832
947
|
testPropertiesByFilepath: testPropertiesByFilepath || {},
|
|
833
948
|
testSessionConfiguration,
|
|
834
949
|
}, {
|
|
950
|
+
reserveEarlyFlakeDetectionSuite,
|
|
835
951
|
shouldReportTestModule: shouldInstallBrowserReporter ? isBrowserTestModule : undefined,
|
|
836
|
-
state:
|
|
952
|
+
state: activeNoWorkerInitState,
|
|
837
953
|
})
|
|
838
954
|
}
|
|
839
955
|
|
|
@@ -846,6 +962,7 @@ function getNoWorkerInitState () {
|
|
|
846
962
|
return {
|
|
847
963
|
attemptToFixExecutions,
|
|
848
964
|
earlyFlakeDetectionRetryPolicy,
|
|
965
|
+
isEfdSuiteAdmissionEnabled,
|
|
849
966
|
isEarlyFlakeDetectionEnabled,
|
|
850
967
|
isEarlyFlakeDetectionFaulty,
|
|
851
968
|
isFlakyTestRetriesEnabled,
|
|
@@ -1172,8 +1289,9 @@ function getTestSpecificationOptions (testSpecification) {
|
|
|
1172
1289
|
function getTestSpecificationPool (testSpecification) {
|
|
1173
1290
|
const options = getTestSpecificationOptions(testSpecification)
|
|
1174
1291
|
const project = getTestSpecificationProject(testSpecification)
|
|
1175
|
-
|
|
1176
|
-
|
|
1292
|
+
const filePool = Array.isArray(testSpecification) ? testSpecification[1]?.pool : undefined
|
|
1293
|
+
return options?.pool || filePool || project?.config?.pool || project?.serializedConfig?.pool ||
|
|
1294
|
+
project?.pool || testSpecification?.pool
|
|
1177
1295
|
}
|
|
1178
1296
|
|
|
1179
1297
|
/**
|
|
@@ -1328,7 +1446,7 @@ function getMainProcessProvidedContext (ctx) {
|
|
|
1328
1446
|
const providedContext = workspaceProject.getProvidedContext?.() || workspaceProject._provided || {}
|
|
1329
1447
|
|
|
1330
1448
|
return {
|
|
1331
|
-
testPropertiesByFilepath: providedContext._ddTestPropertiesByFilepath || {},
|
|
1449
|
+
testPropertiesByFilepath: parseProvidedContextValue(providedContext._ddTestPropertiesByFilepath) || {},
|
|
1332
1450
|
}
|
|
1333
1451
|
} catch {
|
|
1334
1452
|
return {
|
|
@@ -1750,7 +1868,10 @@ function getWrappedOn (on) {
|
|
|
1750
1868
|
arguments[1] = shimmer.wrapFunction(callback, callback => function (message) {
|
|
1751
1869
|
if (message.type !== 'Buffer' && Array.isArray(message)) {
|
|
1752
1870
|
const [interprocessCode, data] = message
|
|
1753
|
-
if (
|
|
1871
|
+
if (
|
|
1872
|
+
handleEfdAdmissionMessage(this, interprocessCode, data) ||
|
|
1873
|
+
handleWorkerReport(interprocessCode, data)
|
|
1874
|
+
) {
|
|
1754
1875
|
// If we execute the callback vitest crashes, as the message is not supported
|
|
1755
1876
|
return
|
|
1756
1877
|
}
|
|
@@ -1761,6 +1882,37 @@ function getWrappedOn (on) {
|
|
|
1761
1882
|
}
|
|
1762
1883
|
}
|
|
1763
1884
|
|
|
1885
|
+
/**
|
|
1886
|
+
* Handles an EFD suite admission request sent through a Vitest worker transport.
|
|
1887
|
+
*
|
|
1888
|
+
* @param {object} workerProcess
|
|
1889
|
+
* @param {number} interprocessCode
|
|
1890
|
+
* @param {object} data
|
|
1891
|
+
* @returns {boolean}
|
|
1892
|
+
*/
|
|
1893
|
+
function handleEfdAdmissionMessage (workerProcess, interprocessCode, data) {
|
|
1894
|
+
if (interprocessCode !== VITEST_WORKER_EFD_SUITE_ADMISSION_REQUEST_CODE) return false
|
|
1895
|
+
|
|
1896
|
+
const response = [VITEST_WORKER_EFD_SUITE_ADMISSION_RESPONSE_CODE, {
|
|
1897
|
+
allowed: reserveEarlyFlakeDetectionSuite(data?.testSuite, data?.hasNewTest === true),
|
|
1898
|
+
requestId: data?.requestId,
|
|
1899
|
+
}]
|
|
1900
|
+
try {
|
|
1901
|
+
if (typeof workerProcess.send === 'function') {
|
|
1902
|
+
workerProcess.send(response, (error) => {
|
|
1903
|
+
if (error) {
|
|
1904
|
+
log.error('Could not send Vitest EFD suite admission response: %s', error.message)
|
|
1905
|
+
}
|
|
1906
|
+
})
|
|
1907
|
+
} else {
|
|
1908
|
+
workerProcess.postMessage(response)
|
|
1909
|
+
}
|
|
1910
|
+
} catch (error) {
|
|
1911
|
+
log.error('Could not send Vitest EFD suite admission response: %s', error?.message)
|
|
1912
|
+
}
|
|
1913
|
+
return true
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1764
1916
|
function handleWorkerReport (interprocessCode, data) {
|
|
1765
1917
|
if (interprocessCode === VITEST_WORKER_TRACE_PAYLOAD_CODE) {
|
|
1766
1918
|
collectTestOptimizationSummariesFromTraces(data, {
|
|
@@ -29,10 +29,12 @@ const testSessionFinishCh = channel('ci:vitest:session:finish')
|
|
|
29
29
|
const testSessionConfigurationCh = channel('ci:vitest:session:configuration')
|
|
30
30
|
const libraryConfigurationCh = channel('ci:vitest:library-configuration')
|
|
31
31
|
const knownTestsCh = channel('ci:vitest:known-tests')
|
|
32
|
-
const isEarlyFlakeDetectionFaultyCh = channel('ci:vitest:is-early-flake-detection-faulty')
|
|
33
32
|
const testManagementTestsCh = channel('ci:vitest:test-management-tests')
|
|
34
33
|
const modifiedFilesCh = channel('ci:vitest:modified-files')
|
|
35
34
|
|
|
35
|
+
const CLOSING_SCRIPT_TAG_RE = /<\/script/i
|
|
36
|
+
const SERIALIZED_CONTEXT_PREFIX = '\u0000dd-vitest-context:'
|
|
37
|
+
|
|
36
38
|
const workerReportTraceCh = channel('ci:vitest:worker-report:trace')
|
|
37
39
|
const workerReportCoverageCh = channel('ci:vitest:worker-report:coverage')
|
|
38
40
|
const workerReportLogsCh = channel('ci:vitest:worker-report:logs')
|
|
@@ -105,18 +107,72 @@ function getWorkspaceProject (ctx) {
|
|
|
105
107
|
|
|
106
108
|
function setProvidedContext (ctx, values, warningMessage) {
|
|
107
109
|
try {
|
|
108
|
-
|
|
110
|
+
const providedContext = getWorkspaceProject(ctx)._provided
|
|
111
|
+
for (const key of Object.keys(values)) {
|
|
112
|
+
providedContext[key] = key.startsWith('_dd')
|
|
113
|
+
? makeProvidedContextBrowserSafe(values[key])
|
|
114
|
+
: values[key]
|
|
115
|
+
}
|
|
109
116
|
} catch {
|
|
110
117
|
log.warn(warningMessage)
|
|
111
118
|
}
|
|
112
119
|
}
|
|
113
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Prevent Vitest Browser Mode from terminating its inline bootstrap script with Datadog metadata.
|
|
123
|
+
*
|
|
124
|
+
* @param {unknown} value
|
|
125
|
+
* @returns {unknown}
|
|
126
|
+
*/
|
|
127
|
+
function makeProvidedContextBrowserSafe (value) {
|
|
128
|
+
if (typeof value !== 'string' && (typeof value !== 'object' || value === null)) return value
|
|
129
|
+
if (typeof value === 'string' && !CLOSING_SCRIPT_TAG_RE.test(value)) return value
|
|
130
|
+
|
|
131
|
+
const serializedValue = JSON.stringify(value)
|
|
132
|
+
return CLOSING_SCRIPT_TAG_RE.test(serializedValue)
|
|
133
|
+
? SERIALIZED_CONTEXT_PREFIX + serializedValue.replaceAll('<', String.raw`\u003c`)
|
|
134
|
+
: value
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Restore context serialized by makeProvidedContextBrowserSafe.
|
|
139
|
+
*
|
|
140
|
+
* @param {unknown} value
|
|
141
|
+
* @returns {unknown}
|
|
142
|
+
*/
|
|
143
|
+
function parseProvidedContextValue (value) {
|
|
144
|
+
if (typeof value !== 'string' || !value.startsWith(SERIALIZED_CONTEXT_PREFIX)) return value
|
|
145
|
+
|
|
146
|
+
let parsedValue
|
|
147
|
+
try {
|
|
148
|
+
parsedValue = JSON.parse(value.slice(SERIALIZED_CONTEXT_PREFIX.length))
|
|
149
|
+
} catch {}
|
|
150
|
+
return parsedValue
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Restores Datadog context values serialized for Vitest Browser Mode.
|
|
155
|
+
*
|
|
156
|
+
* @param {Record<string, unknown>} values
|
|
157
|
+
* @returns {Record<string, unknown>}
|
|
158
|
+
*/
|
|
159
|
+
function parseProvidedContextValues (values) {
|
|
160
|
+
const parsedValues = {}
|
|
161
|
+
for (const key of Object.keys(values)) {
|
|
162
|
+
if (key.startsWith('_dd')) {
|
|
163
|
+
parsedValues[key] = parseProvidedContextValue(values[key])
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return parsedValues
|
|
167
|
+
}
|
|
168
|
+
|
|
114
169
|
function getProvidedContext () {
|
|
115
170
|
try {
|
|
116
171
|
const {
|
|
117
172
|
_ddIsEarlyFlakeDetectionEnabled,
|
|
173
|
+
_ddIsEfdSuiteAdmissionEnabled: isEfdSuiteAdmissionEnabled,
|
|
118
174
|
_ddIsDiEnabled,
|
|
119
|
-
_ddTestPropertiesByFilepath
|
|
175
|
+
_ddTestPropertiesByFilepath,
|
|
120
176
|
_ddEarlyFlakeDetectionRetryPolicy: earlyFlakeDetectionRetryPolicy,
|
|
121
177
|
_ddIsKnownTestsEnabled: isKnownTestsEnabled,
|
|
122
178
|
_ddIsTestManagementTestsEnabled: isTestManagementTestsEnabled,
|
|
@@ -135,11 +191,13 @@ function getProvidedContext () {
|
|
|
135
191
|
_ddItrCorrelationId: itrCorrelationId,
|
|
136
192
|
_ddUnskippableSuites: unskippableSuites,
|
|
137
193
|
_ddForcedToRunSuites: forcedToRunSuites,
|
|
138
|
-
} = globalThis.__vitest_worker__.providedContext
|
|
194
|
+
} = parseProvidedContextValues(globalThis.__vitest_worker__.providedContext)
|
|
139
195
|
const retryPolicy = earlyFlakeDetectionRetryPolicy ?? EMPTY_EFD_RETRY_POLICY
|
|
196
|
+
const testPropertiesByFilepath = _ddTestPropertiesByFilepath || {}
|
|
140
197
|
|
|
141
198
|
return {
|
|
142
199
|
isDiEnabled: _ddIsDiEnabled,
|
|
200
|
+
isEfdSuiteAdmissionEnabled,
|
|
143
201
|
isEarlyFlakeDetectionEnabled: _ddIsEarlyFlakeDetectionEnabled && hasEfdRetries(retryPolicy),
|
|
144
202
|
testPropertiesByFilepath,
|
|
145
203
|
earlyFlakeDetectionRetryPolicy: retryPolicy,
|
|
@@ -165,6 +223,7 @@ function getProvidedContext () {
|
|
|
165
223
|
log.error('Vitest workers could not parse provided context, so some features will not work.')
|
|
166
224
|
return {
|
|
167
225
|
isDiEnabled: false,
|
|
226
|
+
isEfdSuiteAdmissionEnabled: false,
|
|
168
227
|
isEarlyFlakeDetectionEnabled: false,
|
|
169
228
|
testPropertiesByFilepath: {},
|
|
170
229
|
earlyFlakeDetectionRetryPolicy: EMPTY_EFD_RETRY_POLICY,
|
|
@@ -258,7 +317,6 @@ module.exports = {
|
|
|
258
317
|
testSessionConfigurationCh,
|
|
259
318
|
libraryConfigurationCh,
|
|
260
319
|
knownTestsCh,
|
|
261
|
-
isEarlyFlakeDetectionFaultyCh,
|
|
262
320
|
testManagementTestsCh,
|
|
263
321
|
modifiedFilesCh,
|
|
264
322
|
workerReportTraceCh,
|
|
@@ -273,6 +331,7 @@ module.exports = {
|
|
|
273
331
|
getTestName,
|
|
274
332
|
getWorkspaceProject,
|
|
275
333
|
setProvidedContext,
|
|
334
|
+
parseProvidedContextValue,
|
|
276
335
|
getProvidedContext,
|
|
277
336
|
isFlakyTestRetriesEnabledForTask,
|
|
278
337
|
getVitestTestProperties,
|