Skip to content

Commit 16c5b92

Browse files
authored
fix(argoCD): avoid duplication of latest deployments (#8862)
1 parent 0e16249 commit 16c5b92

2 files changed

Lines changed: 53 additions & 1 deletion

File tree

backend/plugins/argocd/tasks/sync_operation_extractor.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,12 @@ func ExtractSyncOperations(taskCtx plugin.SubTaskContext) errors.Error {
188188

189189
isOperationState := apiOp.Phase != ""
190190

191+
// operationState always represents the same sync as the latest history entry
192+
// (when phase=Succeeded). Skip it to avoid the duplicate DeploymentId.
193+
if isOperationState && isRedundantOperationState(apiOp.Phase) {
194+
return nil, nil
195+
}
196+
191197
// For multi-source apps ArgoCD sets revisions[] instead of revision. Resolve
192198
// the single commit SHA we care about before deciding whether to skip this entry.
193199
if apiOp.Revision == "" {
@@ -534,3 +540,21 @@ func isCommitSHA(s string) bool {
534540
}
535541
return true
536542
}
543+
544+
// isRedundantOperationState reports whether an operationState entry should be
545+
// skipped because it duplicates the most recent history entry.
546+
//
547+
// ArgoCD exposes a completed sync in two places:
548+
// - status.history[] — authoritative log, one entry per sync
549+
// - status.operationState — mirrors the last sync while it is current
550+
//
551+
// When phase is Succeeded the operationState is always already present in
552+
// history[]. Emitting it would produce a second ArgocdSyncOperation whose
553+
// DeploymentId differs by one second (startedAt vs deployedAt), creating a
554+
// duplicate deployment in DORA metrics.
555+
//
556+
// In-flight (Running, Terminating) and terminal-failure (Failed, Error) states
557+
// are not yet — or may never be — written to history, so they must be kept.
558+
func isRedundantOperationState(phase string) bool {
559+
return phase == "Succeeded"
560+
}

backend/plugins/argocd/tasks/sync_operation_extractor_test.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func TestIsCommitSHA(t *testing.T) {
143143
assert.True(t, isCommitSHA("AABBCCDD11223344AABBCCDD11223344AABBCCDD"))
144144
assert.False(t, isCommitSHA("2.6.2"))
145145
assert.False(t, isCommitSHA(""))
146-
assert.False(t, isCommitSHA("5dd95b4efd7e9b668c361bbddb8d7f1e56c32ac")) // 39 chars
146+
assert.False(t, isCommitSHA("5dd95b4efd7e9b668c361bbddb8d7f1e56c32ac")) // 39 chars
147147
assert.False(t, isCommitSHA("5dd95b4efd7e9b668c361bbddb8d7f1e56c32ac12")) // 41 chars
148148
}
149149

@@ -216,3 +216,31 @@ func TestIsGitHostedURL(t *testing.T) {
216216
assert.False(t, isGitHostedURL("s3://my-bucket/charts"))
217217
assert.False(t, isGitHostedURL(""))
218218
}
219+
220+
// ── isRedundantOperationState ─────────────────────────────────────────────────
221+
222+
func TestIsRedundantOperationState_SucceededIsSkipped(t *testing.T) {
223+
assert.True(t, isRedundantOperationState("Succeeded"),
224+
"Succeeded operationState always duplicates the latest history entry")
225+
}
226+
227+
func TestIsRedundantOperationState_NonTerminalPhasesAreKept(t *testing.T) {
228+
for _, phase := range []string{"Running", "Terminating"} {
229+
assert.False(t, isRedundantOperationState(phase),
230+
"in-flight phase %q is not yet in history and must be kept", phase)
231+
}
232+
}
233+
234+
func TestIsRedundantOperationState_FailurePhasesAreKept(t *testing.T) {
235+
for _, phase := range []string{"Failed", "Error"} {
236+
assert.False(t, isRedundantOperationState(phase),
237+
"failure phase %q may never reach history and must be kept", phase)
238+
}
239+
}
240+
241+
func TestIsRedundantOperationState_HistoryEntryHasNoPhase(t *testing.T) {
242+
// History entries have phase="" — isOperationState is false before this
243+
// function is called, but double-check the function itself is safe with
244+
// an empty string so the guard can never accidentally suppress history rows.
245+
assert.False(t, isRedundantOperationState(""))
246+
}

0 commit comments

Comments
 (0)