Integrate selected builds with candidate workflows
This commit is contained in:
@@ -16,7 +16,7 @@ import (
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/internal/process"
|
||||
)
|
||||
|
||||
const Usage = "usage: releasekit version\n releasekit check [--repo DIR] [--config FILE] VERSION\n releasekit publish [--repo DIR] [--config FILE] VERSION"
|
||||
const Usage = "usage: releasekit version\n releasekit check [--repo DIR] [--config FILE] VERSION\n releasekit publish [--repo DIR] [--config FILE] VERSION\n releasekit build [--repo DIR] [--config FILE] [--output DIR] VERSION"
|
||||
|
||||
type Command string
|
||||
|
||||
@@ -24,6 +24,7 @@ const (
|
||||
VersionCommand Command = "version"
|
||||
CheckAction Command = "check"
|
||||
PublishAction Command = "publish"
|
||||
BuildAction Command = "build"
|
||||
)
|
||||
|
||||
// Invocation contains parsed command settings owned by the CLI adapter.
|
||||
@@ -31,6 +32,7 @@ type Invocation struct {
|
||||
Command Command
|
||||
Repository string
|
||||
ConfigPath string
|
||||
OutputDir string
|
||||
Version string
|
||||
}
|
||||
|
||||
@@ -45,19 +47,23 @@ func Parse(args []string) (Invocation, error) {
|
||||
return Invocation{}, errors.New("version takes no arguments")
|
||||
}
|
||||
return Invocation{Command: VersionCommand}, nil
|
||||
case string(CheckAction), string(PublishAction):
|
||||
case string(CheckAction), string(PublishAction), string(BuildAction):
|
||||
action := Command(args[0])
|
||||
flags := flag.NewFlagSet(string(action), flag.ContinueOnError)
|
||||
flags.SetOutput(io.Discard)
|
||||
repository := flags.String("repo", ".", "repository directory")
|
||||
configPath := flags.String("config", "", "profile path")
|
||||
var outputDir string
|
||||
if action == BuildAction {
|
||||
flags.StringVar(&outputDir, "output", "", "build output directory")
|
||||
}
|
||||
if err := flags.Parse(args[1:]); err != nil {
|
||||
return Invocation{}, err
|
||||
}
|
||||
if flags.NArg() != 1 {
|
||||
return Invocation{}, fmt.Errorf("%s requires one version argument", action)
|
||||
}
|
||||
return Invocation{Command: action, Repository: *repository, ConfigPath: *configPath, Version: flags.Arg(0)}, nil
|
||||
return Invocation{Command: action, Repository: *repository, ConfigPath: *configPath, OutputDir: outputDir, Version: flags.Arg(0)}, nil
|
||||
default:
|
||||
return Invocation{}, fmt.Errorf("unknown command %q", args[0])
|
||||
}
|
||||
@@ -75,6 +81,14 @@ type Settings struct {
|
||||
Product string `json:"product"`
|
||||
Remote string `json:"remote,omitempty"`
|
||||
Checks []CheckCommand `json:"checks,omitempty"`
|
||||
Build *BuildSettings `json:"build,omitempty"`
|
||||
}
|
||||
|
||||
// BuildSettings selects the Go application package, artifact name, and targets.
|
||||
type BuildSettings struct {
|
||||
MainPackage string `json:"main_package,omitempty"`
|
||||
BinaryName string `json:"binary_name,omitempty"`
|
||||
Targets []string `json:"targets,omitempty"`
|
||||
}
|
||||
|
||||
// LoadSettings reads a profile path relative to repoDir unless it is absolute.
|
||||
@@ -122,6 +136,31 @@ func LoadSettings(repoDir, configPath string) (Settings, error) {
|
||||
return Settings{}, fmt.Errorf("profile %q: checks[%d].args must include a command", configPath, i)
|
||||
}
|
||||
}
|
||||
if settings.Build != nil {
|
||||
if len(settings.Build.Targets) != 0 {
|
||||
if strings.TrimSpace(settings.Build.MainPackage) == "" {
|
||||
return Settings{}, fmt.Errorf("profile %q: build.main_package is required when targets are selected", configPath)
|
||||
}
|
||||
if strings.TrimSpace(settings.Build.BinaryName) == "" {
|
||||
return Settings{}, fmt.Errorf("profile %q: build.binary_name is required when targets are selected", configPath)
|
||||
}
|
||||
if strings.ContainsAny(settings.Build.BinaryName, "/\\\r\n") {
|
||||
return Settings{}, fmt.Errorf("profile %q: build.binary_name must be a filename component", configPath)
|
||||
}
|
||||
}
|
||||
for i, target := range settings.Build.Targets {
|
||||
if strings.Count(target, "/") != 1 {
|
||||
return Settings{}, fmt.Errorf("profile %q: build.targets[%d] must be GOOS/GOARCH", configPath, i)
|
||||
}
|
||||
goos, goarch, _ := strings.Cut(target, "/")
|
||||
if strings.TrimSpace(goos) == "" || strings.TrimSpace(goarch) == "" {
|
||||
return Settings{}, fmt.Errorf("profile %q: build.targets[%d] must be GOOS/GOARCH", configPath, i)
|
||||
}
|
||||
if strings.ContainsAny(goos+goarch, "\\\r\n") {
|
||||
return Settings{}, fmt.Errorf("profile %q: build.targets[%d] contains an unsafe filename component", configPath, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user