e2e/migratemr_test.go

v1.34.1
gitbay/e2e/migratemr_test.go history · blame · raw

100 lines · 4133 bytes

  1package e2e
  2
  3import (
  4	"os"
  5	"path/filepath"
  6	"strings"
  7	"testing"
  8)
  9
 10// TestMigratedMRHasADiff covers #128's concrete symptom: a merge request
 11// replayed from a bundle used to arrive with an empty head, so `mr diff`
 12// on it could only fail. The bundle carries the head and the merge base
 13// now, and the head ref is set once the git objects are pushed.
 14//
 15// The merge request here is merged and its source branch deleted, which
 16// is the case that actually breaks. While the branch still exists the
 17// diff resolves through it and an empty head_sha is invisible — the first
 18// version of this test made that mistake and passed without the fix.
 19func TestMigratedMRHasADiff(t *testing.T) {
 20	t.Parallel()
 21	src := startInstance(t)
 22	dst := startInstance(t)
 23	key := src.newKey(t, "alice")
 24	src.admin(t, "admin", "user", "create", "alice", "--key", key+".pub")
 25	dst.admin(t, "admin", "user", "create", "alice", "--key", key+".pub")
 26
 27	if _, errOut, code := src.ssh(t, key, "", "repo", "create", "alice/tool"); code != 0 {
 28		t.Fatalf("repo create: %s", errOut)
 29	}
 30	env := src.gitEnv(key)
 31	work := t.TempDir()
 32	mustGit(t, work, env, "clone", src.sshURL("alice/tool"), "w")
 33	dir := filepath.Join(work, "w")
 34	os.WriteFile(filepath.Join(dir, "main.go"), []byte("package main\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
 40	mustGit(t, dir, env, "checkout", "-q", "-b", "feat")
 41	os.WriteFile(filepath.Join(dir, "main.go"), []byte("package main\n\nfunc F() {}\n"), 0o644)
 42	mustGit(t, dir, env, "add", ".")
 43	mustGit(t, dir, env, "commit", "-q", "-m", "add F")
 44	mustGit(t, dir, env, "push", "-q", "origin", "feat")
 45	if _, errOut, code := src.ssh(t, key, "", "mr", "create", "alice/tool",
 46		"--source", "feat", "--target", "main", "--title", "'add F'"); code != 0 {
 47		t.Fatalf("mr create: %s", errOut)
 48	}
 49	// Merge it and delete the branch, the way a finished merge request
 50	// ends up. Now nothing but the recorded head says what it contained.
 51	if _, errOut, code := src.ssh(t, key, "", "mr", "merge", "alice/tool", "1"); code != 0 {
 52		t.Fatalf("merge: %s", errOut)
 53	}
 54	mustGit(t, dir, env, "push", "-q", "origin", "--delete", "feat")
 55
 56	// The source's own diff is the standard to match.
 57	want, errOut, code := src.ssh(t, key, "", "mr", "diff", "alice/tool", "1")
 58	if code != 0 || !strings.Contains(want, "func F()") {
 59		t.Fatalf("source diff: %s\n%s", errOut, want)
 60	}
 61
 62	bundle, errOut, code := src.ssh(t, key, "", "account", "export")
 63	if code != 0 {
 64		t.Fatalf("export: %s", errOut)
 65	}
 66	if !strings.Contains(bundle, `"head_sha"`) {
 67		t.Fatalf("bundle carries no head_sha:\n%s", bundle)
 68	}
 69	if _, errOut, code := dst.ssh(t, key, bundle, "account", "import-bundle"); code != 0 {
 70		t.Fatalf("import: %s", errOut)
 71	}
 72
 73	// Git data moves separately, which is the order a real migration runs
 74	// in: the bundle first, the push after.
 75	// Only main: the feature branch is gone, exactly as at the source.
 76	// The merge commit carries the head's objects, so they arrive anyway.
 77	denv := dst.gitEnv(key)
 78	mustGit(t, dir, denv, "remote", "add", "dst", dst.sshURL("alice/tool"))
 79	mustGit(t, dir, denv, "fetch", "-q", "origin", "main")
 80	mustGit(t, dir, denv, "push", "-q", "dst", "refs/remotes/origin/main:refs/heads/main")
 81
 82	// Re-importing the same bundle is how the head ref gets set once the
 83	// objects are present; the merge request itself is already there.
 84	out, errOut, code := dst.ssh(t, key, bundle, "account", "import-bundle")
 85	if code != 0 {
 86		t.Fatalf("re-import: %s", errOut)
 87	}
 88	if !strings.Contains(out, "already present") {
 89		t.Fatalf("re-import did not skip what it had: %s", out)
 90	}
 91
 92	show, _, _ := dst.ssh(t, key, "", "mr", "show", "alice/tool", "1", "--json")
 93	got, errOut, code := dst.ssh(t, key, "", "mr", "diff", "alice/tool", "1")
 94	if code != 0 {
 95		t.Fatalf("migrated MR has no diff: %s\n%s\nmr show: %s", errOut, got, show)
 96	}
 97	if !strings.Contains(got, "func F()") {
 98		t.Fatalf("migrated diff does not match the source:\nwant to contain func F()\ngot:\n%s", got)
 99	}
100}