Skip to content

Commit

Permalink
feat: ability to lint and validate the nitric.yaml from json schema
Browse files Browse the repository at this point in the history
  • Loading branch information
davemooreuws committed Jun 12, 2024
1 parent 6e0a93d commit 68876c4
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 0 deletions.
7 changes: 7 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/spf13/cobra"

"github.com/nitrictech/cli/pkg/paths"
"github.com/nitrictech/cli/pkg/schemas"
"github.com/nitrictech/cli/pkg/update"
"github.com/nitrictech/cli/pkg/view/tui"
)
Expand Down Expand Up @@ -72,6 +73,12 @@ var rootCmd = &cobra.Command{
update.PrintOutdatedWarning()
// an unstyled \n is always needed at the end of the view to ensure the last line renders
fmt.Println()

// Check/install schemas
err := schemas.Install()
if err != nil {
tui.CheckErr(fmt.Errorf("Failed to create nitric schema. %w", err))
}
},
}

Expand Down
5 changes: 5 additions & 0 deletions pkg/paths/paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ func NitricTemplatesDir() string {
return filepath.Join(NitricHomeDir(), "store")
}

// NitricSchemasDir returns the directory to place schema related data.
func NitricSchemasDir() string {
return filepath.Join(NitricHomeDir(), "schemas")
}

func NitricStacksDir() (string, error) {
homeDir := NitricHomeDir()
stacksDir := path.Join(homeDir, "stacks")
Expand Down
85 changes: 85 additions & 0 deletions pkg/schemas/nitric-yaml-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "{{.Version}}",
"title": "JSON schema for the Nitric configuration file",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"description": "The name of the project."
},
"directory": {
"type": "string",
"description": "The directory of the project."
},
"services": {
"type": "array",
"description": "A list of service configurations.",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"match": {
"type": "string",
"description": "The file pattern to match service files."
},
"runtime": {
"type": "string",
"description": "This is the custom runtime version (is custom if not nil, we auto-detect a standard language runtime)."
},
"start": {
"type": "string",
"description": "The command to start the service. A $SERVICE_PATH environment variable is available which will specify the relative filepath of each matched service."
},
"type": {
"type": "string",
"description": "The type of the service.",
"enum": ["default", "memory-optimized"]
}
},
"required": ["match", "start"]
}
},
"runtimes": {
"type": "object",
"description": "A map of runtime configurations.",
"additionalProperties": {
"type": "object",
"properties": {
"dockerfile": {
"type": "string",
"description": "The path to the Dockerfile for this runtime."
},
"args": {
"type": "object",
"description": "Arguments for the Docker build.",
"additionalProperties": {
"type": "string"
}
}
},
"required": ["dockerfile"]
}
},
"preview": {
"type": "array",
"minItems": 1,
"description": "A list of preview features to enable. Checkout https://nitric.io/docs/reference/preview-features for the latest preview features.",
"items": {
"type": "string",
"oneOf": [
{
"const": "docker-providers",
"description": "Use docker containers to distribute nitric providers."
},
{
"const": "beta-providers",
"description": "Use nitric providers that are currently in beta."
}
]
}
}
},
"required": ["name", "services"]
}
92 changes: 92 additions & 0 deletions pkg/schemas/schemas.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright Nitric Pty Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package schemas

import (
"bytes"
_ "embed"
"fmt"
"html/template"
"os"
"path/filepath"

"github.com/nitrictech/cli/pkg/paths"
"github.com/nitrictech/cli/pkg/version"
)

//go:embed nitric-yaml-schema.json
var nitricYamlSchemaTemplate string

// NewProvider - Returns a new provider instance based on the given providerId string
// The providerId string is in the form of <org-name>/<provider-name>@<version>
func Install() error {
currentVersion := version.Version
dir := paths.NitricSchemasDir()
filePath := filepath.Join(dir, "nitric-yaml-schema.json")
versionFilePath := filepath.Join(dir, "version.lock")

// Ensure the Nitric Schemas Directory Exists
if _, err := os.Stat(dir); os.IsNotExist(err) {
err := os.MkdirAll(dir, 0o700)
if err != nil {
return fmt.Errorf("failed to create nitric schemas directory. %w", err)
}
}

// Read the existing version from the version file, if it exists
storedVersion, err := os.ReadFile(versionFilePath)
if err == nil {
// Remove trailing newline for comparison
storedVersion = bytes.TrimSpace(storedVersion)
}

// Check if the stored version matches the current version
if string(storedVersion) == currentVersion {
// Versions are the same, no need to update
return nil
}

// Prepare the template with the current version
tmpl, err := template.New("schema").Parse(nitricYamlSchemaTemplate)
if err != nil {
return fmt.Errorf("failed to parse nitric schema template: %w", err)
}

var content bytes.Buffer
err = tmpl.Execute(&content, struct {
Version string
}{
Version: currentVersion,
})
if err != nil {
return fmt.Errorf("failed to execute template for nitric schema file: %w", err)
}

// Write the new content to the schema file
err = os.WriteFile(filePath, content.Bytes(), 0o644)
if err != nil {
return fmt.Errorf("failed to write nitric schema file: %w", err)
}

// Write the new version lock
err = os.WriteFile(versionFilePath, []byte(currentVersion+"\n"), 0o644)
if err != nil {
return fmt.Errorf("failed to write nitric schema version lock file: %w", err)
}

return nil
}

0 comments on commit 68876c4

Please sign in to comment.