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 the forge web UI

f09ef39efe44de693748053a7b596ef328fcf06b · Keenan Nemetz · 15d ago · parent 70b70264

Build out the forge web UI

Turn the web surface into a compact, server-rendered forge with HTMX as the
progressive dynamic layer.

- Split templates and assets into embedded files; add a tokenised dark theme,
  Lucide icons, and vendored HTMX.
- Add the repository Overview page and a separate chronological Activity feed
  with type filters and HTMX fragment updates.
- Finish the issue and change workflows: create pages, comments, close/reopen,
  labels and assignees, approval, discussion, line-anchored review comments,
  and HTMX list filters.
- Add syntax-highlighted blobs, contributor/statistics derivation, branch-aware
  code browsing, and a repository Runs list.
- Add a loopback-only development login for local write testing, with explicit
  configuration and listener checks.
- Extend tests for the new pages, fragments, labels, assignees, anchors, and
  development login.

server/web/templates/releases.html +84

@@ -0,0 +1,84 @@
1 {{define "releases"}}
2 {{template "header" .}}
3 {{template "repohead" (nav .Name "releases")}}
4 {{if .Tags}}
5 <table>
6 <tr><th>Tag</th><th>Notes</th><th>Tagger</th><th>Age</th><th>Source</th></tr>
7 {{range .Tags}}
8 <tr>
9 <td><a href="/r/{{$.Name}}/releases/{{.Name}}">{{.Name}}</a>{{if not .Annotated}} <span class="label">lightweight</span>{{end}}</td>
10 <td class="muted">{{.Subject}}</td>
11 <td class="muted">{{if .Tagger}}{{.Tagger}}{{else}}—{{end}}</td>
12 <td class="muted">{{since .When}}</td>
13 <td><a href="/r/{{$.Name}}/releases/{{.Name}}/archive.tar">tar</a> · <a href="/r/{{$.Name}}/releases/{{.Name}}/archive.tar.gz">tar.gz</a></td>
14 </tr>
15 {{end}}
16 </table>
17 {{else}}
18 <p class="muted">No releases yet. A release is an annotated tag, so this is the whole flow:</p>
19 <pre>git tag -a v1.0.0 -F notes.md
20 git push --follow-tags</pre>
21 {{end}}
22 {{if .Lightweight}}
23 <p class="muted">{{.Lightweight}} lightweight tag(s) are listed but carry no notes: <code>git tag -a</code>
24 records a tagger and a message, which is what makes a tag a release.</p>
25 {{end}}
26 {{template "footer" .}}
27 {{end}}
28
29 {{define "release"}}
30 {{template "header" .}}
31 {{template "repohead" (nav .Name "releases")}}
32 <h1>{{.Tag.Name}}</h1>
33 <p class="muted">
34 {{if .Tag.Annotated}}annotated tag{{else}}lightweight tag{{end}}
35 {{if .Tag.Tagger}}by {{.Tag.Tagger}}{{end}}
36 · {{since .Tag.When}}
37 · commit <a class="sha" href="/r/{{.Name}}/commit/{{.Tag.Commit}}">{{short .Tag.Commit}}</a>
38 </p>
39
40 {{if .Notes}}
41 <div class="md">{{.Notes}}</div>
42 {{else if not .Tag.Annotated}}
43 <p class="muted">A lightweight tag has no notes. Annotate it (<code>git tag -a</code>) to give this
44 release a description; the tarball below works either way.</p>
45 {{end}}
46
47 <div class="card">
48 <h2>Artifacts</h2>
49 {{if .Artifacts}}
50 <table>
51 <tr><th>File</th><th>Size</th><th>SHA-256</th><th></th></tr>
52 {{range .Artifacts}}
53 <tr>
54 <td><a href="/r/{{$.Name}}/releases/{{$.Tag.Name}}/artifacts/{{.Name}}">{{.Name}}</a></td>
55 <td class="muted">{{.Size}}</td>
56 <td class="muted"><code>{{short .OID}}</code></td>
57 <td><a href="/r/{{$.Name}}/releases/{{$.Tag.Name}}/artifacts/{{.Name}}">download</a></td>
58 </tr>
59 {{end}}
60 </table>
61 <p class="muted">Bytes live once in the instance's content-addressed store, so the same
62 file on two releases costs one copy.</p>
63 {{else}}
64 <p class="muted">No artifacts attached. Push the tag first, then:</p>
65 <pre>vole release attach {{.Tag.Name}} dist/*</pre>
66 {{end}}
67 </div>
68
69 <div class="card">
70 <h2>Source</h2>
71 <p><a href="/r/{{.Name}}/releases/{{.Tag.Name}}/archive.tar">Download .tar</a>
72 · <a href="/r/{{.Name}}/releases/{{.Tag.Name}}/archive.tar.gz">Download .tar.gz</a></p>
73 <p class="muted">Generated from the tag when you ask for it, not stored — the same bytes on
74 every request, so a cached copy cannot go stale.</p>
75 {{if .LFSPointers}}<p class="muted">This repository tracks files with Git LFS: those files appear
76 in the tarball as pointer files, not their contents. Clone with <code>git lfs</code> for the
77 real bytes.</p>{{end}}
78 </div>
79
80 <h2>{{if .Prev}}{{.Count}} commit(s) since {{.Prev}}{{else}}{{.Count}} commit(s){{end}}</h2>
81 {{template "commitlist" .}}
82 {{if .Capped}}<p class="muted">Showing the first {{.CappedAt}}; the rest are in the history.</p>{{end}}
83 {{template "footer" .}}
84 {{end}}