Address PR #1519 review round 2 · Entire

Address PR #1519 review round 2

0b20568→main·

toothbrush·3w ago·4 files·+23 added/-21 removed

- handleFormCancellation: also treat a cancelled/expired context as a clean cancel, so a RunWithContext form whose context is cancelled exits quietly instead of "prompt failed: huh: context canceled" (Cursor). - Drop internal terminology from suspended/failed user messages: the wizard now says "the mirror is suspended; contact support" / "the initial clone failed; contact support", and explainSuspendedMirror points at support instead of the internal entire-core admin mirrors resume command (Cursor).

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

Sessions

9ea51e10ee42View transcript

?\ Interactive Repo Mirror Onboarding WizardClaude Code·2 steps

Changes

4

534 unmodified lines

535
536
537
538
539
540
541
538
539
543
544
540
541
542
543

534 unmodified lines

case coreapi.MirrorStatusReady:
        res.status = mirrorStatusReady
    case coreapi.MirrorStatusSuspended:
        // Carry the mirror id + resume command so the failure summary is
        // actionable, matching the one-shot's explainSuspendedMirror guidance.
        res.status, res.err = mirrorStatusSuspended,
            fmt.Errorf("suspended — an operator can resume it: entire-core admin mirrors resume %s", outcome.created.MirrorId)
        res.status, res.err = mirrorStatusSuspended, errors.New("the mirror is suspended; contact support")
    case coreapi.MirrorStatusFailed:
        res.status, res.err = mirrorStatusFailed,
            fmt.Errorf("initial clone failed (mirror %s)", outcome.created.MirrorId)
        res.status, res.err = mirrorStatusFailed, errors.New("the initial clone failed; contact support")
    case coreapi.MirrorStatusProcessing:
        nonTerminal()
    default:

Mcmd/entire/cli/repo_mirror_create_wizard.go+2/-6

149 unmodified lines

150
151
152
153
154
155
156
153
154
155
156
157
158
159
159
160
161
161
162
163
164
162
163
164
165

149 unmodified lines

return fmt.Errorf("timed out waiting for initial clone: %w", err)
}

// explainSuspendedMirror prints operator-recovery guidance for a suspended
// placement: the cluster won't serve clones until upstream GitHub access is
// restored and an operator resumes it. Suspension usually follows upstream
// access loss (App uninstalled, repo went private, or a transient API error).
// explainSuspendedMirror tells the user a suspended placement can't be served
// and to contact support. Suspension usually follows a loss of upstream GitHub
// access (App uninstalled, repo went private, or a transient API error); the
// fix is operator-side, so we point at support rather than leaking an internal
// admin command.
func explainSuspendedMirror(w io.Writer, mirrorID string) {
    fmt.Fprintf(w,
        "\nMirror %s is registered but suspended — the cluster won't serve it.\n"+
        "\nMirror %s is registered but suspended, so it can't be cloned yet.\n"+
        "This usually means upstream GitHub access was lost (App uninstalled,\n"+
        "the repo went private, or a transient API error). An operator can\n"+
        "re-enable it once access is restored:\n"+
        "  entire-core admin mirrors resume %s\n",
        mirrorID, mirrorID)
        "the repo went private, or a transient API error). Contact support to\n"+
        "restore it.\n",
        mirrorID)
}

Mcmd/entire/cli/repo_mirror_probe.go+9/-9

21 unmodified lines

22
23
24
25
25
26
27
28
29
30
113 unmodified lines

144
145
146
145
147
148
149
150
151
152
153
152
154
155
156
157
158

21 unmodified lines

explainSuspendedMirror(&buf, id)
    out := buf.String()
    require.Contains(t, out, id, "message must name the mirror")
    require.Contains(t, out, "entire-core admin mirrors resume "+id, "message must give the resume command")
    require.Contains(t, out, "suspended")
    require.Contains(t, out, "Contact support", "must point at support, not an internal admin command")
    require.NotContains(t, out, "entire-core", "must not leak internal terminology")

// fakeMirrorGetter feeds awaitMirrorReady a scripted sequence of statuses (the
113 unmodified lines

require.Contains(t, out.String(), "git clone "+mirrorURL)
    })

t.Run("suspended surfaces resume guidance as SilentError", func(t *testing.T) {
t.Run("suspended surfaces support guidance as SilentError", func(t *testing.T) {
    t.Parallel()
    var out, errW bytes.Buffer
    outcome := mirrorCreateOutcome{created: mk(false, false), status: coreapi.MirrorStatusSuspended, polled: true}
    err := reportOneShotMirror(&out, &errW, outcome, errMirrorSuspended)
    var silent *SilentError
    require.ErrorAs(t, err, &silent)
    require.Contains(t, errW.String(), "entire-core admin mirrors resume "+id)
    require.Contains(t, errW.String(), "Contact support")
    require.NotContains(t, errW.String(), "entire-core")
    require.NotContains(t, out.String(), "git clone")
    })
}

Mcmd/entire/cli/repo_mirror_test.go+6/-3

27 unmodified lines

28
29
30
31
32
31
32
33
34
35
34
36
37
38
39
40

27 unmodified lines

// handleFormCancellation handles cancellation from huh form prompts.
// User abort (Ctrl+C) and timeout both print a cancelled message and return nil.
// Other errors are wrapped with the action name for context.
// User abort (Ctrl+C), timeout, and a cancelled/expired context (when the form
// ran via RunWithContext and the command's context was cancelled) all print a
// cancelled message and return nil. Other errors are wrapped with the action
// name for context.
func handleFormCancellation(w io.Writer, action string, err error) error {
    if errors.Is(err, huh.ErrUserAborted) || errors.Is(err, huh.ErrTimeout) {
    if errors.Is(err, huh.ErrUserAborted) || errors.Is(err, huh.ErrTimeout) ||
        errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
        fmt.Fprintf(w, "%s cancelled.\n", action)
        return nil
    }