e2e/status_test.go

v1.7.0
gitbay/e2e/status_test.go history · blame · raw

108 lines · 4749 bytes

  1package e2e
  2
  3import (
  4	"os"
  5	"path/filepath"
  6	"strings"
  7	"testing"
  8)
  9
 10func TestCommitStatuses(t *testing.T) {
 11	inst := startInstance(t)
 12	aliceKey := inst.newKey(t, "alice")
 13	bobKey := inst.newKey(t, "bob")
 14	eveKey := inst.newKey(t, "eve")
 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	inst.admin(t, "admin", "user", "create", "eve", "--key", eveKey+".pub")
 19
 20	// Repo with a branch and an MR.
 21	if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/svc"); code != 0 {
 22		t.Fatalf("repo create: %s", errOut)
 23	}
 24	if _, _, code := inst.ssh(t, aliceKey, "", "repo", "access", "grant", "alice/svc", "bob", "write"); code != 0 {
 25		t.Fatal("grant failed")
 26	}
 27	work := t.TempDir()
 28	env := inst.gitEnv(aliceKey)
 29	mustGit(t, work, env, "clone", inst.sshURL("alice/svc"), "w")
 30	dir := filepath.Join(work, "w")
 31	os.WriteFile(filepath.Join(dir, "svc.txt"), []byte("v1\n"), 0o644)
 32	mustGit(t, dir, env, "checkout", "-q", "-b", "main")
 33	mustGit(t, dir, env, "add", ".")
 34	mustGit(t, dir, env, "commit", "-q", "-m", "base")
 35	mustGit(t, dir, env, "push", "-q", "origin", "main")
 36	mustGit(t, dir, env, "checkout", "-q", "-b", "feat")
 37	mustGit(t, dir, env, "commit", "-q", "--allow-empty", "-m", "feature")
 38	mustGit(t, dir, env, "push", "-q", "origin", "feat")
 39	head := strings.TrimSpace(mustGit(t, dir, env, "rev-parse", "feat"))
 40	if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "create", "alice/svc",
 41		"--source", "feat", "--target", "main", "--title", "'gated'"); code != 0 {
 42		t.Fatalf("mr create: %s", errOut)
 43	}
 44
 45	// Reporting requires write: eve (read-only public) is denied.
 46	if _, _, code := inst.ssh(t, eveKey, "", "status", "set", "alice/svc", head, "--context", "build", "--state", "success"); code != 4 {
 47		t.Fatal("reader reported a status")
 48	}
 49
 50	// Bob (write) reports pending, then success: upsert, not duplicate.
 51	if _, errOut, code := inst.ssh(t, bobKey, "", "status", "set", "alice/svc", head,
 52		"--context", "build", "--state", "pending", "--description", "'compiling'"); code != 0 {
 53		t.Fatalf("status set: %s", errOut)
 54	}
 55	if _, _, code := inst.ssh(t, bobKey, "", "status", "set", "alice/svc", head,
 56		"--context", "build", "--state", "success", "--url", "https://ci.example/1"); code != 0 {
 57		t.Fatal("status update failed")
 58	}
 59	out, _, _ := inst.ssh(t, aliceKey, "", "status", "list", "alice/svc", head, "--json")
 60	if !strings.Contains(out, `"combined":"success"`) || strings.Count(out, `"context":"build"`) != 1 {
 61		t.Fatalf("status list after upsert: %s", out)
 62	}
 63
 64	// A second failing context drags the combined state down; mr show sees it.
 65	if _, _, code := inst.ssh(t, bobKey, "", "status", "set", "alice/svc", head,
 66		"--context", "lint", "--state", "failure"); code != 0 {
 67		t.Fatal("lint status failed")
 68	}
 69	out, _, _ = inst.ssh(t, aliceKey, "", "mr", "show", "alice/svc", "1", "--json")
 70	if !strings.Contains(out, `"checks_combined":"failure"`) {
 71		t.Fatalf("mr show checks: %s", out)
 72	}
 73
 74	// require-checks gates the merge: failing -> refused naming context,
 75	// green -> merges.
 76	if _, _, code := inst.ssh(t, aliceKey, "", "repo", "settings", "require-checks", "alice/svc", "on"); code != 0 {
 77		t.Fatal("require-checks failed")
 78	}
 79	_, errOut, code := inst.ssh(t, aliceKey, "", "mr", "merge", "alice/svc", "1")
 80	if code != 4 || !strings.Contains(errOut, "lint=failure") {
 81		t.Fatalf("merge with red checks: exit %d, %s", code, errOut)
 82	}
 83	if _, _, code := inst.ssh(t, bobKey, "", "status", "set", "alice/svc", head, "--context", "lint", "--state", "success"); code != 0 {
 84		t.Fatal("lint fix failed")
 85	}
 86	if _, errOut, code = inst.ssh(t, aliceKey, "", "mr", "merge", "alice/svc", "1"); code != 0 {
 87		t.Fatalf("merge with green checks: %s", errOut)
 88	}
 89
 90	// A repo requiring checks refuses merges with NO statuses at all.
 91	mustGit(t, dir, env, "checkout", "-q", "-b", "feat2", "main")
 92	mustGit(t, dir, env, "commit", "-q", "--allow-empty", "-m", "next")
 93	mustGit(t, dir, env, "push", "-q", "origin", "feat2")
 94	if _, _, code := inst.ssh(t, aliceKey, "", "mr", "create", "alice/svc",
 95		"--source", "feat2", "--target", "main", "--title", "'unchecked'"); code != 0 {
 96		t.Fatal("mr2 create failed")
 97	}
 98	_, errOut, code = inst.ssh(t, aliceKey, "", "mr", "merge", "alice/svc", "2")
 99	if code != 4 || !strings.Contains(errOut, "none were reported") {
100		t.Fatalf("merge with no checks: exit %d, %s", code, errOut)
101	}
102
103	// Web: the commit page shows check badges.
104	status, body := inst.get(t, "/alice/svc/commit/"+head)
105	if status != 200 || !strings.Contains(body, "check-success") || !strings.Contains(body, "build") {
106		t.Fatalf("commit page checks: %d", status)
107	}
108}