Skip to content

Commit 84a1ae6

Browse files
authored
Added support for pipeline environment field (#3153)
## Changes Added support for pipeline `environment` field ## Why This allows setting libraries as dependencies for pipeline serverless environments in the form of ``` pipelines: test_pipeline: name: "Test Pipeline" environment: dependencies: - "dist/*.whl" ``` ## Tests Added an acceptance test <!-- If your PR needs to be included in the release notes for next release, add a separate entry in NEXT_CHANGELOG.md as part of your PR. -->
1 parent 4078ab4 commit 84a1ae6

File tree

9 files changed

+124
-9
lines changed

9 files changed

+124
-9
lines changed

NEXT_CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* Fixed an issue where running `databricks auth login` would remove the `cluster_id` field from profiles in `.databrickscfg`. The login process now preserves the `cluster_id` field. ([#2988](https://github.com/databricks/cli/pull/2988))
1212

1313
### Bundles
14+
* Added support for pipeline environment field ([#3153](https://github.com/databricks/cli/pull/3153))
1415
* "bundle summary" now prints diagnostic warnings to stderr ([#3123](https://github.com/databricks/cli/pull/3123))
1516

1617
### API Changes

acceptance/bundle/environments/dependencies/databricks.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,16 @@ resources:
2929
- "beautifulsoup4>=1.0.0,~=1.2.0,<2.0.0"
3030
- "beautifulsoup4[security, tests] ~= 4.12.3"
3131
- "requests[security] @ https://github.com/psf/requests/archive/refs/heads/main.zip"
32+
33+
pipelines:
34+
test_pipeline:
35+
name: "Test Pipeline"
36+
environment:
37+
dependencies:
38+
- "dist/*.whl"
39+
- "/Workspace/Users/test@databricks.com/test-package.whl"
40+
- "test_package"
41+
- "test_package==2.0.1"
42+
- "test_package>=2.0.1"
43+
- "beautifulsoup4>=1.0.0,~=1.2.0,<2.0.0"
44+
- "requests[security] @ https://github.com/psf/requests/archive/refs/heads/main.zip"

acceptance/bundle/environments/dependencies/output.txt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,32 @@ Deployment complete!
4545
}
4646
]
4747

48+
>>> jq -s .[] | select(.path=="/api/2.0/pipelines") out.requests.txt
49+
{
50+
"method": "POST",
51+
"path": "/api/2.0/pipelines",
52+
"body": {
53+
"channel": "CURRENT",
54+
"deployment": {
55+
"kind": "BUNDLE",
56+
"metadata_file_path": "/Workspace/Users/[USERNAME]/.bundle/dependencies/default/state/metadata.json"
57+
},
58+
"edition": "ADVANCED",
59+
"environment": {
60+
"dependencies": [
61+
"/Workspace/Users/[USERNAME]/.bundle/dependencies/default/artifacts/.internal/test.whl",
62+
"/Workspace/Users/test@databricks.com/test-package.whl",
63+
"test_package",
64+
"test_package==2.0.1",
65+
"test_package>=2.0.1",
66+
"beautifulsoup4>=1.0.0,~=1.2.0,<2.0.0",
67+
"requests[security] @ https://github.com/psf/requests/archive/refs/heads/main.zip"
68+
]
69+
},
70+
"name": "Test Pipeline"
71+
}
72+
}
73+
4874
>>> [CLI] bundle validate -o json
4975
[
5076
{
@@ -74,3 +100,16 @@ Deployment complete!
74100
}
75101
}
76102
]
103+
104+
>>> [CLI] bundle validate -o json
105+
{
106+
"dependencies": [
107+
"./dist/*.whl",
108+
"/Workspace/Users/test@databricks.com/test-package.whl",
109+
"test_package",
110+
"test_package==2.0.1",
111+
"test_package>=2.0.1",
112+
"beautifulsoup4>=1.0.0,~=1.2.0,<2.0.0",
113+
"requests[security] @ https://github.com/psf/requests/archive/refs/heads/main.zip"
114+
]
115+
}

acceptance/bundle/environments/dependencies/script

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,10 @@ trace $CLI bundle validate
55

66
trace $CLI bundle deploy
77
trace jq -s '.[] | select(.path=="/api/2.2/jobs/create") | .body.environments' out.requests.txt
8+
9+
trace jq -s '.[] | select(.path=="/api/2.0/pipelines")' out.requests.txt
10+
811
trace $CLI bundle validate -o json | jq '.resources.jobs.test_job.environments'
12+
trace $CLI bundle validate -o json | jq '.resources.pipelines.test_pipeline.environment'
13+
914
rm out.requests.txt

bundle/config/mutator/paths/pipeline_paths_visitor.go

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
package paths
22

33
import (
4+
"github.com/databricks/cli/bundle/libraries"
45
"github.com/databricks/cli/libs/dyn"
56
)
67

78
type pipelineRewritePattern struct {
89
pattern dyn.Pattern
910
mode TranslateMode
11+
12+
// If function defined in skipRewrite returns true, we skip rewriting the path.
13+
// For example, for environment dependencies, we skip rewriting if the path is not a local library.
14+
skipRewrite func(string) bool
1015
}
1116

1217
func pipelineRewritePatterns() []pipelineRewritePattern {
@@ -17,25 +22,49 @@ func pipelineRewritePatterns() []pipelineRewritePattern {
1722
dyn.AnyKey(),
1823
)
1924

25+
pipelineEnvironmentsPatterns := []pipelineRewritePattern{
26+
{
27+
pattern: dyn.NewPattern(
28+
dyn.Key("resources"),
29+
dyn.Key("pipelines"),
30+
dyn.AnyKey(),
31+
dyn.Key("environment"),
32+
dyn.Key("dependencies"),
33+
dyn.AnyIndex(),
34+
),
35+
mode: TranslateModeLocalRelativeWithPrefix,
36+
skipRewrite: func(s string) bool {
37+
return !libraries.IsLibraryLocal(s)
38+
},
39+
},
40+
}
41+
2042
// Compile list of configuration paths to rewrite.
21-
return []pipelineRewritePattern{
43+
allPatterns := []pipelineRewritePattern{
2244
{
23-
pattern: base.Append(dyn.Key("libraries"), dyn.AnyIndex(), dyn.Key("notebook"), dyn.Key("path")),
24-
mode: TranslateModeNotebook,
45+
pattern: base.Append(dyn.Key("libraries"), dyn.AnyIndex(), dyn.Key("notebook"), dyn.Key("path")),
46+
mode: TranslateModeNotebook,
47+
skipRewrite: noSkipRewrite,
2548
},
2649
{
27-
pattern: base.Append(dyn.Key("libraries"), dyn.AnyIndex(), dyn.Key("file"), dyn.Key("path")),
28-
mode: TranslateModeFile,
50+
pattern: base.Append(dyn.Key("libraries"), dyn.AnyIndex(), dyn.Key("file"), dyn.Key("path")),
51+
mode: TranslateModeFile,
52+
skipRewrite: noSkipRewrite,
2953
},
3054
{
31-
pattern: base.Append(dyn.Key("libraries"), dyn.AnyIndex(), dyn.Key("glob"), dyn.Key("include")),
32-
mode: TranslateModeGlob,
55+
pattern: base.Append(dyn.Key("libraries"), dyn.AnyIndex(), dyn.Key("glob"), dyn.Key("include")),
56+
mode: TranslateModeGlob,
57+
skipRewrite: noSkipRewrite,
3358
},
3459
{
35-
pattern: base.Append(dyn.Key("root_path")),
36-
mode: TranslateModeDirectory,
60+
pattern: base.Append(dyn.Key("root_path")),
61+
mode: TranslateModeDirectory,
62+
skipRewrite: noSkipRewrite,
3763
},
3864
}
65+
66+
allPatterns = append(allPatterns, pipelineEnvironmentsPatterns...)
67+
return allPatterns
3968
}
4069

4170
func VisitPipelinePaths(value dyn.Value, fn VisitFunc) (dyn.Value, error) {
@@ -44,6 +73,14 @@ func VisitPipelinePaths(value dyn.Value, fn VisitFunc) (dyn.Value, error) {
4473

4574
for _, rewritePattern := range pipelineRewritePatterns() {
4675
newValue, err = dyn.MapByPattern(newValue, rewritePattern.pattern, func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
76+
sv, ok := v.AsString()
77+
if !ok {
78+
return v, nil
79+
}
80+
if rewritePattern.skipRewrite(sv) {
81+
return v, nil
82+
}
83+
4784
return fn(p, rewritePattern.mode, v)
4885
})
4986
if err != nil {

bundle/config/mutator/paths/pipeline_paths_visitor_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ func TestVisitPipelinePaths(t *testing.T) {
3434
},
3535
},
3636
},
37+
Environment: &pipelines.PipelinesEnvironment{
38+
Dependencies: []string{
39+
"src/foo.whl",
40+
},
41+
},
3742
},
3843
},
3944
},
@@ -46,6 +51,7 @@ func TestVisitPipelinePaths(t *testing.T) {
4651
dyn.MustPathFromString("resources.pipelines.pipeline0.libraries[1].notebook.path"),
4752
dyn.MustPathFromString("resources.pipelines.pipeline0.libraries[2].glob.include"),
4853
dyn.MustPathFromString("resources.pipelines.pipeline0.root_path"),
54+
dyn.MustPathFromString("resources.pipelines.pipeline0.environment.dependencies[0]"),
4955
}
5056

5157
assert.ElementsMatch(t, expected, actual)

bundle/libraries/expand_glob_references.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,14 @@ var envDepsPattern = dyn.NewPattern(
165165
dyn.Key("dependencies"),
166166
)
167167

168+
var pipelineEnvDepsPattern = dyn.NewPattern(
169+
dyn.Key("resources"),
170+
dyn.Key("pipelines"),
171+
dyn.AnyKey(),
172+
dyn.Key("environment"),
173+
dyn.Key("dependencies"),
174+
)
175+
168176
func (e *expand) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics {
169177
expanders := []expandPattern{
170178
{
@@ -179,6 +187,10 @@ func (e *expand) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics {
179187
pattern: envDepsPattern,
180188
fn: expandEnvironmentDeps,
181189
},
190+
{
191+
pattern: pipelineEnvDepsPattern,
192+
fn: expandEnvironmentDeps,
193+
},
182194
}
183195

184196
var diags diag.Diagnostics

bundle/libraries/same_name_libraries.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ var patterns = []dyn.Pattern{
1818
forEachTaskLibrariesPattern.Append(dyn.AnyIndex(), dyn.Key("whl")),
1919
forEachTaskLibrariesPattern.Append(dyn.AnyIndex(), dyn.Key("jar")),
2020
envDepsPattern.Append(dyn.AnyIndex()),
21+
pipelineEnvDepsPattern.Append(dyn.AnyIndex()),
2122
}
2223

2324
type libData struct {

bundle/libraries/upload.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ func collectLocalLibraries(b *bundle.Bundle) (map[string][]configLocation, error
5959
forEachTaskLibrariesPattern.Append(dyn.AnyIndex(), dyn.Key("whl")),
6060
forEachTaskLibrariesPattern.Append(dyn.AnyIndex(), dyn.Key("jar")),
6161
envDepsPattern.Append(dyn.AnyIndex()),
62+
pipelineEnvDepsPattern.Append(dyn.AnyIndex()),
6263
}
6364

6465
for _, pattern := range patterns {

0 commit comments

Comments
 (0)