A CLI-first git forge.

cli forge git self-hosted

https://gitbay.org

Commit a997bedea1

a997bedea13d1e8a109271c3966bc0d0e7c0e477

parent: 768fd2e0ca

Verified · cmc ci/build: success

cmc <hello@cleberg.net> · 2026-08-31T15:29:14Z

deps: pad the issue table so the mail is legible

The body is read twice: as a rendered table on the web, and as the plain
text of the notification mail. Padding every cell to its column width is
ignored by the renderer and is the only thing keeping the mail's columns
readable, so one body serves both.

Closes #61
internal/deps/report.go +29 −2
@@ -39,10 +39,37 @@ func Body(branch string, reports []store.DepReport) string {
3939 continue
4040 }
4141 sort.Slice(rows, func(i, j int) bool { return rows[i].Name < rows[j].Name })
42 fmt.Fprintf(&b, "\n### %s\n\n| Package | Current | Latest |\n| --- | --- | --- |\n", ecosystemNames[eco])
42 fmt.Fprintf(&b, "\n### %s\n\n", ecosystemNames[eco])
43 cells := [][3]string{{"Package", "Current", "Latest"}}
4344 for _, r := range rows {
44 fmt.Fprintf(&b, "| `%s` | %s | %s |\n", r.Name, r.Current, r.Latest)
45 cells = append(cells, [3]string{"`" + r.Name + "`", r.Current, r.Latest})
4546 }
47 b.WriteString(table(cells))
48 }
49 return b.String()
50}
51
52// table pads every cell to its column, because the body is read twice: as
53// a rendered table on the web, where the padding is ignored, and as the
54// plain text of the notification mail, where it is the only thing keeping
55// the columns readable. Row 0 is the header.
56func table(cells [][3]string) string {
57 var w [3]int
58 for _, c := range cells {
59 for i := range w {
60 if n := len(c[i]); n > w[i] {
61 w[i] = n
62 }
63 }
64 }
65 var b strings.Builder
66 row := func(c [3]string) {
67 fmt.Fprintf(&b, "| %-*s | %-*s | %-*s |\n", w[0], c[0], w[1], c[1], w[2], c[2])
68 }
69 row(cells[0])
70 row([3]string{strings.Repeat("-", w[0]), strings.Repeat("-", w[1]), strings.Repeat("-", w[2])})
71 for _, c := range cells[1:] {
72 row(c)
4673 }
4774 return b.String()
4875}
internal/deps/report_test.go added +43
@@ -0,0 +1,43 @@
1package deps
2
3import (
4 "strings"
5 "testing"
6
7 "gitbay.org/gitbay/internal/store"
8)
9
10// The body is read as a rendered table on the web and as the plain text of
11// the notification mail, so every row has to line up on its own.
12func TestBodyAlignsColumns(t *testing.T) {
13 body := Body("main", []store.DepReport{
14 {Ecosystem: EcoGo, Name: "go.yaml.in/yaml/v3", Current: "v3.0.4", Latest: "v3.0.5"},
15 {Ecosystem: EcoGo, Name: "golang.org/x/net", Current: "v0.57.0", Latest: "v0.58.0"},
16 {Ecosystem: EcoNPM, Name: "react", Current: "18.2.0", Latest: "19.0.0"},
17 })
18 var pipes []int
19 for _, line := range strings.Split(body, "\n") {
20 if !strings.HasPrefix(line, "|") {
21 pipes = append(pipes, -1) // section break
22 continue
23 }
24 pipes = append(pipes, len(line))
25 }
26 // Within a run of table lines every line is the same length.
27 var run []int
28 for _, n := range append(pipes, -1) {
29 if n == -1 {
30 for _, w := range run {
31 if w != run[0] {
32 t.Fatalf("ragged table in:\n%s", body)
33 }
34 }
35 run = nil
36 continue
37 }
38 run = append(run, n)
39 }
40 if !strings.Contains(body, "| `golang.org/x/net` | v0.57.0 | v0.58.0 |") {
41 t.Errorf("row not padded to its column:\n%s", body)
42 }
43}