Skip to content

Commit

Permalink
Improve RunMode / dev mode (#24886)
Browse files Browse the repository at this point in the history
1. non-dev mode is treated as prod mode, to protect users from
accidentally running in dev mode if there is a typo in this value.
2. in dev mode, do not need to really exit if there are template errors,
because the template errors could be fixed by developer soon and the
templates get reloaded, help:
* #24845 (comment)
3. Fine tune the mail template loading message.
  • Loading branch information
wxiaoguang authored May 25, 2023
1 parent 694b38b commit 5f39285
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 15 deletions.
5 changes: 3 additions & 2 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ APP_NAME = ; Gitea: Git with a cup of tea
;; RUN_USER will automatically detect the current user - but you can set it here change it if you run locally
RUN_USER = ; git
;;
;; Application run mode, affects performance and debugging. Either "dev", "prod" or "test", default is "prod"
RUN_MODE = ; prod
;; Application run mode, affects performance and debugging: "dev" or "prod", default is "prod"
;; Mode "dev" makes Gitea easier to develop and debug, values other than "dev" are treated as "prod" which is for production use.
;RUN_MODE = prod

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ In addition there is _`StaticRootPath`_ which can be set as a built-in at build
- `RUN_USER`: **_current OS username_/`$USER`/`$USERNAME` e.g. git**: The user Gitea will run as.
This should be a dedicated system (non-user) account. Setting this incorrectly will cause Gitea
to not start.
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging. Either "dev", "prod" or "test".
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging: `dev` or `prod`, default is `prod`. Mode `dev` makes Gitea easier to develop and debug, values other than `dev` are treated as `prod` which is for production use.

## Repository (`repository`)

Expand Down
8 changes: 7 additions & 1 deletion modules/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,13 @@ func loadRunModeFrom(rootCfg ConfigProvider) {
if RunMode == "" {
RunMode = rootSec.Key("RUN_MODE").MustString("prod")
}
IsProd = strings.EqualFold(RunMode, "prod")

// non-dev mode is treated as prod mode, to protect users from accidentally running in dev mode if there is a typo in this value.
RunMode = strings.ToLower(RunMode)
if RunMode != "dev" {
RunMode = "prod"
}
IsProd = RunMode != "dev"

// check if we run as root
if os.Getuid() == 0 {
Expand Down
21 changes: 14 additions & 7 deletions modules/templates/htmlrenderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ func HTMLRenderer() *HTMLRender {
}

func ReloadHTMLTemplates() error {
log.Trace("Reloading HTML templates")
if err := htmlRender.CompileTemplates(); err != nil {
log.Error("Template error: %v\n%s", err, log.Stack(2))
return err
Expand All @@ -114,11 +115,11 @@ func initHTMLRenderer() {
htmlRender = &HTMLRender{}
if err := htmlRender.CompileTemplates(); err != nil {
p := &templateErrorPrettier{assets: AssetFS()}
wrapFatal(p.handleFuncNotDefinedError(err))
wrapFatal(p.handleUnexpectedOperandError(err))
wrapFatal(p.handleExpectedEndError(err))
wrapFatal(p.handleGenericTemplateError(err))
log.Fatal("HTMLRenderer CompileTemplates error: %v", err)
wrapTmplErrMsg(p.handleFuncNotDefinedError(err))
wrapTmplErrMsg(p.handleUnexpectedOperandError(err))
wrapTmplErrMsg(p.handleExpectedEndError(err))
wrapTmplErrMsg(p.handleGenericTemplateError(err))
wrapTmplErrMsg(fmt.Sprintf("CompileTemplates error: %v", err))
}

if !setting.IsProd {
Expand All @@ -128,11 +129,17 @@ func initHTMLRenderer() {
}
}

func wrapFatal(msg string) {
func wrapTmplErrMsg(msg string) {
if msg == "" {
return
}
log.Fatal("Unable to compile templates, %s", msg)
if setting.IsProd {
// in prod mode, Gitea must have correct templates to run
log.Fatal("Gitea can't run with template errors: %s", msg)
} else {
// in dev mode, do not need to really exit, because the template errors could be fixed by developer soon and the templates get reloaded
log.Error("There are template errors but Gitea continues to run in dev mode: %s", msg)
}
}

type templateErrorPrettier struct {
Expand Down
15 changes: 11 additions & 4 deletions modules/templates/mailer.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ func Mailer(ctx context.Context) (*texttmpl.Template, *template.Template) {
bodyTemplates.Funcs(NewFuncMap())

assetFS := AssetFS()
refreshTemplates := func() {
refreshTemplates := func(firstRun bool) {
if !firstRun {
log.Trace("Reloading mail templates")
}
assetPaths, err := ListMailTemplateAssetNames(assetFS)
if err != nil {
log.Error("Failed to list mail templates: %v", err)
Expand All @@ -75,17 +78,21 @@ func Mailer(ctx context.Context) (*texttmpl.Template, *template.Template) {
continue
}
tmplName := strings.TrimPrefix(strings.TrimSuffix(assetPath, ".tmpl"), "mail/")
log.Trace("Adding mail template %s: %s by %s", tmplName, assetPath, layerName)
if firstRun {
log.Trace("Adding mail template %s: %s by %s", tmplName, assetPath, layerName)
}
buildSubjectBodyTemplate(subjectTemplates, bodyTemplates, tmplName, content)
}
}

refreshTemplates()
refreshTemplates(true)

if !setting.IsProd {
// Now subjectTemplates and bodyTemplates are both synchronized
// thus it is safe to call refresh from a different goroutine
go assetFS.WatchLocalChanges(ctx, refreshTemplates)
go assetFS.WatchLocalChanges(ctx, func() {
refreshTemplates(false)
})
}

return subjectTemplates, bodyTemplates
Expand Down

0 comments on commit 5f39285

Please sign in to comment.