feat(git-remote-entire): surface wrong-cluster clone errors clearly · Entire

feat(git-remote-entire): surface wrong-cluster clone errors clearly

97aa0c9→main·

toothbrush·2w ago·3 files·+96 added/-6 removed

When a repo lives on a different cluster than the one in the entire:// URL, the data plane rejects the token exchange with an RFC 8693 invalid_target carrying an error_description naming the correct host. Previously this surfaced as a raw, multiply-wrapped HTTP 400 JSON blob.

Now git-remote-entire detects this case and prints an actionable message naming the correct host and the corrected git clone entire://... URL.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Sessions

7cf3c440ed71View transcript

Changes

3

import (
    "context"
    "errors"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "os"
    "os/signal"
    "regexp"
    "runtime"
    "strings"
    "syscall"
    "github.com/entireio/cli/cmd/entire/cli/versioninfo"
    "github.com/entireio/cli/internal/entireclient/clusterdiscovery"
    "github.com/entireio/cli/internal/entireclient/httpclient"
    "github.com/entireio/cli/internal/entireclient/httputil"
    "github.com/entireio/cli/internal/entireclient/repocreds"
    "github.com/entireio/cli/internal/entireclient/userdirs"
    "github.com/entireio/cli/internal/remotehelper"
)

// wrongClusterRe extracts the host that actually serves the repo from the // data plane's invalid_target error_description (RFC 8693). The data plane // emits this when the audience host doesn't host the repo but a sibling // cluster does, naming the correct host so we can point the user at it. The // phrasing is "… it lives on "" …"; anchoring on "lives on" keeps the // match tied to this specific, actionable case rather than other // invalid_target variants (e.g. a suspended mirror). var wrongClusterRe = regexp.MustCompile(lives on "([^"]+)")

// fatalMessage renders the stderr "fatal: …" line for a transfer error. When // the failure is the data plane reporting that the repo lives on a different // cluster, it special-cases the raw OAuth chain into an actionable message // naming the correct host (and the corrected entire:// URL). Everything else // falls back to the verbatim error. func fatalMessage(err error, parsedURL *url.URL) string { var oe *httputil.OAuthError if errors.As(err, &oe) && oe.Code == "invalid_target" { if m := wrongClusterRe.FindStringSubmatch(oe.Description); m != nil { host := m[1] corrected := (&url.URL{Scheme: "entire", Host: host, Path: parsedURL.Path}).String() return fmt.Sprintf("fatal: this repository is not hosted on %s; it lives on %s.\nRe-run against the correct host, e.g.:\n\n git clone %s\n", parsedURL.Host, host, corrected) } } return fmt.Sprintf("fatal: %v\n", err) }

// loadedVersion populates the build info and returns the resolved version. func loadedVersion() string { versioninfo.Load() }

func TestFatalMessage(t *testing.T) { t.Parallel() parsedURL := &url.URL{Scheme: "entire", Host: "aws-us-east-2.entire.io", Path: "/et/paul/dogbark"} wrongCluster := &httputil.OAuthError{ Status: http.StatusBadRequest, Code: "invalid_target", Description: audience host "aws-us-east-2.entire.io" does not host this repo; it lives on "aws-eu-central-1.entire.io" — re-target the request there, Body: "{...}", } tests := []struct { name string err error contains []string notContains []string }{ { name: "wrong cluster names correct host and URL", // Wrapped to mirror production: the OAuthError surfaces buried under // several fmt.Errorf layers, so errors.As must dig it out. err: fmt.Errorf("stateless-connect v2 info/refs: fetching info/refs from entry domain: repo-scoped token exchange: oauth token exchange: %w", wrongCluster), contains: []string{ "aws-eu-central-1.entire.io", "git clone entire://aws-eu-central-1.entire.io/et/paul/dogbark", }, notContains: []string{"HTTP 400", "invalid_target"}, }, { name: "invalid_target without lives-on hint falls back", err: &httputil.OAuthError{Status: http.StatusBadRequest, Code: "invalid_target", Description: "no servable mirror", Body: "HTTP 400: no servable mirror"}, contains: []string{"fatal:", "no servable mirror"}, }, { name: "unrelated error falls back verbatim", err: errors.New("connection refused"), contains: []string{"fatal: connection refused"}, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { t.Parallel() got := fatalMessage(tc.err, parsedURL) for _, sub := range tc.contains { if !strings.Contains(got, sub) { t.Errorf("fatalMessage() = %q, missing %q", got, sub) } } for _, sub := range tc.notContains { if strings.Contains(got, sub) { t.Errorf("fatalMessage() = %q, should not contain %q", got, sub) } } } } }