Drop workflow kinds, deliver reviews when done, rename/delete workflows

This commit is contained in:
Ian Gulliver
2026-10-20 20:09:38 -07:00
parent 51df9adf61
commit 35f59246f7
17 changed files with 671 additions and 531 deletions
+70 -5
View File
@@ -18,7 +18,7 @@ type FrozenWorkflow struct {
}
func (s *Store) ListWorkflows(ctx context.Context) ([]api.WorkflowSummary, error) {
rows, err := s.db.QueryContext(ctx, `SELECT name, coalesce(json_extract(definition, '$.description'), ''), coalesce(nullif(json_extract(definition, '$.kind'), ''), 'task') FROM workflows ORDER BY name`)
rows, err := s.db.QueryContext(ctx, `SELECT name, coalesce(json_extract(definition, '$.description'), '') FROM workflows ORDER BY name`)
if err != nil {
return nil, err
}
@@ -27,7 +27,7 @@ func (s *Store) ListWorkflows(ctx context.Context) ([]api.WorkflowSummary, error
workflows := []api.WorkflowSummary{}
for rows.Next() {
w := api.WorkflowSummary{}
err = rows.Scan(&w.Name, &w.Description, &w.Kind)
err = rows.Scan(&w.Name, &w.Description)
if err != nil {
return nil, err
}
@@ -50,12 +50,46 @@ func (s *Store) GetWorkflow(ctx context.Context, name string) (api.WorkflowDefin
return w, err
}
func (s *Store) PutWorkflow(ctx context.Context, name string, def api.WorkflowDefinition, actor string) error {
var ErrWorkflowExists = errors.New("workflow exists")
func (s *Store) PutWorkflow(ctx context.Context, name, from string, def api.WorkflowDefinition, actor string) error {
b, err := json.Marshal(def)
if err != nil {
return err
}
return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error {
if from != "" {
found := false
err := tx.QueryRowContext(ctx, `SELECT EXISTS (SELECT 1 FROM workflows WHERE name = ?)`, from).Scan(&found)
if err != nil {
return err
}
if !found {
return fmt.Errorf("%w: no workflow %q", ErrNotFound, from)
}
}
if from != "" && from != name {
taken := false
err := tx.QueryRowContext(ctx, `SELECT EXISTS (SELECT 1 FROM workflows WHERE name = ?)`, name).Scan(&taken)
if err != nil {
return err
}
if taken {
return fmt.Errorf("%w: a workflow named %q already exists", ErrWorkflowExists, name)
}
_, err = tx.ExecContext(ctx, `DELETE FROM workflows WHERE name = ?`, from)
if err != nil {
return err
}
err = repointReviews(ctx, tx, emit, from, name, actor)
if err != nil {
return err
}
err = emit(api.Event{Kind: "workflow.deleted", Actor: actor, Payload: map[string]any{"name": from}})
if err != nil {
return err
}
}
_, err := tx.ExecContext(ctx, `INSERT INTO workflows (name, definition) VALUES (?, ?)
ON CONFLICT (name) DO UPDATE SET definition = excluded.definition`, name, string(b))
if err != nil {
@@ -65,6 +99,33 @@ func (s *Store) PutWorkflow(ctx context.Context, name string, def api.WorkflowDe
})
}
func repointReviews(ctx context.Context, tx *sql.Tx, emit emitFunc, from, to, actor string) error {
rows, err := tx.QueryContext(ctx, `UPDATE projects SET review_workflow = ? WHERE review_workflow = ? RETURNING `+projectColumns, to, from)
if err != nil {
return err
}
projects := []api.Project{}
for rows.Next() {
p, err := scanProject(rows)
if err != nil {
rows.Close()
return err
}
projects = append(projects, p)
}
err = errors.Join(rows.Err(), rows.Close())
if err != nil {
return err
}
for _, p := range projects {
err = emit(api.Event{Kind: "project.updated", ProjectId: &p.Id, Actor: actor, Payload: ToPayload(p)})
if err != nil {
return err
}
}
return nil
}
func (s *Store) DeleteWorkflow(ctx context.Context, name, actor string) error {
return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error {
res, err := tx.ExecContext(ctx, `DELETE FROM workflows WHERE name = ?`, name)
@@ -78,6 +139,10 @@ func (s *Store) DeleteWorkflow(ctx context.Context, name, actor string) error {
if n == 0 {
return fmt.Errorf("%w: no workflow %q", ErrNotFound, name)
}
err = repointReviews(ctx, tx, emit, name, "", actor)
if err != nil {
return err
}
return emit(api.Event{Kind: "workflow.deleted", Actor: actor, Payload: map[string]any{"name": name}})
})
}
@@ -201,7 +266,7 @@ func clearStage(ctx context.Context, tx *sql.Tx, sessionID string) error {
return err
}
func (s *Store) FinishWorkflow(ctx context.Context, task api.Task, sessionID, workflowName, output string) error {
func (s *Store) FinishWorkflow(ctx context.Context, task api.Task, sessionID, workflowName, output string, kept []string) error {
return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error {
err := clearStage(ctx, tx, sessionID)
if err != nil {
@@ -212,7 +277,7 @@ func (s *Store) FinishWorkflow(ctx context.Context, task api.Task, sessionID, wo
ProjectId: &task.ProjectId,
TaskId: &task.Id,
Actor: "byre",
Payload: map[string]any{"id": task.Id, "workflow": workflowName, "output": output},
Payload: map[string]any{"id": task.Id, "workflow": workflowName, "output": output, "kept": kept},
})
})
}