feat: allow override of template delims

When you want to use "source":"template" arguments inside your hook file but also parse the hook file itself as a template, it is necessary use different delimiters on the two template parsers to avoid having to pepper all the inner templates with constructs like {{"{{"}}.  Added an extra command line argument -template-delims that expects a comma-separated pair of delimiters like '[[,]]' that will be used when parsing the whole hooks file template.  Inner templates in an Argument always use the default double-brace style.
This commit is contained in:
Ian Roberts 2024-10-24 09:38:31 +01:00
parent 9892bc678b
commit bb8be5ed9a
3 changed files with 13 additions and 6 deletions

View file

@ -818,7 +818,9 @@ type Hooks []Hook
// LoadFromFile attempts to load hooks from the specified file, which // LoadFromFile attempts to load hooks from the specified file, which
// can be either JSON or YAML. The asTemplate parameter causes the file // can be either JSON or YAML. The asTemplate parameter causes the file
// contents to be parsed as a Go text/template prior to unmarshalling. // contents to be parsed as a Go text/template prior to unmarshalling.
func (h *Hooks) LoadFromFile(path string, asTemplate bool) error { // The delimsStr parameter is a comma-separated pair of the left and right
// template delimiters, or an empty string to use the default '{{,}}'.
func (h *Hooks) LoadFromFile(path string, asTemplate bool, delimsStr string) error {
if path == "" { if path == "" {
return nil return nil
} }
@ -832,8 +834,12 @@ func (h *Hooks) LoadFromFile(path string, asTemplate bool) error {
if asTemplate { if asTemplate {
funcMap := template.FuncMap{"getenv": getenv} funcMap := template.FuncMap{"getenv": getenv}
left, right, found := strings.Cut(delimsStr, ",")
if !found && delimsStr != "" {
return fmt.Errorf("invalid delimiters %q - should be left and right delimiters separated by a comma", delimsStr)
}
tmpl, err := template.New("hooks").Funcs(funcMap).Parse(string(file)) tmpl, err := template.New("hooks").Funcs(funcMap).Delims(strings.TrimSpace(left), strings.TrimSpace(right)).Parse(string(file))
if err != nil { if err != nil {
return err return err
} }

View file

@ -433,7 +433,7 @@ func TestHooksLoadFromFile(t *testing.T) {
for _, tt := range hooksLoadFromFileTests { for _, tt := range hooksLoadFromFileTests {
h := &Hooks{} h := &Hooks{}
err := h.LoadFromFile(tt.path, tt.asTemplate) err := h.LoadFromFile(tt.path, tt.asTemplate, "")
if (err == nil) != tt.ok { if (err == nil) != tt.ok {
t.Errorf(err.Error()) t.Errorf(err.Error())
} }
@ -450,7 +450,7 @@ func TestHooksTemplateLoadFromFile(t *testing.T) {
} }
h := &Hooks{} h := &Hooks{}
err := h.LoadFromFile(tt.path, tt.asTemplate) err := h.LoadFromFile(tt.path, tt.asTemplate, "")
if (err == nil) != tt.ok { if (err == nil) != tt.ok {
t.Errorf(err.Error()) t.Errorf(err.Error())
continue continue

View file

@ -39,6 +39,7 @@ var (
hooksURLPrefix = flag.String("urlprefix", "hooks", "url prefix to use for served hooks (protocol://yourserver:port/PREFIX/:hook-id)") hooksURLPrefix = flag.String("urlprefix", "hooks", "url prefix to use for served hooks (protocol://yourserver:port/PREFIX/:hook-id)")
secure = flag.Bool("secure", false, "use HTTPS instead of HTTP") secure = flag.Bool("secure", false, "use HTTPS instead of HTTP")
asTemplate = flag.Bool("template", false, "parse hooks file as a Go template") asTemplate = flag.Bool("template", false, "parse hooks file as a Go template")
templateDelimiters = flag.String("template-delims", "", "a comma-separated pair of delimiters, e.g. '((,))' or '[[,]]' to use instead of the standard '{{,}}' when parsing hooks file as a template, to avoid clashing with any \"source\": \"template\" arguments")
cert = flag.String("cert", "cert.pem", "path to the HTTPS certificate pem file") cert = flag.String("cert", "cert.pem", "path to the HTTPS certificate pem file")
key = flag.String("key", "key.pem", "path to the HTTPS certificate private key pem file") key = flag.String("key", "key.pem", "path to the HTTPS certificate private key pem file")
justDisplayVersion = flag.Bool("version", false, "display webhook version and quit") justDisplayVersion = flag.Bool("version", false, "display webhook version and quit")
@ -204,7 +205,7 @@ func main() {
newHooks := hook.Hooks{} newHooks := hook.Hooks{}
err := newHooks.LoadFromFile(hooksFilePath, *asTemplate) err := newHooks.LoadFromFile(hooksFilePath, *asTemplate, *templateDelimiters)
if err != nil { if err != nil {
log.Printf("couldn't load hooks from file! %+v\n", err) log.Printf("couldn't load hooks from file! %+v\n", err)
@ -670,7 +671,7 @@ func reloadHooks(hooksFilePath string) {
// parse and swap // parse and swap
log.Printf("attempting to reload hooks from %s\n", hooksFilePath) log.Printf("attempting to reload hooks from %s\n", hooksFilePath)
err := hooksInFile.LoadFromFile(hooksFilePath, *asTemplate) err := hooksInFile.LoadFromFile(hooksFilePath, *asTemplate, *templateDelimiters)
if err != nil { if err != nil {
log.Printf("couldn't load hooks from file! %+v\n", err) log.Printf("couldn't load hooks from file! %+v\n", err)