Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions bundle/config/mutator/resourcemutator/validate_target_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,17 @@ func findNonUserPath(b *bundle.Bundle) string {
if b.Config.Workspace.RootPath != "" && !containsName(b.Config.Workspace.RootPath) {
return "root_path"
}
if b.Config.Workspace.FilePath != "" && !containsName(b.Config.Workspace.FilePath) {
return "file_path"
if !b.IsImmutableFolder() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Databricks Runtime, development mode automatically enables source-linked deployment for bundles under /Workspace. With immutable folders enabled, TranslatePaths sends relative resource paths to the snapshot, but ${workspace.file_path} references in resources still resolve to the mutable sync root through the source-linked lookup. This skip makes that combination pass validation, so a single job can mix snapshot paths with source-tree paths that change without a deploy. Please disable source linking for immutable bundles or make those references resolve to the snapshot; a full-pipeline development-mode test would catch the mismatch.

if b.Config.Workspace.FilePath != "" && !containsName(b.Config.Workspace.FilePath) {
return "file_path"
}
if b.Config.Workspace.ArtifactPath != "" && !containsName(b.Config.Workspace.ArtifactPath) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An explicitly configured workspace.artifact_path survives DefineDefaultWorkspacePaths because it only fills empty values, but this guard now skips it for every immutable bundle. For example, with artifact_path: /Workspace/Shared/libs, a job library at ${workspace.artifact_path}/.internal/pkg.whl resolves to that shared path, while immutable deployment packages the wheel under the snapshot's artifacts/.internal and skips the normal library upload. The job can point to a missing or stale wheel. Please reject an explicit artifact_path in immutable mode, as TranslatePaths already does for file_path, or restrict this exemption to the generated snapshot path. The new test at line 184 uses an explicit /Shared path and would need to change accordingly.

return "artifact_path"
}
}
if b.Config.Workspace.ResourcePath != "" && !containsName(b.Config.Workspace.ResourcePath) {
return "resource_path"
}
if b.Config.Workspace.ArtifactPath != "" && !containsName(b.Config.Workspace.ArtifactPath) {
return "artifact_path"
}
if b.Config.Workspace.StatePath != "" && !containsName(b.Config.Workspace.StatePath) {
return "state_path"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,58 @@ func TestProcessTargetModeProductionOkWithRootPath(t *testing.T) {
require.NoError(t, diags.Error())
}

func TestFindNonUserPath(t *testing.T) {
// No paths set at all.
b := mockBundle(config.Development)
b.Config.Workspace.StatePath = ""
b.Config.Workspace.ArtifactPath = ""
b.Config.Workspace.FilePath = ""
assert.Empty(t, findNonUserPath(b))

// All paths contain the username or short name: no non-user path found.
b = mockBundle(config.Development)
b.Config.Workspace.RootPath = "/Users/lennart@company.com/.bundle/x/y/state"
b.Config.Workspace.ResourcePath = "/Users/lennart/.bundle/x/y/resources"
assert.Empty(t, findNonUserPath(b))

// root_path is checked first.
b = mockBundle(config.Development)
b.Config.Workspace.RootPath = "/Shared/.bundle/x/y"
assert.Equal(t, "root_path", findNonUserPath(b))

// file_path is checked next.
b = mockBundle(config.Development)
b.Config.Workspace.FilePath = "/Shared/.bundle/x/y/files"
assert.Equal(t, "file_path", findNonUserPath(b))

// file_path is skipped when the workspace uses an immutable folder.
b = mockBundle(config.Development)
b.Config.Workspace.FilePath = "/Shared/.bundle/x/y/files"
b.Config.Experimental = &config.Experimental{ImmutableFolder: true}
assert.Empty(t, findNonUserPath(b))

// resource_path is checked next.
b = mockBundle(config.Development)
b.Config.Workspace.ResourcePath = "/Shared/.bundle/x/y/resources"
assert.Equal(t, "resource_path", findNonUserPath(b))

// artifact_path is checked next.
b = mockBundle(config.Development)
b.Config.Workspace.ArtifactPath = "/Shared/.bundle/x/y/artifacts"
assert.Equal(t, "artifact_path", findNonUserPath(b))

// artifact_path is skipped when the workspace uses an immutable folder.
b = mockBundle(config.Development)
b.Config.Workspace.ArtifactPath = "/Shared/.bundle/x/y/artifacts"
b.Config.Experimental = &config.Experimental{ImmutableFolder: true}
assert.Empty(t, findNonUserPath(b))

// state_path is checked last.
b = mockBundle(config.Development)
b.Config.Workspace.StatePath = "/Shared/.bundle/x/y/state"
assert.Equal(t, "state_path", findNonUserPath(b))
}

func TestTriggerPauseStatusWhenUnpaused(t *testing.T) {
b := mockBundle(config.Development)
b.Config.Presets.TriggerPauseStatus = config.Unpaused
Expand Down