WIP workflow_job webhook

fixup

initial working draft

Add more fields

More Complete
This commit is contained in:
Christopher Homberger 2025-02-23 13:52:40 +01:00
parent 8ae46d9684
commit a4f32e57c8
20 changed files with 241 additions and 8 deletions

View File

@ -469,3 +469,18 @@ type CommitStatusPayload struct {
func (p *CommitStatusPayload) JSONPayload() ([]byte, error) { func (p *CommitStatusPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ") return json.MarshalIndent(p, "", " ")
} }
// WorkflowJobPayload represents a payload information of workflow job event.
type WorkflowJobPayload struct {
Action string `json:"action"`
WorkflowJob *ActionWorkflowJob `json:"workflow_job"`
PullRequest *PullRequest `json:"pull_request,omitempty"`
Organization *Organization `json:"organization,omitempty"`
Repository *Repository `json:"repository"`
Sender *User `json:"sender"`
}
// JSONPayload implements Payload
func (p *WorkflowJobPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}

View File

@ -96,3 +96,36 @@ type ActionArtifactsResponse struct {
Entries []*ActionArtifact `json:"artifacts"` Entries []*ActionArtifact `json:"artifacts"`
TotalCount int64 `json:"total_count"` TotalCount int64 `json:"total_count"`
} }
// ActionWorkflowRun represents a WorkflowJob
type ActionWorkflowStep struct {
Name string `json:"name"`
Number int64 `json:"number"`
Conclusion string `json:"conclusion,omitempty"`
// swagger:strfmt date-time
StartedAt time.Time `json:"started_at,omitempty"`
// swagger:strfmt date-time
CompletedAt time.Time `json:"completed_at,omitempty"`
}
// ActionWorkflowJob represents a WorkflowJob
type ActionWorkflowJob struct {
ID int64 `json:"id"`
RunID int64 `json:"run_id"`
RunURL string `json:"run_url"`
Name string `json:"name"`
Labels []string `json:"labels"`
RunAttempt int64 `json:"run_attempt"`
HeadSha string `json:"head_sha"`
HeadBranch string `json:"head_branch,omitempty"`
Conclusion string `json:"conclusion,omitempty"`
RunnerID int64 `json:"runner_id"`
RunnerName string `json:"runner_name"`
Steps []*ActionWorkflowStep `json:"steps"`
// swagger:strfmt date-time
CreatedAt time.Time `json:"created_at"`
// swagger:strfmt date-time
StartedAt time.Time `json:"started_at,omitempty"`
// swagger:strfmt date-time
CompletedAt time.Time `json:"completed_at,omitempty"`
}

View File

@ -37,7 +37,8 @@ const (
// FIXME: This event should be a group of pull_request_review_xxx events // FIXME: This event should be a group of pull_request_review_xxx events
HookEventPullRequestReview HookEventType = "pull_request_review" HookEventPullRequestReview HookEventType = "pull_request_review"
// Actions event only // Actions event only
HookEventSchedule HookEventType = "schedule" HookEventSchedule HookEventType = "schedule"
HookEventWorkflowJob HookEventType = "workflow_job"
) )
func AllEvents() []HookEventType { func AllEvents() []HookEventType {
@ -66,6 +67,7 @@ func AllEvents() []HookEventType {
HookEventRelease, HookEventRelease,
HookEventPackage, HookEventPackage,
HookEventStatus, HookEventStatus,
HookEventWorkflowJob,
} }
} }

View File

@ -2379,6 +2379,8 @@ settings.event_pull_request_review_request = Pull Request Review Requested
settings.event_pull_request_review_request_desc = Pull request review requested or review request removed. settings.event_pull_request_review_request_desc = Pull request review requested or review request removed.
settings.event_pull_request_approvals = Pull Request Approvals settings.event_pull_request_approvals = Pull Request Approvals
settings.event_pull_request_merge = Pull Request Merge settings.event_pull_request_merge = Pull Request Merge
settings.event_workflow_job = Workflow Job
settings.event_workflow_job_desc = Gitea Actions Workflow Job queued, started or completed.
settings.event_package = Package settings.event_package = Package
settings.event_package_desc = Package created or deleted in a repository. settings.event_package_desc = Package created or deleted in a repository.
settings.branch_filter = Branch filter settings.branch_filter = Branch filter

