diff --git a/apps/workspace-engine/pkg/oapi/persistence.go b/apps/workspace-engine/pkg/oapi/persistence.go index f967d5c7d..f70f24b8f 100644 --- a/apps/workspace-engine/pkg/oapi/persistence.go +++ b/apps/workspace-engine/pkg/oapi/persistence.go @@ -42,7 +42,7 @@ func (s *System) CompactionKey() (string, string) { } func (r *Release) CompactionKey() (string, string) { - return "release", r.ContentHash() + return "release", r.Id.String() } func (j *Job) CompactionKey() (string, string) { diff --git a/apps/workspace-engine/pkg/persistence/integration_test.go b/apps/workspace-engine/pkg/persistence/integration_test.go index a17ef9e3a..417d6707c 100644 --- a/apps/workspace-engine/pkg/persistence/integration_test.go +++ b/apps/workspace-engine/pkg/persistence/integration_test.go @@ -664,7 +664,7 @@ func TestPersistence_ComplexWorkspaceWithComputedValues(t *testing.T) { require.True(t, ok, "JobAgent should be restored") assert.Equal(t, "k8s-agent", restoredJobAgent.Name) - restoredRelease, ok := newStore.Repo().Releases().Get(release.ContentHash()) + restoredRelease, ok := newStore.Repo().Releases().Get(release.Id.String()) require.True(t, ok, "Release should be restored") assert.Equal(t, "v1.2.3", restoredRelease.Version.Tag) diff --git a/apps/workspace-engine/pkg/workspace/jobs/factory.go b/apps/workspace-engine/pkg/workspace/jobs/factory.go index 683a2f58b..3642cc08d 100644 --- a/apps/workspace-engine/pkg/workspace/jobs/factory.go +++ b/apps/workspace-engine/pkg/workspace/jobs/factory.go @@ -169,11 +169,11 @@ func (f *Factory) CreateJobForRelease(ctx context.Context, release *oapi.Release if action != nil { action.AddStep("Create job", trace.StepResultPass, - fmt.Sprintf("Job created successfully with ID %s for release %s", jobId, release.ContentHash())). + fmt.Sprintf("Job created successfully with ID %s for release %s", jobId, release.Id.String())). AddMetadata("job_id", jobId). AddMetadata("job_status", string(oapi.JobStatusPending)). AddMetadata("job_agent_id", jobAgent.Id). - AddMetadata("release_id", release.ContentHash()). + AddMetadata("release_id", release.Id.String()). AddMetadata("version_tag", release.Version.Tag) } @@ -184,7 +184,7 @@ func (f *Factory) CreateJobForRelease(ctx context.Context, release *oapi.Release return &oapi.Job{ Id: jobId, - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), JobAgentId: jobAgent.Id, JobAgentConfig: jobAgent.Config, Status: oapi.JobStatusPending, diff --git a/apps/workspace-engine/pkg/workspace/jobs/factory_test.go b/apps/workspace-engine/pkg/workspace/jobs/factory_test.go index 97a0ef815..bc6be1f11 100644 --- a/apps/workspace-engine/pkg/workspace/jobs/factory_test.go +++ b/apps/workspace-engine/pkg/workspace/jobs/factory_test.go @@ -174,7 +174,7 @@ func TestFactory_CreateJobForRelease_SetsCorrectJobFields(t *testing.T) { require.NoError(t, err) // Verify release ID is correct - require.Equal(t, release.ContentHash(), job.ReleaseId) + require.Equal(t, release.Id.String(), job.ReleaseId) // Verify job agent ID is correct require.Equal(t, jobAgentId, job.JobAgentId) diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator.go b/apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator.go index 04adcd8c2..f557074cb 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator.go @@ -67,7 +67,7 @@ func (o *Orchestrator) OnJobStatusChange( return nil // No release found } - span.SetAttributes(attribute.String("release.id", release.ContentHash())) + span.SetAttributes(attribute.String("release.id", release.Id.String()), attribute.String("release.content_hash", release.ContentHash())) policies, err := o.store.ReleaseTargets.GetPolicies(ctx, &release.ReleaseTarget) if err != nil { @@ -97,7 +97,8 @@ func (o *Orchestrator) OnJobStatusChange( log.Error("Policy action failed", "action", action.Name(), "job_id", job.Id, - "release_id", release.ContentHash(), + "release_id", release.Id.String(), + "content_hash", release.ContentHash(), "error", err) // Continue with other actions } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator_test.go index 2a25f2af8..92d7592e9 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator_test.go @@ -159,7 +159,7 @@ func TestOrchestrator_OnJobStatusChange_TriggerJobSuccess(t *testing.T) { // Create job job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -172,7 +172,7 @@ func TestOrchestrator_OnJobStatusChange_TriggerJobSuccess(t *testing.T) { assert.True(t, mockAct.executeCalled) assert.Equal(t, action.TriggerJobSuccess, mockAct.lastTrigger) assert.Equal(t, job.Id, mockAct.lastContext.Job.Id) - assert.Equal(t, release.ContentHash(), mockAct.lastContext.Release.ContentHash()) + assert.Equal(t, release.Id.String(), mockAct.lastContext.Release.Id.String()) } func TestOrchestrator_OnJobStatusChange_TriggerJobStarted(t *testing.T) { @@ -190,7 +190,7 @@ func TestOrchestrator_OnJobStatusChange_TriggerJobStarted(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: time.Now(), } @@ -217,7 +217,7 @@ func TestOrchestrator_OnJobStatusChange_TriggerJobFailure(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now(), } @@ -244,7 +244,7 @@ func TestOrchestrator_OnJobStatusChange_NoTrigger(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: time.Now(), } @@ -272,7 +272,7 @@ func TestOrchestrator_OnJobStatusChange_ShouldNotExecute(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -301,7 +301,7 @@ func TestOrchestrator_OnJobStatusChange_MultipleActions(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -357,7 +357,7 @@ func TestOrchestrator_OnJobStatusChange_ActionError(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/hooks.go b/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/hooks.go index 96860bc5b..3c110b6ff 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/hooks.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/hooks.go @@ -72,7 +72,8 @@ func (h *RollbackHooks) OnVerificationComplete(ctx context.Context, verification } span.SetAttributes( - attribute.String("release.id", release.ContentHash()), + attribute.String("release.id", release.Id.String()), + attribute.String("release.content_hash", release.ContentHash()), attribute.String("release_target.key", release.ReleaseTarget.Key()), ) @@ -106,7 +107,8 @@ func (h *RollbackHooks) OnVerificationComplete(ctx context.Context, verification } span.SetAttributes( - attribute.String("rollback_to_release.id", currentRelease.ContentHash()), + attribute.String("rollback_to_release.id", currentRelease.Id.String()), + attribute.String("rollback_to_release.content_hash", currentRelease.ContentHash()), attribute.String("rollback_to_version.id", currentRelease.Version.Id), attribute.String("rollback_to_version.tag", currentRelease.Version.Tag), ) diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/rollback.go b/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/rollback.go index 460dbf177..905901ea5 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/rollback.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/rollback.go @@ -43,7 +43,8 @@ func (r *RollbackAction) Execute( span.SetAttributes( attribute.String("trigger", string(trigger)), - attribute.String("release.id", actx.Release.ContentHash()), + attribute.String("release.id", actx.Release.Id.String()), + attribute.String("release.content_hash", actx.Release.ContentHash()), attribute.String("job.id", actx.Job.Id), attribute.String("job.status", string(actx.Job.Status)), ) @@ -70,7 +71,8 @@ func (r *RollbackAction) Execute( } span.SetAttributes( - attribute.String("rollback_to_release.id", currentRelease.ContentHash()), + attribute.String("rollback_to_release.id", currentRelease.Id.String()), + attribute.String("rollback_to_release.content_hash", currentRelease.ContentHash()), attribute.String("rollback_to_version.id", currentRelease.Version.Id), attribute.String("rollback_to_version.tag", currentRelease.Version.Tag), ) diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification.go b/apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification.go index 619f69598..53aeb6eed 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification.go @@ -43,7 +43,8 @@ func (v *VerificationAction) Execute( span.SetAttributes( attribute.String("trigger", string(trigger)), - attribute.String("release.id", actx.Release.ContentHash()), + attribute.String("release.id", actx.Release.Id.String()), + attribute.String("release.content_hash", actx.Release.ContentHash()), attribute.String("job.id", actx.Job.Id)) // Extract all verification metrics from matching policies @@ -62,7 +63,8 @@ func (v *VerificationAction) Execute( span.SetStatus(codes.Error, "failed to create verification") log.Error("Failed to create verification", "error", err, - "release_id", actx.Release.ContentHash(), + "release_id", actx.Release.Id.String(), + "content_hash", actx.Release.ContentHash(), "job_id", actx.Job.Id, "trigger", trigger) return err @@ -70,7 +72,8 @@ func (v *VerificationAction) Execute( span.SetStatus(codes.Ok, "verification created") log.Info("Created verification from policy action", - "release_id", actx.Release.ContentHash(), + "release_id", actx.Release.Id.String(), + "content_hash", actx.Release.ContentHash(), "job_id", actx.Job.Id, "trigger", trigger, "metric_count", len(metrics)) diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification_test.go index db41c45e0..340b81ae8 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification_test.go @@ -113,7 +113,7 @@ func TestVerificationAction_Execute_NoMetrics(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -181,7 +181,7 @@ func TestVerificationAction_Execute_CreatesVerification(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -271,7 +271,7 @@ func TestVerificationAction_Execute_SkipsWrongTrigger(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -308,7 +308,7 @@ func TestVerificationAction_Execute_DefaultsTriggerToJobSuccess(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -346,7 +346,7 @@ func TestVerificationAction_Execute_DeduplicatesMetrics(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -406,7 +406,7 @@ func TestVerificationAction_Execute_TriggerJobCreated(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusPending, CreatedAt: time.Now(), } @@ -447,7 +447,7 @@ func TestVerificationAction_Execute_TriggerJobStarted(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: time.Now(), } @@ -488,7 +488,7 @@ func TestVerificationAction_Execute_TriggerJobFailure(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now(), } @@ -545,7 +545,7 @@ func TestVerificationAction_Execute_PolicyWithMixedRules(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -602,7 +602,7 @@ func TestVerificationAction_Execute_MultipleVerificationRulesInPolicy(t *testing job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -671,7 +671,7 @@ func TestVerificationAction_Execute_NilVerificationRule(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -711,7 +711,7 @@ func TestVerificationAction_Execute_EmptyMetricsArray(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -755,7 +755,7 @@ func TestVerificationAction_Execute_NilPoliciesSlice(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -785,7 +785,7 @@ func TestVerificationAction_Execute_PolicyWithNoRules(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -820,7 +820,7 @@ func TestVerificationAction_Execute_VerificationIsRunningWithCorrectMetricSpecs( job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -887,7 +887,7 @@ func TestVerificationAction_Execute_VerificationRecordHasCorrectReleaseLink(t *t job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } @@ -933,7 +933,7 @@ func TestVerificationAction_Execute_MultipleMetricsAllRunning(t *testing.T) { job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor.go b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor.go index 56205cebc..170ab5709 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor.go @@ -91,7 +91,7 @@ func (e *Executor) dispatchJobForAgent(ctx context.Context, release *oapi.Releas func (e *Executor) ExecuteRelease(ctx context.Context, releaseToDeploy *oapi.Release, recorder *trace.ReconcileTarget) ([]*oapi.Job, error) { ctx, span := tracer.Start(ctx, "ExecuteRelease", oteltrace.WithAttributes( - attribute.String("release.id", releaseToDeploy.ContentHash()), + attribute.String("release.id", releaseToDeploy.Id.String()), attribute.String("deployment.id", releaseToDeploy.ReleaseTarget.DeploymentId), attribute.String("environment.id", releaseToDeploy.ReleaseTarget.EnvironmentId), attribute.String("resource.id", releaseToDeploy.ReleaseTarget.ResourceId), @@ -121,7 +121,7 @@ func (e *Executor) ExecuteRelease(ctx context.Context, releaseToDeploy *oapi.Rel if err != nil { span.RecordError(err) span.SetStatus(codes.Error, "failed to get deployment agents") - failedJob := e.jobFactory.InvalidDeploymentAgentsJob(releaseToDeploy.ContentHash(), deployment.Name, nil) + failedJob := e.jobFactory.InvalidDeploymentAgentsJob(releaseToDeploy.Id.String(), deployment.Name, nil) e.store.Jobs.Upsert(ctx, failedJob) return []*oapi.Job{failedJob}, nil } @@ -138,7 +138,7 @@ func (e *Executor) ExecuteRelease(ctx context.Context, releaseToDeploy *oapi.Rel } if len(agents) == 0 { - failedJob := e.jobFactory.NoAgentConfiguredJob(releaseToDeploy.ContentHash(), "", deployment.Name, nil) + failedJob := e.jobFactory.NoAgentConfiguredJob(releaseToDeploy.Id.String(), "", deployment.Name, nil) e.store.Jobs.Upsert(ctx, failedJob) return []*oapi.Job{failedJob}, nil } @@ -183,12 +183,13 @@ func BuildRelease( } } - return &oapi.Release{ - Id: uuid.New(), + release := &oapi.Release{ ReleaseTarget: *releaseTarget, Version: *version, Variables: clonedVariables, EncryptedVariables: []string{}, CreatedAt: time.Now().Format(time.RFC3339), } + release.Id = uuid.NewSHA1(uuid.NameSpaceOID, []byte(release.ContentHash())) + return release } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor_test.go index 5227e548a..9e4f8f09e 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor_test.go @@ -40,7 +40,7 @@ func createTestJobAgent(id, workspaceID, name, agentType string) *oapi.JobAgent } } -func createTestDeploymentForExecutor(id, systemID, name, jobAgentID string) *oapi.Deployment { +func createTestDeploymentForExecutor(id, name, jobAgentID string) *oapi.Deployment { selector := &oapi.Selector{} _ = selector.FromCelSelector(oapi.CelSelector{Cel: "true"}) @@ -54,7 +54,7 @@ func createTestDeploymentForExecutor(id, systemID, name, jobAgentID string) *oap } } -func createTestEnvironmentForExecutor(id, systemID, name string) *oapi.Environment { +func createTestEnvironmentForExecutor(id, name string) *oapi.Environment { selector := &oapi.Selector{} _ = selector.FromCelSelector(oapi.CelSelector{Cel: "true"}) return &oapi.Environment{ @@ -109,15 +109,23 @@ func TestExecuteRelease_Success(t *testing.T) { versionID := uuid.New().String() jobAgentID := uuid.New().String() + testStore.Systems.Upsert(ctx, &oapi.System{ + Id: systemID, + Name: "test-system", + }) + // Create necessary entities in store jobAgent := createTestJobAgent(jobAgentID, workspaceID, "test-agent", "test-runner") testStore.JobAgents.Upsert(ctx, jobAgent) - deployment := createTestDeploymentForExecutor(deploymentID, systemID, "test-deployment", jobAgentID) + deployment := createTestDeploymentForExecutor(deploymentID, "test-deployment", jobAgentID) _ = testStore.Deployments.Upsert(ctx, deployment) - environment := createTestEnvironmentForExecutor(environmentID, systemID, "test-environment") + testStore.SystemDeployments.Link(systemID, deploymentID) + + environment := createTestEnvironmentForExecutor(environmentID, "test-environment") _ = testStore.Environments.Upsert(ctx, environment) + testStore.SystemEnvironments.Link(systemID, environmentID) resource := createTestResourceForExecutor(resourceID, "test-resource", workspaceID) _, _ = testStore.Resources.Upsert(ctx, resource) @@ -132,14 +140,14 @@ func TestExecuteRelease_Success(t *testing.T) { require.NoError(t, err) require.Len(t, jobs, 1) job := jobs[0] - assert.Equal(t, release.ContentHash(), job.ReleaseId) + assert.Equal(t, release.Id.String(), job.ReleaseId) assert.Equal(t, oapi.JobStatusPending, job.Status) assert.Equal(t, jobAgentID, job.JobAgentId) // Verify release was persisted - storedRelease, exists := testStore.Releases.Get(release.ContentHash()) + storedRelease, exists := testStore.Releases.Get(release.Id.String()) require.True(t, exists) - assert.Equal(t, release.ContentHash(), storedRelease.ContentHash()) + assert.Equal(t, release.Id.String(), storedRelease.Id.String()) // Verify job was persisted storedJob, exists := testStore.Jobs.Get(job.Id) @@ -173,7 +181,12 @@ func TestExecuteRelease_MultipleDeploymentJobAgents_MergesSelectedAgentConfig(t testStore.JobAgents.Upsert(ctx, selectedAgent) testStore.JobAgents.Upsert(ctx, otherAgent) - deployment := createTestDeploymentForExecutor(deploymentID, systemID, "test-deployment", selectedAgentID) + testStore.Systems.Upsert(ctx, &oapi.System{ + Id: systemID, + Name: "test-system", + }) + + deployment := createTestDeploymentForExecutor(deploymentID, "test-deployment", selectedAgentID) deployment.JobAgentConfig = oapi.JobAgentConfig{ "template": "deployment-template", "retries": 3, @@ -196,9 +209,11 @@ func TestExecuteRelease_MultipleDeploymentJobAgents_MergesSelectedAgentConfig(t }, } _ = testStore.Deployments.Upsert(ctx, deployment) + testStore.SystemDeployments.Link(systemID, deploymentID) - environment := createTestEnvironmentForExecutor(environmentID, systemID, "test-environment") + environment := createTestEnvironmentForExecutor(environmentID, "test-environment") _ = testStore.Environments.Upsert(ctx, environment) + testStore.SystemEnvironments.Link(systemID, environmentID) resource := createTestResourceForExecutor(resourceID, "test-resource", workspaceID) _, _ = testStore.Resources.Upsert(ctx, resource) @@ -249,7 +264,7 @@ func TestExecuteRelease_NoJobAgentConfigured(t *testing.T) { require.Equal(t, oapi.JobStatusInvalidJobAgent, jobs[0].Status) // Verify release was still persisted - _, exists := testStore.Releases.Get(release.ContentHash()) + _, exists := testStore.Releases.Get(release.Id.String()) require.True(t, exists) } @@ -286,9 +301,15 @@ func TestExecuteRelease_SkipsDispatchForInvalidJobAgent(t *testing.T) { versionID := uuid.New().String() nonExistentJobAgentID := uuid.New().String() + testStore.Systems.Upsert(ctx, &oapi.System{ + Id: systemID, + Name: "test-system", + }) + // Create deployment with non-existent job agent - deployment := createTestDeploymentForExecutor(deploymentID, systemID, "test-deployment", nonExistentJobAgentID) + deployment := createTestDeploymentForExecutor(deploymentID, "test-deployment", nonExistentJobAgentID) _ = testStore.Deployments.Upsert(ctx, deployment) + testStore.SystemDeployments.Link(systemID, deploymentID) // Create release release := createTestRelease(deploymentID, environmentID, resourceID, versionID, "v1.0.0") @@ -323,15 +344,22 @@ func TestExecuteRelease_MultipleReleases(t *testing.T) { resourceID := uuid.New().String() jobAgentID := uuid.New().String() + testStore.Systems.Upsert(ctx, &oapi.System{ + Id: systemID, + Name: "test-system", + }) + // Create necessary entities jobAgent := createTestJobAgent(jobAgentID, workspaceID, "test-agent", "test-runner") testStore.JobAgents.Upsert(ctx, jobAgent) - deployment := createTestDeploymentForExecutor(deploymentID, systemID, "test-deployment", jobAgentID) + deployment := createTestDeploymentForExecutor(deploymentID, "test-deployment", jobAgentID) _ = testStore.Deployments.Upsert(ctx, deployment) + testStore.SystemDeployments.Link(systemID, deploymentID) - environment := createTestEnvironmentForExecutor(environmentID, systemID, "test-environment") + environment := createTestEnvironmentForExecutor(environmentID, "test-environment") _ = testStore.Environments.Upsert(ctx, environment) + testStore.SystemEnvironments.Link(systemID, environmentID) resource := createTestResourceForExecutor(resourceID, "test-resource", workspaceID) _, _ = testStore.Resources.Upsert(ctx, resource) @@ -356,7 +384,7 @@ func TestExecuteRelease_MultipleReleases(t *testing.T) { for i, job := range allJobs { // Verify each job has correct release ID - assert.Equal(t, releases[i].ContentHash(), job.ReleaseId) + assert.Equal(t, releases[i].Id.String(), job.ReleaseId) // Verify job was persisted storedJob, exists := testStore.Jobs.Get(job.Id) @@ -364,8 +392,9 @@ func TestExecuteRelease_MultipleReleases(t *testing.T) { assert.Equal(t, job.Id, storedJob.Id) // Verify release was persisted - storedRelease, exists := testStore.Releases.Get(releases[i].ContentHash()) + storedRelease, exists := testStore.Releases.Get(releases[i].Id.String()) require.True(t, exists) + assert.Equal(t, releases[i].Id.String(), storedRelease.Id.String()) assert.Equal(t, releases[i].ContentHash(), storedRelease.ContentHash()) } } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility.go b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility.go index 4a45bbc4a..a0b442a72 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility.go @@ -60,7 +60,8 @@ func (c *JobEligibilityChecker) ShouldCreateJob( ) (*EligibilityResult, error) { ctx, span := jobEligibilityTracer.Start(ctx, "ShouldCreateJob", oteltrace.WithAttributes( - attribute.String("release.id", release.ContentHash()), + attribute.String("release.id", release.Id.String()), + attribute.String("release.content_hash", release.ContentHash()), attribute.String("release.version.id", release.Version.Id), attribute.String("release.version.tag", release.Version.Tag), attribute.String("release.target.key", release.ReleaseTarget.Key()), diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_retry_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_retry_test.go index 65ba5d7ab..29c203849 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_retry_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_retry_test.go @@ -82,7 +82,7 @@ func TestRetryPolicy_MultipleRules_FirstNoRetry_SecondHasRetry(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, @@ -99,7 +99,7 @@ func TestRetryPolicy_MultipleRules_FirstNoRetry_SecondHasRetry(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-" + string(rune(i)), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now(), CompletedAt: &completedAt, @@ -196,7 +196,7 @@ func TestRetryPolicy_MultiplePolicies_MostRestrictiveWins(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, @@ -211,7 +211,7 @@ func TestRetryPolicy_MultiplePolicies_MostRestrictiveWins(t *testing.T) { completedAt2 := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-2", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now(), CompletedAt: &completedAt2, @@ -294,7 +294,7 @@ func TestRetryPolicy_AllRulesNoRetry_UsesDefault(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, @@ -366,7 +366,7 @@ func TestRetryPolicy_DisabledPolicy_NotApplied(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_test.go index 37ecf2545..1895727ae 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_test.go @@ -85,7 +85,7 @@ func TestShouldCreateJob_AlreadyDeployed(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, @@ -115,7 +115,7 @@ func TestShouldCreateJob_NewVersionAfterSuccessfulDeployment(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-v1", - ReleaseId: releaseV1.ContentHash(), + ReleaseId: releaseV1.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, @@ -150,7 +150,7 @@ func TestShouldCreateJob_JobInProgress(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: time.Now(), }) @@ -179,7 +179,7 @@ func TestShouldCreateJob_PendingJob(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusPending, CreatedAt: time.Now(), }) @@ -209,7 +209,7 @@ func TestShouldCreateJob_FailedJobPreventsRedeploy(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, @@ -240,7 +240,7 @@ func TestShouldCreateJob_CancelledJobPreventsRedeploy(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusCancelled, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, @@ -288,7 +288,7 @@ func TestShouldCreateJob_DifferentVariablesAllowsNewJob(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, @@ -340,7 +340,7 @@ func TestShouldCreateJob_ConcurrentJobsForSameTarget(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: time.Now(), }) @@ -390,7 +390,7 @@ func TestShouldCreateJob_AllowsConcurrentJobsForDifferentTargets(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: time.Now(), }) @@ -440,7 +440,7 @@ func TestShouldCreateJob_MultipleCompletedJobs(t *testing.T) { completedAt := time.Now().Add(-time.Duration(4-i) * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-time.Duration(4-i) * time.Hour), CompletedAt: &completedAt, @@ -485,7 +485,7 @@ func TestShouldCreateJob_SkippedJobPreventsRedeploy(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSkipped, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, @@ -515,7 +515,7 @@ func TestShouldCreateJob_InvalidJobAgentStatusPreventsRedeploy(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusInvalidJobAgent, CreatedAt: time.Now().Add(-1 * time.Hour), }) @@ -576,7 +576,7 @@ func TestShouldCreateJob_EvaluatorOrdering(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: time.Now(), }) diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/planner.go b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/planner.go index 4fb6a1f4e..a3e7ba940 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/planner.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/planner.go @@ -176,7 +176,8 @@ func (p *Planner) PlanDeployment(ctx context.Context, releaseTarget *oapi.Releas desiredRelease := BuildRelease(ctx, releaseTarget, deployableVersion, resolvedVariables) span.SetAttributes( attribute.Bool("has_desired_release", true), - attribute.String("release.id", desiredRelease.ContentHash()), + attribute.String("release.id", desiredRelease.Id.String()), + attribute.String("release.content_hash", desiredRelease.ContentHash()), ) span.SetStatus(codes.Ok, "planning completed successfully") diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/manager.go b/apps/workspace-engine/pkg/workspace/releasemanager/manager.go index f39198141..4ff23afb2 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/manager.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/manager.go @@ -299,7 +299,7 @@ func (m *Manager) reconcileTargetWithRecorder( planning := recorder.StartPlanning() if desiredRelease != nil { planning.MakeDecision( - fmt.Sprintf("Desired release resolved from index: %s", desiredRelease.ContentHash()), + fmt.Sprintf("Desired release resolved from index: %s", desiredRelease.Id.String()), trace.DecisionApproved, ) } else { diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/manager_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/manager_test.go index e50cd3c1b..361eb89d4 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/manager_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/manager_test.go @@ -103,7 +103,7 @@ func TestProcessChanges_DeleteOnly(t *testing.T) { _ = testStore.Releases.Upsert(ctx, release) // Create a pending job for this release target - job := createTestJob(release.ContentHash(), oapi.JobStatusPending) + job := createTestJob(release.Id.String(), oapi.JobStatusPending) testStore.Jobs.Upsert(ctx, job) // Verify job is pending @@ -266,10 +266,10 @@ func TestProcessChanges_OnlyPendingJobsCancelled(t *testing.T) { _ = testStore.Releases.Upsert(ctx, release) // Create jobs in different states - pendingJob := createTestJob(release.ContentHash(), oapi.JobStatusPending) - inProgressJob := createTestJob(release.ContentHash(), oapi.JobStatusInProgress) - successfulJob := createTestJob(release.ContentHash(), oapi.JobStatusSuccessful) - failedJob := createTestJob(release.ContentHash(), oapi.JobStatusFailure) + pendingJob := createTestJob(release.Id.String(), oapi.JobStatusPending) + inProgressJob := createTestJob(release.Id.String(), oapi.JobStatusInProgress) + successfulJob := createTestJob(release.Id.String(), oapi.JobStatusSuccessful) + failedJob := createTestJob(release.Id.String(), oapi.JobStatusFailure) testStore.Jobs.Upsert(ctx, pendingJob) testStore.Jobs.Upsert(ctx, inProgressJob) @@ -323,7 +323,7 @@ func TestProcessChanges_MixedOperations(t *testing.T) { Variables: map[string]oapi.LiteralValue{}, } _ = testStore.Releases.Upsert(ctx, release2) - job2 := createTestJob(release2.ContentHash(), oapi.JobStatusPending) + job2 := createTestJob(release2.Id.String(), oapi.JobStatusPending) testStore.Jobs.Upsert(ctx, job2) // Create changeset with mixed operations diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_policy_action.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_policy_action.go index 5f4c90d33..7ff276418 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_policy_action.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_policy_action.go @@ -37,7 +37,8 @@ func (d *DeploymentDependencyAction) Execute(ctx context.Context, trigger action span.SetAttributes( attribute.String("trigger", string(trigger)), - attribute.String("release.id", context.Release.ContentHash()), + attribute.String("release.id", context.Release.Id.String()), + attribute.String("release.content_hash", context.Release.ContentHash()), attribute.String("job.id", context.Job.Id), attribute.String("job.status", string(context.Job.Status)), ) diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_test.go index a6e7083cd..a4f2d7926 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_test.go @@ -91,7 +91,7 @@ func generateReleaseAndJob(ctx context.Context, releaseTarget *oapi.ReleaseTarge job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: jobStatus, CreatedAt: now, CompletedAt: completedAt, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentwindow/deploymentwindow_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentwindow/deploymentwindow_test.go index a8151beca..959fc2d86 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentwindow/deploymentwindow_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentwindow/deploymentwindow_test.go @@ -90,7 +90,7 @@ func seedSuccessfulRelease( completedAt := time.Now().Add(-1 * time.Hour) job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CompletedAt: &completedAt, CreatedAt: completedAt, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environment_progression_action.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environment_progression_action.go index 40e6785a0..a33014502 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environment_progression_action.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environment_progression_action.go @@ -44,7 +44,8 @@ func (a *EnvironmentProgressionAction) Execute(ctx context.Context, trigger acti span.SetAttributes( attribute.String("trigger", string(trigger)), - attribute.String("release.id", actx.Release.ContentHash()), + attribute.String("release.id", actx.Release.Id.String()), + attribute.String("release.content_hash", actx.Release.ContentHash()), attribute.String("job.id", actx.Job.Id), attribute.String("job.status", string(actx.Job.Status)), ) diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environmentprogression_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environmentprogression_test.go index 5635dd9fd..61f492da8 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environmentprogression_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environmentprogression_test.go @@ -195,7 +195,7 @@ func TestEnvironmentProgressionEvaluator_VersionSuccessfulInDependency(t *testin completedAt := time.Now().Add(-10 * time.Minute) job := &oapi.Job{ Id: "job-1", - ReleaseId: stagingRelease.ContentHash(), + ReleaseId: stagingRelease.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-15 * time.Minute), @@ -275,7 +275,7 @@ func TestEnvironmentProgressionEvaluator_SoakTimeNotMet(t *testing.T) { completedAt := time.Now().Add(-2 * time.Minute) job := &oapi.Job{ Id: "job-1", - ReleaseId: stagingRelease.ContentHash(), + ReleaseId: stagingRelease.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-5 * time.Minute), @@ -464,7 +464,7 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_PassRateOnly(t *testing.T) completedAt1 := time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC), @@ -478,7 +478,7 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_PassRateOnly(t *testing.T) completedAt2 := time.Date(2024, 1, 1, 10, 10, 0, 0, time.UTC) // This should be the satisfiedAt job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC), @@ -492,7 +492,7 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_PassRateOnly(t *testing.T) completedAt3 := time.Date(2024, 1, 1, 10, 15, 0, 0, time.UTC) job3 := &oapi.Job{ Id: "job-3", - ReleaseId: release3.ContentHash(), + ReleaseId: release3.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 10, 0, 0, time.UTC), @@ -577,7 +577,7 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_SoakTimeOnly(t *testing.T) completedAt := mostRecentSuccess job := &oapi.Job{ Id: "job-1", - ReleaseId: stagingRelease.ContentHash(), + ReleaseId: stagingRelease.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: mostRecentSuccess.Add(-5 * time.Minute), @@ -683,7 +683,7 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_BothPassRateAndSoakTime(t * completedAt1 := passRateSatisfiedAt job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC), @@ -698,7 +698,7 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_BothPassRateAndSoakTime(t * completedAt2 := mostRecentSuccess job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 15, 0, 0, time.UTC), @@ -842,7 +842,7 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_PassRateBeforeSoakTime(t *t completedAt1 := mostRecentSuccess job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-35 * time.Minute), @@ -856,7 +856,7 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_PassRateBeforeSoakTime(t *t completedAt2 := time.Now().Add(-18 * time.Minute) // Completes before job3 job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-20 * time.Minute), @@ -873,7 +873,7 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_PassRateBeforeSoakTime(t *t completedAt3 := passRateSatisfiedAt job3 := &oapi.Job{ Id: "job-3", - ReleaseId: release3.ContentHash(), + ReleaseId: release3.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-22 * time.Minute), @@ -964,7 +964,7 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_NotSatisfied(t *testing.T) completedAt := time.Now().Add(-2 * time.Minute) job := &oapi.Job{ Id: "job-1", - ReleaseId: stagingRelease.ContentHash(), + ReleaseId: stagingRelease.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-5 * time.Minute), 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 efaea24cd..938c81895 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 @@ -184,7 +184,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentage_WithSuccesses(t *testing.T completedAt := time.Now().Add(-5 * time.Minute) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-10 * time.Minute), @@ -197,7 +197,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentage_WithSuccesses(t *testing.T // Create pending job for release2 job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusPending, CreatedAt: time.Now().Add(-3 * time.Minute), @@ -258,7 +258,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentage_AllSuccessful(t *testing.T completedAt1 := time.Now().Add(-5 * time.Minute) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-10 * time.Minute), @@ -269,7 +269,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentage_AllSuccessful(t *testing.T completedAt2 := time.Now().Add(-3 * time.Minute) job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-8 * time.Minute), @@ -339,7 +339,7 @@ func TestReleaseTargetJobTracker_MeetsSoakTimeRequirement_SoakTimeMet(t *testing completedAt := time.Now().Add(-15 * time.Minute) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-20 * time.Minute), @@ -401,7 +401,7 @@ func TestReleaseTargetJobTracker_MeetsSoakTimeRequirement_MultipleJobs(t *testin completedAt1 := time.Now().Add(-20 * time.Minute) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-25 * time.Minute), @@ -414,7 +414,7 @@ func TestReleaseTargetJobTracker_MeetsSoakTimeRequirement_MultipleJobs(t *testin completedAt2 := time.Now().Add(-5 * time.Minute) job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-10 * time.Minute), @@ -466,7 +466,7 @@ func TestReleaseTargetJobTracker_GetSoakTimeRemaining(t *testing.T) { completedAt := time.Now().Add(-5 * time.Minute) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-10 * time.Minute), @@ -526,7 +526,7 @@ func TestReleaseTargetJobTracker_GetMostRecentSuccess(t *testing.T) { completedAt := time.Now().Add(-5 * time.Minute) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-10 * time.Minute), @@ -586,7 +586,7 @@ func TestReleaseTargetJobTracker_IsWithinMaxAge_WithinAge(t *testing.T) { completedAt := time.Now().Add(-5 * time.Minute) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-10 * time.Minute), @@ -649,7 +649,7 @@ func TestReleaseTargetJobTracker_Jobs(t *testing.T) { completedAt := time.Now().Add(-5 * time.Minute) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-10 * time.Minute), @@ -659,7 +659,7 @@ func TestReleaseTargetJobTracker_Jobs(t *testing.T) { } job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusPending, CreatedAt: time.Now().Add(-3 * time.Minute), @@ -726,7 +726,7 @@ func TestReleaseTargetJobTracker_FiltersByEnvironmentAndDeployment(t *testing.T) completedAt1 := time.Now().Add(-5 * time.Minute) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-10 * time.Minute), @@ -737,7 +737,7 @@ func TestReleaseTargetJobTracker_FiltersByEnvironmentAndDeployment(t *testing.T) completedAt2 := time.Now().Add(-3 * time.Minute) job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-8 * time.Minute), @@ -794,7 +794,7 @@ func TestReleaseTargetJobTracker_MultipleJobsPerTarget_TracksOldestSuccess(t *te completedAt1 := time.Now().Add(-20 * time.Minute) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-25 * time.Minute), @@ -807,7 +807,7 @@ func TestReleaseTargetJobTracker_MultipleJobsPerTarget_TracksOldestSuccess(t *te completedAt2 := time.Now().Add(-10 * time.Minute) job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-15 * time.Minute), @@ -892,7 +892,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_Basic(t *testin completedAt1 := time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC), @@ -907,7 +907,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_Basic(t *testin completedAt2 := time.Date(2024, 1, 1, 10, 10, 0, 0, time.UTC) job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC), @@ -921,7 +921,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_Basic(t *testin completedAt3 := time.Date(2024, 1, 1, 10, 15, 0, 0, time.UTC) job3 := &oapi.Job{ Id: "job-3", - ReleaseId: release3.ContentHash(), + ReleaseId: release3.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 10, 0, 0, time.UTC), @@ -998,7 +998,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_NotEnoughSucces completedAt1 := time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC), @@ -1105,7 +1105,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_ZeroMinimumPerc completedAt1 := time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC), @@ -1116,7 +1116,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_ZeroMinimumPerc completedAt2 := time.Date(2024, 1, 1, 10, 10, 0, 0, time.UTC) job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC), @@ -1198,7 +1198,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_OutOfOrderCompl completedAt2 := time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC) job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC), @@ -1212,7 +1212,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_OutOfOrderCompl completedAt1 := time.Date(2024, 1, 1, 10, 10, 0, 0, time.UTC) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC), @@ -1226,7 +1226,7 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_OutOfOrderCompl completedAt3 := time.Date(2024, 1, 1, 10, 15, 0, 0, time.UTC) job3 := &oapi.Job{ Id: "job-3", - ReleaseId: release3.ContentHash(), + ReleaseId: release3.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 10, 0, 0, time.UTC), 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 8da342af9..ef0e634d5 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 @@ -150,7 +150,7 @@ func TestPassRateEvaluator_MeetsMinimumRequirement(t *testing.T) { completedAt1 := time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC), @@ -161,7 +161,7 @@ func TestPassRateEvaluator_MeetsMinimumRequirement(t *testing.T) { completedAt2 := time.Date(2024, 1, 1, 10, 10, 0, 0, time.UTC) job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC), @@ -279,7 +279,7 @@ func TestPassRateEvaluator_BelowMinimumRequirement(t *testing.T) { completedAt1 := time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC), @@ -397,7 +397,7 @@ func TestPassRateEvaluator_SatisfiedAt_ExactThreshold(t *testing.T) { completedAt1 := time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC), @@ -410,7 +410,7 @@ func TestPassRateEvaluator_SatisfiedAt_ExactThreshold(t *testing.T) { completedAt2 := satisfiedAtTime job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC), @@ -422,7 +422,7 @@ func TestPassRateEvaluator_SatisfiedAt_ExactThreshold(t *testing.T) { completedAt3 := time.Date(2024, 1, 1, 10, 15, 0, 0, time.UTC) job3 := &oapi.Job{ Id: "job-3", - ReleaseId: release3.ContentHash(), + ReleaseId: release3.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 10, 0, 0, time.UTC), @@ -501,7 +501,7 @@ func TestPassRateEvaluator_ZeroMinimumPercentage(t *testing.T) { completedAt := time.Date(2024, 1, 1, 10, 5, 0, 0, time.UTC) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC), @@ -602,7 +602,7 @@ func TestPassRateEvaluator_CustomSuccessStatuses(t *testing.T) { completedAt := time.Now().Add(-5 * time.Minute) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusInProgress, CreatedAt: time.Now().Add(-10 * time.Minute), diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/soaktime_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/soaktime_test.go index 654b4edc3..1718331a8 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/soaktime_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/soaktime_test.go @@ -97,7 +97,7 @@ func TestSoakTimeEvaluator_SoakTimeMet(t *testing.T) { completedAt := mostRecentSuccess job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: mostRecentSuccess.Add(-5 * time.Minute), @@ -162,7 +162,7 @@ func TestSoakTimeEvaluator_SoakTimeNotMet(t *testing.T) { completedAt := mostRecentSuccess job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: mostRecentSuccess.Add(-5 * time.Minute), @@ -222,7 +222,7 @@ func TestSoakTimeEvaluator_NoSuccessfulJobs(t *testing.T) { // Create a pending job (not successful) job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusPending, CreatedAt: time.Now(), @@ -284,7 +284,7 @@ func TestSoakTimeEvaluator_SatisfiedAt_Calculation(t *testing.T) { completedAt := mostRecentSuccess job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: mostRecentSuccess.Add(-5 * time.Minute), @@ -350,7 +350,7 @@ func TestSoakTimeEvaluator_MultipleJobs_UseMostRecent(t *testing.T) { completedAt1 := oldSuccess job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: oldSuccess.Add(-5 * time.Minute), @@ -366,7 +366,7 @@ func TestSoakTimeEvaluator_MultipleJobs_UseMostRecent(t *testing.T) { completedAt2 := mostRecentSuccess job2 := &oapi.Job{ Id: "job-2", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: mostRecentSuccess.Add(-5 * time.Minute), @@ -445,7 +445,7 @@ func TestSoakTimeEvaluator_CustomSuccessStatuses(t *testing.T) { completedAt := mostRecentSuccess job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusInProgress, CreatedAt: mostRecentSuccess.Add(-5 * time.Minute), @@ -510,7 +510,7 @@ func TestSoakTimeEvaluator_ExactlyAtThreshold(t *testing.T) { completedAt := mostRecentSuccess job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: mostRecentSuccess.Add(-5 * time.Minute), @@ -574,7 +574,7 @@ func TestSoakTimeEvaluator_NextEvaluationTime_WhenPending(t *testing.T) { completedAt := mostRecentSuccess job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: mostRecentSuccess.Add(-5 * time.Minute), @@ -641,7 +641,7 @@ func TestSoakTimeEvaluator_NextEvaluationTime_WhenSatisfied(t *testing.T) { completedAt := mostRecentSuccess job1 := &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), JobAgentId: "agent-1", Status: oapi.JobStatusSuccessful, CreatedAt: mostRecentSuccess.Add(-5 * time.Minute), diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/gradualrollout_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/gradualrollout_test.go index 6b57fc7ea..c0122552f 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/gradualrollout_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/gradualrollout_test.go @@ -93,7 +93,7 @@ func seedSuccessfulRelease(ctx context.Context, store *store.Store, releaseTarge completedAt := time.Now().Add(-23 * time.Hour) job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CompletedAt: &completedAt, CreatedAt: completedAt, @@ -953,7 +953,7 @@ func TestGradualRolloutEvaluator_EnvironmentProgressionOnly_SuccessPercentage(t completedAt := successTime.Add(time.Duration(i) * time.Minute) job := &oapi.Job{ Id: fmt.Sprintf("job-staging-%d", i), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: successTime, CompletedAt: &completedAt, @@ -1070,7 +1070,7 @@ func TestGradualRolloutEvaluator_EnvironmentProgressionOnly_SoakTime(t *testing. jobCompletedAt := baseTime.Add(1 * time.Hour) job := &oapi.Job{ Id: "job-staging-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: baseTime, CompletedAt: &jobCompletedAt, @@ -1191,7 +1191,7 @@ func TestGradualRolloutEvaluator_EnvironmentProgressionOnly_BothSuccessPercentag completedAt := successTime.Add(time.Duration(i) * time.Minute) job := &oapi.Job{ Id: fmt.Sprintf("job-staging-%d", i), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: successTime, CompletedAt: &completedAt, @@ -1429,7 +1429,7 @@ func TestGradualRolloutEvaluator_BothPolicies_BothSatisfied(t *testing.T) { completedAt := envProgTime.Add(time.Duration(i) * time.Minute) job := &oapi.Job{ Id: fmt.Sprintf("job-staging-%d", i), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: envProgTime, CompletedAt: &completedAt, @@ -1553,7 +1553,7 @@ func TestGradualRolloutEvaluator_BothPolicies_ApprovalLater(t *testing.T) { completedAt := envProgTime.Add(time.Duration(i) * time.Minute) job := &oapi.Job{ Id: fmt.Sprintf("job-staging-%d", i), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: envProgTime, CompletedAt: &completedAt, @@ -1694,7 +1694,7 @@ func TestGradualRolloutEvaluator_BothPolicies_ApprovalUnsatisfied(t *testing.T) completedAt := envProgTime.Add(time.Duration(i) * time.Minute) job := &oapi.Job{ Id: fmt.Sprintf("job-staging-%d", i), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: envProgTime, CompletedAt: &completedAt, @@ -2165,7 +2165,7 @@ func TestGradualRolloutEvaluator_EnvProgressionJustSatisfied_OnlyPosition0Allowe completedAt := stagingCompletionTime job := &oapi.Job{ Id: fmt.Sprintf("job-staging-%d", i), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: baseTime, CompletedAt: &completedAt, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go index c938171c5..ac8664782 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go @@ -87,7 +87,7 @@ func TestReleaseTargetConcurrencyEvaluator_JobInPendingState(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: existingRelease.ContentHash(), + ReleaseId: existingRelease.Id.String(), Status: oapi.JobStatusPending, CreatedAt: time.Now(), }) @@ -149,7 +149,7 @@ func TestReleaseTargetConcurrencyEvaluator_JobInProgressState(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: existingRelease.ContentHash(), + ReleaseId: existingRelease.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: time.Now(), }) @@ -203,7 +203,7 @@ func TestReleaseTargetConcurrencyEvaluator_JobInActionRequiredState(t *testing.T st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: existingRelease.ContentHash(), + ReleaseId: existingRelease.Id.String(), Status: oapi.JobStatusActionRequired, CreatedAt: time.Now(), }) @@ -269,14 +269,14 @@ func TestReleaseTargetConcurrencyEvaluator_MultipleActiveJobs(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), Status: oapi.JobStatusPending, CreatedAt: time.Now().Add(-1 * time.Hour), }) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: time.Now(), }) @@ -360,7 +360,7 @@ func TestReleaseTargetConcurrencyEvaluator_TerminalStateJobsDoNotBlock(t *testin st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-3 * time.Hour), CompletedAt: &completedAt, @@ -368,7 +368,7 @@ func TestReleaseTargetConcurrencyEvaluator_TerminalStateJobsDoNotBlock(t *testin st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-2", - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-2 * time.Hour), CompletedAt: &completedAt, @@ -376,7 +376,7 @@ func TestReleaseTargetConcurrencyEvaluator_TerminalStateJobsDoNotBlock(t *testin st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-3", - ReleaseId: release3.ContentHash(), + ReleaseId: release3.Id.String(), Status: oapi.JobStatusCancelled, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, @@ -453,7 +453,7 @@ func TestReleaseTargetConcurrencyEvaluator_DifferentReleaseTargetsDoNotInterfere st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: time.Now(), }) @@ -512,7 +512,7 @@ func TestReleaseTargetConcurrencyEvaluator_AllProcessingStatesBlock(t *testing.T st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: existingRelease.ContentHash(), + ReleaseId: existingRelease.Id.String(), Status: status, CreatedAt: time.Now(), }) @@ -586,7 +586,7 @@ func TestReleaseTargetConcurrencyEvaluator_AllTerminalStatesAllow(t *testing.T) completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: existingRelease.ContentHash(), + ReleaseId: existingRelease.Id.String(), Status: status, CreatedAt: time.Now(), CompletedAt: &completedAt, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry.go index 294065efc..3c6453e7e 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry.go @@ -116,7 +116,7 @@ func (e *RetryEvaluator) Evaluate( for _, job := range jobs { // Only count jobs for this exact release - if job.ReleaseId != release.ContentHash() { + if job.ReleaseId != release.Id.String() { break } @@ -149,7 +149,8 @@ func (e *RetryEvaluator) Evaluate( NewDeniedResult( fmt.Sprintf("Retry limit exceeded (%d/%d attempts)", attemptCount, maxRetries), ). - WithDetail("release_id", release.ContentHash()). + WithDetail("release_id", release.Id.String()). + WithDetail("release_content_hash", release.ContentHash()). WithDetail("attempt_count", attemptCount). WithDetail("max_retries", maxRetries). WithDetail("version", release.Version.Tag). @@ -171,7 +172,8 @@ func (e *RetryEvaluator) Evaluate( NewAllowedResult( fmt.Sprintf("First attempt (0/%d retries used)", maxRetries), ). - WithDetail("release_id", release.ContentHash()). + WithDetail("release_id", release.Id.String()). + WithDetail("release_content_hash", release.ContentHash()). WithDetail("max_retries", maxRetries). WithDetail("version", release.Version.Tag) } @@ -180,7 +182,8 @@ func (e *RetryEvaluator) Evaluate( NewAllowedResult( fmt.Sprintf("Retry allowed (%d/%d attempts)", attemptCount, maxRetries), ). - WithDetail("release_id", release.ContentHash()). + WithDetail("release_id", release.Id.String()). + WithDetail("release_content_hash", release.ContentHash()). WithDetail("attempt_count", attemptCount). WithDetail("max_retries", maxRetries). WithDetail("version", release.Version.Tag). @@ -246,7 +249,8 @@ func (e *RetryEvaluator) evaluateBackoff( "wait", fmt.Sprintf("Waiting for retry backoff (%ds remaining)", remainingSeconds), ). - WithDetail("release_id", release.ContentHash()). + WithDetail("release_id", release.Id.String()). + WithDetail("release_content_hash", release.ContentHash()). WithDetail("attempt_count", attemptCount). WithDetail("max_retries", int(e.rule.MaxRetries)). WithDetail("version", release.Version.Tag). diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry_test.go index e90055382..1a79bd634 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry_test.go @@ -86,7 +86,7 @@ func TestRetryEvaluator_DefaultBehavior_SecondAttemptDenied(t *testing.T) { completedAt := time.Now().Add(-1 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-2 * time.Hour), CompletedAt: &completedAt, @@ -115,7 +115,7 @@ func TestRetryEvaluator_DefaultBehavior_AllStatusesCount(t *testing.T) { completedAt := time.Now().Add(-1 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-success", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-2 * time.Hour), CompletedAt: &completedAt, @@ -159,7 +159,7 @@ func TestRetryEvaluator_MaxRetries_Zero(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now(), CompletedAt: &completedAt, @@ -191,7 +191,7 @@ func TestRetryEvaluator_MaxRetries_Three(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-" + string(rune(i)), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now(), CompletedAt: &completedAt, @@ -206,7 +206,7 @@ func TestRetryEvaluator_MaxRetries_Three(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-4", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now(), CompletedAt: &completedAt, @@ -244,7 +244,7 @@ func TestRetryEvaluator_RetryOnStatuses_OnlyCountsFailures(t *testing.T) { completedAt1 := time.Now().Add(-2 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-success", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-3 * time.Hour), CompletedAt: &completedAt1, @@ -254,7 +254,7 @@ func TestRetryEvaluator_RetryOnStatuses_OnlyCountsFailures(t *testing.T) { completedAt2 := time.Now().Add(-1 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-cancelled", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusCancelled, CreatedAt: time.Now().Add(-90 * time.Minute), CompletedAt: &completedAt2, @@ -269,7 +269,7 @@ func TestRetryEvaluator_RetryOnStatuses_OnlyCountsFailures(t *testing.T) { completedAt3 := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-failed", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now(), CompletedAt: &completedAt3, @@ -284,7 +284,7 @@ func TestRetryEvaluator_RetryOnStatuses_OnlyCountsFailures(t *testing.T) { completedAt4 := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-failed-2", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now(), CompletedAt: &completedAt4, @@ -320,7 +320,7 @@ func TestRetryEvaluator_RetryOnStatuses_MultipleStatuses(t *testing.T) { completedAt1 := time.Now().Add(-3 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-4 * time.Hour), CompletedAt: &completedAt1, @@ -329,7 +329,7 @@ func TestRetryEvaluator_RetryOnStatuses_MultipleStatuses(t *testing.T) { completedAt2 := time.Now().Add(-2 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-2", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusInvalidJobAgent, CreatedAt: time.Now().Add(-150 * time.Minute), CompletedAt: &completedAt2, @@ -343,7 +343,7 @@ func TestRetryEvaluator_RetryOnStatuses_MultipleStatuses(t *testing.T) { completedAt3 := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-3", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusExternalRunNotFound, CreatedAt: time.Now(), CompletedAt: &completedAt3, @@ -385,7 +385,7 @@ func TestRetryEvaluator_DifferentReleasesIndependent(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-r1", - ReleaseId: release1.ContentHash(), + ReleaseId: release1.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now(), CompletedAt: &completedAt, @@ -423,7 +423,7 @@ func TestRetryEvaluator_LinearBackoff_StillWaiting(t *testing.T) { completedAt := time.Now().Add(-30 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, @@ -466,7 +466,7 @@ func TestRetryEvaluator_LinearBackoff_BackoffElapsed(t *testing.T) { completedAt := time.Now().Add(-90 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-2 * time.Minute), CompletedAt: &completedAt, @@ -503,7 +503,7 @@ func TestRetryEvaluator_LinearBackoff_ConstantDelay(t *testing.T) { completedAt := time.Now().Add(-20 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-" + string(rune(i)), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Minute), CompletedAt: &completedAt, @@ -553,7 +553,7 @@ func TestRetryEvaluator_ExponentialBackoff_DoublesEachRetry(t *testing.T) { completedAt := time.Now().Add(-10 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-" + string(rune(i)), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Minute), CompletedAt: &completedAt, @@ -604,7 +604,7 @@ func TestRetryEvaluator_ExponentialBackoff_WithCap(t *testing.T) { completedAt := time.Now().Add(-5 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-" + string(rune(i)), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Minute), CompletedAt: &completedAt, @@ -641,7 +641,7 @@ func TestRetryEvaluator_NoBackoff_ImmediateRetry(t *testing.T) { completedAt := time.Now().Add(-1 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Minute), CompletedAt: &completedAt, @@ -678,7 +678,7 @@ func TestRetryEvaluator_Backoff_UsesCompletedAt(t *testing.T) { completedAt := time.Now().Add(-30 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-2 * time.Hour), CompletedAt: &completedAt, @@ -713,7 +713,7 @@ func TestRetryEvaluator_Backoff_FallsBackToCreatedAt(t *testing.T) { // Job with no completedAt (still running) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: time.Now().Add(-30 * time.Second), CompletedAt: nil, // No completion time @@ -745,7 +745,7 @@ func TestRetryEvaluator_Backoff_NextEvaluationTime(t *testing.T) { completedAt := time.Now().Add(-60 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-2 * time.Minute), CompletedAt: &completedAt, @@ -790,7 +790,7 @@ func TestRetryEvaluator_Backoff_OnlyForRetryableStatuses(t *testing.T) { completedAt1 := time.Now().Add(-5 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-success", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt1, @@ -804,7 +804,7 @@ func TestRetryEvaluator_Backoff_OnlyForRetryableStatuses(t *testing.T) { completedAt2 := time.Now().Add(-5 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-failed", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-10 * time.Second), CompletedAt: &completedAt2, @@ -844,7 +844,7 @@ func TestRetryEvaluator_VersionFlip_AllowsRedeployAfterDifferentRelease(t *testi completedAt1 := time.Now().Add(-3 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-v1-first", - ReleaseId: releaseV1.ContentHash(), + ReleaseId: releaseV1.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-4 * time.Hour), CompletedAt: &completedAt1, @@ -854,7 +854,7 @@ func TestRetryEvaluator_VersionFlip_AllowsRedeployAfterDifferentRelease(t *testi completedAt2 := time.Now().Add(-2 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-v2", - ReleaseId: releaseV2.ContentHash(), + ReleaseId: releaseV2.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-150 * time.Minute), CompletedAt: &completedAt2, @@ -891,7 +891,7 @@ func TestRetryEvaluator_VersionFlip_CountsOnlyLatestConsecutiveJobs(t *testing.T completedAt1 := time.Now().Add(-5 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-v1-old", - ReleaseId: releaseV1.ContentHash(), + ReleaseId: releaseV1.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-6 * time.Hour), CompletedAt: &completedAt1, @@ -901,7 +901,7 @@ func TestRetryEvaluator_VersionFlip_CountsOnlyLatestConsecutiveJobs(t *testing.T completedAt2 := time.Now().Add(-3 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-v2", - ReleaseId: releaseV2.ContentHash(), + ReleaseId: releaseV2.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-4 * time.Hour), CompletedAt: &completedAt2, @@ -911,7 +911,7 @@ func TestRetryEvaluator_VersionFlip_CountsOnlyLatestConsecutiveJobs(t *testing.T completedAt3 := time.Now().Add(-1 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-v1-recent", - ReleaseId: releaseV1.ContentHash(), + ReleaseId: releaseV1.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-2 * time.Hour), CompletedAt: &completedAt3, @@ -945,7 +945,7 @@ func TestRetryEvaluator_VersionFlip_DeniesWhenConsecutiveExceedsLimit(t *testing completedAt1 := time.Now().Add(-5 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-v2", - ReleaseId: releaseV2.ContentHash(), + ReleaseId: releaseV2.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-6 * time.Hour), CompletedAt: &completedAt1, @@ -955,7 +955,7 @@ func TestRetryEvaluator_VersionFlip_DeniesWhenConsecutiveExceedsLimit(t *testing completedAt2 := time.Now().Add(-2 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-v1-a", - ReleaseId: releaseV1.ContentHash(), + ReleaseId: releaseV1.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-3 * time.Hour), CompletedAt: &completedAt2, @@ -964,7 +964,7 @@ func TestRetryEvaluator_VersionFlip_DeniesWhenConsecutiveExceedsLimit(t *testing completedAt3 := time.Now().Add(-1 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-v1-b", - ReleaseId: releaseV1.ContentHash(), + ReleaseId: releaseV1.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-90 * time.Minute), CompletedAt: &completedAt3, @@ -997,22 +997,22 @@ func TestRetryEvaluator_VersionFlip_MultipleFlips(t *testing.T) { // v1 → v2 → v1 → v2 (each successful) completedAt1 := time.Now().Add(-4 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1-v1", ReleaseId: releaseV1.ContentHash(), Status: oapi.JobStatusSuccessful, + Id: "job-1-v1", ReleaseId: releaseV1.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-5 * time.Hour), CompletedAt: &completedAt1, }) completedAt2 := time.Now().Add(-3 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-2-v2", ReleaseId: releaseV2.ContentHash(), Status: oapi.JobStatusSuccessful, + Id: "job-2-v2", ReleaseId: releaseV2.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-210 * time.Minute), CompletedAt: &completedAt2, }) completedAt3 := time.Now().Add(-2 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-3-v1", ReleaseId: releaseV1.ContentHash(), Status: oapi.JobStatusSuccessful, + Id: "job-3-v1", ReleaseId: releaseV1.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-150 * time.Minute), CompletedAt: &completedAt3, }) completedAt4 := time.Now().Add(-1 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-4-v2", ReleaseId: releaseV2.ContentHash(), Status: oapi.JobStatusSuccessful, + Id: "job-4-v2", ReleaseId: releaseV2.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-90 * time.Minute), CompletedAt: &completedAt4, }) @@ -1058,7 +1058,7 @@ func TestRetryEvaluator_MultipleJobsSameRelease_FindsMostRecent(t *testing.T) { oldCompletedAt := time.Now().Add(-2 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-old", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-3 * time.Hour), CompletedAt: &oldCompletedAt, @@ -1068,7 +1068,7 @@ func TestRetryEvaluator_MultipleJobsSameRelease_FindsMostRecent(t *testing.T) { recentCompletedAt := time.Now().Add(-30 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-recent", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Minute), CompletedAt: &recentCompletedAt, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/smart_defaults_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/smart_defaults_test.go index ce7409b67..2688bea1e 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/smart_defaults_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/smart_defaults_test.go @@ -36,7 +36,7 @@ func TestRetryEvaluator_SmartDefault_OnlyCountsFailures(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1-success", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-5 * time.Minute), CompletedAt: &completedAt, @@ -50,7 +50,7 @@ func TestRetryEvaluator_SmartDefault_OnlyCountsFailures(t *testing.T) { // Add a failed job - should count st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-2-failure", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-3 * time.Minute), CompletedAt: &completedAt, @@ -81,7 +81,7 @@ func TestRetryEvaluator_SmartDefault_CountsInvalidIntegration(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1-invalid", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusInvalidIntegration, CreatedAt: time.Now().Add(-1 * time.Minute), CompletedAt: &completedAt, @@ -94,7 +94,7 @@ func TestRetryEvaluator_SmartDefault_CountsInvalidIntegration(t *testing.T) { // Add another invalidIntegration - should exceed limit st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-2-invalid", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusInvalidIntegration, CreatedAt: time.Now(), CompletedAt: &completedAt, @@ -124,14 +124,14 @@ func TestRetryEvaluator_SmartDefault_DoesNotCountCancelled(t *testing.T) { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1-cancelled", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusCancelled, CreatedAt: time.Now().Add(-5 * time.Minute), CompletedAt: &completedAt, }) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-2-cancelled", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusCancelled, CreatedAt: time.Now().Add(-3 * time.Minute), CompletedAt: &completedAt, @@ -164,7 +164,7 @@ func TestRetryEvaluator_SmartDefault_MixedStatuses(t *testing.T) { // so they must be older than the retryable ones. st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1-success", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-10 * time.Minute), CompletedAt: &completedAt, @@ -172,7 +172,7 @@ func TestRetryEvaluator_SmartDefault_MixedStatuses(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-2-cancelled", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusCancelled, CreatedAt: time.Now().Add(-8 * time.Minute), CompletedAt: &completedAt, @@ -180,7 +180,7 @@ func TestRetryEvaluator_SmartDefault_MixedStatuses(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-3-skipped", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSkipped, CreatedAt: time.Now().Add(-6 * time.Minute), CompletedAt: &completedAt, @@ -189,7 +189,7 @@ func TestRetryEvaluator_SmartDefault_MixedStatuses(t *testing.T) { // Retryable jobs (most recent consecutive) — only these count st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-4-failure", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-4 * time.Minute), CompletedAt: &completedAt, @@ -197,7 +197,7 @@ func TestRetryEvaluator_SmartDefault_MixedStatuses(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-5-invalid", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusInvalidIntegration, CreatedAt: time.Now().Add(-2 * time.Minute), CompletedAt: &completedAt, @@ -211,7 +211,7 @@ func TestRetryEvaluator_SmartDefault_MixedStatuses(t *testing.T) { // Add one more failure - should exceed st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-6-failure", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now(), CompletedAt: &completedAt, @@ -247,7 +247,7 @@ func TestRetryEvaluator_ExplicitStatuses_OverridesSmartDefault(t *testing.T) { // Add a failure - should NOT count (only cancelled counts) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1-failure", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-5 * time.Minute), CompletedAt: &completedAt, @@ -260,7 +260,7 @@ func TestRetryEvaluator_ExplicitStatuses_OverridesSmartDefault(t *testing.T) { // Add cancelled job - should count st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-2-cancelled", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusCancelled, CreatedAt: time.Now(), CompletedAt: &completedAt, @@ -293,7 +293,7 @@ func TestRetryEvaluator_ZeroMaxRetries_CountsSuccessfulAndErrors(t *testing.T) { // Add a successful job - should count (strict mode: successful counts for maxRetries=0) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1-success", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now(), CompletedAt: &completedAt, @@ -326,7 +326,7 @@ func TestRetryEvaluator_ZeroMaxRetries_AllowsAfterCancelled(t *testing.T) { // Add a cancelled job - should NOT count st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1-cancelled", - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusCancelled, CreatedAt: time.Now(), CompletedAt: &completedAt, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/rollback/rollback_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/rollback/rollback_test.go index 096d1f579..896534660 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/rollback/rollback_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/rollback/rollback_test.go @@ -92,7 +92,7 @@ func createJob(t *testing.T, s *store.Store, ctx context.Context, e testEntities completedAt := createdAt.Add(30 * time.Second) job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: status, CreatedAt: createdAt, } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/version_summary_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/version_summary_test.go index 3d64b70d3..61a9ec51d 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/version_summary_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/version_summary_test.go @@ -159,7 +159,7 @@ func TestSummaryEvaluator_SomeTargetsDenied(t *testing.T) { completedAt := time.Now().Add(-5 * time.Second) job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CompletedAt: &completedAt, CreatedAt: completedAt, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/versioncooldown_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/versioncooldown_test.go index 699b2a2a6..e05e69acb 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/versioncooldown_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/versioncooldown_test.go @@ -88,7 +88,7 @@ func createSuccessfulJob(ctx context.Context, s *store.Store, release *oapi.Rele completedAt := time.Now() job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CompletedAt: &completedAt, CreatedAt: time.Now(), @@ -426,7 +426,7 @@ func TestVersionCooldownEvaluator_Evaluate(t *testing.T) { // Create in-progress job (no completedAt) inProgressJob := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release2.ContentHash(), + ReleaseId: release2.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: time.Now(), } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/state_index_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/state_index_test.go index 5e4eb4f5b..97dbccbe4 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/state_index_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/state_index_test.go @@ -90,7 +90,7 @@ func TestRestoreAll_ComputesLatestJob(t *testing.T) { now := time.Now() job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: now, UpdatedAt: now, @@ -175,7 +175,7 @@ func TestGetReleaseTargetState_AfterRestore(t *testing.T) { now := time.Now() job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusPending, CreatedAt: now, UpdatedAt: now, @@ -228,7 +228,7 @@ func TestRecomputeEntity_RefreshesAfterRestore(t *testing.T) { now := time.Now() job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusInProgress, CreatedAt: now, UpdatedAt: now, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/verification/executor_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/verification/executor_test.go index afd032a3b..4b0db5f81 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/verification/executor_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/verification/executor_test.go @@ -38,7 +38,7 @@ func TestExecutor_Execute_Success(t *testing.T) { metric := createHTTPMetricStatus(server.URL) // Execute measurement with direct objects - measurement, err := executor.Execute(ctx, &metric, release.ContentHash()) + measurement, err := executor.Execute(ctx, &metric, release.Id.String()) require.NoError(t, err) assert.Equal(t, oapi.Passed, measurement.Status) @@ -78,7 +78,7 @@ func TestExecutor_Execute_FailedMeasurement(t *testing.T) { // Execute measurement - should not error but should fail // (success condition not met, no failure condition = binary pass/fail) - measurement, err := executor.Execute(ctx, &metric, release.ContentHash()) + measurement, err := executor.Execute(ctx, &metric, release.Id.String()) require.NoError(t, err) assert.Equal(t, oapi.Failed, measurement.Status) @@ -103,7 +103,7 @@ func TestExecutor_Execute_ContextCancellation(t *testing.T) { metric := createHTTPMetricStatus(server.URL) // Execute should fail due to context timeout - _, err := executor.Execute(ctx, &metric, release.ContentHash()) + _, err := executor.Execute(ctx, &metric, release.Id.String()) assert.Error(t, err) } @@ -125,7 +125,7 @@ func TestExecutor_Execute_WithTemplatedURL(t *testing.T) { metric := createHTTPMetricStatus(server.URL + "/{{.release.version.tag}}") // Execute - template should be resolved - measurement, err := executor.Execute(ctx, &metric, release.ContentHash()) + measurement, err := executor.Execute(ctx, &metric, release.Id.String()) require.NoError(t, err) assert.Equal(t, oapi.Passed, measurement.Status) @@ -138,7 +138,7 @@ func TestExecutor_BuildProviderContext_Success(t *testing.T) { release := createTestRelease(s, ctx) - providerCtx, err := executor.BuildProviderContext(release.ContentHash()) + providerCtx, err := executor.BuildProviderContext(release.Id.String()) require.NoError(t, err) require.NotNil(t, providerCtx) @@ -181,7 +181,7 @@ func TestExecutor_BuildProviderContext_WithVariables(t *testing.T) { } _ = s.Releases.Upsert(ctx, release) - providerCtx, err := executor.BuildProviderContext(release.ContentHash()) + providerCtx, err := executor.BuildProviderContext(release.Id.String()) require.NoError(t, err) require.NotNil(t, providerCtx) diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/verification/manager_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/verification/manager_test.go index 542f2c94d..0ecc44ce9 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/verification/manager_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/verification/manager_test.go @@ -37,7 +37,7 @@ func TestManager_StartVerification_Success(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) // Create metric specs using test server metrics := []oapi.VerificationMetricSpec{ @@ -87,7 +87,7 @@ func TestManager_StartVerification_MultipleMetrics(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) metrics := []oapi.VerificationMetricSpec{ { @@ -131,7 +131,7 @@ func TestManager_StartVerification_AlreadyExists(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) metrics := []oapi.VerificationMetricSpec{ { @@ -173,7 +173,7 @@ func TestManager_StartVerification_NoMetrics(t *testing.T) { manager := NewManager(s) release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) // Try to start with empty metrics err := manager.StartVerification(ctx, job, []oapi.VerificationMetricSpec{}) @@ -196,7 +196,7 @@ func TestManager_StartVerification_WithFailureLimit(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) failureLimit := 3 metrics := []oapi.VerificationMetricSpec{ @@ -234,7 +234,7 @@ func TestManager_StopVerification_Success(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) metrics := []oapi.VerificationMetricSpec{ { @@ -305,11 +305,11 @@ func TestManager_Restore_RunningVerifications(t *testing.T) { // Create some releases, jobs, and verifications in running state release1 := createTestRelease(s, ctx) - job1 := createTestJob(s, ctx, release1.ContentHash()) + job1 := createTestJob(s, ctx, release1.Id.String()) release2 := createTestRelease(s, ctx) - job2 := createTestJob(s, ctx, release2.ContentHash()) + job2 := createTestJob(s, ctx, release2.Id.String()) release3 := createTestRelease(s, ctx) - job3 := createTestJob(s, ctx, release3.ContentHash()) + job3 := createTestJob(s, ctx, release3.Id.String()) verification1 := createTestVerification(s, ctx, job1.Id, 2, 3600) verification2 := createTestVerification(s, ctx, job2.Id, 1, 300) @@ -367,7 +367,7 @@ func TestManager_Restore_FailedVerifications(t *testing.T) { manager := NewManager(s) release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) verification := createTestVerification(s, ctx, job.Id, 1, 30) // Make verification failed by exceeding failure limit @@ -404,11 +404,11 @@ func TestManager_Restore_MixedStates(t *testing.T) { // Create verifications in different states runningRelease := createTestRelease(s, ctx) - runningJob := createTestJob(s, ctx, runningRelease.ContentHash()) + runningJob := createTestJob(s, ctx, runningRelease.Id.String()) passedRelease := createTestRelease(s, ctx) - passedJob := createTestJob(s, ctx, passedRelease.ContentHash()) + passedJob := createTestJob(s, ctx, passedRelease.Id.String()) failedRelease := createTestRelease(s, ctx) - failedJob := createTestJob(s, ctx, failedRelease.ContentHash()) + failedJob := createTestJob(s, ctx, failedRelease.Id.String()) runningVerification := createTestVerification(s, ctx, runningJob.Id, 1, 3600) @@ -480,7 +480,7 @@ func TestManager_StartAndStopMultiple(t *testing.T) { jobs := make([]*oapi.Job, 5) for i := 0; i < 5; i++ { release := createTestRelease(s, ctx) - jobs[i] = createTestJob(s, ctx, release.ContentHash()) + jobs[i] = createTestJob(s, ctx, release.Id.String()) err := manager.StartVerification(ctx, jobs[i], metrics) require.NoError(t, err) } @@ -513,7 +513,7 @@ func TestManager_StartVerification_PreservesAllMetricFields(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) method := oapi.POST timeout := "10s" @@ -583,7 +583,7 @@ func TestManager_Integration_FullLifecycle(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) metrics := []oapi.VerificationMetricSpec{ { @@ -646,7 +646,7 @@ func BenchmarkManager_StartVerification(b *testing.B) { jobs := make([]*oapi.Job, b.N) for i := 0; i < b.N; i++ { release := createTestRelease(s, ctx) - jobs[i] = createTestJob(s, ctx, release.ContentHash()) + jobs[i] = createTestJob(s, ctx, release.Id.String()) } b.ResetTimer() @@ -686,7 +686,7 @@ func BenchmarkManager_StopVerification(b *testing.B) { jobs := make([]*oapi.Job, b.N) for i := 0; i < b.N; i++ { release := createTestRelease(s, ctx) - jobs[i] = createTestJob(s, ctx, release.ContentHash()) + jobs[i] = createTestJob(s, ctx, release.Id.String()) _ = manager.StartVerification(ctx, jobs[i], metrics) } @@ -706,7 +706,7 @@ func BenchmarkManager_Restore(b *testing.B) { // Create 10 running verifications per store for j := 0; j < 10; j++ { release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) createTestVerification(s, ctx, job.Id, 2, 3600) } stores[i] = s @@ -848,7 +848,7 @@ func TestManager_HooksOnVerificationStarted(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) metrics := []oapi.VerificationMetricSpec{ { @@ -889,7 +889,7 @@ func TestManager_HooksOnVerificationStopped(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) metrics := []oapi.VerificationMetricSpec{ { @@ -930,7 +930,7 @@ func TestManager_HooksOnMeasurementTaken(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) metrics := []oapi.VerificationMetricSpec{ { @@ -978,7 +978,7 @@ func TestManager_HooksOnMetricComplete(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) // Use a very short interval, low count, and short timeout to complete quickly metrics := []oapi.VerificationMetricSpec{ @@ -1027,7 +1027,7 @@ func TestManager_HooksOnVerificationComplete(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) // Use a very short interval, low count, and short timeout to complete quickly metrics := []oapi.VerificationMetricSpec{ @@ -1083,7 +1083,7 @@ func TestManager_HooksErrorsDontFailVerification(t *testing.T) { manager := NewManager(s, WithHooks(hooks)) release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) metrics := []oapi.VerificationMetricSpec{ { @@ -1125,7 +1125,7 @@ func TestManager_HooksWithMultipleMetrics(t *testing.T) { defer ts.Close() release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) // Create multiple metrics metrics := []oapi.VerificationMetricSpec{ diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/verification/recorder_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/verification/recorder_test.go index 32fcc1031..910b0e6e5 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/verification/recorder_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/verification/recorder_test.go @@ -27,7 +27,7 @@ func TestRecorder_RecordMeasurement_Success(t *testing.T) { recorder := NewMeasurementRecorder(s) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 1, 60) + verification := createTestVerification(s, ctx, release.Id.String(), 1, 60) // Record a measurement measurement := oapi.VerificationMeasurement{ @@ -68,7 +68,7 @@ func TestRecorder_RecordMeasurement_MetricIndexOutOfRange(t *testing.T) { recorder := NewMeasurementRecorder(s) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 1, 60) + verification := createTestVerification(s, ctx, release.Id.String(), 1, 60) measurement := oapi.VerificationMeasurement{ Status: oapi.Passed, @@ -87,7 +87,7 @@ func TestRecorder_RecordMeasurement_MultipleMeasurements(t *testing.T) { recorder := NewMeasurementRecorder(s) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 1, 60) + verification := createTestVerification(s, ctx, release.Id.String(), 1, 60) // Record multiple measurements for i := 0; i < 5; i++ { @@ -116,7 +116,7 @@ func TestRecorder_RecordMeasurement_MultipleMetrics(t *testing.T) { recorder := NewMeasurementRecorder(s) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 3, 60) + verification := createTestVerification(s, ctx, release.Id.String(), 3, 60) // Record measurement for each metric for i := 0; i < 3; i++ { @@ -143,7 +143,7 @@ func TestRecorder_RecordError_Success(t *testing.T) { recorder := NewMeasurementRecorder(s) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 1, 60) + verification := createTestVerification(s, ctx, release.Id.String(), 1, 60) // Record an error testError := errors.New("connection timeout") @@ -180,7 +180,7 @@ func TestRecorder_UpdateMessage_Success(t *testing.T) { recorder := NewMeasurementRecorder(s) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 1, 60) + verification := createTestVerification(s, ctx, release.Id.String(), 1, 60) // Update message testMessage := "Verification completed: 5/5 measurements passed" @@ -212,7 +212,7 @@ func TestRecorder_ConcurrentRecordMeasurements(t *testing.T) { recorder := NewMeasurementRecorder(s) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 1, 60) + verification := createTestVerification(s, ctx, release.Id.String(), 1, 60) // Record measurements concurrently var wg sync.WaitGroup @@ -246,7 +246,7 @@ func TestRecorder_ConcurrentRecordAndUpdate(t *testing.T) { recorder := NewMeasurementRecorder(s) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 3, 60) + verification := createTestVerification(s, ctx, release.Id.String(), 3, 60) var wg sync.WaitGroup @@ -294,7 +294,7 @@ func TestRecorder_AppendMeasurement_PreservesExistingMeasurements(t *testing.T) recorder := NewMeasurementRecorder(s) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 2, 60) + verification := createTestVerification(s, ctx, release.Id.String(), 2, 60) // Record first measurement measurement1 := oapi.VerificationMeasurement{ diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/verification/scheduler_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/verification/scheduler_test.go index 259cfe23b..4eac0fcaa 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/verification/scheduler_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/verification/scheduler_test.go @@ -177,7 +177,7 @@ func createTestRelease(s *store.Store, ctx context.Context) *oapi.Release { func createTestReleaseAndJob(s *store.Store, ctx context.Context) (*oapi.Release, *oapi.Job) { release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) return release, job } @@ -269,7 +269,7 @@ func TestScheduler_StartVerification_AlreadyRunning(t *testing.T) { scheduler := newScheduler(s, DefaultHooks()) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 1, 3600) + verification := createTestVerification(s, ctx, release.Id.String(), 1, 3600) // Start verification first time scheduler.StartVerification(ctx, verification.Id) @@ -300,7 +300,7 @@ func TestScheduler_StartVerification_AlreadyCompleted(t *testing.T) { scheduler := newScheduler(s, DefaultHooks()) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 1, 3600) + verification := createTestVerification(s, ctx, release.Id.String(), 1, 3600) // Mark all metrics as complete by adding measurements for i := range verification.Metrics { @@ -330,7 +330,7 @@ func TestScheduler_StartVerification_Success(t *testing.T) { scheduler := newScheduler(s, DefaultHooks()) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 3, 3600) + verification := createTestVerification(s, ctx, release.Id.String(), 3, 3600) scheduler.StartVerification(ctx, verification.Id) @@ -350,7 +350,7 @@ func TestScheduler_StopVerification(t *testing.T) { scheduler := newScheduler(s, DefaultHooks()) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 2, 3600) + verification := createTestVerification(s, ctx, release.Id.String(), 2, 3600) scheduler.StartVerification(ctx, verification.Id) @@ -385,7 +385,7 @@ func TestScheduler_StopVerification_MultipleTimes(t *testing.T) { scheduler := newScheduler(s, DefaultHooks()) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 1, 3600) + verification := createTestVerification(s, ctx, release.Id.String(), 1, 3600) scheduler.StartVerification(ctx, verification.Id) scheduler.StopVerification(verification.Id) @@ -405,7 +405,7 @@ func TestScheduler_ConcurrentStartStop(t *testing.T) { verificationIDs := make([]string, 10) for i := 0; i < 10; i++ { release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 2, 3600) + verification := createTestVerification(s, ctx, release.Id.String(), 2, 3600) verificationIDs[i] = verification.Id } @@ -452,7 +452,7 @@ func TestScheduler_MultipleMetrics(t *testing.T) { release := createTestRelease(s, ctx) // Create verification with 5 metrics - verification := createTestVerification(s, ctx, release.ContentHash(), 5, 3600) + verification := createTestVerification(s, ctx, release.Id.String(), 5, 3600) scheduler.StartVerification(ctx, verification.Id) @@ -472,7 +472,7 @@ func TestScheduler_RestartAfterStop(t *testing.T) { scheduler := newScheduler(s, DefaultHooks()) release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 2, 3600) + verification := createTestVerification(s, ctx, release.Id.String(), 2, 3600) // Start, stop, start again scheduler.StartVerification(ctx, verification.Id) @@ -504,7 +504,7 @@ func TestScheduler_VerificationWithNoMetrics(t *testing.T) { scheduler := newScheduler(s, DefaultHooks()) release := createTestRelease(s, ctx) - job := createTestJob(s, ctx, release.ContentHash()) + job := createTestJob(s, ctx, release.Id.String()) verification := &oapi.JobVerification{ Id: uuid.New().String(), @@ -708,7 +708,7 @@ func BenchmarkScheduler_StartVerification(b *testing.B) { verificationIDs := make([]string, b.N) for i := 0; i < b.N; i++ { release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 2, 3600) + verification := createTestVerification(s, ctx, release.Id.String(), 2, 3600) verificationIDs[i] = verification.Id } @@ -732,7 +732,7 @@ func BenchmarkScheduler_StopVerification(b *testing.B) { verificationIDs := make([]string, b.N) for i := 0; i < b.N; i++ { release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 2, 3600) + verification := createTestVerification(s, ctx, release.Id.String(), 2, 3600) verificationIDs[i] = verification.Id scheduler.StartVerification(ctx, verification.Id) } @@ -752,7 +752,7 @@ func BenchmarkScheduler_ConcurrentOperations(b *testing.B) { verificationIDs := make([]string, 100) for i := 0; i < 100; i++ { release := createTestRelease(s, ctx) - verification := createTestVerification(s, ctx, release.ContentHash(), 2, 3600) + verification := createTestVerification(s, ctx, release.Id.String(), 2, 3600) verificationIDs[i] = verification.Id } diff --git a/apps/workspace-engine/pkg/workspace/store/jobs.go b/apps/workspace-engine/pkg/workspace/store/jobs.go index 13bb38239..644c895ce 100644 --- a/apps/workspace-engine/pkg/workspace/store/jobs.go +++ b/apps/workspace-engine/pkg/workspace/store/jobs.go @@ -81,7 +81,7 @@ func (j *Jobs) GetJobsForReleaseTarget(releaseTarget *oapi.ReleaseTarget) map[st } for _, release := range releases { - releaseJobs := j.store.Releases.Jobs(release.ContentHash()) + releaseJobs := j.store.Releases.Jobs(release.Id.String()) for _, job := range releaseJobs { jobs[job.Id] = job } diff --git a/apps/workspace-engine/pkg/workspace/store/release_targets_test.go b/apps/workspace-engine/pkg/workspace/store/release_targets_test.go index 56c6747b1..d19134e68 100644 --- a/apps/workspace-engine/pkg/workspace/store/release_targets_test.go +++ b/apps/workspace-engine/pkg/workspace/store/release_targets_test.go @@ -93,7 +93,7 @@ func createTestReleaseAndJob(s *store.Store, ctx context.Context, tag string, co // Create job job := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: completedAt.Add(-1 * time.Minute), CompletedAt: &completedAt, @@ -204,6 +204,7 @@ func TestGetCurrentRelease_NoVerification(t *testing.T) { require.NoError(t, err) require.NotNil(t, currentRelease) require.NotNil(t, currentJob) + assert.Equal(t, release.Id.String(), currentRelease.Id.String()) assert.Equal(t, release.ContentHash(), currentRelease.ContentHash()) assert.Equal(t, oapi.JobStatusSuccessful, currentJob.Status) } @@ -228,6 +229,7 @@ func TestGetCurrentRelease_PassedVerification(t *testing.T) { require.NoError(t, err) require.NotNil(t, currentRelease) require.NotNil(t, currentJob) + assert.Equal(t, release.Id.String(), currentRelease.Id.String()) assert.Equal(t, release.ContentHash(), currentRelease.ContentHash()) } @@ -294,7 +296,7 @@ func TestGetCurrentRelease_FailedVerification_FallbackToPrevious(t *testing.T) { olderJobCompletedAt := time.Now().Add(-1 * time.Hour) olderJob := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: olderRelease.ContentHash(), + ReleaseId: olderRelease.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: olderJobCompletedAt.Add(-1 * time.Minute), CompletedAt: &olderJobCompletedAt, @@ -325,7 +327,7 @@ func TestGetCurrentRelease_FailedVerification_FallbackToPrevious(t *testing.T) { newerJobCompletedAt := time.Now() newerJob := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: newerRelease.ContentHash(), + ReleaseId: newerRelease.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: newerJobCompletedAt.Add(-1 * time.Minute), CompletedAt: &newerJobCompletedAt, @@ -342,6 +344,7 @@ func TestGetCurrentRelease_FailedVerification_FallbackToPrevious(t *testing.T) { require.NoError(t, err) require.NotNil(t, currentRelease) require.NotNil(t, currentJob) + assert.Equal(t, olderRelease.Id.String(), currentRelease.Id.String()) assert.Equal(t, olderRelease.ContentHash(), currentRelease.ContentHash()) assert.Equal(t, "v1.0.0", currentRelease.Version.Tag) } @@ -409,7 +412,7 @@ func TestGetCurrentRelease_RunningVerification_FallbackToPrevious(t *testing.T) olderJobCompletedAt := time.Now().Add(-1 * time.Hour) olderJob := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: olderRelease.ContentHash(), + ReleaseId: olderRelease.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: olderJobCompletedAt.Add(-1 * time.Minute), CompletedAt: &olderJobCompletedAt, @@ -440,7 +443,7 @@ func TestGetCurrentRelease_RunningVerification_FallbackToPrevious(t *testing.T) newerJobCompletedAt := time.Now() newerJob := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: newerRelease.ContentHash(), + ReleaseId: newerRelease.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: newerJobCompletedAt.Add(-1 * time.Minute), CompletedAt: &newerJobCompletedAt, @@ -457,6 +460,7 @@ func TestGetCurrentRelease_RunningVerification_FallbackToPrevious(t *testing.T) require.NoError(t, err) require.NotNil(t, currentRelease) require.NotNil(t, currentJob) + assert.Equal(t, olderRelease.Id.String(), currentRelease.Id.String()) assert.Equal(t, olderRelease.ContentHash(), currentRelease.ContentHash()) assert.Equal(t, "v1.0.0", currentRelease.Version.Tag) } @@ -551,7 +555,7 @@ func TestGetCurrentRelease_CancelledVerification_FallbackToPrevious(t *testing.T olderJobCompletedAt := time.Now().Add(-1 * time.Hour) olderJob := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: olderRelease.ContentHash(), + ReleaseId: olderRelease.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: olderJobCompletedAt.Add(-1 * time.Minute), CompletedAt: &olderJobCompletedAt, @@ -579,7 +583,7 @@ func TestGetCurrentRelease_CancelledVerification_FallbackToPrevious(t *testing.T newerJobCompletedAt := time.Now() newerJob := &oapi.Job{ Id: uuid.New().String(), - ReleaseId: newerRelease.ContentHash(), + ReleaseId: newerRelease.Id.String(), Status: oapi.JobStatusSuccessful, CreatedAt: newerJobCompletedAt.Add(-1 * time.Minute), CompletedAt: &newerJobCompletedAt, @@ -597,6 +601,7 @@ func TestGetCurrentRelease_CancelledVerification_FallbackToPrevious(t *testing.T require.NoError(t, err) require.NotNil(t, currentRelease) require.NotNil(t, currentJob) + assert.Equal(t, olderRelease.Id.String(), currentRelease.Id.String()) assert.Equal(t, olderRelease.ContentHash(), currentRelease.ContentHash()) assert.Equal(t, "v1.0.0", currentRelease.Version.Tag) } diff --git a/apps/workspace-engine/pkg/workspace/store/releases.go b/apps/workspace-engine/pkg/workspace/store/releases.go index 4d4af4a97..491899243 100644 --- a/apps/workspace-engine/pkg/workspace/store/releases.go +++ b/apps/workspace-engine/pkg/workspace/store/releases.go @@ -29,6 +29,7 @@ func (r *Releases) Upsert(ctx context.Context, release *oapi.Release) error { if release.Id == uuid.Nil { release.Id = uuid.NewSHA1(uuid.NameSpaceOID, []byte(release.ContentHash())) } + if err := r.repo.Set(release); err != nil { return err } diff --git a/apps/workspace-engine/pkg/workspace/store/repository/db/releases/repo.go b/apps/workspace-engine/pkg/workspace/store/repository/db/releases/repo.go index a83c4a45e..01a269ddc 100644 --- a/apps/workspace-engine/pkg/workspace/store/repository/db/releases/repo.go +++ b/apps/workspace-engine/pkg/workspace/store/repository/db/releases/repo.go @@ -44,7 +44,10 @@ func (r *Repo) fetchOapiRelease(row db.Release) (*oapi.Release, error) { } func (r *Repo) Get(id string) (*oapi.Release, bool) { - uid := uuid.NewSHA1(uuid.NameSpaceOID, []byte(id)) + uid, err := uuid.Parse(id) + if err != nil { + uid = uuid.NewSHA1(uuid.NameSpaceOID, []byte(id)) + } row, err := db.GetQueries(r.ctx).GetReleaseByID(r.ctx, uid) if err != nil { @@ -134,7 +137,10 @@ func (r *Repo) Set(entity *oapi.Release) error { } func (r *Repo) Remove(id string) error { - uid := uuid.NewSHA1(uuid.NameSpaceOID, []byte(id)) + uid, err := uuid.Parse(id) + if err != nil { + uid = uuid.NewSHA1(uuid.NameSpaceOID, []byte(id)) + } if err := db.GetQueries(r.ctx).DeleteReleaseVariablesByReleaseID(r.ctx, uid); err != nil { return fmt.Errorf("delete release variables: %w", err) @@ -165,7 +171,7 @@ func (r *Repo) Items() map[string]*oapi.Release { log.Warn("Failed to assemble release", "release_id", row.ID, "error", err) continue } - result[release.ContentHash()] = release + result[release.Id.String()] = release } return result diff --git a/apps/workspace-engine/pkg/workspace/store/repository/memory/indexstore/schema_release.go b/apps/workspace-engine/pkg/workspace/store/repository/memory/indexstore/schema_release.go index 4ac7fbd11..8f5f53f37 100644 --- a/apps/workspace-engine/pkg/workspace/store/repository/memory/indexstore/schema_release.go +++ b/apps/workspace-engine/pkg/workspace/store/repository/memory/indexstore/schema_release.go @@ -30,7 +30,7 @@ func (r *ReleaseIDIndexer) FromObject(obj any) (bool, []byte, error) { if !ok { return false, nil, fmt.Errorf("expected *oapi.Release, got %T", obj) } - id := release.ContentHash() + id := release.Id.String() return true, []byte(id + "\x00"), nil } diff --git a/apps/workspace-engine/pkg/workspace/store/restore_test.go b/apps/workspace-engine/pkg/workspace/store/restore_test.go index 29382f381..3dd4ae2ec 100644 --- a/apps/workspace-engine/pkg/workspace/store/restore_test.go +++ b/apps/workspace-engine/pkg/workspace/store/restore_test.go @@ -1057,3 +1057,127 @@ func TestStore_Restore_DuplicateIDs(t *testing.T) { assert.Equal(t, "resource-second", restoredResource.Name, "Last write should win") assert.Equal(t, "docker", restoredResource.Kind) } + +func TestStore_Restore_ReleaseIdBackfill(t *testing.T) { + ctx := context.Background() + namespace := "workspace-" + uuid.New().String() + + persistenceStore := memory.NewStore() + + deploymentId := uuid.New().String() + version := &oapi.DeploymentVersion{ + Id: uuid.New().String(), + DeploymentId: deploymentId, + Tag: "v1.0.0", + } + + release := &oapi.Release{ + ReleaseTarget: oapi.ReleaseTarget{ + ResourceId: uuid.New().String(), + EnvironmentId: uuid.New().String(), + DeploymentId: deploymentId, + }, + Version: *version, + Variables: map[string]oapi.LiteralValue{}, + EncryptedVariables: []string{}, + CreatedAt: time.Now().Format(time.RFC3339), + } + + changes := persistence.NewChangesBuilder(namespace). + Set(release). + Build() + + err := persistenceStore.Save(ctx, changes) + require.NoError(t, err) + + loadedChanges, err := persistenceStore.Load(ctx, namespace) + require.NoError(t, err) + + testStore := store.New("test-workspace", statechange.NewChangeSet[any]()) + err = testStore.Restore(ctx, loadedChanges, nil) + require.NoError(t, err) + + releases := testStore.Releases.Items() + require.Len(t, releases, 1) + + for _, r := range releases { + assert.NotEqual(t, uuid.Nil, r.Id, "Release should have a non-nil Id after restore") + expectedUUID := uuid.NewSHA1(uuid.NameSpaceOID, []byte(r.ContentHash())) + assert.Equal(t, expectedUUID, r.Id, "Release Id should be deterministic UUID from content hash") + } +} + +func TestStore_Restore_JobReleaseIdMigration(t *testing.T) { + ctx := context.Background() + namespace := "workspace-" + uuid.New().String() + + persistenceStore := memory.NewStore() + + contentHash := "abc123def456abc123def456abc123def456abc123def456abc123def456abcd" + expectedUUID := uuid.NewSHA1(uuid.NameSpaceOID, []byte(contentHash)).String() + + job := &oapi.Job{ + Id: uuid.New().String(), + ReleaseId: contentHash, + Status: oapi.JobStatusSuccessful, + JobAgentId: uuid.New().String(), + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + changes := persistence.NewChangesBuilder(namespace). + Set(job). + Build() + + err := persistenceStore.Save(ctx, changes) + require.NoError(t, err) + + loadedChanges, err := persistenceStore.Load(ctx, namespace) + require.NoError(t, err) + + testStore := store.New("test-workspace", statechange.NewChangeSet[any]()) + err = testStore.Restore(ctx, loadedChanges, nil) + require.NoError(t, err) + + restoredJob, ok := testStore.Jobs.Get(job.Id) + require.True(t, ok, "Job should be restored") + assert.Equal(t, expectedUUID, restoredJob.ReleaseId, + "Job ReleaseId should be migrated from content hash to deterministic UUID") +} + +func TestStore_Restore_JobReleaseIdAlreadyUUID(t *testing.T) { + ctx := context.Background() + namespace := "workspace-" + uuid.New().String() + + persistenceStore := memory.NewStore() + + releaseUUID := uuid.New().String() + + job := &oapi.Job{ + Id: uuid.New().String(), + ReleaseId: releaseUUID, + Status: oapi.JobStatusPending, + JobAgentId: uuid.New().String(), + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + changes := persistence.NewChangesBuilder(namespace). + Set(job). + Build() + + err := persistenceStore.Save(ctx, changes) + require.NoError(t, err) + + loadedChanges, err := persistenceStore.Load(ctx, namespace) + require.NoError(t, err) + + testStore := store.New("test-workspace", statechange.NewChangeSet[any]()) + err = testStore.Restore(ctx, loadedChanges, nil) + require.NoError(t, err) + + restoredJob, ok := testStore.Jobs.Get(job.Id) + require.True(t, ok, "Job should be restored") + assert.Equal(t, releaseUUID, restoredJob.ReleaseId, + "Job ReleaseId that is already a UUID should not be changed") +} diff --git a/apps/workspace-engine/pkg/workspace/store/store.go b/apps/workspace-engine/pkg/workspace/store/store.go index 5d49518d6..8fcb57535 100644 --- a/apps/workspace-engine/pkg/workspace/store/store.go +++ b/apps/workspace-engine/pkg/workspace/store/store.go @@ -10,6 +10,7 @@ import ( "workspace-engine/pkg/workspace/store/repository/memory" "github.com/charmbracelet/log" + "github.com/google/uuid" "go.opentelemetry.io/otel/attribute" ) @@ -461,12 +462,32 @@ func (s *Store) Restore(ctx context.Context, changes persistence.Changes, setSta setStatus("Migrating legacy releases") } for _, rel := range s.repo.Releases().Items() { + if rel.Id == uuid.Nil { + rel.Id = uuid.NewSHA1(uuid.NameSpaceOID, []byte(rel.ContentHash())) + } if err := s.Releases.repo.Set(rel); err != nil { log.Warn("Failed to migrate legacy release", "content_hash", rel.ContentHash(), "error", err) } } + if setStatus != nil { + setStatus("Migrating legacy job release IDs") + } + for _, job := range s.repo.Jobs.Items() { + if job.ReleaseId == "" { + continue + } + if _, err := uuid.Parse(job.ReleaseId); err == nil { + continue + } + job.ReleaseId = uuid.NewSHA1(uuid.NameSpaceOID, []byte(job.ReleaseId)).String() + if err := s.Jobs.repo.Set(job); err != nil { + log.Warn("Failed to migrate legacy job release ID", + "job_id", job.Id, "error", err) + } + } + if setStatus != nil { setStatus("Computing release targets") } diff --git a/apps/workspace-engine/svc/controllers/desiredrelease/reconcile.go b/apps/workspace-engine/svc/controllers/desiredrelease/reconcile.go index 0c1ebc606..6bec0b7cd 100644 --- a/apps/workspace-engine/svc/controllers/desiredrelease/reconcile.go +++ b/apps/workspace-engine/svc/controllers/desiredrelease/reconcile.go @@ -71,7 +71,8 @@ func Reconcile(ctx context.Context, getter Getter, setter Setter, rt *ReleaseTar } span.SetAttributes( - attribute.String("release.id", release.ContentHash()), + attribute.String("release.id", release.Id.String()), + attribute.String("release.content_hash", release.ContentHash()), attribute.Bool("has_desired_release", true), ) span.SetStatus(codes.Ok, "reconcile completed") diff --git a/apps/workspace-engine/svc/controllers/jobdispatch/reconcile.go b/apps/workspace-engine/svc/controllers/jobdispatch/reconcile.go index 1b2504e09..d7fdbe398 100644 --- a/apps/workspace-engine/svc/controllers/jobdispatch/reconcile.go +++ b/apps/workspace-engine/svc/controllers/jobdispatch/reconcile.go @@ -35,7 +35,8 @@ func Reconcile(ctx context.Context, getter Getter, setter Setter, verifier Agent span.AddEvent("no desired release") return &ReconcileResult{}, nil } - span.SetAttributes(attribute.String("release.id", release.ContentHash())) + span.SetAttributes(attribute.String("release.id", release.Id.String())) + span.SetAttributes(attribute.String("release.content_hash", release.ContentHash())) releaseID := release.UUID() @@ -111,7 +112,7 @@ func buildJob(release *oapi.Release, agent *oapi.JobAgent) *oapi.Job { now := time.Now() return &oapi.Job{ Id: uuid.New().String(), - ReleaseId: release.ContentHash(), + ReleaseId: release.Id.String(), JobAgentId: agent.Id, JobAgentConfig: agent.Config, Status: oapi.JobStatusPending, diff --git a/apps/workspace-engine/test/controllers/pipeline_test.go b/apps/workspace-engine/test/controllers/pipeline_test.go index f2a6f39ac..d9d4704c4 100644 --- a/apps/workspace-engine/test/controllers/pipeline_test.go +++ b/apps/workspace-engine/test/controllers/pipeline_test.go @@ -452,7 +452,7 @@ func TestPipeline_JobReferencesRelease(t *testing.T) { p.AssertJobCreated(t) release := p.Releases()[0] - p.AssertJobReleaseID(t, 0, release.ContentHash()) + p.AssertJobReleaseID(t, 0, release.Id.String()) } func TestRun_FullPipeline_WithJobDispatch(t *testing.T) { diff --git a/apps/workspace-engine/test/e2e/engine_job_verification_query_test.go b/apps/workspace-engine/test/e2e/engine_job_verification_query_test.go index 0bfd3ec65..e14548b24 100644 --- a/apps/workspace-engine/test/e2e/engine_job_verification_query_test.go +++ b/apps/workspace-engine/test/e2e/engine_job_verification_query_test.go @@ -88,7 +88,7 @@ func TestEngine_JobVerification_QueryByReleaseId(t *testing.T) { assert.Len(t, byJob, 1) // Query by release ID - byRelease := engine.Workspace().Store().JobVerifications.GetByReleaseId(release.ContentHash()) + byRelease := engine.Workspace().Store().JobVerifications.GetByReleaseId(release.Id.String()) assert.Len(t, byRelease, 1) assert.Equal(t, job.Id, byRelease[0].JobId) } diff --git a/apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go b/apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go index aa1488221..a99381ba3 100644 --- a/apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go +++ b/apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go @@ -78,7 +78,7 @@ func TestEngine_JobsWithNilReleaseReference(t *testing.T) { // EDGE CASE 1: Manually remove the release but keep the job // This simulates a corrupted state where a job references a non-existent release - engine.Workspace().Releases().Remove(ctx, release.ContentHash()) + engine.Workspace().Releases().Remove(ctx, release.Id.String()) // Verify release is gone _, ok = engine.Workspace().Releases().Get(job.ReleaseId) @@ -173,7 +173,7 @@ func TestEngine_ReleaseTargetStateWithNilRelease(t *testing.T) { if !ok { t.Fatalf("release should exist") } - engine.Workspace().Releases().Remove(ctx, release.ContentHash()) + engine.Workspace().Releases().Remove(ctx, release.Id.String()) releaseTarget := &oapi.ReleaseTarget{ ResourceId: resource.Id, @@ -294,7 +294,7 @@ func TestEngine_MultipleJobsWithMixedNilReleases(t *testing.T) { t.Fatalf("release should exist") } - releaseIdToDelete := release.ContentHash() + releaseIdToDelete := release.Id.String() engine.Workspace().Releases().Remove(ctx, releaseIdToDelete) // Get jobs for release target - should only return jobs with valid releases diff --git a/apps/workspace-engine/test/e2e/engine_releasemanager_test.go b/apps/workspace-engine/test/e2e/engine_releasemanager_test.go index ef0d9664e..849a408dc 100644 --- a/apps/workspace-engine/test/e2e/engine_releasemanager_test.go +++ b/apps/workspace-engine/test/e2e/engine_releasemanager_test.go @@ -564,7 +564,7 @@ func TestEngine_ReleaseManager_MultipleResources(t *testing.T) { } if release.Version.Tag != "v3.0.0" { - t.Errorf("release %s has version tag %s, want v3.0.0", release.ContentHash(), release.Version.Tag) + t.Errorf("release %s has version tag %s, want v3.0.0", release.Id.String(), release.Version.Tag) } } diff --git a/apps/workspace-engine/test/e2e/engine_releasetarget_state_test.go b/apps/workspace-engine/test/e2e/engine_releasetarget_state_test.go index 5a3073dca..9439b20db 100644 --- a/apps/workspace-engine/test/e2e/engine_releasetarget_state_test.go +++ b/apps/workspace-engine/test/e2e/engine_releasetarget_state_test.go @@ -67,12 +67,12 @@ func TestEngine_ReleaseTargetState_NoCurrentNoDesired(t *testing.T) { // Verify: no current release (no successful jobs) if state.CurrentRelease != nil { - t.Errorf("expected no current release, got release %s", state.CurrentRelease.ContentHash()) + t.Errorf("expected no current release, got release %s", state.CurrentRelease.Id.String()) } // Verify: no desired release (no versions available) if state.DesiredRelease != nil { - t.Errorf("expected no desired release, got release %s", state.DesiredRelease.ContentHash()) + t.Errorf("expected no desired release, got release %s", state.DesiredRelease.Id.String()) } } @@ -137,7 +137,7 @@ func TestEngine_ReleaseTargetState_NoCurrentWithDesired(t *testing.T) { // Verify: no current release (job not completed yet) if state.CurrentRelease != nil { - t.Errorf("expected no current release, got release %s", state.CurrentRelease.ContentHash()) + t.Errorf("expected no current release, got release %s", state.CurrentRelease.Id.String()) } // Verify: desired release exists @@ -189,6 +189,11 @@ func TestEngine_ReleaseTargetState_CurrentMatchesDesired(t *testing.T) { version.Tag = "v1.0.0" engine.PushEvent(ctx, handler.DeploymentVersionCreate, version) + allReleases := engine.Workspace().Releases().Items() + if len(allReleases) != 1 { + t.Fatalf("expected 1 release, got %d", len(allReleases)) + } + // Get the job and mark it as successful jobs := engine.Workspace().Jobs().Items() if len(jobs) != 1 { @@ -203,9 +208,23 @@ func TestEngine_ReleaseTargetState_CurrentMatchesDesired(t *testing.T) { // Mark the job as successful now := time.Now() - job.Status = oapi.JobStatusSuccessful - job.CompletedAt = &now - engine.PushEvent(ctx, handler.JobUpdate, &oapi.JobUpdateEvent{Id: &job.Id, Job: *job}) + engine.PushEvent(ctx, handler.JobUpdate, &oapi.JobUpdateEvent{ + Id: &job.Id, + Job: oapi.Job{ + Id: job.Id, + Status: oapi.JobStatusSuccessful, + CompletedAt: &now, + }, + FieldsToUpdate: &[]oapi.JobUpdateEventFieldsToUpdate{ + oapi.JobUpdateEventFieldsToUpdateStatus, + oapi.JobUpdateEventFieldsToUpdateCompletedAt, + }, + }) + + allReleases2 := engine.Workspace().Releases().Items() + if len(allReleases2) != 1 { + t.Fatalf("expected 1 release, got %d", len(allReleases2)) + } // Get the release target (get it first so we can invalidate cache) releaseTargets, err := engine.Workspace().ReleaseTargets().Items() @@ -216,6 +235,11 @@ func TestEngine_ReleaseTargetState_CurrentMatchesDesired(t *testing.T) { t.Fatalf("expected 1 release target, got %d", len(releaseTargets)) } + allReleases3 := engine.Workspace().Releases().Items() + if len(allReleases3) != 1 { + t.Fatalf("expected 1 release, got %d", len(allReleases3)) + } + var releaseTarget *oapi.ReleaseTarget for _, rt := range releaseTargets { releaseTarget = rt @@ -248,9 +272,14 @@ func TestEngine_ReleaseTargetState_CurrentMatchesDesired(t *testing.T) { // Verify: releases are the same if state.CurrentRelease.ContentHash() != state.DesiredRelease.ContentHash() { - t.Errorf("expected current and desired releases to be the same, got current=%s, desired=%s", + t.Errorf("expected current and desired releases to have the same content hash, got current=%s, desired=%s", state.CurrentRelease.ContentHash(), state.DesiredRelease.ContentHash()) } + + if state.CurrentRelease.Id.String() != state.DesiredRelease.Id.String() { + t.Errorf("expected current and desired releases to be the same, got current=%s, desired=%s", + state.CurrentRelease.Id.String(), state.DesiredRelease.Id.String()) + } } // TestEngine_ReleaseTargetState_CurrentDiffersFromDesired tests state when @@ -352,7 +381,7 @@ func TestEngine_ReleaseTargetState_CurrentDiffersFromDesired(t *testing.T) { } // Verify: releases are different - if state.CurrentRelease.ContentHash() == state.DesiredRelease.ContentHash() { + if state.CurrentRelease.Id.String() == state.DesiredRelease.Id.String() { t.Errorf("expected current and desired releases to differ") } } @@ -428,7 +457,7 @@ func TestEngine_ReleaseTargetState_JobStatusTransitions(t *testing.T) { t.Fatalf("failed to get release target state: %v", err) } if state.CurrentRelease != nil { - t.Errorf("expected no current release when job is pending, got release %s", state.CurrentRelease.ContentHash()) + t.Errorf("expected no current release when job is pending, got release %s", state.CurrentRelease.Id.String()) } // State 2: Job is InProgress - still no current release @@ -440,7 +469,7 @@ func TestEngine_ReleaseTargetState_JobStatusTransitions(t *testing.T) { t.Fatalf("failed to get release target state: %v", err) } if state.CurrentRelease != nil { - t.Errorf("expected no current release when job is in progress, got release %s", state.CurrentRelease.ContentHash()) + t.Errorf("expected no current release when job is in progress, got release %s", state.CurrentRelease.Id.String()) } // State 3: Job is Successful - current release should now exist @@ -619,7 +648,7 @@ func TestEngine_ReleaseTargetState_MultipleReleaseTargets(t *testing.T) { t.Fatalf("failed to get release target state for pending: %v", err) } if state2.CurrentRelease != nil { - t.Errorf("expected no current release for pending target, got release %s", state2.CurrentRelease.ContentHash()) + t.Errorf("expected no current release for pending target, got release %s", state2.CurrentRelease.Id.String()) } if state2.DesiredRelease == nil { t.Errorf("expected desired release for pending target, got nil") diff --git a/apps/workspace-engine/test/e2e/engine_verification_hooks_test.go b/apps/workspace-engine/test/e2e/engine_verification_hooks_test.go index 2f4609e68..5bcb7136b 100644 --- a/apps/workspace-engine/test/e2e/engine_verification_hooks_test.go +++ b/apps/workspace-engine/test/e2e/engine_verification_hooks_test.go @@ -127,7 +127,7 @@ func TestEngineVerificationHooks(t *testing.T) { if releaseTargetState.CurrentRelease == nil { t.Fatalf("expected current release, got nil") } - assert.Equal(t, release.ContentHash(), releaseTargetState.CurrentRelease.ContentHash()) + assert.Equal(t, release.Id.String(), releaseTargetState.CurrentRelease.Id.String()) } func TestEngineVerificationHooks_SuccessThreshold(t *testing.T) { @@ -243,5 +243,5 @@ func TestEngineVerificationHooks_SuccessThreshold(t *testing.T) { if releaseTargetState.CurrentRelease == nil { t.Fatalf("expected current release, got nil") } - assert.Equal(t, release.ContentHash(), releaseTargetState.CurrentRelease.ContentHash()) + assert.Equal(t, release.Id.String(), releaseTargetState.CurrentRelease.Id.String()) }