Skip to content

refactor: add uuid field to release (noop)#826

Merged
adityachoudhari26 merged 1 commit intomainfrom
release-uuid
Mar 3, 2026
Merged

refactor: add uuid field to release (noop)#826
adityachoudhari26 merged 1 commit intomainfrom
release-uuid

Conversation

@adityachoudhari26
Copy link
Member

@adityachoudhari26 adityachoudhari26 commented Mar 3, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added unique identifier field to releases for improved tracking and consistency.
  • Refactor

    • Improved release identification to use content-based hashing instead of ID-based references for more deterministic and consistent behavior across job tracking and deployment operations.

@CLAassistant
Copy link

CLAassistant commented Mar 3, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

The PR refactors release identification by adding a required UUID id field to the Release schema and renaming the ID() method to ContentHash(), which computes a content-based hash from release metadata. The id is deterministically generated using SHA1 with the content hash. Release references throughout the system are updated to use ContentHash() for lookups and associations.

Changes

Cohort / File(s) Summary
OpenAPI Schema
apps/workspace-engine/oapi/openapi.json, apps/workspace-engine/oapi/spec/schemas/entities.jsonnet
Added required id field (UUID type) to Release schema definition.
Generated Release Types
apps/workspace-engine/pkg/oapi/oapi.gen.go, apps/workspace-engine/pkg/oapi/oapi.go
Added public Id field to Release struct and renamed ID() method to ContentHash() with updated logic computing SHA-256 hash.
Persistence & Core
apps/workspace-engine/pkg/oapi/persistence.go, apps/workspace-engine/pkg/workspace/store/repository/db/releases/mapper.go, apps/workspace-engine/pkg/workspace/store/repository/db/releases/repo.go, apps/workspace-engine/pkg/workspace/store/repository/memory/indexstore/schema_release.go
Updated Release persistence to use Id field and ContentHash() for keying; added deterministic UUID generation via SHA1 in Upsert.
Release Storage
apps/workspace-engine/pkg/workspace/store/releases.go, apps/workspace-engine/pkg/workspace/store/jobs.go
Added pre-condition to assign deterministic ID when nil; updated job retrieval to use ContentHash() as release key.
Deployment Management
apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor.go, apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor_test.go, apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility.go, apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_test.go, apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_retry_test.go, apps/workspace-engine/pkg/workspace/releasemanager/deployment/planner.go, apps/workspace-engine/pkg/workspace/releasemanager/deployment/planner_test.go
Replaced all release.ID() usages with release.ContentHash() in deployment execution, eligibility checks, and planning; added UUID import for ID initialization.
Release Manager Core
apps/workspace-engine/pkg/workspace/releasemanager/manager.go, apps/workspace-engine/pkg/workspace/releasemanager/manager_test.go
Updated tracing and test job creation to use ContentHash() instead of ID().
Action/Orchestration Layer
apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator.go, apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator_test.go, apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/hooks.go, apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/rollback.go, apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification.go, apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification_test.go
Replaced release.ID() with release.ContentHash() across tracing, logging, comparisons, and test setup for action orchestration and rollback/verification flows.
Policy Evaluators - Deployment & Retry
apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_policy_action.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_test.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry_test.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/smart_defaults_test.go
Updated all release identifier usages in deployment dependency and retry policies from ID() to ContentHash().
Policy Evaluators - Environment Progression
apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environment_progression_action.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environmentprogression_test.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker_test.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/passrate_test.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/soaktime_test.go
Replaced release.ID() with release.ContentHash() across environment progression policy evaluators and test setup.
Policy Evaluators - Other
apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentwindow/deploymentwindow_test.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/gradualrollout_test.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/rollback/rollback_test.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/version_summary_test.go, apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/versioncooldown_test.go
Updated release identifier source in policy evaluator tests from ID() to ContentHash().
Verification Management
apps/workspace-engine/pkg/workspace/releasemanager/verification/executor_test.go, apps/workspace-engine/pkg/workspace/releasemanager/verification/manager_test.go, apps/workspace-engine/pkg/workspace/releasemanager/verification/recorder_test.go, apps/workspace-engine/pkg/workspace/releasemanager/verification/scheduler_test.go
Replaced all release.ID() usages with release.ContentHash() in verification management tests and helpers.
Release Target & State
apps/workspace-engine/pkg/workspace/releasemanager/state_index_test.go, apps/workspace-engine/pkg/workspace/store/release_targets_test.go
Updated release identity assertions and lookups from ID() to ContentHash().
Service Controllers
apps/workspace-engine/svc/controllers/desiredrelease/policyeval/adapters.go, apps/workspace-engine/svc/controllers/desiredrelease/reconcile.go, apps/workspace-engine/svc/controllers/jobdispatch/reconcile.go
Updated tracing and job creation in service controllers to use ContentHash() instead of ID().
Integration & End-to-End Tests
apps/workspace-engine/pkg/persistence/integration_test.go, apps/workspace-engine/pkg/workspace/jobs/factory.go, apps/workspace-engine/pkg/workspace/jobs/factory_test.go, apps/workspace-engine/test/controllers/pipeline_test.go, apps/workspace-engine/test/e2e/engine_job_verification_query_test.go, apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go, apps/workspace-engine/test/e2e/engine_releasemanager_test.go, apps/workspace-engine/test/e2e/engine_releasetarget_state_test.go, apps/workspace-engine/test/e2e/engine_verification_hooks_test.go
Updated all integration and end-to-end tests to use release.ContentHash() for release lookups, assertions, and job creation.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Possibly related PRs

  • ctrlplanedev/ctrlplane#764 — Modifies rollback hooks in apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/hooks.go, which is also modified in this PR to update release identity handling.
  • ctrlplanedev/ctrlplane#689 — Both PRs add/modify the Id field to oapi.Release and refactor how release identifiers are derived and used across persistence and UUID generation.