View File

@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
actions_service "code.gitea.io/gitea/services/actions" actions_service "code.gitea.io/gitea/services/actions"
notifier "code.gitea.io/gitea/services/notify"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1" runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
"code.gitea.io/actions-proto-go/runner/v1/runnerv1connect" "code.gitea.io/actions-proto-go/runner/v1/runnerv1connect"
@ -210,7 +211,7 @@ func (s *Service) UpdateTask(
if err := task.LoadJob(ctx); err != nil { if err := task.LoadJob(ctx); err != nil {
return nil, status.Errorf(codes.Internal, "load job: %v", err) return nil, status.Errorf(codes.Internal, "load job: %v", err)
} }
if err := task.Job.LoadRun(ctx); err != nil { if err := task.Job.LoadAttributes(ctx); err != nil {
return nil, status.Errorf(codes.Internal, "load run: %v", err) return nil, status.Errorf(codes.Internal, "load run: %v", err)
} }
@ -224,7 +225,9 @@ func (s *Service) UpdateTask(
log.Error("Emit ready jobs of run %d: %v", task.Job.RunID, err) log.Error("Emit ready jobs of run %d: %v", task.Job.RunID, err)
} }
} }
if task.Status.IsDone() {
notifier.CreateWorkflowJob(ctx, task.Job.Run.Repo, task.Job.Run.TriggerUser, task.Job, task)
}
return connect.NewResponse(&runnerv1.UpdateTaskResponse{ return connect.NewResponse(&runnerv1.UpdateTaskResponse{
State: &runnerv1.TaskState{ State: &runnerv1.TaskState{
Id: req.Msg.State.Id, Id: req.Msg.State.Id,

View File

@ -207,6 +207,7 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, ownerID, repoI
webhook_module.HookEventRelease: util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true), webhook_module.HookEventRelease: util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true),
webhook_module.HookEventPackage: util.SliceContainsString(form.Events, string(webhook_module.HookEventPackage), true), webhook_module.HookEventPackage: util.SliceContainsString(form.Events, string(webhook_module.HookEventPackage), true),
webhook_module.HookEventStatus: util.SliceContainsString(form.Events, string(webhook_module.HookEventStatus), true), webhook_module.HookEventStatus: util.SliceContainsString(form.Events, string(webhook_module.HookEventStatus), true),
webhook_module.HookEventWorkflowJob: util.SliceContainsString(form.Events, string(webhook_module.HookEventWorkflowJob), true),
}, },
BranchFilter: form.BranchFilter, BranchFilter: form.BranchFilter,
}, },

View File

