diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index c497f1be6..344f92be4 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/docs/content/doc/administration/config-cheat-sheet.en-us.md b/docs/content/doc/administration/config-cheat-sheet.en-us.md index e7e482fc7..9bb2533da 100644 --- a/docs/content/doc/administration/config-cheat-sheet.en-us.md +++ b/docs/content/doc/administration/config-cheat-sheet.en-us.md @@ -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`) diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 8f20ef085..71cd9a12a 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -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 { diff --git a/modules/templates/htmlrenderer.go b/modules/templates/htmlrenderer.go index 21c268da7..e0cbc49ff 100644 --- a/modules/templates/htmlrenderer.go +++ b/modules/templates/htmlrenderer.go @@ -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 @@ -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 { @@ -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 { diff --git a/modules/templates/mailer.go b/modules/templates/mailer.go index ac1715fcd..54d857a8f 100644 --- a/modules/templates/mailer.go +++ b/modules/templates/mailer.go @@ -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) @@ -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