e2e/releaseweb_test.go

a7c9352033c319587613cb6825035e8d99f5871a
gitbay/e2e/releaseweb_test.go history · blame · raw

121 lines · 5054 bytes

  1package e2e
  2
  3import (
  4	"net/url"
  5	"os"
  6	"path/filepath"
  7	"strings"
  8	"testing"
  9)
 10
 11// TestReleaseAndBuildWeb creates and edits a release and triggers a build
 12// from the browser, each through the command the CLI runs.
 13func TestReleaseAndBuildWeb(t *testing.T) {
 14	inst := startInstanceWith(t, "[web]\nmode = \"accounts\"\n")
 15	inst.runner = buildRunner(t)
 16	aliceKey := inst.newKey(t, "alice")
 17	inst.admin(t, "admin", "user", "create", "alice",
 18		"--key", aliceKey+".pub", "--email", "alice@example.test", "--verified")
 19	runnerKey := inst.newKey(t, "ci")
 20	inst.admin(t, "admin", "user", "create", "ci", "--key", runnerKey+".pub", "--admin")
 21
 22	if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
 23		t.Fatalf("repo create: %s", errOut)
 24	}
 25	env := inst.gitEnv(aliceKey)
 26	work := t.TempDir()
 27	mustGit(t, work, env, "clone", inst.sshURL("alice/app"), "w")
 28	dir := filepath.Join(work, "w")
 29	os.MkdirAll(filepath.Join(dir, ".gitbay"), 0o755)
 30	os.WriteFile(filepath.Join(dir, ".gitbay", "ci.yml"),
 31		[]byte("jobs:\n  smoke:\n    steps:\n      - echo ok\n"), 0o644)
 32	os.WriteFile(filepath.Join(dir, "a.txt"), []byte("a\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, "tag", "-a", "v1.0", "-m", "first")
 37	mustGit(t, dir, env, "push", "-q", "origin", "main", "v1.0")
 38
 39	alice := inst.login(t, aliceKey)
 40	base := inst.base() + "/alice/app"
 41
 42	// The pushed tag is offered, and creating from it works.
 43	_, page := browserGet(t, alice, base+"/releases")
 44	if !strings.Contains(page, `value="v1.0"`) {
 45		t.Fatalf("tag not offered:\n%s", page)
 46	}
 47	if status, _ := browserPost(t, alice, base+"/releases", url.Values{
 48		"tag": {"v1.0"}, "title": {"First light"}, "notes": {"the **first** one"}}); status != 200 {
 49		t.Fatal("release create failed")
 50	}
 51	out, _, _ := inst.ssh(t, aliceKey, "", "release", "show", "alice/app", "v1.0", "--json")
 52	if !strings.Contains(out, "First light") || !strings.Contains(out, "the **first** one") {
 53		t.Fatalf("release not created:\n%s", out)
 54	}
 55
 56	// Editing keeps the tag and replaces the fields.
 57	if status, _ := browserPost(t, alice, base+"/releases", url.Values{
 58		"action": {"edit"}, "tag": {"v1.0"}, "title": {"Second light"}, "notes": {"revised"}}); status != 200 {
 59		t.Fatal("release edit failed")
 60	}
 61	out, _, _ = inst.ssh(t, aliceKey, "", "release", "show", "alice/app", "v1.0", "--json")
 62	if !strings.Contains(out, "Second light") || !strings.Contains(out, "revised") {
 63		t.Fatalf("release not edited:\n%s", out)
 64	}
 65	// A released tag is no longer offered for creation.
 66	if _, page = browserGet(t, alice, base+"/releases"); strings.Contains(page, `<option value="v1.0"`) {
 67		t.Fatalf("released tag still offered:\n%s", page)
 68	}
 69
 70	// Builds: the job from the config is offered and runs on demand.
 71	_, bpage := browserGet(t, alice, base+"/builds")
 72	if !strings.Contains(bpage, `value="smoke"`) {
 73		t.Fatalf("job not offered:\n%s", bpage)
 74	}
 75	if status, _ := browserPost(t, alice, base+"/builds", url.Values{"job": {"smoke"}}); status != 200 {
 76		t.Fatal("trigger failed")
 77	}
 78	inst.runnerOnce(t, runnerKey)
 79	out, _, _ = inst.ssh(t, aliceKey, "", "build", "list", "alice/app")
 80	if !strings.Contains(out, "smoke\tsuccess") {
 81		t.Fatalf("triggered build did not run:\n%s", out)
 82	}
 83
 84	// A reader sees neither control.
 85	bobKey := inst.newKey(t, "bob")
 86	inst.admin(t, "admin", "user", "create", "bob", "--key", bobKey+".pub")
 87	bob := inst.login(t, bobKey)
 88	if _, p := browserGet(t, bob, base+"/builds"); strings.Contains(p, "Run a job now") {
 89		t.Fatal("reader sees the trigger control")
 90	}
 91	if _, p := browserGet(t, bob, base+"/releases"); strings.Contains(p, "New release") ||
 92		strings.Contains(p, "Delete release") {
 93		t.Fatal("reader sees a release control")
 94	}
 95
 96	// Delete is offered to a repo admin and removes the release; the tag
 97	// survives, so it is offered for creation again (#165).
 98	if _, p := browserGet(t, alice, base+"/releases"); !strings.Contains(p, "Delete release") {
 99		t.Fatalf("owner is not offered the delete control:\n%s", p)
100	}
101	_, body := browserPost(t, alice, base+"/releases", url.Values{
102		"action": {"delete"}, "tag": {"v1.0"}})
103	if !strings.Contains(body, "type v1.0 to confirm") {
104		t.Fatalf("unconfirmed delete was not refused:\n%s", body)
105	}
106	out, _, _ = inst.ssh(t, aliceKey, "", "release", "list", "alice/app", "--json")
107	if !strings.Contains(out, "v1.0") {
108		t.Fatalf("release removed without confirmation: %s", out)
109	}
110	if status, _ := browserPost(t, alice, base+"/releases", url.Values{
111		"action": {"delete"}, "tag": {"v1.0"}, "confirm": {"v1.0"}}); status != 200 {
112		t.Fatal("release delete failed")
113	}
114	out, _, _ = inst.ssh(t, aliceKey, "", "release", "list", "alice/app", "--json")
115	if strings.Contains(out, "v1.0") {
116		t.Fatalf("release still listed after delete:\n%s", out)
117	}
118	if _, p := browserGet(t, alice, base+"/releases"); !strings.Contains(p, `<option value="v1.0"`) {
119		t.Fatalf("tag not free again after delete:\n%s", p)
120	}
121}