Add background audits of the default branch's newest commit

This commit is contained in:
Ian Gulliver
2026-10-20 21:08:31 -07:00
parent 1d3c4576ff
commit 5823af6ff9
21 changed files with 745 additions and 357 deletions
+42 -5
View File
@@ -231,7 +231,7 @@ type parentStage struct {
commit string
}
func (m *Manager) StartWorkflow(ctx context.Context, project api.Project, creator api.User, title, base, actor, name, brief string, todoItem *string) ([]api.Task, error) {
func (m *Manager) StartWorkflow(ctx context.Context, project api.Project, creator api.User, title, base, actor, name, brief string, todoItem *string, audit string) ([]api.Task, error) {
if creator.GitName == "" || creator.GitEmail == "" {
return nil, ErrNoGitIdentity
}
@@ -241,6 +241,7 @@ func (m *Manager) StartWorkflow(ctx context.Context, project api.Project, creato
}
frozen.Brief = brief
frozen.Title = title
frozen.Audit = audit
run := store.NewID()
tasks := []api.Task{}
@@ -250,23 +251,29 @@ func (m *Manager) StartWorkflow(ctx context.Context, project api.Project, creato
from = project.DefaultBranch
}
task, err := m.startStage(ctx, project, creator, frozen, run, stage, from, todoItem, nil, actor)
if task.Id != "" {
tasks = append(tasks, task)
}
if err != nil {
return tasks, fmt.Errorf("workflow %q: stage %q did not start: %w", name, stage, err)
}
tasks = append(tasks, task)
}
return tasks, nil
}
func (m *Manager) startStage(ctx context.Context, project api.Project, creator api.User, frozen store.FrozenWorkflow, run, stage, base string, todoItem *string, parents []parentStage, actor string) (api.Task, error) {
task, err := m.createTask(ctx, project, api.Task{
t := api.Task{
Title: fmt.Sprintf("%s: %s", frozen.Title, stage),
MergeTitle: frozen.Title,
CreatedBy: creator.Login,
TodoItem: todoItem,
WorkflowRun: &run,
WorkflowStage: &stage,
}, &frozen, base, actor)
}
if frozen.Audit != "" {
t.Audit = &frozen.Audit
}
task, err := m.createTask(ctx, project, t, &frozen, base, actor)
if err != nil {
return api.Task{}, err
}
@@ -489,7 +496,11 @@ func (m *Manager) advanceTo(ctx context.Context, from api.Task, frozen store.Fro
}
base := parents[0].commit
if workflow.FromMain(frozen.Definition, stage) {
switch {
case !workflow.FromMain(frozen.Definition, stage):
case frozen.Audit != "":
base = frozen.Audit
default:
base = project.DefaultBranch
}
task, err := m.startStage(ctx, project, creator, frozen, *from.WorkflowRun, stage, base, from.TodoItem, parents, "byre")
@@ -811,6 +822,32 @@ func (m *Manager) workflowTools(tool func(name, description, schema string, run
return fmt.Sprintf("Project %s reviews with workflow %q from its next snapshot on.", p.Name, p.ReviewWorkflow), nil
}),
tool("set_audit_workflow",
"Set the audit workflow (any saved workflow) that byre runs in the background on a project's default branch: one run at a time, started whenever the branch's newest commit hasn't had one, to check the whole codebase against its standards rather than one change. "+
"An audit's tasks stay out of list_tasks and your signals until one asks a question, calls ready_for_merge or hits an error; one that suggests discarding first is discarded by byre. An empty workflow turns audits off. Only when the human asks.",
`{"type": "object", "properties": {
"project_id": {"type": "string"},
"workflow": {"type": "string"}
}, "required": ["project_id", "workflow"]}`,
func(ctx context.Context, user api.User, raw json.RawMessage) (string, error) {
args := struct {
ProjectID string `json:"project_id"`
Workflow string `json:"workflow"`
}{}
err := json.Unmarshal(raw, &args)
if err != nil {
return "", err
}
p, err := m.SetAuditWorkflow(ctx, args.ProjectID, args.Workflow, leadActor(user.Login))
if err != nil {
return "", err
}
if p.AuditWorkflow == "" {
return fmt.Sprintf("Project %s has no audit workflow now: it isn't audited.", p.Name), nil
}
return fmt.Sprintf("Project %s is audited with workflow %q.", p.Name, p.AuditWorkflow), nil
}),
tool("delete_workflow",
"Delete a workflow from the server. Tasks that froze it keep their copy. Only when the human asks.",
`{"type": "object", "properties": {"name": {"type": "string"}}, "required": ["name"]}`,