e2e/status_test.go

ba0a7d33f3a65ce53aafb074fda1682cf1cecfdf
gitbay/e2e/status_test.go history · blame · raw

109 lines · 4763 bytes

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