SPB Git

Repository Public MIT Selected

DEPLOY.md 8.7 KB 147 lines markdown

1<!--2  ─────────────────────────────────────────────3   SPB Git — Personal Git Platform4  ─────────────────────────────────────────────5   Author  : Simon-Pierre Boucher6   Contact : contact@spboucher.ai7   File    : docs/DEPLOY.md8   Purpose : SPB Git 3.0 — deployment on M1M32 (MacLustr gateway), rollback, verification9   License : MIT © Simon-Pierre Boucher10  ─────────────────────────────────────────────11-->12# Deploying SPB Git to M1M32 (3.0 "Monograph")1314Production is the git clone at `M1M32:~/srv/spbgit/app`, run by PM2 as15`spbgit-server` (manifest `M1M32:~/dispatch/apps/spbgit.json`, pinned to16M1M32, published through the MacLustr Tunnel as https://git.spboucher.ai).17`origin` of that clone is spbgit itself (`https://git.spboucher.ai/spbgit.git`,18bare repo `~/srv/git/spbgit.git` on the same machine).1920## 0. Pre-flight (laptop)2122```bash23cd ~/Desktop/Cluster/projets/spbgit24npm run lint && npm run check:headers && npm test          # 89 tests25python3 -I scripts/qa/screens.py http://127.0.0.1:7421 /tmp/qa --no-shots   # dev server on 7421 → OK — 0 failing26python3 -I scripts/qa/axe.py http://127.0.0.1:7421                          # → OK — 0 violation groups27git log --oneline -3                                        # 3.0.0 commit on main28git push origin main                                        # → spbgit bare repo on M1M3229```3031## 1. Deploy (M1M32)3233```bash34ssh M1M3235export PATH=/opt/homebrew/bin:$PATH36cd ~/srv/spbgit/app37git fetch origin && git status                              # must be clean, on main38cp -a ~/srv/spbgit/cache ~/srv/spbgit/cache.bak-$(date +%Y%m%d)   # optional: 2 GB, speeds up rollback39git pull --ff-only origin main40npm ci --omit=dev --no-audit --no-fund                      # no dependency change in 3.041node scripts/fetch-fonts.mjs                                # fonts are tracked in git since 3.0: must print "fonts: 13/13 present"42pm2 restart spbgit-server --update-env43pm2 logs spbgit-server --lines 20 --nostream44```45463.0 changes markup, not data: overviews and the search index are reused. The47calendar (`heatmap-v6.json`) is rebuilt on the first home request (a few48seconds once), and READMEs, highlighted blobs, diffs, insights, OG cards and49favicons are re-rendered lazily under new cache names (`readme-v3`, `md-v3`,50`hl-v3`, `commit-v4`, `insights-v2`, `og-v3`, `favicon-v3-*`). The 2.0 cache51files stay in place (a rollback is warm). (2.0 note: the first home request recomputed the overviews with the52cache shape `overview-v5.json`, `search-index-v2.json`; ~10 s once.) Old `overview-v4.json`/`heatmap-v4.json`53files are simply ignored (delete them with54`find ~/srv/spbgit/cache -name 'overview-v4.json' -delete` when convenient).5556### Recommended at the same time (operational, reversible)5758- **Memory limit**: the 2.0 server idles around 250–350 MB and no longer59  buffers blobs; keep `max_memory_restart: 750M` in the manifest but expect60  zero memory restarts. Check after 24 h: `pm2 describe spbgit-server | grep restarts`.61- **Log rotation**: `~/.pm2/logs/spbgit-server-out.log` was 599 MB.62  `pm2 install pm2-logrotate && pm2 set pm2-logrotate:max_size 50M && pm2 set pm2-logrotate:retain 7`,63  then `pm2 flush spbgit-server` once.64- **AI (optional, off by default)**: add to the manifest env65  `SPBGIT_AI_PROVIDER=anthropic`, `SPBGIT_AI_API_KEY=…` (server-side only),66  optionally `SPBGIT_AI_MODEL` (default `claude-opus-5-5`),67  `SPBGIT_AI_DAILY_BUDGET_TOKENS` (default 500 000). Or point at a local68  OpenAI-compatible server: `SPBGIT_AI_PROVIDER=openai-compatible`,69  `SPBGIT_AI_BASE_URL=http://<node>:<port>/v1`, `SPBGIT_AI_MODEL=…`.70  Every repository is public, so no private code is involved, but enabling a71  remote provider still sends repository excerpts and visitor questions to it —72  decide explicitly.7374## 2. Verify7576```bash77curl -s https://git.spboucher.ai/healthz | jq .                     # version 3.0.0, features, git concurrency78# (`cache` is null until the background footprint walk has finished; `cacheComputedAt` gives its age)79curl -s -o /dev/null -w '%{http_code} %{time_total}\n' https://git.spboucher.ai/80curl -s -o /dev/null -w '%{http_code}\n' https://git.spboucher.ai/spbgit/blob/main/src/server.mjs81curl -s "https://git.spboucher.ai/api/v1/search?q=server&scope=files&limit=3" | jq .files82curl -s https://git.spboucher.ai/api/v1/stats | jq '{commits, commitsLast52Weeks}'   # commits ≥ commitsLast52Weeks83git ls-remote https://git.spboucher.ai/spbgit.git | head -2            # Smart HTTP advertisement84# from the laptop: a real clone + a push to a scratch repo with a PAT85```8687Then the manual Safari/iPhone checklist in `docs/SPBGIT-2-PROGRESS.md` (Phase 7).8889## 3. Rollback9091```bash92ssh M1M3293export PATH=/opt/homebrew/bin:$PATH94cd ~/srv/spbgit/app95git checkout 7864e4d            # last 2.0.0 commit (use 810e402 for 1.1.0, v4 "Monolith")96node scripts/fetch-fonts.mjs    # 2.0 fonts were git-ignored downloads: fetch them again97npm ci --omit=dev --no-audit --no-fund98pm2 restart spbgit-server --update-env99```100101Data is untouched by 2.0 (bare repos, `meta.json`, `activity.jsonl`,102`clones.json`, `tokens.json`, releases). 2.0 only *adds* `data/ai-usage.json`103(when AI is enabled) and new cache file names; 1.1.0 ignores both. The 1.1.0104caches (`overview-v4.json`, `heatmap-v4.json`, `search-index.json`) are left in105place by 2.0, so a rollback is warm immediately. Return to the current release with106`git checkout main`. 3.0 adds no data file at all: it only writes new cache names.107108## 4. What changed operationally109110| Item | 1.1.0 | 2.0.0 |111|---|---|---|112| `/raw/*` | whole blob buffered (≤ 64 MB) | streamed from `git cat-file`, `Content-Length` from `cat-file -s` |113| git subprocesses | unbounded | 12 concurrent (`SPBGIT_GIT_CONCURRENCY`) |114| Request logging | 2 lines per request (incl. assets) | 1 line per completed request, assets only on error |115| Compression | none in-process | brotli q4 / gzip 5 for text ≥ 1 KB (`@fastify/compress`) |116| Overview cache | per repo, busted by hook only | validated against ref stamps (HEAD, packed-refs, refs/heads, refs/tags mtimes) |117| New routes | — | `/about/metrics`, `/:repo/insights`, `/:repo/research`, `/api/v1/search`, `/api/v1/repos/:name/tree`, `/api/v1/ai/*` (404 unless enabled) |118| Dependencies | — | `@anthropic-ai/sdk`, `@fastify/compress`; dev: `axe-core` |119120## 5. Deployment record — 3.0.0 "Monograph" (2026-11-09)121122- Commits `c462ed4` (redesign) and `23a33be` (`/healthz` fix) pushed to spbgit, pulled on M1M32,123  `node scripts/fetch-fonts.mjs` → `fonts: 13/13 present`, `pm2 restart spbgit-server --update-env`.124  `npm ci` was skipped on purpose: the lock file differs from 2.0.0 by the version field only.125- Verified on https://git.spboucher.ai: `/healthz` (version 3.0.0, 183 repositories, answers in 2 ms),126  home, `/spbgit`, `/wp16_uqo`, `/wp9_uqo`, a blob, a commit diff, `/about/api`, `/about/metrics`,127  the ⌘K palette, at 1440 px and 390 px, light and dark (`docs/screenshots/v3/prod-*.png`);128  security headers and CSP unchanged; `git ls-remote` answers.129- The nine font files downloaded by 2.0 (`inter-400.woff2` … `jetbrains-mono-600.woff2`) are still in130  `src/web/assets/fonts/` on M1M32 as untracked files, so a rollback to 2.0 is immediate. Delete them131  once a rollback is no longer wanted.132- Rate limit reminder when checking by script: 200 requests per minute per IP, static assets and README133  images included — four loads of a badge-heavy README inside a minute return 429.134135### Known production issues that predate 3.0 (not addressed by the redesign)136137- **Memory restart loop.** Since at least 2026-11-08, PM2 restarts `spbgit-server` 10–30 times per hour138  because RSS passes `max_memory_restart` (750 MB) within one to three minutes of each start (RSS up to139  2 GB with a heap under 100 MB). The traffic at those moments is two crawlers walking every blob, tree140  and commit URL at historical SHAs (about 10 requests per second). 3.0 neither causes nor fixes it.141- **Cache growth.** `~/srv/spbgit/cache` weighs 75 GB (83 GB free on the volume), almost entirely142  per-SHA `hl-v2-*` highlight files produced by the same crawl; 3.0 writes `hl-v3-*` beside them.143  Once a rollback is ruled out, the 2.0 files can be removed:144  `find ~/srv/spbgit/cache/repos \( -name 'hl-v2-*' -o -name 'md-v2-*' -o -name 'commit-v3.json' -o -name 'readme-v2.json' -o -name 'insights-v1.json' \) -delete`.145  A lasting answer needs a policy for crawlers on SHA-pinned URLs (robots rules, a tighter rate limit,146  or not caching highlight output for non-branch refs) — an operational decision left to the owner.147
Files main
Menu

Theme