Add function to opportunistically load a bundle (#180)

It is not an error if a bundle cannot be found for this category.
This sets the stage for using bundle configuration in non-bundle
commands.
This commit is contained in:
Pieter Noordhuis 2023-01-27 16:57:39 +01:00 committed by GitHub
parent 035fb6514d
commit 9a1d908f79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 110 additions and 25 deletions

View File

@ -41,8 +41,10 @@ func Load(path string) (*Bundle, error) {
return bundle, nil
}
func LoadFromRoot() (*Bundle, error) {
root, err := getRoot()
// MustLoad returns a bundle configuration.
// It returns an error if a bundle was not found or could not be loaded.
func MustLoad() (*Bundle, error) {
root, err := mustGetRoot()
if err != nil {
return nil, err
}
@ -50,6 +52,23 @@ func LoadFromRoot() (*Bundle, error) {
return Load(root)
}
// TryLoad returns a bundle configuration if there is one, but doesn't fail if there isn't one.
// It returns an error if a bundle was found but could not be loaded.
// It returns a `nil` bundle if a bundle was not found.
func TryLoad() (*Bundle, error) {
root, err := tryGetRoot()
if err != nil {
return nil, err
}
// No root is fine in this function.
if root == "" {
return nil, nil
}
return Load(root)
}
func (b *Bundle) WorkspaceClient() *databricks.WorkspaceClient {
b.clientOnce.Do(func() {
var err error

View File

@ -39,3 +39,42 @@ func TestBundleCacheDir(t *testing.T) {
assert.NoError(t, err)
assert.True(t, strings.HasPrefix(cacheDir, projectDir))
}
func TestBundleMustLoadSuccess(t *testing.T) {
t.Setenv(envBundleRoot, "./tests/basic")
b, err := MustLoad()
require.NoError(t, err)
assert.Equal(t, "./tests/basic", b.Config.Path)
}
func TestBundleMustLoadFailureWithEnv(t *testing.T) {
t.Setenv(envBundleRoot, "./tests/doesntexist")
_, err := MustLoad()
require.Error(t, err, "not a directory")
}
func TestBundleMustLoadFailureIfNotFound(t *testing.T) {
chdir(t, t.TempDir())
_, err := MustLoad()
require.Error(t, err, "unable to find bundle root")
}
func TestBundleTryLoadSuccess(t *testing.T) {
t.Setenv(envBundleRoot, "./tests/basic")
b, err := TryLoad()
require.NoError(t, err)
assert.Equal(t, "./tests/basic", b.Config.Path)
}
func TestBundleTryLoadFailureWithEnv(t *testing.T) {
t.Setenv(envBundleRoot, "./tests/doesntexist")
_, err := TryLoad()
require.Error(t, err, "not a directory")
}
func TestBundleTryLoadOkIfNotFound(t *testing.T) {
chdir(t, t.TempDir())
b, err := TryLoad()
assert.NoError(t, err)
assert.Nil(t, b)
}

View File

@ -10,29 +10,56 @@ import (
const envBundleRoot = "BUNDLE_ROOT"
// getRoot returns the bundle root.
// If the `BUNDLE_ROOT` environment variable is set, we assume its value
// to be a valid bundle root. Otherwise we try to find it by traversing
// the path and looking for a project configuration file.
func getRoot() (string, error) {
// getRootEnv returns the value of the `BUNDLE_ROOT` environment variable
// if it set and is a directory. If the environment variable is set but
// is not a directory, it returns an error. If the environment variable is
// not set, it returns an empty string.
func getRootEnv() (string, error) {
path, ok := os.LookupEnv(envBundleRoot)
if ok {
stat, err := os.Stat(path)
if err == nil && !stat.IsDir() {
err = fmt.Errorf("not a directory")
}
if err != nil {
return "", fmt.Errorf(`invalid bundle root %s="%s": %w`, envBundleRoot, path, err)
}
return path, nil
if !ok {
return "", nil
}
stat, err := os.Stat(path)
if err == nil && !stat.IsDir() {
err = fmt.Errorf("not a directory")
}
if err != nil {
return "", fmt.Errorf(`invalid bundle root %s="%s": %w`, envBundleRoot, path, err)
}
return path, nil
}
// getRootWithTraversal returns the bundle root by traversing the filesystem
// from the working directory to the root looking for a configuration file.
func getRootWithTraversal() (string, error) {
wd, err := os.Getwd()
if err != nil {
return "", err
}
path, err = folders.FindDirWithLeaf(wd, config.FileName)
path, err := folders.FindDirWithLeaf(wd, config.FileName)
if err != nil {
return "", fmt.Errorf(`unable to locate bundle root`)
return "", fmt.Errorf(`unable to locate bundle root: %s not found`, config.FileName)
}
return path, nil
}
// mustGetRoot returns a bundle root or an error if one cannot be found.
func mustGetRoot() (string, error) {
path, err := getRootEnv()
if path != "" || err != nil {
return path, err
}
return getRootWithTraversal()
}
// tryGetRoot returns a bundle root or an empty string if one cannot be found.
func tryGetRoot() (string, error) {
// Note: an invalid value in the environment variable is still an error.
path, err := getRootEnv()
if path != "" || err != nil {
return path, err
}
// Note: traversal failing means the bundle root cannot be found.
path, _ = getRootWithTraversal()
return path, nil
}

View File

@ -34,7 +34,7 @@ func TestRootFromEnv(t *testing.T) {
t.Setenv(envBundleRoot, dir)
// It should pull the root from the environment variable.
root, err := getRoot()
root, err := mustGetRoot()
require.NoError(t, err)
require.Equal(t, root, dir)
}
@ -44,7 +44,7 @@ func TestRootFromEnvDoesntExist(t *testing.T) {
t.Setenv(envBundleRoot, filepath.Join(dir, "doesntexist"))
// It should pull the root from the environment variable.
_, err := getRoot()
_, err := mustGetRoot()
require.Errorf(t, err, "invalid bundle root")
}
@ -56,7 +56,7 @@ func TestRootFromEnvIsFile(t *testing.T) {
t.Setenv(envBundleRoot, f.Name())
// It should pull the root from the environment variable.
_, err = getRoot()
_, err = mustGetRoot()
require.Errorf(t, err, "invalid bundle root")
}
@ -65,7 +65,7 @@ func TestRootIfEnvIsEmpty(t *testing.T) {
t.Setenv(envBundleRoot, dir)
// It should pull the root from the environment variable.
_, err := getRoot()
_, err := mustGetRoot()
require.Errorf(t, err, "invalid bundle root")
}
@ -87,7 +87,7 @@ func TestRootLookup(t *testing.T) {
// It should find the project root from $PWD.
wd := chdir(t, "./a/b/c")
root, err := getRoot()
root, err := mustGetRoot()
require.NoError(t, err)
require.Equal(t, wd, root)
}
@ -99,6 +99,6 @@ func TestRootLookupError(t *testing.T) {
// It can't find a project root from a temporary directory.
_ = chdir(t, t.TempDir())
_, err := getRoot()
_, err := mustGetRoot()
require.ErrorContains(t, err, "unable to locate bundle root")
}

View File

@ -17,7 +17,7 @@ var rootCmd = &cobra.Command{
// and configures it on the command's context.
func ConfigureBundle(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
b, err := bundle.LoadFromRoot()
b, err := bundle.MustLoad()
if err != nil {
return err
}