~bigbes/sr-ht-compare

1a83202b — bigbes 9 days ago
deps: sr-ht-ecore with the web-tier packages

Brings in assets, pages, csrf, middleware and ecoretest, plus the
chrome that grew Service.Assets — the slot three services had each
added a field of their own for.
3e79c6de — bigbes 9 days ago
web: draw the chrome from sr-ht-ecore

The nav/service-switcher, the brand, the login block and the environment
banner were a copy of code every custom service on this instance carries.
The copies drifted, so they now come from one place:
sourcecraft.dev/bigbes/sr-ht-ecore/chrome.

web/chrome.go is gone. New builds one chrome.Service from the shared
config.ini and hands it the discovered stylesheet; view() asks it for a
chrome.Page per request, which viewData embeds rather than copies, so a
field ecore adds later arrives here without an edit. The layout invokes
"srht-env-banner" and "srht-nav" instead of the markup it used to spell
out, the landing's repository listing goes through "srht-repo-list", and
the FuncMap starts from chrome.Funcs() with the local shortsha deleted.

Two ecore policies differ from what this service did and are adopted as
the instance's: the brand label is the config section's short name rather
than a literal "compare", and the origins are trimmed of a trailing
slash. What stays local is what is compare's alone: the bundle href, the
diff-status colours, and the container-fluid the two diff views ask for.

Tests move to testify; the nav ordering/exclusion test goes with the code
it tested, and a test that the layout invokes the chrome at all replaces
it.
04b591cd — bigbes 11 days ago
web: git.sr.ht-style dashboard and unified nav brand

Adopt the family look the dolt service already has. The nav brand
becomes circle icon + site name + red service label (dropping the
hub-origin variant), matching every other service on the instance. The
logged-in index turns into the two-column dashboard: a sidebar with the
service blurb and the jump form, and the repositories as shared-theme
event-list cards — name, visibility as small muted text (non-public
only, lowercase), description underneath. The big in-page h2 lives on
only for anonymous visitors, where the nav has no user context yet.
981e4f75 — bigbes 13 days ago
fix(apk): keep -modcacherw when overriding GOFLAGS

