refactor(cli): move cmd/shared to pkg/cli with runtime
Moves shared utilities (styles, utils) from cmd/shared to pkg/cli. Adds CLI runtime with global singleton pattern: - cli.Init() initialises the runtime - cli.App() returns the global instance - OutputService for styled terminal printing - SignalService for graceful shutdown handling All cmd/ packages now import pkg/cli instead of cmd/shared. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
6ed025d3e6
commit
23d399407c
31 changed files with 406 additions and 208 deletions
32
cmd/ai/ai.go
32
cmd/ai/ai.go
|
|
@ -3,35 +3,35 @@
|
|||
package ai
|
||||
|
||||
import (
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Style aliases from shared package
|
||||
var (
|
||||
successStyle = shared.SuccessStyle
|
||||
errorStyle = shared.ErrorStyle
|
||||
dimStyle = shared.DimStyle
|
||||
truncate = shared.Truncate
|
||||
formatAge = shared.FormatAge
|
||||
successStyle = cli.SuccessStyle
|
||||
errorStyle = cli.ErrorStyle
|
||||
dimStyle = cli.DimStyle
|
||||
truncate = cli.Truncate
|
||||
formatAge = cli.FormatAge
|
||||
)
|
||||
|
||||
// Task priority/status styles from shared
|
||||
var (
|
||||
taskPriorityHighStyle = shared.PriorityHighStyle
|
||||
taskPriorityMediumStyle = shared.PriorityMediumStyle
|
||||
taskPriorityLowStyle = shared.PriorityLowStyle
|
||||
taskStatusPendingStyle = shared.StatusPendingStyle
|
||||
taskStatusInProgressStyle = shared.StatusRunningStyle
|
||||
taskStatusCompletedStyle = shared.StatusSuccessStyle
|
||||
taskStatusBlockedStyle = shared.StatusErrorStyle
|
||||
taskPriorityHighStyle = cli.PriorityHighStyle
|
||||
taskPriorityMediumStyle = cli.PriorityMediumStyle
|
||||
taskPriorityLowStyle = cli.PriorityLowStyle
|
||||
taskStatusPendingStyle = cli.StatusPendingStyle
|
||||
taskStatusInProgressStyle = cli.StatusRunningStyle
|
||||
taskStatusCompletedStyle = cli.StatusSuccessStyle
|
||||
taskStatusBlockedStyle = cli.StatusErrorStyle
|
||||
)
|
||||
|
||||
// Task-specific styles (aliases to shared where possible)
|
||||
var (
|
||||
taskIDStyle = shared.TitleStyle // Bold + blue
|
||||
taskTitleStyle = shared.ValueStyle // Light gray
|
||||
taskLabelStyle = shared.AccentLabelStyle // Violet for labels
|
||||
taskIDStyle = cli.TitleStyle // Bold + blue
|
||||
taskTitleStyle = cli.ValueStyle // Light gray
|
||||
taskLabelStyle = cli.AccentLabelStyle // Violet for labels
|
||||
)
|
||||
|
||||
// AddAgenticCommands adds the agentic task management commands to the ai command.
|
||||
|
|
|
|||
|
|
@ -4,18 +4,18 @@ package build
|
|||
import (
|
||||
"embed"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Style aliases from shared package
|
||||
var (
|
||||
buildHeaderStyle = shared.TitleStyle
|
||||
buildTargetStyle = shared.ValueStyle
|
||||
buildSuccessStyle = shared.SuccessStyle
|
||||
buildErrorStyle = shared.ErrorStyle
|
||||
buildDimStyle = shared.DimStyle
|
||||
buildHeaderStyle = cli.TitleStyle
|
||||
buildTargetStyle = cli.ValueStyle
|
||||
buildSuccessStyle = cli.SuccessStyle
|
||||
buildErrorStyle = cli.ErrorStyle
|
||||
buildDimStyle = cli.DimStyle
|
||||
)
|
||||
|
||||
//go:embed all:tmpl/gui
|
||||
|
|
|
|||
|
|
@ -2,18 +2,18 @@
|
|||
package ci
|
||||
|
||||
import (
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Style aliases from shared
|
||||
var (
|
||||
releaseHeaderStyle = shared.RepoNameStyle
|
||||
releaseSuccessStyle = shared.SuccessStyle
|
||||
releaseErrorStyle = shared.ErrorStyle
|
||||
releaseDimStyle = shared.DimStyle
|
||||
releaseValueStyle = shared.ValueStyle
|
||||
releaseHeaderStyle = cli.RepoNameStyle
|
||||
releaseSuccessStyle = cli.SuccessStyle
|
||||
releaseErrorStyle = cli.ErrorStyle
|
||||
releaseDimStyle = cli.DimStyle
|
||||
releaseValueStyle = cli.ValueStyle
|
||||
)
|
||||
|
||||
// Flag variables for ci command
|
||||
|
|
|
|||
|
|
@ -19,17 +19,17 @@ package cmd
|
|||
import (
|
||||
"os"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Terminal styles using Tailwind colour palette (from shared package).
|
||||
var (
|
||||
// coreStyle is used for primary headings and the CLI name.
|
||||
coreStyle = shared.RepoNameStyle
|
||||
coreStyle = cli.RepoNameStyle
|
||||
|
||||
// linkStyle is used for URLs and clickable references.
|
||||
linkStyle = shared.LinkStyle
|
||||
linkStyle = cli.LinkStyle
|
||||
)
|
||||
|
||||
// rootCmd is the base command for the CLI.
|
||||
|
|
|
|||
|
|
@ -29,27 +29,27 @@
|
|||
package dev
|
||||
|
||||
import (
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Style aliases from shared package
|
||||
var (
|
||||
successStyle = shared.SuccessStyle
|
||||
errorStyle = shared.ErrorStyle
|
||||
warningStyle = shared.WarningStyle
|
||||
dimStyle = shared.DimStyle
|
||||
valueStyle = shared.ValueStyle
|
||||
headerStyle = shared.HeaderStyle
|
||||
repoNameStyle = shared.RepoNameStyle
|
||||
successStyle = cli.SuccessStyle
|
||||
errorStyle = cli.ErrorStyle
|
||||
warningStyle = cli.WarningStyle
|
||||
dimStyle = cli.DimStyle
|
||||
valueStyle = cli.ValueStyle
|
||||
headerStyle = cli.HeaderStyle
|
||||
repoNameStyle = cli.RepoNameStyle
|
||||
)
|
||||
|
||||
// Table styles for status display (extends shared styles with cell padding)
|
||||
var (
|
||||
dirtyStyle = shared.GitDirtyStyle.Padding(0, 1)
|
||||
aheadStyle = shared.GitAheadStyle.Padding(0, 1)
|
||||
cleanStyle = shared.GitCleanStyle.Padding(0, 1)
|
||||
dirtyStyle = cli.GitDirtyStyle.Padding(0, 1)
|
||||
aheadStyle = cli.GitAheadStyle.Padding(0, 1)
|
||||
cleanStyle = cli.GitCleanStyle.Padding(0, 1)
|
||||
)
|
||||
|
||||
// AddCommands registers the 'dev' command and all subcommands.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/host-uk/core/pkg/repos"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -16,10 +16,10 @@ import (
|
|||
|
||||
// CI-specific styles (aliases to shared)
|
||||
var (
|
||||
ciSuccessStyle = shared.SuccessStyle
|
||||
ciFailureStyle = shared.ErrorStyle
|
||||
ciPendingStyle = shared.StatusWarningStyle
|
||||
ciSkippedStyle = shared.DimStyle
|
||||
ciSuccessStyle = cli.SuccessStyle
|
||||
ciFailureStyle = cli.ErrorStyle
|
||||
ciPendingStyle = cli.StatusWarningStyle
|
||||
ciSkippedStyle = cli.DimStyle
|
||||
)
|
||||
|
||||
// WorkflowRun represents a GitHub Actions workflow run
|
||||
|
|
@ -246,10 +246,10 @@ func printWorkflowRun(run WorkflowRun) {
|
|||
}
|
||||
|
||||
// Workflow name (truncated)
|
||||
workflowName := shared.Truncate(run.Name, 20)
|
||||
workflowName := cli.Truncate(run.Name, 20)
|
||||
|
||||
// Age
|
||||
age := shared.FormatAge(run.UpdatedAt)
|
||||
age := cli.FormatAge(run.UpdatedAt)
|
||||
|
||||
fmt.Printf(" %s %-18s %-22s %s\n",
|
||||
status,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/git"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/host-uk/core/pkg/repos"
|
||||
|
|
@ -128,7 +128,7 @@ func runCommit(registryPath string, all bool) error {
|
|||
// Confirm unless --all
|
||||
if !all {
|
||||
fmt.Println()
|
||||
if !shared.Confirm(i18n.T("cmd.dev.confirm_claude_commit")) {
|
||||
if !cli.Confirm(i18n.T("cmd.dev.confirm_claude_commit")) {
|
||||
fmt.Println(i18n.T("cli.aborted"))
|
||||
return nil
|
||||
}
|
||||
|
|
@ -207,7 +207,7 @@ func runCommitSingleRepo(ctx context.Context, repoPath string, all bool) error {
|
|||
// Confirm unless --all
|
||||
if !all {
|
||||
fmt.Println()
|
||||
if !shared.Confirm(i18n.T("cmd.dev.confirm_claude_commit")) {
|
||||
if !cli.Confirm(i18n.T("cmd.dev.confirm_claude_commit")) {
|
||||
fmt.Println(i18n.T("cli.aborted"))
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"os"
|
||||
"sort"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/git"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/host-uk/core/pkg/repos"
|
||||
|
|
@ -144,36 +144,36 @@ func runHealth(registryPath string, verbose bool) error {
|
|||
|
||||
func printHealthSummary(total int, dirty, ahead, behind, errors []string) {
|
||||
parts := []string{
|
||||
shared.StatusPart(total, i18n.T("cmd.dev.health.repos"), shared.ValueStyle),
|
||||
cli.StatusPart(total, i18n.T("cmd.dev.health.repos"), cli.ValueStyle),
|
||||
}
|
||||
|
||||
// Dirty status
|
||||
if len(dirty) > 0 {
|
||||
parts = append(parts, shared.StatusPart(len(dirty), i18n.T("cmd.dev.health.dirty"), shared.WarningStyle))
|
||||
parts = append(parts, cli.StatusPart(len(dirty), i18n.T("cmd.dev.health.dirty"), cli.WarningStyle))
|
||||
} else {
|
||||
parts = append(parts, shared.StatusText(i18n.T("cmd.dev.status.clean"), shared.SuccessStyle))
|
||||
parts = append(parts, cli.StatusText(i18n.T("cmd.dev.status.clean"), cli.SuccessStyle))
|
||||
}
|
||||
|
||||
// Push status
|
||||
if len(ahead) > 0 {
|
||||
parts = append(parts, shared.StatusPart(len(ahead), i18n.T("cmd.dev.health.to_push"), shared.ValueStyle))
|
||||
parts = append(parts, cli.StatusPart(len(ahead), i18n.T("cmd.dev.health.to_push"), cli.ValueStyle))
|
||||
} else {
|
||||
parts = append(parts, shared.StatusText(i18n.T("cmd.dev.health.synced"), shared.SuccessStyle))
|
||||
parts = append(parts, cli.StatusText(i18n.T("cmd.dev.health.synced"), cli.SuccessStyle))
|
||||
}
|
||||
|
||||
// Pull status
|
||||
if len(behind) > 0 {
|
||||
parts = append(parts, shared.StatusPart(len(behind), i18n.T("cmd.dev.health.to_pull"), shared.WarningStyle))
|
||||
parts = append(parts, cli.StatusPart(len(behind), i18n.T("cmd.dev.health.to_pull"), cli.WarningStyle))
|
||||
} else {
|
||||
parts = append(parts, shared.StatusText(i18n.T("cmd.dev.health.up_to_date"), shared.SuccessStyle))
|
||||
parts = append(parts, cli.StatusText(i18n.T("cmd.dev.health.up_to_date"), cli.SuccessStyle))
|
||||
}
|
||||
|
||||
// Errors (only if any)
|
||||
if len(errors) > 0 {
|
||||
parts = append(parts, shared.StatusPart(len(errors), i18n.T("cmd.dev.health.errors"), shared.ErrorStyle))
|
||||
parts = append(parts, cli.StatusPart(len(errors), i18n.T("cmd.dev.health.errors"), cli.ErrorStyle))
|
||||
}
|
||||
|
||||
fmt.Println(shared.StatusLine(parts...))
|
||||
fmt.Println(cli.StatusLine(parts...))
|
||||
}
|
||||
|
||||
func formatRepoList(reposList []string) string {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/host-uk/core/pkg/repos"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -12,9 +12,9 @@ import (
|
|||
|
||||
// Impact-specific styles (aliases to shared)
|
||||
var (
|
||||
impactDirectStyle = shared.ErrorStyle
|
||||
impactIndirectStyle = shared.StatusWarningStyle
|
||||
impactSafeStyle = shared.StatusSuccessStyle
|
||||
impactDirectStyle = cli.ErrorStyle
|
||||
impactIndirectStyle = cli.StatusWarningStyle
|
||||
impactSafeStyle = cli.StatusSuccessStyle
|
||||
)
|
||||
|
||||
// Impact command flags
|
||||
|
|
@ -112,7 +112,7 @@ func runImpact(registryPath string, repoName string) error {
|
|||
r, _ := reg.Get(d)
|
||||
desc := ""
|
||||
if r != nil && r.Description != "" {
|
||||
desc = dimStyle.Render(" - " + shared.Truncate(r.Description, 40))
|
||||
desc = dimStyle.Render(" - " + cli.Truncate(r.Description, 40))
|
||||
}
|
||||
fmt.Printf(" %s%s\n", d, desc)
|
||||
}
|
||||
|
|
@ -129,7 +129,7 @@ func runImpact(registryPath string, repoName string) error {
|
|||
r, _ := reg.Get(d)
|
||||
desc := ""
|
||||
if r != nil && r.Description != "" {
|
||||
desc = dimStyle.Render(" - " + shared.Truncate(r.Description, 40))
|
||||
desc = dimStyle.Render(" - " + cli.Truncate(r.Description, 40))
|
||||
}
|
||||
fmt.Printf(" %s%s\n", d, desc)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/host-uk/core/pkg/repos"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -17,12 +17,12 @@ import (
|
|||
|
||||
// Issue-specific styles (aliases to shared)
|
||||
var (
|
||||
issueRepoStyle = shared.DimStyle
|
||||
issueNumberStyle = shared.TitleStyle
|
||||
issueTitleStyle = shared.ValueStyle
|
||||
issueLabelStyle = shared.WarningStyle
|
||||
issueAssigneeStyle = shared.StatusSuccessStyle
|
||||
issueAgeStyle = shared.DimStyle
|
||||
issueRepoStyle = cli.DimStyle
|
||||
issueNumberStyle = cli.TitleStyle
|
||||
issueTitleStyle = cli.ValueStyle
|
||||
issueLabelStyle = cli.WarningStyle
|
||||
issueAssigneeStyle = cli.StatusSuccessStyle
|
||||
issueAgeStyle = cli.DimStyle
|
||||
)
|
||||
|
||||
// GitHubIssue represents a GitHub issue from the API.
|
||||
|
|
@ -201,7 +201,7 @@ func printIssue(issue GitHubIssue) {
|
|||
// #42 [core-bio] Fix avatar upload
|
||||
num := issueNumberStyle.Render(fmt.Sprintf("#%d", issue.Number))
|
||||
repo := issueRepoStyle.Render(fmt.Sprintf("[%s]", issue.RepoName))
|
||||
title := issueTitleStyle.Render(shared.Truncate(issue.Title, 60))
|
||||
title := issueTitleStyle.Render(cli.Truncate(issue.Title, 60))
|
||||
|
||||
line := fmt.Sprintf(" %s %s %s", num, repo, title)
|
||||
|
||||
|
|
@ -224,7 +224,7 @@ func printIssue(issue GitHubIssue) {
|
|||
}
|
||||
|
||||
// Add age
|
||||
age := shared.FormatAge(issue.CreatedAt)
|
||||
age := cli.FormatAge(issue.CreatedAt)
|
||||
line += " " + issueAgeStyle.Render(age)
|
||||
|
||||
fmt.Println(line)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/git"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/host-uk/core/pkg/repos"
|
||||
|
|
@ -122,7 +122,7 @@ func runPush(registryPath string, force bool) error {
|
|||
// Confirm unless --force
|
||||
if !force {
|
||||
fmt.Println()
|
||||
if !shared.Confirm(i18n.T("cmd.dev.push.confirm_push", map[string]interface{}{"Commits": totalCommits, "Repos": len(aheadRepos)})) {
|
||||
if !cli.Confirm(i18n.T("cmd.dev.push.confirm_push", map[string]interface{}{"Commits": totalCommits, "Repos": len(aheadRepos)})) {
|
||||
fmt.Println(i18n.T("cli.aborted"))
|
||||
return nil
|
||||
}
|
||||
|
|
@ -161,7 +161,7 @@ func runPush(registryPath string, force bool) error {
|
|||
if len(divergedRepos) > 0 {
|
||||
fmt.Println()
|
||||
fmt.Printf("%s\n", i18n.T("cmd.dev.push.diverged_help"))
|
||||
if shared.Confirm(i18n.T("cmd.dev.push.pull_and_retry")) {
|
||||
if cli.Confirm(i18n.T("cmd.dev.push.pull_and_retry")) {
|
||||
fmt.Println()
|
||||
for _, r := range divergedRepos {
|
||||
fmt.Printf(" %s %s...\n", dimStyle.Render("↓"), r.Name)
|
||||
|
|
@ -226,7 +226,7 @@ func runPushSingleRepo(ctx context.Context, repoPath string, force bool) error {
|
|||
}
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
if shared.Confirm(i18n.T("cmd.dev.push.uncommitted_changes_commit")) {
|
||||
if cli.Confirm(i18n.T("cmd.dev.push.uncommitted_changes_commit")) {
|
||||
fmt.Println()
|
||||
// Use edit-enabled commit if only untracked files (may need .gitignore fix)
|
||||
var err error
|
||||
|
|
@ -260,7 +260,7 @@ func runPushSingleRepo(ctx context.Context, repoPath string, force bool) error {
|
|||
// Confirm unless --force
|
||||
if !force {
|
||||
fmt.Println()
|
||||
if !shared.Confirm(i18n.T("cmd.dev.push.confirm_push", map[string]interface{}{"Commits": s.Ahead, "Repos": 1})) {
|
||||
if !cli.Confirm(i18n.T("cmd.dev.push.confirm_push", map[string]interface{}{"Commits": s.Ahead, "Repos": 1})) {
|
||||
fmt.Println(i18n.T("cli.aborted"))
|
||||
return nil
|
||||
}
|
||||
|
|
@ -275,7 +275,7 @@ func runPushSingleRepo(ctx context.Context, repoPath string, force bool) error {
|
|||
fmt.Printf(" %s %s: %s\n", warningStyle.Render("!"), repoName, i18n.T("cmd.dev.push.diverged"))
|
||||
fmt.Println()
|
||||
fmt.Printf("%s\n", i18n.T("cmd.dev.push.diverged_help"))
|
||||
if shared.Confirm(i18n.T("cmd.dev.push.pull_and_retry")) {
|
||||
if cli.Confirm(i18n.T("cmd.dev.push.pull_and_retry")) {
|
||||
fmt.Println()
|
||||
fmt.Printf(" %s %s...\n", dimStyle.Render("↓"), repoName)
|
||||
if pullErr := git.Pull(ctx, repoPath); pullErr != nil {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/host-uk/core/pkg/repos"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -17,13 +17,13 @@ import (
|
|||
|
||||
// PR-specific styles (aliases to shared)
|
||||
var (
|
||||
prNumberStyle = shared.PrNumberStyle
|
||||
prTitleStyle = shared.ValueStyle
|
||||
prAuthorStyle = shared.InfoStyle
|
||||
prApprovedStyle = shared.SuccessStyle
|
||||
prChangesStyle = shared.WarningStyle
|
||||
prPendingStyle = shared.DimStyle
|
||||
prDraftStyle = shared.DimStyle
|
||||
prNumberStyle = cli.PrNumberStyle
|
||||
prTitleStyle = cli.ValueStyle
|
||||
prAuthorStyle = cli.InfoStyle
|
||||
prApprovedStyle = cli.SuccessStyle
|
||||
prChangesStyle = cli.WarningStyle
|
||||
prPendingStyle = cli.DimStyle
|
||||
prDraftStyle = cli.DimStyle
|
||||
)
|
||||
|
||||
// GitHubPR represents a GitHub pull request.
|
||||
|
|
@ -234,7 +234,7 @@ func printPR(pr GitHubPR) {
|
|||
// #12 [core-php] Webhook validation
|
||||
num := prNumberStyle.Render(fmt.Sprintf("#%d", pr.Number))
|
||||
repo := issueRepoStyle.Render(fmt.Sprintf("[%s]", pr.RepoName))
|
||||
title := prTitleStyle.Render(shared.Truncate(pr.Title, 50))
|
||||
title := prTitleStyle.Render(cli.Truncate(pr.Title, 50))
|
||||
author := prAuthorStyle.Render("@" + pr.Author.Login)
|
||||
|
||||
// Review status
|
||||
|
|
@ -254,7 +254,7 @@ func printPR(pr GitHubPR) {
|
|||
draft = prDraftStyle.Render(" " + i18n.T("cmd.dev.reviews.draft"))
|
||||
}
|
||||
|
||||
age := shared.FormatAge(pr.CreatedAt)
|
||||
age := cli.FormatAge(pr.CreatedAt)
|
||||
|
||||
fmt.Printf(" %s %s %s%s %s %s %s\n", num, repo, title, draft, author, status, issueAgeStyle.Render(age))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/agentic"
|
||||
"github.com/host-uk/core/pkg/git"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
|
|
@ -109,7 +109,7 @@ func runWork(registryPath string, statusOnly, autoCommit bool) error {
|
|||
// Auto-commit dirty repos if requested
|
||||
if autoCommit && len(dirtyRepos) > 0 {
|
||||
fmt.Println()
|
||||
fmt.Printf("%s\n", shared.TitleStyle.Render(i18n.T("cmd.dev.commit.committing")))
|
||||
fmt.Printf("%s\n", cli.TitleStyle.Render(i18n.T("cmd.dev.commit.committing")))
|
||||
fmt.Println()
|
||||
|
||||
for _, s := range dirtyRepos {
|
||||
|
|
@ -168,7 +168,7 @@ func runWork(registryPath string, statusOnly, autoCommit bool) error {
|
|||
}
|
||||
|
||||
fmt.Println()
|
||||
if !shared.Confirm(i18n.T("cmd.dev.push.confirm")) {
|
||||
if !cli.Confirm(i18n.T("cmd.dev.push.confirm")) {
|
||||
fmt.Println(i18n.T("cli.aborted"))
|
||||
return nil
|
||||
}
|
||||
|
|
@ -203,7 +203,7 @@ func runWork(registryPath string, statusOnly, autoCommit bool) error {
|
|||
if len(divergedRepos) > 0 {
|
||||
fmt.Println()
|
||||
fmt.Printf("%s\n", i18n.T("cmd.dev.push.diverged_help"))
|
||||
if shared.Confirm(i18n.T("cmd.dev.push.pull_and_retry")) {
|
||||
if cli.Confirm(i18n.T("cmd.dev.push.pull_and_retry")) {
|
||||
fmt.Println()
|
||||
for _, s := range divergedRepos {
|
||||
fmt.Printf(" %s %s...\n", dimStyle.Render("↓"), s.Name)
|
||||
|
|
@ -244,11 +244,11 @@ func printStatusTable(statuses []git.RepoStatus) {
|
|||
// Print header with fixed-width formatting
|
||||
fmt.Printf("%-*s %8s %9s %6s %5s\n",
|
||||
nameWidth,
|
||||
shared.TitleStyle.Render(i18n.T("cmd.dev.work.table_repo")),
|
||||
shared.TitleStyle.Render(i18n.T("cmd.dev.work.table_modified")),
|
||||
shared.TitleStyle.Render(i18n.T("cmd.dev.work.table_untracked")),
|
||||
shared.TitleStyle.Render(i18n.T("cmd.dev.work.table_staged")),
|
||||
shared.TitleStyle.Render(i18n.T("cmd.dev.work.table_ahead")),
|
||||
cli.TitleStyle.Render(i18n.T("cmd.dev.work.table_repo")),
|
||||
cli.TitleStyle.Render(i18n.T("cmd.dev.work.table_modified")),
|
||||
cli.TitleStyle.Render(i18n.T("cmd.dev.work.table_untracked")),
|
||||
cli.TitleStyle.Render(i18n.T("cmd.dev.work.table_staged")),
|
||||
cli.TitleStyle.Render(i18n.T("cmd.dev.work.table_ahead")),
|
||||
)
|
||||
|
||||
// Print separator
|
||||
|
|
|
|||
|
|
@ -2,22 +2,22 @@
|
|||
package docs
|
||||
|
||||
import (
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Style and utility aliases from shared
|
||||
var (
|
||||
repoNameStyle = shared.RepoNameStyle
|
||||
successStyle = shared.SuccessStyle
|
||||
errorStyle = shared.ErrorStyle
|
||||
dimStyle = shared.DimStyle
|
||||
headerStyle = shared.HeaderStyle
|
||||
confirm = shared.Confirm
|
||||
docsFoundStyle = shared.SuccessStyle
|
||||
docsMissingStyle = shared.DimStyle
|
||||
docsFileStyle = shared.InfoStyle
|
||||
repoNameStyle = cli.RepoNameStyle
|
||||
successStyle = cli.SuccessStyle
|
||||
errorStyle = cli.ErrorStyle
|
||||
dimStyle = cli.DimStyle
|
||||
headerStyle = cli.HeaderStyle
|
||||
confirm = cli.Confirm
|
||||
docsFoundStyle = cli.SuccessStyle
|
||||
docsMissingStyle = cli.DimStyle
|
||||
docsFileStyle = cli.InfoStyle
|
||||
)
|
||||
|
||||
var docsCmd = &cobra.Command{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
@ -44,11 +44,11 @@ func runDocsList(registryPath string) error {
|
|||
for _, repo := range reg.List() {
|
||||
info := scanRepoDocs(repo)
|
||||
|
||||
readme := shared.CheckMark(info.Readme != "")
|
||||
claude := shared.CheckMark(info.ClaudeMd != "")
|
||||
changelog := shared.CheckMark(info.Changelog != "")
|
||||
readme := cli.CheckMark(info.Readme != "")
|
||||
claude := cli.CheckMark(info.ClaudeMd != "")
|
||||
changelog := cli.CheckMark(info.Changelog != "")
|
||||
|
||||
docsDir := shared.CheckMark(false)
|
||||
docsDir := cli.CheckMark(false)
|
||||
if len(info.DocsFiles) > 0 {
|
||||
docsDir = docsFoundStyle.Render(i18n.T("cmd.docs.list.files_count", map[string]interface{}{"Count": len(info.DocsFiles)}))
|
||||
}
|
||||
|
|
@ -70,7 +70,7 @@ func runDocsList(registryPath string) error {
|
|||
|
||||
fmt.Println()
|
||||
fmt.Printf("%s %s\n",
|
||||
shared.Label(i18n.T("cmd.docs.list.coverage_label")),
|
||||
cli.Label(i18n.T("cmd.docs.list.coverage_label")),
|
||||
i18n.T("cmd.docs.list.coverage_summary", map[string]interface{}{"WithDocs": withDocs, "WithoutDocs": withoutDocs}),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,16 +4,16 @@ package doctor
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Style aliases from shared
|
||||
var (
|
||||
successStyle = shared.SuccessStyle
|
||||
errorStyle = shared.ErrorStyle
|
||||
dimStyle = shared.DimStyle
|
||||
successStyle = cli.SuccessStyle
|
||||
errorStyle = cli.ErrorStyle
|
||||
dimStyle = cli.DimStyle
|
||||
)
|
||||
|
||||
// Flag variable for doctor command
|
||||
|
|
@ -44,13 +44,13 @@ func runDoctor(verbose bool) error {
|
|||
ok, version := runCheck(c)
|
||||
if ok {
|
||||
if verbose {
|
||||
fmt.Println(shared.CheckResult(true, c.name, version))
|
||||
fmt.Println(cli.CheckResult(true, c.name, version))
|
||||
} else {
|
||||
fmt.Println(shared.CheckResult(true, c.name, ""))
|
||||
fmt.Println(cli.CheckResult(true, c.name, ""))
|
||||
}
|
||||
passed++
|
||||
} else {
|
||||
fmt.Printf(" %s %s - %s\n", errorStyle.Render(shared.SymbolCross), c.name, c.description)
|
||||
fmt.Printf(" %s %s - %s\n", errorStyle.Render(cli.SymbolCross), c.name, c.description)
|
||||
failed++
|
||||
}
|
||||
}
|
||||
|
|
@ -61,13 +61,13 @@ func runDoctor(verbose bool) error {
|
|||
ok, version := runCheck(c)
|
||||
if ok {
|
||||
if verbose {
|
||||
fmt.Println(shared.CheckResult(true, c.name, version))
|
||||
fmt.Println(cli.CheckResult(true, c.name, version))
|
||||
} else {
|
||||
fmt.Println(shared.CheckResult(true, c.name, ""))
|
||||
fmt.Println(cli.CheckResult(true, c.name, ""))
|
||||
}
|
||||
passed++
|
||||
} else {
|
||||
fmt.Printf(" %s %s - %s\n", dimStyle.Render(shared.SymbolSkip), c.name, dimStyle.Render(c.description))
|
||||
fmt.Printf(" %s %s - %s\n", dimStyle.Render(cli.SymbolSkip), c.name, dimStyle.Render(c.description))
|
||||
optional++
|
||||
}
|
||||
}
|
||||
|
|
@ -75,16 +75,16 @@ func runDoctor(verbose bool) error {
|
|||
// Check GitHub access
|
||||
fmt.Printf("\n%s\n", i18n.T("cmd.doctor.github"))
|
||||
if checkGitHubSSH() {
|
||||
fmt.Println(shared.CheckResult(true, i18n.T("cmd.doctor.ssh_found"), ""))
|
||||
fmt.Println(cli.CheckResult(true, i18n.T("cmd.doctor.ssh_found"), ""))
|
||||
} else {
|
||||
fmt.Printf(" %s %s\n", errorStyle.Render(shared.SymbolCross), i18n.T("cmd.doctor.ssh_missing"))
|
||||
fmt.Printf(" %s %s\n", errorStyle.Render(cli.SymbolCross), i18n.T("cmd.doctor.ssh_missing"))
|
||||
failed++
|
||||
}
|
||||
|
||||
if checkGitHubCLI() {
|
||||
fmt.Println(shared.CheckResult(true, i18n.T("cmd.doctor.cli_auth"), ""))
|
||||
fmt.Println(cli.CheckResult(true, i18n.T("cmd.doctor.cli_auth"), ""))
|
||||
} else {
|
||||
fmt.Printf(" %s %s\n", errorStyle.Render(shared.SymbolCross), i18n.T("cmd.doctor.cli_auth_missing"))
|
||||
fmt.Printf(" %s %s\n", errorStyle.Render(cli.SymbolCross), i18n.T("cmd.doctor.cli_auth_missing"))
|
||||
failed++
|
||||
}
|
||||
|
||||
|
|
@ -95,12 +95,12 @@ func runDoctor(verbose bool) error {
|
|||
// Summary
|
||||
fmt.Println()
|
||||
if failed > 0 {
|
||||
fmt.Println(shared.Error(i18n.T("cmd.doctor.issues", map[string]interface{}{"Count": failed})))
|
||||
fmt.Println(cli.Error(i18n.T("cmd.doctor.issues", map[string]interface{}{"Count": failed})))
|
||||
fmt.Printf("\n%s\n", i18n.T("cmd.doctor.install_missing"))
|
||||
printInstallInstructions()
|
||||
return fmt.Errorf("%s", i18n.T("cmd.doctor.issues_error", map[string]interface{}{"Count": failed}))
|
||||
}
|
||||
|
||||
fmt.Println(shared.Success(i18n.T("cmd.doctor.ready")))
|
||||
fmt.Println(cli.Success(i18n.T("cmd.doctor.ready")))
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,16 +4,16 @@
|
|||
package gocmd
|
||||
|
||||
import (
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Style aliases for shared styles
|
||||
var (
|
||||
successStyle = shared.SuccessStyle
|
||||
errorStyle = shared.ErrorStyle
|
||||
dimStyle = shared.DimStyle
|
||||
successStyle = cli.SuccessStyle
|
||||
errorStyle = cli.ErrorStyle
|
||||
dimStyle = cli.DimStyle
|
||||
)
|
||||
|
||||
// AddGoCommands adds Go development commands.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
@ -119,7 +119,7 @@ func runGoTest(coverage bool, pkg, run string, short, race, jsonOut, verbose boo
|
|||
}
|
||||
|
||||
if cov > 0 {
|
||||
fmt.Printf("\n %s %s\n", shared.ProgressLabel(i18n.T("cmd.go.test.coverage")), shared.FormatCoverage(cov))
|
||||
fmt.Printf("\n %s %s\n", cli.ProgressLabel(i18n.T("cmd.go.test.coverage")), cli.FormatCoverage(cov))
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
|
|
@ -241,7 +241,7 @@ func addGoCovCommand(parent *cobra.Command) {
|
|||
|
||||
// Print coverage summary
|
||||
fmt.Println()
|
||||
fmt.Printf(" %s %s\n", shared.ProgressLabel(i18n.T("label.total")), shared.FormatCoverage(totalCov))
|
||||
fmt.Printf(" %s %s\n", cli.ProgressLabel(i18n.T("label.total")), cli.FormatCoverage(totalCov))
|
||||
|
||||
// Generate HTML if requested
|
||||
if covHTML || covOpen {
|
||||
|
|
|
|||
|
|
@ -3,49 +3,49 @@ package php
|
|||
|
||||
import (
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Style aliases from shared
|
||||
var (
|
||||
successStyle = shared.SuccessStyle
|
||||
errorStyle = shared.ErrorStyle
|
||||
dimStyle = shared.DimStyle
|
||||
linkStyle = shared.LinkStyle
|
||||
successStyle = cli.SuccessStyle
|
||||
errorStyle = cli.ErrorStyle
|
||||
dimStyle = cli.DimStyle
|
||||
linkStyle = cli.LinkStyle
|
||||
)
|
||||
|
||||
// Service colors for log output (domain-specific, keep local)
|
||||
var (
|
||||
phpFrankenPHPStyle = lipgloss.NewStyle().Foreground(shared.ColourIndigo500)
|
||||
phpViteStyle = lipgloss.NewStyle().Foreground(shared.ColourYellow500)
|
||||
phpHorizonStyle = lipgloss.NewStyle().Foreground(shared.ColourOrange500)
|
||||
phpReverbStyle = lipgloss.NewStyle().Foreground(shared.ColourViolet500)
|
||||
phpRedisStyle = lipgloss.NewStyle().Foreground(shared.ColourRed500)
|
||||
phpFrankenPHPStyle = lipgloss.NewStyle().Foreground(cli.ColourIndigo500)
|
||||
phpViteStyle = lipgloss.NewStyle().Foreground(cli.ColourYellow500)
|
||||
phpHorizonStyle = lipgloss.NewStyle().Foreground(cli.ColourOrange500)
|
||||
phpReverbStyle = lipgloss.NewStyle().Foreground(cli.ColourViolet500)
|
||||
phpRedisStyle = lipgloss.NewStyle().Foreground(cli.ColourRed500)
|
||||
)
|
||||
|
||||
// Status styles (from shared)
|
||||
var (
|
||||
phpStatusRunning = shared.SuccessStyle
|
||||
phpStatusStopped = shared.StatusPendingStyle
|
||||
phpStatusError = shared.ErrorStyle
|
||||
phpStatusRunning = cli.SuccessStyle
|
||||
phpStatusStopped = cli.StatusPendingStyle
|
||||
phpStatusError = cli.ErrorStyle
|
||||
)
|
||||
|
||||
// QA command styles (from shared)
|
||||
var (
|
||||
phpQAPassedStyle = shared.SuccessStyle
|
||||
phpQAFailedStyle = shared.ErrorStyle
|
||||
phpQAWarningStyle = shared.WarningStyle
|
||||
phpQAStageStyle = shared.StageStyle
|
||||
phpQAPassedStyle = cli.SuccessStyle
|
||||
phpQAFailedStyle = cli.ErrorStyle
|
||||
phpQAWarningStyle = cli.WarningStyle
|
||||
phpQAStageStyle = cli.StageStyle
|
||||
)
|
||||
|
||||
// Security severity styles (from shared)
|
||||
var (
|
||||
phpSecurityCriticalStyle = shared.SeverityCriticalStyle
|
||||
phpSecurityHighStyle = shared.SeverityHighStyle
|
||||
phpSecurityMediumStyle = shared.SeverityMediumStyle
|
||||
phpSecurityLowStyle = shared.SeverityLowStyle
|
||||
phpSecurityCriticalStyle = cli.SeverityCriticalStyle
|
||||
phpSecurityHighStyle = cli.SeverityHighStyle
|
||||
phpSecurityMediumStyle = cli.SeverityMediumStyle
|
||||
phpSecurityLowStyle = cli.SeverityLowStyle
|
||||
)
|
||||
|
||||
// AddPHPCommands adds PHP/Laravel development commands.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
phppkg "github.com/host-uk/core/pkg/php"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -14,9 +14,9 @@ import (
|
|||
|
||||
// Deploy command styles (aliases to shared)
|
||||
var (
|
||||
phpDeployStyle = shared.DeploySuccessStyle
|
||||
phpDeployPendingStyle = shared.StatusWarningStyle
|
||||
phpDeployFailedStyle = shared.StatusErrorStyle
|
||||
phpDeployStyle = cli.DeploySuccessStyle
|
||||
phpDeployPendingStyle = cli.StatusWarningStyle
|
||||
phpDeployFailedStyle = cli.StatusErrorStyle
|
||||
)
|
||||
|
||||
func addPHPDeployCommands(parent *cobra.Command) {
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@
|
|||
package pkg
|
||||
|
||||
import (
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Style and utility aliases
|
||||
var (
|
||||
repoNameStyle = shared.RepoNameStyle
|
||||
successStyle = shared.SuccessStyle
|
||||
errorStyle = shared.ErrorStyle
|
||||
dimStyle = shared.DimStyle
|
||||
ghAuthenticated = shared.GhAuthenticated
|
||||
gitClone = shared.GitClone
|
||||
repoNameStyle = cli.RepoNameStyle
|
||||
successStyle = cli.SuccessStyle
|
||||
errorStyle = cli.ErrorStyle
|
||||
dimStyle = cli.DimStyle
|
||||
ghAuthenticated = cli.GhAuthenticated
|
||||
gitClone = cli.GitClone
|
||||
)
|
||||
|
||||
// AddPkgCommands adds the 'pkg' command and subcommands for package management.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
sdkpkg "github.com/host-uk/core/pkg/sdk"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -13,10 +13,10 @@ import (
|
|||
|
||||
// SDK styles (aliases to shared)
|
||||
var (
|
||||
sdkHeaderStyle = shared.TitleStyle
|
||||
sdkSuccessStyle = shared.SuccessStyle
|
||||
sdkErrorStyle = shared.ErrorStyle
|
||||
sdkDimStyle = shared.DimStyle
|
||||
sdkHeaderStyle = cli.TitleStyle
|
||||
sdkSuccessStyle = cli.SuccessStyle
|
||||
sdkErrorStyle = cli.ErrorStyle
|
||||
sdkDimStyle = cli.DimStyle
|
||||
)
|
||||
|
||||
var sdkCmd = &cobra.Command{
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@
|
|||
package setup
|
||||
|
||||
import (
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Style aliases from shared package
|
||||
var (
|
||||
repoNameStyle = shared.RepoNameStyle
|
||||
successStyle = shared.SuccessStyle
|
||||
errorStyle = shared.ErrorStyle
|
||||
dimStyle = shared.DimStyle
|
||||
repoNameStyle = cli.RepoNameStyle
|
||||
successStyle = cli.SuccessStyle
|
||||
errorStyle = cli.ErrorStyle
|
||||
dimStyle = cli.DimStyle
|
||||
)
|
||||
|
||||
// Default organization and devops repo for bootstrap
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/host-uk/core/pkg/repos"
|
||||
)
|
||||
|
|
@ -216,7 +216,7 @@ func runRegistrySetupWithReg(ctx context.Context, reg *repos.Registry, registryP
|
|||
// gitClone clones a repository using gh CLI or git.
|
||||
func gitClone(ctx context.Context, org, repo, path string) error {
|
||||
// Try gh clone first with HTTPS (works without SSH keys)
|
||||
if shared.GhAuthenticated() {
|
||||
if cli.GhAuthenticated() {
|
||||
// Use HTTPS URL directly to bypass git_protocol config
|
||||
httpsURL := fmt.Sprintf("https://github.com/%s/%s.git", org, repo)
|
||||
cmd := exec.CommandContext(ctx, "gh", "repo", "clone", httpsURL, path)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/charmbracelet/huh"
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/host-uk/core/pkg/repos"
|
||||
"golang.org/x/term"
|
||||
|
|
@ -157,7 +157,7 @@ func runPackageWizard(reg *repos.Registry, preselectedTypes []string) ([]string,
|
|||
var selected []string
|
||||
|
||||
// Header styling
|
||||
headerStyle := shared.TitleStyle.MarginBottom(1)
|
||||
headerStyle := cli.TitleStyle.MarginBottom(1)
|
||||
|
||||
fmt.Println(headerStyle.Render(i18n.T("cmd.setup.wizard.package_selection")))
|
||||
fmt.Println(i18n.T("cmd.setup.wizard.selection_hint"))
|
||||
|
|
|
|||
|
|
@ -4,21 +4,21 @@
|
|||
package testcmd
|
||||
|
||||
import (
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Style aliases from shared
|
||||
var (
|
||||
testHeaderStyle = shared.RepoNameStyle
|
||||
testPassStyle = shared.SuccessStyle
|
||||
testFailStyle = shared.ErrorStyle
|
||||
testSkipStyle = shared.WarningStyle
|
||||
testDimStyle = shared.DimStyle
|
||||
testCovHighStyle = shared.CoverageHighStyle
|
||||
testCovMedStyle = shared.CoverageMedStyle
|
||||
testCovLowStyle = shared.CoverageLowStyle
|
||||
testHeaderStyle = cli.RepoNameStyle
|
||||
testPassStyle = cli.SuccessStyle
|
||||
testFailStyle = cli.ErrorStyle
|
||||
testSkipStyle = cli.WarningStyle
|
||||
testDimStyle = cli.DimStyle
|
||||
testCovHighStyle = cli.CoverageHighStyle
|
||||
testCovMedStyle = cli.CoverageMedStyle
|
||||
testCovLowStyle = cli.CoverageLowStyle
|
||||
)
|
||||
|
||||
// Flag variables for test command
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
)
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ func printCoverageSummary(results testResults) {
|
|||
}
|
||||
|
||||
func formatCoverage(cov float64) string {
|
||||
return shared.FormatCoverage(cov)
|
||||
return cli.FormatCoverage(cov)
|
||||
}
|
||||
|
||||
func shortenPackageName(name string) string {
|
||||
|
|
|
|||
14
cmd/vm/vm.go
14
cmd/vm/vm.go
|
|
@ -3,23 +3,23 @@ package vm
|
|||
|
||||
import (
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/host-uk/core/cmd/shared"
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Style aliases from shared
|
||||
var (
|
||||
repoNameStyle = shared.RepoNameStyle
|
||||
successStyle = shared.SuccessStyle
|
||||
errorStyle = shared.ErrorStyle
|
||||
dimStyle = shared.DimStyle
|
||||
repoNameStyle = cli.RepoNameStyle
|
||||
successStyle = cli.SuccessStyle
|
||||
errorStyle = cli.ErrorStyle
|
||||
dimStyle = cli.DimStyle
|
||||
)
|
||||
|
||||
// VM-specific styles
|
||||
var (
|
||||
varStyle = lipgloss.NewStyle().Foreground(shared.ColourAmber500)
|
||||
defaultStyle = lipgloss.NewStyle().Foreground(shared.ColourGray500).Italic(true)
|
||||
varStyle = lipgloss.NewStyle().Foreground(cli.ColourAmber500)
|
||||
defaultStyle = lipgloss.NewStyle().Foreground(cli.ColourGray500).Italic(true)
|
||||
)
|
||||
|
||||
// AddVMCommands adds container-related commands under 'vm' to the CLI.
|
||||
|
|
|
|||
198
pkg/cli/runtime.go
Normal file
198
pkg/cli/runtime.go
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
// Package cli provides the CLI runtime and utilities.
|
||||
//
|
||||
// The CLI uses the Core framework for its own runtime, providing:
|
||||
// - Global singleton access via cli.App()
|
||||
// - Output service for styled terminal printing
|
||||
// - Signal handling for graceful shutdown
|
||||
// - Worker bundle spawning for commands
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/host-uk/core/pkg/framework"
|
||||
)
|
||||
|
||||
var (
|
||||
instance *Runtime
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
// Runtime is the CLI's Core runtime.
|
||||
type Runtime struct {
|
||||
Core *framework.Core
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
// RuntimeOptions configures the CLI runtime.
|
||||
type RuntimeOptions struct {
|
||||
// AppName is the CLI application name (used in output)
|
||||
AppName string
|
||||
// Version is the CLI version string
|
||||
Version string
|
||||
}
|
||||
|
||||
// Init initialises the global CLI runtime.
|
||||
// Call this once at startup (typically in main.go).
|
||||
func Init(opts RuntimeOptions) error {
|
||||
var initErr error
|
||||
once.Do(func() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
core, err := framework.New(
|
||||
framework.WithService(NewOutputService(OutputServiceOptions{
|
||||
AppName: opts.AppName,
|
||||
})),
|
||||
framework.WithService(NewSignalService(SignalServiceOptions{
|
||||
Cancel: cancel,
|
||||
})),
|
||||
framework.WithServiceLock(),
|
||||
)
|
||||
if err != nil {
|
||||
initErr = err
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
|
||||
instance = &Runtime{
|
||||
Core: core,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
|
||||
// Start services
|
||||
if err := core.ServiceStartup(ctx, nil); err != nil {
|
||||
initErr = err
|
||||
return
|
||||
}
|
||||
})
|
||||
return initErr
|
||||
}
|
||||
|
||||
// App returns the global CLI runtime.
|
||||
// Panics if Init() hasn't been called.
|
||||
func App() *Runtime {
|
||||
if instance == nil {
|
||||
panic("cli.App() called before cli.Init()")
|
||||
}
|
||||
return instance
|
||||
}
|
||||
|
||||
// Context returns the CLI's root context.
|
||||
// This context is cancelled on shutdown signals.
|
||||
func (r *Runtime) Context() context.Context {
|
||||
return r.ctx
|
||||
}
|
||||
|
||||
// Shutdown gracefully shuts down the CLI runtime.
|
||||
func (r *Runtime) Shutdown() {
|
||||
r.cancel()
|
||||
r.Core.ServiceShutdown(r.ctx)
|
||||
}
|
||||
|
||||
// Output returns the output service for styled printing.
|
||||
func (r *Runtime) Output() *OutputService {
|
||||
return framework.MustServiceFor[*OutputService](r.Core, "output")
|
||||
}
|
||||
|
||||
// --- Output Service ---
|
||||
|
||||
// OutputServiceOptions configures the output service.
|
||||
type OutputServiceOptions struct {
|
||||
AppName string
|
||||
}
|
||||
|
||||
// OutputService provides styled terminal output.
|
||||
type OutputService struct {
|
||||
*framework.ServiceRuntime[OutputServiceOptions]
|
||||
}
|
||||
|
||||
// NewOutputService creates an output service factory.
|
||||
func NewOutputService(opts OutputServiceOptions) func(*framework.Core) (any, error) {
|
||||
return func(c *framework.Core) (any, error) {
|
||||
return &OutputService{
|
||||
ServiceRuntime: framework.NewServiceRuntime(c, opts),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Success prints a success message with checkmark.
|
||||
func (s *OutputService) Success(msg string) {
|
||||
fmt.Println(SuccessStyle.Render(SymbolCheck + " " + msg))
|
||||
}
|
||||
|
||||
// Error prints an error message with cross.
|
||||
func (s *OutputService) Error(msg string) {
|
||||
fmt.Println(ErrorStyle.Render(SymbolCross + " " + msg))
|
||||
}
|
||||
|
||||
// Warning prints a warning message.
|
||||
func (s *OutputService) Warning(msg string) {
|
||||
fmt.Println(WarningStyle.Render(SymbolWarning + " " + msg))
|
||||
}
|
||||
|
||||
// Info prints an info message.
|
||||
func (s *OutputService) Info(msg string) {
|
||||
fmt.Println(InfoStyle.Render(SymbolInfo + " " + msg))
|
||||
}
|
||||
|
||||
// Title prints a title/header.
|
||||
func (s *OutputService) Title(msg string) {
|
||||
fmt.Println(TitleStyle.Render(msg))
|
||||
}
|
||||
|
||||
// Dim prints dimmed/subtle text.
|
||||
func (s *OutputService) Dim(msg string) {
|
||||
fmt.Println(DimStyle.Render(msg))
|
||||
}
|
||||
|
||||
// --- Signal Service ---
|
||||
|
||||
// SignalServiceOptions configures the signal service.
|
||||
type SignalServiceOptions struct {
|
||||
Cancel context.CancelFunc
|
||||
}
|
||||
|
||||
// SignalService handles OS signals for graceful shutdown.
|
||||
type SignalService struct {
|
||||
*framework.ServiceRuntime[SignalServiceOptions]
|
||||
sigChan chan os.Signal
|
||||
}
|
||||
|
||||
// NewSignalService creates a signal service factory.
|
||||
func NewSignalService(opts SignalServiceOptions) func(*framework.Core) (any, error) {
|
||||
return func(c *framework.Core) (any, error) {
|
||||
return &SignalService{
|
||||
ServiceRuntime: framework.NewServiceRuntime(c, opts),
|
||||
sigChan: make(chan os.Signal, 1),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// OnStartup starts listening for signals.
|
||||
func (s *SignalService) OnStartup(ctx context.Context) error {
|
||||
signal.Notify(s.sigChan, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
select {
|
||||
case <-s.sigChan:
|
||||
s.Opts().Cancel()
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// OnShutdown stops listening for signals.
|
||||
func (s *SignalService) OnShutdown(ctx context.Context) error {
|
||||
signal.Stop(s.sigChan)
|
||||
close(s.sigChan)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
// Package shared provides common utilities and styles for CLI commands.
|
||||
// Package cli provides common utilities and styles for CLI commands.
|
||||
//
|
||||
// This package contains:
|
||||
// - Terminal styling using lipgloss with Tailwind colours
|
||||
// - Unicode symbols for consistent visual indicators
|
||||
// - Helper functions for common output patterns
|
||||
// - Git and GitHub CLI utilities
|
||||
package shared
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package shared
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
Loading…
Add table
Reference in a new issue