diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0b7dd74cef..c39d32a076 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -80,10 +80,17 @@ jobs: - name: Build frontend run: npm run build - - name: Build + - name: Build Linux run: make build if: matrix.os == 'ubuntu-22.04' || matrix.os == 'macos-latest' + - name: Build macOS + run: make build + if: matrix.os == 'macos-latest' + env: + LIBRARY_PATH: "/opt/homebrew/lib" + CGO_CPPFLAGS: "-I/opt/homebrew/include" + - name: Build Windows shell: msys2 {0} run: | @@ -91,9 +98,16 @@ jobs: make build if: matrix.os == 'windows-latest' - - name: Test + - name: Test Linux run: make test - if: matrix.os == 'ubuntu-22.04' || matrix.os == 'macos-latest' + if: matrix.os == 'ubuntu-22.04' + + - name: Test macOS + run: make test + if: matrix.os == 'macos-latest' + env: + LIBRARY_PATH: "/opt/homebrew/lib" + CGO_CPPFLAGS: "-I/opt/homebrew/include" - name: Test Windows shell: msys2 {0} @@ -126,6 +140,8 @@ jobs: run: make release-macos env: PIXLET_VERSION: ${{ steps.vars.outputs.tag }} + LIBRARY_PATH: "/opt/homebrew/lib" + CGO_CPPFLAGS: "-I/opt/homebrew/include" - name: Build Release Windows if: matrix.os == 'windows-latest' diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 5c3e7c593f..0f22cb3939 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -78,9 +78,16 @@ jobs: - name: Build frontend run: npm run build - - name: Build + - name: Build Linux run: make build - if: matrix.os == 'ubuntu-22.04' || matrix.os == 'macos-latest' + if: matrix.os == 'ubuntu-22.04' + + - name: Build macOS + run: make build + if: matrix.os == 'macos-latest' + env: + LIBRARY_PATH: "/opt/homebrew/lib" + CGO_CPPFLAGS: "-I/opt/homebrew/include" - name: Build Windows shell: msys2 {0} @@ -89,9 +96,16 @@ jobs: make build if: matrix.os == 'windows-latest' - - name: Test + - name: Test Linux + run: make test + if: matrix.os == 'ubuntu-22.04' + + - name: Test macOS run: make test - if: matrix.os == 'ubuntu-22.04' || matrix.os == 'macos-latest' + if: matrix.os == 'macos-latest' + env: + LIBRARY_PATH: "/opt/homebrew/lib" + CGO_CPPFLAGS: "-I/opt/homebrew/include" - name: Test Windows shell: msys2 {0} diff --git a/cmd/check.go b/cmd/check.go index 25e4254650..61f8a48476 100644 --- a/cmd/check.go +++ b/cmd/check.go @@ -2,29 +2,32 @@ package cmd import ( "fmt" + "io/fs" "os" "path/filepath" "strings" "time" - "github.com/bazelbuild/buildtools/buildifier/utils" "github.com/fatih/color" "github.com/spf13/cobra" "tidbyt.dev/pixlet/cmd/community" "tidbyt.dev/pixlet/manifest" + "tidbyt.dev/pixlet/tools" ) const MaxRenderTime = 1000000000 // 1000ms -func init() { - CheckCmd.Flags().BoolVarP(&rflag, "recursive", "r", false, "find apps recursively") -} - var CheckCmd = &cobra.Command{ - Use: "check ...", - Example: ` pixlet check app.star`, - Short: "Checks if an app is ready to publish", - Long: `The check command runs a series of checks to ensure your app is ready + Use: "check ...", + Example: `pixlet check examples/clock`, + Short: "Check if an app is ready to publish", + Long: `Check if an app is ready to publish. + +The path argument should be the path to the Pixlet app to check. The +app can be a single file with the .star extension, or a directory +containing multiple Starlark files and resources. + +The check command runs a series of checks to ensure your app is ready to publish in the community repo. Every failed check will have a solution provided. If your app fails a check, try the provided solution and reach out on Discord if you get stuck.`, @@ -33,85 +36,59 @@ Discord if you get stuck.`, } func checkCmd(cmd *cobra.Command, args []string) error { - // Use the same logic as buildifier to find relevant Tidbyt apps. - apps := args - if rflag { - discovered, err := utils.ExpandDirectories(&args) + // check every path. + foundIssue := false + for _, path := range args { + // check if path exists, and whether it is a directory or a file + info, err := os.Stat(path) if err != nil { - return fmt.Errorf("could not discover apps using recursive flag: %w", err) + return fmt.Errorf("failed to stat %s: %w", path, err) } - apps = discovered - } else { - for _, app := range apps { - if filepath.Ext(app) != ".star" { - return fmt.Errorf("only starlark source files or directories with the recursive flag are supported") - } - } - } - // TODO: this needs to be parallelized. + var fsys fs.FS + var baseDir string + if info.IsDir() { + fsys = os.DirFS(path) + baseDir = path + } else { + if !strings.HasSuffix(path, ".star") { + return fmt.Errorf("script file must have suffix .star: %s", path) + } - // Check every app. - foundIssue := false - for _, app := range apps { - // Check app formatting. - dryRunFlag = true - err := formatCmd(cmd, []string{app}) - if err != nil { - foundIssue = true - failure(app, fmt.Errorf("app is not formatted correctly: %w", err), fmt.Sprintf("try `pixlet format %s`", app)) - continue + fsys = tools.NewSingleFileFS(path) + baseDir = filepath.Dir(path) } // Check if an app can load. - err = community.LoadApp(cmd, []string{app}) - if err != nil { - foundIssue = true - failure(app, fmt.Errorf("app failed to load: %w", err), "try `pixlet community load-app` and resolve any runtime issues") - continue - } - - // Check if app is linted. - outputFormat = "off" - err = lintCmd(cmd, []string{app}) + err = community.LoadApp(cmd, []string{path}) if err != nil { foundIssue = true - failure(app, fmt.Errorf("app has lint warnings: %w", err), fmt.Sprintf("try `pixlet lint --fix %s`", app)) + failure(path, fmt.Errorf("app failed to load: %w", err), "try `pixlet community load-app` and resolve any runtime issues") continue } // Ensure icons are valid. - err = community.ValidateIcons(cmd, []string{app}) + err = community.ValidateIcons(cmd, []string{path}) if err != nil { foundIssue = true - failure(app, fmt.Errorf("app has invalid icons: %w", err), "try `pixlet community list-icons` for the full list of valid icons") + failure(path, fmt.Errorf("app has invalid icons: %w", err), "try `pixlet community list-icons` for the full list of valid icons") continue } // Check app manifest exists - dir := filepath.Dir(app) - if !doesManifestExist(dir) { + if !doesManifestExist(baseDir) { 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.ManifestFileName))) + failure(path, fmt.Errorf("couldn't find app manifest"), fmt.Sprintf("try `pixlet community create-manifest %s`", filepath.Join(baseDir, manifest.ManifestFileName))) continue } // Validate manifest. - manifestFile := filepath.Join(dir, manifest.ManifestFileName) - community.ValidateManifestAppFileName = filepath.Base(app) + manifestFile := filepath.Join(baseDir, manifest.ManifestFileName) + community.ValidateManifestAppFileName = filepath.Base(path) err = community.ValidateManifest(cmd, []string{manifestFile}) if err != nil { foundIssue = true - failure(app, fmt.Errorf("manifest didn't validate: %w", err), "try correcting the validation issue by updating your manifest") - continue - } - - // Check spelling. - community.SilentSpelling = true - 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)) + failure(path, fmt.Errorf("manifest didn't validate: %w", err), "try correcting the validation issue by updating your manifest") continue } @@ -125,26 +102,58 @@ func checkCmd(cmd *cobra.Command, args []string) error { // Check if app renders. silenceOutput = true output = f.Name() - err = render(cmd, []string{app}) + err = render(cmd, []string{path}) if err != nil { foundIssue = true - failure(app, fmt.Errorf("app failed to render: %w", err), "try `pixlet render` and resolve any runtime issues") + failure(path, fmt.Errorf("app failed to render: %w", err), "try `pixlet render` and resolve any runtime issues") continue } // Check performance. - p, err := ProfileApp(app, map[string]string{}) + p, err := ProfileApp(path, map[string]string{}) if err != nil { return fmt.Errorf("could not profile app: %w", err) } if p.DurationNanos > MaxRenderTime { foundIssue = true - failure(app, fmt.Errorf("app takes too long to render %s", time.Duration(p.DurationNanos)), fmt.Sprintf("try optimizing your app using `pixlet profile %s` to get it under %s", app, time.Duration(MaxRenderTime))) + failure( + path, + fmt.Errorf("app takes too long to render %s", time.Duration(p.DurationNanos)), + fmt.Sprintf("try optimizing your app using `pixlet profile %s` to get it under %s", path, time.Duration(MaxRenderTime)), + ) continue } + // run format and lint on *.star files in the fs + fs.WalkDir(fsys, ".", func(p string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() || !strings.HasSuffix(p, ".star") { + return nil + } + + realPath := filepath.Join(baseDir, p) + + dryRunFlag = true + if err := formatCmd(cmd, []string{realPath}); err != nil { + foundIssue = true + failure(p, fmt.Errorf("app is not formatted correctly: %w", err), fmt.Sprintf("try `pixlet format %s`", realPath)) + } + + outputFormat = "off" + err = lintCmd(cmd, []string{realPath}) + if err != nil { + foundIssue = true + failure(p, fmt.Errorf("app has lint warnings: %w", err), fmt.Sprintf("try `pixlet lint --fix %s`", realPath)) + } + + return nil + }) + // If we're here, the app and manifest are good to go! - success(app) + success(path) } if foundIssue { diff --git a/cmd/community/community.go b/cmd/community/community.go index aa8e3064ef..46c350e1c3 100644 --- a/cmd/community/community.go +++ b/cmd/community/community.go @@ -7,7 +7,6 @@ import ( func init() { CommunityCmd.AddCommand(ListIconsCmd) CommunityCmd.AddCommand(LoadAppCmd) - CommunityCmd.AddCommand(SpellCheckCmd) CommunityCmd.AddCommand(TargetDeterminatorCmd) CommunityCmd.AddCommand(ValidateIconsCmd) CommunityCmd.AddCommand(ValidateManifestCmd) diff --git a/cmd/community/loadapp.go b/cmd/community/loadapp.go index 8217976cb1..8fece80051 100644 --- a/cmd/community/loadapp.go +++ b/cmd/community/loadapp.go @@ -2,39 +2,50 @@ package community import ( "fmt" + "io/fs" "os" + "path/filepath" "strings" "github.com/spf13/cobra" "tidbyt.dev/pixlet/runtime" + "tidbyt.dev/pixlet/tools" ) var LoadAppCmd = &cobra.Command{ - Use: "load-app ", + Use: "load-app ", Short: "Validates an app can be successfully loaded in our runtime.", - Example: ` pixlet community load-app app.star`, + Example: `pixlet community load-app examples/clock`, 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] + path := args[0] - if !strings.HasSuffix(script, ".star") { - return fmt.Errorf("script file must have suffix .star: %s", script) + // check if path exists, and whether it is a directory or a file + info, err := os.Stat(path) + if err != nil { + return fmt.Errorf("failed to stat %s: %w", path, err) } - src, err := os.ReadFile(script) - if err != nil { - return fmt.Errorf("failed to read file %s: %w", script, err) + var fs fs.FS + if info.IsDir() { + fs = os.DirFS(path) + } else { + if !strings.HasSuffix(path, ".star") { + return fmt.Errorf("script file must have suffix .star: %s", path) + } + + fs = tools.NewSingleFileFS(path) } cache := runtime.NewInMemoryCache() runtime.InitHTTP(cache) runtime.InitCache(cache) - if _, err := runtime.NewApplet(script, src, runtime.WithPrintDisabled()); err != nil { + if _, err := runtime.NewAppletFromFS(filepath.Base(path), fs, runtime.WithPrintDisabled()); err != nil { return fmt.Errorf("failed to load applet: %w", err) } diff --git a/cmd/community/spellcheck.go b/cmd/community/spellcheck.go deleted file mode 100644 index 1aebcd0c5f..0000000000 --- a/cmd/community/spellcheck.go +++ /dev/null @@ -1,98 +0,0 @@ -package community - -import ( - "fmt" - "io" - "os" - - "github.com/client9/misspell" - "github.com/spf13/cobra" -) - -var ( - FixSpelling bool - SilentSpelling bool -) - -func init() { - SpellCheckCmd.Flags().BoolVarP(&FixSpelling, "fix", "f", false, "fixes spelling mistakes automatically") - SpellCheckCmd.Flags().BoolVarP(&SilentSpelling, "silent", "s", false, "silences spelling mistakes") -} - -var SpellCheckCmd = &cobra.Command{ - Use: "spell-check ", - Short: "Spell check for a file", - Example: ` pixlet community spell-check manifest.yaml - pixlet community spell-check app.star`, - Long: `This command checks the spelling of strings located in a file. This can be used -both for a manifest and Tidbyt app.`, - Args: cobra.ExactArgs(1), - RunE: SpellCheck, -} - -func SpellCheck(cmd *cobra.Command, args []string) error { - // Load file for checking. - f, err := os.OpenFile(args[0], os.O_RDWR, 0644) - if err != nil { - return fmt.Errorf("could not open file: %w", err) - } - defer f.Close() - - b, err := io.ReadAll(f) - if err != nil { - return fmt.Errorf("could not read file: %w", err) - } - - // Create replacer. - r := misspell.Replacer{ - Replacements: misspell.DictMain, - } - - // Tidbyt is primarily in US markets. We only ship a US power plug, and all - // materials are in the US locale. In the future, we will need to consider - // how we manage spell check as we look to support more markets. - r.AddRuleList(misspell.DictAmerican) - r.Compile() - - // Run replacer. - updated, diffs := r.Replace(string(b)) - - // If FixSpelling is true, we only want to fix spelling and return - if FixSpelling { - // Updating a file in line gets a bit tricky. The file would first have - // to be cleared of the file contents, which feels dangerous. So - // instead, create a temp file, write the contents, and then replace - // the original file with the new file. - temp := args[0] + ".temp" - t, err := os.Create(temp) - if err != nil { - return fmt.Errorf("could not create file: %w", err) - } - defer t.Close() - - _, err = t.WriteString(updated) - if err != nil { - return fmt.Errorf("could not update file: %w", err) - } - - err = os.Rename(temp, args[0]) - if err != nil { - return fmt.Errorf("could not replace file: %w", err) - } - - return nil - } - - if !SilentSpelling { - for _, diff := range diffs { - fmt.Printf("`%s` is a misspelling of `%s` at line: %d\n", diff.Original, diff.Corrected, diff.Line) - } - } - - // Return error if there are any diffs. - if len(diffs) > 0 { - return fmt.Errorf("%s contains spelling errors", args[0]) - } - - return nil -} diff --git a/cmd/community/validateicons.go b/cmd/community/validateicons.go index f6d055afb1..d693995bd2 100644 --- a/cmd/community/validateicons.go +++ b/cmd/community/validateicons.go @@ -3,20 +3,22 @@ package community import ( "encoding/json" "fmt" - "io" + "io/fs" "os" + "path/filepath" + "strings" "github.com/spf13/cobra" - "go.starlark.net/starlark" "tidbyt.dev/pixlet/icons" "tidbyt.dev/pixlet/runtime" "tidbyt.dev/pixlet/schema" + "tidbyt.dev/pixlet/tools" ) var ValidateIconsCmd = &cobra.Command{ - Use: "validate-icons ", + Use: "validate-icons ", Short: "Validates the schema icons used are available in our mobile app.", - Example: ` pixlet community validate-icons app.star`, + Example: `pixlet community validate-icons examples/schema_hello_world`, Long: `This command determines if the icons selected in your app schema are supported by our mobile app.`, Args: cobra.ExactArgs(1), @@ -24,29 +26,30 @@ by our mobile app.`, } func ValidateIcons(cmd *cobra.Command, args []string) error { - f, err := os.Open(args[0]) + path := args[0] + + // check if path exists, and whether it is a directory or a file + info, err := os.Stat(path) if err != nil { - return fmt.Errorf("couldn't open app: %w", err) + return fmt.Errorf("failed to stat %s: %w", path, err) } - defer f.Close() - src, err := io.ReadAll(f) - if err != nil { - return fmt.Errorf("failed to read app %s: %w", args[0], err) + var fs fs.FS + if info.IsDir() { + fs = os.DirFS(path) + } else { + if !strings.HasSuffix(path, ".star") { + return fmt.Errorf("script file must have suffix .star: %s", path) + } + + fs = tools.NewSingleFileFS(path) } cache := runtime.NewInMemoryCache() runtime.InitHTTP(cache) runtime.InitCache(cache) - // Remove the print function from the starlark thread. - initializers := []runtime.ThreadInitializer{} - initializers = append(initializers, func(thread *starlark.Thread) *starlark.Thread { - thread.Print = func(thread *starlark.Thread, msg string) {} - return thread - }) - - applet, err := runtime.NewApplet(args[0], src, runtime.WithPrintDisabled()) + applet, err := runtime.NewAppletFromFS(filepath.Base(path), fs, runtime.WithPrintDisabled()) if err != nil { return fmt.Errorf("failed to load applet: %w", err) } diff --git a/cmd/lint.go b/cmd/lint.go index eaec00b9ab..104507c48e 100644 --- a/cmd/lint.go +++ b/cmd/lint.go @@ -48,11 +48,6 @@ func lintCmd(cmd *cobra.Command, args []string) error { differ, _ := differ.Find() diff = differ - // TODO: We currently offer misspelling protection in the community repo - // for app manifests. We'll want to consider adding additional spelling - // support to pixlet lint to ensure typos in apps don't make it to - // production. - // Run buildifier and exit with the returned exit code. exitCode := runBuildifier(args, lint, mode, outputFormat, rflag, vflag) if exitCode != 0 { diff --git a/cmd/profile.go b/cmd/profile.go index 27d5a9b7e2..1a4d691d9b 100644 --- a/cmd/profile.go +++ b/cmd/profile.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "io/fs" "os" "strings" "time" @@ -14,6 +15,7 @@ import ( "go.starlark.net/starlark" "tidbyt.dev/pixlet/runtime" + "tidbyt.dev/pixlet/tools" ) var ( @@ -27,8 +29,8 @@ func init() { } var ProfileCmd = &cobra.Command{ - Use: "profile [script] [=value>]...", - Short: "Run a Pixlet script and print its execution-time profile", + Use: "profile [=value>]...", + Short: "Run a Pixlet app and print its execution-time profile", Args: cobra.MinimumNArgs(1), RunE: profile, } @@ -65,11 +67,7 @@ func (u printUI) WantBrowser() bool { return false } func (u printUI) SetAutoComplete(complete func(string) string) {} func profile(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) - } + path := args[0] config := map[string]string{} for _, param := range args[1:] { @@ -80,7 +78,7 @@ func profile(cmd *cobra.Command, args []string) error { config[split[0]] = split[1] } - profile, err := ProfileApp(script, config) + profile, err := ProfileApp(path, config) if err != nil { return err } @@ -96,17 +94,28 @@ func profile(cmd *cobra.Command, args []string) error { return nil } -func ProfileApp(script string, config map[string]string) (*pprof_profile.Profile, error) { - src, err := os.ReadFile(script) +func ProfileApp(path string, config map[string]string) (*pprof_profile.Profile, error) { + info, err := os.Stat(path) if err != nil { - return nil, fmt.Errorf("failed to read file %s: %w", script, err) + return nil, fmt.Errorf("failed to stat %s: %w", path, err) + } + + var fsys fs.FS + if info.IsDir() { + fsys = os.DirFS(path) + } else { + if !strings.HasSuffix(path, ".star") { + return nil, fmt.Errorf("script file must have suffix .star: %s", path) + } + + fsys = tools.NewSingleFileFS(path) } cache := runtime.NewInMemoryCache() runtime.InitHTTP(cache) runtime.InitCache(cache) - applet, err := runtime.NewApplet(script, src, runtime.WithPrintDisabled()) + applet, err := runtime.NewAppletFromFS(path, fsys, runtime.WithPrintDisabled()) if err != nil { return nil, fmt.Errorf("failed to load applet: %w", err) } diff --git a/cmd/render.go b/cmd/render.go index d64327c78c..e7c532c4c0 100644 --- a/cmd/render.go +++ b/cmd/render.go @@ -8,7 +8,6 @@ import ( "os" "path/filepath" "strings" - "testing/fstest" "time" "github.com/spf13/cobra" @@ -16,6 +15,7 @@ import ( "tidbyt.dev/pixlet/encode" "tidbyt.dev/pixlet/globals" "tidbyt.dev/pixlet/runtime" + "tidbyt.dev/pixlet/tools" ) var ( @@ -102,15 +102,7 @@ func render(cmd *cobra.Command, args []string) error { return fmt.Errorf("script file must have suffix .star: %s", path) } - src, err := os.ReadFile(path) - if err != nil { - return fmt.Errorf("failed to read file %s: %w", path, err) - } - - fs = fstest.MapFS{ - filepath.Base(path): {Data: src}, - } - + fs = tools.NewSingleFileFS(path) outPath = strings.TrimSuffix(path, ".star") } diff --git a/go.mod b/go.mod index 962910d4b3..228bc50f82 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/Code-Hex/Neo-cowsay/v2 v2.0.4 github.com/antchfx/xmlquery v1.4.0 github.com/bazelbuild/buildtools v0.0.0-20230425225026-3dcc8d67e8ea - github.com/client9/misspell v0.3.4 github.com/dustin/go-humanize v1.0.1 github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 github.com/fatih/color v1.16.0 diff --git a/go.sum b/go.sum index e874881344..86b6fb1b2f 100644 --- a/go.sum +++ b/go.sum @@ -51,7 +51,6 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= @@ -90,8 +89,6 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -116,8 +113,6 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.15.1 h1:BSe8uhN+xQ4r5guV/ywQI4gO59C2raYcGffYWZEjZzM= -github.com/go-playground/validator/v10 v10.15.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -161,8 +156,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/pprof v0.0.0-20240416155748-26353dc0451f h1:WpZiq8iqvGjJ3m3wzAVKL6+0vz7VkE79iSy9GII00II= -github.com/google/pprof v0.0.0-20240416155748-26353dc0451f/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w= @@ -202,8 +195,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -332,7 +323,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= diff --git a/icons/icons.go b/icons/icons.go index 1b4661eb8d..12f71f96b2 100644 --- a/icons/icons.go +++ b/icons/icons.go @@ -1,4 +1,3 @@ -//nolint:misspell package icons // IconsMap is the name of a FontAwesome icon to the name in our mobile app. In diff --git a/runtime/applet.go b/runtime/applet.go index 2bac67fe01..0c4ddddc5c 100644 --- a/runtime/applet.go +++ b/runtime/applet.go @@ -11,9 +11,9 @@ import ( "testing" "testing/fstest" + starlibbsoup "github.com/qri-io/starlib/bsoup" starlibgzip "github.com/qri-io/starlib/compress/gzip" starlibbase64 "github.com/qri-io/starlib/encoding/base64" - starlibbsoup "github.com/qri-io/starlib/bsoup" starlibcsv "github.com/qri-io/starlib/encoding/csv" starlibhash "github.com/qri-io/starlib/hash" starlibhtml "github.com/qri-io/starlib/html" @@ -311,24 +311,21 @@ func (a *Applet) PathsForBundle() []string { } func (a *Applet) load(fsys fs.FS) (err error) { - if err := fs.WalkDir(fsys, ".", func(pathToLoad string, d fs.DirEntry, walkDirErr error) error { - if walkDirErr != nil { - return walkDirErr - } + // list files in the root directory of fsys + rootDir, err := fs.ReadDir(fsys, ".") + if err != nil { + return fmt.Errorf("reading root directory: %v", err) + } - if d.IsDir() || path.Dir(pathToLoad) != "." { - // only process files in the root directory - return nil + for _, d := range rootDir { + if d.IsDir() || !strings.HasSuffix(d.Name(), ".star") { + // only process Starlark files + continue } - if !strings.HasSuffix(pathToLoad, ".star") { - // not a starlark file - return nil + if err := a.ensureLoaded(fsys, d.Name()); err != nil { + return err } - - return a.ensureLoaded(fsys, pathToLoad) - }); err != nil { - return err } if a.mainFun == nil {