internal/httpd/releaseactions.go
92 lines · 3238 bytes
4 symbols in this file
1package httpd
2
3import (
4 "fmt"
5 "net/http"
6 "strings"
7
8 "gitbay.org/gitbay/internal/store"
9)
10
11// Release and build actions. As elsewhere, the browser chooses arguments
12// and the command decides: tag existence, access, and the gates around
13// archived repositories all stay in one implementation.
14
15func (s *Server) backTo(w http.ResponseWriter, r *http.Request, page, msg string) {
16 dest := fmt.Sprintf("/%s/%s/%s", r.PathValue("owner"), r.PathValue("repo"), page)
17 s.setFlash(w, msg)
18 http.Redirect(w, r, dest, http.StatusSeeOther)
19}
20
21func (s *Server) releaseSubmit(w http.ResponseWriter, r *http.Request, u store.User) {
22 repo := r.PathValue("owner") + "/" + r.PathValue("repo")
23 tag := strings.TrimSpace(r.FormValue("tag"))
24 title := strings.TrimSpace(r.FormValue("title"))
25 notes := strings.TrimSpace(r.FormValue("notes"))
26 if tag == "" {
27 s.backTo(w, r, "releases", "pick a tag")
28 return
29 }
30 // Preview: the page back with the notes rendered, nothing written.
31 // The form name carries the tag, because every release on the page
32 // has an edit box and only the one submitted shows its draft.
33 if wantsPreview(r) {
34 form := "release"
35 if r.FormValue("action") == "edit" {
36 form = "release:" + tag
37 }
38 s.releasesPage(w, r, form)
39 return
40 }
41 back := func(w http.ResponseWriter, r *http.Request, msg string) { s.backTo(w, r, "releases", msg) }
42 // The CLI's --yes guards against a mistyped tag; here the tag comes
43 // from the page, so the browser's own confirm field stands in.
44 if r.FormValue("action") == "delete" {
45 if ok, msg := confirmed(r, tag); !ok {
46 back(w, r, msg)
47 return
48 }
49 _, msg, code := s.runControlCode(u, []string{"release", "delete", repo, tag, "--yes"})
50 s.done(w, r, code, msg, back)
51 return
52 }
53 verb := "create"
54 if r.FormValue("action") == "edit" {
55 verb = "edit"
56 }
57 argv := []string{"release", verb, repo, tag}
58 if title != "" {
59 argv = append(argv, "--title", title)
60 }
61 // edit needs at least one field; create takes the tag alone.
62 if notes != "" || verb == "edit" {
63 argv = append(argv, "--notes", notes)
64 }
65 _, msg, code := s.runControlCode(u, argv)
66 s.done(w, r, code, msg, back)
67}
68
69func (s *Server) buildTriggerSubmit(w http.ResponseWriter, r *http.Request, u store.User) {
70 repo := r.PathValue("owner") + "/" + r.PathValue("repo")
71 job := strings.TrimSpace(r.FormValue("job"))
72 if job == "" {
73 s.backTo(w, r, "builds", "pick a job")
74 return
75 }
76 _, msg, code := s.runControlCode(u, []string{"build", "trigger", repo, job})
77 s.done(w, r, code, msg, func(w http.ResponseWriter, r *http.Request, msg string) { s.backTo(w, r, "builds", msg) })
78}
79
80// buildCancelSubmit withdraws a build. The page only offers the control
81// while a build is still queued; the command decides for real, so a stale
82// page posting against a build that has since finished sees the refusal
83// instead of a silent no-op.
84func (s *Server) buildCancelSubmit(w http.ResponseWriter, r *http.Request, u store.User) {
85 repo := r.PathValue("owner") + "/" + r.PathValue("repo")
86 n := r.PathValue("n")
87 back := func(w http.ResponseWriter, r *http.Request, msg string) {
88 s.backTo(w, r, "builds/"+n, msg)
89 }
90 _, msg, code := s.runControlCode(u, []string{"build", "cancel", repo, n})
91 s.done(w, r, code, msg, back)
92}