Skip to content

Allow ProductDefinition to be configured to start manual rebuilds at Synchronize Data#1352

Draft
FyreByrd wants to merge 8 commits intodevelopfrom
feature/start-flow-at
Draft

Allow ProductDefinition to be configured to start manual rebuilds at Synchronize Data#1352
FyreByrd wants to merge 8 commits intodevelopfrom
feature/start-flow-at

Conversation

@FyreByrd
Copy link
Contributor

@FyreByrd FyreByrd commented Oct 20, 2025

Fixes #1333

Below screenshot shows product definition automatically updated by startup migration task

Screenshot 2025-10-20 at 3 41 10 PM

Summary by CodeRabbit

  • New Features

    • Admins can set a configurable "Start Manual Rebuilds at" state for product definitions; option appears when a rebuild workflow is selected.
  • Chores

    • Added translations for the new UI string in multiple languages.
    • A data migration populates the new field for existing product definitions.

@FyreByrd FyreByrd requested a review from chrisvire October 20, 2025 20:41
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 20, 2025

Walkthrough

Adds a nullable StartManualRebuildAt field to ProductDefinitions (DB + Prisma), migration logic to populate it from existing Properties.ShouldExecute, exposes it in product APIs and workflow types, and adds UI and localization to configure the manual rebuild start state.

Changes

Cohort / File(s) Summary
Localization
src/lib/locales/en-US.json, src/lib/locales/es-419.json, src/lib/locales/fr-FR.json
Added prodDefs_startAt translation key across three locales.
Database Schema / Migrations
src/lib/prisma/migrations/14_start_rebuilds_at_state/migration.sql, src/lib/prisma/schema.prisma
Added StartManualRebuildAt column and corresponding optional String? field on ProductDefinitions.
Migration Job Logic
src/lib/server/job-executors/system.ts
New migration steps: scan Properties JSON for ShouldExecute, parse and set StartManualRebuildAt when a single target exists; adjusted progress updates and added updatedProductDefinitions flag to migration result.
Workflow Types
src/lib/workflowTypes.ts
Added optional start?: WorkflowState to WorkflowInstanceContext and WorkflowConfig.
Product API / Server
src/lib/products/server.ts
Selects StartManualRebuildAt on product fetch; includes start in workflow creation payload for rebuild actions (set from StartManualRebuildAt).
Admin UI — Edit
src/routes/(authenticated)/admin/settings/product-definitions/edit/+page.server.ts, .../edit/+page.svelte
Added startManualRebuildAt field to server/schema and a conditional select in the edit form (options from WorkflowState) when rebuild workflow is chosen.
Admin UI — New
src/routes/(authenticated)/admin/settings/product-definitions/new/+page.server.ts, .../new/+page.svelte
Added startManualRebuildAt to creation schema and a conditional select in the new-product form when rebuild workflow is chosen.

Sequence Diagram(s)

sequenceDiagram
  participant Admin as Admin UI
  participant Server as App Server
  participant DB as Database
  participant Migrator as Migration Job
  participant Worker as Workflow Engine

  rect rgb(230,245,255)
    Admin->>Server: submit product definition (create/edit) with StartManualRebuildAt
    Server->>DB: persist ProductDefinitions.StartManualRebuildAt
  end

  rect rgb(245,245,230)
    Migrator->>DB: read ProductDefinitions.Properties
    Migrator->>Migrator: parse JSON -> extract ShouldExecute targets
    alt exactly one target found
      Migrator->>DB: update StartManualRebuildAt for that product
      Migrator-->>Migrator: mark updatedProductDefinitions = true
    else multiple/none found
      Migrator-->>Migrator: log info, skip
    end
  end

  rect rgb(235,255,235)
    Admin->>Server: trigger manual rebuild
    Server->>DB: read ProductDefinitions.StartManualRebuildAt
    Server->>Worker: create workflow (type: rebuild, start = StartManualRebuildAt)
    Worker->>Worker: execute workflow from specified start state
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Reasoning: multiple layers changed (DB migration, parsing-heavy migration job, API/server payloads, types, and UI). Migration logic and workflow persistence require careful review; other changes are repetitive and lower risk.

Possibly related PRs

Suggested reviewers

  • chrisvire

Poem

