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.

Build out change review and threaded discussions

f6f4b1db24292d1df877680714952a9c568e2b78 · Keenan Nemetz · 15d ago · parent 564acd4b

Build out change review and threaded discussions

- Add Conversation, Files and Runs tabs to change requests. Files uses the
  code-browser shape with a changed-file tree and one selected-file diff;
  Runs lists the head commit's workflow results.
- Show anchored review comments beneath the line, with a collapsed excerpt
  read from the exact blob that was reviewed, and return posted anchors to
  their line note.
- Add comment threads: any comment can be replied to, the UI flattens the
  descendants under one root, reply context links back to the parent, and
  reply targets feed a single composer at the foot of the discussion.
- Collapse reply groups while keeping the root visible, and scroll to the
  composer when Reply is selected.
- Add comment context menus with Reply, Copy text, Copy link, Edit and
  Delete. Add web edit/delete routes with author or admin checks; deletion
  leaves a tombstone so replies keep their thread.
- Support --reply-to in the issue and change CLI commands, and treat a
  missing parent as a tombstone rather than an invalid tree.
- Fix the diff comment gutter, action button colours, reply labels, and
  keep the Files tree and diff pane aligned.

Update metadata validation, web templates, CSS, JavaScript, tests, and the
CLI/change-request/issue docs.

server/web_test.go +13−3

@@ -86,14 +86,24 @@ func TestRequestPageShowsWhatWouldLand(t *testing.T) {
86 86 if code != 200 {
87 87 t.Fatalf("request page = %d", code)
88 88 }
89 for _, want := range []string{"Land the feature", "readme.md", "feature line", "why this change", `class="add"`} {
89 for _, want := range []string{"Land the feature", "why this change", "Review files"} {
90 90 if !strings.Contains(body, want) {
91 91 t.Fatalf("request page does not show %q:\n%s", want, body)
92 92 }
93 93 }
94 // The request page is the approval surface, so it must not need a clone.
94
95 code, body = f.get("/r/" + f.repo + "/requests/" + reqID + "/files")
96 if code != 200 {
97 t.Fatalf("request files page = %d", code)
98 }
99 for _, want := range []string{"readme.md", "feature line", `class="add"`, `id="review-tree"`} {
100 if !strings.Contains(body, want) {
101 t.Fatalf("request files page does not show %q:\n%s", want, body)
102 }
103 }
104 // The Files tab is the approval surface, so it must not need a clone.
95 105 if strings.Contains(body, "No changes, or the head is not reachable") {
96 t.Fatalf("request page found no diff for a branch with a change:\n%s", body)
106 t.Fatalf("request files page found no diff for a branch with a change:\n%s", body)
97 107 }
98 108 }
99 109