vole
Clone
Read only, no credentials:
https://rodent.software/vole.git
Write over SSH with a registered key:
git clone ssh://git@rodent.software:2222/vole.git
A free and open-source forge that lives in your Git repo.
|
6c84d387
Keenan Nemetz
16d ago
|
1 | package web |
| 2 | ||
| 3 | import ( | |
| 4 | "net/http" | |
| 5 | "strings" | |
| 6 | ||
|
d37d301f
Keenan Nemetz
19h ago
|
7 | "rodent.software/vole/forge/access" |
|
6c84d387
Keenan Nemetz
16d ago
|
8 | ) |
| 9 | ||
| 10 | // AllowContributorCI records a maintainer's decision that the current tip of one | |
| 11 | // contributor branch may run. The approval is per commit: a new push waits again. | |
| 12 | // The queue-side operation is supplied by the server (Web.AllowCI), because the | |
| 13 | // web package does not own workflow discovery or the job queue. | |
| 14 | func (w *Web) AllowContributorCI(rw http.ResponseWriter, r *http.Request) { | |
|
c717d4eb
Keenan Nemetz
13d ago
|
15 | ctx, ok := w.beginWrite(rw, r, maxTinyForm) |
|
6c84d387
Keenan Nemetz
16d ago
|
16 | if !ok { |
| 17 | return | |
| 18 | } | |
|
c717d4eb
Keenan Nemetz
13d ago
|
19 | m := ctx.Repo |
| 20 | // Allowing CI is the approval capability: a contributor must not be able to | |
| 21 | // release their own branch's work to a runner. | |
| 22 | if !ctx.canApproveChange() { | |
| 23 | w.refuse(rw, r, "only a maintainer or admin may allow CI") | |
|
6c84d387
Keenan Nemetz
16d ago
|
24 | return |
| 25 | } | |
| 26 | ref := strings.TrimSpace(r.PostFormValue("ref")) | |
|
474a812d
Keenan Nemetz
16d ago
|
27 | if _, ok := access.ContributorRefName(ref); !ok { |
|
6c84d387
Keenan Nemetz
16d ago
|
28 | http.Error(rw, "that is not a contributor branch", http.StatusBadRequest) |
| 29 | return | |
| 30 | } | |
| 31 | tip, err := m.Git().RevParseRaw(ref) | |
| 32 | if err != nil || tip == "" { | |
| 33 | http.Error(rw, "that branch does not exist", http.StatusNotFound) | |
| 34 | return | |
| 35 | } | |
| 36 | if w.AllowCI == nil { | |
|
e84a66f5
Keenan Nemetz
15d ago
|
37 | w.serverError(rw, r, "CI is not wired into this server") |
|
6c84d387
Keenan Nemetz
16d ago
|
38 | return |
| 39 | } | |
|
c717d4eb
Keenan Nemetz
13d ago
|
40 | if err := w.AllowCI(m.Name, ref, tip, ctx.Name); err != nil { |
|
6c84d387
Keenan Nemetz
16d ago
|
41 | http.Error(rw, err.Error(), http.StatusConflict) |
| 42 | return | |
| 43 | } | |
|
b1499c72
Keenan Nemetz
13d ago
|
44 | w.audit("web.ci.allow", ctx.Name, m.Name, ref+" "+tip) |
|
564acd4b
Keenan Nemetz
15d ago
|
45 | // The control lives on the change request now, so return there when the form |
| 46 | // named one. A direct CLI or old-form post still lands on the run history. | |
|
ed03b3d1
Keenan Nemetz
6h ago
|
47 | next := "/" + m.Name + "/runs" |
|
564acd4b
Keenan Nemetz
15d ago
|
48 | if id := strings.TrimSpace(r.PostFormValue("request")); id != "" { |
|
5d440e37
Keenan Nemetz
10d ago
|
49 | if req, err := w.requestAt(memoOf(r), m, id); err == nil { |
|
ed03b3d1
Keenan Nemetz
6h ago
|
50 | next = "/" + m.Name + "/changes/" + req.ID |
|
564acd4b
Keenan Nemetz
15d ago
|
51 | } |
| 52 | } | |
| 53 | http.Redirect(rw, r, next, http.StatusSeeOther) | |
|
6c84d387
Keenan Nemetz
16d ago
|
54 | } |