fix(i18n): restore missing translation keys for health command (#65)
* fix(i18n): restore missing translation keys for health command
The locale consolidation in 39de3c2 removed keys still used by
cmd_health.go. Added back:
- cmd.dev.health.* keys (long, repos, to_push, to_pull, etc.)
- common.status.* keys (dirty, clean, synced, up_to_date)
- common.flag.registry
Also fixed workspace.LoadConfig() returning default PackagesDir
when no .core/workspace.yaml exists, which was overriding repo
paths from repos.yaml.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: add nil checks for workspace.LoadConfig callers
LoadConfig now returns nil when no .core/workspace.yaml exists.
Added defensive nil checks to all callers to prevent panics.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: align workspace.LoadConfig error handling
Both call sites now gracefully ignore errors and fall back to defaults,
since workspace config is optional for setup commands.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e813c1f07e
commit
a0088a34a8
8 changed files with 55 additions and 14 deletions
|
|
@ -44,8 +44,8 @@ func loadRegistryWithConfig(registryPath string) (*repos.Registry, string, error
|
||||||
registryDir = cwd
|
registryDir = cwd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Load workspace config to respect packages_dir
|
// Load workspace config to respect packages_dir (only if config exists)
|
||||||
if wsConfig, err := workspace.LoadConfig(registryDir); err == nil {
|
if wsConfig, err := workspace.LoadConfig(registryDir); err == nil && wsConfig != nil {
|
||||||
if wsConfig.PackagesDir != "" {
|
if wsConfig.PackagesDir != "" {
|
||||||
pkgDir := wsConfig.PackagesDir
|
pkgDir := wsConfig.PackagesDir
|
||||||
// Expand ~
|
// Expand ~
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ func loadRegistry(registryPath string) (*repos.Registry, string, error) {
|
||||||
|
|
||||||
basePath := registryDir
|
basePath := registryDir
|
||||||
|
|
||||||
if wsConfig.PackagesDir != "" && wsConfig.PackagesDir != "./packages" {
|
if wsConfig != nil && wsConfig.PackagesDir != "" && wsConfig.PackagesDir != "./packages" {
|
||||||
pkgDir := wsConfig.PackagesDir
|
pkgDir := wsConfig.PackagesDir
|
||||||
|
|
||||||
// Expand ~
|
// Expand ~
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,18 @@
|
||||||
"no_git_repos": "No git repositories found.",
|
"no_git_repos": "No git repositories found.",
|
||||||
"confirm_claude_commit": "Have Claude commit these repos?",
|
"confirm_claude_commit": "Have Claude commit these repos?",
|
||||||
"health.short": "Quick health check across all repos",
|
"health.short": "Quick health check across all repos",
|
||||||
|
"health.long": "Shows a summary of repository health across all repos in the workspace.",
|
||||||
|
"health.flag.verbose": "Show detailed breakdown",
|
||||||
|
"health.repos": "repos",
|
||||||
|
"health.to_push": "to push",
|
||||||
|
"health.to_pull": "to pull",
|
||||||
|
"health.errors": "errors",
|
||||||
|
"health.more": "+{{.Count}} more",
|
||||||
|
"health.dirty_label": "Dirty:",
|
||||||
|
"health.ahead_label": "Ahead:",
|
||||||
|
"health.behind_label": "Behind:",
|
||||||
|
"health.errors_label": "Errors:",
|
||||||
|
"status.clean": "clean",
|
||||||
"commit.short": "Claude-assisted commits across repos",
|
"commit.short": "Claude-assisted commits across repos",
|
||||||
"push.short": "Push commits across all repos",
|
"push.short": "Push commits across all repos",
|
||||||
"push.diverged": "branch has diverged from remote",
|
"push.diverged": "branch has diverged from remote",
|
||||||
|
|
@ -293,6 +305,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
"status": {
|
||||||
|
"dirty": "dirty",
|
||||||
|
"clean": "clean",
|
||||||
|
"synced": "synced",
|
||||||
|
"up_to_date": "up to date"
|
||||||
|
},
|
||||||
"label": {
|
"label": {
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"error": "Error",
|
"error": "Error",
|
||||||
|
|
@ -309,7 +327,8 @@
|
||||||
"fix": "Auto-fix issues where possible",
|
"fix": "Auto-fix issues where possible",
|
||||||
"diff": "Show diff of changes",
|
"diff": "Show diff of changes",
|
||||||
"json": "Output as JSON",
|
"json": "Output as JSON",
|
||||||
"verbose": "Show detailed output"
|
"verbose": "Show detailed output",
|
||||||
|
"registry": "Path to repos.yaml registry file"
|
||||||
},
|
},
|
||||||
"progress": {
|
"progress": {
|
||||||
"running": "Running {{.Task}}...",
|
"running": "Running {{.Task}}...",
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,8 @@ func AddPHPCommands(root *cobra.Command) {
|
||||||
|
|
||||||
// Load workspace config
|
// Load workspace config
|
||||||
config, err := workspace.LoadConfig(wsRoot)
|
config, err := workspace.LoadConfig(wsRoot)
|
||||||
if err != nil {
|
if err != nil || config == nil {
|
||||||
return nil // Failed to load, ignore
|
return nil // Failed to load or no config, ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Active == "" {
|
if config.Active == "" {
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/host-uk/core/pkg/i18n"
|
"github.com/host-uk/core/pkg/i18n"
|
||||||
"github.com/host-uk/core/pkg/repos"
|
"github.com/host-uk/core/pkg/repos"
|
||||||
|
"github.com/host-uk/core/pkg/workspace"
|
||||||
)
|
)
|
||||||
|
|
||||||
// runSetupOrchestrator decides between registry mode and bootstrap mode.
|
// runSetupOrchestrator decides between registry mode and bootstrap mode.
|
||||||
|
|
@ -133,6 +135,13 @@ func runBootstrap(ctx context.Context, only string, dryRun, all bool, projectNam
|
||||||
// Override base path to target directory
|
// Override base path to target directory
|
||||||
reg.BasePath = targetDir
|
reg.BasePath = targetDir
|
||||||
|
|
||||||
|
// Check workspace config for default_only if no filter specified
|
||||||
|
if only == "" {
|
||||||
|
if wsConfig, err := workspace.LoadConfig(devopsPath); err == nil && wsConfig != nil && len(wsConfig.DefaultOnly) > 0 {
|
||||||
|
only = strings.Join(wsConfig.DefaultOnly, ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now run the regular setup with the loaded registry
|
// Now run the regular setup with the loaded registry
|
||||||
return runRegistrySetupWithReg(ctx, reg, registryPath, only, dryRun, all, runBuild)
|
return runRegistrySetupWithReg(ctx, reg, registryPath, only, dryRun, all, runBuild)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,14 @@ func runRegistrySetup(ctx context.Context, registryPath, only string, dryRun, al
|
||||||
return fmt.Errorf("failed to load registry: %w", err)
|
return fmt.Errorf("failed to load registry: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check workspace config for default_only if no filter specified
|
||||||
|
if only == "" {
|
||||||
|
registryDir := filepath.Dir(registryPath)
|
||||||
|
if wsConfig, err := workspace.LoadConfig(registryDir); err == nil && wsConfig != nil && len(wsConfig.DefaultOnly) > 0 {
|
||||||
|
only = strings.Join(wsConfig.DefaultOnly, ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return runRegistrySetupWithReg(ctx, reg, registryPath, only, dryRun, all, runBuild)
|
return runRegistrySetupWithReg(ctx, reg, registryPath, only, dryRun, all, runBuild)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,12 +47,9 @@ func runRegistrySetupWithReg(ctx context.Context, reg *repos.Registry, registryP
|
||||||
// Determine base path for cloning
|
// Determine base path for cloning
|
||||||
basePath := reg.BasePath
|
basePath := reg.BasePath
|
||||||
if basePath == "" {
|
if basePath == "" {
|
||||||
// Load workspace config to see if packages_dir is set
|
// Load workspace config to see if packages_dir is set (ignore errors, fall back to default)
|
||||||
wsConfig, err := workspace.LoadConfig(registryDir)
|
wsConfig, _ := workspace.LoadConfig(registryDir)
|
||||||
if err != nil {
|
if wsConfig != nil && wsConfig.PackagesDir != "" {
|
||||||
return fmt.Errorf("failed to load workspace config: %w", err)
|
|
||||||
}
|
|
||||||
if wsConfig.PackagesDir != "" {
|
|
||||||
basePath = wsConfig.PackagesDir
|
basePath = wsConfig.PackagesDir
|
||||||
} else {
|
} else {
|
||||||
basePath = "./packages"
|
basePath = "./packages"
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,9 @@ func runWorkspaceInfo(cmd *cobra.Command, args []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if config == nil {
|
||||||
|
return cli.Err("workspace config not found")
|
||||||
|
}
|
||||||
|
|
||||||
cli.Print("Active: %s\n", cli.ValueStyle.Render(config.Active))
|
cli.Print("Active: %s\n", cli.ValueStyle.Render(config.Active))
|
||||||
cli.Print("Packages: %s\n", cli.DimStyle.Render(config.PackagesDir))
|
cli.Print("Packages: %s\n", cli.DimStyle.Render(config.PackagesDir))
|
||||||
|
|
@ -53,6 +56,9 @@ func runWorkspaceActive(cmd *cobra.Command, args []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if config == nil {
|
||||||
|
config = DefaultConfig()
|
||||||
|
}
|
||||||
|
|
||||||
// If no args, show active
|
// If no args, show active
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
|
|
@ -60,7 +66,7 @@ func runWorkspaceActive(cmd *cobra.Command, args []string) error {
|
||||||
cli.Println("No active package set")
|
cli.Println("No active package set")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cli.Println(config.Active)
|
cli.Text(config.Active)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ func DefaultConfig() *WorkspaceConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfig tries to load workspace.yaml from the given directory's .core subfolder.
|
// LoadConfig tries to load workspace.yaml from the given directory's .core subfolder.
|
||||||
|
// Returns nil if no config file exists (caller should check for nil).
|
||||||
func LoadConfig(dir string) (*WorkspaceConfig, error) {
|
func LoadConfig(dir string) (*WorkspaceConfig, error) {
|
||||||
path := filepath.Join(dir, ".core", "workspace.yaml")
|
path := filepath.Join(dir, ".core", "workspace.yaml")
|
||||||
data, err := os.ReadFile(path)
|
data, err := os.ReadFile(path)
|
||||||
|
|
@ -35,7 +36,8 @@ func LoadConfig(dir string) (*WorkspaceConfig, error) {
|
||||||
if parent != dir {
|
if parent != dir {
|
||||||
return LoadConfig(parent)
|
return LoadConfig(parent)
|
||||||
}
|
}
|
||||||
return DefaultConfig(), nil
|
// No workspace.yaml found anywhere - return nil to indicate no config
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("failed to read workspace config: %w", err)
|
return nil, fmt.Errorf("failed to read workspace config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue