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

forge/access/acl.go +21

@@ -327,6 +327,27 @@ func ContributorRefName(ref string) (name string, ok bool) {
327 327 return rest[:i], true
328 328 }
329 329
330 // CandidateRoot is the server-only namespace a combined result is published under.
331 // It lives here rather than in forge/landing so the runner can read the trust of a
332 // ref without importing the landing rules.
333 const CandidateRoot = "refs/vole/candidates/"
334
335 // TrustNamespace names the cache namespace a run's ref belongs to. A contributor
336 // branch and a combined result derived from one are both untrusted code, and a
337 // cache is shared mutable state: they may not seed the cache a protected branch
338 // builds into. Everything else is direct.
339 func TrustNamespace(ref string) string {
340 if name, ok := ContributorRefName(ref); ok {
341 return "contrib-" + name
342 }
343 if rest, ok := strings.CutPrefix(ref, CandidateRoot+"contrib/"); ok {
344 if i := strings.IndexByte(rest, '/'); i > 0 {
345 return "contrib-" + rest[:i]
346 }
347 }
348 return "direct"
349 }
350
330 351 // CanDiscuss covers filing issues and commenting. The Contribute role may do
331 352 // this without being able to move a shared branch.
332 353 func (a *ACL) CanDiscuss(user string) bool { return a.RoleFor(user).AtLeast(Contribute) }