Poem

🐰 A UUID now graces each release so fine,
ContentHash replaces where IDs aligned,
Deterministic seeds from hash to pure form,
Release identity dancing through every norm,
Seventy files transformed in a grand refactored spree! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.37% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a UUID field to the Release entity as a refactoring effort marked as no-op in behavior.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch release-uuid

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/workspace-engine/svc/controllers/jobdispatch/reconcile.go (1)

40-42: ⚠️ Potential issue | 🔴 Critical

Fix the identifier mismatch between job query and creation.

Line 40 queries jobs using release.UUID() but line 114 creates jobs with release.ContentHash() as the ReleaseId. Since UUID() is derived from ContentHash() but produces a different string value, GetJobsForRelease() will fail to find existing jobs once implemented, causing duplicate job creation. Use release.ContentHash() for both operations:

releaseID := release.ContentHash()

existingJobs, err := getter.GetJobsForRelease(ctx, releaseID)

Also verify that GetJobsForRelease() in getters_postgres.go (currently unimplemented) queries the jobs table by matching the ReleaseId string field.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/workspace-engine/svc/controllers/jobdispatch/reconcile.go` around lines
40 - 42, The code uses release.UUID() when fetching existing jobs but uses
release.ContentHash() when creating jobs, causing a mismatch; change the lookup
to use release.ContentHash() by setting releaseID := release.ContentHash()
before calling getter.GetJobsForRelease(ctx, releaseID), and ensure the
getter.GetJobsForRelease implementation in getters_postgres.go queries the jobs
table by the ReleaseId string field (matching ContentHash) so the lookup and
creation use the same identifier.
🧹 Nitpick comments (2)
apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go (1)

297-298: Optional: rename variable to reflect content hash semantics.

releaseIdToDelete now stores a content hash, so a more explicit name would reduce ambiguity in future maintenance.

Proposed rename
-	releaseIdToDelete := release.ContentHash()
-	engine.Workspace().Releases().Remove(ctx, releaseIdToDelete)
+	releaseContentHashToDelete := release.ContentHash()
+	engine.Workspace().Releases().Remove(ctx, releaseContentHashToDelete)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go` around
lines 297 - 298, The variable releaseIdToDelete actually holds a content hash
(from release.ContentHash()), which is misleading; rename it to something
explicit like releaseContentHash or contentHashToDelete and update its usage in
the call to engine.Workspace().Releases().Remove(ctx, ...) so the identifier
reflects the data it contains (change both the declaration and the argument
passed to Releases().Remove to use the new name).
apps/workspace-engine/pkg/persistence/integration_test.go (1)