"🐰 I nibbled the schema, hopped through the code,
Found ShouldExecute paths on a migration road.
Start states planted where rebuilds will begin,
Forms and locales humming — a soft, eager grin.
Hop on, rebuilds — let the workflows sing!"

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "Allow ProductDefinition to be configured to start manual rebuilds at Synchronize Data" clearly and specifically describes the main feature being implemented. The title directly addresses the core objective from the linked issue #1333, which requests support for configuring where to start manual workflow rebuilds. The title is concise, meaningful, and provides sufficient context for a developer scanning the history to understand the primary change without being overly detailed.
Linked Issues Check ✅ Passed The pull request successfully implements the core requirements from linked issue #1333. The changes include: parsing of the ShouldExecute property from ProductDefinition JSON configuration in the system migration (system.ts), storing the parsed workflow start point in the new StartManualRebuildAt field, exposing configuration UI for this field in both edit and new product definition pages, and passing the start point through the workflow creation payload. The implementation enables starting manual rebuilds at specific steps like "Synchronize Data" as required, with the system migration logic handling automatic population of this field for existing configurations. All coding-related objectives from the linked issue are addressed.
Out of Scope Changes Check ✅ Passed All changes in the pull request are directly related to implementing the ShouldExecute feature and configuring where manual rebuilds start. The modifications span consistently from database schema changes, localization keys, UI components, server-side product definition handling, and system migration logic that parses ShouldExecute and populates StartManualRebuildAt. Even the progress value adjustments in the system migration are part of the same migration task being enhanced. No changes appear to address unrelated features or objectives outside the scope of issue #1333.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/start-flow-at

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 64f8e88 and 4464b9f.

📒 Files selected for processing (1)
  • src/lib/locales/es-419.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/locales/es-419.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-test

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: 4

Caution

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

⚠️ Outside diff range comments (1)
src/lib/server/job-executors/system.ts (1)

724-739: Fix always-true updatedProductDefinitions flag

Using !!array is always true. Base it on length or actual updates.

-    updatedProductDefinitions: !!prodDefsNeedUpdate,
+    updatedProductDefinitions: prodDefsNeedUpdate.length > 0,

If you adopt the counter in the previous diff, prefer returning the count instead (e.g., updatedProductDefinitionsCount).

🧹 Nitpick comments (5)
src/lib/products/server.ts (1)

54-60: Consider validating before casting to WorkflowState.

The code casts StartManualRebuildAt directly to WorkflowState without validation. If the database contains an invalid value (due to manual editing or data migration), this could cause runtime issues downstream.

Apply this diff to add defensive validation:

 workflowType: product.ProductDefinition[flowType].Type,
 // ISSUE #1324 use isAutomatic here
 start:
   (action === 'rebuild' &&
-    (product.ProductDefinition.StartManualRebuildAt as WorkflowState)) ||
+    product.ProductDefinition.StartManualRebuildAt &&
+    Object.values(WorkflowState).includes(product.ProductDefinition.StartManualRebuildAt as WorkflowState)
+      ? (product.ProductDefinition.StartManualRebuildAt as WorkflowState)
+      : undefined) ||
   undefined
src/routes/(authenticated)/admin/settings/product-definitions/edit/+page.server.ts (2)

17-17: Make field nullish and drop String() to avoid hidden-control validation failures

When the select is hidden, the field may be absent; v.nullable won’t accept undefined. Also, String(...) is redundant.

Apply:

-  startManualRebuildAt: v.nullable(v.literal(String(WorkflowState.Synchronize_Data))),
+  startManualRebuildAt: v.nullish(v.literal(WorkflowState.Synchronize_Data)),

67-75: Clear StartManualRebuildAt when rebuildWorkflow is unset

Prevents stale state if a user selects a start point then removes the rebuild flow.

       data: {
         TypeId: form.data.applicationType,
         Name: form.data.name,
         WorkflowId: form.data.workflow,
         RebuildWorkflowId: form.data.rebuildWorkflow,
-        StartManualRebuildAt: form.data.startManualRebuildAt,
+        StartManualRebuildAt: form.data.rebuildWorkflow
+          ? form.data.startManualRebuildAt ?? null
+          : null,
         RepublishWorkflowId: form.data.republishWorkflow,
         Description: form.data.description,
         Properties: form.data.properties
       }
src/routes/(authenticated)/admin/settings/product-definitions/edit/+page.svelte (1)

99-111: Avoid sending "null" string; ensure field presence/reset when hidden

value={null} serializes as "null". If the control is hidden, the field may be missing.

Option A (simplest):

-        <option value={null}>{WorkflowState.Product_Build}</option>
+        <option value="">{WorkflowState.Product_Build}</option>

…and pair with the server change to map '' -> null (via v.nullish as proposed).

Option B (also reset on hide):

