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
+49
View File
@@ -984,6 +984,55 @@ func notifyPackage(ctx context.Context, sender *user_model.User, pd *packages_mo
}
}
func (*webhookNotifier) WorkflowStepStatusUpdate(ctx context.Context, repo *repo_model.Repository, sender *user_model.User, job *actions_model.ActionRunJob, task *actions_model.ActionTask, step *actions_model.ActionTaskStep) {
source := EventSource{
Repository: repo,
Owner: repo.Owner,
}
var org *api.Organization
if repo.Owner.IsOrganization() {
org = convert.ToOrganization(ctx, organization.OrgFromUser(repo.Owner))
}
stepStatus, _ := convert.ToActionsStatus(step.Status)
convertedJob, err := convert.ToActionWorkflowJob(ctx, repo, task, job)
if err != nil {
log.Error("ToActionWorkflowJob: %v", err)
return
}
// Find the step index within the task steps for the Number field.
stepIndex := int(step.Index)
convertedStep := convert.ToActionWorkflowStep(step, stepIndex)
// Build a minimal WorkflowRun for the payload.
if err := job.LoadAttributes(ctx); err != nil {
log.Error("job.LoadAttributes: %v", err)
return
}
convertedRun, err := convert.ToActionWorkflowRun(ctx, job.Run, nil)
if err != nil {
log.Error("ToActionWorkflowRun: %v", err)
return
}
if err := PrepareWebhooks(ctx, source, webhook_module.HookEventWorkflowStep, &api.WorkflowStepPayload{
Action: stepStatus,
WorkflowRun: convertedRun,
WorkflowJob: convertedJob,
Step: convertedStep,
Organization: org,
Repo: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
Sender: convert.ToUser(ctx, sender, nil),
}); err != nil {
log.Error("PrepareWebhooks: %v", err)
}
}
func (*webhookNotifier) WorkflowJobStatusUpdate(ctx context.Context, repo *repo_model.Repository, sender *user_model.User, job *actions_model.ActionRunJob, task *actions_model.ActionTask) {
source := EventSource{
Repository: repo,