Skip to content

Commit

Permalink
Revert "add jsonschema command"
Browse files Browse the repository at this point in the history
This reverts commit e1cda7f.
  • Loading branch information
WillAbides committed Jun 4, 2023
1 parent c8b98af commit f2df01d
Show file tree
Hide file tree
Showing 12 changed files with 285 additions and 74 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,6 @@ Commands:
cache clear clear the cache
version show bindown version
install-completions install shell completions
jsonschema output json schema for bindown config

Run "bindown <command> --help" for more information on a command.
```
Expand Down
17 changes: 0 additions & 17 deletions cmd/bindown/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"context"
"encoding/json"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -62,7 +61,6 @@ type rootCmd struct {

Version versionCmd `kong:"cmd,help='show bindown version'"`
InstallCompletions kongplete.InstallCompletions `kong:"cmd,help=${config_install_completions_help}"`
JSONSchema jsonschemaCmd `kong:"cmd,name='jsonschema',help='output json schema for bindown config'"`
}

var defaultConfigFilenames = []string{
Expand Down Expand Up @@ -340,18 +338,3 @@ func (d *extractCmd) Run(ctx *runContext) error {
}
return nil
}

type jsonschemaCmd struct{}

func (d *jsonschemaCmd) Run(ctx *runContext) error {
schema, err := bindown.GetJSONSchema()
if err != nil {
return err
}
b, err := json.MarshalIndent(schema, "", " ")
if err != nil {
return err
}
fmt.Fprintln(ctx.stdout, string(b))
return nil
}
2 changes: 1 addition & 1 deletion cmd/bindown/testutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (c *cmdRunner) runExpect(expectFunc func(*expect.Console), commandLine ...s

func mustConfigFromYAML(t *testing.T, yml string) *bindown.Config {
t.Helper()
got, err := bindown.ConfigFromYAML([]byte(yml))
got, err := bindown.ConfigFromYAML(context.Background(), []byte(yml))
require.NoError(t, err)
return got
}
Expand Down
1 change: 0 additions & 1 deletion docs/clihelp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,5 @@ Commands:
cache clear clear the cache
version show bindown version
install-completions install shell completions
jsonschema output json schema for bindown config

Run "bindown <command> --help" for more information on a command.
217 changes: 217 additions & 0 deletions internal/bindown/bindown.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://willabides.github.io/bindown/bindown.schema.json",
"$defs": {
"Dependency": {
"properties": {
"homepage": {
"type": "string",
"description": "The homepage for this dependency. Informational only."
},
"description": {
"type": "string",
"description": "A description of the dependency. Informational only."
},
"template": {
"type": "string",
"description": "A template for this dependency. Value is the name of a template in the templates section of this config.\nAny unset fields in this dependency will be set by values from the template. Overrides in the dependency\nand its template are concatenated with the template's overrides coming first. Vars and substitutions\nare both combined with the dependency's value taking precedence."
},
"url": {
"type": "string",
"description": "The url to download a dependency from."
},
"archive_path": {
"type": "string",
"description": "The path in the downloaded archive where the binary is located. Default is ./\u003cbin\u003e"
},
"bin": {
"type": "string",
"description": "The name of the binary to be installed. Default is the name of the dependency."
},
"link": {
"type": "boolean",
"description": "Whether to create a symlink to the bin instead of copying it."
},
"vars": {
"patternProperties": {
".*": {
"type": "string"
}
},
"type": "object",
"description": "A list of variables that can be used in 'url', 'archive_path' and 'bin'.\n\nTwo variables are always added based on the current environment: 'os' and 'arch'. Those are the operating\nsystem and architecture as defined by go's GOOS and GOARCH variables. I should document what those are\nsomewhere.\n\nYou can reference a variable using golang template syntax. For example, you could have a url set to\n`https://example.org/mydependency/v{{.version}}/mydependency-{{.os}}-{{.arch}}.tar.gz`. If you define the var\n'version: 1.2.3' and run bindown on a 64-bit Linux system, it will download\n`https://example.org/mydependency/v1.2.3/mydependency-linux-amd64.tar.gz`."
},
"overrides": {
"items": {
"$ref": "#/$defs/DependencyOverride"
},
"type": "array",
"description": "Overrides allows you to override values depending on the os and architecture of the target system."
},
"substitutions": {
"patternProperties": {
".*": {
"patternProperties": {
".*": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object",
"description": "Substitutions will substitute values from vars. The key is the name of the variable to substitute. The value is\na map of substitutions. { \"os\": { \"linux\": \"Linux\", \"darwin\": \"MacOS\" } } is an example of a substitution that\nwill update the os variable."
},
"systems": {
"items": {
"type": "string"
},
"type": "array",
"description": "List of systems this dependency supports. Systems are in the form of os/architecture."
},
"required_vars": {
"items": {
"type": "string"
},
"type": "array",
"description": "A list of variables that must be present for an install to succeed"
}
},
"additionalProperties": false,
"type": "object"
},
"DependencyOverride": {
"properties": {
"matcher": {
"patternProperties": {
".*": {
"items": {
"type": "string"
},
"type": "array"
}
},
"type": "object",
"description": "Limits the override to configurations matching all of the matchers. Keys may be \"os\", \"arch\" or any variable name.\nValues are an array of values to match. Any matching value will match. If a value can be interpreted as a\nsemantic version it will be treated as such."
},
"dependency": {
"$ref": "#/$defs/Overrideable",
"description": "Values to override the parent dependency"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"matcher",
"dependency"
]
},
"Overrideable": {
"properties": {
"url": {
"type": "string",
"description": "The url to download a dependency from."
},
"archive_path": {
"type": "string",
"description": "The path in the downloaded archive where the binary is located. Default is ./\u003cbin\u003e"
},
"bin": {
"type": "string",
"description": "The name of the binary to be installed. Default is the name of the dependency."
},
"link": {
"type": "boolean",
"description": "Whether to create a symlink to the bin instead of copying it."
},
"vars": {
"patternProperties": {
".*": {
"type": "string"
}
},
"type": "object",
"description": "A list of variables that can be used in 'url', 'archive_path' and 'bin'.\n\nTwo variables are always added based on the current environment: 'os' and 'arch'. Those are the operating\nsystem and architecture as defined by go's GOOS and GOARCH variables. I should document what those are\nsomewhere.\n\nYou can reference a variable using golang template syntax. For example, you could have a url set to\n`https://example.org/mydependency/v{{.version}}/mydependency-{{.os}}-{{.arch}}.tar.gz`. If you define the var\n'version: 1.2.3' and run bindown on a 64-bit Linux system, it will download\n`https://example.org/mydependency/v1.2.3/mydependency-linux-amd64.tar.gz`."
},
"overrides": {
"items": {
"$ref": "#/$defs/DependencyOverride"
},
"type": "array",
"description": "Overrides allows you to override values depending on the os and architecture of the target system."
},
"substitutions": {
"patternProperties": {
".*": {
"patternProperties": {
".*": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object",
"description": "Substitutions will substitute values from vars. The key is the name of the variable to substitute. The value is\na map of substitutions. { \"os\": { \"linux\": \"Linux\", \"darwin\": \"MacOS\" } } is an example of a substitution that\nwill update the os variable."
}
},
"additionalProperties": false,
"type": "object"
}
},
"properties": {
"cache": {
"type": "string",
"description": "The directory where bindown will cache downloads and extracted files. This is relative to the directory where\nthe configuration file resides. cache paths should always use / as a delimiter even on Windows or other\noperating systems where the native delimiter isn't /."
},
"install_dir": {
"type": "string",
"description": "The directory that bindown installs files to. This is relative to the directory where the configuration file\nresides. install_directory paths should always use / as a delimiter even on Windows or other operating systems\nwhere the native delimiter isn't /."
},
"systems": {
"items": {
"type": "string"
},
"type": "array",
"description": "List of systems supported by this config. Systems are in the form of os/architecture."
},
"dependencies": {
"patternProperties": {
".*": {
"$ref": "#/$defs/Dependency"
}
},
"type": "object",
"description": "Dependencies available for bindown to install."
},
"templates": {
"patternProperties": {
".*": {
"$ref": "#/$defs/Dependency"
}
},
"type": "object",
"description": "Templates that can be used by dependencies in this file."
},
"template_sources": {
"patternProperties": {
".*": {
"type": "string"
}
},
"type": "object",
"description": "Upstream sources for templates."
},
"url_checksums": {
"patternProperties": {
".*": {
"type": "string"
}
},
"type": "object",
"description": "Checksums of downloaded files."
}
},
"additionalProperties": false,
"type": "object"
}
8 changes: 4 additions & 4 deletions internal/bindown/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ func NewConfig(ctx context.Context, cfgSrc string, noDefaultDirs bool) (*Config,
if err != nil {
return nil, err
}
cfg, err := ConfigFromYAML(data)
cfg, err := ConfigFromYAML(ctx, data)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -680,11 +680,11 @@ func configFromHTTP(ctx context.Context, src string) (*Config, error) {
if err != nil {
return nil, err
}
return ConfigFromYAML(data)
return ConfigFromYAML(ctx, data)
}

func ConfigFromYAML(data []byte) (*Config, error) {
err := validateConfig(data)
func ConfigFromYAML(ctx context.Context, data []byte) (*Config, error) {
err := validateConfig(ctx, data)
if err != nil {
return nil, err
}
Expand Down
45 changes: 14 additions & 31 deletions internal/bindown/jsonschema.go
Original file line number Diff line number Diff line change
@@ -1,58 +1,41 @@
package bindown

import (
"context"
_ "embed"
"encoding/json"
"fmt"

"github.com/invopop/jsonschema"
validator "github.com/santhosh-tekuri/jsonschema/v5"
"github.com/santhosh-tekuri/jsonschema/v5"
"gopkg.in/yaml.v3"
)

var (
_jsonSchema *jsonschema.Schema
_jsonSchemaText []byte
)
//go:embed bindown.schema.json
var jsonSchemaText string

// validateConfig checks whether cfg meets the json schema.
func validateConfig(cfg []byte) error {
func validateConfig(ctx context.Context, cfg []byte) error {
var val any
err := yaml.Unmarshal(cfg, &val)
if err != nil {
return fmt.Errorf("config is not valid yaml (or json)")
}
if _jsonSchemaText == nil {
var s *jsonschema.Schema
s, err = GetJSONSchema()
if err != nil {
return err
}
_jsonSchemaText, err = json.Marshal(s)
if err != nil {
return err
}
}
vSchema, err := validator.CompileString("", string(_jsonSchemaText))
schema, err := jsonschema.CompileString("", jsonSchemaText)
if err != nil {
return err
}
err = vSchema.Validate(val)
err = schema.Validate(val)
if err != nil {
return fmt.Errorf("invalid config: %w", err)
}
return nil
}

func GetJSONSchema() (*jsonschema.Schema, error) {
if _jsonSchema == nil {
r := &jsonschema.Reflector{}
r.ExpandedStruct = true
err := r.AddGoComments("github.com/willabides/bindown/v4", "./")
if err != nil {
return nil, err
}
_jsonSchema = r.Reflect(&Config{})
_jsonSchema.ID = "https://willabides.github.io/bindown/bindown.schema.json"
func yaml2json(y []byte) ([]byte, error) {
var data any
err := yaml.Unmarshal(y, &data)
if err != nil {
return nil, err
}
return _jsonSchema, nil
return json.Marshal(data)
}
Loading

0 comments on commit f2df01d

Please sign in to comment.