Skip to content

Latest commit

 

History

History
140 lines (115 loc) · 9.28 KB

AGENTS.md

File metadata and controls

140 lines (115 loc) · 9.28 KB

Repository guidelines

objgitd is a single-binary git server. It stores repositories as objects in a Tigris bucket, and not on a local filesystem.

Module path: github.com/tigrisdata/objgit. Go 1.26.

Transports

One backend answers three transports:

Transport Flag Default Notes
Smart HTTP -http-bind :8080 The primary transport. Carries HTTP Basic.
git:// -git-bind :9418 Unauthenticated TCP. Opt-in.
SSH -ssh-bind off Public-key. Opt-in. Host key lives in the bucket.

All three funnel authorization through one pluggable internal/auth.Authorizer.

Git LFS rides on the Smart HTTP listener, behind -allow-lfs. It is HTTP even for an ssh:// remote: SSH only answers git-lfs-authenticate, which names the HTTP endpoint. See docs/architecture/lfs.md.

A fourth listener serves Prometheus metrics at /metrics and a /healthz probe endpoint (-metrics-bind, default :9090). An empty value disables it.

Commands

go build ./...                  # build everything
go build -o objgitd ./cmd/objgitd
go test ./...                   # full test suite
go test ./cmd/objgitd/...       # protocol tests
go test -run TestSmartHTTP ./cmd/objgitd/...
go test -run TestSSH ./cmd/objgitd/...

# Run locally.
./objgitd -bucket $BUCKET -http-bind :8080 -allow-push
./objgitd -bucket $BUCKET -ssh-bind :2222 -allow-push   # git clone ssh://git@host:2222/repo.git

Notes on the tests and on configuration:

  • Protocol tests need git on PATH. They skip themselves without it.
  • SSH tests also need ssh and ssh-keygen on PATH. They skip themselves without them.
  • Flags can also come from the environment through flagenv, which maps each flag to UPPER_SNAKE. -allow-push becomes ALLOW_PUSH, and -bucket becomes BUCKET.
  • godotenv loads a .env file from the working directory at startup.
  • The .wasm files in bin/ are Git LFS objects. Run git lfs pull before you build. Without them, TestRepoBin fails. The image copies bin/ to /usr/libexec/objgit/bin. For a local run with hooks, set WASM_PATH=./bin.
  • TestCluster in internal/kube needs a real cluster. It skips itself without the OBJGIT_TEST_KUBE_* variables.
  • Tigris client credentials come from the standard AWS SDK chain, such as AWS_PROFILE.

Where the code lives

Path Purpose
cmd/objgitd/main.go Builds the one *daemon and starts every listener.
cmd/objgitd/git_protocol.go The git:// server. Also holds operationFor and (*daemon).authorize.
cmd/objgitd/http.go Smart HTTP. *daemon is the http.Handler itself.
cmd/objgitd/ssh.go The SSH server and its per-session dispatch.
cmd/objgitd/shell.go The SSH sh command: an interactive shell in the hook sandbox.
cmd/objgitd/receivepack.go The go-git fork that streams hook output, plus writePack.
cmd/objgitd/hooks.go Ref diffing and the sandboxed hook run.
cmd/objgitd/snapshots.go The erofs snapshot run after a push.
cmd/objgitd/lfs.go The Git LFS HTTP handlers and git-lfs-authenticate over SSH.
internal/auth The one authorization interface.
internal/kube The in-cluster API client, kube:apply, and tekton:pipelinerun.
internal/wasmbin Runs the WASI programs in -wasm-path, such as kustomize, as hook commands.
internal/lfs Git LFS: protocol types, the bucket store, and the presigner.
internal/repofs Maps a repository path to a storage.Storer.
internal/storage/tigris Repository storage. A storage.Storer on the bucket.
internal/bundler The async upload queue behind that storer.
internal/s3fs Daemon-level state only, which is the SSH host key.
internal/mountfs, internal/treefs, internal/kefkash The hook sandbox filesystem and shell wiring.
internal/metrics Every Prometheus vector, plus thin helpers.
internal/gittest Isolate, which keeps the real git client in tests away from this repository.
internal/snapshot erofs images of git trees: Ensure, Open, and the Store interface.
internal/slog.go JSON handler init.
bin/ WASI programs for hooks (Git LFS). The image copies them to /usr/libexec/objgit/bin.
cmd/membench/ Push memory benchmark harness. Not shipped; see docs/usage/memory-benchmark.md.

Architecture

Read docs/architecture/README.md first. It describes the daemon and links to one page for each subsystem.

Page Read it before you change...
transports.md Any transport. It holds two protocol points that are easy to get wrong.
auth.md Credentials, decisions, or a new Authorizer.
hooks.md Push hooks, output streaming, the sandbox, or its Kubernetes commands.
metrics.md Any metric or instrumentation seam.
snapshots.md Snapshot images, the snapshot cache, or runSnapshots.
tigris-storer.md Object layout, refs, packs, the pack cache, or the upload path.
s3fs.md The billy.Filesystem over the bucket.
lfs.md Git LFS: the batch API, presigned transfers, locks, or the blob layout.

Two more directories carry detail:

  • docs/reference/ — the .cue binary layout, the failure modes, and the build order.
  • docs/usage/ — how to use a feature, such as a hook script, or the push memory benchmark.

Conventions

  • Flags use kebab-case, paired with flagenv for the environment fallback.
  • slog uses "err" as the error key, and never "error".
  • Errgroup owns the server lifecycle. signal.NotifyContext provides cancellation. HTTP shutdown uses a 10s context.WithTimeout.
  • Tests are table-driven with tt. Gate a test with exec.LookPath("git") when it shells out to a real git client. See http_test.go and git_protocol_test.go.
  • Reuse the shared test helpers runGit, tryGit, and seedRepo. They live in git_protocol_test.go.
  • If a package runs the real git client in its tests, call gittest.Isolate from its TestMain. The husky commit-msg hook runs go test, and git exports GIT_DIR to hooks. Without Isolate, a test can write to the config that all worktrees share and set core.bare = true.
  • Put a plan for non-trivial work in docs/plans/. git-http-protocol.md shows the style.
  • Put architecture notes in docs/architecture/, and not in this file. Keep this file an index.

Tigris and object storage

When you work with Tigris buckets, access keys, or IAM, use the tigris-storage skills.

Tigris is S3-compatible. The client here is github.com/tigrisdata/storage-go, which is a thin Tigris-aware wrapper.