From 1f450dcf1448c283ec6b1358e175dfcfa262ec99 Mon Sep 17 00:00:00 2001 From: Amy Gale Ruth Bowersox Date: Thu, 5 Mar 2026 14:50:20 -0700 Subject: [PATCH] add the Production flag, command-line options, and DebugMode computed flag, and put it in the main places I expect it to be used --- config/config.go | 28 ++++++++++++++++++++-------- config/default.yaml | 1 + email/sender.go | 2 +- ui/render_wrap.go | 2 ++ ui/templates.go | 2 +- ui/views/frame.jet | 7 ++++++- 6 files changed, 31 insertions(+), 11 deletions(-) diff --git a/config/config.go b/config/config.go index 17adf75..8cf094b 100644 --- a/config/config.go +++ b/config/config.go @@ -39,6 +39,8 @@ const CONFIGFILE_NAME = "amsterdam.yaml" // AmCLI is the command-line interface arguments structure. type AmCLI struct { ConfigFile string `arg:"-C,--config,env:AMSTERDAM_CONFIG" help:"Location of the configuration file."` + Debug bool `arg:"-D,--debug,env:AMSTERDAM_DEBUG" help:"Force Amsterdam to run in debug mode."` + Production bool `arg:"-P,--prod,--production,env:AMSTERDAM_PROD" help:"Force Amsterdam to run in production mode."` DebugPanic bool `arg:"--debug-panic" help:"Development Only - disable Echo panic recovery"` BuggyAttachments bool `arg:"--buggy-attachments" help:"Some attachments may be buggy - truncate data if necessary"` } @@ -59,9 +61,10 @@ func (*AmCLI) Version() string { // AmConfig holds the configuration of the application as read from YAML. type AmConfig struct { Site struct { - BaseURL string `yaml:"baseURL"` - Title string `yaml:"title"` - SiteIcon struct { + Production bool `yaml:"production"` + BaseURL string `yaml:"baseURL"` + Title string `yaml:"title"` + SiteIcon struct { Path string `yaml:"path"` Type string `yaml:"type"` } `yaml:"siteIcon"` @@ -148,6 +151,7 @@ type AmConfig struct { // AmConfigComputed is the configuration values which are "computed" based only on values in AmConfig. type AmConfigComputed struct { + DebugMode bool // are we in debug mode? UploadMaxSize int32 // maximum upload size in bytes UploadNoCompress map[string]bool // which upload types are not compressed? } @@ -214,15 +218,16 @@ func overlayStructValue(dest, loaded, defaults reflect.Value) { } else if fldDest.Kind() == reflect.Array || fldDest.Kind() == reflect.Slice { // array of strings - merge the two arrays m := make(map[string]bool) + rc := make([]string, 0, fldDefaults.Len()+fldLoaded.Len()) for i := 0; i < fldDefaults.Len(); i++ { m[fldDefaults.Index(i).String()] = true + rc = append(rc, fldDefaults.Index(i).String()) } for i := 0; i < fldLoaded.Len(); i++ { - m[fldLoaded.Index(i).String()] = true - } - rc := make([]string, 0, len(m)) - for s := range m { - rc = append(rc, s) + if !m[fldLoaded.Index(i).String()] { + m[fldLoaded.Index(i).String()] = true + rc = append(rc, fldLoaded.Index(i).String()) + } } fldDest.Set(reflect.ValueOf(rc)) } else if fldDest.Kind() == reflect.Bool { @@ -320,6 +325,13 @@ func SetupConfig() { } // Compute additional values. + if CommandLine.Debug { + GlobalComputedConfig.DebugMode = true + } else if CommandLine.Production { + GlobalComputedConfig.DebugMode = false + } else { + GlobalComputedConfig.DebugMode = !GlobalConfig.Site.Production + } tmp, err := parseDataSize(GlobalConfig.Posting.Uploads.MaxSize) if err != nil { panic(err.Error()) diff --git a/config/default.yaml b/config/default.yaml index 888a0ff..bef3d74 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -7,6 +7,7 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. # site: + production: false baseURL: "http://localhost:1323" title: "Amsterdam Web Communities System" siteIcon: diff --git a/email/sender.go b/email/sender.go index cd17a21..dcba50c 100644 --- a/email/sender.go +++ b/email/sender.go @@ -228,7 +228,7 @@ func SetupMailSender() func() { templateLoaders = append(templateLoaders, embedfs.NewLoader("templates/", emailTemplates)) // Initialize the template engine. - emailRenderer = jet.NewSet(multi.NewLoader(templateLoaders...), jet.DevelopmentMode(true)) + emailRenderer = jet.NewSet(multi.NewLoader(templateLoaders...), jet.DevelopmentMode(config.GlobalComputedConfig.DebugMode)) emailRenderer.AddGlobal("AmsterdamVersion", config.AMSTERDAM_VERSION) emailRenderer.AddGlobal("AmsterdamCopyright", config.AMSTERDAM_COPYRIGHT) emailRenderer.AddGlobal("GlobalConfig", config.GlobalConfig) diff --git a/ui/render_wrap.go b/ui/render_wrap.go index ebaba3b..ab3ae18 100644 --- a/ui/render_wrap.go +++ b/ui/render_wrap.go @@ -16,6 +16,7 @@ import ( "net/http" "time" + "git.erbosoft.com/amy/amsterdam/config" "git.erbosoft.com/amy/amsterdam/database" "github.com/klauspost/lctime" "github.com/labstack/echo/v4" @@ -141,6 +142,7 @@ func AmSendPageData(ctxt echo.Context, amctxt AmContext, command string, data an } } amctxt.VarMap().Set("__bannerad", ad) + amctxt.VarMap().Set("__debugMode", config.GlobalComputedConfig.DebugMode) if tmp := amctxt.GetScratch("frame_suppressLogin"); tmp != nil { amctxt.VarMap().Set("__suppressLogin", true) } diff --git a/ui/templates.go b/ui/templates.go index ebce38f..404ce69 100644 --- a/ui/templates.go +++ b/ui/templates.go @@ -302,7 +302,7 @@ func setupTemplates() { templateLoaders = append(templateLoaders, embedfs.NewLoader("views/", static_views)) // Create the template renderer and add our globals to it. - views = jet.NewSet(multi.NewLoader(templateLoaders...), jet.DevelopmentMode(true)) + views = jet.NewSet(multi.NewLoader(templateLoaders...), jet.DevelopmentMode(config.GlobalComputedConfig.DebugMode)) views.AddGlobal("AmsterdamVersion", config.AMSTERDAM_VERSION) views.AddGlobal("AmsterdamCopyright", config.AMSTERDAM_COPYRIGHT) views.AddGlobal("GlobalConfig", config.GlobalConfig) diff --git a/ui/views/frame.jet b/ui/views/frame.jet index f0057ad..a5667a2 100644 --- a/ui/views/frame.jet +++ b/ui/views/frame.jet @@ -18,7 +18,12 @@ {{ range k, v := .FrameMetadata(0) }} {{ end }} - + {{ if __debugMode }} + + {{ else }} + {* TODO - replace with reference to generated Tailwind CSS file *} + + {{ end }}