diff --git a/runtime/local/local.go b/runtime/local/local.go index 8ed52210..1807ddb6 100644 --- a/runtime/local/local.go +++ b/runtime/local/local.go @@ -286,8 +286,13 @@ func (r *localRuntime) Create(s *runtime.Service, opts ...runtime.CreateOption) options.Namespace = defaultNamespace } if len(options.Command) == 0 { + ep, err := Entrypoint(s.Source) + if err != nil { + return err + } + options.Command = []string{"go"} - options.Args = []string{"run", "."} + options.Args = []string{"run", ep} } // pass secrets as env vars @@ -633,3 +638,42 @@ func (r *localRuntime) Stop() error { func (r *localRuntime) String() string { return "local" } + +// Entrypoint determines the entrypoint for the service, since main.go doesn't always exist at +// the top level +func Entrypoint(dir string) (string, error) { + var entrypoints []string + + filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // get the relative path to the directory + rel, err := filepath.Rel(dir, path) + if err != nil { + return err + } + + // only look for files in the top level or the cmd folder + if dir := filepath.Dir(rel); !filepath.HasPrefix(dir, "cmd") && dir != "." { + return nil + } + + // only look for main.go files + if filepath.Base(rel) == "main.go" { + entrypoints = append(entrypoints, rel) + } + + return nil + }) + + switch len(entrypoints) { + case 0: + return "", errors.New("No entrypoint found") + case 1: + return entrypoints[0], nil + default: + return "", errors.New("More than one entrypoint found") + } +} diff --git a/runtime/local/local_test.go b/runtime/local/local_test.go new file mode 100644 index 00000000..b2f97b9f --- /dev/null +++ b/runtime/local/local_test.go @@ -0,0 +1,33 @@ +package local + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestEntrypoint(t *testing.T) { + wd, _ := os.Getwd() + + // test a service with idiomatic folder structure + result, err := Entrypoint(filepath.Join(wd, "test")) + assert.Nil(t, err, "Didn'expected entrypoint to return an error") + assert.Equal(t, "cmd/test/main.go", result, "Expected entrypoint to return cmd/test/main.go") + + // test a service with a top level main.go + result, err = Entrypoint(filepath.Join(wd, "test/bar")) + assert.Nil(t, err, "Didn'expected entrypoint to return an error") + assert.Equal(t, "main.go", result, "Expected entrypoint to return main.go") + + // test a service with multiple main.go files within the cmd folder + result, err = Entrypoint(filepath.Join(wd, "test/foo")) + assert.Error(t, err, "Expected entrypoint to return an error when multiple main.go files exist") + assert.Equal(t, "", result, "Expected entrypoint to not return a result") + + // test a service with no main.go files + result, err = Entrypoint(filepath.Join(wd, "test/empty")) + assert.Error(t, err, "Expected entrypoint to return an error when no main.go files exist") + assert.Equal(t, "", result, "Expected entrypoint to not return a result") +} diff --git a/runtime/local/test/bar/main.go b/runtime/local/test/bar/main.go new file mode 100644 index 00000000..9d5fa3a5 --- /dev/null +++ b/runtime/local/test/bar/main.go @@ -0,0 +1,4 @@ +// Package main is used to test the local runtime, specifically the entrypoint function +package main + +func main() {} diff --git a/runtime/local/test/cmd/test/main.go b/runtime/local/test/cmd/test/main.go new file mode 100644 index 00000000..9d5fa3a5 --- /dev/null +++ b/runtime/local/test/cmd/test/main.go @@ -0,0 +1,4 @@ +// Package main is used to test the local runtime, specifically the entrypoint function +package main + +func main() {} diff --git a/runtime/local/test/empty/empty.go b/runtime/local/test/empty/empty.go new file mode 100644 index 00000000..609cf0e0 --- /dev/null +++ b/runtime/local/test/empty/empty.go @@ -0,0 +1 @@ +package empty diff --git a/runtime/local/test/foo/cmd/bar/main.go b/runtime/local/test/foo/cmd/bar/main.go new file mode 100644 index 00000000..9d5fa3a5 --- /dev/null +++ b/runtime/local/test/foo/cmd/bar/main.go @@ -0,0 +1,4 @@ +// Package main is used to test the local runtime, specifically the entrypoint function +package main + +func main() {} diff --git a/runtime/local/test/foo/cmd/baz/main.go b/runtime/local/test/foo/cmd/baz/main.go new file mode 100644 index 00000000..9d5fa3a5 --- /dev/null +++ b/runtime/local/test/foo/cmd/baz/main.go @@ -0,0 +1,4 @@ +// Package main is used to test the local runtime, specifically the entrypoint function +package main + +func main() {}