SPB Git

spb/spbgit

Public MIT Pinned

SPB Git — the platform hosting itself

5.7 KB

# Deploying SPB Git 2.0 to M1M32

Production is the git clone at M1M32:~/srv/spbgit/app, run by PM2 as spbgit-server (manifest M1M32:~/dispatch/apps/spbgit.json, pinned to M1M32, published through the MacLustr Tunnel as https://git.spboucher.ai). origin of that clone is spbgit itself (https://git.spboucher.ai/spbgit.git, bare repo ~/srv/git/spbgit.git on the same machine).

# 0. Pre-flight (laptop)

bash
cd ~/Desktop/Cluster/projets/spbgit
npm run lint && npm run check:headers && npm test          # 86 tests
python3 -I scripts/qa/screens.py http://127.0.0.1:7421 /tmp/qa --no-shots   # dev server on 7421
git log --oneline -3                                        # 2.0.0 commits on main
git push origin main                                        # → spbgit bare repo on M1M32

# 1. Deploy (M1M32)

bash
ssh M1M32
export PATH=/opt/homebrew/bin:$PATH
cd ~/srv/spbgit/app
git fetch origin && git status                              # must be clean, on main
cp -a ~/srv/spbgit/cache ~/srv/spbgit/cache.bak-$(date +%Y%m%d)   # optional: 2 GB, speeds up rollback
git pull --ff-only origin main
npm ci --omit=dev --no-audit --no-fund                      # @anthropic-ai/sdk, @fastify/compress added in 2.0
node scripts/fetch-fonts.mjs                                # woff2 are git-ignored
pm2 restart spbgit-server --update-env
pm2 logs spbgit-server --lines 20 --nostream

The first home request after the restart recomputes 157 overviews with the new cache shape (overview-v5.json, heatmap-v5.json, search-index-v2.json); expect ~10 s once, then ≤ 100 ms. Old overview-v4.json/heatmap-v4.json files are simply ignored (delete them with find ~/srv/spbgit/cache -name 'overview-v4.json' -delete when convenient).

  • Memory limit: the 2.0 server idles around 250–350 MB and no longer buffers blobs; keep max_memory_restart: 750M in the manifest but expect zero memory restarts. Check after 24 h: pm2 describe spbgit-server | grep restarts.
  • Log rotation: ~/.pm2/logs/spbgit-server-out.log was 599 MB. pm2 install pm2-logrotate && pm2 set pm2-logrotate:max_size 50M && pm2 set pm2-logrotate:retain 7, then pm2 flush spbgit-server once.
  • AI (optional, off by default): add to the manifest env SPBGIT_AI_PROVIDER=anthropic, SPBGIT_AI_API_KEY=… (server-side only), optionally SPBGIT_AI_MODEL (default claude-opus-5-5), SPBGIT_AI_DAILY_BUDGET_TOKENS (default 500 000). Or point at a local OpenAI-compatible server: SPBGIT_AI_PROVIDER=openai-compatible, SPBGIT_AI_BASE_URL=http://<node>:<port>/v1, SPBGIT_AI_MODEL=…. Every repository is public, so no private code is involved, but enabling a remote provider still sends repository excerpts and visitor questions to it — decide explicitly.

# 2. Verify

bash
curl -s https://git.spboucher.ai/healthz | jq .                     # version 2.0.0, features, git concurrency
curl -s -o /dev/null -w '%{http_code} %{time_total}\n' https://git.spboucher.ai/
curl -s -o /dev/null -w '%{http_code}\n' https://git.spboucher.ai/spbgit/blob/main/src/server.mjs
curl -s "https://git.spboucher.ai/api/v1/search?q=server&scope=files&limit=3" | jq .files
curl -s https://git.spboucher.ai/api/v1/stats | jq '{commits, commitsLast52Weeks}'   # commits ≥ commitsLast52Weeks
git ls-remote https://git.spboucher.ai/spbgit.git | head -2            # Smart HTTP advertisement
# from the laptop: a real clone + a push to a scratch repo with a PAT

Then the manual Safari/iPhone checklist in docs/SPBGIT-2-PROGRESS.md (Phase 7).

# 3. Rollback

bash
ssh M1M32
export PATH=/opt/homebrew/bin:$PATH
cd ~/srv/spbgit/app
git checkout 810e402            # last 1.1.0 commit (v4 "Monolith")
npm ci --omit=dev --no-audit --no-fund
pm2 restart spbgit-server --update-env

Data is untouched by 2.0 (bare repos, meta.json, activity.jsonl, clones.json, tokens.json, releases). 2.0 only adds data/ai-usage.json (when AI is enabled) and new cache file names; 1.1.0 ignores both. The 1.1.0 caches (overview-v4.json, heatmap-v4.json, search-index.json) are left in place by 2.0, so a rollback is warm immediately. Return to 2.0 with git checkout main.

# 4. What changed operationally

Item 1.1.0 2.0.0
/raw/* whole blob buffered (≤ 64 MB) streamed from git cat-file, Content-Length from cat-file -s
git subprocesses unbounded 12 concurrent (SPBGIT_GIT_CONCURRENCY)
Request logging 2 lines per request (incl. assets) 1 line per completed request, assets only on error
Compression none in-process brotli q4 / gzip 5 for text ≥ 1 KB (@fastify/compress)
Overview cache per repo, busted by hook only validated against ref stamps (HEAD, packed-refs, refs/heads, refs/tags mtimes)
New routes — /about/metrics, /:repo/insights, /:repo/research, /api/v1/search, /api/v1/repos/:name/tree, /api/v1/ai/* (404 unless enabled)
Dependencies — @anthropic-ai/sdk, @fastify/compress; dev: axe-core
Files · main
Menu

Theme