Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ abstract class CiVisibilityInstrumentationTest extends InstrumentationSpecificat
settings.disabledTests,
settings.attemptToFixTests,
settings.diff,
false)
ConfigurationErrors.NONE)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class CiVisibilitySettings {
null,
false);

public static final CiVisibilitySettings REQUEST_ERROR =
public static final CiVisibilitySettings SETTINGS_REQUEST_ERROR =
new CiVisibilitySettings(
false,
false,
Expand Down Expand Up @@ -52,7 +52,7 @@ public class CiVisibilitySettings {
private final EarlyFlakeDetectionSettings earlyFlakeDetectionSettings;
private final TestManagementSettings testManagementSettings;
@Nullable private final String defaultBranch;
private final boolean requestError;
private final boolean settingsRequestError;

CiVisibilitySettings(
boolean itrEnabled,
Expand All @@ -67,7 +67,7 @@ public class CiVisibilitySettings {
EarlyFlakeDetectionSettings earlyFlakeDetectionSettings,
TestManagementSettings testManagementSettings,
@Nullable String defaultBranch,
boolean requestError) {
boolean settingsRequestError) {
this.itrEnabled = itrEnabled;
this.codeCoverage = codeCoverage;
this.testsSkipping = testsSkipping;
Expand All @@ -80,7 +80,7 @@ public class CiVisibilitySettings {
this.earlyFlakeDetectionSettings = earlyFlakeDetectionSettings;
this.testManagementSettings = testManagementSettings;
this.defaultBranch = defaultBranch;
this.requestError = requestError;
this.settingsRequestError = settingsRequestError;
}

public boolean isItrEnabled() {
Expand Down Expand Up @@ -132,8 +132,8 @@ public String getDefaultBranch() {
return defaultBranch;
}

public boolean isRequestError() {
return requestError;
public boolean isSettingsRequestError() {
return settingsRequestError;
}

@Override
Expand All @@ -157,7 +157,7 @@ public boolean equals(Object o) {
&& Objects.equals(earlyFlakeDetectionSettings, that.earlyFlakeDetectionSettings)
&& Objects.equals(testManagementSettings, that.testManagementSettings)
&& Objects.equals(defaultBranch, that.defaultBranch)
&& requestError == that.requestError;
&& settingsRequestError == that.settingsRequestError;
}

@Override
Expand All @@ -175,7 +175,7 @@ public int hashCode() {
earlyFlakeDetectionSettings,
testManagementSettings,
defaultBranch,
requestError);
settingsRequestError);
}

public interface Factory {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package datadog.trace.civisibility.config;

import datadog.trace.api.DDTags;
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
import datadog.trace.civisibility.ipc.serialization.Serializer;
import java.nio.ByteBuffer;
import java.util.Objects;

/** Tracks which CI Visibility backend requests failed. */
public class ConfigurationErrors {

public static final ConfigurationErrors NONE =
new ConfigurationErrors(false, false, false, false, false);

private static final int SETTINGS_FLAG = 1;
private static final int SKIPPABLE_TESTS_FLAG = 2;
private static final int FLAKY_TESTS_FLAG = 4;
private static final int KNOWN_TESTS_FLAG = 8;
private static final int TEST_MANAGEMENT_TESTS_FLAG = 16;

private final boolean settings;
private final boolean skippableTests;
private final boolean flakyTests;
private final boolean knownTests;
private final boolean testManagementTests;

public ConfigurationErrors(
boolean settings,
boolean skippableTests,
boolean flakyTests,
boolean knownTests,
boolean testManagementTests) {
this.settings = settings;
this.skippableTests = skippableTests;
this.flakyTests = flakyTests;
this.knownTests = knownTests;
this.testManagementTests = testManagementTests;
}

public boolean hasAny() {
return settings || skippableTests || flakyTests || knownTests || testManagementTests;
}

public void applyTags(AgentSpan span) {
Copy link
Copy Markdown
Contributor

@ygree ygree Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this patch, the old tag disappears entirely and only the new per-request tags are emitted. Should it continue setting the old tag so that any legacy tag consumer can still detect an error?

if (settings) {
span.setTag(DDTags.CI_LIBRARY_CONFIGURATION_ERROR_SETTINGS, true);
}
if (skippableTests) {
span.setTag(DDTags.CI_LIBRARY_CONFIGURATION_ERROR_SKIPPABLE_TESTS, true);
}
if (flakyTests) {
span.setTag(DDTags.CI_LIBRARY_CONFIGURATION_ERROR_FLAKY_TESTS, true);
}
if (knownTests) {
span.setTag(DDTags.CI_LIBRARY_CONFIGURATION_ERROR_KNOWN_TESTS, true);
}
if (testManagementTests) {
span.setTag(DDTags.CI_LIBRARY_CONFIGURATION_ERROR_TEST_MANAGEMENT_TESTS, true);
}
}

public static void serialize(Serializer s, ConfigurationErrors errors) {
byte flags =
(byte)
((errors.settings ? SETTINGS_FLAG : 0)
| (errors.skippableTests ? SKIPPABLE_TESTS_FLAG : 0)
| (errors.flakyTests ? FLAKY_TESTS_FLAG : 0)
| (errors.knownTests ? KNOWN_TESTS_FLAG : 0)
| (errors.testManagementTests ? TEST_MANAGEMENT_TESTS_FLAG : 0));
s.write(flags);
}

public static ConfigurationErrors deserialize(ByteBuffer buffer) {
byte flags = Serializer.readByte(buffer);
if (flags == 0) {
return NONE;
}
return new ConfigurationErrors(
(flags & SETTINGS_FLAG) != 0,
(flags & SKIPPABLE_TESTS_FLAG) != 0,
(flags & FLAKY_TESTS_FLAG) != 0,
(flags & KNOWN_TESTS_FLAG) != 0,
(flags & TEST_MANAGEMENT_TESTS_FLAG) != 0);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ConfigurationErrors that = (ConfigurationErrors) o;
return settings == that.settings
&& skippableTests == that.skippableTests
&& flakyTests == that.flakyTests
&& knownTests == that.knownTests
&& testManagementTests == that.testManagementTests;
}

@Override
public int hashCode() {
return Objects.hash(settings, skippableTests, flakyTests, knownTests, testManagementTests);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ public class ExecutionSettings {
Collections.emptyList(),
Collections.emptyList(),
LineDiff.EMPTY,
false);
ConfigurationErrors.NONE);

public static final ExecutionSettings REQUEST_ERROR =
public static final ExecutionSettings SETTINGS_REQUEST_ERROR =
new ExecutionSettings(
false,
false,
Expand All @@ -61,7 +61,7 @@ public class ExecutionSettings {
Collections.emptyList(),
Collections.emptyList(),
LineDiff.EMPTY,
true);
new ConfigurationErrors(true, false, false, false, false));

private final boolean itrEnabled;
private final boolean codeCoverageEnabled;
Expand All @@ -78,7 +78,7 @@ public class ExecutionSettings {
@Nonnull private final Map<TestFQN, Integer> testSettings;
@Nonnull private final Map<TestSetting, Integer> settingsCount;
@Nonnull private final Diff pullRequestDiff;
private final boolean configurationError;
@Nonnull private final ConfigurationErrors configurationErrors;

public ExecutionSettings(
boolean itrEnabled,
Expand All @@ -99,7 +99,7 @@ public ExecutionSettings(
@Nonnull Collection<TestFQN> disabledTests,
@Nonnull Collection<TestFQN> attemptToFixTests,
@Nonnull Diff pullRequestDiff,
boolean configurationError) {
@Nonnull ConfigurationErrors configurationErrors) {
this.itrEnabled = itrEnabled;
this.codeCoverageEnabled = codeCoverageEnabled;
this.testSkippingEnabled = testSkippingEnabled;
Expand All @@ -113,7 +113,7 @@ public ExecutionSettings(
this.skippableTests = skippableTests;
this.skippableTestsCoverage = skippableTestsCoverage;
this.pullRequestDiff = pullRequestDiff;
this.configurationError = configurationError;
this.configurationErrors = configurationErrors;

testSettings = new HashMap<>();
if (flakyTests != null) {
Expand Down Expand Up @@ -154,7 +154,7 @@ private ExecutionSettings(
@Nonnull Map<TestFQN, Integer> testSettings,
@Nonnull EnumMap<TestSetting, Integer> settingsCount,
@Nonnull Diff pullRequestDiff,
boolean configurationError) {
@Nonnull ConfigurationErrors configurationErrors) {
this.itrEnabled = itrEnabled;
this.codeCoverageEnabled = codeCoverageEnabled;
this.testSkippingEnabled = testSkippingEnabled;
Expand All @@ -170,7 +170,7 @@ private ExecutionSettings(
this.testSettings = testSettings;
this.settingsCount = settingsCount;
this.pullRequestDiff = pullRequestDiff;
this.configurationError = configurationError;
this.configurationErrors = configurationErrors;
}

/**
Expand Down Expand Up @@ -277,8 +277,9 @@ public Diff getPullRequestDiff() {
return pullRequestDiff;
}

public boolean isConfigurationError() {
return configurationError;
@Nonnull
public ConfigurationErrors getConfigurationErrors() {
return configurationErrors;
}

@Override
Expand All @@ -305,7 +306,7 @@ public boolean equals(Object o) {
&& Objects.equals(testSettings, that.testSettings)
&& Objects.equals(settingsCount, that.settingsCount)
&& Objects.equals(pullRequestDiff, that.pullRequestDiff)
&& configurationError == that.configurationError;
&& Objects.equals(configurationErrors, that.configurationErrors);
}

@Override
Expand All @@ -326,7 +327,7 @@ public int hashCode() {
testSettings,
settingsCount,
pullRequestDiff,
configurationError);
configurationErrors);
}

public static class Serializer {
Expand All @@ -338,7 +339,6 @@ public static class Serializer {
private static final int IMPACTED_TESTS_DETECTION_ENABLED_FLAG = 16;
private static final int CODE_COVERAGE_REPORT_UPLOAD_ENABLED_FLAG = 32;
private static final int FAILED_TEST_REPLAY_ENABLED_FLAG = 64;
private static final int CONFIGURATION_ERROR_FLAG = 128;

public static ByteBuffer serialize(ExecutionSettings settings) {
datadog.trace.civisibility.ipc.serialization.Serializer s =
Expand All @@ -356,10 +356,11 @@ public static ByteBuffer serialize(ExecutionSettings settings) {
| (settings.codeCoverageReportUploadEnabled
? CODE_COVERAGE_REPORT_UPLOAD_ENABLED_FLAG
: 0)
| (settings.failedTestReplayEnabled ? FAILED_TEST_REPLAY_ENABLED_FLAG : 0)
| (settings.configurationError ? CONFIGURATION_ERROR_FLAG : 0));
| (settings.failedTestReplayEnabled ? FAILED_TEST_REPLAY_ENABLED_FLAG : 0));
s.write(flags);

ConfigurationErrors.serialize(s, settings.configurationErrors);

EarlyFlakeDetectionSettings.Serializer.serialize(s, settings.earlyFlakeDetectionSettings);

TestManagementSettings.Serializer.serialize(s, settings.testManagementSettings);
Expand Down Expand Up @@ -399,7 +400,8 @@ public static ExecutionSettings deserialize(ByteBuffer buffer) {
boolean codeCoverageReportUploadEnabled =
(flags & CODE_COVERAGE_REPORT_UPLOAD_ENABLED_FLAG) != 0;
boolean failedTestReplayEnabled = (flags & FAILED_TEST_REPLAY_ENABLED_FLAG) != 0;
boolean configurationError = (flags & CONFIGURATION_ERROR_FLAG) != 0;

ConfigurationErrors configurationErrors = ConfigurationErrors.deserialize(buffer);

EarlyFlakeDetectionSettings earlyFlakeDetectionSettings =
EarlyFlakeDetectionSettings.Serializer.deserialize(buffer);
Expand Down Expand Up @@ -452,7 +454,7 @@ public static ExecutionSettings deserialize(ByteBuffer buffer) {
testSettings,
settingsCount,
diff,
configurationError);
configurationErrors);
}
}
}
Loading
Loading