diff --git a/internal/commands/doc.go b/internal/commands/doc.go index 1940435b..26ba08ce 100644 --- a/internal/commands/doc.go +++ b/internal/commands/doc.go @@ -1,10 +1,16 @@ package commands import ( + "github.com/hazelops/ize/internal/schema" "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" + "golang.org/x/text/cases" + "golang.org/x/text/language" "os" + "path/filepath" + "strings" + "text/template" ) func NewCmdDoc() *cobra.Command { @@ -25,6 +31,26 @@ func NewCmdDoc() *cobra.Command { return err } + sections := []string{"main", "terraform", "ecs", "alias", "serverless", "tunnel"} + + err = os.MkdirAll("./website/schema", 0777) + if err != nil { + return err + } + + t := template.New("schema") + t, err = t.Parse(sectionTmpl) + if err != nil { + return err + } + + for _, s := range sections { + err := generateSection(s, t) + if err != nil { + return err + } + } + pterm.Success.Printfln("Docs generated") return nil @@ -33,3 +59,42 @@ func NewCmdDoc() *cobra.Command { return cmd } + +func generateSection(name string, t *template.Template) error { + s := schema.GetSchema() + filename := "README.md" + if name != "main" { + filename = strings.ToUpper(name) + ".md" + s = schema.GetSchema()[name].Items + } + f, err := os.Create(filepath.Join(".", "website", "schema", filename)) + if err != nil { + return err + } + + err = t.Execute(f, Section{ + Name: cases.Title(language.Und).String(name), + Items: s, + }) + if err != nil { + return err + } + err = f.Close() + if err != nil { + return err + } + + return nil +} + +type Section struct { + Name string + schema.Items +} + +var sectionTmpl = `# {{.Name}} Section +| Parameter | Required | Description | +| --- | --- | --- | +{{range $k, $v := .Items}}| {{$k}} | {{if $v.Required}}yes{{else}}no{{end}}| {{$v.Description}} | +{{end}} +` diff --git a/internal/schema/ize-spec.json b/internal/schema/ize-spec.json index 0fb46f19..cbdf04bf 100644 --- a/internal/schema/ize-spec.json +++ b/internal/schema/ize-spec.json @@ -119,7 +119,7 @@ "$ref": "#/definitions/app" } }, - "description": "Apps configuration.", + "description": "(deprecated) Apps configuration.", "additionalProperties": false }, "ecs": { @@ -205,7 +205,7 @@ "description": "(optional) Terraform-specific AWS profile (optional) can be specified here (but normally it should be inherited from a global AWS_PROFILE)." } }, - "description": "Infrastructure configuration.", + "description": "(deprecated) Infrastructure configuration.", "additionalProperties": false }, "tunnel": { @@ -308,7 +308,7 @@ "description": "(optional) expresses startup and shutdown dependencies between apps" } }, - "description": "App configuration.", + "description": "(deprecated) App configuration.", "additionalProperties": false }, "ecs": { diff --git a/internal/schema/schema.go b/internal/schema/schema.go index 0c17c6de..284132cd 100644 --- a/internal/schema/schema.go +++ b/internal/schema/schema.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/santhosh-tekuri/jsonschema" "github.com/xeipuuv/gojsonschema" + "golang.org/x/exp/slices" "strings" // Enable support for embedded static resources @@ -55,3 +56,62 @@ func GetJsonSchema() interface{} { return json } + +func GetSchema() Items { + compiler := jsonschema.NewCompiler() + compiler.Draft = jsonschema.Draft7 + if err := compiler.AddResource("schema.json", strings.NewReader(Schema)); err != nil { + panic(err) + } + compiler.ExtractAnnotations = true + schema, err := compiler.Compile("schema.json") + if err != nil { + panic(err) + } + + items := Items{} + getProperties(items, schema) + + return items +} + +func getProperties(items Items, schema *jsonschema.Schema) { + for k, v := range schema.Properties { + if strings.Contains(v.Description, "deprecated") { + continue + } + if !slices.Contains(v.Types, "object") { + r := slices.Contains(schema.Required, k) + items[k] = Item{ + Default: v.Default, + Required: r, + Description: v.Description, + } + } else { + r := slices.Contains(schema.Required, k) + i := Items{} + if len(v.PatternProperties) == 0 { + getProperties(i, v) + } else { + for _, p := range v.PatternProperties { + getProperties(i, p.Ref) + } + } + items[k] = Item{ + Default: v.Default, + Required: r, + Description: v.Description, + Items: i, + } + } + } +} + +type Item struct { + Default interface{} + Required bool + Description string + Items Items +} + +type Items map[string]Item