@ -33,6 +33,7 @@ import (
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
actions_service "code.gitea.io/gitea/services/actions" actions_service "code.gitea.io/gitea/services/actions"
context_module "code.gitea.io/gitea/services/context" context_module "code.gitea.io/gitea/services/context"
notifier "code.gitea.io/gitea/services/notify"
"github.com/nektos/act/pkg/model" "github.com/nektos/act/pkg/model"
"xorm.io/builder" "xorm.io/builder"
@ -458,6 +459,9 @@ func rerunJob(ctx *context_module.Context, job *actions_model.ActionRunJob, shou
} }
actions_service.CreateCommitStatus(ctx, job) actions_service.CreateCommitStatus(ctx, job)
_ = job.LoadAttributes(ctx)
notifier.CreateWorkflowJob(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
return nil return nil
} }
@ -518,6 +522,8 @@ func Cancel(ctx *context_module.Context) {
return return
} }
var updatedjobs []*actions_model.ActionRunJob
if err := db.WithTx(ctx, func(ctx context.Context) error { if err := db.WithTx(ctx, func(ctx context.Context) error {
for _, job := range jobs { for _, job := range jobs {
status := job.Status status := job.Status
@ -534,6 +540,9 @@ func Cancel(ctx *context_module.Context) {
if n == 0 { if n == 0 {
return fmt.Errorf("job has changed, try again") return fmt.Errorf("job has changed, try again")
} }
if n > 0 {
updatedjobs = append(updatedjobs, job)
}
continue continue
} }
if err := actions_model.StopTask(ctx, job.TaskID, actions_model.StatusCancelled); err != nil { if err := actions_model.StopTask(ctx, job.TaskID, actions_model.StatusCancelled); err != nil {
@ -548,6 +557,11 @@ func Cancel(ctx *context_module.Context) {
actions_service.CreateCommitStatus(ctx, jobs...) actions_service.CreateCommitStatus(ctx, jobs...)
for _, job := range updatedjobs {
_ = job.LoadAttributes(ctx)
notifier.CreateWorkflowJob(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
}
ctx.JSON(http.StatusOK, struct{}{}) ctx.JSON(http.StatusOK, struct{}{})
} }
@ -561,6 +575,8 @@ func Approve(ctx *context_module.Context) {
run := current.Run run := current.Run
doer := ctx.Doer doer := ctx.Doer
var updatedjobs []*actions_model.ActionRunJob
if err := db.WithTx(ctx, func(ctx context.Context) error { if err := db.WithTx(ctx, func(ctx context.Context) error {
run.NeedApproval = false run.NeedApproval = false
run.ApprovedBy = doer.ID run.ApprovedBy = doer.ID
@ -570,10 +586,13 @@ func Approve(ctx *context_module.Context) {
for _, job := range jobs { for _, job := range jobs {
if len(job.Needs) == 0 && job.Status.IsBlocked() { if len(job.Needs) == 0 && job.Status.IsBlocked() {
job.Status = actions_model.StatusWaiting job.Status = actions_model.StatusWaiting
_, err := actions_model.UpdateRunJob(ctx, job, nil, "status") n, err := actions_model.UpdateRunJob(ctx, job, nil, "status")
if err != nil { if err != nil {
return err return err
} }
if n > 0 {
updatedjobs = append(updatedjobs, job)
}
} }
} }
return nil return nil
@ -584,6 +603,11 @@ func Approve(ctx *context_module.Context) {
actions_service.CreateCommitStatus(ctx, jobs...) actions_service.CreateCommitStatus(ctx, jobs...)
for _, job := range updatedjobs {
_ = job.LoadAttributes(ctx)
notifier.CreateWorkflowJob(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
}
ctx.JSON(http.StatusOK, struct{}{}) ctx.JSON(http.StatusOK, struct{}{})
} }

View File

@ -185,6 +185,7 @@ func ParseHookEvent(form forms.WebhookForm) *webhook_module.HookEvent {
webhook_module.HookEventRepository: form.Repository, webhook_module.HookEventRepository: form.Repository,
webhook_module.HookEventPackage: form.Package, webhook_module.HookEventPackage: form.Package,
webhook_module.HookEventStatus: form.Status, webhook_module.HookEventStatus: form.Status,
webhook_module.HookEventWorkflowJob: form.WorkflowJob,
}, },
BranchFilter: form.BranchFilter, BranchFilter: form.BranchFilter,
} }

View File

@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
notifier "code.gitea.io/gitea/services/notify"
) )
// StopZombieTasks stops the task which have running status, but haven't been updated for a long time // StopZombieTasks stops the task which have running status, but haven't been updated for a long time
@ -68,7 +69,10 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error {
} }
CreateCommitStatus(ctx, jobs...) CreateCommitStatus(ctx, jobs...)
for _, job := range jobs {
_ = job.LoadAttributes(ctx)
notifier.CreateWorkflowJob(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
}
return nil return nil
} }
@ -87,14 +91,20 @@ func CancelAbandonedJobs(ctx context.Context) error {
for _, job := range jobs { for _, job := range jobs {
job.Status = actions_model.StatusCancelled job.Status = actions_model.StatusCancelled
job.Stopped = now job.Stopped = now
updated := false
if err := db.WithTx(ctx, func(ctx context.Context) error { if err := db.WithTx(ctx, func(ctx context.Context) error {
_, err := actions_model.UpdateRunJob(ctx, job, nil, "status", "stopped") n, err := actions_model.UpdateRunJob(ctx, job, nil, "status", "stopped")
updated = err == nil && n > 0
return err return err
}); err != nil { }); err != nil {
log.Warn("cancel abandoned job %v: %v", job.ID, err) log.Warn("cancel abandoned job %v: %v", job.ID, err)
// go on // go on
} }
CreateCommitStatus(ctx, job) CreateCommitStatus(ctx, job)
if updated {
_ = job.LoadAttributes(ctx)
notifier.CreateWorkflowJob(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
}
} }
return nil return nil

View File

@ -12,6 +12,7 @@ import (
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/queue" "code.gitea.io/gitea/modules/queue"
notifier "code.gitea.io/gitea/services/notify"
"github.com/nektos/act/pkg/jobparser" "github.com/nektos/act/pkg/jobparser"
"xorm.io/builder" "xorm.io/builder"
@ -49,6 +50,7 @@ func checkJobsOfRun(ctx context.Context, runID int64) error {
if err != nil { if err != nil {
return err return err
} }
var updatedjobs []*actions_model.ActionRunJob
if err := db.WithTx(ctx, func(ctx context.Context) error { if err := db.WithTx(ctx, func(ctx context.Context) error {
idToJobs := make(map[string][]*actions_model.ActionRunJob, len(jobs)) idToJobs := make(map[string][]*actions_model.ActionRunJob, len(jobs))
for _, job := range jobs { for _, job := range jobs {
@ -64,6 +66,7 @@ func checkJobsOfRun(ctx context.Context, runID int64) error {
} else if n != 1 { } else if n != 1 {
return fmt.Errorf("no affected for updating blocked job %v", job.ID) return fmt.Errorf("no affected for updating blocked job %v", job.ID)
} }
updatedjobs = append(updatedjobs, job)
} }
} }
return nil return nil
@ -71,6 +74,10 @@ func checkJobsOfRun(ctx context.Context, runID int64) error {
return err return err
} }
CreateCommitStatus(ctx, jobs...) CreateCommitStatus(ctx, jobs...)
for _, job := range updatedjobs {
_ = job.LoadAttributes(ctx)
notifier.CreateWorkflowJob(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
}
return nil return nil
} }

View File

@ -27,6 +27,7 @@ import (
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
webhook_module "code.gitea.io/gitea/modules/webhook" webhook_module "code.gitea.io/gitea/modules/webhook"
"code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/convert"
notifier "code.gitea.io/gitea/services/notify"
"github.com/nektos/act/pkg/jobparser" "github.com/nektos/act/pkg/jobparser"
"github.com/nektos/act/pkg/model" "github.com/nektos/act/pkg/model"
@ -363,6 +364,9 @@ func handleWorkflows(
continue continue
} }
CreateCommitStatus(ctx, alljobs...) CreateCommitStatus(ctx, alljobs...)
for _, job := range alljobs {
notifier.CreateWorkflowJob(ctx, input.Repo, input.Doer, job, nil)
}
} }
return nil return nil
} }

View File

@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
webhook_module "code.gitea.io/gitea/modules/webhook" webhook_module "code.gitea.io/gitea/modules/webhook"
notifier "code.gitea.io/gitea/services/notify"
"github.com/nektos/act/pkg/jobparser" "github.com/nektos/act/pkg/jobparser"
) )
@ -148,6 +149,17 @@ func CreateScheduleTask(ctx context.Context, cron *actions_model.ActionSchedule)
if err := actions_model.InsertRun(ctx, run, workflows); err != nil { if err := actions_model.InsertRun(ctx, run, workflows); err != nil {
return err return err
} }
allJobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID})
if err != nil {
log.Error("FindRunJobs: %v", err)
}
err = run.LoadAttributes(ctx)
if err != nil {
log.Error("LoadAttributes: %v", err)
}
for _, job := range allJobs {
notifier.CreateWorkflowJob(ctx, run.Repo, run.TriggerUser, job, nil)
}
// Return nil if no errors occurred // Return nil if no errors occurred
return nil return nil

View File

@ -12,13 +12,15 @@ import (
secret_model "code.gitea.io/gitea/models/secret" secret_model "code.gitea.io/gitea/models/secret"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1" runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
notifier "code.gitea.io/gitea/services/notify"
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
) )
func PickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv1.Task, bool, error) { func PickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv1.Task, bool, error) {
var ( var (
task *runnerv1.Task task *runnerv1.Task
job *actions_model.ActionRunJob job *actions_model.ActionRunJob
actionTask *actions_model.ActionTask
) )
if err := db.WithTx(ctx, func(ctx context.Context) error { if err := db.WithTx(ctx, func(ctx context.Context) error {
@ -34,6 +36,7 @@ func PickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv
return fmt.Errorf("task LoadAttributes: %w", err) return fmt.Errorf("task LoadAttributes: %w", err)
} }
job = t.Job job = t.Job
actionTask = t
secrets, err := secret_model.GetSecretsOfTask(ctx, t) secrets, err := secret_model.GetSecretsOfTask(ctx, t)
if err != nil { if err != nil {
@ -74,6 +77,7 @@ func PickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv
} }
CreateCommitStatus(ctx, job) CreateCommitStatus(ctx, job)
notifier.CreateWorkflowJob(ctx, job.Run.Repo, job.Run.TriggerUser, job, actionTask)
return task, true, nil return task, true, nil
} }

View File

@ -10,6 +10,8 @@ import (
"path" "path"
"strings" "strings"
notifier "code.gitea.io/gitea/services/notify"
actions_model "code.gitea.io/gitea/models/actions" actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/perm"
@ -276,6 +278,9 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
log.Error("FindRunJobs: %v", err) log.Error("FindRunJobs: %v", err)
} }
CreateCommitStatus(ctx, allJobs...) CreateCommitStatus(ctx, allJobs...)
for _, job := range allJobs {
notifier.CreateWorkflowJob(ctx, repo, doer, job, nil)
}
return nil return nil
} }

