fix(dirty-state): exclude live-pushed fields from deploy diff
All checks were successful
All checks were successful
Live-pushed config fields (taps, tapVersion, tracedProcessors, routeRecording) apply via SSE CONFIG_UPDATE — they take effect on running agents without a redeploy and are fetched on agent restart from application_config. They must not contribute to the "pending deploy" diff against the last-successful-deployment snapshot. Before this fix, applying a tap from the process diagram correctly rolled out in real time but then marked the app "Pending Deploy (1)" because DirtyStateCalculator compared every agentConfig field. This also contradicted the UI rule (ui.md) that the live tabs "never mark dirty". Adds taps, tapVersion, tracedProcessors, routeRecording to AGENT_CONFIG_IGNORED_KEYS. Updates the nested-path test to use a staged field (sensitiveKeys) and adds a new test asserting that divergent live-push fields keep dirty=false. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,8 +23,13 @@ import java.util.UUID;
|
||||
*/
|
||||
public class DirtyStateCalculator {
|
||||
|
||||
// Live-pushed fields are excluded from the deploy diff: changes to them take effect
|
||||
// via SSE config-update without a redeploy, so they are not "pending deploy" when they
|
||||
// differ from the last successful deployment snapshot. See ui/rules: the Traces & Taps
|
||||
// and Route Recording tabs apply with ?apply=live and "never mark dirty".
|
||||
private static final Set<String> AGENT_CONFIG_IGNORED_KEYS = Set.of(
|
||||
"version", "updatedAt", "updatedBy", "environment", "application"
|
||||
"version", "updatedAt", "updatedBy", "environment", "application",
|
||||
"taps", "tapVersion", "tracedProcessors", "routeRecording"
|
||||
);
|
||||
|
||||
private final ObjectMapper mapper;
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -114,9 +115,9 @@ class DirtyStateCalculatorTest {
|
||||
DirtyStateCalculator calc = CALC;
|
||||
|
||||
ApplicationConfig deployed = new ApplicationConfig();
|
||||
deployed.setTracedProcessors(Map.of("proc-1", "DEBUG"));
|
||||
deployed.setSensitiveKeys(List.of("password", "token"));
|
||||
ApplicationConfig desired = new ApplicationConfig();
|
||||
desired.setTracedProcessors(Map.of("proc-1", "TRACE"));
|
||||
desired.setSensitiveKeys(List.of("password", "token", "secret"));
|
||||
UUID jarId = UUID.randomUUID();
|
||||
DeploymentConfigSnapshot snap = new DeploymentConfigSnapshot(jarId, deployed, Map.of(), null);
|
||||
|
||||
@@ -124,7 +125,29 @@ class DirtyStateCalculatorTest {
|
||||
|
||||
assertThat(result.dirty()).isTrue();
|
||||
assertThat(result.differences()).extracting(DirtyStateResult.Difference::field)
|
||||
.contains("agentConfig.tracedProcessors.proc-1");
|
||||
.anyMatch(f -> f.startsWith("agentConfig.sensitiveKeys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void livePushedFields_doNotMarkDirty() {
|
||||
// Taps, tracedProcessors, and routeRecording apply via live SSE push (never redeploy),
|
||||
// so they must not appear as "pending deploy" when they differ from the last deploy snapshot.
|
||||
ApplicationConfig deployed = new ApplicationConfig();
|
||||
deployed.setTracedProcessors(Map.of("proc-1", "DEBUG"));
|
||||
deployed.setRouteRecording(Map.of("route-a", true));
|
||||
deployed.setTapVersion(1);
|
||||
|
||||
ApplicationConfig desired = new ApplicationConfig();
|
||||
desired.setTracedProcessors(Map.of("proc-1", "TRACE", "proc-2", "DEBUG"));
|
||||
desired.setRouteRecording(Map.of("route-a", false, "route-b", true));
|
||||
desired.setTapVersion(5);
|
||||
|
||||
UUID jarId = UUID.randomUUID();
|
||||
DeploymentConfigSnapshot snap = new DeploymentConfigSnapshot(jarId, deployed, Map.of(), null);
|
||||
DirtyStateResult result = CALC.compute(jarId, desired, Map.of(), snap);
|
||||
|
||||
assertThat(result.dirty()).isFalse();
|
||||
assertThat(result.differences()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user