Skip to content

refactor: make init wizard purely interactive, fix orchestrator UX#52

Merged
ewega merged 1 commit intomainfrom
refactor/init-wizard-interactive
Feb 20, 2026
Merged

refactor: make init wizard purely interactive, fix orchestrator UX#52
ewega merged 1 commit intomainfrom
refactor/init-wizard-interactive

Conversation

@ewega
Copy link
Copy Markdown
Contributor

@ewega ewega commented Feb 20, 2026

Summary

Make init fully interactive and fix both orchestrator commands (init, configure full) to call inner functions directly instead of sub-command entry points.

init changes

  • Stripped flags: removed --org, --repos, --repos-file, --enterprise — kept only --token and --env-file
  • No sub-command delegation: calls scopeGitHub(), scopeCopilot(), listConnectionScopes(), finalizeProject() directly — no duplicate banners, no redundant discovery
  • No default selection: connection picker uses SelectMulti instead of SelectMultiWithDefaults — user explicitly chooses
  • Plugin-aware scoping: Phase 3 handles each plugin type in a switch — GitHub gets DORA patterns + repo selection, Copilot gets org/enterprise scope, unknown plugins get a 'not yet supported' message

configure full changes

  • Same inner-function pattern — no runConfigureScopes/runConfigureProjects calls
  • Plugin-aware scope handling with switch statement
  • Connection picker with no pre-selected defaults

Testing

  • go build clean
  • go test ./... all pass
  • init --help shows only --token and --env-file

## init command
- Stripped all config flags (--org, --repos, --repos-file, --enterprise)
- Kept only --token and --env-file (PAT source)
- Calls inner functions (scopeGitHub, scopeCopilot, listConnectionScopes,
  finalizeProject) directly instead of runConfigureScopes/runConfigureProjects
- No duplicate banners or redundant DevLake discovery
- Connection picker uses SelectMulti (no pre-selected defaults)
- Scope configuration is plugin-aware: GitHub gets DORA patterns + repo
  selection, Copilot gets org/enterprise scope, unknown plugins get a
  'not yet supported' message (future-proofing for GitLab, ADO)
- Explicitly prompts for project name in Phase 4

## configure full command
- Same inner-function pattern: calls scopeGitHub/scopeCopilot and
  listConnectionScopes/finalizeProject directly
- No duplicate banners from sub-commands
- Connection picker uses SelectMulti (no pre-selected defaults)
- Plugin-specific scope handling with switch statement
Copilot AI review requested due to automatic review settings February 20, 2026 10:16
@ewega ewega added this to the v0.3.7 milestone Feb 20, 2026
@ewega ewega merged commit e4a304e into main Feb 20, 2026
1 check passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the CLI orchestrators (init and configure full) to use a more interactive, plugin-aware workflow, and updates terminal UX output (banners/emoji) while avoiding sub-command entrypoint delegation.

Changes:

  • Removed most init flags to make the wizard primarily interactive and added plugin-aware scoping/project setup.
  • Updated configure full to scope per-plugin via direct helper calls and removed default connection pre-selections.
  • Standardized various CLI outputs (Unicode banners/emoji) and adjusted connection selection behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.

File Description
cmd/init.go Makes init interactive, adds plugin-aware scoping + direct project finalization, and updates wizard UX output.
cmd/configure_full.go Refactors full orchestrator to call inner helpers directly, removes default selections, and updates UX output and flow.
Comments suppressed due to low confidence (5)

