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/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Tighten up the issue and change review pages

564acd4b6de233740f3c19e297c4655e8952d40c · Keenan Nemetz · 15d ago · parent a464f892

Tighten up the issue and change review pages

- Move contributor-branch CI approval from the Runs tab to the change
  request header, and return the allow form to that request.
- Put issue and change actions in the page header, right aligned with the
  title, instead of duplicating them in the sidebar.
- Drop sidebar details that repeated the header: state, author, age and
  reference. Keep labels, assignees, review base/head, approvals and checks.
- Consolidate approval status into one section and remove the empty-state
  line now covered by the count.
- Fix diff row spacing: keep pre-wrap on the code column only, so template
  whitespace in the gutter cells no longer creates blank lines.

Update the contributor CI test, the HTMX fragment expectations and the
documentation that named the Runs tab as the approval location.

server/web/requests.go +62−13

@@ -199,6 +199,14 @@ type requestCheck struct {
199 199 Exit int
200 200 }
201 201
202 // requestCI is the approval a contributor branch needs before its workflow may
203 // run. It belongs on the request because that is where a maintainer reviews the
204 // code the tip contains.
205 type requestCI struct {
206 Ref string
207 CanAllow bool
208 }
209
202 210 type requestCommentView struct {
203 211 metadata.Comment
204 212 Body template.HTML
@@ -213,17 +221,17 @@ type requestCommentView struct {
213 221 // refresh the whole sidebar without rebuilding the rest of the review.
214 222 type requestSidebarView struct {
215 223 Page
216 Name string
217 Request *metadata.Request
218 Approvals []requestApproval
219 Checks []requestCheck
220 Required int
221 Current int
222 CanApprove bool
223 CanClose bool
224 CanDiscuss bool
225 CommentCount int
226 Error string
224 Name string
225 Request *metadata.Request
226 Approvals []requestApproval
227 Checks []requestCheck
228 Required int
229 Current int
230 CanApprove bool
231 CanClose bool
232 CanDiscuss bool
233 ContributorCI *requestCI
234 Error string
227 235 }
228 236
229 237 type commentTarget struct {
@@ -289,13 +297,54 @@ func (w *Web) requestSidebar(r *http.Request, m *repo.Meta, req *metadata.Reques
289 297 if pr := w.principal(r); pr != nil && acl != nil {
290 298 canClose = acl.CanTriage(pr.account.ID) || req.AuthorID == pr.account.ID
291 299 }
300 var contributorCI *requestCI
301 if req.Open() {
302 if ref := w.pendingContributorCI(m, req.Head); ref != "" {
303 canAllow := false
304 if id := w.accountID(r); id != "" && acl != nil && acl.CanApprove(id) {
305 canAllow = true
306 }
307 contributorCI = &requestCI{Ref: strings.TrimPrefix(ref, "refs/heads/"), CanAllow: canAllow}
308 }
309 }
292 310 return requestSidebarView{
293 311 Page: w.page(r, title), Name: m.Name, Request: req,
294 312 Approvals: approvals, Checks: checks, Required: required, Current: current,
295 313 CanApprove: canApprove, CanClose: canClose,
296 CanDiscuss: acl != nil && w.canDiscuss(r, acl),
297 CommentCount: len(req.Comments), Error: errMsg,
314 CanDiscuss: acl != nil && w.canDiscuss(r, acl),
315 ContributorCI: contributorCI,
316 Error: errMsg,
317 }
318 }
319
320 // pendingContributorCI finds the contributor branch whose tip is head and whose
321 // CI still waits for a maintainer. It is keyed by the commit: a branch that has
322 // moved past this request is not what is under review here.
323 func (w *Web) pendingContributorCI(m *repo.Meta, head string) string {
324 if w.Runs == nil || head == "" {
325 return ""
326 }
327 refs, err := m.Git().ListRefs("refs/heads/")
328 if err != nil {
329 return ""
330 }
331 var candidates []string
332 for ref, tip := range refs {
333 if tip != head {
334 continue
335 }
336 if _, ok := access.ContributorRefName(ref); ok {
337 candidates = append(candidates, ref)
338 }
339 }
340 sort.Strings(candidates)
341 for _, ref := range candidates {
342 allowed, err := w.Runs.CIAllowed(m.Name, ref, head)
343 if err == nil && !allowed {
344 return ref
345 }
298 346 }
347 return ""
299 348 }
300 349
301 350 func (w *Web) requestComments(m *repo.Meta, req *metadata.Request) []requestCommentView {