Skip to content

feat(python-setup): recover from a constraint conflict with a Retry-as-DB-Connect fallback - #2186

Merged
rugpanov merged 1 commit into
mainfrom
rugpanov/python-setup-conflict-fallback-main
Sep 10, 2026
Merged

feat(python-setup): recover from a constraint conflict with a Retry-as-DB-Connect fallback#2186
rugpanov merged 1 commit into
mainfrom
rugpanov/python-setup-conflict-fallback-main

Conversation

@rugpanov

@rugpanov rugpanov commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Why

The uv-native "set up Python environment" Full preset pins the cluster's
dependencies, so uv sync can fail when those pins conflict with the user's own
dependencies. The CLI now emits a distinct E_PROVISION_CONFLICT for that
case (shipped in CLI v1.16.0, already bundled on main). Rather than the
generic E_PROVISION toast ("uv could not resolve the project's dependencies…
adjust your dependencies"), offer a one-click recovery: re-run as DB Connect
(--no-constraints), which drops the conflicting cluster-dependency pins while
keeping matched Python + databricks-connect.

What

  • E_PROVISION_CONFLICT — a distinct result-model error code for a genuine
    pin-vs-local conflict (a generic sync failure stays E_PROVISION), with its
    own copy: "The cluster dependencies conflict with your local dependencies, so
    uv sync couldn't resolve the environment."
  • Recovery UX (Full-preset conflict only) — the generic toast is replaced
    with Retry DB Connect setup and Open pyproject.toml. "Show Logs" is
    dropped from this self-service toast (the channel is still revealed).
  • Restore-then-retry — the conflict fails after the runtime pins were
    merged into pyproject.toml (diskMutated: true, pre-merge file saved to the
    CLI's backupPath). So Retry first restores that backup, then re-runs with
    the dbconnect preset — --no-constraints alone would only stop the retry
    from re-adding pins, not remove those already on disk. The restore is atomic
    (temp sibling + rename) and refuses a backupPath resolving outside the
    project. When backupPath is absent/empty (e.g. a no-op-merge re-run), Retry
    isn't offered and the run falls back to the ordinary doc-link handling.
  • GuardsrunGuarded/runResolved let the retry re-enter with the
    dbconnect preset directly (no re-prompt), coalesced so a click can't race an
    in-flight run; dbconnect skips constraints so the retry can't loop; a stale
    toast's Retry no-ops once the project is ready.
  • Telemetry — a conflict_retry value on the existing
    python_env.setup.attempt trigger dimension marks recovery runs, paired with
    the python_env.setup.result outcome for the recovery success rate. No new
    event. A conflict is never report-worthy (it's the user's own dependencies).

Live against the shipped CLI

Unlike when this was first written, CLI v1.16.0 (on main) emits
E_PROVISION_CONFLICT
, so the recovery path is now exercised end-to-end, not
dormant. Note: the CLI only populates backupPath on the first merge; a
re-run over an already-merged pyproject.toml is a no-op merge and returns an
empty backupPath, in which case the run correctly falls through to the generic
path (the truthy-backupPath guard).

Testing

  • test:unit: new coverage for the conflict copy + fallback doc link, the
    run-action dispatch, openProjectFile, the controller conflict→retry flow
    (restore-before-retry ordering, --no-constraints + adopt on success,
    conflict_retry telemetry paired with its outcome, open pyproject at the run's
    cwd, reportOffered: false, missing/empty-backupPath and non-Full fallbacks,
    restore-failure aborts without a retry attempt), and the atomic/in-project
    restore wiring.
  • tsc + eslint + prettier clean on changed files.

Supersedes #2181, which merged into the (now-defunct) preset-picker branch rather
than main.

This pull request and its description were written by Isaac.

…s-DB-Connect fallback

*Why*
The uv-native "set up Python environment" Full preset pins the cluster/serverless
runtime's dependencies, so `uv sync` can fail when those pins conflict with the
user's own. The CLI now emits a distinct E_PROVISION_CONFLICT for that case
(shipped in CLI v1.16.0). Rather than the generic "adjust your dependencies"
message, offer a one-click recovery: re-run as DB Connect (which drops the pins).

*What*
- E_PROVISION_CONFLICT error code + actionable copy; a genuine pin-vs-local
  conflict, distinct from the generic E_PROVISION.
- Recovery toast (Full preset only): "Retry DB Connect setup" + "Open
  pyproject.toml"; "Show Logs" dropped from this self-service toast.
- Retry restores the CLI's pre-merge pyproject.toml backup (result.backupPath)
  before re-running with --no-constraints — the pins are merged to disk before
  provision fails, so --no-constraints alone would leave them in place. Restore
  is atomic (temp + rename), refuses a backupPath outside the project, and a
  truthy-backupPath guard falls through to the generic path when absent (e.g. a
  no-op-merge re-run).
- Guarded against loops (dbconnect skips constraints), stale-toast re-provision,
  and concurrent runs (coalesces onto an in-flight run).
- Telemetry: a conflict_retry value on the setup.attempt trigger dimension,
  paired with the result outcome for the recovery success rate.

*Verification*
- Unit tests for the conflict copy, run-action dispatch, restore ordering,
  --no-constraints + adopt, telemetry pairing, no-loop, coalescing, stale/empty/
  missing-backupPath fallbacks, and atomic/in-project restore wiring.
- Recreated cleanly against main (supersedes #2181, which merged into the
  preset-picker branch, not main); tsc + targeted unit tests green.

Co-authored-by: Isaac <no-reply@databricks.com>
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

If integration tests don't run automatically, an authorized user can run them manually by following the instructions below:

Trigger:
go/deco-tests-run/vscode

Inputs:

  • PR number: 2186
  • Commit SHA: 5e67299046dfab1ea30148396ab4ab40c8d1fadc

Checks will be approved automatically on success.

@rugpanov

rugpanov commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Integration tests running for 5e672990 — ⏳.
View run

@rugpanov
rugpanov merged commit 06cfbf1 into main Sep 10, 2026
9 of 11 checks passed
@github-actions github-actions Bot mentioned this pull request Sep 10, 2026
rugpanov added a commit that referenced this pull request Sep 10, 2026
Release **v2.17.0** of the Databricks VS Code extension.

## What's included

- Add a Python environment setup preset picker to choose a Full, DB
Connect, or Python-only environment (#2179)
- Recover from a dependency constraint conflict during Python setup by
offering to retry as a DB Connect environment (#2186)
-   Add recovery UX for Python download failures (#2164)
- Show an actionable error when Python setup hits a merge conflict on a
`pyproject.toml` without a `[project]` table (#2180)
-   Preserve script stdout when an Upload-and-Run file fails (#2171)
- Update Databricks CLI to v1.16.0 (#2175, #2183) — see the [CLI release
notes](https://github.com/databricks/cli/releases) for changes

Changelog curated from the generated output (stripped auto-close refs,
dropped internal telemetry/CI-only items). Tracking: DECO-28498.

---------

Co-authored-by: releasebot <noreply@github.com>
Co-authored-by: @rugpanov <gripanov@gmail.com>
Co-authored-by: Isaac <no-reply@databricks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants