internal/web/templates/settings.html
293 lines · 18330 bytes
1{{define "width"}}wide{{end}}
2{{define "title"}}settings · {{.Repo.OwnerName}}/{{.Repo.Name}}{{end}}
3{{define "content"}}
4{{$base := printf "/%s/%s/settings" .Repo.OwnerName .Repo.Name}}
5<h1>Settings</h1>
6{{if .Notice}}{{if .Saved}}<p class="notice" role="status">{{.Notice}}</p>{{else}}<p class="error" role="alert">{{.Notice}}{{if .Reauth}} <a href="/login">Sign in again</a>{{end}}</p>{{end}}{{end}}
7<div class="withcol narrow">
8<nav class="sidecol" aria-label="Sections">
9<details class="sidedrop">
10<summary><span class="sideword">Sections</span></summary>
11 <div class="grp"><h2 class="colhead">Sections</h2>
12 <ul>
13 <li><a href="#identity">Identity</a></li>
14 <li><a href="#access">Access</a></li>
15 <li><a href="#webhooks">Webhooks</a></li>
16 <li><a href="#gates">Merge gates</a></li>
17 <li><a href="#branches">Protected branches</a></li>
18 <li><a href="#tags">Protected tags</a></li>
19 <li><a href="#deps">Dependencies</a></li>
20 <li><a href="#runners">Runners</a></li>
21 <li><a href="#lifecycle">Lifecycle</a></li>
22 </ul></div>
23</details>
24</nav>
25<div class="colmain">
26
27<section id="identity"><h2>Identity</h2>
28<form method="post" action="{{$base}}" class="setform">
29 <input type="hidden" name="field" value="description">
30 <div><label for="description">Description</label></div>
31 <div><input type="text" id="description" name="description" value="{{or (index .Submitted "description") .Desc}}" placeholder="one line, shown in listings"></div>
32 <div><button type="submit">Save</button></div>
33</form>
34<form method="post" action="{{$base}}" class="setform">
35 <input type="hidden" name="field" value="website">
36 <div><label for="website">Website</label></div>
37 <div><input type="text" id="website" name="website" value="{{or (index .Submitted "website") .Repo.Settings.Website}}" placeholder="https://example.org"></div>
38 <div><button type="submit" class="btn">Save</button></div>
39</form>
40<form method="post" action="{{$base}}" class="setform">
41 <input type="hidden" name="field" value="topics">
42 <div><label for="topics">Topics</label><p class="hint">Comma separated, lower case.</p></div>
43 <div><input type="text" id="topics" name="topics" value="{{or (index .Submitted "topics") (join .Topics ", ")}}"></div>
44 <div><button type="submit" class="btn">Save</button></div>
45</form>
46{{if .Branches}}<form method="post" action="{{$base}}" class="setform">
47 <input type="hidden" name="field" value="default-branch">
48 <div><label for="default-branch">Default branch</label></div>
49 <div><select id="default-branch" name="default-branch">{{$cur := .Repo.DefaultBranch}}{{range .Branches}}<option value="{{.Name}}"{{if eq .Name $cur}} selected{{end}}>{{.Name}}</option>{{end}}</select></div>
50 <div><button type="submit" class="btn">Save</button></div>
51</form>{{end}}
52</section>
53
54<section id="access"><h2>Access</h2>
55<form method="post" action="{{$base}}" class="setform">
56 <input type="hidden" name="field" value="visibility">
57 <div><span class="fieldname">Visibility</span></div>
58 <div class="check">
59 <label><input type="radio" name="visibility" value="public"{{if eq .Repo.Visibility "public"}} checked{{end}}> Public</label>
60 <label><input type="radio" name="visibility" value="private"{{if eq .Repo.Visibility "private"}} checked{{end}}> Private</label>
61 </div>
62 <div><button type="submit" class="btn">Save</button></div>
63</form>
64<form method="post" action="{{$base}}" class="setform">
65 <input type="hidden" name="field" value="git-daemon">
66 <div><label for="git-daemon">Serve over git://</label><p class="hint">Public repositories only.</p></div>
67 <div class="check"><input type="checkbox" id="git-daemon" name="git-daemon" value="on"{{if .Repo.Settings.GitDaemon}} checked{{end}}></div>
68 <div><button type="submit" class="btn">Save</button></div>
69</form>
70<h3>Who can reach this repository</h3>
71{{if .Access}}<div class="tablewrap"><table class="keys">
72<thead><tr class="cols"><th scope="col">user</th><th scope="col">role</th><th scope="col">via</th><th scope="col"><span class="vh">actions</span></th></tr></thead>
73<tbody>{{range .Access}}<tr>
74 <td class="mono"><a href="/{{.User}}">{{.User}}</a></td>
75 <td>{{.Role}}</td>
76 <td>{{.Source}}</td>
77 <td class="act">{{if eq .Source "direct"}}<form method="post" action="{{$base}}" class="inline">
78 <input type="hidden" name="field" value="access-revoke">
79 <input type="hidden" name="user" value="{{.User}}">
80 <button type="submit" class="danger">Revoke</button>
81 </form>{{end}}</td>
82</tr>{{end}}</tbody></table></div>
83{{else}}<p class="meta">Nobody else can reach it.</p>{{end}}
84<form method="post" action="{{$base}}" class="setform">
85 <input type="hidden" name="field" value="access-grant">
86 <div><label for="grant-user">Grant access</label><p class="hint">An account name and a role. A grant adds to what an organization or team already gives.</p></div>
87 <div><input type="text" id="grant-user" name="user" value="{{index .Submitted "user"}}" autocomplete="off" spellcheck="false" placeholder="username">
88 <select name="role" aria-label="Role">{{$role := index .Submitted "role"}}<option value="read"{{if eq $role "read"}} selected{{end}}>read</option><option value="write"{{if eq $role "write"}} selected{{end}}>write</option><option value="admin"{{if eq $role "admin"}} selected{{end}}>admin</option></select></div>
89 <div><button type="submit" class="btn">Grant</button></div>
90</form>
91</section>
92
93<section id="webhooks"><h2>Webhooks</h2>
94{{if .Hooks}}
95<ul class="protlist">
96{{range .Hooks}}<li><span class="mono">#{{.ID}}</span> <code>{{.URL}}</code> <span class="meta">{{.Events}}{{if .Secret}}, signed{{end}}</span>
97 <form method="post" action="{{$base}}" class="inline">
98 <input type="hidden" name="field" value="webhook-remove">
99 <input type="hidden" name="id" value="{{.ID}}">
100 <button type="submit" class="danger">Remove</button>
101 </form></li>
102{{end}}
103</ul>
104{{else}}<p class="meta">No webhooks.</p>{{end}}
105<form method="post" action="{{$base}}" class="setform stack" autocomplete="off">
106 <input type="hidden" name="field" value="webhook-add">
107 <label for="hook-url">Add a webhook</label>
108 <input type="text" id="hook-url" name="url" value="{{index .Submitted "url"}}" placeholder="https://ci.example.org/hook" spellcheck="false">
109 <label for="hook-events">Events</label>
110 <p class="hint">Comma separated, or <code>*</code> for all.</p>
111 <input type="text" id="hook-events" name="events" value="{{or (index .Submitted "events") "*"}}" spellcheck="false">
112 <label for="hook-secret">Secret</label>
113 <p class="hint">Optional. Signs each delivery; it is not shown again.</p>
114 <input type="password" id="hook-secret" name="secret" value="" autocomplete="new-password">
115 <button type="submit" class="btn">Add</button>
116</form>
117<h3>Recent deliveries</h3>
118{{if .Deliveries}}<div class="tablewrap"><table class="keys">
119<thead><tr class="cols"><th scope="col">id</th><th scope="col">event</th><th scope="col">url</th><th scope="col">state</th><th scope="col"><span class="vh">actions</span></th></tr></thead>
120<tbody>{{range .Deliveries}}<tr>
121 <td class="mono">{{.ID}}</td>
122 <td>{{.Event}}</td>
123 <td class="mono">{{.URL}}</td>
124 <td>{{.Status}} ({{.Attempts}} attempts){{if .LastError}}<br><span class="meta">{{.LastError}}</span>{{end}}</td>
125 <td class="act"><form method="post" action="{{$base}}" class="inline">
126 <input type="hidden" name="field" value="webhook-redeliver">
127 <input type="hidden" name="delivery" value="{{.ID}}">
128 <button type="submit" class="btn">Redeliver</button>
129 </form></td>
130</tr>{{end}}</tbody></table></div>
131{{else}}<p class="meta">Nothing delivered yet.</p>{{end}}
132</section>
133
134<section id="gates"><h2>Merge gates</h2>
135<p class="meta">Checked before a merge, in this order: checks, approvals, resolved threads, signatures.</p>
136<form method="post" action="{{$base}}" class="setform">
137 <input type="hidden" name="field" value="require-checks">
138 <div><label for="require-checks">Required checks</label><p class="hint">Requires CI to succeed.{{with .Repo.Settings.RequiredContexts}} Also waits for {{range $i, $c := .}}{{if $i}}, {{end}}<code>{{$c}}</code>{{end}} until they report{{if not $.Repo.Settings.RequireChecks}}, once this is on{{end}}.{{end}}</p></div>
139 <div class="check"><input type="checkbox" id="require-checks" name="require-checks" value="on"{{if .Repo.Settings.RequireChecks}} checked{{end}}></div>
140 <div><button type="submit" class="btn">Save</button></div>
141</form>
142<form method="post" action="{{$base}}" class="setform">
143 <input type="hidden" name="field" value="require-contexts">
144 <div><label for="contexts">Required contexts</label><p class="hint">Statuses the checks gate waits for until they report, separated by spaces. Saving any turns required checks on; saving none leaves it as it is.</p></div>
145 <div><input type="text" id="contexts" name="contexts" value="{{range $i, $c := .Repo.Settings.RequiredContexts}}{{if $i}} {{end}}{{$c}}{{end}}" autocomplete="off"></div>
146 <div><button type="submit" class="btn">Save</button></div>
147</form>
148<form method="post" action="{{$base}}" class="setform">
149 <input type="hidden" name="field" value="require-approvals">
150 <div><label for="approvals">Approvals</label><p class="hint">Approvals from anyone with write access. Zero means none required.</p></div>
151 <div class="num"><input type="number" id="approvals" name="approvals" min="0" max="10" value="{{.Repo.Settings.RequireApprovals}}"></div>
152 <div><button type="submit" class="btn">Save</button></div>
153</form>
154<form method="post" action="{{$base}}" class="setform">
155 <input type="hidden" name="field" value="require-resolved">
156 <div><label for="require-resolved">Review threads</label><p class="hint">Every thread on the diff must be resolved before merging.</p></div>
157 <div class="check"><input type="checkbox" id="require-resolved" name="require-resolved" value="on"{{if .Repo.Settings.RequireResolved}} checked{{end}}></div>
158 <div><button type="submit" class="btn">Save</button></div>
159</form>
160<form method="post" action="{{$base}}" class="setform">
161 <input type="hidden" name="field" value="require-codeowners">
162 <div><label for="require-codeowners">CODEOWNERS</label><p class="hint">Code owners must approve.</p></div>
163 <div class="check"><input type="checkbox" id="require-codeowners" name="require-codeowners" value="on"{{if .Repo.Settings.RequireCodeowners}} checked{{end}}></div>
164 <div><button type="submit" class="btn">Save</button></div>
165</form>
166<form method="post" action="{{$base}}" class="setform">
167 <input type="hidden" name="field" value="require-signed">
168 <div><label for="require-signed">Signed commits</label><p class="hint">Every commit in the request must carry a verified signature. Squash and merge strategies are refused, since both mint an unsigned commit.</p></div>
169 <div class="check"><input type="checkbox" id="require-signed" name="require-signed" value="on"{{if .Repo.Settings.RequireSignedCommits}} checked{{end}}></div>
170 <div><button type="submit" class="btn">Save</button></div>
171</form>
172</section>
173
174<section id="branches"><h2>Protected branches</h2>
175{{if .Repo.Settings.ProtectedBranches}}
176<ul class="protlist">
177{{$mr := .Repo.Settings.RequireMR}}{{range .Repo.Settings.ProtectedBranches}}<li><code>{{.}}</code>{{if $mr}} <span class="hint">Direct pushes refused, merge requests only.</span>{{end}}
178 <form method="post" action="{{$base}}" class="inline">
179 <input type="hidden" name="field" value="unprotect">
180 <input type="hidden" name="branch" value="{{.}}">
181 <button type="submit" class="danger">Unprotect</button>
182 </form></li>
183{{end}}
184</ul>
185{{else}}<p class="meta">No protected branches. A protected branch refuses deletion and force-pushes.</p>{{end}}
186<form method="post" action="{{$base}}" class="setform">
187 <input type="hidden" name="field" value="protect">
188 <div><label for="branch">Protect a branch</label></div>
189 <div><select id="branch" name="branch">{{range .Branches}}<option value="{{.Name}}">{{.Name}}</option>{{end}}</select></div>
190 <div><button type="submit" class="btn">Protect</button></div>
191</form>
192<form method="post" action="{{$base}}" class="setform">
193 <input type="hidden" name="field" value="require-mr">
194 <div><label for="require-mr">Require merge requests</label><p class="hint">Every protected branch changes through a merge request. A direct push is refused in pre-receive.</p></div>
195 <div class="check"><input type="checkbox" id="require-mr" name="require-mr" value="on"{{if .Repo.Settings.RequireMR}} checked{{end}}></div>
196 <div><button type="submit" class="btn">Save</button></div>
197</form>
198</section>
199
200<section id="tags"><h2>Protected tags</h2>
201{{if .Repo.Settings.ProtectedTags}}
202<ul class="protlist">
203{{range .Repo.Settings.ProtectedTags}}<li><code>{{.}}</code>
204 <form method="post" action="{{$base}}" class="inline">
205 <input type="hidden" name="field" value="unprotect-tag">
206 <input type="hidden" name="glob" value="{{.}}">
207 <button type="submit" class="danger">Unprotect</button>
208 </form></li>
209{{end}}
210</ul>
211{{else}}<p class="meta">No protected tags. A tag matching a protected glob is created once and refuses moves and deletion. A tag a release is anchored to refuses both regardless.</p>{{end}}
212<form method="post" action="{{$base}}" class="setform">
213 <input type="hidden" name="field" value="protect-tag">
214 <div><label for="glob">Protect tags matching</label></div>
215 <div><input type="text" id="glob" name="glob" placeholder="v*"></div>
216 <div><button type="submit" class="btn">Protect</button></div>
217</form>
218</section>
219
220<section id="deps"><h2>Dependencies</h2>
221<form method="post" action="{{$base}}" class="setform">
222 <input type="hidden" name="field" value="deps">
223 <div><label for="deps-enabled">Check for updates</label><p class="hint">Evaluates the manifests on <code>{{.Repo.DefaultBranch}}</code> and opens an issue. Go, NPM, Crates, and PyPI only.</p></div>
224 <div class="check"><input type="checkbox" id="deps-enabled" name="deps" value="on"{{if .DepsEnabled}} checked{{end}}></div>
225 <div><button type="submit" class="btn">Save</button></div>
226</form>
227{{if .DepsEnabled}}
228<p class="meta">Last checked {{if .Deps.LastCheck}}{{when .Deps.LastCheck}}{{else}}never{{end}}{{if .Deps.IssueNumber}} · <a href="/{{.Repo.OwnerName}}/{{.Repo.Name}}/issues/{{.Deps.IssueNumber}}">#{{.Deps.IssueNumber}}</a>{{end}}</p>
229{{if .Deps.LastError}}<p class="error" role="alert">{{.Deps.LastError}}</p>{{end}}
230{{if .Deps.Behind}}<div class="tablewrap"><table class="keys">
231<tr class="cols"><th scope="col">dependency</th><th scope="col">pinned</th><th scope="col">latest</th></tr>
232{{range .Deps.Behind}}<tr>
233 <td class="mono">{{.Ecosystem}} {{.Name}}</td>
234 <td class="mono">{{.Current}}</td>
235 <td class="mono">{{.Latest}}</td>
236</tr>
237{{end}}</table></div>
238{{else}}<p class="none">Nothing behind{{if not .Deps.LastCheck}} — the first check has not run yet{{end}}.</p>{{end}}
239{{end}}
240</section>
241
242<section id="runners"><h2>Runners</h2>
243{{if .Runners}}
244<ul class="protlist">
245{{range .Runners}}<li><code>{{.Fingerprint}}</code> <span class="meta">{{.Username}}{{if .LastSeen}}, last poll {{when .LastSeen}}{{else}}, never polled{{end}}{{if .BuildNumber}}, running {{.BuildRepo}} #{{.BuildNumber}} {{.BuildJob}}{{end}}</span>
246 <form method="post" action="{{$base}}" class="inline">
247 <input type="hidden" name="field" value="runner-remove">
248 <input type="hidden" name="fingerprint" value="{{.Fingerprint}}">
249 <button type="submit" class="danger">Detach</button>
250 </form></li>
251{{end}}
252</ul>
253{{else}}<p class="meta">No runners attached. Builds for this repository run on the runners attached here; a repository with none queues builds nothing claims.</p>{{end}}
254<form method="post" action="{{$base}}" class="setform stack">
255 <input type="hidden" name="field" value="runner-add">
256 <label for="runner-key">Attach a runner</label>
257 <p class="hint">Install <code>gitbay-runner</code>, run <code>gitbay-runner init</code>, and paste the key it prints. The runner builds your commits with the repository's secrets; merge requests from forks wait unless it runs with <code>-untrusted</code>.</p>
258 <textarea id="runner-key" name="key" rows="3" spellcheck="false" placeholder="ssh-ed25519 AAAA… (from gitbay-runner init)">{{index .Submitted "key"}}</textarea>
259 <button type="submit" class="btn">Attach</button>
260</form>
261</section>
262
263<section id="lifecycle"><h2>Lifecycle</h2>
264<form method="post" action="{{$base}}" class="setform">
265 <input type="hidden" name="field" value="archive">
266 <div><label for="archive">Archived</label><p class="hint">Read-only for everyone. Issues and requests close to new activity. Reversible.</p></div>
267 <div class="check"><input type="checkbox" id="archive" name="archive" value="on"{{if .Repo.Settings.Archived}} checked{{end}}></div>
268 <div><button type="submit" {{if .Repo.Settings.Archived}}class="btn"{{else}}class="danger"{{end}}>Save</button></div>
269</form>
270<form method="post" action="{{$base}}" class="setform">
271 <input type="hidden" name="field" value="rename">
272 <div><label for="rename">Name</label><p class="hint">Clone URLs change. The old path stops resolving.</p></div>
273 <div><input type="text" id="rename" name="name" value="{{or (index .Submitted "name") .Repo.Name}}" autocomplete="off" spellcheck="false"></div>
274 <div><button type="submit" class="btn">Rename</button></div>
275</form>
276{{$path := printf "%s/%s" .Repo.OwnerName .Repo.Name}}
277<form method="post" action="{{$base}}" class="setform stack">
278 <input type="hidden" name="field" value="transfer">
279 <label for="new-owner">Transfer</label>
280 <p class="hint">Move it to your own account or an organization you administer. Clone URLs change.</p>
281 <input type="text" id="new-owner" name="new-owner" value="{{index .Submitted "new-owner"}}" placeholder="new owner" autocomplete="off" spellcheck="false">
282 <p>{{template "confirmfield" $path}} <button type="submit" class="danger">Transfer</button></p>
283</form>
284<form method="post" action="{{$base}}" class="setform stack">
285 <input type="hidden" name="field" value="delete">
286 <span class="fieldname">Delete</span>
287 <p class="hint">Removes the repository, its issues and merge requests. Cannot be undone.</p>
288 <p>{{template "confirmfield" $path}} <button type="submit" class="danger">Delete repository</button></p>
289</form>
290</section>
291</div>
292</div>
293{{end}}