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.

Phase 5: LFS objects, over SSH for writes and the proxy for reads

64ac5071a173e4e9ce8bc8d7170f9b0411bee52a · Keenan Nemetz · 18d 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/config/config.go +20

@@ -21,6 +21,11 @@ type Config struct {
21 21 // ReceiveMaxBytes caps a whole push, enforced by git's own
22 22 // receive.maxInputSize in each repo rather than by buffering in the proxy.
23 23 ReceiveMaxBytes int64 `toml:"receive_max_bytes"`
24 // LFSObjectMaxBytes caps a single LFS object.
25 LFSObjectMaxBytes int64 `toml:"lfs_object_max_bytes"`
26 // LFSWarnBytes makes a push that commits a binary larger than this carry a
27 // suggestion to track it with git-lfs. Zero disables the warning.
28 LFSWarnBytes int64 `toml:"lfs_warn_bytes"`
24 29 // LeaseSeconds is how long a runner may hold a job without a heartbeat before
25 30 // the job is handed to somebody else.
26 31 LeaseSeconds int `toml:"lease_seconds"`
@@ -35,6 +40,9 @@ func defaults() *Config {
35 40 SSHAddr: "127.0.0.1:2222",
36 41 MaxBlobBytes: 100 << 20, // 100 MiB per blob
37 42 ReceiveMaxBytes: 1 << 30, // 1 GiB per push
43
44 LFSObjectMaxBytes: 2 << 30, // 2 GiB per LFS object
45 LFSWarnBytes: 5 << 20, // flag binaries over 5 MiB that are not in LFS
38 46 }
39 47 }
40 48
@@ -72,6 +80,10 @@ func (c *Config) RunsDB() string { return filepath.Join(c.DataDir, "runs.db") }
72 80 // SpoolDir receives accepted push events from post-receive hooks.
73 81 func (c *Config) SpoolDir() string { return filepath.Join(c.DataDir, "queue", "spool") }
74 82
83 // LFSDir is the instance-wide content-addressed store. Objects are shared by
84 // every repository: the same artifact pushed twice costs one copy.
85 func (c *Config) LFSDir() string { return filepath.Join(c.DataDir, "lfs") }
86
75 87 // Lease returns how long a runner may hold a job without a heartbeat.
76 88 func (c *Config) Lease() time.Duration {
77 89 if c.LeaseSeconds <= 0 {
@@ -97,6 +109,14 @@ ssh_addr = "127.0.0.1:2222"
97 109 # git-lfs instead.
98 110 max_blob_bytes = 104857600
99 111
112 # LFS objects live in a content-addressed store shared by every repository.
113 # This caps one object; anything larger is refused rather than spooled.
114 lfs_object_max_bytes = 2147483648
115
116 # A push that commits a binary bigger than this, and is not already an LFS
117 # pointer, gets a warning naming the git lfs track command. Zero disables it.
118 lfs_warn_bytes = 5242880
119
100 120 # Cap a whole push. Enforced by git's receive.maxInputSize in each repo, because
101 121 # receive-pack indexes a pack in memory and a large push costs its own size in
102 122 # RSS.