e2e/mergequeue_test.go

v1.38.0
gitbay/e2e/mergequeue_test.go history · blame · raw

103 lines · 4304 bytes

  1package e2e
  2
  3import (
  4	"net/url"
  5	"os"
  6	"path/filepath"
  7	"strings"
  8	"testing"
  9)
 10
 11// A merge queued with mr merge --when-ready waits on its gates, shows on
 12// the page with a cancel button, and merges as the user who queued it
 13// when a status turns the checks green (#289).
 14func TestMergeWhenReady(t *testing.T) {
 15	t.Parallel()
 16	inst := startInstanceWith(t, "[web]\nmode = \"accounts\"\n")
 17	aliceKey := inst.newKey(t, "alice")
 18	bobKey := inst.newKey(t, "bob")
 19	inst.admin(t, "admin", "user", "create", "alice",
 20		"--key", aliceKey+".pub", "--email", "alice@example.test", "--verified")
 21	inst.admin(t, "admin", "user", "create", "bob",
 22		"--key", bobKey+".pub", "--email", "bob@example.test", "--verified")
 23	for _, args := range [][]string{
 24		{"repo", "create", "alice/lib"},
 25		{"repo", "access", "grant", "alice/lib", "bob", "write"},
 26		{"repo", "settings", "require-contexts", "alice/lib", "ext/test"},
 27	} {
 28		if _, errOut, code := inst.ssh(t, aliceKey, "", args...); code != 0 {
 29			t.Fatalf("%v: %s", args, errOut)
 30		}
 31	}
 32
 33	env := inst.gitEnv(aliceKey)
 34	work := t.TempDir()
 35	mustGit(t, work, env, "clone", "-q", inst.sshURL("alice/lib"), "w")
 36	dir := filepath.Join(work, "w")
 37	mustGit(t, dir, env, "checkout", "-q", "-b", "main")
 38	os.WriteFile(filepath.Join(dir, "lib.txt"), []byte("v1\n"), 0o644)
 39	mustGit(t, dir, env, "add", ".")
 40	mustGit(t, dir, env, "commit", "-q", "-m", "base")
 41	mustGit(t, dir, env, "push", "-q", "origin", "main")
 42	mustGit(t, dir, env, "checkout", "-q", "-b", "feature")
 43	os.WriteFile(filepath.Join(dir, "lib.txt"), []byte("v2\n"), 0o644)
 44	mustGit(t, dir, env, "commit", "-q", "-am", "change")
 45	mustGit(t, dir, env, "push", "-q", "origin", "feature")
 46	head := strings.TrimSpace(mustGit(t, dir, env, "rev-parse", "HEAD"))
 47	if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "create", "alice/lib",
 48		"--source", "feature", "--target", "main", "--title", "'change'"); code != 0 {
 49		t.Fatalf("mr create: %s", errOut)
 50	}
 51
 52	// Queued over SSH: the checks have not reported, so it waits.
 53	out, errOut, code := inst.ssh(t, bobKey, "", "mr", "merge", "alice/lib", "1", "--when-ready")
 54	if code != 0 || !strings.Contains(out, "queued") || !strings.Contains(out, "ext/test=missing") {
 55		t.Fatalf("mr merge --when-ready: %d %s %s", code, out, errOut)
 56	}
 57	out, _, _ = inst.ssh(t, aliceKey, "", "mr", "show", "alice/lib", "1", "--json")
 58	if !strings.Contains(out, `"queued":{"by":"bob"`) {
 59		t.Fatalf("mr show does not carry the queue:\n%s", out)
 60	}
 61	out, _, _ = inst.ssh(t, bobKey, "", "dashboard", "--json")
 62	if !strings.Contains(out, `"queued":true`) {
 63		t.Fatalf("dashboard does not carry the queue:\n%s", out)
 64	}
 65
 66	// The page shows it; its cancel button dequeues and its queue button
 67	// queues again, now as alice.
 68	mrURL := inst.base() + "/alice/lib/mrs/1"
 69	alice := inst.login(t, aliceKey)
 70	_, body := browserGet(t, alice, mrURL)
 71	for _, want := range []string{"Queued to merge by", "waiting: ", "Cancel queued merge"} {
 72		if !strings.Contains(body, want) {
 73			t.Fatalf("MR page missing %q:\n%s", want, body)
 74		}
 75	}
 76	if status, _ := browserPost(t, alice, mrURL+"/merge", url.Values{"cancel": {"on"}}); status != 200 {
 77		t.Fatalf("cancel post: %d", status)
 78	}
 79	if out, _, _ := inst.ssh(t, aliceKey, "", "mr", "show", "alice/lib", "1", "--json"); strings.Contains(out, `"queued":`) {
 80		t.Fatalf("web cancel left the queue:\n%s", out)
 81	}
 82	if status, _ := browserPost(t, alice, mrURL+"/merge",
 83		url.Values{"strategy": {"auto"}, "when_ready": {"on"}}); status != 200 {
 84		t.Fatalf("queue post: %d", status)
 85	}
 86	if st := inst.mrShow(t, aliceKey, "alice/lib", "1").State; st != "open" {
 87		t.Fatalf("queued MR is %s before its checks", st)
 88	}
 89
 90	// The status that turns the checks green merges it, as alice.
 91	if _, errOut, code := inst.ssh(t, bobKey, "", "status", "set", "alice/lib", head,
 92		"--context", "ext/test", "--state", "success"); code != 0 {
 93		t.Fatalf("status set: %s", errOut)
 94	}
 95	merged := inst.mrShow(t, aliceKey, "alice/lib", "1")
 96	if merged.State != "merged" || merged.MergedBy != "alice" {
 97		t.Fatalf("after green checks: state %s merged by %q", merged.State, merged.MergedBy)
 98	}
 99	mustGit(t, dir, env, "fetch", "-q", "origin")
100	if got := strings.TrimSpace(mustGit(t, dir, env, "rev-parse", "origin/main")); got != head {
101		t.Fatalf("main = %s, want %s", got, head)
102	}
103}