feat(webhook): add workflow_step webhook events for step-level CI notifications

Adds HookEventWorkflowStep event type that fires on every step state
transition (queued -> in_progress -> completed). Follows the same
pattern as the existing workflow_job events.

- New WorkflowStepPayload struct with run/job/step context
- WorkflowStepStatusUpdate notifier interface + dispatch
- Step state change detection in UpdateTask runner endpoint
- Fix: register workflow_step in updateHookEvents API mapping
- Full test coverage mirroring workflow_job tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-06 17:47:14 -05:00
parent a39af1a829
commit bb6faa4c5d
30 changed files with 504 additions and 3 deletions
+18
View File
@@ -183,6 +183,16 @@ func (s *Service) UpdateTask(
) (*connect.Response[runnerv1.UpdateTaskResponse], error) {
runner := GetRunner(ctx)
// Snapshot step states before the update so we can detect which steps changed.
oldStepStates := make(map[int64]actions_model.Status)
if existingTask, err := actions_model.GetTaskByID(ctx, req.Msg.State.Id); err == nil {
if err := existingTask.LoadAttributes(ctx); err == nil {
for _, step := range existingTask.Steps {
oldStepStates[step.Index] = step.Status
}
}
}
task, err := actions_model.UpdateTaskByState(ctx, runner.ID, req.Msg.State)
if err != nil {
return nil, status.Errorf(codes.Internal, "update task: %v", err)
@@ -222,6 +232,14 @@ func (s *Service) UpdateTask(
actions_service.CreateCommitStatusForRunJobs(ctx, task.Job.Run, task.Job)
// Emit step events for any step whose status changed during this update.
for _, step := range task.Steps {
oldStatus, seen := oldStepStates[step.Index]
if !seen || oldStatus != step.Status {
actions_service.NotifyWorkflowStepStatusUpdate(ctx, task.Job, task, step)
}
}
if task.Status.IsDone() {
actions_service.NotifyWorkflowJobStatusUpdateWithTask(ctx, task.Job, task)
}