e2e/requiremr_test.go
83 lines · 3305 bytes
1package e2e
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7 "testing"
8)
9
10// With require-mr on, a protected branch takes changes through mr merge
11// only: direct pushes and commit-file are refused, a branch that does
12// not exist yet can still be created, and unprotected branches are
13// unaffected (#197).
14func TestRequireMR(t *testing.T) {
15 inst := startInstance(t)
16 aliceKey := inst.newKey(t, "alice")
17 inst.admin(t, "admin", "user", "create", "alice",
18 "--key", aliceKey+".pub", "--email", "alice@example.test", "--verified")
19 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/lib"); code != 0 {
20 t.Fatalf("repo create: %s", errOut)
21 }
22 env := inst.gitEnv(aliceKey)
23 work := t.TempDir()
24 mustGit(t, work, env, "clone", "-q", inst.sshURL("alice/lib"), "lib")
25 dir := filepath.Join(work, "lib")
26 write := func(name, content string) {
27 t.Helper()
28 if err := os.WriteFile(filepath.Join(dir, name), []byte(content), 0o644); err != nil {
29 t.Fatal(err)
30 }
31 mustGit(t, dir, env, "add", name)
32 mustGit(t, dir, env, "commit", "-q", "-m", name)
33 }
34 mustGit(t, dir, env, "checkout", "-q", "-b", "main")
35 write("README", "one\n")
36 mustGit(t, dir, env, "push", "-q", "origin", "main")
37
38 for _, args := range [][]string{
39 {"repo", "settings", "protect", "alice/lib", "main"},
40 {"repo", "settings", "protect", "alice/lib", "release"},
41 {"repo", "settings", "require-mr", "alice/lib", "on"},
42 } {
43 if _, errOut, code := inst.ssh(t, aliceKey, "", args...); code != 0 {
44 t.Fatalf("%v: %s", args, errOut)
45 }
46 }
47 out, _, _ := inst.ssh(t, aliceKey, "", "repo", "settings", "show", "alice/lib", "--json")
48 if !strings.Contains(out, `"require_mr":true`) {
49 t.Fatalf("settings show: %s", out)
50 }
51
52 // Direct push to main: refused, with the reason.
53 write("two", "two\n")
54 if out, code := gitRun(t, dir, env, "push", "origin", "main"); code == 0 || !strings.Contains(out, "merge requests only") {
55 t.Fatalf("direct push to protected branch: %d\n%s", code, out)
56 }
57 if _, errOut, code := inst.ssh(t, aliceKey, "x\n", "repo", "commit-file", "alice/lib", "notes.txt",
58 "--ref", "main", "--file", "-"); code != 4 || !strings.Contains(errOut, "merge requests only") {
59 t.Fatalf("commit-file to protected branch: %d %s", code, errOut)
60 }
61 // Creating a protected branch is still a push; so is an unprotected one.
62 mustGit(t, dir, env, "push", "-q", "origin", "main:release")
63 mustGit(t, dir, env, "push", "-q", "origin", "main:feature")
64
65 // The same change lands through a merge request.
66 if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "create", "alice/lib",
67 "--source", "feature", "--target", "main", "--title", "'two'"); code != 0 {
68 t.Fatalf("mr create: %s", errOut)
69 }
70 if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "merge", "alice/lib", "1", "--strategy", "ff"); code != 0 {
71 t.Fatalf("mr merge: %s", errOut)
72 }
73 if out, _, _ := inst.ssh(t, aliceKey, "", "repo", "log", "alice/lib", "--limit", "1"); !strings.Contains(out, "two") {
74 t.Fatalf("merge did not move main: %s", out)
75 }
76
77 // Off again, and the push goes through.
78 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "settings", "require-mr", "alice/lib", "off"); code != 0 {
79 t.Fatalf("require-mr off: %s", errOut)
80 }
81 write("three", "three\n")
82 mustGit(t, dir, env, "push", "-q", "origin", "main")
83}