View File

@ -244,6 +244,7 @@ type WebhookForm struct {
Release bool Release bool
Package bool Package bool
Status bool Status bool
WorkflowJob bool
Active bool Active bool
BranchFilter string `binding:"GlobPattern"` BranchFilter string `binding:"GlobPattern"`
AuthorizationHeader string AuthorizationHeader string

View File

@ -6,6 +6,8 @@ package notify
import ( import (
"context" "context"
"code.gitea.io/gitea/models/actions"
actions_model "code.gitea.io/gitea/models/actions"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
packages_model "code.gitea.io/gitea/models/packages" packages_model "code.gitea.io/gitea/models/packages"
@ -77,4 +79,6 @@ type Notifier interface {
ChangeDefaultBranch(ctx context.Context, repo *repo_model.Repository) ChangeDefaultBranch(ctx context.Context, repo *repo_model.Repository)
CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, commit *repository.PushCommit, sender *user_model.User, status *git_model.CommitStatus) CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, commit *repository.PushCommit, sender *user_model.User, status *git_model.CommitStatus)
CreateWorkflowJob(ctx context.Context, repo *repo_model.Repository, sender *user_model.User, job *actions.ActionRunJob, task *actions_model.ActionTask)
} }

View File

@ -6,6 +6,7 @@ package notify
import ( import (
"context" "context"
actions_model "code.gitea.io/gitea/models/actions"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
packages_model "code.gitea.io/gitea/models/packages" packages_model "code.gitea.io/gitea/models/packages"
@ -374,3 +375,9 @@ func CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, commit
notifier.CreateCommitStatus(ctx, repo, commit, sender, status) notifier.CreateCommitStatus(ctx, repo, commit, sender, status)
} }
} }
func CreateWorkflowJob(ctx context.Context, repo *repo_model.Repository, sender *user_model.User, job *actions_model.ActionRunJob, task *actions_model.ActionTask) {
for _, notifier := range notifiers {
notifier.CreateWorkflowJob(ctx, repo, sender, job, task)
}
}