+  $: if (!$form.rebuildWorkflow) $form.startManualRebuildAt = null;

Option C (ensure field present when hidden):

{#if !$form.rebuildWorkflow}
  <input type="hidden" name="startManualRebuildAt" value="" />
{/if}
src/lib/workflowTypes.ts (1)

251-255: Harden canJump against non-enum targets

If a plain string slips in, short-circuit before comparison.

 export function canJump(args: { context: WorkflowContext }, params: JumpParams): boolean {
-  return (
-    args.context.start === params.target && includeStateOrTransition(args.context, params.filter)
-  );
+  const target = params.target;
+  if (typeof target === 'string' && !isWorkflowState(target)) return false;
+  return args.context.start === target && includeStateOrTransition(args.context, params.filter);
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fcaca1d and 64f8e88.

📒 Files selected for processing (12)
  • src/lib/locales/en-US.json (1 hunks)
  • src/lib/locales/es-419.json (1 hunks)
  • src/lib/locales/fr-FR.json (1 hunks)
  • src/lib/prisma/migrations/14_start_rebuilds_at_state/migration.sql (1 hunks)
  • src/lib/prisma/schema.prisma (1 hunks)
  • src/lib/products/server.ts (3 hunks)
  • src/lib/server/job-executors/system.ts (3 hunks)
  • src/lib/workflowTypes.ts (2 hunks)
  • src/routes/(authenticated)/admin/settings/product-definitions/edit/+page.server.ts (3 hunks)
  • src/routes/(authenticated)/admin/settings/product-definitions/edit/+page.svelte (2 hunks)
  • src/routes/(authenticated)/admin/settings/product-definitions/new/+page.server.ts (2 hunks)
  • src/routes/(authenticated)/admin/settings/product-definitions/new/+page.svelte (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/routes/(authenticated)/admin/settings/product-definitions/edit/+page.server.ts (1)
src/lib/valibot.ts (1)
  • idSchema (3-3)
src/lib/server/job-executors/system.ts (2)
src/lib/server/database/prisma.ts (1)
  • DatabaseReads (22-22)
src/lib/server/database/index.ts (1)
  • DatabaseWrites (68-71)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: typecheck-lint
  • GitHub Check: build-and-test
🔇 Additional comments (7)
src/lib/locales/en-US.json (1)

537-537: LGTM!

The translation key follows the naming convention and is appropriately placed within the Product Definitions section.

src/lib/prisma/schema.prisma (1)

221-221: LGTM!

The field definition is correct and follows the schema conventions. The placement between rebuild and republish workflow fields is logical.

src/lib/prisma/migrations/14_start_rebuilds_at_state/migration.sql (1)

1-2: LGTM!

The migration correctly adds a nullable TEXT column that aligns with the schema definition.

src/routes/(authenticated)/admin/settings/product-definitions/new/+page.server.ts (1)

15-15: The validation schema is correct as-is and requires no changes.

The schema at line 15 uses v.literal(String(WorkflowState.Synchronize_Data)) to accept only the Synchronize_Data value or null. The UI in +page.svelte (lines 104-105) confirms this is intentional—it presents exactly two options: null and Synchronize_Data. The v.literal() approach is appropriate here since only one non-null value is expected. No refactoring to v.union() or v.picklist() is needed.

Likely an incorrect or invalid review comment.

src/routes/(authenticated)/admin/settings/product-definitions/edit/+page.server.ts (1)

9-9: LGTM on importing WorkflowState for schema literal

Import aligns with new field usage.

src/routes/(authenticated)/admin/settings/product-definitions/edit/+page.svelte (1)

11-11: LGTM on importing WorkflowState for option labels

Consistent with server schema.

src/lib/workflowTypes.ts (1)

133-135: LGTM: Persisting start in context

Keeps DB snapshots self-contained; matches migration/PR intent.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@chrisvire
Copy link
Member

I have contacted Kalaam. They said they would review at their next team meeting (Tuesday, 10/28/25). Thanks for implementing this. If they don't need it, then it would likely be better not to add the complexity.

@chrisvire
Copy link
Member

Waiting to hear back from Kalaam. They are meeting on Tuesday, 10/28/25

@chrisvire chrisvire removed their request for review December 8, 2025 21:00
@chrisvire chrisvire marked this pull request as draft December 8, 2025 21:02
@chrisvire
Copy link
Member

I don't think they need it at the moment. I am moving it back to draft until we make sure they need it.

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.

ProductDefinition: Properties has ShouldExecute

2 participants