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.
Phase 5: LFS objects, over SSH for writes and the proxy for reads
64ac5071a173e4e9ce8bc8d7170f9b0411bee52a · Keenan Nemetz · 17d ago · parent 35eaeccf
Phase 5: LFS objects, over SSH for writes and the proxy for reads Large files leave the git object database and land in one content-addressed store per instance. Reads are anonymous like clone; writes ride the SSH key that already authenticates the push, so no token exists anywhere. - internal/lfs: sha256-addressed store that verifies content and size before an object becomes visible; parser for the pointer format a client writes - HTTP: POST .../info/lfs/objects/batch for downloads, GET .../objects/<oid> with the object id as ETag; upload over HTTP is refused and names SSH - SSH: git-lfs-transfer speaking the pure SSH protocol (pkt-line), so `git lfs push` needs nothing but the key at the handshake - pre-receive: a pointer whose object is missing, or whose size disagrees with the stored object, fails the push that introduced it; a binary over lfs_warn_bytes is accepted with a `git lfs track` suggestion. Checks run before the protected-branch gate, because an admin's approval bypass is about review, not about whether the commit can be checked out - runs: a finished log becomes a content-addressed object in the same write that records the status, served at /r/<repo>/runs/<id>/log - vole gc [--dry-run] [--grace]: marks pointer targets from every ref in every repository plus archived logs, sweeps the rest. Mark-and-sweep rather than reference counts: a counter that is one too low deletes an artifact, a walk over the refs cannot be wrong about what is reachable
internal/server/integration_test.go +22−7
| @@ -1772,10 +1772,14 @@ jobs: | |||
| 1772 | 1772 | ||
| 1773 | 1773 | done := f.waitForRun(t, 10*time.Second, func(r *runs.Run) bool { return r.Status != runs.StatusQueued && r.Status != runs.StatusRunning }) | |
| 1774 | 1774 | if done.Status != runs.StatusSuccess { | |
| 1775 | t.Fatalf("run status = %s (exit %d), log:\n%s", done.Status, done.ExitCode, done.Log) | ||
| 1775 | t.Fatalf("run status = %s (exit %d)", done.Status, done.ExitCode) | ||
| 1776 | 1776 | } | |
| 1777 | if !strings.Contains(done.Log, "hello from the runner") { | ||
| 1778 | t.Fatalf("log does not contain the step output:\n%s", done.Log) | ||
| 1777 | // The log left the queue as a content-addressed object, and the web serves it. | ||
| 1778 | if done.LogOID == "" { | ||
| 1779 | t.Fatalf("finished run has no archived log: %+v", done) | ||
| 1780 | } | ||
| 1781 | if code, body := f.get("/r/" + f.repo + "/runs/" + done.ID + "/log"); code != 200 || !strings.Contains(body, "hello from the runner") { | ||
| 1782 | t.Fatalf("run log page = %d, body:\n%s", code, body) | ||
| 1779 | 1783 | } | |
| 1780 | 1784 | if done.SHA != mustSHA(t, work) { | |
| 1781 | 1785 | t.Fatalf("run recorded sha %s, want the pushed commit", done.SHA) | |
| @@ -1889,11 +1893,22 @@ jobs: | |||
| 1889 | 1893 | second := f.waitForRun(t, 30*time.Second, func(r *runs.Run) bool { | |
| 1890 | 1894 | return r.SHA == secondSHA && r.Status != runs.StatusQueued && r.Status != runs.StatusRunning | |
| 1891 | 1895 | }) | |
| 1892 | if !strings.Contains(first.Log, "first-version") || strings.Contains(first.Log, "second-version") { | ||
| 1893 | t.Fatalf("the run queued from v1 executed something else:\n%s", first.Log) | ||
| 1896 | // Logs are content-addressed objects once a run finishes, so read them the | ||
| 1897 | // way the web does rather than from the queue row. | ||
| 1898 | logOf := func(r *runs.Run) string { | ||
| 1899 | t.Helper() | ||
| 1900 | code, body := f.get("/r/" + f.repo + "/runs/" + r.ID + "/log") | ||
| 1901 | if code != 200 { | ||
| 1902 | t.Fatalf("log of run %s = %d", r.ID, code) | ||
| 1903 | } | ||
| 1904 | return body | ||
| 1905 | } | ||
| 1906 | firstLog, secondLog := logOf(first), logOf(second) | ||
| 1907 | if !strings.Contains(firstLog, "first-version") || strings.Contains(firstLog, "second-version") { | ||
| 1908 | t.Fatalf("the run queued from v1 executed something else:\n%s", firstLog) | ||
| 1894 | 1909 | } | |
| 1895 | if !strings.Contains(second.Log, "second-version") { | ||
| 1896 | t.Fatalf("the run queued from v2 did not use its own workflow:\n%s", second.Log) | ||
| 1910 | if !strings.Contains(secondLog, "second-version") { | ||
| 1911 | t.Fatalf("the run queued from v2 did not use its own workflow:\n%s", secondLog) | ||
| 1897 | 1912 | } | |
| 1898 | 1913 | } | |
| 1899 | 1914 | ||