From 1a5ed79abc4004ac114f8aca3821f2c7da903d49 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 21 May 2023 15:39:34 +0200 Subject: [PATCH 1/5] Add git manager reload-templates command to reload templates This can be useful to update custom templates in production mode, when they are updated frequently and a full gitea restart each time is disruptive. --- cmd/manager.go | 20 ++++++++++++++++++++ modules/private/manager.go | 7 +++++++ modules/templates/htmlrenderer.go | 10 +++++++--- routers/private/internal.go | 1 + routers/private/manager.go | 7 +++++++ 5 files changed, 42 insertions(+), 3 deletions(-) diff --git a/cmd/manager.go b/cmd/manager.go index 3f1e2231903ae..2024d5ebbda97 100644 --- a/cmd/manager.go +++ b/cmd/manager.go @@ -21,6 +21,7 @@ var ( Subcommands: []cli.Command{ subcmdShutdown, subcmdRestart, + subcmdReloadTemplates, subcmdFlushQueues, subcmdLogging, subCmdProcesses, @@ -46,6 +47,16 @@ var ( }, Action: runRestart, } + subcmdReloadTemplates = cli.Command{ + Name: "reload-templates", + Usage: "Reload template files in the running process", + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "debug", + }, + }, + Action: runReloadTemplates, + } subcmdFlushQueues = cli.Command{ Name: "flush-queues", Usage: "Flush queues in the running process", @@ -115,6 +126,15 @@ func runRestart(c *cli.Context) error { return handleCliResponseExtra(extra) } +func runReloadTemplates(c *cli.Context) error { + ctx, cancel := installSignals() + defer cancel() + + setup(ctx, c.Bool("debug")) + extra := private.ReloadTemplates(ctx) + return handleCliResponseExtra(extra) +} + func runFlushQueues(c *cli.Context) error { ctx, cancel := installSignals() defer cancel() diff --git a/modules/private/manager.go b/modules/private/manager.go index 5853db34e4b74..6712cf260079e 100644 --- a/modules/private/manager.go +++ b/modules/private/manager.go @@ -29,6 +29,13 @@ func Restart(ctx context.Context) ResponseExtra { return requestJSONUserMsg(req, "Restarting") } +// ReloadTemplates calls the internal reload-templates function +func ReloadTemplates(ctx context.Context) ResponseExtra { + reqURL := setting.LocalURL + "api/internal/manager/reload-templates" + req := newInternalRequest(ctx, reqURL, "POST") + return requestJSONUserMsg(req, "Reloaded") +} + // FlushOptions represents the options for the flush call type FlushOptions struct { Timeout time.Duration diff --git a/modules/templates/htmlrenderer.go b/modules/templates/htmlrenderer.go index d60be887278a5..9873b19cb42cc 100644 --- a/modules/templates/htmlrenderer.go +++ b/modules/templates/htmlrenderer.go @@ -96,6 +96,12 @@ func HTMLRenderer() *HTMLRender { return htmlRender } +func ReloadHTMLTemplates() { + if err := htmlRender.CompileTemplates(); err != nil { + log.Error("Template error: %v\n%s", err, log.Stack(2)) + } +} + func initHTMLRenderer() { rendererType := "static" if !setting.IsProd { @@ -115,9 +121,7 @@ func initHTMLRenderer() { if !setting.IsProd { go AssetFS().WatchLocalChanges(graceful.GetManager().ShutdownContext(), func() { - if err := htmlRender.CompileTemplates(); err != nil { - log.Error("Template error: %v\n%s", err, log.Stack(2)) - } + ReloadHTMLTemplates() }) } } diff --git a/routers/private/internal.go b/routers/private/internal.go index c6ea9e026383d..efa7d49504962 100644 --- a/routers/private/internal.go +++ b/routers/private/internal.go @@ -67,6 +67,7 @@ func Routes() *web.Route { r.Get("/serv/command/{keyid}/{owner}/{repo}", ServCommand) r.Post("/manager/shutdown", Shutdown) r.Post("/manager/restart", Restart) + r.Post("/manager/reload-templates", ReloadTemplates) r.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues) r.Post("/manager/pause-logging", PauseLogging) r.Post("/manager/resume-logging", ResumeLogging) diff --git a/routers/private/manager.go b/routers/private/manager.go index 38ad83326fe10..fd0fd87104a51 100644 --- a/routers/private/manager.go +++ b/routers/private/manager.go @@ -15,9 +15,16 @@ import ( "code.gitea.io/gitea/modules/private" "code.gitea.io/gitea/modules/queue" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/web" ) +// ReloadTemplates reloads all the templates +func ReloadTemplates(ctx *context.PrivateContext) { + templates.ReloadHTMLTemplates() + ctx.PlainText(http.StatusOK, "success") +} + // FlushQueues flushes all the Queues func FlushQueues(ctx *context.PrivateContext) { opts := web.GetForm(ctx).(*private.FlushOptions) From 7a0509145f4ef046e5a0b6dd725e69f99e0249db Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 22 May 2023 02:35:30 +0200 Subject: [PATCH 2/5] Report back template errors --- modules/templates/htmlrenderer.go | 6 ++++-- routers/private/manager.go | 8 +++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/modules/templates/htmlrenderer.go b/modules/templates/htmlrenderer.go index 9873b19cb42cc..cd1061289905a 100644 --- a/modules/templates/htmlrenderer.go +++ b/modules/templates/htmlrenderer.go @@ -96,10 +96,12 @@ func HTMLRenderer() *HTMLRender { return htmlRender } -func ReloadHTMLTemplates() { +func ReloadHTMLTemplates() error { if err := htmlRender.CompileTemplates(); err != nil { log.Error("Template error: %v\n%s", err, log.Stack(2)) + return err } + return nil } func initHTMLRenderer() { @@ -121,7 +123,7 @@ func initHTMLRenderer() { if !setting.IsProd { go AssetFS().WatchLocalChanges(graceful.GetManager().ShutdownContext(), func() { - ReloadHTMLTemplates() + _ = ReloadHTMLTemplates() }) } } diff --git a/routers/private/manager.go b/routers/private/manager.go index fd0fd87104a51..cdc459033fe88 100644 --- a/routers/private/manager.go +++ b/routers/private/manager.go @@ -21,7 +21,13 @@ import ( // ReloadTemplates reloads all the templates func ReloadTemplates(ctx *context.PrivateContext) { - templates.ReloadHTMLTemplates() + err := templates.ReloadHTMLTemplates() + if err != nil { + ctx.JSON(http.StatusInternalServerError, private.Response{ + UserMsg: fmt.Sprintf("Template error: %v", err), + }) + return + } ctx.PlainText(http.StatusOK, "success") } From 3849b33d42f4cdb43c00e484df7b651a7f4a8e9c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 22 May 2023 02:45:35 +0200 Subject: [PATCH 3/5] Add --test flag to test for errors without actually reloading --- cmd/manager.go | 6 +++++- modules/private/manager.go | 4 ++-- modules/templates/htmlrenderer.go | 17 +++++++++++------ routers/private/manager.go | 3 ++- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/cmd/manager.go b/cmd/manager.go index 2024d5ebbda97..3a96c8f92e89d 100644 --- a/cmd/manager.go +++ b/cmd/manager.go @@ -54,6 +54,10 @@ var ( cli.BoolFlag{ Name: "debug", }, + cli.BoolFlag{ + Name: "test", + Usage: "Test templates for errors without actually reloading", + }, }, Action: runReloadTemplates, } @@ -131,7 +135,7 @@ func runReloadTemplates(c *cli.Context) error { defer cancel() setup(ctx, c.Bool("debug")) - extra := private.ReloadTemplates(ctx) + extra := private.ReloadTemplates(ctx, c.Bool("test")) return handleCliResponseExtra(extra) } diff --git a/modules/private/manager.go b/modules/private/manager.go index 6712cf260079e..e7f360534bdfa 100644 --- a/modules/private/manager.go +++ b/modules/private/manager.go @@ -30,8 +30,8 @@ func Restart(ctx context.Context) ResponseExtra { } // ReloadTemplates calls the internal reload-templates function -func ReloadTemplates(ctx context.Context) ResponseExtra { - reqURL := setting.LocalURL + "api/internal/manager/reload-templates" +func ReloadTemplates(ctx context.Context, test bool) ResponseExtra { + reqURL := setting.LocalURL + fmt.Sprintf("api/internal/manager/reload-templates?test=%t", test) req := newInternalRequest(ctx, reqURL, "POST") return requestJSONUserMsg(req, "Reloaded") } diff --git a/modules/templates/htmlrenderer.go b/modules/templates/htmlrenderer.go index cd1061289905a..783ebacbcc424 100644 --- a/modules/templates/htmlrenderer.go +++ b/modules/templates/htmlrenderer.go @@ -62,7 +62,7 @@ func (h *HTMLRender) TemplateLookup(name string) (TemplateExecutor, error) { return tmpls.Executor(name, NewFuncMap()) } -func (h *HTMLRender) CompileTemplates() error { +func (h *HTMLRender) CompileTemplates(test bool) error { assets := AssetFS() extSuffix := ".tmpl" tmpls := scopedtmpl.NewScopedTemplate() @@ -85,6 +85,9 @@ func (h *HTMLRender) CompileTemplates() error { return err } } + if test { + return nil + } tmpls.Freeze() h.templates.Store(tmpls) return nil @@ -96,9 +99,11 @@ func HTMLRenderer() *HTMLRender { return htmlRender } -func ReloadHTMLTemplates() error { - if err := htmlRender.CompileTemplates(); err != nil { - log.Error("Template error: %v\n%s", err, log.Stack(2)) +func ReloadHTMLTemplates(test bool) error { + if err := htmlRender.CompileTemplates(test); err != nil { + if !test { + log.Error("Template error: %v\n%s", err, log.Stack(2)) + } return err } return nil @@ -112,7 +117,7 @@ func initHTMLRenderer() { log.Debug("Creating %s HTML Renderer", rendererType) htmlRender = &HTMLRender{} - if err := htmlRender.CompileTemplates(); err != nil { + if err := htmlRender.CompileTemplates(false); err != nil { p := &templateErrorPrettier{assets: AssetFS()} wrapFatal(p.handleFuncNotDefinedError(err)) wrapFatal(p.handleUnexpectedOperandError(err)) @@ -123,7 +128,7 @@ func initHTMLRenderer() { if !setting.IsProd { go AssetFS().WatchLocalChanges(graceful.GetManager().ShutdownContext(), func() { - _ = ReloadHTMLTemplates() + _ = ReloadHTMLTemplates(false) }) } } diff --git a/routers/private/manager.go b/routers/private/manager.go index cdc459033fe88..a6bd8222effb2 100644 --- a/routers/private/manager.go +++ b/routers/private/manager.go @@ -21,7 +21,8 @@ import ( // ReloadTemplates reloads all the templates func ReloadTemplates(ctx *context.PrivateContext) { - err := templates.ReloadHTMLTemplates() + test := ctx.FormBool("test") + err := templates.ReloadHTMLTemplates(test) if err != nil { ctx.JSON(http.StatusInternalServerError, private.Response{ UserMsg: fmt.Sprintf("Template error: %v", err), From 14a533d84e526bd7a748b120b9d31ed24ddea46d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 22 May 2023 10:30:50 +0200 Subject: [PATCH 4/5] Revert "Add --test flag to test for errors without actually reloading" This reverts commit 3849b33d42f4cdb43c00e484df7b651a7f4a8e9c. --- cmd/manager.go | 6 +----- modules/private/manager.go | 4 ++-- modules/templates/htmlrenderer.go | 17 ++++++----------- routers/private/manager.go | 3 +-- 4 files changed, 10 insertions(+), 20 deletions(-) diff --git a/cmd/manager.go b/cmd/manager.go index 3a96c8f92e89d..2024d5ebbda97 100644 --- a/cmd/manager.go +++ b/cmd/manager.go @@ -54,10 +54,6 @@ var ( cli.BoolFlag{ Name: "debug", }, - cli.BoolFlag{ - Name: "test", - Usage: "Test templates for errors without actually reloading", - }, }, Action: runReloadTemplates, } @@ -135,7 +131,7 @@ func runReloadTemplates(c *cli.Context) error { defer cancel() setup(ctx, c.Bool("debug")) - extra := private.ReloadTemplates(ctx, c.Bool("test")) + extra := private.ReloadTemplates(ctx) return handleCliResponseExtra(extra) } diff --git a/modules/private/manager.go b/modules/private/manager.go index e7f360534bdfa..6712cf260079e 100644 --- a/modules/private/manager.go +++ b/modules/private/manager.go @@ -30,8 +30,8 @@ func Restart(ctx context.Context) ResponseExtra { } // ReloadTemplates calls the internal reload-templates function -func ReloadTemplates(ctx context.Context, test bool) ResponseExtra { - reqURL := setting.LocalURL + fmt.Sprintf("api/internal/manager/reload-templates?test=%t", test) +func ReloadTemplates(ctx context.Context) ResponseExtra { + reqURL := setting.LocalURL + "api/internal/manager/reload-templates" req := newInternalRequest(ctx, reqURL, "POST") return requestJSONUserMsg(req, "Reloaded") } diff --git a/modules/templates/htmlrenderer.go b/modules/templates/htmlrenderer.go index 783ebacbcc424..cd1061289905a 100644 --- a/modules/templates/htmlrenderer.go +++ b/modules/templates/htmlrenderer.go @@ -62,7 +62,7 @@ func (h *HTMLRender) TemplateLookup(name string) (TemplateExecutor, error) { return tmpls.Executor(name, NewFuncMap()) } -func (h *HTMLRender) CompileTemplates(test bool) error { +func (h *HTMLRender) CompileTemplates() error { assets := AssetFS() extSuffix := ".tmpl" tmpls := scopedtmpl.NewScopedTemplate() @@ -85,9 +85,6 @@ func (h *HTMLRender) CompileTemplates(test bool) error { return err } } - if test { - return nil - } tmpls.Freeze() h.templates.Store(tmpls) return nil @@ -99,11 +96,9 @@ func HTMLRenderer() *HTMLRender { return htmlRender } -func ReloadHTMLTemplates(test bool) error { - if err := htmlRender.CompileTemplates(test); err != nil { - if !test { - log.Error("Template error: %v\n%s", err, log.Stack(2)) - } +func ReloadHTMLTemplates() error { + if err := htmlRender.CompileTemplates(); err != nil { + log.Error("Template error: %v\n%s", err, log.Stack(2)) return err } return nil @@ -117,7 +112,7 @@ func initHTMLRenderer() { log.Debug("Creating %s HTML Renderer", rendererType) htmlRender = &HTMLRender{} - if err := htmlRender.CompileTemplates(false); err != nil { + if err := htmlRender.CompileTemplates(); err != nil { p := &templateErrorPrettier{assets: AssetFS()} wrapFatal(p.handleFuncNotDefinedError(err)) wrapFatal(p.handleUnexpectedOperandError(err)) @@ -128,7 +123,7 @@ func initHTMLRenderer() { if !setting.IsProd { go AssetFS().WatchLocalChanges(graceful.GetManager().ShutdownContext(), func() { - _ = ReloadHTMLTemplates(false) + _ = ReloadHTMLTemplates() }) } } diff --git a/routers/private/manager.go b/routers/private/manager.go index a6bd8222effb2..cdc459033fe88 100644 --- a/routers/private/manager.go +++ b/routers/private/manager.go @@ -21,8 +21,7 @@ import ( // ReloadTemplates reloads all the templates func ReloadTemplates(ctx *context.PrivateContext) { - test := ctx.FormBool("test") - err := templates.ReloadHTMLTemplates(test) + err := templates.ReloadHTMLTemplates() if err != nil { ctx.JSON(http.StatusInternalServerError, private.Response{ UserMsg: fmt.Sprintf("Template error: %v", err), From ae295916d47af9b512592c973f205be5560c6c67 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 22 May 2023 13:24:07 +0200 Subject: [PATCH 5/5] Fix merge with main --- modules/private/manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/private/manager.go b/modules/private/manager.go index 64defd817c136..382986bf1db11 100644 --- a/modules/private/manager.go +++ b/modules/private/manager.go @@ -33,7 +33,7 @@ func Restart(ctx context.Context) ResponseExtra { func ReloadTemplates(ctx context.Context) ResponseExtra { reqURL := setting.LocalURL + "api/internal/manager/reload-templates" req := newInternalRequest(ctx, reqURL, "POST") - return requestJSONUserMsg(req, "Reloaded") + return requestJSONClientMsg(req, "Reloaded") } // FlushOptions represents the options for the flush call