repo clone: resolve /gh/ shorthand via pull-gated placement lookup · Entire
repo clone: resolve /gh/ shorthand via pull-gated placement lookup
2e21aaf→main·
matthiaswenz·yesterday·12 files·+1,233 added/-2 removed
Why
entire repo clone /gh/<owner>/<repo> resolved owner/repo to a cluster
host via the mirror list (repo#list), which omits the public_viewer
wildcard. A public mirror the caller held no grant on was invisible to
discovery, so the shorthand failed with "no mirror found" even though
cloning the full entire:// URL (repo#pull) worked. Discovery and
authorization disagreed.
What
Point the clone path's discovery at the new pull-gated GET /api/v1/mirrors/placements (resolveMirrorPlacements): regenerate the ogen client from the spec, add resolvePullablePlacements() in repo_clone.go, and call it instead of listMirrorsForRepo. Now discovery uses the same authority (repo#pull) as the clone itself, so anything clonable-by-URL — public or private-with-grant — resolves by shorthand.
The three routing callers (api passthrough, experts cell-target, activity/recap) keep using the affiliation-scoped listMirrorsForRepo: enumeration should stay repo#list so public repos don't flood listings. Only targeted clone-by-name uses pull. Results map into coreapi.Mirror so the cluster picker (selectCloneTarget) is unchanged.
Tests
repo_clone_test.go: TestResolvePullablePlacements_MapsPlacements asserts the endpoint, query, and field mapping. Existing picker/list tests unchanged and passing.
Paired server change (entiredb): link added after creation.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Changes
12
cmd/entire/cli
Mrepo_clone.go+49/-2
Mrepo_clone_test.go+46
internal/coreapi
Moas_client_gen.go+133
Moas_json_gen.go+424
Moas_operations_gen.go+1
Moas_parameters_gen.go+9
Moas_response_decoders_gen.go+92
Moas_schemas_gen.go+155
Moas_security_gen.go+2
Moas_validators_gen.go+32
spec
Mcore.gen.json+125
Mcore.openapi.json+165
106 unmodified lines
107
108
109
110
110
111
112
113
114
115
116
117
118
117
119
120
121
122
83 unmodified lines
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
106 unmodified lines
return runGitClone(cmd.Context(), cmd, ref, targetDir)
}
provider, owner, repo, err := parseMirrorCloneRef(ref)
// provider is always "github" for the /gh/ shorthand; the pull-gated
// resolver pins the provider itself, so it's not threaded through.
_, owner, repo, err := parseMirrorCloneRef(ref)
if err != nil {
return fmt.Errorf("invalid <repo>: %w", err)
}
var mirrors []coreapi.Mirror
lister := func(ctx context.Context, c *coreapi.Client) error {
ms, err := listMirrorsForRepo(ctx, c, provider, owner, repo)
ms, err := resolvePullablePlacements(ctx, c, owner, repo)
if err != nil {
return err
}
83 unmodified lines
return matched, nil
}
// mirrorResolver is the subset of the control-plane client
// resolvePullablePlacements needs. Narrowing to an interface lets tests inject
// a fake; *coreapi.Client satisfies it.
type mirrorResolver interface {
ResolveMirrorPlacements(ctx context.Context, params coreapi.ResolveMirrorPlacementsParams) (*coreapi.ResolvePlacementsOutputBody, error)
}
// resolvePullablePlacements returns every cluster placement of one GitHub
// upstream the caller may pull (clone). It backs `repo clone /gh/<owner>/<repo>`
// and deliberately differs from listMirrorsForRepo: that reads the
// affiliation-scoped mirror list (repo#list), which omits public mirrors the
// caller holds no grant on, so the shorthand used to fail on a public repo that
// clones fine by full entire:// URL. This hits the pull-gated /mirrors/placements
// endpoint instead — the same authority the clone's STS exchange enforces — so
// anything clonable resolves, public or private-with-grant.
//
// owner/repo arrive already lowercased from parseMirrorCloneRef; the server
// matches case-insensitively regardless. Results map into coreapi.Mirror so the
// cluster picker (selectCloneTarget) is untouched — only the fields it reads
// (ClusterHost, Cell, Jurisdiction) plus the coords are populated. An empty
// result means not mirrored or not pullable, and the caller surfaces that.
func resolvePullablePlacements(ctx context.Context, c mirrorResolver, owner, repo string) ([]coreapi.Mirror, error) {
out, err := c.ResolveMirrorPlacements(ctx, coreapi.ResolveMirrorPlacementsParams{
Provider: coreapi.ResolveMirrorPlacementsProviderGithub,
Owner: owner,
Repo: repo,
})
if err != nil {
return nil, fmt.Errorf("resolve mirror placements: %w", err)
}
mirrors := make([]coreapi.Mirror, 0, len(out.Placements))
for _, p := range out.Placements {
mirrors = append(mirrors, coreapi.Mirror{
MirrorId: p.MirrorId,
Provider: mirrorCloneProviderGitHub,
Owner: owner,
Repo: repo,
ClusterHost: p.ClusterHost,
Cell: p.Cell,
Jurisdiction: p.Jurisdiction,
})
}
return mirrors, nil
}
// selectCloneTarget resolves which mirror placement to clone from. With one
// placement it returns it directly. With --cluster it picks the matching one (or
// errors listing the available hosts). With more than one and no flag it prompts
Mcmd/entire/cli/repo_clone.go+49/-2
188 unmodified lines
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
188 unmodified lines
// TestResolvePullablePlacements_MapsPlacements verifies the clone-discovery // resolver hits the pull-gated /mirrors/placements endpoint with the upstream // coords and maps every returned placement into a coreapi.Mirror the picker can // consume (host + cell + jurisdiction + coords). A public mirror the caller // holds no grant on resolves here even though it never would via the // affiliation-scoped list — that's the whole point of the endpoint. func TestResolvePullablePlacements_MapsPlacements(t *testing.T) { t.Parallel() var gotPath, gotQuery string srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { gotPath = r.URL.Path gotQuery = r.URL.RawQuery w.Header().Set("Content-Type", "application/json") body := &coreapi.ResolvePlacementsOutputBody{Placements: []coreapi.ResolvedPlacement{ {MirrorId: "01AAA", ClusterHost: "aws-us-east-2.entire.io", Cell: coreapi.NewOptString("aws-us-east-2"), Jurisdiction: coreapi.NewOptString("us")}, {MirrorId: "01BBB", ClusterHost: "aws-eu-west-1.entire.io", Cell: coreapi.NewOptString("aws-eu-west-1"), Jurisdiction: coreapi.NewOptString("eu")}, }} if err := printJSON(w, body); err != nil { t.Errorf("encode response: %v", err) } })) t.Cleanup(srv.Close)
c, err := coreapi.NewWithBearer(srv.URL, "tok") require.NoError(t, err)
got, err := resolvePullablePlacements(t.Context(), c, "karthik-rameshkumar", "my-entire") require.NoError(t, err)
require.Equal(t, "/api/v1/mirrors/placements", gotPath) require.Contains(t, gotQuery, "provider=github") require.Contains(t, gotQuery, "owner=karthik-rameshkumar") require.Contains(t, gotQuery, "repo=my-entire")
require.Len(t, got, 2) require.Equal(t, "aws-us-east-2.entire.io", got[0].ClusterHost) require.Equal(t, "aws-us-east-2", got[0].Cell.Or("")) require.Equal(t, "us", got[0].Jurisdiction.Or("")) require.Equal(t, "01AAA", got[0].MirrorId) // Coords are echoed onto every placement so the synthesized clone URL and // the picker labels carry them. require.Equal(t, "karthik-rameshkumar", got[0].Owner) require.Equal(t, "my-entire", got[0].Repo) require.Equal(t, "aws-eu-west-1.entire.io", got[1].ClusterHost) }
// TestListMirrorsForRepo_FiltersByRepo verifies the client-side repo filter: // the list API filters provider+owner server-side, but the repo match (which // the API has no param for) is applied locally.