internal/web/templates/settings.html

v1.41.0
gitbay/internal/web/templates/settings.html history · blame · raw

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}}