e2e/archive_test.go
135 lines · 5938 bytes
1package e2e
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7 "testing"
8)
9
10func TestArchiveAndTopics(t *testing.T) {
11 t.Parallel()
12 inst := startInstance(t)
13 aliceKey := inst.newKey(t, "alice")
14 bobKey := inst.newKey(t, "bob")
15 inst.admin(t, "admin", "user", "create", "alice",
16 "--key", aliceKey+".pub", "--email", "alice@example.test", "--verified")
17 inst.admin(t, "admin", "user", "create", "bob", "--key", bobKey+".pub")
18
19 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
20 t.Fatalf("repo create: %s", errOut)
21 }
22 if _, _, code := inst.ssh(t, aliceKey, "", "repo", "access", "grant", "alice/app", "bob", "write"); code != 0 {
23 t.Fatal("grant failed")
24 }
25 work := t.TempDir()
26 env := inst.gitEnv(aliceKey)
27 mustGit(t, work, env, "clone", inst.sshURL("alice/app"), "w")
28 dir := filepath.Join(work, "w")
29 os.WriteFile(filepath.Join(dir, "a.txt"), []byte("a\n"), 0o644)
30 mustGit(t, dir, env, "checkout", "-q", "-b", "main")
31 mustGit(t, dir, env, "add", ".")
32 mustGit(t, dir, env, "commit", "-q", "-m", "base")
33 mustGit(t, dir, env, "push", "-q", "origin", "main")
34
35 // Topics: admin-only edits, validation, idempotent add, listing.
36 if _, errOut, code := inst.ssh(t, bobKey, "", "repo", "topics", "add", "alice/app", "go"); code != 4 {
37 t.Fatalf("non-admin added topics: exit %d, %s", code, errOut)
38 }
39 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "topics", "add", "alice/app", "Bad_Topic"); code != 2 || !strings.Contains(errOut, "invalid topic") {
40 t.Fatalf("bad topic accepted: exit %d, %s", code, errOut)
41 }
42 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "topics", "add", "alice/app", "go", "cli", "go"); code != 0 {
43 t.Fatalf("topics add: %s", errOut)
44 }
45 out, _, _ := inst.ssh(t, aliceKey, "", "repo", "topics", "alice/app", "--json")
46 if !strings.Contains(out, `["cli","go"]`) {
47 t.Fatalf("topics list: %s", out)
48 }
49 out, _, _ = inst.ssh(t, aliceKey, "", "repo", "show", "alice/app", "--json")
50 if !strings.Contains(out, `"topics":["cli","go"]`) || strings.Contains(out, `"archived"`) {
51 t.Fatalf("repo show topics: %s", out)
52 }
53 if _, _, code := inst.ssh(t, aliceKey, "", "repo", "topics", "remove", "alice/app", "cli"); code != 0 {
54 t.Fatal("topics remove failed")
55 }
56 if _, _, code := inst.ssh(t, aliceKey, "", "repo", "topics", "remove", "alice/app", "cli"); code != 3 {
57 t.Fatal("removing an absent topic should be not-found")
58 }
59
60 // An MR and an issue that predate archiving.
61 mustGit(t, dir, env, "checkout", "-q", "-b", "feat")
62 os.WriteFile(filepath.Join(dir, "b.txt"), []byte("b\n"), 0o644)
63 mustGit(t, dir, env, "add", ".")
64 mustGit(t, dir, env, "commit", "-q", "-m", "feat")
65 mustGit(t, dir, env, "push", "-q", "origin", "feat")
66 if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "create", "alice/app",
67 "--source", "feat", "--target", "main", "--title", "'feat'"); code != 0 {
68 t.Fatalf("mr create: %s", errOut)
69 }
70 if _, errOut, code := inst.ssh(t, aliceKey, "", "issue", "create", "alice/app", "--title", "'todo'"); code != 0 {
71 t.Fatalf("issue create: %s", errOut)
72 }
73
74 // Archive: admin-only, then everything content-mutating is refused.
75 if _, _, code := inst.ssh(t, bobKey, "", "repo", "archive", "alice/app"); code != 4 {
76 t.Fatal("non-admin archived the repo")
77 }
78 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "archive", "alice/app"); code != 0 {
79 t.Fatalf("archive: %s", errOut)
80 }
81 if _, _, code := inst.ssh(t, aliceKey, "", "repo", "archive", "alice/app"); code != 2 {
82 t.Fatal("double archive not refused")
83 }
84
85 os.WriteFile(filepath.Join(dir, "c.txt"), []byte("c\n"), 0o644)
86 mustGit(t, dir, env, "checkout", "-q", "main")
87 mustGit(t, dir, env, "add", ".")
88 mustGit(t, dir, env, "commit", "-q", "-m", "more")
89 if out, code := gitRun(t, dir, env, "push", "origin", "main"); code == 0 || !strings.Contains(out, "archived and read-only") {
90 t.Fatalf("push to archived repo: exit %d\n%s", code, out)
91 }
92 for _, cmd := range [][]string{
93 {"issue", "create", "alice/app", "--title", "'x'"},
94 {"issue", "comment", "alice/app", "1", "--message", "'x'"},
95 {"issue", "close", "alice/app", "1"},
96 {"mr", "comment", "alice/app", "1", "--message", "'x'"},
97 {"mr", "review", "alice/app", "1", "--approve"},
98 {"mr", "merge", "alice/app", "1"},
99 {"mr", "close", "alice/app", "1"},
100 {"status", "set", "alice/app", "HEAD", "--context", "ci", "--state", "success"},
101 } {
102 if _, errOut, code := inst.ssh(t, bobKey, "", cmd...); code != 4 || !strings.Contains(errOut, "archived and read-only") {
103 t.Fatalf("%v on archived repo: exit %d, %s", cmd, code, errOut)
104 }
105 }
106
107 // Reading stays untouched: clone, listings, show, web.
108 work2 := t.TempDir()
109 mustGit(t, work2, env, "clone", "-q", inst.sshURL("alice/app"), "r")
110 if out, _, code := inst.ssh(t, aliceKey, "", "issue", "list", "alice/app"); code != 0 || !strings.Contains(out, "todo") {
111 t.Fatalf("issue list on archived repo: %s", out)
112 }
113 out, _, _ = inst.ssh(t, aliceKey, "", "repo", "show", "alice/app", "--json")
114 if !strings.Contains(out, `"archived":true`) {
115 t.Fatalf("repo show archived flag: %s", out)
116 }
117 if status, _ := inst.get(t, "/alice/app"); status != 200 {
118 t.Fatalf("web browse on archived repo: %d", status)
119 }
120
121 // Settings and unarchive still work; writes come back.
122 if _, _, code := inst.ssh(t, aliceKey, "", "repo", "settings", "protect", "alice/app", "main"); code != 0 {
123 t.Fatal("settings on archived repo should still work")
124 }
125 if _, _, code := inst.ssh(t, aliceKey, "", "repo", "settings", "unprotect", "alice/app", "main"); code != 0 {
126 t.Fatal("unprotect failed")
127 }
128 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "unarchive", "alice/app"); code != 0 {
129 t.Fatalf("unarchive: %s", errOut)
130 }
131 mustGit(t, dir, env, "push", "-q", "origin", "main")
132 if _, errOut, code := inst.ssh(t, bobKey, "", "issue", "comment", "alice/app", "1", "--message", "'back'"); code != 0 {
133 t.Fatalf("comment after unarchive: %s", errOut)
134 }
135}