aboutsummaryrefslogtreecommitdiffstats
path: root/routers/web
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2025-02-11 03:05:42 +0800
committerGitHub <noreply@github.com>2025-02-11 03:05:42 +0800
commit30993e95082356daa40b3605bff65b565e913bcc (patch)
treedecb86d86ce6bbc783f5b72ff297eb98db378f1a /routers/web
parent085f273d19a30cc7cb7f6315a15a95c2b59fc5b9 (diff)
downloadgitea-30993e95082356daa40b3605bff65b565e913bcc.tar.gz
gitea-30993e95082356daa40b3605bff65b565e913bcc.zip
Feature: Support workflow event dispatch via API (#33545)
Fix: https://github.com/go-gitea/gitea/issues/31765 (Re-open #32059) --------- Co-authored-by: Bence Santha <git@santha.eu> Co-authored-by: Bence Sántha <7604637+bencurio@users.noreply.github.com> Co-authored-by: Christopher Homberger <christopher.homberger@web.de>
Diffstat (limited to 'routers/web')
-rw-r--r--routers/web/repo/actions/view.go141
1 files changed, 11 insertions, 130 deletions
diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go
index fc346b83b4..7099582c1b 100644
--- a/routers/web/repo/actions/view.go
+++ b/routers/web/repo/actions/view.go
@@ -20,8 +20,6 @@ import (
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
- "code.gitea.io/gitea/models/perm"
- access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/actions"
@@ -30,16 +28,13 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
- api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
actions_service "code.gitea.io/gitea/services/actions"
context_module "code.gitea.io/gitea/services/context"
- "code.gitea.io/gitea/services/convert"
- "github.com/nektos/act/pkg/jobparser"
"github.com/nektos/act/pkg/model"
"xorm.io/builder"
)
@@ -792,142 +787,28 @@ func Run(ctx *context_module.Context) {
ctx.ServerError("ref", nil)
return
}
-
- // can not rerun job when workflow is disabled
- cfgUnit := ctx.Repo.Repository.MustGetUnit(ctx, unit.TypeActions)
- cfg := cfgUnit.ActionsConfig()
- if cfg.IsWorkflowDisabled(workflowID) {
- ctx.Flash.Error(ctx.Tr("actions.workflow.disabled"))
- ctx.Redirect(redirectURL)
- return
- }
-
- // get target commit of run from specified ref
- refName := git.RefName(ref)
- var runTargetCommit *git.Commit
- var err error
- if refName.IsTag() {
- runTargetCommit, err = ctx.Repo.GitRepo.GetTagCommit(refName.TagName())
- } else if refName.IsBranch() {
- runTargetCommit, err = ctx.Repo.GitRepo.GetBranchCommit(refName.BranchName())
- } else {
- ctx.Flash.Error(ctx.Tr("form.git_ref_name_error", ref))
- ctx.Redirect(redirectURL)
- return
- }
- if err != nil {
- ctx.Flash.Error(ctx.Tr("form.target_ref_not_exist", ref))
- ctx.Redirect(redirectURL)
- return
- }
-
- // get workflow entry from runTargetCommit
- entries, err := actions.ListWorkflows(runTargetCommit)
- if err != nil {
- ctx.Error(http.StatusInternalServerError, err.Error())
- return
- }
-
- // find workflow from commit
- var workflows []*jobparser.SingleWorkflow
- for _, entry := range entries {
- if entry.Name() == workflowID {
- content, err := actions.GetContentFromEntry(entry)
- if err != nil {
- ctx.Error(http.StatusInternalServerError, err.Error())
- return
- }
- workflows, err = jobparser.Parse(content)
- if err != nil {
- ctx.ServerError("workflow", err)
- return
- }
- break
- }
- }
-
- if len(workflows) == 0 {
- ctx.Flash.Error(ctx.Tr("actions.workflow.not_found", workflowID))
- ctx.Redirect(redirectURL)
- return
- }
-
- // get inputs from post
- workflow := &model.Workflow{
- RawOn: workflows[0].RawOn,
- }
- inputs := make(map[string]any)
- if workflowDispatch := workflow.WorkflowDispatchConfig(); workflowDispatch != nil {
+ err := actions_service.DispatchActionWorkflow(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, workflowID, ref, func(workflowDispatch *model.WorkflowDispatch, inputs map[string]any) error {
for name, config := range workflowDispatch.Inputs {
value := ctx.Req.PostFormValue(name)
if config.Type == "boolean" {
- // https://www.w3.org/TR/html401/interact/forms.html
- // https://stackoverflow.com/questions/11424037/do-checkbox-inputs-only-post-data-if-theyre-checked
- // Checkboxes (and radio buttons) are on/off switches that may be toggled by the user.
- // A switch is "on" when the control element's checked attribute is set.
- // When a form is submitted, only "on" checkbox controls can become successful.
- inputs[name] = strconv.FormatBool(value == "on")
+ inputs[name] = strconv.FormatBool(ctx.FormBool(name))
} else if value != "" {
inputs[name] = value
} else {
inputs[name] = config.Default
}
}
- }
-
- // ctx.Req.PostForm -> WorkflowDispatchPayload.Inputs -> ActionRun.EventPayload -> runner: ghc.Event
- // https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
- // https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_dispatch
- workflowDispatchPayload := &api.WorkflowDispatchPayload{
- Workflow: workflowID,
- Ref: ref,
- Repository: convert.ToRepo(ctx, ctx.Repo.Repository, access_model.Permission{AccessMode: perm.AccessModeNone}),
- Inputs: inputs,
- Sender: convert.ToUserWithAccessMode(ctx, ctx.Doer, perm.AccessModeNone),
- }
- var eventPayload []byte
- if eventPayload, err = workflowDispatchPayload.JSONPayload(); err != nil {
- ctx.ServerError("JSONPayload", err)
- return
- }
-
- run := &actions_model.ActionRun{
- Title: strings.SplitN(runTargetCommit.CommitMessage, "\n", 2)[0],
- RepoID: ctx.Repo.Repository.ID,
- OwnerID: ctx.Repo.Repository.OwnerID,
- WorkflowID: workflowID,
- TriggerUserID: ctx.Doer.ID,
- Ref: ref,
- CommitSHA: runTargetCommit.ID.String(),
- IsForkPullRequest: false,
- Event: "workflow_dispatch",
- TriggerEvent: "workflow_dispatch",
- EventPayload: string(eventPayload),
- Status: actions_model.StatusWaiting,
- }
-
- // cancel running jobs of the same workflow
- if err := actions_model.CancelPreviousJobs(
- ctx,
- run.RepoID,
- run.Ref,
- run.WorkflowID,
- run.Event,
- ); err != nil {
- log.Error("CancelRunningJobs: %v", err)
- }
-
- // Insert the action run and its associated jobs into the database
- if err := actions_model.InsertRun(ctx, run, workflows); err != nil {
- ctx.ServerError("workflow", err)
- return
- }
-
- alljobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID})
+ return nil
+ })
if err != nil {
- log.Error("FindRunJobs: %v", err)
+ if errLocale := util.ErrAsLocale(err); errLocale != nil {
+ ctx.Flash.Error(ctx.Tr(errLocale.TrKey, errLocale.TrArgs...))
+ ctx.Redirect(redirectURL)
+ } else {
+ ctx.ServerError("DispatchActionWorkflow", err)
+ }
+ return
}
- actions_service.CreateCommitStatus(ctx, alljobs...)
ctx.Flash.Success(ctx.Tr("actions.workflow.run_success", workflowID))
ctx.Redirect(redirectURL)