core/plan/step.go
core/plan/step.goBrowse 1970 files
829 tokens
3,497 bytes
Token encoding: o200k_base
Snapshot 21a254f
← Back to SKILL.md
1package plan2 3import (4 "encoding/json"5 6 "github.com/invopop/jsonschema"7)8 9type Step struct {10 Name string `json:"name,omitempty" jsonschema:"description=The name of the step"`11 Inputs []Layer `json:"inputs,omitempty" jsonschema:"description=The inputs for this step"`12 Commands []Command `json:"commands,omitempty" jsonschema:"description=The commands to run in this step"`13 Secrets []string `json:"secrets,omitempty" jsonschema:"description=The secrets that this step uses"`14 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"`15 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"`16 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"`17}18 19func NewStep(name string) *Step {20 return &Step{21 Name: name,22 Assets: make(map[string]string),23 Variables: make(map[string]string),24 Secrets: []string{"*"}, // default to using all secrets25 }26}27 28func (s *Step) AddCommands(commands []Command) {29 if s.Commands == nil {30 s.Commands = []Command{}31 }32 s.Commands = append(s.Commands, commands...)33}34 35func (s *Step) UnmarshalJSON(data []byte) error {36 type Alias Step37 aux := &struct {38 Commands *[]json.RawMessage `json:"commands"`39 *Alias40 }{41 Alias: (*Alias)(s),42 }43 44 if err := json.Unmarshal(data, &aux); err != nil {45 return err46 }47 48 if aux.Commands != nil {49 s.Commands = []Command{}50 for _, rawCmd := range *aux.Commands {51 cmd, err := UnmarshalCommand(rawCmd)52 if err != nil {53 return err54 }55 s.Commands = append(s.Commands, cmd)56 }57 }58 59 return nil60}61 62func (Step) JSONSchemaExtend(schema *jsonschema.Schema) {63 // Remove name from the schema64 var required []string65 for _, prop := range schema.Required {66 if prop != "name" {67 required = append(required, prop)68 }69 }70 schema.Required = required71 schema.Properties.Delete("name")72 73 // Add proper schemas for the commands74 var commandsDescription string75 if currCommandsSchema, ok := schema.Properties.Get("commands"); ok {76 commandsDescription = currCommandsSchema.Description77 }78 79 commandSchema := &jsonschema.Schema{80 Type: "array",81 Description: commandsDescription,82 Items: CommandsSchema(),83 }84 85 schema.Properties.Set("commands", commandSchema)86}87 88func CommandsSchema() *jsonschema.Schema {89 execSchema := generateSchemaWithComments(ExecCommand{})90 pathSchema := generateSchemaWithComments(PathCommand{})91 copySchema := generateSchemaWithComments(CopyCommand{})92 fileSchema := generateSchemaWithComments(FileCommand{})93 94 availableCommands := []*jsonschema.Schema{execSchema, pathSchema, copySchema, fileSchema}95 96 // Add string schema type as an additional valid command type97 stringSchema := &jsonschema.Schema{98 Type: "string",99 Description: "Strings will be parsed and interpreted as a command to run",100 }101 availableCommands = append([]*jsonschema.Schema{stringSchema}, availableCommands...)102 103 return &jsonschema.Schema{104 OneOf: availableCommands,105 }106}107 108func generateSchemaWithComments(v any) *jsonschema.Schema {109 r := jsonschema.Reflector{110 Anonymous: true,111 DoNotReference: true,112 }113 return r.Reflect(v)114}115