Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

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.

Test the merge result before landing it

e5478085e5b53a2892d0649d6f07c6f0a5653378 · Keenan Nemetz · 11d ago · parent db5e4382

Test the merge result before landing it

A protected branch could receive a non-fast-forward landing whose tree was
never built: the gate asked for checks on the request head, and the merge
commit was made at landing time. A pushed merge with the right parents but
extra content was accepted too.

Publish the merge commit under refs/vole/candidates/, test it as the base
branch, and make the gate require its results. Approvals name the head and
the base branch, so a moved base retests without a new approval. A merger
who clicks while that run is still going waits for it instead of clicking
again. A pushed merge commit now has to carry exactly the tree a clean merge
would produce.

Closes: 01M61QQ56TESQ1HTMB1Z5C3733

server/web/templates/requests.html +37−3

@@ -114,6 +114,7 @@
114 114 {{define "request_sidebar"}}
115 115 <div id="request-sidebar">
116 116 {{if .Error}}<p class="error">{{.Error}}</p>{{end}}
117 {{if .Notice}}<p class="muted">{{.Notice}}</p>{{end}}
117 118 <section>
118 119 <h2 class="with-more"><span>{{icon "git-branch"}}Review{{template "help" "The request follows its head branch, so a push moves the head with it. Changing the base or head starts approvals over. A conflict here blocks landing."}}</span> <a class="more sha" href="/r/{{.Name}}/commit/{{.Request.Head}}" title="commit under review">{{short .Request.Head}}</a></h2>
119 120 {{if .MergeChecked}}{{if .Conflicts}}
@@ -199,6 +200,34 @@
199 200 <p class="muted">No CI run for this commit yet.</p>
200 201 {{end}}
201 202 </section>
203
204 {{if .CombinedNeeded}}
205 <section>
206 <h2 class="with-more"><span>{{icon "git-merge"}}Combined result{{template "help" "The merge that would land, built from this change and the latest base. It is tested automatically so the branch is ready when the review is. Only a conflict needs work on the branch."}}</span> {{if .CombinedSHA}}<a class="more sha" href="/r/{{.Name}}/commit/{{.CombinedSHA}}" title="combined result commit">{{short .CombinedSHA}}</a>{{end}}</h2>
207 {{if eq .CombinedState "passed"}}
208 <p class="muted">Passed with the latest <code>{{.Request.Base}}</code>.</p>
209 {{else if eq .CombinedState "testing"}}
210 <p class="muted">Testing the merge with the latest <code>{{.Request.Base}}</code>…</p>
211 {{else if eq .CombinedState "failed"}}
212 <p class="conflict">The combined result with <code>{{.Request.Base}}</code> failed. The runs below name the job.</p>
213 {{else if eq .CombinedState "conflict"}}
214 <p class="conflict">This change conflicts with the latest <code>{{.Request.Base}}</code>. Resolve it on the branch and push again.</p>
215 {{end}}
216 {{if .CombinedRuns}}
217 <div class="side-list">
218 {{range .CombinedRuns}}
219 <a class="side-run" href="/r/{{$.Name}}/runs/{{.ID}}">
220 <span class="side-run-top">
221 <span class="status {{.Status}}">{{.Status}}</span>
222 <span class="side-subject">{{.Job}}</span>
223 </span>
224 <span class="side-meta"><span>{{.Workflow}}</span><span>{{if not .Started.IsZero}}{{duration .Duration}}{{else}}{{duration .Wait}} queued{{end}}</span><span>{{since .Created.Unix}}</span></span>
225 </a>
226 {{end}}
227 </div>
228 {{end}}
229 </section>
230 {{end}}
202 231 </div>
203 232 {{end}}
204 233
@@ -237,7 +266,7 @@
237 266 {{end}}
238 267 </p>
239 268 </div>
240 {{if or .CanApprove .CanClose .CanMerge .ContributorCI}}
269 {{if or .CanApprove .CanClose .CanMerge .MergeArmed .ContributorCI}}
241 270 <div class="page-head-actions">
242 271 {{with .ContributorCI}}{{if .CanAllow}}
243 272 <form method="post" action="/r/{{$.Name}}/ci/allow">
@@ -255,10 +284,15 @@
255 284 <button class="success" type="submit">{{icon "check"}}Approve</button>
256 285 </form>
257 286 {{end}}
258 {{if .CanMerge}}
287 {{if .MergeArmed}}
288 <form method="post" action="/r/{{.Name}}/requests/{{.Request.ID}}/merge/cancel">
289 <input type="hidden" name="csrf" value="{{.CSRF}}">
290 <button class="secondary" type="submit">{{icon "circle-x"}}Cancel merge</button>
291 </form>
292 {{else if .CanMerge}}
259 293 <form method="post" action="/r/{{.Name}}/requests/{{.Request.ID}}/merge">
260 294 <input type="hidden" name="csrf" value="{{.CSRF}}">
261 <button class="success" type="submit">{{icon "git-merge"}}Merge</button>
295 <button class="success" type="submit"{{if .MergeBlocked}} disabled{{end}}>{{icon "git-merge"}}{{if .MergePending}}Merge when ready{{else}}Merge{{end}}</button>
262 296 </form>
263 297 {{end}}
264 298 {{if .CanClose}}