The GOFLAGS="-trimpath" passed to make clobbers abuild's default
GOFLAGS, dropping -modcacherw: the module cache then extracts read-only
and the CI cache tarball made from it fails to unpack on the next build
(mkdir into 0555 dirs, permission denied — warm build #266). The
poisoned gomod tarball was deleted by ad-hoc job #268.
2ce47ce9 — bigbes 13 days ago
ci: cache Go module and build dirs via cacher

Same scheme as sr-ht-dolt (dbd8638 there): restore ~/go/pkg/mod and
~/.cache/go-build from the Garage docker-cache bucket before abuild and
seed them back after, keyed by go.sum via cacher (go.bigb.es/cacher).
GOCACHE/GOMODCACHE are re-pinned inside build() because abuild redirects
them into its throwaway $tmpdir and an upstream typo in abuild.in
clobbers any pre-set GOMODCACHE with GOCACHE's value.
f41a0465 — bigbes 13 days ago
ci: commit the apk build, packaging and mirror-trigger files

These three were written but never committed, so the whole publishing chain
was dead from its first link: with no .build.yml on sourcecraft there is none
on the git.srht.bigb.es mirror either, so the push hook has no manifest to
submit, no build ever ran, and compare.sr.ht has never appeared in the apk
index at repo.bigb.es — which today holds spec.sr.ht alone.

The code itself was mirroring fine, which is what made this hard to see: the
sourcehut side sits on the current commit, so everything looks configured
until you ask git which of these files it actually knows about.

.sourcecraft/webhooks.yaml is in the same state and has the same consequence
one level up: the gitsync webhook was never registered, so the mirror has been
riding its hourly safety-net poll rather than updating on push.

The build secret apk-ci-s3 the publish task needs now exists on the account,
so nothing else blocks the first build.
3382707e — bigbes 28 days ago
web: add long-line wrapping toggle
cf3b7f28 — bigbes 30 days ago
web: hide the per-row diff scrollbar gutter (overlay style)

Each @pierre/diffs code row scrolls horizontally on its own
(overflow-x: scroll) and reserves a classic scrollbar track sized to the
measured --diffs-scrollbar-gutter. On platforms with non-overlay
scrollbars (e.g. macOS "always show"), that track shows as a grey strip
under any row with a long line, reading as leftover bottom padding.

Set --diffs-scrollbar-gutter-override: 0 on #diff-root so the track is
never reserved; long lines stay scrollable by trackpad / wheel. Verified
the override wins over a simulated 14px measured gutter (reserved height
stays 0).

Re-hashed the embedded stylesheet.
44cc9550 — bigbes 30 days ago
web: remove grey padding bands inside each diff file

Two sources put a grey strip above the first line and below the last,
inside the file border:

- The shared `base` partial's `section { padding-bottom: .5rem }` applied
  to .diff-file (it is a <section>). Cancel it with padding-bottom: 0.
- The @pierre/diffs vertical code padding (--diffs-gap-block, default 8px)
  above the first and below the last line. Set it to 0 on #diff-root; it
  inherits into the DIFFS-CONTAINER shadow DOM. Horizontal code padding
  (--diffs-gap-inline) is left on its default.

Re-hashed the embedded stylesheet.
9df88758 — bigbes 30 days ago
web: tighten diff and file-tree spacing

Address three spacing complaints in the compare view:

- File tree: switch @pierre/trees to the "compact" density preset (24px
  rows, 0.8 factor) so folder/child rows read as a dense index rather
  than an airy list.
- Diff blocks: drop the inter-file gap (.diff-file margin-bottom
  1rem -> .5rem) and the tree/diff column gap (1rem -> .75rem).
- File tree height: size the mount to its content height (capped at the
  viewport) instead of always filling the viewport, removing the band of
  empty tree background below the last file. Re-measures on resize and on
  every tree change (expand/collapse) via tree.subscribe.

Rebuilt and re-hashed the embedded bundle and stylesheet.
5ca23c05 — bigbes 30 days ago
web: content-hash the bundle and colour the status column

Two diff-view fixes reported against the deployed instance.

Empty file tree after an upgrade: bundle.js had a stable filename served with a
1-hour cache, so browsers kept a pre-fix bundle and the @pierre/trees sidebar
rendered blank. Content-hash the bundle like the stylesheet — Makefile emits
bundle.<sha256[:8]>.js, server.go globs it into a BundleHref, the templates
reference {{.BundleHref}}, and the hashed name is served immutable. A deploy now
always busts the cache.

Unreadable status column: the changed-files table rendered A/M/D in the dim
default cell colour, near-invisible on the dark chrome. Render each status as a
semantic .diff-status badge (added=green, modified=amber, deleted=red,
renamed=blue) with light/dark variants, via statusClass/statusLabel helpers and
a small self-contained style block (the sourcehut-derived main.min.css can't be
rebuilt locally).

Tests resolve the hashed bundle via a bundleName helper and assert its immutable
cache header; docs updated for the hashed filename.
53d7b970 — bigbes 30 days ago
docs: note that static assets are embedded and need a rebuild

web/static is //go:embed-ed into the binary, so `make css`/`make bundle` alone
don't reach the running daemon — re-run `make build` after either. Documents the
stale-asset gotcha in the build section.
4a741216 — bigbes 30 days ago
docs: spec for inline code comments on diffs

Draft proposal for line-anchored comment threads on the commit and compare
pages. Records the key finding that storage is already available through
sr-ht-core (Postgres via the database package + connection-string), that the
service is stateless by choice rather than by limitation, and that @pierre/diffs
already provides the thread UI primitives (DiffLineAnnotation + renderAnnotation
+ onDiffLineClick). Covers the anchoring model, schema, authz reuse, HTTP API,
frontend wiring, config, and a commit-first phasing.
4e7c6329 — bigbes 30 days ago
web: full-width split diff view with a rendered file tree

Make the commit and compare pages full-bleed and default to the side-by-side
(split) diff, so the layout matches a conventional diff viewer: file tree on
the left, split diff on the right.

- layout.html renders the content wrapper with a per-page ContainerClass;
  chrome() defaults it to "container" and the commit/compare handlers set
  "container-fluid" for the diff views (the nav stays centered).
- app.ts defaults DEFAULT_LAYOUT to "split".
- Fix the @pierre/trees sidebar rendering blank: its virtualized container
  collapses to zero height unless the mount has a definite height, so
  sizeTreeRoot() gives #tree-root a viewport-height panel (re-applied on
  resize). Rebuilt the vendored bundle.
a4853d05 — Eugene Blikh 30 days ago
rename module to sourcecraft.dev/bigbes/sr-ht-compare; depend on sourcecraft sr-ht-core
c1ae0fc5 — bigbes a month ago
go.mod: tidy and complete the README

go mod tidy promotes fernet-go and vaughan0/go-ini from indirect to
direct (the cmd entry point imports go-ini and the smoke test imports
fernet) and drops stale transitive checksums for AWS S3/CLI packages that
core-go pulls but compare.sr.ht never imports. The require block is
otherwise unchanged; build and tests stay green.

