mirror of
https://github.com/hanzoai/pack.git
synced 2026-09-30 23:43:13 +00:00
115 lines
3.4 KiB
Go
115 lines
3.4 KiB
Go
package plan
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"github.com/invopop/jsonschema"
|
|
)
|
|
|
|
type Step struct {
|
|
Name string `json:"name,omitempty" jsonschema:"description=The name of the step"`
|
|
Inputs []Input `json:"inputs,omitempty" jsonschema:"description=The inputs for this step"`
|
|
Commands []Command `json:"commands,omitempty" jsonschema:"description=The commands to run in this step"`
|
|
Secrets []string `json:"secrets,omitempty" jsonschema:"description=The secrets that this step uses"`
|
|
Assets map[string]string `json:"assets,omitempty" jsonschema:"description=The assets available to this step. The key is the name of the asset that is referenced in a file command"`
|
|
Variables map[string]string `json:"variables,omitempty" jsonschema:"description=The variables available to this step. The key is the name of the variable that is referenced in a variable command"`
|
|
Caches []string `json:"caches,omitempty" jsonschema:"description=The caches available to all commands in this step. Each cache must refer to a cache at the top level of the plan"`
|
|
}
|
|
|
|
func NewStep(name string) *Step {
|
|
return &Step{
|
|
Name: name,
|
|
Assets: make(map[string]string),
|
|
Variables: make(map[string]string),
|
|
Secrets: []string{"*"}, // default to using all secrets
|
|
}
|
|
}
|
|
|
|
func (s *Step) AddCommands(commands []Command) {
|
|
if s.Commands == nil {
|
|
s.Commands = []Command{}
|
|
}
|
|
s.Commands = append(s.Commands, commands...)
|
|
}
|
|
|
|
func (s *Step) UnmarshalJSON(data []byte) error {
|
|
type Alias Step
|
|
aux := &struct {
|
|
Commands *[]json.RawMessage `json:"commands"`
|
|
*Alias
|
|
}{
|
|
Alias: (*Alias)(s),
|
|
}
|
|
|
|
if err := json.Unmarshal(data, &aux); err != nil {
|
|
return err
|
|
}
|
|
|
|
if aux.Commands != nil {
|
|
s.Commands = []Command{}
|
|
for _, rawCmd := range *aux.Commands {
|
|
cmd, err := UnmarshalCommand(rawCmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
s.Commands = append(s.Commands, cmd)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (Step) JSONSchemaExtend(schema *jsonschema.Schema) {
|
|
// Remove name from the schema
|
|
var required []string
|
|
for _, prop := range schema.Required {
|
|
if prop != "name" {
|
|
required = append(required, prop)
|
|
}
|
|
}
|
|
schema.Required = required
|
|
schema.Properties.Delete("name")
|
|
|
|
// Add proper schemas for the commands
|
|
var commandsDescription string
|
|
if currCommandsSchema, ok := schema.Properties.Get("commands"); ok {
|
|
commandsDescription = currCommandsSchema.Description
|
|
}
|
|
|
|
commandSchema := &jsonschema.Schema{
|
|
Type: "array",
|
|
Description: commandsDescription,
|
|
Items: CommandsSchema(),
|
|
}
|
|
|
|
schema.Properties.Set("commands", commandSchema)
|
|
}
|
|
|
|
func CommandsSchema() *jsonschema.Schema {
|
|
execSchema := generateSchemaWithComments(ExecCommand{})
|
|
pathSchema := generateSchemaWithComments(PathCommand{})
|
|
copySchema := generateSchemaWithComments(CopyCommand{})
|
|
fileSchema := generateSchemaWithComments(FileCommand{})
|
|
|
|
availableCommands := []*jsonschema.Schema{execSchema, pathSchema, copySchema, fileSchema}
|
|
|
|
// Add string schema type as an additional valid command type
|
|
stringSchema := &jsonschema.Schema{
|
|
Type: "string",
|
|
Description: "Strings will be parsed and interpreted as a command to run",
|
|
}
|
|
availableCommands = append([]*jsonschema.Schema{stringSchema}, availableCommands...)
|
|
|
|
return &jsonschema.Schema{
|
|
OneOf: availableCommands,
|
|
}
|
|
}
|
|
|
|
func generateSchemaWithComments(v any) *jsonschema.Schema {
|
|
r := jsonschema.Reflector{
|
|
Anonymous: true,
|
|
DoNotReference: true,
|
|
}
|
|
return r.Reflect(v)
|
|
}
|