e2e/migrate_test.go

v1.16.0
gitbay/e2e/migrate_test.go history · blame · raw

103 lines · 4713 bytes

  1package e2e
  2
  3import (
  4	"os"
  5	"path/filepath"
  6	"strings"
  7	"testing"
  8)
  9
 10func TestAccountMigration(t *testing.T) {
 11	src := startInstance(t)
 12	dst := startInstance(t)
 13	key := src.newKey(t, "alice") // one identity, both instances
 14	src.admin(t, "admin", "user", "create", "alice", "--key", key+".pub")
 15	dst.admin(t, "admin", "user", "create", "alice", "--key", key+".pub")
 16
 17	// Source: profile, a repo with settings/topics, an issue thread, an MR.
 18	if _, _, code := src.ssh(t, key, "", "profile", "set", "--description", "'tinkerer'", "--website", "https://alice.example"); code != 0 {
 19		t.Fatal("profile set failed")
 20	}
 21	if _, _, code := src.ssh(t, key, "", "repo", "create", "alice/tool", "--description", "'a fine tool'"); code != 0 {
 22		t.Fatal("repo create failed")
 23	}
 24	if _, _, code := src.ssh(t, key, "", "repo", "create", "alice/notes", "--private"); code != 0 {
 25		t.Fatal("private repo create failed")
 26	}
 27	src.ssh(t, key, "", "repo", "topics", "add", "alice/tool", "go", "cli")
 28	work := t.TempDir()
 29	env := src.gitEnv(key)
 30	mustGit(t, work, env, "clone", src.sshURL("alice/tool"), "w")
 31	dir := filepath.Join(work, "w")
 32	os.WriteFile(filepath.Join(dir, "main.go"), []byte("package main\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	head := strings.TrimSpace(mustGit(t, dir, env, "rev-parse", "HEAD"))
 38	src.ssh(t, key, "", "repo", "settings", "protect", "alice/tool", "main")
 39	src.ssh(t, key, "", "repo", "settings", "require-signed", "alice/tool", "on")
 40	if _, _, code := src.ssh(t, key, "", "issue", "create", "alice/tool", "--title", "'sharpen it'", "--body", "'too dull'"); code != 0 {
 41		t.Fatal("issue create failed")
 42	}
 43	src.ssh(t, key, "", "issue", "label", "alice/tool", "1", "--add", "bug")
 44	src.ssh(t, key, "", "issue", "comment", "alice/tool", "1", "--message", "'on it'")
 45	src.ssh(t, key, "", "issue", "close", "alice/tool", "1")
 46
 47	// Export from the source, replay on the target.
 48	bundleOut, errOut, code := src.ssh(t, key, "", "account", "export")
 49	if code != 0 {
 50		t.Fatalf("export: %s", errOut)
 51	}
 52	if strings.Contains(bundleOut, "ssh-ed25519") || strings.Contains(bundleOut, "PRIVATE") {
 53		t.Fatal("bundle carries key material")
 54	}
 55	out, errOut, code := dst.ssh(t, key, bundleOut, "account", "import-bundle", "--source", "old.example")
 56	if code != 0 {
 57		t.Fatalf("import-bundle: %s", errOut)
 58	}
 59	if !strings.Contains(out, "imported 2 repos, 1 issues, 0 MRs, 1 comments") ||
 60		!strings.Contains(out, "require-signed alice/tool on") ||
 61		!strings.Contains(out, "protect alice/tool main") {
 62		t.Fatalf("import summary: %s", out)
 63	}
 64
 65	// Metadata arrived: issue with state, label, comment, attribution;
 66	// topics, description, visibility.
 67	out, _, _ = dst.ssh(t, key, "", "issue", "show", "alice/tool", "1", "--json")
 68	if !strings.Contains(out, "sharpen it") || !strings.Contains(out, `"state":"closed"`) ||
 69		!strings.Contains(out, `"labels":["bug"]`) || !strings.Contains(out, "on it") ||
 70		!strings.Contains(out, "migrated issue old.example#1") {
 71		t.Fatalf("migrated issue: %s", out)
 72	}
 73	out, _, _ = dst.ssh(t, key, "", "repo", "show", "alice/tool", "--json")
 74	if !strings.Contains(out, `"topics":["cli","go"]`) || !strings.Contains(out, "a fine tool") {
 75		t.Fatalf("migrated repo: %s", out)
 76	}
 77	out, _, _ = dst.ssh(t, key, "", "repo", "show", "alice/notes", "--json")
 78	if !strings.Contains(out, `"visibility":"private"`) {
 79		t.Fatalf("private visibility lost: %s", out)
 80	}
 81	// Deferred policies are NOT applied yet — the push must succeed.
 82	out, _, _ = dst.ssh(t, key, "", "repo", "settings", "show", "alice/tool", "--json")
 83	if strings.Contains(out, `"require_signed_commits":true`) || strings.Contains(out, "protected") {
 84		t.Fatalf("push-blocking settings applied early: %s", out)
 85	}
 86
 87	// Git data client-side: clone from source, push to target (unsigned
 88	// history lands because the policy is deferred).
 89	mirror := t.TempDir()
 90	mustGit(t, mirror, env, "clone", "-q", "--mirror", src.sshURL("alice/tool"), "m")
 91	mdir := filepath.Join(mirror, "m")
 92	mustGit(t, mdir, env, "push", "-q", dst.sshURL("alice/tool"), "+refs/heads/*:refs/heads/*", "+refs/tags/*:refs/tags/*")
 93	out, _, _ = dst.ssh(t, key, "", "repo", "log", "alice/tool", "--json")
 94	if !strings.Contains(out, head) {
 95		t.Fatalf("git data missing on target: %s", out)
 96	}
 97
 98	// Resume: a second replay imports nothing twice.
 99	out, _, code = dst.ssh(t, key, bundleOut, "account", "import-bundle", "--source", "old.example")
100	if code != 0 || !strings.Contains(out, "imported 0 repos, 0 issues, 0 MRs, 0 comments (1 already present)") {
101		t.Fatalf("re-import: %s", out)
102	}
103}