Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ability to lint and validate the nitric.yaml from json schema #735

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
return filepath.Join(NitricHomeDir(), "store")
}

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

Check warning on line 70 in pkg/paths/paths.go

View check run for this annotation

Codecov / codecov/patch

pkg/paths/paths.go#L69-L70

Added lines #L69 - L70 were not covered by tests
}

func NitricStacksDir() (string, error) {
homeDir := NitricHomeDir()
stacksDir := path.Join(homeDir, "stacks")
Expand Down
89 changes: 89 additions & 0 deletions pkg/schemas/nitric-yaml-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{
"$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."
},
{
"const": "sql-databases",
"description": "Use SQL Databases."
}
]
}
}
},
"required": ["name", "services"]
}
93 changes: 93 additions & 0 deletions pkg/schemas/schemas.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// 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)
}

Check warning on line 47 in pkg/schemas/schemas.go

View check run for this annotation

Codecov / codecov/patch

pkg/schemas/schemas.go#L36-L47

Added lines #L36 - L47 were not covered by tests
}

// 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 warning on line 55 in pkg/schemas/schemas.go

View check run for this annotation

Codecov / codecov/patch

pkg/schemas/schemas.go#L51-L55

Added lines #L51 - L55 were not covered by tests

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

Check warning on line 61 in pkg/schemas/schemas.go

View check run for this annotation

Codecov / codecov/patch

pkg/schemas/schemas.go#L58-L61

Added lines #L58 - L61 were not covered by tests

// 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)
}

Check warning on line 67 in pkg/schemas/schemas.go

View check run for this annotation

Codecov / codecov/patch

pkg/schemas/schemas.go#L64-L67

Added lines #L64 - L67 were not covered by tests

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)
}

Check warning on line 78 in pkg/schemas/schemas.go

View check run for this annotation

Codecov / codecov/patch

pkg/schemas/schemas.go#L69-L78

Added lines #L69 - L78 were not covered by tests

// 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)
}

Check warning on line 84 in pkg/schemas/schemas.go

View check run for this annotation

Codecov / codecov/patch

pkg/schemas/schemas.go#L81-L84

Added lines #L81 - L84 were not covered by tests

// 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)
}

Check warning on line 90 in pkg/schemas/schemas.go

View check run for this annotation

Codecov / codecov/patch

pkg/schemas/schemas.go#L87-L90

Added lines #L87 - L90 were not covered by tests

return nil

Check warning on line 92 in pkg/schemas/schemas.go

View check run for this annotation

Codecov / codecov/patch

pkg/schemas/schemas.go#L92

Added line #L92 was not covered by tests
}
Loading