140 lines
3.5 KiB
Go
140 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
)
|
|
|
|
func main() {
|
|
var bunDarwinAarch64 string
|
|
var bunDarwinX64 string
|
|
var bunLinuxAarch64 string
|
|
var bunLinuxX64 string
|
|
var bunWindowsX64 string
|
|
var packageDir string
|
|
var script string
|
|
|
|
flag.StringVar(&bunDarwinAarch64, "bun-darwin-aarch64", "", "")
|
|
flag.StringVar(&bunDarwinX64, "bun-darwin-x64", "", "")
|
|
flag.StringVar(&bunLinuxAarch64, "bun-linux-aarch64", "", "")
|
|
flag.StringVar(&bunLinuxX64, "bun-linux-x64", "", "")
|
|
flag.StringVar(&bunWindowsX64, "bun-windows-x64", "", "")
|
|
flag.StringVar(&packageDir, "package-dir", "", "")
|
|
flag.StringVar(&script, "script", "dev", "")
|
|
flag.Parse()
|
|
|
|
require(packageDir != "", "missing --package-dir")
|
|
|
|
bunPath, err := resolveBunBinary(bunDarwinAarch64, bunDarwinX64, bunLinuxAarch64, bunLinuxX64, bunWindowsX64)
|
|
must(err)
|
|
must(makeAbsolute(&bunPath))
|
|
|
|
workspaceRoot := os.Getenv("BUILD_WORKSPACE_DIRECTORY")
|
|
if workspaceRoot == "" {
|
|
returnError("BUILD_WORKSPACE_DIRECTORY is required for frontend dev sessions")
|
|
}
|
|
|
|
packageRoot := filepath.Join(workspaceRoot, filepath.FromSlash(packageDir))
|
|
if _, err := os.Stat(filepath.Join(packageRoot, "package.json")); err != nil {
|
|
returnError("frontend package.json not found in workspace package dir: " + packageRoot)
|
|
}
|
|
|
|
environment := append([]string{}, os.Environ()...)
|
|
environment = setPath(environment, buildPath(workspaceRoot, packageRoot))
|
|
|
|
command := exec.Command(bunPath, "--bun", "run", script)
|
|
command.Dir = packageRoot
|
|
command.Env = environment
|
|
command.Stdout = os.Stdout
|
|
command.Stderr = os.Stderr
|
|
command.Stdin = os.Stdin
|
|
|
|
if err := command.Run(); err != nil {
|
|
if exitError, ok := err.(*exec.ExitError); ok {
|
|
os.Exit(exitError.ExitCode())
|
|
}
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func resolveBunBinary(darwinAarch64 string, darwinX64 string, linuxAarch64 string, linuxX64 string, windowsX64 string) (string, error) {
|
|
switch runtime.GOOS + "/" + runtime.GOARCH {
|
|
case "darwin/arm64":
|
|
return darwinAarch64, nil
|
|
case "darwin/amd64":
|
|
return darwinX64, nil
|
|
case "linux/arm64":
|
|
return linuxAarch64, nil
|
|
case "linux/amd64":
|
|
return linuxX64, nil
|
|
case "windows/amd64":
|
|
return windowsX64, nil
|
|
default:
|
|
return "", fmt.Errorf("unsupported Bun exec platform: %s/%s", runtime.GOOS, runtime.GOARCH)
|
|
}
|
|
}
|
|
|
|
func buildPath(workspaceRoot string, packageRoot string) string {
|
|
entries := make([]string, 0, 4)
|
|
for _, candidate := range []string{
|
|
filepath.Join(packageRoot, "node_modules", ".bin"),
|
|
filepath.Join(workspaceRoot, "node_modules", ".bin"),
|
|
os.Getenv("PATH"),
|
|
} {
|
|
if candidate != "" {
|
|
entries = append(entries, candidate)
|
|
}
|
|
}
|
|
return strings.Join(entries, string(os.PathListSeparator))
|
|
}
|
|
|
|
func setPath(environment []string, pathValue string) []string {
|
|
return setEnv(environment, "PATH", pathValue)
|
|
}
|
|
|
|
func setEnv(environment []string, key string, value string) []string {
|
|
prefix := key + "="
|
|
for index, entry := range environment {
|
|
if strings.HasPrefix(entry, prefix) {
|
|
environment[index] = prefix + value
|
|
return environment
|
|
}
|
|
}
|
|
return append(environment, prefix+value)
|
|
}
|
|
|
|
func makeAbsolute(path *string) error {
|
|
if filepath.IsAbs(*path) {
|
|
return nil
|
|
}
|
|
|
|
absolutePath, err := filepath.Abs(*path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*path = absolutePath
|
|
return nil
|
|
}
|
|
|
|
func returnError(message string) {
|
|
fmt.Fprintln(os.Stderr, message)
|
|
os.Exit(1)
|
|
}
|
|
|
|
func must(err error) {
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func require(condition bool, message string) {
|
|
if !condition {
|
|
panic(message)
|
|
}
|
|
}
|