feat: implement thin vertical slice of system-generated notifications (#13537)

This commit is contained in:
Danny Kopping
2024-07-08 15:38:50 +02:00
committed by GitHub
parent 10aa32ca08
commit bdd2caf95d
51 changed files with 3686 additions and 50 deletions
+26
View File
@@ -0,0 +1,26 @@
package render
import (
"strings"
"text/template"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/coderd/notifications/types"
)
// GoTemplate attempts to substitute the given payload into the given template using Go's templating syntax.
// TODO: memoize templates for memory efficiency?
func GoTemplate(in string, payload types.MessagePayload, extraFuncs template.FuncMap) (string, error) {
tmpl, err := template.New("text").Funcs(extraFuncs).Parse(in)
if err != nil {
return "", xerrors.Errorf("template parse: %w", err)
}
var out strings.Builder
if err = tmpl.Execute(&out, payload); err != nil {
return "", xerrors.Errorf("template execute: %w", err)
}
return out.String(), nil
}
@@ -0,0 +1,59 @@
package render_test
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/coderd/notifications/render"
"github.com/coder/coder/v2/coderd/notifications/types"
)
func TestGoTemplate(t *testing.T) {
t.Parallel()
const userEmail = "bob@xyz.com"
tests := []struct {
name string
in string
payload types.MessagePayload
expectedOutput string
expectedErr error
}{
{
name: "top-level variables are accessible and substituted",
in: "{{ .UserEmail }}",
payload: types.MessagePayload{UserEmail: userEmail},
expectedOutput: userEmail,
expectedErr: nil,
},
{
name: "input labels are accessible and substituted",
in: "{{ .Labels.user_email }}",
payload: types.MessagePayload{Labels: map[string]string{
"user_email": userEmail,
}},
expectedOutput: userEmail,
expectedErr: nil,
},
}
for _, tc := range tests {
tc := tc // unnecessary as of go1.22 but the linter is outdated
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
out, err := render.GoTemplate(tc.in, tc.payload, nil)
if tc.expectedErr == nil {
require.NoError(t, err)
} else {
require.ErrorIs(t, err, tc.expectedErr)
}
require.Equal(t, tc.expectedOutput, out)
})
}
}