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.

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