Add goproxy virtual repositories #159

Open
unkin-agent wants to merge 7 commits from benvin/virtual-go into master
Member

Go clients need one GOPROXY for internal and public modules; goproxy has no virtual type, so a local goproxy repo and proxy.golang.org cannot be served together.

  • union member @v/lists; compute @latest over the union (highest release, else highest prerelease)
  • 302 @latest and .info/.mod/.zip to the first member with that version, root-relative and no-store; probe .info for unlisted pseudo-versions
  • validate case-encoded module paths and versions
  • fail closed with 502 on a member error, skip members answering 404/410
  • cache merged lists, keyed on list and version owners, and module misses for the merge TTL
  • add docs/goproxy/virtual.md and a stock golang:1.25 e2e-docker case

requires unkin/artifactapi#143

Go clients need one GOPROXY for internal and public modules; goproxy has no virtual type, so a local goproxy repo and proxy.golang.org cannot be served together. - union member `@v/list`s; compute `@latest` over the union (highest release, else highest prerelease) - 302 `@latest` and `.info`/`.mod`/`.zip` to the first member with that version, root-relative and `no-store`; probe `.info` for unlisted pseudo-versions - validate case-encoded module paths and versions - fail closed with 502 on a member error, skip members answering 404/410 - cache merged lists, keyed on list and version owners, and module misses for the merge TTL - add `docs/goproxy/virtual.md` and a stock `golang:1.25` e2e-docker case requires unkin/artifactapi#143
Author
Member
  • internal/virtual/goproxy_merger.go:35 — GoDoc.index() returns only Body, and merged() (engine.go:311) keeps the old generation when the body is unchanged, so Owners is never refreshed while the version list stays the same (e.g. a version deleted from the first member but still listed by a later one keeps 302ing to the first member and 404s; a version newly added to the first member keeps being served from the later one) → make index() include the owners (e.g. version owner lines) so an owner change replaces the cached doc; add a test.
  • nit: internal/virtual/engine.go:434 — the shared fetchMemberPath 404/410 → ErrNotFound change has no test → add one covering a ServeRemote/ServeLocalIndex 404 and 410 (goMember is stubbed everywhere, so nothing exercises it).
  • nit: internal/virtual/goproxy_merger.go:157 — ErrNotFound merges are not cached, so every request for a module no member has fans out to all members (including proxy.golang.org) → cache the miss for a short TTL or document it.
- internal/virtual/goproxy_merger.go:35 — `GoDoc.index()` returns only `Body`, and `merged()` (engine.go:311) keeps the old generation when the body is unchanged, so `Owners` is never refreshed while the version list stays the same (e.g. a version deleted from the first member but still listed by a later one keeps 302ing to the first member and 404s; a version newly added to the first member keeps being served from the later one) → make `index()` include the owners (e.g. `version owner` lines) so an owner change replaces the cached doc; add a test. - nit: internal/virtual/engine.go:434 — the shared `fetchMemberPath` 404/410 → `ErrNotFound` change has no test → add one covering a `ServeRemote`/`ServeLocalIndex` 404 and 410 (goMember is stubbed everywhere, so nothing exercises it). - nit: internal/virtual/goproxy_merger.go:157 — `ErrNotFound` merges are not cached, so every request for a module no member has fans out to all members (including proxy.golang.org) → cache the miss for a short TTL or document it.
Author
Member

No findings.

No findings.
benvin changed target branch from benvin/local-go to master 2026-10-19 00:01:54 +11:00
benvin added 6 commits 2026-10-19 00:01:54 +11:00
Add goproxy local repositories for private Go modules
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
a51323c725
merge master
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
8378701d9a
merge master
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
5a2bfdf73a
merge master
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
8e96aabbef
Add goproxy virtual repositories
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
c6f7eb3eb7
Key goproxy merge cache on owners and cache module misses
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ac6e1bf798
unkin-agent added 1 commit 2026-10-19 00:03:49 +11:00
Merge remote-tracking branch 'origin/master' into benvin/virtual-go
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
be7be0bd04
# Conflicts:
#	README.md
#	internal/provider/goproxy/local.go
All checks were successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Required
Details
ci/woodpecker/pr/build Pipeline was successful
Required
Details
ci/woodpecker/pr/test Pipeline was successful
Required
Details
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin benvin/virtual-go:benvin/virtual-go
git checkout benvin/virtual-go
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unkin/artifactapi#159