667-667: Strengthen this test to fully validate content-hash linkage.

Releases().Get(release.ContentHash()) is correct, but this test still seeds jobs with a separate random releaseId, so it doesn’t verify release↔job linkage under the new identifier.

Proposed test-alignment diff
-	releaseId := uuid.New().String()
@@
 	jobPending := &oapi.Job{
 		Id:        uuid.New().String(),
 		Status:    "pending",
-		ReleaseId: releaseId,
+		ReleaseId: release.ContentHash(),
 	}
@@
 	jobInProgress := &oapi.Job{
 		Id:        uuid.New().String(),
 		Status:    "in_progress",
-		ReleaseId: releaseId,
+		ReleaseId: release.ContentHash(),
 	}
@@
 	jobCompleted := &oapi.Job{
 		Id:        uuid.New().String(),
 		Status:    "completed",
-		ReleaseId: releaseId,
+		ReleaseId: release.ContentHash(),
 	}
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/workspace-engine/pkg/workspace/store/releases.go`:
- Around line 29-31: The upsert currently only sets release.Id when it's nil,
allowing a stale non-nil Id to be persisted and become unreachable by Get/Remove
which derive the DB UUID from release.ContentHash(); modify the upsert logic in
releases.go (the block that touches release.Id and uses uuid.NewSHA1) to always
compute and assign release.Id = uuid.NewSHA1(uuid.NameSpaceOID,
[]byte(release.ContentHash())) (i.e., overwrite release.Id unconditionally) so
the stored Id always matches release.ContentHash() and Get/Remove/references
remain consistent.

---

Outside diff comments:
In `@apps/workspace-engine/svc/controllers/jobdispatch/reconcile.go`:
- Around line 40-42: The code uses release.UUID() when fetching existing jobs
but uses release.ContentHash() when creating jobs, causing a mismatch; change
the lookup to use release.ContentHash() by setting releaseID :=
release.ContentHash() before calling getter.GetJobsForRelease(ctx, releaseID),
and ensure the getter.GetJobsForRelease implementation in getters_postgres.go
queries the jobs table by the ReleaseId string field (matching ContentHash) so
the lookup and creation use the same identifier.

---

Nitpick comments:
In `@apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go`:
- Around line 297-298: The variable releaseIdToDelete actually holds a content
hash (from release.ContentHash()), which is misleading; rename it to something
explicit like releaseContentHash or contentHashToDelete and update its usage in
the call to engine.Workspace().Releases().Remove(ctx, ...) so the identifier
reflects the data it contains (change both the declaration and the argument
passed to Releases().Remove to use the new name).

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 15147a8 and 3a88574.

📒 Files selected for processing (60)
  • apps/workspace-engine/oapi/openapi.json
  • apps/workspace-engine/oapi/spec/schemas/entities.jsonnet
  • apps/workspace-engine/pkg/oapi/oapi.gen.go
  • apps/workspace-engine/pkg/oapi/oapi.go
  • apps/workspace-engine/pkg/oapi/persistence.go
  • apps/workspace-engine/pkg/persistence/integration_test.go
  • apps/workspace-engine/pkg/workspace/jobs/factory.go
  • apps/workspace-engine/pkg/workspace/jobs/factory_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator.go
  • apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/hooks.go
  • apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/rollback.go
  • apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification.go
  • apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor.go
  • apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility.go
  • apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_retry_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/deployment/planner.go
  • apps/workspace-engine/pkg/workspace/releasemanager/deployment/planner_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/manager.go
  • apps/workspace-engine/pkg/workspace/releasemanager/manager_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_policy_action.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentwindow/deploymentwindow_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environment_progression_action.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environmentprogression_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/passrate_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/soaktime_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/gradualrollout_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/smart_defaults_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/rollback/rollback_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/version_summary_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/versioncooldown_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/state_index_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/verification/executor_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/verification/manager_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/verification/recorder_test.go
  • apps/workspace-engine/pkg/workspace/releasemanager/verification/scheduler_test.go
  • apps/workspace-engine/pkg/workspace/store/jobs.go
  • apps/workspace-engine/pkg/workspace/store/release_targets_test.go
  • apps/workspace-engine/pkg/workspace/store/releases.go
  • apps/workspace-engine/pkg/workspace/store/repository/db/releases/mapper.go
  • apps/workspace-engine/pkg/workspace/store/repository/db/releases/repo.go
  • apps/workspace-engine/pkg/workspace/store/repository/memory/indexstore/schema_release.go
  • apps/workspace-engine/svc/controllers/desiredrelease/policyeval/adapters.go
  • apps/workspace-engine/svc/controllers/desiredrelease/reconcile.go
  • apps/workspace-engine/svc/controllers/jobdispatch/reconcile.go
  • apps/workspace-engine/test/controllers/pipeline_test.go
  • apps/workspace-engine/test/e2e/engine_job_verification_query_test.go
  • apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go
  • apps/workspace-engine/test/e2e/engine_releasemanager_test.go
  • apps/workspace-engine/test/e2e/engine_releasetarget_state_test.go
  • apps/workspace-engine/test/e2e/engine_verification_hooks_test.go
  • packages/workspace-engine-sdk/src/schema.ts

Comment on lines +29 to +31
if release.Id == uuid.Nil {
release.Id = uuid.NewSHA1(uuid.NameSpaceOID, []byte(release.ContentHash()))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep release.Id synchronized with ContentHash() on every upsert.

Get/Remove paths derive DB UUID from the content hash key, but this block only derives Id when it is nil. A non-nil stale/mismatched Id can be persisted and then become unreachable via Get(release.ContentHash()).

🔧 Proposed fix
 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()))
-	}
+	expectedID := uuid.NewSHA1(uuid.NameSpaceOID, []byte(release.ContentHash()))
+	if release.Id != expectedID {
+		release.Id = expectedID
+	}
 	if err := r.repo.Set(release); err != nil {
 		return err
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if release.Id == uuid.Nil {
release.Id = uuid.NewSHA1(uuid.NameSpaceOID, []byte(release.ContentHash()))
}
func (r *Releases) Upsert(ctx context.Context, release *oapi.Release) error {
expectedID := uuid.NewSHA1(uuid.NameSpaceOID, []byte(release.ContentHash()))
if release.Id != expectedID {
release.Id = expectedID
}
if err := r.repo.Set(release); err != nil {
return err
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/workspace-engine/pkg/workspace/store/releases.go` around lines 29 - 31,
The upsert currently only sets release.Id when it's nil, allowing a stale
non-nil Id to be persisted and become unreachable by Get/Remove which derive the
DB UUID from release.ContentHash(); modify the upsert logic in releases.go (the
block that touches release.Id and uses uuid.NewSHA1) to always compute and
assign release.Id = uuid.NewSHA1(uuid.NameSpaceOID,
[]byte(release.ContentHash())) (i.e., overwrite release.Id unconditionally) so
the stored Id always matches release.ContentHash() and Get/Remove/references
remain consistent.

@adityachoudhari26 adityachoudhari26 merged commit 12bb834 into main Mar 3, 2026
11 checks passed
@adityachoudhari26 adityachoudhari26 deleted the release-uuid branch March 3, 2026 05:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants