diff --git a/internal/projectinstance/store.go b/internal/projectinstance/store.go index 0bfd5863..e3555219 100644 --- a/internal/projectinstance/store.go +++ b/internal/projectinstance/store.go @@ -214,13 +214,24 @@ func (s *pgStore) UpsertPlanningInstance(ctx context.Context, inst *WorkflowInst SELECT id FROM project_workflow_instances WHERE project_id = $1 AND status = 'planning' LIMIT 1 `, inst.ProjectID).Scan(&existingID) if errors.Is(err, pgx.ErrNoRows) { + // Allocate next instance_no so planning drafts after a completed main/rdev + // instance do not collide on (project_id, instance_no). + var nextNo int + if err := tx.QueryRow(ctx, ` + SELECT COALESCE(MAX(instance_no), 0) + 1 + FROM project_workflow_instances + WHERE project_id = $1 + `, inst.ProjectID).Scan(&nextNo); err != nil { + return nil, err + } + inst.InstanceNo = nextNo err = tx.QueryRow(ctx, ` INSERT INTO project_workflow_instances ( project_id, workflow_version_id, instance_no, status, config_revision, plan_hash, config_snapshot, created_by, created_at, updated_at - ) VALUES ($1, $2, 1, 'planning', $3, $4, $5, $6, $7, $8) + ) VALUES ($1, $2, $3, 'planning', $4, $5, $6, $7, $8, $9) RETURNING id - `, inst.ProjectID, inst.WorkflowVersionID, inst.ConfigRevision, inst.PlanHash, snapRaw, + `, inst.ProjectID, inst.WorkflowVersionID, nextNo, inst.ConfigRevision, inst.PlanHash, snapRaw, inst.CreatedBy, inst.CreatedAt, inst.UpdatedAt).Scan(&inst.ID) if err != nil { return nil, err