e2e/reviewrequest_test.go

a7c9352033c319587613cb6825035e8d99f5871a
gitbay/e2e/reviewrequest_test.go history · blame · raw

128 lines · 5627 bytes

  1package e2e
  2
  3import (
  4	"os"
  5	"path/filepath"
  6	"strings"
  7	"testing"
  8)
  9
 10// TestMRReviewRequest drives "mr review request" (#145) end to end: a
 11// requested reviewer reaches the queue without being otherwise involved,
 12// drops out once they review the current head, comes back on a new push,
 13// and --remove takes them out outright. A separate, private repository
 14// checks that requesting someone who cannot read it is refused.
 15func TestMRReviewRequest(t *testing.T) {
 16	inst := startInstance(t)
 17	aliceKey := inst.newKey(t, "alice")
 18	bobKey := inst.newKey(t, "bob")
 19	carolKey := inst.newKey(t, "carol")
 20	inst.admin(t, "admin", "user", "create", "alice", "--key", aliceKey+".pub")
 21	inst.admin(t, "admin", "user", "create", "bob", "--key", bobKey+".pub")
 22	inst.admin(t, "admin", "user", "create", "carol", "--key", carolKey+".pub")
 23
 24	// Public, and bob is granted nothing: any involvement he has in the
 25	// queue can only come from being asked directly.
 26	if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
 27		t.Fatalf("repo create: %s", errOut)
 28	}
 29
 30	env := inst.gitEnv(aliceKey)
 31	work := t.TempDir()
 32	mustGit(t, work, env, "clone", inst.sshURL("alice/app"), "w")
 33	dir := filepath.Join(work, "w")
 34	os.WriteFile(filepath.Join(dir, "a.txt"), []byte("a\n"), 0o644)
 35	mustGit(t, dir, env, "checkout", "-q", "-b", "main")
 36	mustGit(t, dir, env, "add", ".")
 37	mustGit(t, dir, env, "commit", "-q", "-m", "base")
 38	mustGit(t, dir, env, "push", "-q", "origin", "main")
 39	mustGit(t, dir, env, "checkout", "-q", "-b", "feat")
 40	os.WriteFile(filepath.Join(dir, "a.txt"), []byte("a\nb\n"), 0o644)
 41	mustGit(t, dir, env, "add", ".")
 42	mustGit(t, dir, env, "commit", "-q", "-m", "feat")
 43	mustGit(t, dir, env, "push", "-q", "origin", "feat")
 44
 45	if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "create", "alice/app",
 46		"--source", "feat", "--target", "main", "--title", "'add b'", "--draft"); code != 0 {
 47		t.Fatalf("mr create: %s", errOut)
 48	}
 49
 50	// Asking while a draft does not put it in bob's queue: draft merge
 51	// requests stay out of the review queue for everyone, requested or
 52	// not.
 53	if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "review", "request", "alice/app", "1", "--add", "bob"); code != 0 {
 54		t.Fatalf("review request: %s", errOut)
 55	}
 56	if q := reviewQueue(t, inst, bobKey); len(q) != 0 {
 57		t.Fatalf("a draft is waiting on the requested reviewer: %v", q)
 58	}
 59
 60	// Ready: the request now surfaces, and it notified bob at the same
 61	// moment it notified everyone else.
 62	if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "ready", "alice/app", "1"); code != 0 {
 63		t.Fatalf("mr ready: %s", errOut)
 64	}
 65	if !strings.Contains(inbox(t, inst, bobKey), "ready for review") {
 66		t.Fatalf("requested reviewer not notified by mr ready:\n%s", inbox(t, inst, bobKey))
 67	}
 68	if q := reviewQueue(t, inst, bobKey); len(q) != 1 || q[0] != 1 {
 69		t.Fatalf("requested reviewer not in queue: %v", q)
 70	}
 71
 72	// Reviewing the current head empties the queue, the same rule an
 73	// involved reviewer follows.
 74	if _, errOut, code := inst.ssh(t, bobKey, "", "mr", "review", "alice/app", "1", "--approve"); code != 0 {
 75		t.Fatalf("review: %s", errOut)
 76	}
 77	if q := reviewQueue(t, inst, bobKey); len(q) != 0 {
 78		t.Fatalf("queue did not empty after reviewing the head: %v", q)
 79	}
 80
 81	// A new push moves the head, so the review no longer covers it: back
 82	// in the queue.
 83	os.WriteFile(filepath.Join(dir, "a.txt"), []byte("a\nb\nc\n"), 0o644)
 84	mustGit(t, dir, env, "add", ".")
 85	mustGit(t, dir, env, "commit", "-q", "-m", "more")
 86	mustGit(t, dir, env, "push", "-q", "origin", "feat")
 87	if q := reviewQueue(t, inst, bobKey); len(q) != 1 || q[0] != 1 {
 88		t.Fatalf("new head did not bring the request back: %v", q)
 89	}
 90
 91	// --remove takes it out outright.
 92	if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "review", "request", "alice/app", "1", "--remove", "bob"); code != 0 {
 93		t.Fatalf("review request --remove: %s", errOut)
 94	}
 95	if q := reviewQueue(t, inst, bobKey); len(q) != 0 {
 96		t.Fatalf("queue after --remove: %v", q)
 97	}
 98	if _, _, code := inst.ssh(t, aliceKey, "", "mr", "review", "request", "alice/app", "1", "--remove", "bob"); code != 3 {
 99		t.Fatalf("removing an absent reviewer should 404, got %d", code)
100	}
101
102	// A private repository where carol has no access at all: asking her
103	// for a review is refused, not silently recorded.
104	if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/secret", "--private"); code != 0 {
105		t.Fatalf("repo create: %s", errOut)
106	}
107	work2 := t.TempDir()
108	mustGit(t, work2, env, "clone", inst.sshURL("alice/secret"), "w")
109	dir2 := filepath.Join(work2, "w")
110	os.WriteFile(filepath.Join(dir2, "a.txt"), []byte("a\n"), 0o644)
111	mustGit(t, dir2, env, "checkout", "-q", "-b", "main")
112	mustGit(t, dir2, env, "add", ".")
113	mustGit(t, dir2, env, "commit", "-q", "-m", "base")
114	mustGit(t, dir2, env, "push", "-q", "origin", "main")
115	mustGit(t, dir2, env, "checkout", "-q", "-b", "feat")
116	os.WriteFile(filepath.Join(dir2, "a.txt"), []byte("a\nb\n"), 0o644)
117	mustGit(t, dir2, env, "add", ".")
118	mustGit(t, dir2, env, "commit", "-q", "-m", "feat")
119	mustGit(t, dir2, env, "push", "-q", "origin", "feat")
120	if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "create", "alice/secret",
121		"--source", "feat", "--target", "main", "--title", "'private'"); code != 0 {
122		t.Fatalf("mr create: %s", errOut)
123	}
124	_, errOut, code := inst.ssh(t, aliceKey, "", "mr", "review", "request", "alice/secret", "1", "--add", "carol")
125	if code != 4 || !strings.Contains(errOut, "cannot read") {
126		t.Fatalf("requesting a review from someone with no access should be refused: exit %d, %s", code, errOut)
127	}
128}