View File

@ -6,6 +6,7 @@ package notify
import ( import (
"context" "context"
actions_model "code.gitea.io/gitea/models/actions"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
packages_model "code.gitea.io/gitea/models/packages" packages_model "code.gitea.io/gitea/models/packages"
@ -212,3 +213,6 @@ func (*NullNotifier) ChangeDefaultBranch(ctx context.Context, repo *repo_model.R
func (*NullNotifier) CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, commit *repository.PushCommit, sender *user_model.User, status *git_model.CommitStatus) { func (*NullNotifier) CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, commit *repository.PushCommit, sender *user_model.User, status *git_model.CommitStatus) {
} }
func (*NullNotifier) CreateWorkflowJob(ctx context.Context, repo *repo_model.Repository, sender *user_model.User, job *actions_model.ActionRunJob, task *actions_model.ActionTask) {
}

View File

@ -6,6 +6,7 @@ package webhook
import ( import (
"context" "context"
actions_model "code.gitea.io/gitea/models/actions"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/organization"
@ -941,3 +942,86 @@ func notifyPackage(ctx context.Context, sender *user_model.User, pd *packages_mo
log.Error("PrepareWebhooks: %v", err) log.Error("PrepareWebhooks: %v", err)
} }
} }
func (*webhookNotifier) CreateWorkflowJob(ctx context.Context, repo *repo_model.Repository, sender *user_model.User, job *actions_model.ActionRunJob, task *actions_model.ActionTask) {
source := EventSource{
Repository: repo,
Owner: repo.Owner,
}
var org *api.Organization
if repo.Owner.IsOrganization() {
org = convert.ToOrganization(ctx, organization.OrgFromUser(repo.Owner))
}
job.LoadAttributes(ctx)
action, conclusion := toActionStatus(job.Status)
var runnerId int64
var steps []*api.ActionWorkflowStep
if task != nil {
runnerId = task.RunnerID
for i, step := range task.Steps {
_, stepConclusion := toActionStatus(job.Status)
steps = append(steps, &api.ActionWorkflowStep{
Name: step.Name,
Number: int64(i),
Conclusion: stepConclusion,
StartedAt: step.Started.AsTime().UTC(),
CompletedAt: step.Stopped.AsTime().UTC(),
})
}
}
if err := PrepareWebhooks(ctx, source, webhook_module.HookEventWorkflowJob, &api.WorkflowJobPayload{
Action: action,
WorkflowJob: &api.ActionWorkflowJob{
ID: job.ID,
RunID: job.RunID,
RunURL: job.Run.HTMLURL(),
Name: job.Name,
Labels: job.RunsOn,
RunAttempt: job.Attempt,
HeadSha: job.Run.CommitSHA,
HeadBranch: git.RefName(job.Run.Ref).BranchName(),
Conclusion: conclusion,
RunnerID: runnerId,
Steps: steps,
CreatedAt: job.Created.AsTime().UTC(),
StartedAt: job.Started.AsTime().UTC(),
CompletedAt: job.Stopped.AsTime().UTC(),
},
Organization: org,
Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
Sender: convert.ToUser(ctx, sender, nil),
}); err != nil {
log.Error("PrepareWebhooks: %v", err)
}
}
func toActionStatus(status actions_model.Status) (string, string) {
var action string
var conclusion string
switch status {
// This is a naming conflict of the webhook between Gitea and GitHub Actions
case actions_model.StatusWaiting:
action = "queued"
case actions_model.StatusBlocked:
action = "waiting"
case actions_model.StatusRunning:
action = "in_progress"
}
if status.IsDone() {
action = "completed"
switch status {
case actions_model.StatusSuccess:
conclusion = "success"
case actions_model.StatusCancelled:
conclusion = "cancelled"
case actions_model.StatusFailure:
conclusion = "failure"
}
}
return action, conclusion
}

View File

@ -259,6 +259,16 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Workflow Job Event -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input name="workflow_job" type="checkbox" {{if .Webhook.HookEvents.Get "workflow_job"}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.settings.event_workflow_job"}}</label>
<span class="help">{{ctx.Locale.Tr "repo.settings.event_workflow_job_desc"}}</span>
</div>
</div>
</div>
</div> </div>
</div> </div>