Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 84 additions & 1 deletion src/lib/utils/mise/mise.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"fmt"
"io"
"os"
"path"
"runtime"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -123,9 +125,65 @@ func (m *Mise) InstallMise(ctx context.Context) error {
return nil
}

// PHPInstaller installs PHP using herd-lite. We cannot use mise
// for PHP installations at the moment because it is very cumbersome
// to manage PHP extensions using mise.
func (m *Mise) PHPInstaller(ctx context.Context, rt string) error {
pieces := strings.SplitN(rt, "@", 2)
version := "8.4"

if len(pieces) == 2 && pieces[1] != "latest" {
version = pieces[1]
}

var osys string

switch runtime.GOOS {
case "linux":
osys = "linux"
case "darwin":
osys = "macos"
default:
return fmt.Errorf("unsupported OS for PHP installation: %s", runtime.GOOS)
}

// PHP installation using mise is not yet supported
// We're using https://laravel.com/docs/12.x/installation as an alternative installation method
cmd := sys.Command(ctx, sys.CommandOpts{
Name: "sh",
Args: []string{
"-c",
fmt.Sprintf(`/bin/bash -c "$(curl -fsSL https://php.new/install/%s/%s)"`, osys, version),
},
Env: []string{
"PATH=" + os.Getenv("PATH"),
"HOME=" + os.Getenv("HOME"),
},
})

if err := cmd.Run(); err != nil {
return err
}

if err := m.updatePath(ctx, ""); err != nil {
return err
}

return nil
}

// phpDir returns the path to the PHP binary installed via herd-lite.
func (m *Mise) phpDir() string {
return path.Join(os.Getenv("HOME"), ".config", "herd-lite", "bin")
}

// Install installs the specified runtime using mise.
// It returns information on the installed runtime or an error if the installation fails.
func (m *Mise) InstallGlobal(ctx context.Context, runtime string) (string, error) {
if strings.HasPrefix(runtime, "php") {
return "", m.PHPInstaller(ctx, runtime)
}

// Install the runtime using mise
cmd := sys.Command(ctx, sys.CommandOpts{
Name: "mise",
Expand Down Expand Up @@ -241,6 +299,25 @@ func (m *Mise) ListGlobal(ctx context.Context) (map[string][]ListOutput, error)
return nil, err
}

// Check if PHP is installed
phpCmd := sys.Command(ctx, sys.CommandOpts{
Name: "php",
Args: []string{"-r", "echo phpversion();"},
})

version, _ := phpCmd.Output()

if version != nil {
data["php"] = []ListOutput{{
// We don't have the requested version info here
// so we set it to the same as Version
RequestedVersion: strings.TrimSpace(string(version)),
Version: strings.TrimSpace(string(version)),
Installed: true,
Active: true,
}}
}

return data, nil
}

Expand Down Expand Up @@ -273,7 +350,13 @@ func (m *Mise) updatePath(ctx context.Context, dir string) error {
return nil
}

os.Setenv("PATH", fmt.Sprintf("%s:%s", strings.Join(newPaths, ":"), os.Getenv("PATH")))
newPath := strings.Join(newPaths, ":")
oldPath := os.Getenv("PATH")
phpPath := m.phpDir()

// We are setting php path here even if it's not installed to make sure
// that if it gets installed later, it's already in the PATH.
os.Setenv("PATH", fmt.Sprintf("%s:%s:%s", newPath, oldPath, phpPath))

return nil
}
Expand Down
3 changes: 2 additions & 1 deletion src/ui/src/pages/admin/System.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import Card from "~/components/Card";
import CardRow from "~/components/CardRow";
import CardHeader from "~/components/CardHeader";
import CardFooter from "~/components/CardFooter";
import { stat } from "fs";

type Status = "ok" | "sent" | "processing" | "error";

Expand Down Expand Up @@ -54,6 +53,8 @@ const useFetchRuntimes = () => {
setStatus(s);
setInstalled(installed);

console.log("Runtimes status:", runtimes);

if (s !== "ok" && s !== "error") {
clearTimeout(timeout);
timeout = setTimeout(() => {
Expand Down
Loading