diff --git a/modules/structs/workflow.go b/modules/structs/workflow.go index c4429ea0a2..f8f1e5a7a5 100644 --- a/modules/structs/workflow.go +++ b/modules/structs/workflow.go @@ -12,4 +12,16 @@ type DispatchWorkflowOption struct { Ref string `json:"ref"` // Input keys and values configured in the workflow file. Inputs map[string]string `json:"inputs"` + // Flag to return the run info + // default: false + ReturnRunInfo bool `json:"return_run_info"` +} + +// DispatchWorkflowRun represents a workflow run +// swagger:model +type DispatchWorkflowRun struct { + // the workflow run id + ID int64 `json:"id"` + // the jobs name + Jobs []string `json:"jobs"` } diff --git a/routers/api/v1/repo/action.go b/routers/api/v1/repo/action.go index 3256b1544a..a2cc70f4d7 100644 --- a/routers/api/v1/repo/action.go +++ b/routers/api/v1/repo/action.go @@ -670,7 +670,8 @@ func DispatchWorkflow(ctx *context.APIContext) { return opt.Inputs[key] } - if err := workflow.Dispatch(ctx, inputGetter, ctx.Repo.Repository, ctx.Doer); err != nil { + run, jobs, err := workflow.Dispatch(ctx, inputGetter, ctx.Repo.Repository, ctx.Doer) + if err != nil { if actions_service.IsInputRequiredErr(err) { ctx.Error(http.StatusBadRequest, "workflow.Dispatch", err) } else { @@ -679,5 +680,14 @@ func DispatchWorkflow(ctx *context.APIContext) { return } - ctx.JSON(http.StatusNoContent, nil) + workflowRun := &api.DispatchWorkflowRun{ + ID: run.ID, + Jobs: jobs, + } + + if opt.ReturnRunInfo { + ctx.JSON(http.StatusCreated, workflowRun) + } else { + ctx.JSON(http.StatusNoContent, nil) + } } diff --git a/routers/api/v1/swagger/action.go b/routers/api/v1/swagger/action.go index e7ec6a81e4..2174b1ff17 100644 --- a/routers/api/v1/swagger/action.go +++ b/routers/api/v1/swagger/action.go @@ -39,3 +39,10 @@ type swaggerRunJobList struct { // in:body Body []*api.ActionRunJob `json:"body"` } + +// DispatchWorkflowRun is a Workflow Run after dispatching +// swagger:response DispatchWorkflowRun +type swaggerDispatchWorkflowRun struct { + // in:body + Body *api.DispatchWorkflowRun `json:"body"` +} diff --git a/routers/web/repo/actions/manual.go b/routers/web/repo/actions/manual.go index 949469fa21..285dc7ab7e 100644 --- a/routers/web/repo/actions/manual.go +++ b/routers/web/repo/actions/manual.go @@ -46,7 +46,8 @@ func ManualRunWorkflow(ctx *context_module.Context) { return ctx.Req.PostFormValue(formKey) } - if err := workflow.Dispatch(ctx, formKeyGetter, ctx.Repo.Repository, ctx.Doer); err != nil { + _, _, err = workflow.Dispatch(ctx, formKeyGetter, ctx.Repo.Repository, ctx.Doer) + if err != nil { if actions_service.IsInputRequiredErr(err) { ctx.Flash.Error(ctx.Locale.Tr("actions.workflow.dispatch.input_required", err.(actions_service.InputRequiredErr).Name)) ctx.Redirect(location) diff --git a/services/actions/workflows.go b/services/actions/workflows.go index e2fb31622a..e3e342264d 100644 --- a/services/actions/workflows.go +++ b/services/actions/workflows.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/webhook" "code.gitea.io/gitea/services/convert" @@ -49,15 +50,15 @@ type Workflow struct { type InputValueGetter func(key string) string -func (entry *Workflow) Dispatch(ctx context.Context, inputGetter InputValueGetter, repo *repo_model.Repository, doer *user.User) error { +func (entry *Workflow) Dispatch(ctx context.Context, inputGetter InputValueGetter, repo *repo_model.Repository, doer *user.User) (r *actions_model.ActionRun, j []string, err error) { content, err := actions.GetContentFromEntry(entry.GitEntry) if err != nil { - return err + return nil, nil, err } wf, err := act_model.ReadWorkflow(bytes.NewReader(content)) if err != nil { - return err + return nil, nil, err } fullWorkflowID := ".forgejo/workflows/" + entry.WorkflowID @@ -79,7 +80,7 @@ func (entry *Workflow) Dispatch(ctx context.Context, inputGetter InputValueGette if len(name) == 0 { name = key } - return InputRequiredErr{Name: name} + return nil, nil, InputRequiredErr{Name: name} } continue } @@ -92,9 +93,11 @@ func (entry *Workflow) Dispatch(ctx context.Context, inputGetter InputValueGette } if int64(len(inputs)) > setting.Actions.LimitDispatchInputs { - return errors.New("to many inputs") + return nil, nil, errors.New("to many inputs") } + jobNames := util.KeysOfMap(wf.Jobs) + payload := &structs.WorkflowDispatchPayload{ Inputs: inputs, Ref: entry.Ref, @@ -105,7 +108,7 @@ func (entry *Workflow) Dispatch(ctx context.Context, inputGetter InputValueGette p, err := json.Marshal(payload) if err != nil { - return err + return nil, nil, err } run := &actions_model.ActionRun{ @@ -126,15 +129,15 @@ func (entry *Workflow) Dispatch(ctx context.Context, inputGetter InputValueGette vars, err := actions_model.GetVariablesOfRun(ctx, run) if err != nil { - return err + return nil, nil, err } jobs, err := jobparser.Parse(content, jobparser.WithVars(vars)) if err != nil { - return err + return nil, nil, err } - return actions_model.InsertRun(ctx, run, jobs) + return run, jobNames, actions_model.InsertRun(ctx, run, jobs) } func GetWorkflowFromCommit(gitRepo *git.Repository, ref, workflowID string) (*Workflow, error) { diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 1399442676..eb891d5a8a 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -23128,6 +23128,33 @@ "description": "Git reference for the workflow", "type": "string", "x-go-name": "Ref" + }, + "return_run_info": { + "description": "Flag to return the run info", + "type": "boolean", + "default": false, + "x-go-name": "ReturnRunInfo" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, + "DispatchWorkflowRun": { + "description": "DispatchWorkflowRun represents a workflow run", + "type": "object", + "properties": { + "id": { + "description": "the workflow run id", + "type": "integer", + "format": "int64", + "x-go-name": "ID" + }, + "jobs": { + "description": "the jobs name", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Jobs" } }, "x-go-package": "code.gitea.io/gitea/modules/structs" @@ -28511,6 +28538,12 @@ } } }, + "DispatchWorkflowRun": { + "description": "DispatchWorkflowRun is a Workflow Run after dispatching", + "schema": { + "$ref": "#/definitions/DispatchWorkflowRun" + } + }, "EmailList": { "description": "EmailList", "schema": { diff --git a/tests/integration/actions_trigger_test.go b/tests/integration/actions_trigger_test.go index 25bdc8018f..ecdf8b7076 100644 --- a/tests/integration/actions_trigger_test.go +++ b/tests/integration/actions_trigger_test.go @@ -752,9 +752,18 @@ func TestWorkflowDispatchEvent(t *testing.T) { return "" } - err = workflow.Dispatch(db.DefaultContext, inputGetter, repo, user2) + var r *actions_model.ActionRun + var j []string + r, j, err = workflow.Dispatch(db.DefaultContext, inputGetter, repo, user2) require.NoError(t, err) assert.Equal(t, 1, unittest.GetCount(t, &actions_model.ActionRun{RepoID: repo.ID})) + + assert.Equal(t, "test", r.Title) + assert.Equal(t, "dispatch.yml", r.WorkflowID) + assert.Equal(t, sha, r.CommitSHA) + assert.Equal(t, actions_module.GithubEventWorkflowDispatch, r.TriggerEvent) + assert.Len(t, j, 1) + assert.Equal(t, "test", j[0]) }) }