From 8eeb6dcf158f05725b83a5b2bc8ad99af0b7239a Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:10:57 +0100 Subject: [PATCH 01/24] WIP --- bundle/artifacts/all.go | 42 ---------- bundle/artifacts/artifacts.go | 74 ----------------- bundle/artifacts/build.go | 80 +++++++++++-------- bundle/artifacts/expand_globs.go | 10 +-- bundle/artifacts/infer.go | 65 --------------- bundle/artifacts/prepare.go | 58 -------------- bundle/artifacts/whl/autodetect.go | 62 -------------- bundle/artifacts/whl/build.go | 57 ------------- bundle/artifacts/whl/infer.go | 48 ----------- bundle/artifacts/whl/prepare.go | 53 ------------ bundle/artifacts/whl/testdata/setup.py | 15 ---- .../artifacts/whl/testdata/setup_incorrect.py | 14 ---- .../artifacts/whl/testdata/setup_minimal.py | 3 - bundle/phases/build.go | 6 +- bundle/phases/initialize.go | 2 + 15 files changed, 52 insertions(+), 537 deletions(-) delete mode 100644 bundle/artifacts/all.go delete mode 100644 bundle/artifacts/artifacts.go delete mode 100644 bundle/artifacts/infer.go delete mode 100644 bundle/artifacts/prepare.go delete mode 100644 bundle/artifacts/whl/autodetect.go delete mode 100644 bundle/artifacts/whl/build.go delete mode 100644 bundle/artifacts/whl/infer.go delete mode 100644 bundle/artifacts/whl/prepare.go delete mode 100644 bundle/artifacts/whl/testdata/setup.py delete mode 100644 bundle/artifacts/whl/testdata/setup_incorrect.py delete mode 100644 bundle/artifacts/whl/testdata/setup_minimal.py diff --git a/bundle/artifacts/all.go b/bundle/artifacts/all.go deleted file mode 100644 index b78e7c100a..0000000000 --- a/bundle/artifacts/all.go +++ /dev/null @@ -1,42 +0,0 @@ -package artifacts - -import ( - "context" - "fmt" - "slices" - - "github.com/databricks/cli/bundle" - "github.com/databricks/cli/libs/diag" - "golang.org/x/exp/maps" -) - -// all is an internal proxy for producing a list of mutators for all artifacts. -// It is used to produce the [BuildAll] and [UploadAll] mutators. -type all struct { - name string - fn func(name string) (bundle.Mutator, error) -} - -func (m *all) Name() string { - return fmt.Sprintf("artifacts.%sAll", m.name) -} - -func (m *all) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { - var out []bundle.Mutator - - // Iterate with stable ordering. - keys := maps.Keys(b.Config.Artifacts) - slices.Sort(keys) - - for _, name := range keys { - m, err := m.fn(name) - if err != nil { - return diag.FromErr(err) - } - if m != nil { - out = append(out, m) - } - } - - return bundle.ApplySeq(ctx, b, out...) -} diff --git a/bundle/artifacts/artifacts.go b/bundle/artifacts/artifacts.go deleted file mode 100644 index e5e55a14d5..0000000000 --- a/bundle/artifacts/artifacts.go +++ /dev/null @@ -1,74 +0,0 @@ -package artifacts - -import ( - "context" - "fmt" - - "github.com/databricks/cli/bundle" - "github.com/databricks/cli/bundle/artifacts/whl" - "github.com/databricks/cli/bundle/config" - "github.com/databricks/cli/bundle/config/mutator" - "github.com/databricks/cli/libs/cmdio" - "github.com/databricks/cli/libs/diag" - "github.com/databricks/cli/libs/log" -) - -type mutatorFactory = func(name string) bundle.Mutator - -var buildMutators map[config.ArtifactType]mutatorFactory = map[config.ArtifactType]mutatorFactory{ - config.ArtifactPythonWheel: whl.Build, -} - -var prepareMutators map[config.ArtifactType]mutatorFactory = map[config.ArtifactType]mutatorFactory{ - config.ArtifactPythonWheel: whl.Prepare, -} - -func getBuildMutator(t config.ArtifactType, name string) bundle.Mutator { - mutatorFactory, ok := buildMutators[t] - if !ok { - mutatorFactory = BasicBuild - } - - return mutatorFactory(name) -} - -func getPrepareMutator(t config.ArtifactType, name string) bundle.Mutator { - mutatorFactory, ok := prepareMutators[t] - if !ok { - mutatorFactory = func(_ string) bundle.Mutator { - return mutator.NoOp() - } - } - - return mutatorFactory(name) -} - -// Basic Build defines a general build mutator which builds artifact based on artifact.BuildCommand -type basicBuild struct { - name string -} - -func BasicBuild(name string) bundle.Mutator { - return &basicBuild{name: name} -} - -func (m *basicBuild) Name() string { - return fmt.Sprintf("artifacts.Build(%s)", m.name) -} - -func (m *basicBuild) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { - artifact, ok := b.Config.Artifacts[m.name] - if !ok { - return diag.Errorf("artifact doesn't exist: %s", m.name) - } - - cmdio.LogString(ctx, fmt.Sprintf("Building %s...", m.name)) - - out, err := artifact.Build(ctx) - if err != nil { - return diag.Errorf("build for %s failed, error: %v, output: %s", m.name, err, out) - } - log.Infof(ctx, "Build succeeded") - - return nil -} diff --git a/bundle/artifacts/build.go b/bundle/artifacts/build.go index 94880bc2cb..7f471a145e 100644 --- a/bundle/artifacts/build.go +++ b/bundle/artifacts/build.go @@ -3,55 +3,71 @@ package artifacts import ( "context" "fmt" + "path/filepath" "github.com/databricks/cli/bundle" + "github.com/databricks/cli/bundle/config" + "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/diag" + "github.com/databricks/cli/libs/exec" + "github.com/databricks/cli/libs/log" + "github.com/databricks/cli/libs/python" ) -func BuildAll() bundle.Mutator { - return &all{ - name: "Build", - fn: buildArtifactByName, - } +func Build() bundle.Mutator { + return &build{} } -type build struct { - name string -} +type build struct{} -func buildArtifactByName(name string) (bundle.Mutator, error) { - return &build{name}, nil -} +func (m *build) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { + for _, artifactName := range sortedKeys(b.Artifacts) { + artifact := b.Artifacts[artifactName] -func (m *build) Name() string { - return fmt.Sprintf("artifacts.Build(%s)", m.name) -} + if a.BuildCommand == "" { + continue + } -func (m *build) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { - artifact, ok := b.Config.Artifacts[m.name] - if !ok { - return diag.Errorf("artifact doesn't exist: %s", m.name) - } + cmdio.LogString(ctx, fmt.Sprintf("Building %s...", artifactName)) + + var e *exec.Executor + var err error + if a.Executable != "" { + e, err = exec.NewCommandExecutorWithExecutable(a.Path, a.Executable) + } else { + e, err = exec.NewCommandExecutor(a.Path) + a.Executable = e.ShellType() + } - var mutators []bundle.Mutator + if err != nil { + // TODO: location + return diag.FromError(err) + } + + out, err := e.Exec(ctx, a.BuildCommand) - // Skip building if build command is not specified or infered - if artifact.BuildCommand == "" { - // If no build command was specified or infered and there is no - // artifact output files specified, artifact is misconfigured - if len(artifact.Files) == 0 { - return diag.Errorf("misconfigured artifact: please specify 'build' or 'files' property") + if err != nil { + return diag.Errorf("build failed %s, error: %v, output: %s", artifactName, err, out) } + log.Infof(ctx, "Build succeeded") - // We can skip calling build mutator if there is no build command - // But we still need to expand glob references in files source path. - } else { - mutators = append(mutators, getBuildMutator(artifact.Type, m.name)) + if artifact.Type == "whl" { + dir := artifact.Path + distPath := filepath.Join(artifact.Path, "dist") + wheels := python.FindFilesWithSuffixInPath(distPath, ".whl") + if len(wheels) == 0 { + return diag.Errorf("cannot find built wheel in %s for package %s", dir, artifactName) + } + for _, wheel := range wheels { + artifact.Files = append(artifact.Files, config.ArtifactFile{ + Source: wheel, + }) + } + } } // We need to expand glob reference after build mutator is applied because // if we do it before, any files that are generated by build command will // not be included into artifact.Files and thus will not be uploaded. - mutators = append(mutators, &expandGlobs{name: m.name}) - return bundle.ApplySeq(ctx, b, mutators...) + return expandGlobs(ctx, b) } diff --git a/bundle/artifacts/expand_globs.go b/bundle/artifacts/expand_globs.go index c0af7c69e7..d860232729 100644 --- a/bundle/artifacts/expand_globs.go +++ b/bundle/artifacts/expand_globs.go @@ -10,14 +10,6 @@ import ( "github.com/databricks/cli/libs/dyn" ) -type expandGlobs struct { - name string -} - -func (m *expandGlobs) Name() string { - return fmt.Sprintf("artifacts.ExpandGlobs(%s)", m.name) -} - func createGlobError(v dyn.Value, p dyn.Path, message string) diag.Diagnostic { // The pattern contained in v is an absolute path. // Make it relative to the value's location to make it more readable. @@ -37,7 +29,7 @@ func createGlobError(v dyn.Value, p dyn.Path, message string) diag.Diagnostic { } } -func (m *expandGlobs) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { +func expandGlobs(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { // Base path for this mutator. // This path is set with the list of expanded globs when done. base := dyn.NewPath( diff --git a/bundle/artifacts/infer.go b/bundle/artifacts/infer.go deleted file mode 100644 index abc5091070..0000000000 --- a/bundle/artifacts/infer.go +++ /dev/null @@ -1,65 +0,0 @@ -package artifacts - -import ( - "context" - "fmt" - - "github.com/databricks/cli/bundle" - "github.com/databricks/cli/bundle/artifacts/whl" - "github.com/databricks/cli/bundle/config" - "github.com/databricks/cli/libs/diag" -) - -var inferMutators map[config.ArtifactType]mutatorFactory = map[config.ArtifactType]mutatorFactory{ - config.ArtifactPythonWheel: whl.InferBuildCommand, -} - -func getInferMutator(t config.ArtifactType, name string) bundle.Mutator { - mutatorFactory, ok := inferMutators[t] - if !ok { - return nil - } - - return mutatorFactory(name) -} - -func InferMissingProperties() bundle.Mutator { - return &all{ - name: "infer", - fn: inferArtifactByName, - } -} - -func inferArtifactByName(name string) (bundle.Mutator, error) { - return &infer{name}, nil -} - -type infer struct { - name string -} - -func (m *infer) Name() string { - return fmt.Sprintf("artifacts.Infer(%s)", m.name) -} - -func (m *infer) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { - artifact, ok := b.Config.Artifacts[m.name] - if !ok { - return diag.Errorf("artifact doesn't exist: %s", m.name) - } - - // only try to infer command if it's not already defined - // and there is no explicitly files defined which means - // that the package is built outside of bundle cycles - // manually by customer - if artifact.BuildCommand != "" || len(artifact.Files) > 0 { - return nil - } - - inferMutator := getInferMutator(artifact.Type, m.name) - if inferMutator != nil { - return bundle.Apply(ctx, b, inferMutator) - } - - return nil -} diff --git a/bundle/artifacts/prepare.go b/bundle/artifacts/prepare.go deleted file mode 100644 index 91e0bd0916..0000000000 --- a/bundle/artifacts/prepare.go +++ /dev/null @@ -1,58 +0,0 @@ -package artifacts - -import ( - "context" - "fmt" - "path/filepath" - - "github.com/databricks/cli/bundle" - "github.com/databricks/cli/libs/diag" -) - -func PrepareAll() bundle.Mutator { - return &all{ - name: "Prepare", - fn: prepareArtifactByName, - } -} - -type prepare struct { - name string -} - -func prepareArtifactByName(name string) (bundle.Mutator, error) { - return &prepare{name}, nil -} - -func (m *prepare) Name() string { - return fmt.Sprintf("artifacts.Prepare(%s)", m.name) -} - -func (m *prepare) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { - artifact, ok := b.Config.Artifacts[m.name] - if !ok { - return diag.Errorf("artifact doesn't exist: %s", m.name) - } - - l := b.Config.GetLocation("artifacts." + m.name) - dirPath := filepath.Dir(l.File) - - // Check if source paths are absolute, if not, make them absolute - for k := range artifact.Files { - f := &artifact.Files[k] - if !filepath.IsAbs(f.Source) { - f.Source = filepath.Join(dirPath, f.Source) - } - } - - // If artifact path is not provided, use bundle root dir - if artifact.Path == "" { - artifact.Path = b.BundleRootPath - } - - if !filepath.IsAbs(artifact.Path) { - artifact.Path = filepath.Join(dirPath, artifact.Path) - } - - return bundle.Apply(ctx, b, getPrepareMutator(artifact.Type, m.name)) -} diff --git a/bundle/artifacts/whl/autodetect.go b/bundle/artifacts/whl/autodetect.go deleted file mode 100644 index 9eead83b74..0000000000 --- a/bundle/artifacts/whl/autodetect.go +++ /dev/null @@ -1,62 +0,0 @@ -package whl - -import ( - "context" - "os" - "path/filepath" - - "github.com/databricks/cli/bundle" - "github.com/databricks/cli/bundle/config" - "github.com/databricks/cli/bundle/libraries" - "github.com/databricks/cli/libs/diag" - "github.com/databricks/cli/libs/log" -) - -type detectPkg struct{} - -func DetectPackage() bundle.Mutator { - return &detectPkg{} -} - -func (m *detectPkg) Name() string { - return "artifacts.whl.AutoDetect" -} - -func (m *detectPkg) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { - if b.Config.Artifacts != nil { - log.Debugf(ctx, "artifacts block is defined, skipping auto-detecting") - return nil - } - - tasks := libraries.FindTasksWithLocalLibraries(b) - if len(tasks) == 0 { - log.Infof(ctx, "No local tasks in databricks.yml config, skipping auto detect") - return nil - } - - log.Infof(ctx, "Detecting Python wheel project...") - - // checking if there is setup.py in the bundle root - setupPy := filepath.Join(b.BundleRootPath, "setup.py") - _, err := os.Stat(setupPy) - if err != nil { - log.Infof(ctx, "No Python wheel project found at bundle root folder") - return nil - } - - log.Infof(ctx, "Found Python wheel project at %s", b.BundleRootPath) - - pkgPath, err := filepath.Abs(b.BundleRootPath) - if err != nil { - return diag.FromErr(err) - } - - b.Config.Artifacts = make(map[string]*config.Artifact) - b.Config.Artifacts["python_artifact"] = &config.Artifact{ - Path: pkgPath, - Type: config.ArtifactPythonWheel, - // BuildCommand will be set by bundle/artifacts/whl/infer.go to "python3 setup.py bdist_wheel" - } - - return nil -} diff --git a/bundle/artifacts/whl/build.go b/bundle/artifacts/whl/build.go deleted file mode 100644 index 18d4b8ede6..0000000000 --- a/bundle/artifacts/whl/build.go +++ /dev/null @@ -1,57 +0,0 @@ -package whl - -import ( - "context" - "fmt" - "path/filepath" - - "github.com/databricks/cli/bundle" - "github.com/databricks/cli/bundle/config" - "github.com/databricks/cli/libs/cmdio" - "github.com/databricks/cli/libs/diag" - "github.com/databricks/cli/libs/log" - "github.com/databricks/cli/libs/python" -) - -type build struct { - name string -} - -func Build(name string) bundle.Mutator { - return &build{ - name: name, - } -} - -func (m *build) Name() string { - return fmt.Sprintf("artifacts.whl.Build(%s)", m.name) -} - -func (m *build) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { - artifact, ok := b.Config.Artifacts[m.name] - if !ok { - return diag.Errorf("artifact doesn't exist: %s", m.name) - } - - cmdio.LogString(ctx, fmt.Sprintf("Building %s...", m.name)) - - out, err := artifact.Build(ctx) - if err != nil { - return diag.Errorf("build failed %s, error: %v, output: %s", m.name, err, out) - } - log.Infof(ctx, "Build succeeded") - - dir := artifact.Path - distPath := filepath.Join(artifact.Path, "dist") - wheels := python.FindFilesWithSuffixInPath(distPath, ".whl") - if len(wheels) == 0 { - return diag.Errorf("cannot find built wheel in %s for package %s", dir, m.name) - } - for _, wheel := range wheels { - artifact.Files = append(artifact.Files, config.ArtifactFile{ - Source: wheel, - }) - } - - return nil -} diff --git a/bundle/artifacts/whl/infer.go b/bundle/artifacts/whl/infer.go deleted file mode 100644 index 9c40360bea..0000000000 --- a/bundle/artifacts/whl/infer.go +++ /dev/null @@ -1,48 +0,0 @@ -package whl - -import ( - "context" - "fmt" - - "github.com/databricks/cli/bundle" - "github.com/databricks/cli/libs/diag" - "github.com/databricks/cli/libs/python" -) - -type infer struct { - name string -} - -func (m *infer) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { - artifact := b.Config.Artifacts[m.name] - - // Note: using --build-number (build tag) flag does not help with re-installing - // libraries on all-purpose clusters. The reason is that `pip` ignoring build tag - // when upgrading the library and only look at wheel version. - // Build tag is only used for sorting the versions and the one with higher build tag takes priority when installed. - // It only works if no library is installed - // See https://github.com/pypa/pip/blob/a15dd75d98884c94a77d349b800c7c755d8c34e4/src/pip/_internal/index/package_finder.py#L522-L556 - // https://github.com/pypa/pip/issues/4781 - // - // Thus, the only way to reinstall the library on all-purpose cluster is to increase wheel version manually or - // use automatic version generation, f.e. - // setup( - // version=datetime.datetime.utcnow().strftime("%Y%m%d.%H%M%S"), - // ... - //) - - py := python.GetExecutable() - artifact.BuildCommand = py + " setup.py bdist_wheel" - - return nil -} - -func (m *infer) Name() string { - return fmt.Sprintf("artifacts.whl.Infer(%s)", m.name) -} - -func InferBuildCommand(name string) bundle.Mutator { - return &infer{ - name: name, - } -} diff --git a/bundle/artifacts/whl/prepare.go b/bundle/artifacts/whl/prepare.go deleted file mode 100644 index 0fbb2080af..0000000000 --- a/bundle/artifacts/whl/prepare.go +++ /dev/null @@ -1,53 +0,0 @@ -package whl - -import ( - "context" - "fmt" - "os" - "path/filepath" - - "github.com/databricks/cli/bundle" - "github.com/databricks/cli/libs/diag" - "github.com/databricks/cli/libs/log" - "github.com/databricks/cli/libs/python" -) - -type prepare struct { - name string -} - -func Prepare(name string) bundle.Mutator { - return &prepare{ - name: name, - } -} - -func (m *prepare) Name() string { - return fmt.Sprintf("artifacts.whl.Prepare(%s)", m.name) -} - -func (m *prepare) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { - artifact, ok := b.Config.Artifacts[m.name] - if !ok { - return diag.Errorf("artifact doesn't exist: %s", m.name) - } - - // If there is no build command for the artifact, we don't need to cleanup the dist folder before - if artifact.BuildCommand == "" { - return nil - } - - dir := artifact.Path - - distPath := filepath.Join(dir, "dist") - - // If we have multiple artifacts con figured, prepare will be called multiple times - // The first time we will remove the folders, other times will be no-op. - err := os.RemoveAll(distPath) - if err != nil { - log.Infof(ctx, "Failed to remove dist folder: %v", err) - } - python.CleanupWheelFolder(dir) - - return nil -} diff --git a/bundle/artifacts/whl/testdata/setup.py b/bundle/artifacts/whl/testdata/setup.py deleted file mode 100644 index 7a1317b2f5..0000000000 --- a/bundle/artifacts/whl/testdata/setup.py +++ /dev/null @@ -1,15 +0,0 @@ -from setuptools import setup, find_packages - -import my_test_code - -setup( - name="my_test_code", - version=my_test_code.__version__, - author=my_test_code.__author__, - url="https://databricks.com", - author_email="john.doe@databricks.com", - description="my test wheel", - packages=find_packages(include=["my_test_code"]), - entry_points={"group_1": "run=my_test_code.__main__:main"}, - install_requires=["setuptools"], -) diff --git a/bundle/artifacts/whl/testdata/setup_incorrect.py b/bundle/artifacts/whl/testdata/setup_incorrect.py deleted file mode 100644 index c6aa17b2d8..0000000000 --- a/bundle/artifacts/whl/testdata/setup_incorrect.py +++ /dev/null @@ -1,14 +0,0 @@ -from setuptools import setup, find_packages - -import my_test_code - -setup( - version=my_test_code.__version__, - author=my_test_code.__author__, - url="https://databricks.com", - author_email="john.doe@databricks.com", - description="my test wheel", - packages=find_packages(include=["my_test_code"]), - entry_points={"group_1": "run=my_test_code.__main__:main"}, - install_requires=["setuptools"], -) diff --git a/bundle/artifacts/whl/testdata/setup_minimal.py b/bundle/artifacts/whl/testdata/setup_minimal.py deleted file mode 100644 index 3e81e72173..0000000000 --- a/bundle/artifacts/whl/testdata/setup_minimal.py +++ /dev/null @@ -1,3 +0,0 @@ -from setuptools import setup - -setup(name="my_test_code") diff --git a/bundle/phases/build.go b/bundle/phases/build.go index 0170ed51cf..7d98dfff52 100644 --- a/bundle/phases/build.go +++ b/bundle/phases/build.go @@ -5,7 +5,6 @@ import ( "github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle/artifacts" - "github.com/databricks/cli/bundle/artifacts/whl" "github.com/databricks/cli/bundle/config" "github.com/databricks/cli/bundle/config/mutator" "github.com/databricks/cli/bundle/scripts" @@ -19,10 +18,7 @@ func Build(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { return bundle.ApplySeq(ctx, b, scripts.Execute(config.ScriptPreBuild), - whl.DetectPackage(), - artifacts.InferMissingProperties(), - artifacts.PrepareAll(), - artifacts.BuildAll(), + artifacts.Build(), scripts.Execute(config.ScriptPostBuild), mutator.ResolveVariableReferences( "artifacts", diff --git a/bundle/phases/initialize.go b/bundle/phases/initialize.go index 1da5b61f49..0dce6f7aca 100644 --- a/bundle/phases/initialize.go +++ b/bundle/phases/initialize.go @@ -96,6 +96,8 @@ func Initialize(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { mutator.TranslatePaths(), trampoline.WrapperWarning(), + artifacts.Validate(), + apps.Validate(), permissions.ValidateSharedRootPermissions(), From 602118e3e8d1ff098b580c27acdd9aaf1c6bdb43 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:11:15 +0100 Subject: [PATCH 02/24] add acc test for expand_globs --- .../bundle/artifacts/expand_globs/databricks.yml | 8 ++++++++ acceptance/bundle/artifacts/expand_globs/script | 12 ++++++++++++ acceptance/bundle/artifacts/expand_globs/test.toml | 1 + 3 files changed, 21 insertions(+) create mode 100644 acceptance/bundle/artifacts/expand_globs/databricks.yml create mode 100644 acceptance/bundle/artifacts/expand_globs/script create mode 100644 acceptance/bundle/artifacts/expand_globs/test.toml diff --git a/acceptance/bundle/artifacts/expand_globs/databricks.yml b/acceptance/bundle/artifacts/expand_globs/databricks.yml new file mode 100644 index 0000000000..c486ba5f70 --- /dev/null +++ b/acceptance/bundle/artifacts/expand_globs/databricks.yml @@ -0,0 +1,8 @@ +bundle: + name: expand_globs + +artifacts: + test: + files: + - source: a*.txt + - source: subdir/*.txt diff --git a/acceptance/bundle/artifacts/expand_globs/script b/acceptance/bundle/artifacts/expand_globs/script new file mode 100644 index 0000000000..2bf0e30c05 --- /dev/null +++ b/acceptance/bundle/artifacts/expand_globs/script @@ -0,0 +1,12 @@ +errcode trace $CLI bundle validate -o json | jq .artifacts + +touch a1.txt +touch a2.txt + +errcode trace $CLI bundle validate -o json | jq .artifacts + +mkdir -p subdir +touch subdir/hello.txt +errcode trace $CLI bundle validate -o json | jq .artifacts + +rm -fr a1.txt a2.txt subdir diff --git a/acceptance/bundle/artifacts/expand_globs/test.toml b/acceptance/bundle/artifacts/expand_globs/test.toml new file mode 100644 index 0000000000..a030353d57 --- /dev/null +++ b/acceptance/bundle/artifacts/expand_globs/test.toml @@ -0,0 +1 @@ +RecordRequests = false From 596a0b3b760a3a429aca2b9327bc16c0ab1b9b14 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:15:40 +0100 Subject: [PATCH 03/24] add output.txt --- .../bundle/artifacts/expand_globs/output.txt | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 acceptance/bundle/artifacts/expand_globs/output.txt diff --git a/acceptance/bundle/artifacts/expand_globs/output.txt b/acceptance/bundle/artifacts/expand_globs/output.txt new file mode 100644 index 0000000000..4f85a10bde --- /dev/null +++ b/acceptance/bundle/artifacts/expand_globs/output.txt @@ -0,0 +1,67 @@ + +>>> [CLI] bundle validate -o json +Warn: processing map[test:%!s(*config.Artifact=&{ [{a*.txt } {subdir/*.txt }] })] +Warn: processing test +Error: a*.txt: no matching files + at artifacts.test.files[0].source + in databricks.yml:7:17 + +Error: subdir/*.txt: no matching files + at artifacts.test.files[1].source + in databricks.yml:8:17 + + +Exit code: 1 +{ + "test": { + "files": [ + { + "source": "a*.txt" + }, + { + "source": "subdir/*.txt" + } + ] + } +} + +>>> [CLI] bundle validate -o json +Warn: processing map[test:%!s(*config.Artifact=&{ [{a*.txt } {subdir/*.txt }] })] +Warn: processing test +Error: subdir/*.txt: no matching files + at artifacts.test.files[1].source + in databricks.yml:8:17 + + +Exit code: 1 +{ + "test": { + "files": [ + { + "source": "a*.txt" + }, + { + "source": "subdir/*.txt" + } + ] + } +} + +>>> [CLI] bundle validate -o json +Warn: processing map[test:%!s(*config.Artifact=&{ [{a*.txt } {subdir/*.txt }] })] +Warn: processing test +{ + "test": { + "files": [ + { + "source": "a1.txt" + }, + { + "source": "a2.txt" + }, + { + "source": "subdir/hello.txt" + } + ] + } +} From d7b0bc0774f51f686668ec4ba667cbe298d67762 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:19:26 +0100 Subject: [PATCH 04/24] fix --- .../{expand_globs => validate_expand_globs}/databricks.yml | 0 .../{expand_globs => validate_expand_globs}/output.txt | 6 ------ .../{expand_globs => validate_expand_globs}/script | 0 .../{expand_globs => validate_expand_globs}/test.toml | 0 4 files changed, 6 deletions(-) rename acceptance/bundle/artifacts/{expand_globs => validate_expand_globs}/databricks.yml (100%) rename acceptance/bundle/artifacts/{expand_globs => validate_expand_globs}/output.txt (73%) rename acceptance/bundle/artifacts/{expand_globs => validate_expand_globs}/script (100%) rename acceptance/bundle/artifacts/{expand_globs => validate_expand_globs}/test.toml (100%) diff --git a/acceptance/bundle/artifacts/expand_globs/databricks.yml b/acceptance/bundle/artifacts/validate_expand_globs/databricks.yml similarity index 100% rename from acceptance/bundle/artifacts/expand_globs/databricks.yml rename to acceptance/bundle/artifacts/validate_expand_globs/databricks.yml diff --git a/acceptance/bundle/artifacts/expand_globs/output.txt b/acceptance/bundle/artifacts/validate_expand_globs/output.txt similarity index 73% rename from acceptance/bundle/artifacts/expand_globs/output.txt rename to acceptance/bundle/artifacts/validate_expand_globs/output.txt index 4f85a10bde..5d5b39de48 100644 --- a/acceptance/bundle/artifacts/expand_globs/output.txt +++ b/acceptance/bundle/artifacts/validate_expand_globs/output.txt @@ -1,7 +1,5 @@ >>> [CLI] bundle validate -o json -Warn: processing map[test:%!s(*config.Artifact=&{ [{a*.txt } {subdir/*.txt }] })] -Warn: processing test Error: a*.txt: no matching files at artifacts.test.files[0].source in databricks.yml:7:17 @@ -26,8 +24,6 @@ Exit code: 1 } >>> [CLI] bundle validate -o json -Warn: processing map[test:%!s(*config.Artifact=&{ [{a*.txt } {subdir/*.txt }] })] -Warn: processing test Error: subdir/*.txt: no matching files at artifacts.test.files[1].source in databricks.yml:8:17 @@ -48,8 +44,6 @@ Exit code: 1 } >>> [CLI] bundle validate -o json -Warn: processing map[test:%!s(*config.Artifact=&{ [{a*.txt } {subdir/*.txt }] })] -Warn: processing test { "test": { "files": [ diff --git a/acceptance/bundle/artifacts/expand_globs/script b/acceptance/bundle/artifacts/validate_expand_globs/script similarity index 100% rename from acceptance/bundle/artifacts/expand_globs/script rename to acceptance/bundle/artifacts/validate_expand_globs/script diff --git a/acceptance/bundle/artifacts/expand_globs/test.toml b/acceptance/bundle/artifacts/validate_expand_globs/test.toml similarity index 100% rename from acceptance/bundle/artifacts/expand_globs/test.toml rename to acceptance/bundle/artifacts/validate_expand_globs/test.toml From fa97c0cc5b8c70b9cf7d7b147facefb1a25ce2da Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:20:02 +0100 Subject: [PATCH 05/24] fixes --- bundle/artifacts/build.go | 44 ++++++++++++++++----------- bundle/artifacts/expand_globs.go | 4 +-- bundle/artifacts/expand_globs_test.go | 18 ++--------- bundle/phases/initialize.go | 1 + 4 files changed, 33 insertions(+), 34 deletions(-) diff --git a/bundle/artifacts/build.go b/bundle/artifacts/build.go index 7f471a145e..76a3df04b2 100644 --- a/bundle/artifacts/build.go +++ b/bundle/artifacts/build.go @@ -20,9 +20,15 @@ func Build() bundle.Mutator { type build struct{} +func (m *build) Name() string { + return "artifacts.Build()" +} + func (m *build) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { - for _, artifactName := range sortedKeys(b.Artifacts) { - artifact := b.Artifacts[artifactName] + var diags diag.Diagnostics + + for _, artifactName := range sortedKeys(b.Config.Artifacts) { + a := b.Config.Artifacts[artifactName] if a.BuildCommand == "" { continue @@ -30,44 +36,48 @@ func (m *build) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { cmdio.LogString(ctx, fmt.Sprintf("Building %s...", artifactName)) - var e *exec.Executor + var executor *exec.Executor var err error if a.Executable != "" { - e, err = exec.NewCommandExecutorWithExecutable(a.Path, a.Executable) + executor, err = exec.NewCommandExecutorWithExecutable(a.Path, a.Executable) } else { - e, err = exec.NewCommandExecutor(a.Path) - a.Executable = e.ShellType() + executor, err = exec.NewCommandExecutor(a.Path) + a.Executable = executor.ShellType() } if err != nil { // TODO: location - return diag.FromError(err) + return diag.FromErr(err) } - out, err := e.Exec(ctx, a.BuildCommand) - + out, err := executor.Exec(ctx, a.BuildCommand) if err != nil { return diag.Errorf("build failed %s, error: %v, output: %s", artifactName, err, out) } log.Infof(ctx, "Build succeeded") - if artifact.Type == "whl" { - dir := artifact.Path - distPath := filepath.Join(artifact.Path, "dist") + if a.Type == "whl" { + dir := a.Path + distPath := filepath.Join(a.Path, "dist") wheels := python.FindFilesWithSuffixInPath(distPath, ".whl") if len(wheels) == 0 { return diag.Errorf("cannot find built wheel in %s for package %s", dir, artifactName) } for _, wheel := range wheels { - artifact.Files = append(artifact.Files, config.ArtifactFile{ + a.Files = append(a.Files, config.ArtifactFile{ Source: wheel, }) } } + + // We need to expand glob reference after build mutator is applied because + // if we do it before, any files that are generated by build command will + // not be included into artifact.Files and thus will not be uploaded. + diags = diags.Extend(expandGlobs(ctx, b, artifactName)) + if diags.HasError() { + break + } } - // We need to expand glob reference after build mutator is applied because - // if we do it before, any files that are generated by build command will - // not be included into artifact.Files and thus will not be uploaded. - return expandGlobs(ctx, b) + return diags } diff --git a/bundle/artifacts/expand_globs.go b/bundle/artifacts/expand_globs.go index d860232729..889a62e268 100644 --- a/bundle/artifacts/expand_globs.go +++ b/bundle/artifacts/expand_globs.go @@ -29,12 +29,12 @@ func createGlobError(v dyn.Value, p dyn.Path, message string) diag.Diagnostic { } } -func expandGlobs(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { +func expandGlobs(ctx context.Context, b *bundle.Bundle, name string) diag.Diagnostics { // Base path for this mutator. // This path is set with the list of expanded globs when done. base := dyn.NewPath( dyn.Key("artifacts"), - dyn.Key(m.name), + dyn.Key(name), dyn.Key("files"), ) diff --git a/bundle/artifacts/expand_globs_test.go b/bundle/artifacts/expand_globs_test.go index 7bf8863306..f16f3cab44 100644 --- a/bundle/artifacts/expand_globs_test.go +++ b/bundle/artifacts/expand_globs_test.go @@ -39,11 +39,7 @@ func TestExpandGlobs_Nominal(t *testing.T) { bundletest.SetLocation(b, "artifacts", []dyn.Location{{File: filepath.Join(tmpDir, "databricks.yml")}}) ctx := context.Background() - diags := bundle.ApplySeq(ctx, b, - // Run prepare first to make paths absolute. - &prepare{"test"}, - &expandGlobs{"test"}, - ) + diags := expandGlobs(ctx, b, "text") require.NoError(t, diags.Error()) // Assert that the expanded paths are correct. @@ -80,11 +76,7 @@ func TestExpandGlobs_InvalidPattern(t *testing.T) { bundletest.SetLocation(b, "artifacts", []dyn.Location{{File: filepath.Join(tmpDir, "databricks.yml")}}) ctx := context.Background() - diags := bundle.ApplySeq(ctx, b, - // Run prepare first to make paths absolute. - &prepare{"test"}, - &expandGlobs{"test"}, - ) + diags := expandGlobs(ctx, b, "test") assert.Len(t, diags, 4) assert.Equal(t, filepath.Clean("a[.txt")+": syntax error in pattern", diags[0].Summary) @@ -128,11 +120,7 @@ func TestExpandGlobs_NoMatches(t *testing.T) { bundletest.SetLocation(b, "artifacts", []dyn.Location{{File: filepath.Join(tmpDir, "databricks.yml")}}) ctx := context.Background() - diags := bundle.ApplySeq(ctx, b, - // Run prepare first to make paths absolute. - &prepare{"test"}, - &expandGlobs{"test"}, - ) + diags := expandGlobs(ctx, b, "test") assert.Len(t, diags, 2) assert.Equal(t, "c*.txt: no matching files", diags[0].Summary) diff --git a/bundle/phases/initialize.go b/bundle/phases/initialize.go index 0dce6f7aca..c95c0c0d8f 100644 --- a/bundle/phases/initialize.go +++ b/bundle/phases/initialize.go @@ -5,6 +5,7 @@ import ( "github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle/apps" + "github.com/databricks/cli/bundle/artifacts" "github.com/databricks/cli/bundle/config" "github.com/databricks/cli/bundle/config/mutator" pythonmutator "github.com/databricks/cli/bundle/config/mutator/python" From 67d746c5a644a3527d9b49e278d960fb9546b6b9 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:25:01 +0100 Subject: [PATCH 06/24] add globs_invalid --- .../artifacts/globs_invalid/databricks.yml | 10 +++++ .../bundle/artifacts/globs_invalid/output.txt | 38 +++++++++++++++++++ .../bundle/artifacts/globs_invalid/script | 1 + .../bundle/artifacts/globs_invalid/test.toml | 1 + 4 files changed, 50 insertions(+) create mode 100644 acceptance/bundle/artifacts/globs_invalid/databricks.yml create mode 100644 acceptance/bundle/artifacts/globs_invalid/output.txt create mode 100644 acceptance/bundle/artifacts/globs_invalid/script create mode 100644 acceptance/bundle/artifacts/globs_invalid/test.toml diff --git a/acceptance/bundle/artifacts/globs_invalid/databricks.yml b/acceptance/bundle/artifacts/globs_invalid/databricks.yml new file mode 100644 index 0000000000..9ceec6ded2 --- /dev/null +++ b/acceptance/bundle/artifacts/globs_invalid/databricks.yml @@ -0,0 +1,10 @@ +bundle: + name: expand_globs + +artifacts: + test: + files: + - source: "a[.txt" + - source: "./a[.txt" + - source: "../a[.txt" + - source: "subdir/a[.txt" diff --git a/acceptance/bundle/artifacts/globs_invalid/output.txt b/acceptance/bundle/artifacts/globs_invalid/output.txt new file mode 100644 index 0000000000..178a9dddbd --- /dev/null +++ b/acceptance/bundle/artifacts/globs_invalid/output.txt @@ -0,0 +1,38 @@ + +>>> [CLI] bundle validate -o json +Error: a[.txt: syntax error in pattern + at artifacts.test.files[0].source + in databricks.yml:7:17 + +Error: ./a[.txt: syntax error in pattern + at artifacts.test.files[1].source + in databricks.yml:8:17 + +Error: ../a[.txt: syntax error in pattern + at artifacts.test.files[2].source + in databricks.yml:9:17 + +Error: subdir/a[.txt: syntax error in pattern + at artifacts.test.files[3].source + in databricks.yml:10:17 + + +Exit code: 1 +{ + "test": { + "files": [ + { + "source": "a[.txt" + }, + { + "source": "./a[.txt" + }, + { + "source": "../a[.txt" + }, + { + "source": "subdir/a[.txt" + } + ] + } +} diff --git a/acceptance/bundle/artifacts/globs_invalid/script b/acceptance/bundle/artifacts/globs_invalid/script new file mode 100644 index 0000000000..aab886a3d5 --- /dev/null +++ b/acceptance/bundle/artifacts/globs_invalid/script @@ -0,0 +1 @@ +errcode trace $CLI bundle validate -o json | jq .artifacts diff --git a/acceptance/bundle/artifacts/globs_invalid/test.toml b/acceptance/bundle/artifacts/globs_invalid/test.toml new file mode 100644 index 0000000000..a030353d57 --- /dev/null +++ b/acceptance/bundle/artifacts/globs_invalid/test.toml @@ -0,0 +1 @@ +RecordRequests = false From f9b9d34148b58459b34901620a8331da204795ae Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:25:25 +0100 Subject: [PATCH 07/24] globs_in_files --- .../{validate_expand_globs => globs_in_files}/databricks.yml | 0 .../{validate_expand_globs => globs_in_files}/output.txt | 0 .../artifacts/{validate_expand_globs => globs_in_files}/script | 0 .../artifacts/{validate_expand_globs => globs_in_files}/test.toml | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename acceptance/bundle/artifacts/{validate_expand_globs => globs_in_files}/databricks.yml (100%) rename acceptance/bundle/artifacts/{validate_expand_globs => globs_in_files}/output.txt (100%) rename acceptance/bundle/artifacts/{validate_expand_globs => globs_in_files}/script (100%) rename acceptance/bundle/artifacts/{validate_expand_globs => globs_in_files}/test.toml (100%) diff --git a/acceptance/bundle/artifacts/validate_expand_globs/databricks.yml b/acceptance/bundle/artifacts/globs_in_files/databricks.yml similarity index 100% rename from acceptance/bundle/artifacts/validate_expand_globs/databricks.yml rename to acceptance/bundle/artifacts/globs_in_files/databricks.yml diff --git a/acceptance/bundle/artifacts/validate_expand_globs/output.txt b/acceptance/bundle/artifacts/globs_in_files/output.txt similarity index 100% rename from acceptance/bundle/artifacts/validate_expand_globs/output.txt rename to acceptance/bundle/artifacts/globs_in_files/output.txt diff --git a/acceptance/bundle/artifacts/validate_expand_globs/script b/acceptance/bundle/artifacts/globs_in_files/script similarity index 100% rename from acceptance/bundle/artifacts/validate_expand_globs/script rename to acceptance/bundle/artifacts/globs_in_files/script diff --git a/acceptance/bundle/artifacts/validate_expand_globs/test.toml b/acceptance/bundle/artifacts/globs_in_files/test.toml similarity index 100% rename from acceptance/bundle/artifacts/validate_expand_globs/test.toml rename to acceptance/bundle/artifacts/globs_in_files/test.toml From 6c45063f20d10bbed851322b79b3b9728fe51601 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:26:18 +0100 Subject: [PATCH 08/24] clean up --- bundle/artifacts/expand_globs_test.go | 144 -------------------------- 1 file changed, 144 deletions(-) delete mode 100644 bundle/artifacts/expand_globs_test.go diff --git a/bundle/artifacts/expand_globs_test.go b/bundle/artifacts/expand_globs_test.go deleted file mode 100644 index f16f3cab44..0000000000 --- a/bundle/artifacts/expand_globs_test.go +++ /dev/null @@ -1,144 +0,0 @@ -package artifacts - -import ( - "context" - "path/filepath" - "testing" - - "github.com/databricks/cli/bundle" - "github.com/databricks/cli/bundle/config" - "github.com/databricks/cli/bundle/internal/bundletest" - "github.com/databricks/cli/internal/testutil" - "github.com/databricks/cli/libs/dyn" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestExpandGlobs_Nominal(t *testing.T) { - tmpDir := t.TempDir() - - testutil.Touch(t, tmpDir, "aa1.txt") - testutil.Touch(t, tmpDir, "aa2.txt") - testutil.Touch(t, tmpDir, "bb.txt") - testutil.Touch(t, tmpDir, "bc.txt") - - b := &bundle.Bundle{ - BundleRootPath: tmpDir, - Config: config.Root{ - Artifacts: config.Artifacts{ - "test": { - Files: []config.ArtifactFile{ - {Source: "./aa*.txt"}, - {Source: "./b[bc].txt"}, - }, - }, - }, - }, - } - - bundletest.SetLocation(b, "artifacts", []dyn.Location{{File: filepath.Join(tmpDir, "databricks.yml")}}) - - ctx := context.Background() - diags := expandGlobs(ctx, b, "text") - require.NoError(t, diags.Error()) - - // Assert that the expanded paths are correct. - a, ok := b.Config.Artifacts["test"] - if !assert.True(t, ok) { - return - } - assert.Len(t, a.Files, 4) - assert.Equal(t, filepath.Join(tmpDir, "aa1.txt"), a.Files[0].Source) - assert.Equal(t, filepath.Join(tmpDir, "aa2.txt"), a.Files[1].Source) - assert.Equal(t, filepath.Join(tmpDir, "bb.txt"), a.Files[2].Source) - assert.Equal(t, filepath.Join(tmpDir, "bc.txt"), a.Files[3].Source) -} - -func TestExpandGlobs_InvalidPattern(t *testing.T) { - tmpDir := t.TempDir() - - b := &bundle.Bundle{ - BundleRootPath: tmpDir, - Config: config.Root{ - Artifacts: config.Artifacts{ - "test": { - Files: []config.ArtifactFile{ - {Source: "a[.txt"}, - {Source: "./a[.txt"}, - {Source: "../a[.txt"}, - {Source: "subdir/a[.txt"}, - }, - }, - }, - }, - } - - bundletest.SetLocation(b, "artifacts", []dyn.Location{{File: filepath.Join(tmpDir, "databricks.yml")}}) - - ctx := context.Background() - diags := expandGlobs(ctx, b, "test") - - assert.Len(t, diags, 4) - assert.Equal(t, filepath.Clean("a[.txt")+": syntax error in pattern", diags[0].Summary) - assert.Equal(t, filepath.Join(tmpDir, "databricks.yml"), diags[0].Locations[0].File) - assert.Equal(t, "artifacts.test.files[0].source", diags[0].Paths[0].String()) - assert.Equal(t, filepath.Clean("a[.txt")+": syntax error in pattern", diags[1].Summary) - assert.Equal(t, filepath.Join(tmpDir, "databricks.yml"), diags[1].Locations[0].File) - assert.Equal(t, "artifacts.test.files[1].source", diags[1].Paths[0].String()) - assert.Equal(t, filepath.Clean("../a[.txt")+": syntax error in pattern", diags[2].Summary) - assert.Equal(t, filepath.Join(tmpDir, "databricks.yml"), diags[2].Locations[0].File) - assert.Equal(t, "artifacts.test.files[2].source", diags[2].Paths[0].String()) - assert.Equal(t, filepath.Clean("subdir/a[.txt")+": syntax error in pattern", diags[3].Summary) - assert.Equal(t, filepath.Join(tmpDir, "databricks.yml"), diags[3].Locations[0].File) - assert.Equal(t, "artifacts.test.files[3].source", diags[3].Paths[0].String()) -} - -func TestExpandGlobs_NoMatches(t *testing.T) { - tmpDir := t.TempDir() - - testutil.Touch(t, tmpDir, "a1.txt") - testutil.Touch(t, tmpDir, "a2.txt") - testutil.Touch(t, tmpDir, "b1.txt") - testutil.Touch(t, tmpDir, "b2.txt") - - b := &bundle.Bundle{ - BundleRootPath: tmpDir, - Config: config.Root{ - Artifacts: config.Artifacts{ - "test": { - Files: []config.ArtifactFile{ - {Source: "a*.txt"}, - {Source: "b*.txt"}, - {Source: "c*.txt"}, - {Source: "d*.txt"}, - }, - }, - }, - }, - } - - bundletest.SetLocation(b, "artifacts", []dyn.Location{{File: filepath.Join(tmpDir, "databricks.yml")}}) - - ctx := context.Background() - diags := expandGlobs(ctx, b, "test") - - assert.Len(t, diags, 2) - assert.Equal(t, "c*.txt: no matching files", diags[0].Summary) - assert.Equal(t, filepath.Join(tmpDir, "databricks.yml"), diags[0].Locations[0].File) - assert.Equal(t, "artifacts.test.files[2].source", diags[0].Paths[0].String()) - assert.Equal(t, "d*.txt: no matching files", diags[1].Summary) - assert.Equal(t, filepath.Join(tmpDir, "databricks.yml"), diags[1].Locations[0].File) - assert.Equal(t, "artifacts.test.files[3].source", diags[1].Paths[0].String()) - - // Assert that the original paths are unchanged. - a, ok := b.Config.Artifacts["test"] - if !assert.True(t, ok) { - return - } - - assert.Len(t, a.Files, 4) - assert.Equal(t, "a*.txt", filepath.Base(a.Files[0].Source)) - assert.Equal(t, "b*.txt", filepath.Base(a.Files[1].Source)) - assert.Equal(t, "c*.txt", filepath.Base(a.Files[2].Source)) - assert.Equal(t, "d*.txt", filepath.Base(a.Files[3].Source)) -} From f38d9f2a2cbaceaa22c643bbd2b6ad462f375d3b Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:27:12 +0100 Subject: [PATCH 09/24] update acc tests --- acceptance/bundle/debug/out.stderr.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/acceptance/bundle/debug/out.stderr.txt b/acceptance/bundle/debug/out.stderr.txt index 631f51990b..a6047208a5 100644 --- a/acceptance/bundle/debug/out.stderr.txt +++ b/acceptance/bundle/debug/out.stderr.txt @@ -60,6 +60,8 @@ 10:07:59 Debug: Apply pid=12345 mutator=ConfigureWSFS 10:07:59 Debug: Apply pid=12345 mutator=TranslatePaths 10:07:59 Debug: Apply pid=12345 mutator=PythonWrapperWarning +10:07:59 Debug: Apply pid=12345 mutator=artifacts.Validate() +10:07:59 Info: No local tasks in databricks.yml config, skipping auto detect pid=12345 mutator=artifacts.Validate() 10:07:59 Debug: Apply pid=12345 mutator=apps.Validate 10:07:59 Debug: Apply pid=12345 mutator=ValidateSharedRootPermissions 10:07:59 Debug: Apply pid=12345 mutator=ApplyBundlePermissions From 11e5f11f3eb9a44cf22dd4d8a9f8710c87008676 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:35:38 +0100 Subject: [PATCH 10/24] clean up --- bundle/config/artifact.go | 22 ---------------------- bundle/config/artifacts_test.go | 18 ------------------ 2 files changed, 40 deletions(-) delete mode 100644 bundle/config/artifacts_test.go diff --git a/bundle/config/artifact.go b/bundle/config/artifact.go index 177799e119..93c220136f 100644 --- a/bundle/config/artifact.go +++ b/bundle/config/artifact.go @@ -1,9 +1,6 @@ package config import ( - "context" - "errors" - "github.com/databricks/cli/libs/exec" ) @@ -34,22 +31,3 @@ type Artifact struct { Executable exec.ExecutableType `json:"executable,omitempty"` } - -func (a *Artifact) Build(ctx context.Context) ([]byte, error) { - if a.BuildCommand == "" { - return nil, errors.New("no build property defined") - } - - var e *exec.Executor - var err error - if a.Executable != "" { - e, err = exec.NewCommandExecutorWithExecutable(a.Path, a.Executable) - } else { - e, err = exec.NewCommandExecutor(a.Path) - a.Executable = e.ShellType() - } - if err != nil { - return nil, err - } - return e.Exec(ctx, a.BuildCommand) -} diff --git a/bundle/config/artifacts_test.go b/bundle/config/artifacts_test.go deleted file mode 100644 index 5fa159fdf3..0000000000 --- a/bundle/config/artifacts_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package config - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestArtifactBuild(t *testing.T) { - artifact := Artifact{ - BuildCommand: "echo 'Hello from build command'", - } - res, err := artifact.Build(context.Background()) - assert.NoError(t, err) - assert.NotNil(t, res) - assert.Equal(t, "Hello from build command\n", string(res)) -} From de893fbac2a2f52ec54af49a68dc98e614ad42b1 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:38:07 +0100 Subject: [PATCH 11/24] add missing validate.go --- bundle/artifacts/validate.go | 148 +++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 bundle/artifacts/validate.go diff --git a/bundle/artifacts/validate.go b/bundle/artifacts/validate.go new file mode 100644 index 0000000000..a15d32cd03 --- /dev/null +++ b/bundle/artifacts/validate.go @@ -0,0 +1,148 @@ +package artifacts + +import ( + "context" + "os" + "path/filepath" + "sort" + + "github.com/databricks/cli/bundle" + "github.com/databricks/cli/bundle/config" + "github.com/databricks/cli/bundle/libraries" + "github.com/databricks/cli/libs/diag" + "github.com/databricks/cli/libs/log" + "github.com/databricks/cli/libs/python" +) + +func Validate() bundle.Mutator { + return &validate{} +} + +type validate struct{} + +func (m *validate) Name() string { + return "artifacts.Validate()" +} + +func (m *validate) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { + var diags diag.Diagnostics + + err := InsertPythonArtifact(ctx, b) + if err != nil { + return diag.FromErr(err) + } + + removeFolders := make(map[string]bool, len(b.Config.Artifacts)) + cleanupWheelFolders := make(map[string]bool, len(b.Config.Artifacts)) + + for _, artifactName := range sortedKeys(b.Config.Artifacts) { + artifact := b.Config.Artifacts[artifactName] + + if artifact.Type == "whl" { + if artifact.BuildCommand == "" && len(artifact.Files) == 0 { + artifact.BuildCommand = python.GetExecutable() + " setup.py bdist_wheel" + } + } + + l := b.Config.GetLocation("artifacts." + artifactName) + dirPath := filepath.Dir(l.File) + + // Check if source paths are absolute, if not, make them absolute + for k := range artifact.Files { + f := &artifact.Files[k] + if !filepath.IsAbs(f.Source) { + f.Source = filepath.Join(dirPath, f.Source) + } + } + + if artifact.Path == "" { + artifact.Path = b.BundleRootPath + } + + if !filepath.IsAbs(artifact.Path) { + artifact.Path = filepath.Join(dirPath, artifact.Path) + } + + if artifact.Type == "whl" && artifact.BuildCommand != "" { + dir := artifact.Path + removeFolders[filepath.Join(dir, "dist")] = true + cleanupWheelFolders[dir] = true + } + + if artifact.BuildCommand == "" && len(artifact.Files) == 0 { + diags = diags.Extend(diag.Errorf("misconfigured artifact: please specify 'build' or 'files' property")) + } + + if len(artifact.Files) > 0 { + diags = diags.Extend(expandGlobs(ctx, b, artifactName)) + } + + if diags.HasError() { + break + } + } + + if diags.HasError() { + return diags + } + + for _, dir := range sortedKeys(removeFolders) { + err := os.RemoveAll(dir) + if err != nil { + log.Infof(ctx, "Failed to remove %s: %s", dir, err) + } + } + + for _, dir := range sortedKeys(cleanupWheelFolders) { + log.Infof(ctx, "Cleaning up Python build artifacts in %s", dir) + python.CleanupWheelFolder(dir) + } + + return diags +} + +func InsertPythonArtifact(ctx context.Context, b *bundle.Bundle) error { + if b.Config.Artifacts != nil { + log.Debugf(ctx, "artifacts block is defined, skipping auto-detecting") + return nil + } + + tasks := libraries.FindTasksWithLocalLibraries(b) + if len(tasks) == 0 { + log.Infof(ctx, "No local tasks in databricks.yml config, skipping auto detect") + return nil + } + + // checking if there is setup.py in the bundle root + setupPy := filepath.Join(b.BundleRootPath, "setup.py") + _, err := os.Stat(setupPy) + if err != nil { + log.Infof(ctx, "No Python wheel project found at bundle root folder") + return nil + } + + log.Infof(ctx, "Found Python wheel project at %s", b.BundleRootPath) + + pkgPath, err := filepath.Abs(b.BundleRootPath) + if err != nil { + return err + } + + b.Config.Artifacts = make(map[string]*config.Artifact) + b.Config.Artifacts["python_artifact"] = &config.Artifact{ + Path: pkgPath, + Type: config.ArtifactPythonWheel, + // BuildCommand will be auto set by later code + } + + return nil +} + +func sortedKeys[T any](m map[string]T) []string { + keys := make([]string, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + sort.Strings(keys) + return keys +} From c50994735f5d952fc8f5f9845f6249d37bbdc6b5 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:42:49 +0100 Subject: [PATCH 12/24] clean up --- bundle/artifacts/build.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bundle/artifacts/build.go b/bundle/artifacts/build.go index 76a3df04b2..989a0db321 100644 --- a/bundle/artifacts/build.go +++ b/bundle/artifacts/build.go @@ -46,15 +46,16 @@ func (m *build) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { } if err != nil { - // TODO: location - return diag.FromErr(err) + diags = diags.Extend(diag.FromErr(err)) + if diags.HasError() { + break + } } out, err := executor.Exec(ctx, a.BuildCommand) if err != nil { return diag.Errorf("build failed %s, error: %v, output: %s", artifactName, err, out) } - log.Infof(ctx, "Build succeeded") if a.Type == "whl" { dir := a.Path @@ -68,6 +69,9 @@ func (m *build) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { Source: wheel, }) } + log.Infof(ctx, "%s: Build succeeded, found %s", artifactName, wheels) + } else { + log.Infof(ctx, "%s: Build succeeded", artifactName) } // We need to expand glob reference after build mutator is applied because From c7c7fbc6ecf2bd1f678cdf93f7b297f2e2c97724 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:45:50 +0100 Subject: [PATCH 13/24] remove () --- bundle/artifacts/build.go | 2 +- bundle/artifacts/validate.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bundle/artifacts/build.go b/bundle/artifacts/build.go index 989a0db321..62529b7ab6 100644 --- a/bundle/artifacts/build.go +++ b/bundle/artifacts/build.go @@ -21,7 +21,7 @@ func Build() bundle.Mutator { type build struct{} func (m *build) Name() string { - return "artifacts.Build()" + return "artifacts.Build" } func (m *build) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { diff --git a/bundle/artifacts/validate.go b/bundle/artifacts/validate.go index a15d32cd03..80c8e52f0f 100644 --- a/bundle/artifacts/validate.go +++ b/bundle/artifacts/validate.go @@ -21,7 +21,7 @@ func Validate() bundle.Mutator { type validate struct{} func (m *validate) Name() string { - return "artifacts.Validate()" + return "artifacts.Validate" } func (m *validate) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { From 762b1d9f060fa0a5daaf6c9c7229bde42f9defc1 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:46:52 +0100 Subject: [PATCH 14/24] update acc tests --- acceptance/bundle/debug/out.stderr.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acceptance/bundle/debug/out.stderr.txt b/acceptance/bundle/debug/out.stderr.txt index a6047208a5..43e96b0210 100644 --- a/acceptance/bundle/debug/out.stderr.txt +++ b/acceptance/bundle/debug/out.stderr.txt @@ -60,8 +60,8 @@ 10:07:59 Debug: Apply pid=12345 mutator=ConfigureWSFS 10:07:59 Debug: Apply pid=12345 mutator=TranslatePaths 10:07:59 Debug: Apply pid=12345 mutator=PythonWrapperWarning -10:07:59 Debug: Apply pid=12345 mutator=artifacts.Validate() -10:07:59 Info: No local tasks in databricks.yml config, skipping auto detect pid=12345 mutator=artifacts.Validate() +10:07:59 Debug: Apply pid=12345 mutator=artifacts.Validate +10:07:59 Info: No local tasks in databricks.yml config, skipping auto detect pid=12345 mutator=artifacts.Validate 10:07:59 Debug: Apply pid=12345 mutator=apps.Validate 10:07:59 Debug: Apply pid=12345 mutator=ValidateSharedRootPermissions 10:07:59 Debug: Apply pid=12345 mutator=ApplyBundlePermissions From 388b8812425f304bbe58b956859a542f9e4fec1e Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 16:49:43 +0100 Subject: [PATCH 15/24] update NEXT_CHANGELOG.md --- NEXT_CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index 0020ab739b..b8d015d151 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -6,4 +6,6 @@ ### Bundles +* Processing 'artifacts' section is now done in "bundle validate" (adding defaults, inferring "build", asserting required fields). + ### API Changes From 842137991514126fc096ff4fa07d371d709dcfad Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 17:00:02 +0100 Subject: [PATCH 16/24] add replacement for windows --- acceptance/bundle/artifacts/globs_in_files/test.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/acceptance/bundle/artifacts/globs_in_files/test.toml b/acceptance/bundle/artifacts/globs_in_files/test.toml index a030353d57..93ee159927 100644 --- a/acceptance/bundle/artifacts/globs_in_files/test.toml +++ b/acceptance/bundle/artifacts/globs_in_files/test.toml @@ -1 +1,5 @@ RecordRequests = false + +[[Repls]] +Old = '\\\\' +New = '/' From 4e961c5b5c7f4cd9ab231c577f0616cae8ecfe17 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 17:10:27 +0100 Subject: [PATCH 17/24] add link to PR in NEXT_CHANGELOG.md --- NEXT_CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index b8d015d151..246418a3a1 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -6,6 +6,6 @@ ### Bundles -* Processing 'artifacts' section is now done in "bundle validate" (adding defaults, inferring "build", asserting required fields). +* Processing 'artifacts' section is now done in "bundle validate" (adding defaults, inferring "build", asserting required fields) ([#2526])(https://github.com/databricks/cli/pull/2526)) ### API Changes From 46c9ce8704ef761e310cde99e483deea3ada6ac6 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 20:52:38 +0100 Subject: [PATCH 18/24] rename Validate() to Prepare() --- bundle/artifacts/{validate.go => prepare.go} | 12 ++++++------ bundle/phases/initialize.go | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) rename bundle/artifacts/{validate.go => prepare.go} (93%) diff --git a/bundle/artifacts/validate.go b/bundle/artifacts/prepare.go similarity index 93% rename from bundle/artifacts/validate.go rename to bundle/artifacts/prepare.go index 80c8e52f0f..b94bfbf4a9 100644 --- a/bundle/artifacts/validate.go +++ b/bundle/artifacts/prepare.go @@ -14,17 +14,17 @@ import ( "github.com/databricks/cli/libs/python" ) -func Validate() bundle.Mutator { - return &validate{} +func Prepare() bundle.Mutator { + return &prepare{} } -type validate struct{} +type prepare struct{} -func (m *validate) Name() string { - return "artifacts.Validate" +func (m *prepare) Name() string { + return "artifacts.Prepare" } -func (m *validate) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { +func (m *prepare) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { var diags diag.Diagnostics err := InsertPythonArtifact(ctx, b) diff --git a/bundle/phases/initialize.go b/bundle/phases/initialize.go index c95c0c0d8f..b3d21be9f4 100644 --- a/bundle/phases/initialize.go +++ b/bundle/phases/initialize.go @@ -97,7 +97,7 @@ func Initialize(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { mutator.TranslatePaths(), trampoline.WrapperWarning(), - artifacts.Validate(), + artifacts.Prepare(), apps.Validate(), From 90e9af295b1391f678ab32332b8c63de0e44cf76 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 20:58:45 +0100 Subject: [PATCH 19/24] update golden files --- .../bundle/testdata/default_python/bundle_summary.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/integration/bundle/testdata/default_python/bundle_summary.txt b/integration/bundle/testdata/default_python/bundle_summary.txt index 0b4cbb1814..6f2eb698f0 100644 --- a/integration/bundle/testdata/default_python/bundle_summary.txt +++ b/integration/bundle/testdata/default_python/bundle_summary.txt @@ -59,6 +59,13 @@ "artifact_path": "/Workspace/Users/[USERNAME]/.bundle/project_name_$UNIQUE_PRJ/dev/artifacts", "state_path": "/Workspace/Users/[USERNAME]/.bundle/project_name_$UNIQUE_PRJ/dev/state" }, + "artifacts": { + "python_artifact": { + "type": "whl", + "path": "/tmp/.../project_name_$UNIQUE_PRJ", + "build": "python3 setup.py bdist_wheel" + } + }, "resources": { "jobs": { "project_name_$UNIQUE_PRJ_job": { From 95bea29c8b062871f6bd7c157cfa9c932b6a22d4 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 21:18:48 +0100 Subject: [PATCH 20/24] fix case when build and files are both present; add test --- .../bundle/artifacts/build_and_files/databricks.yml | 9 +++++++++ .../bundle/artifacts/build_and_files/output.txt | 11 +++++++++++ acceptance/bundle/artifacts/build_and_files/script | 1 + bundle/artifacts/prepare.go | 2 +- 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 acceptance/bundle/artifacts/build_and_files/databricks.yml create mode 100644 acceptance/bundle/artifacts/build_and_files/output.txt create mode 100644 acceptance/bundle/artifacts/build_and_files/script diff --git a/acceptance/bundle/artifacts/build_and_files/databricks.yml b/acceptance/bundle/artifacts/build_and_files/databricks.yml new file mode 100644 index 0000000000..159d806fb5 --- /dev/null +++ b/acceptance/bundle/artifacts/build_and_files/databricks.yml @@ -0,0 +1,9 @@ +bundle: + name: build_and_files + +artifacts: + custom: + build: touch built.txt + files: + # this file does not exist yet, will be generated by build command + - source: built.txt diff --git a/acceptance/bundle/artifacts/build_and_files/output.txt b/acceptance/bundle/artifacts/build_and_files/output.txt new file mode 100644 index 0000000000..ef4cb6002b --- /dev/null +++ b/acceptance/bundle/artifacts/build_and_files/output.txt @@ -0,0 +1,11 @@ +{ + "custom": { + "build": "touch built.txt", + "files": [ + { + "source": "[TMPDIR]/built.txt" + } + ], + "path": "[TMPDIR]" + } +} diff --git a/acceptance/bundle/artifacts/build_and_files/script b/acceptance/bundle/artifacts/build_and_files/script new file mode 100644 index 0000000000..c3ba9bd25f --- /dev/null +++ b/acceptance/bundle/artifacts/build_and_files/script @@ -0,0 +1 @@ +$CLI bundle validate -o json | jq .artifacts diff --git a/bundle/artifacts/prepare.go b/bundle/artifacts/prepare.go index b94bfbf4a9..fb3b718ab9 100644 --- a/bundle/artifacts/prepare.go +++ b/bundle/artifacts/prepare.go @@ -73,7 +73,7 @@ func (m *prepare) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics diags = diags.Extend(diag.Errorf("misconfigured artifact: please specify 'build' or 'files' property")) } - if len(artifact.Files) > 0 { + if len(artifact.Files) > 0 && artifact.BuildCommand == "" { diags = diags.Extend(expandGlobs(ctx, b, artifactName)) } From 41630bbe2c56cce8d4a27c636a8a3ad0f3724f3f Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 21:23:21 +0100 Subject: [PATCH 21/24] fix build_and_files --- acceptance/bundle/artifacts/build_and_files/test.toml | 1 + 1 file changed, 1 insertion(+) create mode 100644 acceptance/bundle/artifacts/build_and_files/test.toml diff --git a/acceptance/bundle/artifacts/build_and_files/test.toml b/acceptance/bundle/artifacts/build_and_files/test.toml new file mode 100644 index 0000000000..a030353d57 --- /dev/null +++ b/acceptance/bundle/artifacts/build_and_files/test.toml @@ -0,0 +1 @@ +RecordRequests = false From c995d6300eca149ba492eb28e7d0687c9d772a45 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 21:28:51 +0100 Subject: [PATCH 22/24] update output --- acceptance/bundle/debug/out.stderr.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acceptance/bundle/debug/out.stderr.txt b/acceptance/bundle/debug/out.stderr.txt index 43e96b0210..dc8f52b79a 100644 --- a/acceptance/bundle/debug/out.stderr.txt +++ b/acceptance/bundle/debug/out.stderr.txt @@ -60,8 +60,8 @@ 10:07:59 Debug: Apply pid=12345 mutator=ConfigureWSFS 10:07:59 Debug: Apply pid=12345 mutator=TranslatePaths 10:07:59 Debug: Apply pid=12345 mutator=PythonWrapperWarning -10:07:59 Debug: Apply pid=12345 mutator=artifacts.Validate -10:07:59 Info: No local tasks in databricks.yml config, skipping auto detect pid=12345 mutator=artifacts.Validate +10:07:59 Debug: Apply pid=12345 mutator=artifacts.Prepare +10:07:59 Info: No local tasks in databricks.yml config, skipping auto detect pid=12345 mutator=artifacts.Prepare 10:07:59 Debug: Apply pid=12345 mutator=apps.Validate 10:07:59 Debug: Apply pid=12345 mutator=ValidateSharedRootPermissions 10:07:59 Debug: Apply pid=12345 mutator=ApplyBundlePermissions From e35b6c35ff491bee9c9eb4b50102d2f6e2994593 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 21:45:00 +0100 Subject: [PATCH 23/24] windows slash fix --- acceptance/bundle/artifacts/build_and_files/test.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/acceptance/bundle/artifacts/build_and_files/test.toml b/acceptance/bundle/artifacts/build_and_files/test.toml index a030353d57..93ee159927 100644 --- a/acceptance/bundle/artifacts/build_and_files/test.toml +++ b/acceptance/bundle/artifacts/build_and_files/test.toml @@ -1 +1,5 @@ RecordRequests = false + +[[Repls]] +Old = '\\\\' +New = '/' From 844f003085fca26b4055d867c028a8cbc01d976a Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 19 Mar 2025 21:51:36 +0100 Subject: [PATCH 24/24] ignore build/path (for windows) --- integration/bundle/init_default_python_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/integration/bundle/init_default_python_test.go b/integration/bundle/init_default_python_test.go index 9ac8f47bdf..917e06f1e4 100644 --- a/integration/bundle/init_default_python_test.go +++ b/integration/bundle/init_default_python_test.go @@ -126,6 +126,8 @@ func testDefaultPython(t *testing.T, pythonVersion string) { []string{"bundle", "summary", "--output", "json"}, testutil.TestData("testdata/default_python/bundle_summary.txt"), []string{ + "/artifacts/python_artifact/build", + "/artifacts/python_artifact/path", "/bundle/terraform/exec_path", "/resources/jobs/project_name_$UNIQUE_PRJ_job/email_notifications", "/resources/jobs/project_name_$UNIQUE_PRJ_job/job_clusters/0/new_cluster/node_type_id",