dd-trace 6.0.0-pre-c26eac4 → 6.0.0-pre-efcd0a3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "6.0.0-pre-c26eac4",
3
+ "version": "6.0.0-pre-efcd0a3",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -69,7 +69,7 @@
69
69
  "node": ">=18"
70
70
  },
71
71
  "dependencies": {
72
- "@datadog/native-appsec": "7.1.0",
72
+ "@datadog/native-appsec": "7.1.1",
73
73
  "@datadog/native-iast-rewriter": "2.3.0",
74
74
  "@datadog/native-iast-taint-tracking": "1.7.0",
75
75
  "@datadog/native-metrics": "^2.0.0",
@@ -76,6 +76,7 @@ const specStatusToTestStatus = {
76
76
  const asyncResources = new WeakMap()
77
77
  const originalTestFns = new WeakMap()
78
78
  const retriedTestsToNumAttempts = new Map()
79
+ const newTestsTestStatuses = new Map()
79
80
 
80
81
  // based on https://github.com/facebook/jest/blob/main/packages/jest-circus/src/formatNodeAssertErrors.ts#L41
81
82
  function formatJestError (errors) {
@@ -104,6 +105,13 @@ function getTestEnvironmentOptions (config) {
104
105
  return {}
105
106
  }
106
107
 
108
+ function getEfdStats (testStatuses) {
109
+ return testStatuses.reduce((acc, testStatus) => {
110
+ acc[testStatus]++
111
+ return acc
112
+ }, { pass: 0, fail: 0 })
113
+ }
114
+
107
115
  function getWrappedEnvironment (BaseEnvironment, jestVersion) {
108
116
  return class DatadogEnvironment extends BaseEnvironment {
109
117
  constructor (config, context) {
@@ -248,6 +256,19 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
248
256
  })
249
257
  // restore in case it is retried
250
258
  event.test.fn = originalTestFns.get(event.test)
259
+ // We'll store the test statuses of the retries
260
+ if (this.isEarlyFlakeDetectionEnabled) {
261
+ const testName = getJestTestName(event.test)
262
+ const originalTestName = removeEfdStringFromTestName(testName)
263
+ const isNewTest = retriedTestsToNumAttempts.has(originalTestName)
264
+ if (isNewTest) {
265
+ if (newTestsTestStatuses.has(originalTestName)) {
266
+ newTestsTestStatuses.get(originalTestName).push(status)
267
+ } else {
268
+ newTestsTestStatuses.set(originalTestName, [status])
269
+ }
270
+ }
271
+ }
251
272
  })
252
273
  }
253
274
  if (event.name === 'test_skip' || event.name === 'test_todo') {
@@ -514,6 +535,28 @@ function cliWrapper (cli, jestVersion) {
514
535
 
515
536
  numSkippedSuites = 0
516
537
 
538
+ /**
539
+ * If Early Flake Detection (EFD) is enabled the logic is as follows:
540
+ * - If all attempts for a test are failing, the test has failed and we will let the test process fail.
541
+ * - If just a single attempt passes, we will prevent the test process from failing.
542
+ * The rationale behind is the following: you may still be able to block your CI pipeline by gating
543
+ * on flakiness (the test will be considered flaky), but you may choose to unblock the pipeline too.
544
+ */
545
+
546
+ if (isEarlyFlakeDetectionEnabled) {
547
+ let numFailedTestsToIgnore = 0
548
+ for (const testStatuses of newTestsTestStatuses.values()) {
549
+ const { pass, fail } = getEfdStats(testStatuses)
550
+ if (pass > 0) { // as long as one passes, we'll consider the test passed
551
+ numFailedTestsToIgnore += fail
552
+ }
553
+ }
554
+ // If every test that failed was an EFD retry, we'll consider the suite passed
555
+ if (numFailedTestsToIgnore !== 0 && result.results.numFailedTests === numFailedTestsToIgnore) {
556
+ result.results.success = true
557
+ }
558
+ }
559
+
517
560
  return result
518
561
  })
519
562
 
@@ -27,6 +27,7 @@ const qsRegex = '(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private
27
27
  const defaultWafObfuscatorKeyRegex = '(?i)(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?)key)|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)|bearer|authorization'
28
28
  // eslint-disable-next-line max-len
29
29
  const defaultWafObfuscatorValueRegex = '(?i)(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:\\s*=[^;]|"\\s*:\\s*"[^"]+")|bearer\\s+[a-z0-9\\._\\-]+|token:[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L][\\w=-]+\\.ey[I-L][\\w=-]+(?:\\.[\\w.+\\/=-]+)?|[\\-]{5}BEGIN[a-z\\s]+PRIVATE\\sKEY[\\-]{5}[^\\-]+[\\-]{5}END[a-z\\s]+PRIVATE\\sKEY|ssh-rsa\\s*[a-z0-9\\/\\.+]{100,}'
30
+ const runtimeId = uuid()
30
31
 
31
32
  function maybeFile (filepath) {
32
33
  if (!filepath) return
@@ -291,7 +292,7 @@ class Config {
291
292
  service: this.service,
292
293
  env: this.env,
293
294
  version: this.version,
294
- 'runtime-id': uuid()
295
+ 'runtime-id': runtimeId
295
296
  })
296
297
 
297
298
  if (this.isCiVisibility) {
@@ -823,6 +824,7 @@ class Config {
823
824
  : undefined
824
825
 
825
826
  tagger.add(tags, options.tracing_tags)
827
+ if (Object.keys(tags).length) tags['runtime-id'] = runtimeId
826
828
 
827
829
  this._setUnit(opts, 'sampleRate', options.tracing_sampling_rate)
828
830
  this._setBoolean(opts, 'logInjection', options.log_injection_enabled)