e2e/tagprotect_test.go
78 lines · 3447 bytes
1package e2e
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7 "testing"
8)
9
10// Protected-tag globs refuse moving and deleting matching tags; a tag a
11// release is anchored to refuses both on its own (#201).
12func TestTagProtection(t *testing.T) {
13 t.Parallel()
14 inst := startInstance(t)
15 aliceKey := inst.newKey(t, "alice")
16 inst.admin(t, "admin", "user", "create", "alice", "--key", aliceKey+".pub")
17 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
18 t.Fatalf("repo create: %s", errOut)
19 }
20 work := t.TempDir()
21 env := inst.gitEnv(aliceKey)
22 mustGit(t, work, env, "clone", "-q", inst.sshURL("alice/app"), "w")
23 dir := filepath.Join(work, "w")
24 if err := os.WriteFile(filepath.Join(dir, "a.txt"), []byte("a\n"), 0o644); err != nil {
25 t.Fatal(err)
26 }
27 mustGit(t, dir, env, "checkout", "-q", "-b", "main")
28 mustGit(t, dir, env, "add", ".")
29 mustGit(t, dir, env, "commit", "-q", "-m", "base")
30 mustGit(t, dir, env, "tag", "v1.0")
31 mustGit(t, dir, env, "tag", "nightly")
32 mustGit(t, dir, env, "push", "-q", "origin", "main", "v1.0", "nightly")
33
34 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "settings", "protect-tag", "alice/app", "'['"); code != 2 {
35 t.Fatalf("bad glob accepted: %d %s", code, errOut)
36 }
37 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "settings", "protect-tag", "alice/app", "'v*'"); code != 0 {
38 t.Fatalf("protect-tag: %s", errOut)
39 }
40 out, _, _ := inst.ssh(t, aliceKey, "", "repo", "settings", "show", "alice/app", "--json")
41 if !strings.Contains(out, `"protected_tags":["v*"]`) {
42 t.Fatalf("settings show: %s", out)
43 }
44
45 // Delete and move are refused for a matching tag; an unmatched tag is
46 // free, and a new matching tag can still be created.
47 if out, code := gitRun(t, dir, env, "push", "origin", ":v1.0"); code == 0 || !strings.Contains(out, "protected") {
48 t.Fatalf("protected tag deleted: %d\n%s", code, out)
49 }
50 mustGit(t, dir, env, "commit", "-q", "--allow-empty", "-m", "second")
51 mustGit(t, dir, env, "tag", "-f", "v1.0")
52 if out, code := gitRun(t, dir, env, "push", "--force", "origin", "v1.0"); code == 0 || !strings.Contains(out, "protected") {
53 t.Fatalf("protected tag moved: %d\n%s", code, out)
54 }
55 mustGit(t, dir, env, "push", "-q", "origin", ":nightly")
56 mustGit(t, dir, env, "tag", "v1.1")
57 mustGit(t, dir, env, "push", "-q", "origin", "v1.1")
58
59 // Unprotected again, the tag can go — unless a release anchors it.
60 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "settings", "unprotect-tag", "alice/app", "'v*'"); code != 0 {
61 t.Fatalf("unprotect-tag: %s", errOut)
62 }
63 if _, errOut, code := inst.ssh(t, aliceKey, "", "release", "create", "alice/app", "v1.1", "--title", "'one one'"); code != 0 {
64 t.Fatalf("release create: %s", errOut)
65 }
66 if out, code := gitRun(t, dir, env, "push", "origin", ":v1.1"); code == 0 || !strings.Contains(out, "anchors a release") {
67 t.Fatalf("release tag deleted: %d\n%s", code, out)
68 }
69 mustGit(t, dir, env, "commit", "-q", "--allow-empty", "-m", "third")
70 mustGit(t, dir, env, "tag", "-f", "v1.1")
71 if out, code := gitRun(t, dir, env, "push", "--force", "origin", "v1.1"); code == 0 || !strings.Contains(out, "anchors a release") {
72 t.Fatalf("release tag moved: %d\n%s", code, out)
73 }
74 if _, errOut, code := inst.ssh(t, aliceKey, "", "release", "delete", "alice/app", "v1.1", "--yes"); code != 0 {
75 t.Fatalf("release delete: %s", errOut)
76 }
77 mustGit(t, dir, env, "push", "-q", "origin", ":v1.1")
78}