bruno: replace Python generator with Go golden-writer in the drift test

The generator moves into the Go toolchain per repo preference:
internal/docs/bruno_gen.go emits the OpenCollection mirrors (same output
contract — gate-verified example-request bodies, env-var params,
device-token headers, login/register/refresh token-capture scripts) and
TestBrunoMirrorsDocs grows a -update flag: verification by default,
regeneration on demand:

  go test ./internal/docs -run TestBrunoMirrorsDocs -update

Generator and checker are now the same code — they cannot drift apart.
scripts/gen_bruno_from_docs.py deleted; opencollection.yml README points
at the go-test command.

Also fixed vs the Python pass: mirror placement follows the docs tree
folder (RelPath), not the area frontmatter (several docs — highlights,
notes, ratings, users, progress — carry a different area); docs blocks
emit the collection's mapping form (content + type), not a bare scalar;
JSON body sanity is checked at generation time.

Idempotent: back-to-back -update runs are byte-identical.
make test green (9 pkgs).
This commit is contained in:
John O'Keefe committed 2026-10-24 18:47:56 -04:00
1 parent acd82fff0a
commit cfcd95b25e
195 files changed
+1479 -1073

No files matched your search

+23 -5
View File
@@ -3,6 +3,7 @@ package docs
import (
"bytes"
"encoding/json"
"flag"
"os"
"path/filepath"
"reflect"
@@ -189,16 +190,33 @@ func parseHandlerMiddleware(rest string) []string {
// TestBrunoMirrorsDocs keeps the executable-verification layer honest:
// every frontmatter'd endpoint doc must have a generated OpenCollection
// (Bruno) request whose method and URL shape match. Bruno is regenerated
// from the docs (scripts/gen_bruno_from_docs.py); if this test fails, the
// collection drifted from the canonical docs or a new doc was added
// without regenerating.
// from the docs; if this test fails, the collection drifted from the
// canonical docs or a new doc was added without regenerating.
//
// Regenerate with: go test ./internal/docs -run TestBrunoMirrorsDocs -update
var updateBruno = flag.Bool("update", false, "rewrite generated Bruno mirrors from the canonical docs")
func TestBrunoMirrorsDocs(t *testing.T) {
docsDir := "../../docs/developer/api"
docsDir := docsRoot
docs, err := LoadAPIDocs(docsDir)
if err != nil {
t.Fatalf("walk %s: %v", docsDir, err)
}
if *updateBruno {
written, deleted, err := updateBrunoMirrors(docs)
if err != nil {
t.Fatalf("regenerate bruno mirrors: %v", err)
}
t.Logf("bruno mirrors: %d written, %d deleted", len(written), len(deleted))
for _, rel := range written {
t.Logf(" wrote %s", rel)
}
for _, rel := range deleted {
t.Logf(" deleted %s", rel)
}
}
// Collect bruno requests: "METHOD normalized-path" -> relpath.
bruno := map[string]string{}
files, _ := filepath.Glob("../../bruno/**/*.yml")
@@ -238,7 +256,7 @@ func TestBrunoMirrorsDocs(t *testing.T) {
path := regexp.MustCompile(`:[^/{}]+`).ReplaceAllString(doc.Frontmatter.Path, "{}")
key := doc.Frontmatter.Method + " " + path
if _, ok := bruno[key]; !ok {
t.Errorf("%s: no Bruno request mirrors %q — run scripts/gen_bruno_from_docs.py --apply", doc.RelPath, key)
t.Errorf("%s: no Bruno request mirrors %q — regenerate: go test ./internal/docs -run TestBrunoMirrorsDocs -update", doc.RelPath, key)
}
}
}