diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker.go index 226ad413a..9c4ec0282 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker.go @@ -196,8 +196,8 @@ func (t *ReleaseTargetJobTracker) GetSuccessPercentage() float32 { numRt := len(t.ReleaseTargets) if numRt == 0 { - span.SetAttributes(attribute.Float64("success_percentage", 0.0)) - return 0.0 // If no targets, consider it 100% successful + span.SetAttributes(attribute.Float64("success_percentage", 100.0)) + return 100.0 // vacuous truth: 0/0 targets successful } // Build a set of release target keys for filtering @@ -242,7 +242,7 @@ func (t *ReleaseTargetJobTracker) GetSuccessPercentageSatisfiedAt( } numRt := len(t.ReleaseTargets) if numRt == 0 { - return time.Time{} + return t.Version.CreatedAt } // Build a set of release target keys for filtering diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker_test.go index 71136c941..96e779a5e 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker_test.go @@ -77,7 +77,13 @@ func TestReleaseTargetJobTracker_GetSuccessPercentage_NoTargets(t *testing.T) { tracker := NewReleaseTargetJobTracker(ctx, mock, env, version, nil, false) percentage := tracker.GetSuccessPercentage() - assert.InDelta(t, float32(0.0), percentage, 0, "expected 0%% success with no targets") + assert.InDelta( + t, + float32(100.0), + percentage, + 0, + "expected 100%% success with no targets (vacuous truth)", + ) } func TestReleaseTargetJobTracker_GetSuccessPercentage_WithSuccesses(t *testing.T) { @@ -941,9 +947,14 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_NoReleaseTarget tracker := NewReleaseTargetJobTracker(ctx, mock, env, version, nil, false) tracker.ReleaseTargets = []oapi.ReleaseTarget{} - // With no release targets, should return zero time + // Vacuous truth: 0/0 targets successful is treated as 100% pass, satisfied at version creation. satisfiedAt := tracker.GetSuccessPercentageSatisfiedAt(50.0) - assert.True(t, satisfiedAt.IsZero(), "expected zero satisfiedAt with no release targets") + assert.Equal( + t, + version.CreatedAt, + satisfiedAt, + "expected satisfiedAt to equal version.CreatedAt with no release targets", + ) } func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_NoSuccessfulJobs(t *testing.T) { diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/passrate_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/passrate_test.go index baf708015..3552481bb 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/passrate_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/passrate_test.go @@ -461,9 +461,9 @@ func TestPassRateEvaluator_NoReleaseTargets(t *testing.T) { } result := eval.Evaluate(ctx, scope) - // With no release targets, success percentage is 0% - assert.False(t, result.Allowed, "expected denied with no release targets") - assert.Contains(t, result.Message, "Success rate 0.0% below required 50.0%") + // Vacuous truth: 0/0 release targets is treated as 100% pass rate. + assert.True(t, result.Allowed, "expected allowed with no release targets (vacuous truth)") + assert.Contains(t, result.Message, "Success rate 100.0% meets required 50.0%") } // TestPassRateEvaluator_CustomSuccessStatuses tests that custom success statuses can be used.