feat(registry): Go module support - #126
Conversation
Adds `go` as a registry: version discovery through proxy.golang.org, plus the
recursive definition walk that Go module paths require.
Three things differ from the existing fetchers, each measured against the live
proxy rather than inferred:
- Uppercase letters must be escaped as "!" + lowercase.
github.com/BurntSushi/toml/@v/list returns 404; github.com/!burnt!sushi/toml
returns 200. Slashes are path separators and must survive, so
encodeURIComponent is the wrong tool.
- The "v" prefix is stripped before the shared helpers see it.
isPrerelease("v1.10.2") is true, so every Go version would be silently
discarded, and compareSemver("v1.10.2", "v1.9.1") is NaN, so sorting breaks.
Definitions restore the prefix with tag_pattern "v{version}", which keeps
both shared functions untouched.
- /@v/list carries no publish dates. Getting them costs one /@v/<version>.info
request per version, so --since filtering is unavailable for Go rather than
merely slow. publishedAt is left undefined.
listDefinitions only recursed into directories starting with "@", so
registry/go/github.com/spf13/cobra.yaml was never loaded — exit 0, no warning.
Every Go module path contains slashes, so this blocked the ecosystem rather
than one package. The general recursive walk that replaces the special case is
smaller than the case it removes, and scoped npm packages still resolve because
loadDefinition already derives expectedName from the path relative to the
manager directory.
registry/go/github.com/spf13/cobra.yaml is included as the first definition. It
was taken end to end before this PR: registry build produced 56 sections /
19631 tokens, context add installed it, and `context query
'github.com/spf13/cobra' 'persistent flags'` returned the right section.
Tests: four new ones. Three cover the fetcher (prefix stripping, case escaping,
a module with no tags) and one covers a definition nested several directories
deep. Each was mutation-checked — dropping the escaping, keeping the v prefix,
and removing the recursion each turn exactly the matching test red. 45/45 green,
biome clean.
One open question for a maintainer: `std` is not on the module proxy, so the Go
standard library would need an unversioned definition like python/python.yaml
rather than a `go` one. Not included here.
🦋 Changeset detectedLatest commit: cac38d9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Thanks for this — I reviewed it closely and verified your central claims against the live proxy. The case-escaping is right ( Four things block merge. The first is serious. 1. A 4xx from the Go proxy kills the entire nightly run.
Reproduced with a bogus module plus a valid npm definition after it: The npm definition was never reached and no This is our fragility, not yours — 2. The nightly runs 3. 4. Go submodules resolve the wrong tag and skip forever. Default Docs need updating. Two smaller notes: deleting Good contribution — the mechanism is right and the verification in your description held up. Happy to review again once these are in. Generated by Claude Code |
) publish-all called discoverVersions outside the try that guards the rest of the loop, so anything it threw escaped and ended the process. Definitions are walked in sorted order, so one third-party registry API returning 404, 410 or 429 silently abandoned every package after it and printed no summary at all. version-check.ts aborts immediately below status 500, so there was no retry either. Discovery talks to an external API and fails for reasons unrelated to the package — a renamed module, a rate limit, an upstream blip. Those now record a failure for that definition and continue, exactly like a failed build. Found while reviewing #126, which adds a Go registry and makes this trivially reachable: go/github.com/spf13/cobra sorts second of 141, so one proxy hiccup would take down the other 139. The fragility is ours and predates it. The new tests run the real CLI against a scratch registry using a registry with no version fetcher, so discovery throws before any network call. Both were verified load-bearing: they fail with the guard reverted and pass with it.
What this adds
goas a registry: version discovery throughproxy.golang.org, and the recursive definition walk that Go module paths require.Three things Go does differently, each measured against the live proxy
Uppercase letters must be escaped as
!+ lowercase.Slashes are path separators and have to survive, so
encodeURIComponentis the wrong tool here.The
vprefix is stripped before the shared helpers see it.isPrerelease("v1.10.2")istrue— it reads the leading letter as a prerelease tag — so every Go version would be silently discarded.compareSemver("v1.10.2", "v1.9.1")isNaN, so sorting breaks too. Stripping it in the fetcher and restoring it withtag_pattern: "v{version}"keeps both shared functions untouched, which is why this PR does not go near them./@v/listcarries no publish dates. Getting them costs one/@v/<version>.inforequest per version, so--sincefiltering is unavailable for Go rather than merely slow.publishedAtis left undefined.The blocker underneath it
listDefinitionsonly recursed into directories starting with@, soregistry/go/github.com/spf13/cobra.yamlwas never loaded — exit code 0, no warning. Every Go module path contains slashes, so this blocked the whole ecosystem rather than one package.The general recursive walk that replaces the special case is smaller than the case it removes. Scoped npm packages still resolve, because
loadDefinitionalready derivesexpectedNamefrom the path relative to the manager directory.Taken end to end before opening this
registry build→ 56 sections / 19631 tokens →context add→context query 'github.com/spf13/cobra' 'persistent flags'returned the correct section.registry/go/github.com/spf13/cobra.yamlis included as the first Go definition.Tests
Four new. Three on the fetcher — prefix stripping, case escaping, a module with no tagged releases — and one on a definition nested several directories deep.
Each was mutation-checked rather than just watched to pass: dropping the escaping, keeping the
vprefix, and removing the recursion each turn exactly the matching test red. 45/45 green, biome clean.One question for a maintainer
stdis not on the module proxy, so the Go standard library would need an unversioned definition likepython/python.yamluses, not agoone. Not included here — it seemed like your call which shape you want.