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