feat: add core-php binary, fix imports to use core/cli
- Create cmd/core-php/main.go standalone binary entry point - Add FrankenPHP serve:embedded and exec commands (CGO build-tagged) - Replace all cobra imports with core/cli re-exports - Replace core/go/pkg/cli with core/cli/pkg/cli - Replace core/go/pkg/i18n with core/go-i18n/pkg/i18n - Add core/go and core/go-i18n as go.mod dependencies Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
d2081d91e7
commit
84ce94b713
23 changed files with 275 additions and 124 deletions
11
cmd.go
11
cmd.go
|
|
@ -4,10 +4,9 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
"forge.lthn.ai/core/go-i18n/pkg/i18n"
|
||||
"forge.lthn.ai/core/go/pkg/io"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// DefaultMedium is the default filesystem medium used by the php package.
|
||||
|
|
@ -67,12 +66,12 @@ var (
|
|||
)
|
||||
|
||||
// AddPHPCommands adds PHP/Laravel development commands.
|
||||
func AddPHPCommands(root *cobra.Command) {
|
||||
phpCmd := &cobra.Command{
|
||||
func AddPHPCommands(root *cli.Command) {
|
||||
phpCmd := &cli.Command{
|
||||
Use: "php",
|
||||
Short: i18n.T("cmd.php.short"),
|
||||
Long: i18n.T("cmd.php.long"),
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
PersistentPreRunE: func(cmd *cli.Command, args []string) error {
|
||||
// Check if we are in a workspace root
|
||||
wsRoot, err := findWorkspaceRoot()
|
||||
if err != nil {
|
||||
|
|
|
|||
15
cmd/core-php/main.go
Normal file
15
cmd/core-php/main.go
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// Package main provides the core-php binary — a standalone PHP/Laravel
|
||||
// development tool with FrankenPHP embedding support.
|
||||
package main
|
||||
|
||||
import (
|
||||
php "forge.lthn.ai/core/go-php"
|
||||
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cli.Main(
|
||||
cli.WithCommands("php", php.AddPHPCommands),
|
||||
)
|
||||
}
|
||||
25
cmd_build.go
25
cmd_build.go
|
|
@ -6,9 +6,8 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
"forge.lthn.ai/core/go-i18n/pkg/i18n"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -23,12 +22,12 @@ var (
|
|||
buildNoCache bool
|
||||
)
|
||||
|
||||
func addPHPBuildCommand(parent *cobra.Command) {
|
||||
buildCmd := &cobra.Command{
|
||||
func addPHPBuildCommand(parent *cli.Command) {
|
||||
buildCmd := &cli.Command{
|
||||
Use: "build",
|
||||
Short: i18n.T("cmd.php.build.short"),
|
||||
Long: i18n.T("cmd.php.build.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -190,12 +189,12 @@ var (
|
|||
serveEnvFile string
|
||||
)
|
||||
|
||||
func addPHPServeCommand(parent *cobra.Command) {
|
||||
serveCmd := &cobra.Command{
|
||||
func addPHPServeCommand(parent *cli.Command) {
|
||||
serveCmd := &cli.Command{
|
||||
Use: "serve",
|
||||
Short: i18n.T("cmd.php.serve.short"),
|
||||
Long: i18n.T("cmd.php.serve.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
imageName := serveImageName
|
||||
if imageName == "" {
|
||||
// Try to detect from current directory
|
||||
|
|
@ -268,13 +267,13 @@ func addPHPServeCommand(parent *cobra.Command) {
|
|||
parent.AddCommand(serveCmd)
|
||||
}
|
||||
|
||||
func addPHPShellCommand(parent *cobra.Command) {
|
||||
shellCmd := &cobra.Command{
|
||||
func addPHPShellCommand(parent *cli.Command) {
|
||||
shellCmd := &cli.Command{
|
||||
Use: "shell [container]",
|
||||
Short: i18n.T("cmd.php.shell.short"),
|
||||
Long: i18n.T("cmd.php.shell.long"),
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
Args: cli.ExactArgs(1),
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
ctx := context.Background()
|
||||
|
||||
cli.Print("%s %s\n", dimStyle.Render(i18n.T("cmd.php.label.php")), i18n.T("cmd.php.shell.opening", map[string]interface{}{"Container": args[0]}))
|
||||
|
|
|
|||
11
cmd_ci.go
11
cmd_ci.go
|
|
@ -21,9 +21,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
"forge.lthn.ai/core/go-i18n/pkg/i18n"
|
||||
)
|
||||
|
||||
// CI command flags
|
||||
|
|
@ -66,12 +65,12 @@ type CISummary struct {
|
|||
Skipped int `json:"skipped"`
|
||||
}
|
||||
|
||||
func addPHPCICommand(parent *cobra.Command) {
|
||||
ciCmd := &cobra.Command{
|
||||
func addPHPCICommand(parent *cli.Command) {
|
||||
ciCmd := &cli.Command{
|
||||
Use: "ci",
|
||||
Short: i18n.T("cmd.php.ci.short"),
|
||||
Long: i18n.T("cmd.php.ci.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
return runPHPCI()
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@
|
|||
// - deploy:list: List recent deployments
|
||||
package php
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
import "forge.lthn.ai/core/cli/pkg/cli"
|
||||
|
||||
// AddCommands registers the 'php' command and all subcommands.
|
||||
func AddCommands(root *cobra.Command) {
|
||||
func AddCommands(root *cli.Command) {
|
||||
AddPHPCommands(root)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
"forge.lthn.ai/core/go-i18n/pkg/i18n"
|
||||
)
|
||||
|
||||
// Deploy command styles (aliases to shared)
|
||||
|
|
@ -17,7 +16,7 @@ var (
|
|||
phpDeployFailedStyle = cli.ErrorStyle
|
||||
)
|
||||
|
||||
func addPHPDeployCommands(parent *cobra.Command) {
|
||||
func addPHPDeployCommands(parent *cli.Command) {
|
||||
// Main deploy command
|
||||
addPHPDeployCommand(parent)
|
||||
|
||||
|
|
@ -37,12 +36,12 @@ var (
|
|||
deployWait bool
|
||||
)
|
||||
|
||||
func addPHPDeployCommand(parent *cobra.Command) {
|
||||
deployCmd := &cobra.Command{
|
||||
func addPHPDeployCommand(parent *cli.Command) {
|
||||
deployCmd := &cli.Command{
|
||||
Use: "deploy",
|
||||
Short: i18n.T("cmd.php.deploy.short"),
|
||||
Long: i18n.T("cmd.php.deploy.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -97,12 +96,12 @@ var (
|
|||
deployStatusDeploymentID string
|
||||
)
|
||||
|
||||
func addPHPDeployStatusCommand(parent *cobra.Command) {
|
||||
statusCmd := &cobra.Command{
|
||||
func addPHPDeployStatusCommand(parent *cli.Command) {
|
||||
statusCmd := &cli.Command{
|
||||
Use: "deploy:status",
|
||||
Short: i18n.T("cmd.php.deploy_status.short"),
|
||||
Long: i18n.T("cmd.php.deploy_status.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -146,12 +145,12 @@ var (
|
|||
rollbackWait bool
|
||||
)
|
||||
|
||||
func addPHPDeployRollbackCommand(parent *cobra.Command) {
|
||||
rollbackCmd := &cobra.Command{
|
||||
func addPHPDeployRollbackCommand(parent *cli.Command) {
|
||||
rollbackCmd := &cli.Command{
|
||||
Use: "deploy:rollback",
|
||||
Short: i18n.T("cmd.php.deploy_rollback.short"),
|
||||
Long: i18n.T("cmd.php.deploy_rollback.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -206,12 +205,12 @@ var (
|
|||
deployListLimit int
|
||||
)
|
||||
|
||||
func addPHPDeployListCommand(parent *cobra.Command) {
|
||||
listCmd := &cobra.Command{
|
||||
func addPHPDeployListCommand(parent *cli.Command) {
|
||||
listCmd := &cli.Command{
|
||||
Use: "deploy:list",
|
||||
Short: i18n.T("cmd.php.deploy_list.short"),
|
||||
Long: i18n.T("cmd.php.deploy_list.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
|
|||
35
cmd_dev.go
35
cmd_dev.go
|
|
@ -10,9 +10,8 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
"forge.lthn.ai/core/go-i18n/pkg/i18n"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -25,12 +24,12 @@ var (
|
|||
devPort int
|
||||
)
|
||||
|
||||
func addPHPDevCommand(parent *cobra.Command) {
|
||||
devCmd := &cobra.Command{
|
||||
func addPHPDevCommand(parent *cli.Command) {
|
||||
devCmd := &cli.Command{
|
||||
Use: "dev",
|
||||
Short: i18n.T("cmd.php.dev.short"),
|
||||
Long: i18n.T("cmd.php.dev.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
return runPHPDev(phpDevOptions{
|
||||
NoVite: devNoVite,
|
||||
NoHorizon: devNoHorizon,
|
||||
|
|
@ -185,12 +184,12 @@ var (
|
|||
logsService string
|
||||
)
|
||||
|
||||
func addPHPLogsCommand(parent *cobra.Command) {
|
||||
logsCmd := &cobra.Command{
|
||||
func addPHPLogsCommand(parent *cli.Command) {
|
||||
logsCmd := &cli.Command{
|
||||
Use: "logs",
|
||||
Short: i18n.T("cmd.php.logs.short"),
|
||||
Long: i18n.T("cmd.php.logs.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
return runPHPLogs(logsService, logsFollow)
|
||||
},
|
||||
}
|
||||
|
|
@ -245,11 +244,11 @@ func runPHPLogs(service string, follow bool) error {
|
|||
return scanner.Err()
|
||||
}
|
||||
|
||||
func addPHPStopCommand(parent *cobra.Command) {
|
||||
stopCmd := &cobra.Command{
|
||||
func addPHPStopCommand(parent *cli.Command) {
|
||||
stopCmd := &cli.Command{
|
||||
Use: "stop",
|
||||
Short: i18n.T("cmd.php.stop.short"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
return runPHPStop()
|
||||
},
|
||||
}
|
||||
|
|
@ -276,11 +275,11 @@ func runPHPStop() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func addPHPStatusCommand(parent *cobra.Command) {
|
||||
statusCmd := &cobra.Command{
|
||||
func addPHPStatusCommand(parent *cli.Command) {
|
||||
statusCmd := &cli.Command{
|
||||
Use: "status",
|
||||
Short: i18n.T("cmd.php.status.short"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
return runPHPStatus()
|
||||
},
|
||||
}
|
||||
|
|
@ -339,11 +338,11 @@ func runPHPStatus() error {
|
|||
|
||||
var sslDomain string
|
||||
|
||||
func addPHPSSLCommand(parent *cobra.Command) {
|
||||
sslCmd := &cobra.Command{
|
||||
func addPHPSSLCommand(parent *cli.Command) {
|
||||
sslCmd := &cli.Command{
|
||||
Use: "ssl",
|
||||
Short: i18n.T("cmd.php.ssl.short"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
return runPHPSSL(sslDomain)
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@ package php
|
|||
import (
|
||||
"os"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
"forge.lthn.ai/core/go-i18n/pkg/i18n"
|
||||
)
|
||||
|
||||
func addPHPPackagesCommands(parent *cobra.Command) {
|
||||
packagesCmd := &cobra.Command{
|
||||
func addPHPPackagesCommands(parent *cli.Command) {
|
||||
packagesCmd := &cli.Command{
|
||||
Use: "packages",
|
||||
Short: i18n.T("cmd.php.packages.short"),
|
||||
Long: i18n.T("cmd.php.packages.long"),
|
||||
|
|
@ -22,13 +21,13 @@ func addPHPPackagesCommands(parent *cobra.Command) {
|
|||
addPHPPackagesListCommand(packagesCmd)
|
||||
}
|
||||
|
||||
func addPHPPackagesLinkCommand(parent *cobra.Command) {
|
||||
linkCmd := &cobra.Command{
|
||||
func addPHPPackagesLinkCommand(parent *cli.Command) {
|
||||
linkCmd := &cli.Command{
|
||||
Use: "link [paths...]",
|
||||
Short: i18n.T("cmd.php.packages.link.short"),
|
||||
Long: i18n.T("cmd.php.packages.link.long"),
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
Args: cli.MinimumNArgs(1),
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -48,13 +47,13 @@ func addPHPPackagesLinkCommand(parent *cobra.Command) {
|
|||
parent.AddCommand(linkCmd)
|
||||
}
|
||||
|
||||
func addPHPPackagesUnlinkCommand(parent *cobra.Command) {
|
||||
unlinkCmd := &cobra.Command{
|
||||
func addPHPPackagesUnlinkCommand(parent *cli.Command) {
|
||||
unlinkCmd := &cli.Command{
|
||||
Use: "unlink [packages...]",
|
||||
Short: i18n.T("cmd.php.packages.unlink.short"),
|
||||
Long: i18n.T("cmd.php.packages.unlink.long"),
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
Args: cli.MinimumNArgs(1),
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -74,12 +73,12 @@ func addPHPPackagesUnlinkCommand(parent *cobra.Command) {
|
|||
parent.AddCommand(unlinkCmd)
|
||||
}
|
||||
|
||||
func addPHPPackagesUpdateCommand(parent *cobra.Command) {
|
||||
updateCmd := &cobra.Command{
|
||||
func addPHPPackagesUpdateCommand(parent *cli.Command) {
|
||||
updateCmd := &cli.Command{
|
||||
Use: "update [packages...]",
|
||||
Short: i18n.T("cmd.php.packages.update.short"),
|
||||
Long: i18n.T("cmd.php.packages.update.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -99,12 +98,12 @@ func addPHPPackagesUpdateCommand(parent *cobra.Command) {
|
|||
parent.AddCommand(updateCmd)
|
||||
}
|
||||
|
||||
func addPHPPackagesListCommand(parent *cobra.Command) {
|
||||
listCmd := &cobra.Command{
|
||||
func addPHPPackagesListCommand(parent *cli.Command) {
|
||||
listCmd := &cli.Command{
|
||||
Use: "list",
|
||||
Short: i18n.T("cmd.php.packages.list.short"),
|
||||
Long: i18n.T("cmd.php.packages.list.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
"forge.lthn.ai/core/go/pkg/framework"
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"forge.lthn.ai/core/go-i18n/pkg/i18n"
|
||||
"forge.lthn.ai/core/go/pkg/process"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"github.com/spf13/cobra"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
"forge.lthn.ai/core/go-i18n/pkg/i18n"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -20,12 +19,12 @@ var (
|
|||
testJSON bool
|
||||
)
|
||||
|
||||
func addPHPTestCommand(parent *cobra.Command) {
|
||||
testCmd := &cobra.Command{
|
||||
func addPHPTestCommand(parent *cli.Command) {
|
||||
testCmd := &cli.Command{
|
||||
Use: "test",
|
||||
Short: i18n.T("cmd.php.test.short"),
|
||||
Long: i18n.T("cmd.php.test.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -77,12 +76,12 @@ var (
|
|||
fmtJSON bool
|
||||
)
|
||||
|
||||
func addPHPFmtCommand(parent *cobra.Command) {
|
||||
fmtCmd := &cobra.Command{
|
||||
func addPHPFmtCommand(parent *cli.Command) {
|
||||
fmtCmd := &cli.Command{
|
||||
Use: "fmt [paths...]",
|
||||
Short: i18n.T("cmd.php.fmt.short"),
|
||||
Long: i18n.T("cmd.php.fmt.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -156,12 +155,12 @@ var (
|
|||
stanSARIF bool
|
||||
)
|
||||
|
||||
func addPHPStanCommand(parent *cobra.Command) {
|
||||
stanCmd := &cobra.Command{
|
||||
func addPHPStanCommand(parent *cli.Command) {
|
||||
stanCmd := &cli.Command{
|
||||
Use: "stan [paths...]",
|
||||
Short: i18n.T("cmd.php.analyse.short"),
|
||||
Long: i18n.T("cmd.php.analyse.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -233,12 +232,12 @@ var (
|
|||
psalmSARIF bool
|
||||
)
|
||||
|
||||
func addPHPPsalmCommand(parent *cobra.Command) {
|
||||
psalmCmd := &cobra.Command{
|
||||
func addPHPPsalmCommand(parent *cli.Command) {
|
||||
psalmCmd := &cli.Command{
|
||||
Use: "psalm",
|
||||
Short: i18n.T("cmd.php.psalm.short"),
|
||||
Long: i18n.T("cmd.php.psalm.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -310,12 +309,12 @@ var (
|
|||
auditFix bool
|
||||
)
|
||||
|
||||
func addPHPAuditCommand(parent *cobra.Command) {
|
||||
auditCmd := &cobra.Command{
|
||||
func addPHPAuditCommand(parent *cli.Command) {
|
||||
auditCmd := &cli.Command{
|
||||
Use: "audit",
|
||||
Short: i18n.T("cmd.php.audit.short"),
|
||||
Long: i18n.T("cmd.php.audit.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -403,12 +402,12 @@ var (
|
|||
securityURL string
|
||||
)
|
||||
|
||||
func addPHPSecurityCommand(parent *cobra.Command) {
|
||||
securityCmd := &cobra.Command{
|
||||
func addPHPSecurityCommand(parent *cli.Command) {
|
||||
securityCmd := &cli.Command{
|
||||
Use: "security",
|
||||
Short: i18n.T("cmd.php.security.short"),
|
||||
Long: i18n.T("cmd.php.security.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -502,12 +501,12 @@ var (
|
|||
qaJSON bool
|
||||
)
|
||||
|
||||
func addPHPQACommand(parent *cobra.Command) {
|
||||
qaCmd := &cobra.Command{
|
||||
func addPHPQACommand(parent *cli.Command) {
|
||||
qaCmd := &cli.Command{
|
||||
Use: "qa",
|
||||
Short: i18n.T("cmd.php.qa.short"),
|
||||
Long: i18n.T("cmd.php.qa.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -670,12 +669,12 @@ var (
|
|||
rectorClearCache bool
|
||||
)
|
||||
|
||||
func addPHPRectorCommand(parent *cobra.Command) {
|
||||
rectorCmd := &cobra.Command{
|
||||
func addPHPRectorCommand(parent *cli.Command) {
|
||||
rectorCmd := &cli.Command{
|
||||
Use: "rector",
|
||||
Short: i18n.T("cmd.php.rector.short"),
|
||||
Long: i18n.T("cmd.php.rector.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
@ -744,12 +743,12 @@ var (
|
|||
infectionOnlyCovered bool
|
||||
)
|
||||
|
||||
func addPHPInfectionCommand(parent *cobra.Command) {
|
||||
infectionCmd := &cobra.Command{
|
||||
func addPHPInfectionCommand(parent *cli.Command) {
|
||||
infectionCmd := &cli.Command{
|
||||
Use: "infection",
|
||||
Short: i18n.T("cmd.php.infection.short"),
|
||||
Long: i18n.T("cmd.php.infection.long"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(cmd *cli.Command, args []string) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err)
|
||||
|
|
|
|||
141
cmd_serve_frankenphp.go
Normal file
141
cmd_serve_frankenphp.go
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
//go:build cgo
|
||||
|
||||
package php
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
serveFPPort int
|
||||
serveFPPath string
|
||||
serveFPWorkers int
|
||||
serveFPThreads int
|
||||
)
|
||||
|
||||
func init() {
|
||||
cli.RegisterCommands(addFrankenPHPCommands)
|
||||
}
|
||||
|
||||
func addFrankenPHPCommands(root *cli.Command) {
|
||||
// Find the php parent command, or create one
|
||||
phpCmd := findOrCreatePHPCmd(root)
|
||||
|
||||
serveCmd := &cli.Command{
|
||||
Use: "serve:embedded",
|
||||
Short: "Serve Laravel via embedded FrankenPHP runtime",
|
||||
Long: "Start an HTTP server using the embedded FrankenPHP runtime with Octane worker mode support.",
|
||||
RunE: runFrankenPHPServe,
|
||||
}
|
||||
serveCmd.Flags().IntVar(&serveFPPort, "port", 8000, "HTTP listen port")
|
||||
serveCmd.Flags().StringVar(&serveFPPath, "path", ".", "Laravel application root")
|
||||
serveCmd.Flags().IntVar(&serveFPWorkers, "workers", 2, "Octane worker count")
|
||||
serveCmd.Flags().IntVar(&serveFPThreads, "threads", 4, "PHP thread count")
|
||||
phpCmd.AddCommand(serveCmd)
|
||||
|
||||
execCmd := &cli.Command{
|
||||
Use: "exec [command...]",
|
||||
Short: "Execute a PHP artisan command via FrankenPHP",
|
||||
Long: "Boot FrankenPHP, run an artisan command, then exit. Stdin/stdout pass-through.",
|
||||
Args: cli.MinimumNArgs(1),
|
||||
RunE: runFrankenPHPExec,
|
||||
}
|
||||
execCmd.Flags().StringVar(&serveFPPath, "path", ".", "Laravel application root")
|
||||
phpCmd.AddCommand(execCmd)
|
||||
}
|
||||
|
||||
func runFrankenPHPServe(cmd *cli.Command, args []string) error {
|
||||
handler, cleanup, err := NewHandler(serveFPPath, HandlerConfig{
|
||||
NumThreads: serveFPThreads,
|
||||
NumWorkers: serveFPWorkers,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("init FrankenPHP: %w", err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
addr := fmt.Sprintf(":%d", serveFPPort)
|
||||
srv := &http.Server{
|
||||
Addr: addr,
|
||||
Handler: handler,
|
||||
}
|
||||
|
||||
// Graceful shutdown
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
defer stop()
|
||||
|
||||
go func() {
|
||||
log.Printf("core-php: serving on http://localhost%s (doc root: %s)", addr, handler.DocRoot())
|
||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("core-php: server error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
<-ctx.Done()
|
||||
log.Println("core-php: shutting down...")
|
||||
return srv.Shutdown(context.Background())
|
||||
}
|
||||
|
||||
func runFrankenPHPExec(cmd *cli.Command, args []string) error {
|
||||
handler, cleanup, err := NewHandler(serveFPPath, HandlerConfig{
|
||||
NumThreads: 1,
|
||||
NumWorkers: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("init FrankenPHP: %w", err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
// Build an artisan request
|
||||
artisanArgs := "artisan"
|
||||
for _, a := range args {
|
||||
artisanArgs += " " + a
|
||||
}
|
||||
|
||||
log.Printf("core-php: exec %s (root: %s)", artisanArgs, handler.LaravelRoot())
|
||||
|
||||
// Execute via internal HTTP request to FrankenPHP
|
||||
// This routes through the PHP runtime as if it were a CLI call
|
||||
req, err := http.NewRequest("GET", "/artisan-exec?cmd="+artisanArgs, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// For now, use the handler directly
|
||||
w := &execResponseWriter{os.Stdout}
|
||||
handler.ServeHTTP(w, req)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// findOrCreatePHPCmd finds an existing "php" command or creates one.
|
||||
func findOrCreatePHPCmd(root *cli.Command) *cli.Command {
|
||||
for _, c := range root.Commands() {
|
||||
if c.Use == "php" {
|
||||
return c
|
||||
}
|
||||
}
|
||||
phpCmd := &cli.Command{
|
||||
Use: "php",
|
||||
Short: "PHP/Laravel development tools",
|
||||
}
|
||||
root.AddCommand(phpCmd)
|
||||
return phpCmd
|
||||
}
|
||||
|
||||
// execResponseWriter writes HTTP response body directly to stdout.
|
||||
type execResponseWriter struct {
|
||||
out *os.File
|
||||
}
|
||||
|
||||
func (w *execResponseWriter) Header() http.Header { return http.Header{} }
|
||||
func (w *execResponseWriter) WriteHeader(statusCode int) {}
|
||||
func (w *execResponseWriter) Write(b []byte) (int, error) { return w.out.Write(b) }
|
||||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
// DockerBuildOptions configures Docker image building for PHP projects.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
// CoolifyClient is an HTTP client for the Coolify API.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"context"
|
||||
"time"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
// Environment represents a deployment environment.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
// DockerfileConfig holds configuration for generating a Dockerfile.
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -4,6 +4,8 @@ go 1.26.0
|
|||
|
||||
require (
|
||||
forge.lthn.ai/core/cli v0.1.0
|
||||
forge.lthn.ai/core/go v0.1.0
|
||||
forge.lthn.ai/core/go-i18n v0.1.0
|
||||
github.com/dunglas/frankenphp v1.5.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
)
|
||||
|
|
|
|||
2
i18n.go
2
i18n.go
|
|
@ -4,7 +4,7 @@ package php
|
|||
import (
|
||||
"embed"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"forge.lthn.ai/core/go-i18n/pkg/i18n"
|
||||
)
|
||||
|
||||
//go:embed locales/*.json
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
// LinkedPackage represents a linked local package.
|
||||
|
|
|
|||
2
php.go
2
php.go
|
|
@ -7,7 +7,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
// Options configures the development server.
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/go/pkg/i18n"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
"forge.lthn.ai/core/go-i18n/pkg/i18n"
|
||||
)
|
||||
|
||||
// FormatOptions configures PHP code formatting.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
// Service represents a managed development service.
|
||||
|
|
|
|||
2
ssl.go
2
ssl.go
|
|
@ -5,7 +5,7 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/cli"
|
||||
"forge.lthn.ai/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
// TestOptions configures PHP test execution.
|
||||
|
|
|
|||
Reference in a new issue