README: correct the architecture to reflect the go-git in-process backend
(no runtime git shell-out), document the full local development recipe
(config.ini template, key generation, dev-stub, forging a login cookie),
the deployment steps (install, config propagation for nav, DNS,
internal-ipnet, nginx, User=git systemd), and design notes recording the
go-git decision, the 10 MB bundle rationale, and the pending LICENSE.
6db8684c — bigbes a month ago
cmd/comparesrht: daemon entry point, startup validation, dev stub

Wire the compare.sr.ht daemon on core-go's server.New: it runs
crypto.InitCrypto, parses -b/-d/-m/-p, and drives the standard SourceHut
warm-shutdown loop (SIGINT). We deliberately skip WithDefaultMiddleware
(it demands Postgres/Redis and 401s anonymous viewers) and instead
install the web package's documented middleware chain — RealIP, Recoverer,
Logger, config.Middleware, authz.Middleware — inside a Group on the
anonymous router.

validateConfig checks every required key up front (network-key, webhook
key, repos root, a git.sr.ht API origin candidate, meta and compare
origins) with a single clear fatal, so a misconfiguration fails loudly at
startup rather than as a deep panic in config.GetAPI on the first request.

A build-and-exec smoke test proves the binary starts against a synthesized
config, answers /healthz 200, and exits cleanly on SIGINT in under 15s.

Makefile: build ./comparesrht from ./cmd/comparesrht, run-dev binds
localhost:5090 against a local config.ini, install ships the binary and
static assets. contrib/dev-stub is a stdlib-only fake git.sr.ht GraphQL
API returning fixed public repos for local development, and the systemd
unit now stops with KillSignal=SIGINT to hit the warm-shutdown path.
71475299 — bigbes a month ago
web: http server, sourcehut chrome, compare/commit pages

Implement the compare.sr.ht HTTP layer over the committed core/gitx/authz
packages:

- Server assembly (New) from shared SourceHut config: [git.sr.ht] repos,
  [meta.sr.ht]/[compare.sr.ht] origins, [sr.ht] site-name/environment, and
  the hashed stylesheet resolved by globbing the embedded static FS.
- Routes: landing, repo page, compare (base..base...head, .patch escape
  hatch), single-commit (+.patch), embedded static assets, healthz. Compare
  form GET canonicalizes to a clean URL via 302.
- SourceHut chrome port to html/template: nav service switcher (canonical
  order, paste/pages/hub excluded, compare active), login/logout with
  return_to, environment banner.
- Embedded compare-data JSON (template.JS so html/template's script-context
  escaper leaves it verbatim; json.Marshal's HTML escaping blocks a
  </script> breakout) plus the vendored bundle.js scaffold.
- httptest coverage with a stub Authorizer and a real git-CLI fixture repo.

The cmd layer must wire, in order: RealIP, Recoverer, Logger,
config.Middleware(conf,"compare.sr.ht"), authz.Middleware.
9473e260 — bigbes a month ago
gitx: repository access and ref-to-ref diffs on go-git

Implement the git access layer for compare.sr.ht on go-git v5 (no runtime
git binary). Public surface: Open (owner/name validated via core, bare-repo
HEAD check, ErrNotFound on any miss); Refs/DefaultBranch; ResolveCommit/Log/
Parents; Diff/RawDiff/DiffStat/MergeBase/CommitPatch.

- Diffs route through DiffTreeWithOptions(DetectRenames) so old/new tree order
  is explicit: three-dot uses the merge base as old side, two-dot uses base;
  CommitPatch diffs a commit against its parent (root vs empty tree, merge vs
  first parent, ParentSHAs exposed for the banner).
- Patch text is generated in memory then capped (5 MiB page, 50 MiB raw,
  injectable override for tests) and cut at a "diff --git" file boundary so the
  browser parser never sees a torn hunk; ctx timeout (10s) guards runaways.
- FileChange status/counts/binary derived purely from go-git FilePatches
  (mapFilePatches); Log excludes base's full reachable set for correct
  base..head semantics.

Tests build fixtures by driving the real git CLI in t.TempDir(). Fidelity gate
(TestPatchFidelity) confirms go-git emits standard git headers — diff --git,
index, rename from/to, "Binary files ... differ", @@ hunks — parseable by the
frontend parsePatchFiles(). 82% coverage.

core validators reject ^/~ so navigation revs are resolved to SHAs in tests.
94142bd8 — bigbes a month ago
frontend: pierre diffs/trees bundle and sourcehut theme css

Vendored esbuild bundle (frontend/src/app.ts) rendering @pierre/diffs
FileDiff per file and a @pierre/trees FileTree sidebar against the SSR
#compare-data contract, plus scss/main.scss (base + compare views)
compiled and content-hashed into web/static/.
Next