v3.3.0 b164fe9

parse_secrets_test.go RawHistoryFolder

1package appmanifest_test
2
3import (
4	"testing"
5
6	"github.com/stretchr/testify/assert"
7	"github.com/stretchr/testify/require"
8
9	"github.com/bnema/gordon/internal/adapters/in/appmanifest"
10	"github.com/bnema/gordon/internal/domain"
11)
12
13const secretsHead = "name = \"blog\"\n[services.web]\nimage = \"img:1\"\n"
14
15func TestParse_SecretForms(t *testing.T) {
16	cases := []struct {
17		name      string
18		doc       string
19		wantMap   map[string]string
20		wantFiles []string
21	}{
22		{"short form", "[services.web.secrets]\nDB = \"db\"\n", map[string]string{"DB": "db"}, nil},
23		{"table name only", "[services.web.secrets]\nDB = { name = \"db\" }\n", map[string]string{"DB": "db"}, nil},
24		{"table env", "[services.web.secrets]\nDB = { name = \"db\", as = \"env\" }\n", map[string]string{"DB": "db"}, nil},
25		{"table file", "[services.web.secrets]\nDB = { name = \"db\", as = \"file\" }\n", map[string]string{"DB": "db"}, []string{"DB"}},
26		{"sub-table", "[services.web.secrets.DB]\nname = \"db\"\nas = \"file\"\n", map[string]string{"DB": "db"}, []string{"DB"}},
27		{
28			"mixed",
29			"[services.web.secrets]\nZ = { name = \"z\", as = \"file\" }\nA = { name = \"a\", as = \"file\" }\nM = \"m\"\nE = { name = \"e\", as = \"env\" }\n",
30			map[string]string{"Z": "z", "A": "a", "M": "m", "E": "e"},
31			[]string{"A", "Z"},
32		},
33	}
34	for _, tc := range cases {
35		t.Run(tc.name, func(t *testing.T) {
36			spec, _, err := appmanifest.Parse([]byte(secretsHead+tc.doc), "blog.toml")
37			require.NoError(t, err)
38			require.Len(t, spec.Services, 1)
39			assert.Equal(t, tc.wantMap, spec.Services[0].Secrets)
40			assert.Equal(t, tc.wantFiles, spec.Services[0].SecretFiles)
41		})
42	}
43}
44
45func TestParse_NoSecretsKeepsEmptyMap(t *testing.T) {
46	spec, _, err := appmanifest.Parse([]byte(secretsHead), "blog.toml")
47	require.NoError(t, err)
48	assert.NotNil(t, spec.Services[0].Secrets)
49	assert.Empty(t, spec.Services[0].Secrets)
50	assert.Nil(t, spec.Services[0].SecretFiles)
51}
52
53func TestParse_SecretFormsInvalid(t *testing.T) {
54	cases := []struct {
55		name    string
56		doc     string
57		wantErr string
58	}{
59		{"bad as", "[services.web.secrets]\nDB = { name = \"db\", as = \"volume\" }\n", "as must be"},
60		{"empty as", "[services.web.secrets]\nDB = { name = \"db\", as = \"\" }\n", "as must be"},
61		{"as not string", "[services.web.secrets]\nDB = { name = \"db\", as = 1 }\n", "as must be"},
62		{"missing name", "[services.web.secrets]\nDB = { as = \"file\" }\n", "name must be"},
63		{"name not string", "[services.web.secrets]\nDB = { name = 1 }\n", "name must be"},
64		{"extra key", "[services.web.secrets]\nDB = { name = \"db\", mode = \"x\" }\n", "unknown key \"mode\""},
65		{"integer value", "[services.web.secrets]\nDB = 42\n", "secret name string"},
66		{"array value", "[services.web.secrets]\nDB = [\"db\"]\n", "secret name string"},
67		{"file key collision", "[services.web.env]\nDB_FILE = \"x\"\n[services.web.secrets]\nDB = { name = \"db\", as = \"file\" }\n", "collides with a secret file key"},
68	}
69	for _, tc := range cases {
70		t.Run(tc.name, func(t *testing.T) {
71			_, _, err := appmanifest.Parse([]byte(secretsHead+tc.doc), "blog.toml")
72			require.Error(t, err)
73			assert.ErrorIs(t, err, domain.ErrInvalidAppSpec)
74			assert.ErrorContains(t, err, tc.wantErr)
75		})
76	}
77}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close