cmd/init.go:88

  • Phase banner is missing the required blank line after the banner frame (terminal output standards rule #5). Add a trailing fmt.Println() after the 3 banner lines.
fmt.Println("\n╔══════════════════════════════════════╗")
fmt.Println("║  PHASE 2: Configure Connections      ║")
fmt.Println("╚══════════════════════════════════════╝")

cmd/init.go:140

  • Phase banner is missing the required blank line after the banner frame (terminal output standards rule #5). Add a trailing fmt.Println() after the 3 banner lines.
fmt.Println("\n╔══════════════════════════════════════╗")
fmt.Println("║  PHASE 3: Configure Scopes           ║")
fmt.Println("╚══════════════════════════════════════╝")

cmd/init.go:193

  • Phase banner is missing the required blank line after the banner frame (terminal output standards rule #5). Add a trailing fmt.Println() after the 3 banner lines.
fmt.Println("\n╔══════════════════════════════════════╗")
fmt.Println("║  PHASE 4: Project Setup              ║")
fmt.Println("╚══════════════════════════════════════╝")

cmd/configure_full.go:104

  • Phase banners should have a blank line on both sides (including after the banner). Add a trailing fmt.Println() after this 3-line banner to match terminal output standards and improve readability (see .github/instructions/terminal-output.instructions.md#phase-banners).
fmt.Println("\n╔══════════════════════════════════════╗")
fmt.Println("║  PHASE 1: Configure Connections      ║")
fmt.Println("╚══════════════════════════════════════╝")

cmd/configure_full.go:138

  • Phase banner is missing the required blank line after the banner frame (terminal output standards rule #5). Add a trailing fmt.Println() after the 3 banner lines.
fmt.Println("\n╔══════════════════════════════════════╗")
fmt.Println("║  PHASE 2: Configure Scopes           ║")
fmt.Println("╚══════════════════════════════════════╝")

fmt.Println("\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d")
fmt.Println("\n╔══════════════════════════════════════╗")
fmt.Println(" PHASE 1: Deploy DevLake ")
fmt.Println("╚══════════════════════════════════════╝")
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phase banners are missing the required blank line after the 3-line banner. Terminal output standards require an empty line after phase banners so the next output/prompt doesn’t jam against the frame (see .github/instructions/terminal-output.instructions.md#phase-banners). Add a trailing fmt.Println() after this banner.

This issue also appears in the following locations of the same file:

  • line 86
  • line 138
  • line 191
Suggested change
fmt.Println("╚══════════════════════════════════════╝")
fmt.Println("╚══════════════════════════════════════╝")
fmt.Println()

Copilot uses AI. Check for mistakes.
}

results, client, statePath, state, err := runConnectionsInternal(selectedDefs, initOrg, initEnterprise, initToken, initEnvFile, true)
results, _, _, _, err := runConnectionsInternal(selectedDefs, org, "", initToken, initEnvFile, true)
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runInit already discovers DevLake (disc := devlake.Discover(cfgURL)) and constructs a client, but Phase 2 calls runConnectionsInternal which performs another devlake.Discover(cfgURL) and prints its own discovery step. This reintroduces redundant discovery/extra UX and contradicts the PR description (“no redundant discovery”). Consider refactoring connection creation to accept the already-discovered URL/client (or split runConnectionsInternal so init can skip discovery).

Copilot uses AI. Check for mistakes.
Comment on lines +155 to +157
fmt.Printf(" Deployment: %s\n", scopeOpts.DeployPattern)
fmt.Printf(" Production: %s\n", scopeOpts.ProdPattern)
fmt.Printf(" Incidents: label=%s\n", scopeOpts.IncidentLabel)
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sub-item indentation is inconsistent with the repo’s terminal output standards (3-space indent). These lines use 5 spaces before labels, which misaligns with other sub-items. Use a consistent " " indent for sub-items under a step (see .github/instructions/terminal-output.instructions.md#indentation).

Suggested change
fmt.Printf(" Deployment: %s\n", scopeOpts.DeployPattern)
fmt.Printf(" Production: %s\n", scopeOpts.ProdPattern)
fmt.Printf(" Incidents: label=%s\n", scopeOpts.IncidentLabel)
fmt.Printf(" Deployment: %s\n", scopeOpts.DeployPattern)
fmt.Printf(" Production: %s\n", scopeOpts.ProdPattern)
fmt.Printf(" Incidents: label=%s\n", scopeOpts.IncidentLabel)

Copilot uses AI. Check for mistakes.
fmt.Printf(" %-18s ID=%d %q\n", name, r.ConnectionID, r.Name)
}
fmt.Println(strings.Repeat("\u2500", 50))
fmt.Println(strings.Repeat("", 50))
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminal output standards require a blank line after separators. This summary prints a separator line, then ends with another separator but doesn’t print an empty line afterward, so subsequent output can run together. Add fmt.Println() after the closing separator (see .github/instructions/terminal-output.instructions.md#line-spacing-rules).

Suggested change
fmt.Println(strings.Repeat("─", 50))
fmt.Println(strings.Repeat("─", 50))
fmt.Println()

Copilot uses AI. Check for mistakes.
// ── Phase 3: Create Project (call inner functions directly) ──
fmt.Println("\n╔══════════════════════════════════════╗")
fmt.Println("║ PHASE 3: Project Setup ║")
fmt.Println("╚══════════════════════════════════════╝")
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phase banner is missing the required blank line after the banner frame (terminal output standards rule #5). Add a trailing fmt.Println() after the 3 banner lines.

This issue also appears in the following locations of the same file:

  • line 102
  • line 136
Suggested change
fmt.Println("╚══════════════════════════════════════╝")
fmt.Println("╚══════════════════════════════════════╝")
fmt.Println()

Copilot uses AI. Check for mistakes.
// ── Phase 1: Deploy ──────────────────────────────────────────
targets := []string{"local - Docker Compose on this machine", "azure - Azure Container Apps"}
choice := prompt.Select("Where would you like to deploy DevLake?", targets)
choice := prompt.Select("\nWhere would you like to deploy DevLake?", targets)
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid embedding leading newlines in prompt labels (e.g., "\nWhere would you like…"). The prompt package prints the label verbatim to stderr, so callers should emit spacing with a separate fmt.Println() before the prompt per terminal output standards; otherwise spacing becomes inconsistent and easy to double-up.

Suggested change
choice := prompt.Select("\nWhere would you like to deploy DevLake?", targets)
fmt.Println()
choice := prompt.Select("Where would you like to deploy DevLake?", targets)

Copilot uses AI. Check for mistakes.
break
}
}
}
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

org can still be empty here when only the GitHub connection is selected and --org wasn’t provided (GitHub connections don’t prompt for org in runConnectionsInternal). Subsequent calls (scopeGitHub/finalizeProject) use org and will produce confusing output or failures. After resolving from results, require org (prompt for it in interactive mode or return a clear error in flag mode).

Suggested change
}
}
if org == "" {
return fmt.Errorf("no GitHub organization could be determined from flags or connections; please re-run with --org or configure a connection that specifies an organization")
}

Copilot uses AI. Check for mistakes.
@ewega ewega deleted the refactor/init-wizard-interactive branch March 4, 2026 14:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants