Skip to content

Development-mode bundles cannot be centrally destroyed by an authorised service principal #6702

Description

@barryjpodonovan

Describe the issue

Databricks Asset Bundle targets in mode: development cannot be destroyed by a central service principal when the bundle was deployed by an individual developer user. This prevents us from implementing reliable lifecycle management for branch-based local-development deployments.

We use "bundles in the workspace" for each developer in a team of 30 people to deploy an isolated development bundle deployment per developer and Git branch combination (target = local_dev & root_path = /Shared/.bundle/${bundle.name}/${bundle.target}/${var.branch_name}/${var.dev_username}). This is intentional as developers can work on multiple branches concurrently. Target mode development is required for source-linked deployment (allowing notebook edits to be run in jobs without deploying between edits).

When a branch is deleted or becomes inactive, our centrally run GitHub Actions Workflow (GitHub trigger on: delete or on no commit in X days) runs to destroy all deployments associated to the deleted/stale branch. Requiring every developer to manually destroy their own deployments does not scale and leaves orphaned jobs, schemas and other resources when developers change branches, leave the team or miss a cleanup step.

Our service principal hasCAN_MANAGE permissions on the deployed resources and the shared bundle workspace path, but databricks bundle destroy is rejected before it can operate on the deployed bundle because the authenticated identity is not the developer whose username appears in the development-mode path and prefix. This is despite the DAB granting manage permissions to the SP explicitly for this purpose.

There is not a risk here of conflicting deployments between development users as each deployment is per developer (as per the root path) and only the individual developer and the SP have manage/write access to the deployed resources.

The current workaround is to enumerate and delete resource types individually through CLI/API commands. It is incomplete by design: every newly supported bundle resource type requires additional custom cleanup logic, and a partial failure can leave orphaned resources without the bundle state being cleaned up atomically.

Configuration

Sanitised relevant target configuration:

variables:

  branch_name:

    description: The name of the branch the bundle is operating under

    default: ${bundle.git.branch}

  dev_username:

    description: The short_name of the developer who deployed the bundle (allows SP to target a specific user's deployment for destroy)

    default: ${workspace.current_user.short_name}

targets:

  local_dev:

    default: true

    mode: development

    presets:

      name_prefix: "zzz_${var.dev_username}__${var.branch_name}__""

      source_linked_deployment: true

      tags:

        branch: ${var.branch_name}

        dev_user: ${var.dev_username}

        dab_target: Local Dev

    workspace:

      root_path: /Shared/.bundle/${bundle.name}/${bundle.target}/${var.branch_name}/${var.dev_username}

    permissions:

      - service_principal_name: ${var.service_principal}

        level: CAN_MANAGE

      - user_name: ${var.dev_user_email}

        level: CAN_MANAGE

The local-development bundle is deployed by an authenticated developer. A scheduled GitHub Actions cleanup workflow later attempts to run databricks bundle destroy -t local_dev --var="dev_username=<dev_username>" --var="branch_name=<branch_name>" using a service principal that has been granted CAN_MANAGE access. The service principal is intentionally not included in the user-specific development root_path or name prefix. These values identify the deployment owner and preserve per-user, per-branch isolation.

Steps to reproduce the behavior

  1. Configure a bundle target with mode: development.
  2. Configure a root path and resource name prefix containing the deploying developer's username.
  3. Enable source_linked_deployment: true.
  4. Deploy the bundle while authenticated as a developer.
  5. Authenticate as that service principal.
  6. Run databricks bundle destroy -t local_dev --var="dev_username=<dev_username>" --var="branch_name=<branch_name>"
  7. The CLI rejects the destroy because the root path and prefix do not contain the currently authenticated service principal identity.

Expected behavior

An explicitly authorised administrative identity should be able to destroy a development-mode bundle deployment owned by another user.

At minimum, one of the following should be supported:

  • Permit source-linked deployment in a production-mode target, allowing teams to use an SP to destroy the target bundle state without losing source-linked development.
  • Relax the development-mode username validation for bundle destroy when the authenticated identity has appropriate workspace and resource permissions as this is a heavy handed approach to protecting the deployed bundle state for targets in mode: development
  • Provide an explicit, auditable administrative override for lifecycle commands, such as bundle destroy, that permits a central service principal to manage another user's development-mode deployment.
  • Provide a supported bundle-native cleanup operation that can discover and destroy a branch deployment independently of the original developer's identity.

The normal safety defaults for development mode make sense for individual developers. The missing case is a controlled platform-admin workflow that performs cleanup using a deliberately authorised service principal.

Actual behavior

The CLI validates the currently authenticated identity against the resolved development-mode root path and resource prefix before it performs the destroy. The centrally authorised service principal therefore cannot destroy the developer-owned deployment.

The workflow reports that cleanup may be partial, and custom resource-by-resource deletion is required as a workaround.

Error output


Warning: source-linked deployment is available only in the Databricks Workspace

  at targets.local_dev.presets.source_linked_deployment

  in databricks.yml:151:33

Error: root_path must start with '~/' or contain the current username to ensure uniqueness when using 'mode: development'

Error: prefix should contain the current username or ${workspace.current_user.short_name} to ensure uniqueness when using 'mode: development'

  in databricks.yml:149:20

Warning: Failed to destroy bundle for user: <developer_username> (may be partially cleaned)

Error: Process completed with exit code 1.

Why the usual workaround is unsuitable

A shared workspace location is deliberate, not accidental. It lets a central service principal discover, manage, and clean up branch-scoped deployments across a larger engineering team.

Moving every deployment into a personal workspace folder would make central automated cleanup impractical. It would require every developer to reliably destroy every branch deployment manually, including deployments created on branches they no longer actively use.

The platform resources are already protected by permissions. In this case, the additional development-mode identity check blocks the identity that has specifically been granted the permissions needed for automated cleanup.

OS and CLI version

  • OS / CI runner: Linux

  • Databricks CLI version: 1.15.0

  • Still reproducible with latest CLI: yes

Is this a regression?

No

Debug logs

The failure occurs in a GitHub Actions cleanup workflow.

Image

Additional context

This is a platform-management use case rather than a request to bypass permissions. The service principal is the approved automation identity for the workspace and has been granted management permissions precisely so that inactive branch deployments can be cleaned up safely and consistently.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    DABsDABs related issues

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions