Files
pack/cli/common.go
T
zeekay 7844a60aff refactor(pack): modernize to github.com/hanzoai/pack and remove upstream branding
- Migrate module path to github.com/hanzoai/pack across all Go packages
- Remove legacy upstream docs and competitor brand references
- Modernize LLM.md and mise.toml for pristine Hanzo Pack builder
2026-09-04 00:40:42 -07:00

129 lines
3.4 KiB
Go

package cli
import (
"encoding/json"
"fmt"
"github.com/charmbracelet/log"
"github.com/hanzoai/pack/core"
a "github.com/hanzoai/pack/core/app"
"github.com/hanzoai/pack/core/config"
"github.com/hanzoai/pack/core/mise"
"github.com/hanzoai/pack/core/plan"
"github.com/hanzoai/pack/internal/utils"
"github.com/urfave/cli/v3"
)
var Version string // This will be set by main
const (
// the command failed for a reason that will not change on a retry
ExitCodeFailure = 1
// EX_TEMPFAIL: the command failed for a transient reason (e.g. a network error
// downloading mise) and is worth retrying. Platforms that run Railpack in a
// build pipeline key their retry logic on this.
ExitCodeTransient = 75
)
func exitCodeForError(err error) int {
if mise.IsTemporary(err) {
return ExitCodeTransient
}
return ExitCodeFailure
}
func commonPlanFlags() []cli.Flag {
return []cli.Flag{
&cli.StringSliceFlag{
Name: "env",
Aliases: []string{"e"},
Usage: "environment variables to set",
},
&cli.StringSliceFlag{
Name: "previous",
Usage: "versions of packages used for previous builds (e.g. 'package@version')",
},
&cli.StringFlag{
Name: "build-cmd",
Usage: "build command to use",
},
&cli.StringFlag{
Name: "start-cmd",
Usage: "start command to use",
},
&cli.StringFlag{
Name: "config-file",
Usage: "relative path to railpack config file (default: railpack.json)",
},
&cli.BoolFlag{
Name: "error-missing-start",
Usage: "error if no start command is found",
},
}
}
func GenerateBuildResultForCommand(cmd *cli.Command) (*core.BuildResult, *a.App, *a.Environment, error) {
directory := cmd.Args().First()
if directory == "" {
return nil, nil, nil, cli.Exit("directory argument is required", ExitCodeFailure)
}
app, err := a.NewApp(directory)
if err != nil {
return nil, nil, nil, fmt.Errorf("error creating app: %w", err)
}
log.Debugf("Building %s", app.Source)
envsArgs := cmd.StringSlice("env")
env, err := a.FromEnvs(envsArgs)
if err != nil {
return nil, nil, nil, fmt.Errorf("error creating env: %w", err)
}
// if --verbose is passed as a CLI global argument, enable verbose mise logging so the user don't have to understand
// the railpack build system deeply to get this debugging information.
if cmd.Bool("verbose") && env.GetVariable("MISE_VERBOSE") == "" {
env.SetVariable("MISE_VERBOSE", "1")
}
previousVersions := utils.ParsePackageWithVersion(cmd.StringSlice("previous"))
generateOptions := &core.GenerateBuildPlanOptions{
RailpackVersion: Version,
BuildCommand: cmd.String("build-cmd"),
StartCommand: cmd.String("start-cmd"),
PreviousVersions: previousVersions,
ConfigFilePath: cmd.String("config-file"),
ErrorMissingStartCommand: cmd.Bool("error-missing-start"),
}
buildResult, err := core.GenerateBuildPlan(app, env, generateOptions)
if err != nil {
return nil, nil, nil, err
}
return buildResult, app, env, nil
}
// add $schema link to resulting map JSON for improved IDE experience when manually editing
func addSchemaToPlanMap(p *plan.BuildPlan) (map[string]any, error) {
if p == nil {
return map[string]any{"$schema": config.SchemaUrl}, nil
}
planBytes, err := json.Marshal(p)
if err != nil {
return nil, err
}
var planMap map[string]any
if err := json.Unmarshal(planBytes, &planMap); err != nil {
return nil, err
}
planMap["$schema"] = config.SchemaUrl
return planMap, nil
}