Address PR #1519 review findings · Entire
Address PR #1519 review findings
7a0ca5c→main·
toothbrush·3w ago·4 files·+78 added/-11 removed
- Wizard: gate on an interactive terminal with a clear pointer at the non-interactive form; run the pickers via RunWithContext so Ctrl+C/ctx cancellation is handled cleanly (Cursor).
- Wizard: a cancelled run no longer reports in-flight mirrors as failures — exit quietly (Cursor).
- createAndAwaitMirror: restore the suspension check for an existing empty placement (one GetMirror) so suspended empties surface resume guidance instead of a benign "nothing to clone" (Cursor).
- Wizard: suspended/failed results now carry the mirror id + resume command in the failure summary, matching the one-shot (Copilot).
- auth token: enforce HTTPS on the core URL unless --insecure-http-auth, like auth status (Copilot).
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
e2c7535c9951View transcript
[?
Interactive Repo Mirror Onboarding WizardClaude Code·2 steps](/content/gh/entireio/cli/session/b1f77cad-1b19-4ba8-bc01-a412c9c54e2a#timeline-e2c7535c9951/index.html)
Changes
4
cmd/entire/cli
Mauth.go+10/-1
Mrepo_mirror.go+19/-1
Mrepo_mirror_create_wizard.go+27/-9
Mrepo_mirror_create_wizard_test.go+22
147 unmodified lines
148
149
150
151
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
147 unmodified lines
RunE: func(cmd *cobra.Command, _ []string) error {
// Refresh may exchange/refresh over the network; honor the
// plain-HTTP opt-in before resolving so local dev cores work.
applyInsecureHTTPAuth(insecureHTTPAuth)
insecure := applyInsecureHTTPAuth(insecureHTTPAuth)
target, err := resolveAuthStatusTarget(cmd.Context(), auth.Contexts, auth.RefreshedLoginToken)
if err != nil {
return err
}
// Don't mint/print a bearer for an insecure core unless explicitly
// opted in — the token would otherwise be usable over plain HTTP.
// Mirrors `auth status`.
if !insecure && target.coreURL != "" {
if err := api.RequireSecureURL(target.coreURL); err != nil {
cmd.SilenceUsage = true
return fmt.Errorf("login server URL check: %w", err)
}
}
if target.token == "" {
cmd.SilenceUsage = true
fmt.Fprintln(cmd.ErrOrStderr(), "Not logged in. Run 'entire login' to authenticate.")
}
Mcmd/entire/cli/auth.go+10/-1
216 unmodified lines
217
218
219
220
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
216 unmodified lines
return mirrorCreateOutcome{}, err
}
outcome := mirrorCreateOutcome{created: created}
if noWait || created.Empty {
if created.Empty {
// An empty upstream has nothing to clone, so don't poll for "ready" — it
// never would. But an *existing* placement can be suspended even when
// empty, and one status read surfaces that (a fresh create can't be
// suspended — suspension follows upstream access loss). Mirrors the old
// finishMirrorCreate behavior; the read is best-effort, so a transient
// GetMirror error just falls through to the benign "nothing to clone".
if !created.Created {
if m, gerr := c.GetMirror(ctx, coreapi.GetMirrorParams{MirrorId: created.MirrorId}); gerr == nil {
if s, ok := m.Status.Get(); ok && s == coreapi.MirrorStatusSuspended {
outcome.status = s
outcome.polled = true
return outcome, errMirrorSuspended
}
}
}
return outcome, nil
}
if noWait {
return outcome, nil
}
status, werr := awaitMirrorReady(ctx, c, created.MirrorId, timeout, onStatus)
Mcmd/entire/cli/repo_mirror.go+19/-1
241 unmodified lines
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
23 unmodified lines
280
281
282
274
283
284
285
286
9 unmodified lines
296
297
298
290
299
300
301
302
2 unmodified lines
305
306
307
308
309
310
311
312
313
314
315
34 unmodified lines
350
351
352
339
340
353
354
355
356
357
19 unmodified lines
377
378
379
366
380
381
382
383
8 unmodified lines
392
393
394
381
395
396
397
398
18 unmodified lines
417
418
419
406
420
421
422
423
111 unmodified lines
535
536
537
524
538
539
540
541
542
526
543
544
545
546
547
241 unmodified lines
outW := cmd.OutOrStdout()
errW := cmd.ErrOrStderr()
// The wizard drives interactive huh pickers, so it needs a real terminal.
// Without one (CI, pipes), fail fast with a clear pointer at the
// non-interactive form rather than letting huh error obscurely.
if !interactive.CanPromptInteractively() {
fmt.Fprintln(errW, "The mirror create wizard needs an interactive terminal.")
fmt.Fprintln(errW, "Run 'entire repo mirror create <github-url> [cluster-host]' to create one non-interactively.")
return NewSilentError(errors.New("not an interactive terminal"))
}
insecure := insecureHTTPRequested(cmd)
if insecure {
auth.EnableInsecureHTTP()
23 unmodified lines
fmt.Fprintln(errW, "Run 'entire repo mirror list --show-available' to see what's onboardable.")
return nil
}
selectedRepos, err := pickRepos(outW, repos)
selectedRepos, err := pickRepos(ctx, outW, repos)
if err != nil || len(selectedRepos) == 0 {
return err
}
9 unmodified lines
if len(regions) == 0 {
return errors.New("no regions available to mirror into")
}
selectedRegions, err := pickRegions(outW, regions, jurisdiction)
selectedRegions, err := pickRegions(ctx, outW, regions, jurisdiction)
if err != nil || len(selectedRegions) == 0 {
return err
}
2 unmodified lines
targets := mirrorTargets(selectedRepos, selectedRegions)
results := createMirrors(ctx, errW, targets, noWait, waitTimeout)
// A cancelled run (Ctrl+C) leaves in-flight mirrors looking like errors;
// exit quietly instead of reporting them as "N mirror(s) failed".
if ctx.Err() != nil {
return NewSilentError(ctx.Err())
}
return reportMirrorResults(outW, errW, results)
}
34 unmodified lines
// pickRepos runs the repo multi-select and returns the chosen available
// mirrors. A clean cancel (Ctrl+C) returns (nil, nil).
func pickRepos(w io.Writer, repos []coreapi.AvailableMirror) ([]coreapi.AvailableMirror, error) {
// mirrors. A clean cancel (Ctrl+C / cancelled ctx) returns (nil, nil).
func pickRepos(ctx context.Context, w io.Writer, repos []coreapi.AvailableMirror) ([]coreapi.AvailableMirror, error) {
repoByKey := make(map[string]coreapi.AvailableMirror, len(repos))
options := make([]huh.Option[string], len(repos))
for i, m := range repos {
19 unmodified lines
Value(&selected),
),
)
if err := form.Run(); err != nil {
if err := form.RunWithContext(ctx); err != nil {
return nil, handleFormCancellation(w, "Mirror create", err)
}
8 unmodified lines
// pickRegions runs the region multi-select, pre-selecting the default cluster
// for the caller's jurisdiction. A clean cancel returns (nil, nil).
func pickRegions(w io.Writer, regions []regionChoice, jurisdiction string) ([]regionChoice, error) {
func pickRegions(ctx context.Context, w io.Writer, regions []regionChoice, jurisdiction string) ([]regionChoice, error) {
opts, defaults := clusterChoices(regions, jurisdiction)
regionByHost := make(map[string]regionChoice, len(regions))
for _, r := range regions {
18 unmodified lines
111 unmodified lines
case coreapi.MirrorStatusReady:
res.status = mirrorStatusReady
case coreapi.MirrorStatusSuspended:
res.status, res.err = mirrorStatusSuspended, err
// 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)
case coreapi.MirrorStatusFailed:
res.status, res.err = mirrorStatusFailed, err
res.status, res.err = mirrorStatusFailed,
fmt.Errorf("initial clone failed (mirror %s)", outcome.created.MirrorId)
case coreapi.MirrorStatusProcessing:
nonTerminal()
default:
Mcmd/entire/cli/repo_mirror_create_wizard.go+27/-9
1 unmodified line
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
1 unmodified line
import ( "bytes" "context" "testing" "time"
"github.com/spf13/cobra" "github.com/stretchr/testify/require"
"github.com/entireio/cli/internal/coreapi" )
func TestRunMirrorCreateWizard_RequiresTTY(t *testing.T) { t.Parallel() // In-process tests are non-interactive, so the wizard must refuse before // touching auth or the network, pointing at the non-interactive form. cmd := &cobra.Command{} var out, errOut bytes.Buffer cmd.SetOut(&out) cmd.SetErr(&errOut) cmd.SetContext(context.Background())
err := runMirrorCreateWizard(cmd, false, time.Minute)
var silent *SilentError
require.ErrorAs(t, err, &silent)
require.Empty(t, out.String(), "stdout must stay clean")
require.Contains(t, errOut.String(), "interactive terminal")
require.Contains(t, errOut.String(), "entire repo mirror create
func TestSelectableAvailableRepos(t *testing.T) { t.Parallel() in := []coreapi.AvailableMirror{