Skip to content

Commit 2807d08

Browse files
committed
use golang err handling approach
1 parent aa80af0 commit 2807d08

File tree

4 files changed

+75
-62
lines changed

4 files changed

+75
-62
lines changed

modules/util/error.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,22 @@ func (w SilentWrap) Unwrap() error {
3636
return w.Err
3737
}
3838

39+
type LocaleWrap struct {
40+
err error
41+
TrKey string
42+
TrArgs []any
43+
}
44+
45+
// Error returns the message
46+
func (w LocaleWrap) Error() string {
47+
return w.err.Error()
48+
}
49+
50+
// Unwrap returns the underlying error
51+
func (w LocaleWrap) Unwrap() error {
52+
return w.err
53+
}
54+
3955
// NewSilentWrapErrorf returns an error that formats as the given text but unwraps as the provided error
4056
func NewSilentWrapErrorf(unwrap error, message string, args ...any) error {
4157
if len(args) == 0 {
@@ -63,3 +79,16 @@ func NewAlreadyExistErrorf(message string, args ...any) error {
6379
func NewNotExistErrorf(message string, args ...any) error {
6480
return NewSilentWrapErrorf(ErrNotExist, message, args...)
6581
}
82+
83+
// ErrWrapLocale wraps an err with a translation key and arguments
84+
func ErrWrapLocale(err error, trKey string, trArgs ...any) error {
85+
return LocaleWrap{err: err, TrKey: trKey, TrArgs: trArgs}
86+
}
87+
88+
func ErrAsLocale(err error) *LocaleWrap {
89+
var e LocaleWrap
90+
if errors.As(err, &e) {
91+
return &e
92+
}
93+
return nil
94+
}

routers/api/v1/repo/action.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package repo
55

66
import (
77
"errors"
8-
"fmt"
98
"net/http"
109

1110
actions_model "code.gitea.io/gitea/models/actions"
@@ -786,34 +785,35 @@ func ActionsDispatchWorkflow(ctx *context.APIContext) {
786785
Base: ctx.Base,
787786
Doer: ctx.Doer,
788787
Repo: ctx.Repo,
789-
}, workflowID, ref, func(workflowDispatch *model.WorkflowDispatch, inputs *map[string]any) error {
788+
}, workflowID, ref, func(workflowDispatch *model.WorkflowDispatch, inputs map[string]any) error {
790789
if workflowDispatch != nil {
791790
// TODO figure out why the inputs map is empty for url form encoding workaround
792791
if opt.Inputs == nil {
793792
for name, config := range workflowDispatch.Inputs {
794793
value := ctx.FormString("inputs["+name+"]", config.Default)
795-
(*inputs)[name] = value
794+
inputs[name] = value
796795
}
797796
} else {
798797
for name, config := range workflowDispatch.Inputs {
799798
value, ok := opt.Inputs[name]
800799
if ok {
801-
(*inputs)[name] = value
800+
inputs[name] = value
802801
} else {
803-
(*inputs)[name] = config.Default
802+
inputs[name] = config.Default
804803
}
805804
}
806805
}
807806
}
808807
return nil
809808
})
810809
if err != nil {
811-
if terr, ok := err.(*actions_service.TranslateableError); ok {
812-
msg := ctx.Locale.TrString(terr.Translation, terr.Args...)
813-
ctx.Error(terr.GetCode(), msg, fmt.Errorf("%s", msg))
814-
return
810+
if errors.Is(err, util.ErrNotExist) {
811+
ctx.Error(http.StatusNotFound, "DispatchActionWorkflow", err)
812+
} else if errors.Is(err, util.ErrPermissionDenied) {
813+
ctx.Error(http.StatusForbidden, "DispatchActionWorkflow", err)
814+
} else {
815+
ctx.Error(http.StatusInternalServerError, "DispatchActionWorkflow", err)
815816
}
816-
ctx.Error(http.StatusInternalServerError, err.Error(), err)
817817
return
818818
}
819819

routers/web/repo/actions/view.go

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -787,33 +787,28 @@ func Run(ctx *context_module.Context) {
787787
ctx.ServerError("ref", nil)
788788
return
789789
}
790-
err := actions_service.DispatchActionWorkflow(ctx, workflowID, ref, func(workflowDispatch *model.WorkflowDispatch, inputs *map[string]any) error {
790+
err := actions_service.DispatchActionWorkflow(ctx, workflowID, ref, func(workflowDispatch *model.WorkflowDispatch, inputs map[string]any) error {
791791
if workflowDispatch != nil {
792792
for name, config := range workflowDispatch.Inputs {
793793
value := ctx.Req.PostFormValue(name)
794794
if config.Type == "boolean" {
795-
// https://www.w3.org/TR/html401/interact/forms.html
796-
// https://stackoverflow.com/questions/11424037/do-checkbox-inputs-only-post-data-if-theyre-checked
797-
// Checkboxes (and radio buttons) are on/off switches that may be toggled by the user.
798-
// A switch is "on" when the control element's checked attribute is set.
799-
// When a form is submitted, only "on" checkbox controls can become successful.
800-
(*inputs)[name] = strconv.FormatBool(value == "on")
795+
inputs[name] = ctx.FormBool(name)
801796
} else if value != "" {
802-
(*inputs)[name] = value
797+
inputs[name] = value
803798
} else {
804-
(*inputs)[name] = config.Default
799+
inputs[name] = config.Default
805800
}
806801
}
807802
}
808803
return nil
809804
})
810805
if err != nil {
811-
if terr, ok := err.(*actions_service.TranslateableError); ok {
812-
ctx.Flash.Error(ctx.Tr(terr.Translation, terr.Args...))
806+
if errLocale := util.ErrAsLocale(err); errLocale != nil {
807+
ctx.Flash.Error(ctx.Tr(errLocale.TrKey, errLocale.TrArgs...))
813808
ctx.Redirect(redirectURL)
814-
return
809+
} else {
810+
ctx.ServerError("DispatchActionWorkflow", err)
815811
}
816-
ctx.ServerError(err.Error(), err)
817812
return
818813
}
819814

services/actions/workflow.go

Lines changed: 28 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,14 @@ import (
1919
"code.gitea.io/gitea/modules/git"
2020
"code.gitea.io/gitea/modules/log"
2121
api "code.gitea.io/gitea/modules/structs"
22+
"code.gitea.io/gitea/modules/util"
2223
"code.gitea.io/gitea/services/context"
2324
"code.gitea.io/gitea/services/convert"
2425

2526
"github.com/nektos/act/pkg/jobparser"
2627
"github.com/nektos/act/pkg/model"
2728
)
2829

29-
type TranslateableError struct {
30-
Translation string
31-
Args []any
32-
Code int
33-
}
34-
35-
func (t TranslateableError) Error() string {
36-
return t.Translation
37-
}
38-
39-
func (t TranslateableError) GetCode() int {
40-
if t.Code == 0 {
41-
return http.StatusInternalServerError
42-
}
43-
return t.Code
44-
}
45-
4630
func getActionWorkflowPath(commit *git.Commit) string {
4731
paths := []string{".gitea/workflows", ".github/workflows"}
4832
for _, path := range paths {
@@ -156,22 +140,29 @@ func DisableActionWorkflow(ctx *context.APIContext, workflowID string) error {
156140
return disableOrEnableWorkflow(ctx, workflowID, false)
157141
}
158142

159-
func DispatchActionWorkflow(ctx *context.Context, workflowID, ref string, processInputs func(model *model.WorkflowDispatch, inputs *map[string]any) error) error {
160-
if len(workflowID) == 0 {
161-
return fmt.Errorf("workflowID is empty")
143+
func DispatchActionWorkflow(ctx *context.Context, workflowID, ref string, processInputs func(model *model.WorkflowDispatch, inputs map[string]any) error) error {
144+
if workflowID == "" {
145+
return util.ErrWrapLocale(
146+
util.NewNotExistErrorf("workflowID is empty"),
147+
"actions.workflow.not_found", workflowID,
148+
)
162149
}
163150

164-
if len(ref) == 0 {
165-
return fmt.Errorf("ref is empty")
151+
if ref == "" {
152+
return util.ErrWrapLocale(
153+
util.NewNotExistErrorf("ref is empty"),
154+
"form.target_ref_not_exist", ref,
155+
)
166156
}
167157

168158
// can not rerun job when workflow is disabled
169159
cfgUnit := ctx.Repo.Repository.MustGetUnit(ctx, unit.TypeActions)
170160
cfg := cfgUnit.ActionsConfig()
171161
if cfg.IsWorkflowDisabled(workflowID) {
172-
return &TranslateableError{
173-
Translation: "actions.workflow.disabled",
174-
}
162+
return util.ErrWrapLocale(
163+
util.NewPermissionDeniedErrorf("workflow is disabled"),
164+
"actions.workflow.disabled",
165+
)
175166
}
176167

177168
// get target commit of run from specified ref
@@ -187,11 +178,10 @@ func DispatchActionWorkflow(ctx *context.Context, workflowID, ref string, proces
187178
runTargetCommit, err = ctx.Repo.GitRepo.GetBranchCommit(ref)
188179
}
189180
if err != nil {
190-
return &TranslateableError{
191-
Code: http.StatusNotFound,
192-
Translation: "form.target_ref_not_exist",
193-
Args: []any{ref},
194-
}
181+
return util.ErrWrapLocale(
182+
util.NewNotExistErrorf("ref %q doesn't exist", ref),
183+
"form.target_ref_not_exist", ref,
184+
)
195185
}
196186

197187
// get workflow entry from runTargetCommit
@@ -219,11 +209,10 @@ func DispatchActionWorkflow(ctx *context.Context, workflowID, ref string, proces
219209
}
220210

221211
if len(workflows) == 0 {
222-
return &TranslateableError{
223-
Code: http.StatusNotFound,
224-
Translation: "actions.workflow.not_found",
225-
Args: []any{workflowID},
226-
}
212+
return util.ErrWrapLocale(
213+
util.NewNotExistErrorf("workflow %q doesn't exist", workflowID),
214+
"actions.workflow.not_found", workflowID,
215+
)
227216
}
228217

229218
// get inputs from post
@@ -232,7 +221,7 @@ func DispatchActionWorkflow(ctx *context.Context, workflowID, ref string, proces
232221
}
233222
inputsWithDefaults := make(map[string]any)
234223
workflowDispatch := workflow.WorkflowDispatchConfig()
235-
if err := processInputs(workflowDispatch, &inputsWithDefaults); err != nil {
224+
if err := processInputs(workflowDispatch, inputsWithDefaults); err != nil {
236225
return err
237226
}
238227

@@ -279,14 +268,14 @@ func DispatchActionWorkflow(ctx *context.Context, workflowID, ref string, proces
279268

280269
// Insert the action run and its associated jobs into the database
281270
if err := actions_model.InsertRun(ctx, run, workflows); err != nil {
282-
return fmt.Errorf("workflow: %w", err)
271+
return fmt.Errorf("InsertRun: %w", err)
283272
}
284273

285-
alljobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID})
274+
allJobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID})
286275
if err != nil {
287276
log.Error("FindRunJobs: %v", err)
288277
}
289-
CreateCommitStatus(ctx, alljobs...)
278+
CreateCommitStatus(ctx, allJobs...)
290279

291280
return nil
292281
}

0 commit comments

Comments
 (0)