diff --git a/cmd/magebox/bootstrap.go b/cmd/magebox/bootstrap.go index bfa49a4..11b6e03 100644 --- a/cmd/magebox/bootstrap.go +++ b/cmd/magebox/bootstrap.go @@ -191,6 +191,12 @@ func runBootstrap(cmd *cobra.Command, args []string) error { errors = append(errors, "mkcert is not installed. Install: "+p.MkcertInstallCommand()) } + // Check mysql-client (required by magerun2 for database operations) + verbose.Debug("Checking mysql-client installation...") + mysqlClientInstalled := platform.CommandExists("mysqldump") + verbose.Debug("mysql-client installed: %v", mysqlClientInstalled) + fmt.Printf(" %-15s %s\n", "mysql-client:", cli.StatusInstalled(mysqlClientInstalled)) + // Check PHP versions verbose.Debug("Detecting installed PHP versions...") detector := php.NewDetector(p) @@ -203,7 +209,7 @@ func runBootstrap(cmd *cobra.Command, args []string) error { fmt.Println() // If critical dependencies are missing, offer to install them - if !dockerInstalled || !nginxInstalled || !mkcertInstalled { + if !dockerInstalled || !nginxInstalled || !mkcertInstalled || !mysqlClientInstalled { cli.PrintWarning("Missing dependencies detected!") fmt.Println() @@ -215,6 +221,9 @@ func runBootstrap(cmd *cobra.Command, args []string) error { if !mkcertInstalled { missingDeps = append(missingDeps, "mkcert") } + if !mysqlClientInstalled { + missingDeps = append(missingDeps, "mysql-client") + } fmt.Println(" Missing: " + cli.Highlight(strings.Join(missingDeps, ", "))) fmt.Println() @@ -257,9 +266,31 @@ func runBootstrap(cmd *cobra.Command, args []string) error { fmt.Println() } + if !mysqlClientInstalled { + fmt.Println(" Installing mysql-client...") + if err := inst.InstallMysqlClient(); err != nil { + cli.PrintError("Failed to install mysql-client: %v", err) + fmt.Println() + cli.PrintInfo("Please install manually: %s", p.MysqlClientInstallCommand()) + } else { + fmt.Printf(" mysql-client installed %s\n", cli.Success("✓")) + if p.Type == platform.Darwin { + shellRC := filepath.Base(os.Getenv("SHELL")) + if shellRC == "" { + shellRC = "zsh" + } + fmt.Println() + cli.PrintInfo("Note: mysql-client is keg-only on macOS. To add it to your PATH:") + fmt.Printf(" echo 'export PATH=\"$(brew --prefix mysql-client)/bin:$PATH\"' >> ~/.%src\n", shellRC) + } + } + fmt.Println() + } + // Re-check after installation nginxInstalled = p.IsNginxInstalled() mkcertInstalled = platform.CommandExists("mkcert") + mysqlClientInstalled = platform.CommandExists("mysqldump") } else { fmt.Println() cli.PrintInfo("Install missing dependencies and run %s again", cli.Command("magebox bootstrap")) diff --git a/cmd/magebox/check.go b/cmd/magebox/check.go index 97226fc..cd75ce3 100644 --- a/cmd/magebox/check.go +++ b/cmd/magebox/check.go @@ -497,6 +497,22 @@ func runCheck(cmd *cobra.Command, args []string) error { }) } printCheckResult(results[len(results)-1]) + + // Check mysql-client (required for magerun2 database commands) + if platform.CommandExists("mysqldump") { + results = append(results, checkResult{ + name: "mysql-client", + status: "ok", + message: "mysqldump available", + }) + } else { + results = append(results, checkResult{ + name: "mysql-client", + status: "error", + message: fmt.Sprintf("Not installed — run '%s'", p.MysqlClientInstallCommand()), + }) + } + printCheckResult(results[len(results)-1]) fmt.Println() // Summary diff --git a/internal/bootstrap/bootstrap.go b/internal/bootstrap/bootstrap.go index 7526ffe..6470fcf 100644 --- a/internal/bootstrap/bootstrap.go +++ b/internal/bootstrap/bootstrap.go @@ -87,6 +87,11 @@ func (b *Bootstrapper) InstallDependency(name string) error { } } +// InstallMysqlClient installs mysql-client tools required by magerun2 +func (b *Bootstrapper) InstallMysqlClient() error { + return b.installer.InstallMysqlClient() +} + // InstallPHP installs a specific PHP version func (b *Bootstrapper) InstallPHP(version string) error { if err := b.installer.InstallPHP(version); err != nil { diff --git a/internal/bootstrap/installer/arch.go b/internal/bootstrap/installer/arch.go index a1d2383..838aaf3 100644 --- a/internal/bootstrap/installer/arch.go +++ b/internal/bootstrap/installer/arch.go @@ -123,6 +123,11 @@ func (a *ArchInstaller) InstallDnsmasq() error { return a.RunSudo("pacman", "-S", "--noconfirm", "dnsmasq") } +// InstallMysqlClient installs the MySQL client tools +func (a *ArchInstaller) InstallMysqlClient() error { + return a.RunSudo("pacman", "-S", "--noconfirm", "mariadb-clients") +} + // InstallMultitail installs multitail func (a *ArchInstaller) InstallMultitail() error { return a.RunSudo("pacman", "-S", "--noconfirm", "multitail") diff --git a/internal/bootstrap/installer/darwin.go b/internal/bootstrap/installer/darwin.go index 5677eb9..b9ee354 100644 --- a/internal/bootstrap/installer/darwin.go +++ b/internal/bootstrap/installer/darwin.go @@ -122,6 +122,11 @@ func (d *DarwinInstaller) InstallDnsmasq() error { return d.RunCommand("brew install dnsmasq") } +// InstallMysqlClient installs the MySQL client tools via Homebrew +func (d *DarwinInstaller) InstallMysqlClient() error { + return d.RunCommand("brew install mysql-client") +} + // InstallMultitail installs multitail via Homebrew func (d *DarwinInstaller) InstallMultitail() error { return d.RunCommand("brew install multitail") diff --git a/internal/bootstrap/installer/fedora.go b/internal/bootstrap/installer/fedora.go index 7922426..58ee8b7 100644 --- a/internal/bootstrap/installer/fedora.go +++ b/internal/bootstrap/installer/fedora.go @@ -149,6 +149,11 @@ func (f *FedoraInstaller) InstallDnsmasq() error { return f.RunSudo("dnf", "install", "-y", "dnsmasq") } +// InstallMysqlClient installs the MySQL client tools +func (f *FedoraInstaller) InstallMysqlClient() error { + return f.RunSudo("dnf", "install", "-y", "community-mysql") +} + // InstallMultitail installs multitail func (f *FedoraInstaller) InstallMultitail() error { return f.RunSudo("dnf", "install", "-y", "multitail") diff --git a/internal/bootstrap/installer/generic.go b/internal/bootstrap/installer/generic.go index 1ff3228..7a20d62 100644 --- a/internal/bootstrap/installer/generic.go +++ b/internal/bootstrap/installer/generic.go @@ -254,6 +254,12 @@ func (g *GenericInstaller) InstallMultitail() error { return g.RunCommand(strings.Join(args, " ")) } +// InstallMysqlClient is a no-op for the generic installer; +// mysql-client installation is handled by the platform-specific installers. +func (g *GenericInstaller) InstallMysqlClient() error { + return nil +} + // InstallXdebug installs Xdebug for a specific PHP version func (g *GenericInstaller) InstallXdebug(version string) error { g.loader.SetupPHPVariables(g.config, version) diff --git a/internal/bootstrap/installer/types.go b/internal/bootstrap/installer/types.go index fc55377..a9dc680 100644 --- a/internal/bootstrap/installer/types.go +++ b/internal/bootstrap/installer/types.go @@ -76,6 +76,10 @@ type Installer interface { // InstallMultitail installs multitail for log viewing InstallMultitail() error + // InstallMysqlClient installs the MySQL client tools (mysql, mysqldump) + // required by magerun2 for database-related commands + InstallMysqlClient() error + // InstallXdebug installs Xdebug for a specific PHP version InstallXdebug(version string) error diff --git a/internal/bootstrap/installer/ubuntu.go b/internal/bootstrap/installer/ubuntu.go index 02e16ec..504c747 100644 --- a/internal/bootstrap/installer/ubuntu.go +++ b/internal/bootstrap/installer/ubuntu.go @@ -249,6 +249,11 @@ func (u *UbuntuInstaller) InstallDnsmasq() error { return u.RunSudo("apt", "install", "-y", "dnsmasq") } +// InstallMysqlClient installs the MySQL client tools +func (u *UbuntuInstaller) InstallMysqlClient() error { + return u.RunSudo("apt", "install", "-y", "default-mysql-client") +} + // InstallMultitail installs multitail func (u *UbuntuInstaller) InstallMultitail() error { return u.RunSudo("apt", "install", "-y", "multitail") diff --git a/internal/platform/platform.go b/internal/platform/platform.go index be2664b..0691d87 100644 --- a/internal/platform/platform.go +++ b/internal/platform/platform.go @@ -440,6 +440,25 @@ func (p *Platform) MkcertInstallCommand() string { } } +// MysqlClientInstallCommand returns the command to install mysql-client +func (p *Platform) MysqlClientInstallCommand() string { + switch p.Type { + case Darwin: + return "brew install mysql-client" + case Linux: + switch p.LinuxDistro { + case DistroFedora: + return "sudo dnf install -y community-mysql" + case DistroArch: + return "sudo pacman -S --noconfirm mariadb-clients" + default: + return "sudo apt install -y default-mysql-client" + } + default: + return "" + } +} + // DockerInstallCommand returns the command to install Docker func (p *Platform) DockerInstallCommand() string { switch p.Type { diff --git a/vitepress/reference/commands.md b/vitepress/reference/commands.md index fa4f8c6..71ac8fe 100644 --- a/vitepress/reference/commands.md +++ b/vitepress/reference/commands.md @@ -1234,7 +1234,7 @@ magebox bootstrap ``` Performs: -- Dependency checking +- Dependency checking (Docker, Nginx, mkcert, mysql-client) - Global configuration creation - SSL CA setup - Nginx configuration @@ -2378,6 +2378,7 @@ Verifies: - SSL certificates - Nginx vhost configuration - File permissions +- magerun2 wrapper and mysql-client availability ---