e2e/releaseweb_test.go

0338e6ace3de199d5fc383852649919b68ef3e42
gitbay/e2e/releaseweb_test.go history · blame · raw

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