1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package app
4
5import (
6 "strings"
7 "testing"
8
9 "github.com/stretchr/testify/assert"
10 "github.com/stretchr/testify/require"
11)
12
13func TestMirrorCLIArguments(t *testing.T) {
14 for _, args := range [][]string{
15 {"mirror", "sync"}, {"mirror", "sync", "repo", "--all"}, {"mirror", "sync", "a", "b"},
16 {"mirror", "add", "repo"}, {"mirror", "remove"}, {"mirror", "exclude"}, {"mirror", "include"},
17 {"mirror", "key", "show", "extra"}, {"mirror", "key", "rotate", "extra"}, {"mirror", "status", "a", "b"},
18 } {
19 t.Run(strings.Join(args, " "), func(t *testing.T) {
20 r := runCLI(t, nil, "", args...)
21 require.Error(t, r.err)
22 assert.NotContains(t, r.err.Error(), "ERMITE_URL", "arguments must be rejected before loading credentials")
23 })
24 }
25 r := runCLI(t, nil, "", "mirror", "sync", "--help").ok(t)
26 assert.Contains(t, r.stdout, "never force-pushes")
27 assert.Contains(t, r.stdout, "lifts a pause")
28}
29
30func TestMirrorCLIConfiguration(t *testing.T) {
31 h := newSecretsCLI(t)
32 run := func(args ...string) result { return h.cli(t, adminToken, append([]string{"mirror"}, args...)...) }
33 run("config", "--enabled", "--url", "git@example.test:owner/{repo}.git", "--cron", "*/5 * * * *", "--all-branches").ok(t)
34 r := run("config", "show", "--json").ok(t)
35 g := decode[map[string]any](t, r.stdout)
36 assert.Equal(t, true, g["enabled"])
37 assert.Equal(t, true, g["all_branches"])
38 assert.Equal(t, "git@example.test:owner/{repo}.git", g["url_template"])
39 run("config", "--enabled=false", "--all-branches=false").ok(t)
40 g = decode[map[string]any](t, run("config", "show", "--json").ok(t).stdout)
41 assert.Equal(t, false, g["enabled"])
42 assert.Equal(t, false, g["all_branches"])
43 assert.Equal(t, "*/5 * * * *", g["cron"], "omitted fields are not cleared")
44 run("add", "proj", "git@example.test:owner/proj.git", "--cron", "*/10 * * * *", "--all-branches=false").ok(t)
45 r = run("status", "proj", "--json").ok(t)
46 s := decode[map[string]any](t, r.stdout)
47 assert.Equal(t, "override", s["source"])
48 assert.Equal(t, false, s["all_branches"])
49 assert.Equal(t, "ok", s["state"])
50 assert.Equal(t, "proj", s["repo"])
51 assert.Contains(t, run("status").ok(t).stdout, "FAILURES")
52 assert.Len(t, decode[[]any](t, run("status", "--json").ok(t).stdout), 1)
53 run("remove", "proj").ok(t)
54 run("exclude", "proj").ok(t)
55 s = decode[map[string]any](t, run("status", "proj", "--json").ok(t).stdout)
56 assert.Equal(t, "excluded", s["source"])
57 run("include", "proj").ok(t)
58 first := run("key", "show").ok(t)
59 assert.Empty(t, first.stderr)
60 firstFingerprint := decode[map[string]any](t, run("key", "show", "--json").ok(t).stdout)["fingerprint"].(string)
61 rotated := run("key", "rotate").ok(t)
62 assert.Contains(t, rotated.stderr, "replaced key "+firstFingerprint)
63 assert.NotEqual(t, first.stdout, rotated.stdout)
64 assert.Contains(t, rotated.stderr, "remotes refuse pushes until this key is added")
65 assert.Equal(t, rotated.stdout, run("key", "show").ok(t).stdout)
66 assert.Equal(t, []string{"authorized_key", "created_at", "fingerprint"}, keys(t, run("key", "show", "--json").ok(t).stdout))
67}