diff --git a/cmd/check.go b/cmd/check.go index 696e20a67c..e416781e16 100644 --- a/cmd/check.go +++ b/cmd/check.go @@ -10,6 +10,7 @@ import ( "github.com/fatih/color" "github.com/spf13/cobra" "tidbyt.dev/pixlet/cmd/community" + "tidbyt.dev/pixlet/manifest" ) func init() { @@ -45,6 +46,8 @@ func checkCmd(cmd *cobra.Command, args []string) error { } } + // TODO: this needs to be parallelized. + // Check every app. foundIssue := false for _, app := range apps { @@ -64,13 +67,14 @@ func checkCmd(cmd *cobra.Command, args []string) error { } defer os.Remove(f.Name()) - // Check if app will render. - silenceOutput = true - output = f.Name() - err = render(cmd, []string{app}) + // TODO: Check if app will render once we are able to enable target + // determination. + + // Check if an app can load. + err = community.LoadApp(cmd, []string{app}) if err != nil { foundIssue = true - failure(app, fmt.Errorf("app failed to render: %w", err), fmt.Sprintf("try `pixlet render %s` and resolve any errors", app)) + failure(app, fmt.Errorf("app failed to load: %w", err), "try `pixlet community load-app` and resolve any runtime issues") continue } @@ -93,18 +97,14 @@ func checkCmd(cmd *cobra.Command, args []string) error { // Check app manifest exists dir := filepath.Dir(app) - options := []string{ - filepath.Join(dir, "manifest.yaml"), - filepath.Join(dir, "manifest.yml"), - } - manifestFile, err := findManifestFile(options) - if err != nil { + if !doesManifestExist(dir) { foundIssue = true - failure(app, fmt.Errorf("couldn't find app manifest: %w", err), fmt.Sprintf("try `pixlet community create-manifest %s`", filepath.Join(dir, "manifest.yaml"))) + failure(app, fmt.Errorf("couldn't find app manifest: %w", err), fmt.Sprintf("try `pixlet community create-manifest %s`", filepath.Join(dir, manifest.ManifestFileName))) continue } // Validate manifest. + manifestFile := filepath.Join(dir, manifest.ManifestFileName) err = community.ValidateManifest(cmd, []string{manifestFile}) if err != nil { foundIssue = true @@ -112,20 +112,16 @@ func checkCmd(cmd *cobra.Command, args []string) error { continue } - // Check spelling in both the app and the manifest. + // Check spelling. community.SilentSpelling = true - err = community.SpellCheck(cmd, []string{app}) - if err != nil { - foundIssue = true - failure(app, fmt.Errorf("app contains spelling errors: %w", err), fmt.Sprintf("try `pixlet community spell-check --fix %s`", app)) - continue - } err = community.SpellCheck(cmd, []string{manifestFile}) if err != nil { foundIssue = true failure(app, fmt.Errorf("manifest contains spelling errors: %w", err), fmt.Sprintf("try `pixlet community spell-check --fix %s`", manifestFile)) continue } + // TODO: enable spell check for apps once we can run it successfully + // against the community repo. // If we're here, the app and manifest are good to go! success(app) @@ -138,21 +134,18 @@ func checkCmd(cmd *cobra.Command, args []string) error { return nil } -func findManifestFile(options []string) (string, error) { - for _, file := range options { - _, err := os.Stat(file) - if os.IsNotExist(err) { - continue - } - - if err != nil { - return "", fmt.Errorf("couldn't check manifest existence: %w", err) - } +func doesManifestExist(dir string) bool { + file := filepath.Join(dir, manifest.ManifestFileName) + _, err := os.Stat(file) + if os.IsNotExist(err) { + return false + } - return file, nil + if err != nil { + return false } - return "", fmt.Errorf("manifest doesn't exist") + return true } func success(app string) { diff --git a/cmd/community/community.go b/cmd/community/community.go index a07834b788..0dca47d42b 100644 --- a/cmd/community/community.go +++ b/cmd/community/community.go @@ -7,6 +7,7 @@ import ( func init() { CommunityCmd.AddCommand(CreateManifestCmd) CommunityCmd.AddCommand(ListIconsCmd) + CommunityCmd.AddCommand(LoadAppCmd) CommunityCmd.AddCommand(SpellCheckCmd) CommunityCmd.AddCommand(TargetDeterminatorCmd) CommunityCmd.AddCommand(ValidateIconsCmd) diff --git a/cmd/community/createmanifest.go b/cmd/community/createmanifest.go index 53cf6e58cd..07137e77c6 100644 --- a/cmd/community/createmanifest.go +++ b/cmd/community/createmanifest.go @@ -6,6 +6,7 @@ import ( "path/filepath" "github.com/spf13/cobra" + "tidbyt.dev/pixlet/manifest" ) var CreateManifestCmd = &cobra.Command{ @@ -19,8 +20,8 @@ var CreateManifestCmd = &cobra.Command{ func CreateManifest(cmd *cobra.Command, args []string) error { fileName := filepath.Base(args[0]) - if fileName != "manifest.yaml" && fileName != "manifest.yml" { - return fmt.Errorf("supplied manifest must be named manifest.yaml or manifest.yml") + if fileName != manifest.ManifestFileName { + return fmt.Errorf("supplied manifest must be named %s", manifest.ManifestFileName) } f, err := os.Create(args[0]) diff --git a/cmd/community/loadapp.go b/cmd/community/loadapp.go new file mode 100644 index 0000000000..9fe01abf5b --- /dev/null +++ b/cmd/community/loadapp.go @@ -0,0 +1,41 @@ +package community + +import ( + "fmt" + "io/ioutil" + "strings" + + "github.com/spf13/cobra" + "tidbyt.dev/pixlet/runtime" +) + +var LoadAppCmd = &cobra.Command{ + Use: "load-app ", + Short: "Validates an app can be successfully loaded in our runtime.", + Example: ` pixlet community load-app app.star`, + Long: `This command ensures an app can be loaded into our runtime successfully.`, + Args: cobra.ExactArgs(1), + RunE: LoadApp, +} + +func LoadApp(cmd *cobra.Command, args []string) error { + script := args[0] + + if !strings.HasSuffix(script, ".star") { + return fmt.Errorf("script file must have suffix .star: %s", script) + } + + src, err := ioutil.ReadFile(script) + if err != nil { + return fmt.Errorf("failed to read file %s: %w", script, err) + } + runtime.InitCache(runtime.NewInMemoryCache()) + + applet := runtime.Applet{} + err = applet.Load(script, src, nil) + if err != nil { + return fmt.Errorf("failed to load applet: %w", err) + } + + return nil +} diff --git a/cmd/community/validatemanifest.go b/cmd/community/validatemanifest.go index f235578387..59ff12320e 100644 --- a/cmd/community/validatemanifest.go +++ b/cmd/community/validatemanifest.go @@ -21,8 +21,8 @@ validating the contents of each field.`, func ValidateManifest(cmd *cobra.Command, args []string) error { fileName := filepath.Base(args[0]) - if fileName != "manifest.yaml" && fileName != "manifest.yml" { - return fmt.Errorf("supplied manifest must be named manifest.yaml or manifest.yml") + if fileName != manifest.ManifestFileName { + return fmt.Errorf("supplied manifest must be named %s", manifest.ManifestFileName) } f, err := os.Open(args[0]) diff --git a/manifest/manifest.go b/manifest/manifest.go index b095086925..bfa0281318 100644 --- a/manifest/manifest.go +++ b/manifest/manifest.go @@ -9,6 +9,8 @@ import ( "gopkg.in/yaml.v3" ) +const ManifestFileName = "manifest.yaml" + // Manifest is a structure to define a starlark applet for Tidbyt in Go. type Manifest struct { // ID is the unique identifier of this app. It has to be globally unique, diff --git a/tools/generator/generator.go b/tools/generator/generator.go index 2a6348f367..b29f051d99 100644 --- a/tools/generator/generator.go +++ b/tools/generator/generator.go @@ -98,7 +98,7 @@ func (g *Generator) writeManifest(app *manifest.Manifest) error { var p string switch g.appType { case Community: - p = path.Join(g.root, appsDir, app.PackageName, app.FileName) + p = path.Join(g.root, appsDir, app.PackageName, manifestName) default: p = path.Join(g.root, manifestName) }