feat(python-setup): add the Python-setup preset picker (Full / DB Connect / Python) - #2179
Merged
Merged
Conversation
rugpanov
temporarily deployed
to
test-trigger-is
September 7, 2026 15:10 — with
GitHub Actions
Inactive
rugpanov
temporarily deployed
to
test-trigger-is
September 7, 2026 15:10 — with
GitHub Actions
Inactive
rugpanov
temporarily deployed
to
test-trigger-is
September 7, 2026 15:10 — with
GitHub Actions
Inactive
Contributor
Author
|
🤖 Integration tests running for |
rugpanov
force-pushed
the
rugpanov/python-setup-preset-picker
branch
from
September 7, 2026 15:30
2462d6e to
04b00a5
Compare
rugpanov
temporarily deployed
to
test-trigger-is
September 7, 2026 15:30 — with
GitHub Actions
Inactive
rugpanov
temporarily deployed
to
test-trigger-is
September 7, 2026 15:30 — with
GitHub Actions
Inactive
rugpanov
temporarily deployed
to
test-trigger-is
September 7, 2026 15:30 — with
GitHub Actions
Inactive
…nect / Python) *Why* - The uv-native setup flow always ran the "Full" preset; users had no way to choose a lighter tier (matching Python + Databricks Connect without pins, or matching Python only), even though the CLI already supports the orthogonal --no-constraints / --no-dbconnect flags. - The two-value telemetry `mode` dimension cannot represent a --no-constraints run, so a DB Connect run would misreport as `mode: default` despite skipping the pins. A picker that sets flags orthogonally makes that gap actionable. *What* - New pure util `pythonSetupPresetPicker.ts`: `SetupPreset`, `presetToFlags` (full -> no flags; dbconnect -> --no-constraints; python -> both), `buildPresetPickItems` (the three verbatim rows, Full starred/first), `computeTargetLabel` (serverless vN / Runtime X.Y / generic fallback), and `pickSetupPreset` using the explicit `createQuickPick` lifecycle (onDidAccept resolves the row, onDidHide = dismissed), createQuickPick injected as a required seam (no global default) for testability. - Controller: a `pickSetupPreset` dep is called after compute resolves (so the title names the target); dismissing it bails out silently with no attempt recorded, mirroring a dismissed serverless-version prompt. The invocation's skip flags are built from the chosen preset. - Wiring: the dep is composed from `computeTargetLabel` + the injected `createQuickPick`; `extension.ts` resolves the cluster's DBR (from the attached cluster, else fetched by id) so the title always carries the runtime. - Telemetry: a new categorical `setupPreset` dimension (full | dbconnect | python) on `python_env.setup.attempt`, disambiguating the two orthogonal skip axes. The legacy `mode` field is kept, derived as before, for dashboard continuity. *Verification* - Unit suite (test:unit): preset/wiring/telemetry tests green. The only failures are the pre-existing packageJsonUtils stale-bundled-CLI worktree artifact (`1.14.1` vs pinned `1.15.0`), which CI passes by fetching the pinned binary. - tsc + eslint clean on all changed files (the one remaining tsc error is the known cross-worktree `Cluster` self-symlink artifact at extension.ts). Co-authored-by: Isaac <no-reply@databricks.com>
rugpanov
force-pushed
the
rugpanov/python-setup-preset-picker
branch
from
September 7, 2026 15:31
04b00a5 to
83549f8
Compare
rugpanov
temporarily deployed
to
test-trigger-is
September 7, 2026 15:31 — with
GitHub Actions
Inactive
rugpanov
temporarily deployed
to
test-trigger-is
September 7, 2026 15:31 — with
GitHub Actions
Inactive
rugpanov
temporarily deployed
to
test-trigger-is
September 7, 2026 15:32 — with
GitHub Actions
Inactive
Contributor
Author
|
🤖 Integration tests ❌ failed for |
*Why*
- The picker added in this branch shows a mandatory single-select QuickPick
after compute resolves. The uv setup-local e2e specs invoked setup and then
waited for the .venv / ready toast without answering that new prompt, so the
run would stall (the interpreter never appears) once it reaches the picker.
- The re-run spec awaited `rerunPythonEnv` *inside* `executeWorkbench`, which
would deadlock: the command can't resolve until the picker is answered, but
the test can't answer it while blocked inside the callback.
*What*
- After each `Databricks: Setup python environment` / `rerunPythonEnv` trigger,
wait for the preset QuickPick and select the recommended Full tier
(index 0 — starred and first), so the full environment is provisioned.
- Fire `rerunPythonEnv` fire-and-forget (`void executeCommand`) instead of
awaiting it inside `executeWorkbench`, then drive the picker from the test.
- Full maps to no skip flags, so the spec keeps working against the pinned CLI
even before the orthogonal-flag CLI ships.
*Verification*
- eslint + prettier clean on the spec; e2e tsconfig typecheck clean for this
file (the only tsc error is the pre-existing wdio.conf import-assertion quirk).
- The current Integration Tests failure was an unrelated shared cluster-start
infra flake ("Timeout while placing nodes") that aborted warm-up before these
specs ran; this change makes them pass once the picker is actually reached.
Co-authored-by: Isaac <no-reply@databricks.com>
rugpanov
temporarily deployed
to
test-trigger-is
September 8, 2026 08:54 — with
GitHub Actions
Inactive
rugpanov
temporarily deployed
to
test-trigger-is
September 8, 2026 08:54 — with
GitHub Actions
Inactive
rugpanov
temporarily deployed
to
test-trigger-is
September 8, 2026 08:54 — with
GitHub Actions
Inactive
rugpanov
marked this pull request as ready for review
September 8, 2026 10:11
Contributor
Author
|
🤖 Integration tests ✅ passed for |
misha-db
approved these changes
Sep 8, 2026
rugpanov
enabled auto-merge (squash)
September 9, 2026 16:20
rugpanov
temporarily deployed
to
test-trigger-is
September 9, 2026 16:20 — with
GitHub Actions
Inactive
rugpanov
temporarily deployed
to
test-trigger-is
September 9, 2026 16:20 — with
GitHub Actions
Inactive
Contributor
|
If integration tests don't run automatically, an authorized user can run them manually by following the instructions below: Trigger: Inputs:
Checks will be approved automatically on success. |
rugpanov
temporarily deployed
to
test-trigger-is
September 9, 2026 16:21 — with
GitHub Actions
Inactive
rugpanov
added a commit
that referenced
this pull request
Sep 9, 2026
…s-DB-Connect fallback (#2181) ## 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. Today that surfaces as the generic `E_PROVISION` toast ("uv could not resolve the project's dependencies… adjust your dependencies"), which leaves the user to work out on their own that dropping the pins — the **DB Connect** preset (`--no-constraints`) — would resolve it 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 actionable copy: *"The cluster dependencies conflict with your local dependencies, so uv sync couldn't resolve the environment."* - **Recovery UX** — on a Full-preset conflict the generic toast is replaced with two buttons: **Retry DB Connect setup** and **Open pyproject.toml**. "Show Logs" is dropped from this toast (it's self-service — the channel is still revealed), and every other provision failure is unchanged. - **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`) — `--no-constraints` alone only stops the retry from re-adding pins, it wouldn't remove the ones already on disk. The restore is atomic (temp sibling + rename) and refuses a `backupPath` outside the project. With no `backupPath`, Retry isn't offered and the run falls back to the ordinary doc-link handling. - **`run` action arm** — `PythonSetupErrorAction` gains an in-process-callback arm alongside `url`/`command`, so the two runtime-stateful buttons reuse `showError`'s existing plumbing (label de-dup, log reveal); `showError` gains an `includeShowLogs` option to drop the trailing button for this toast. - **`runGuarded` / `runResolved`** extracted from `runSetup`, so the retry re-enters the flow with the `dbconnect` preset directly — no re-prompt of the compute or the preset picker, and guarded so a click can't race an in-flight run (and the restore only fires when the retry actually runs). Because `dbconnect` skips constraints, the retry can't itself surface a recoverable conflict (no loop), and 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). ## Depends on the CLI conflict code (dormant until it ships) `E_PROVISION_CONFLICT` is a CLI-emitted code that is **not yet in a released CLI** — the extension is coded against the contract, so the new recovery path is fully unit-tested but stays inert (a real conflict still arrives as `E_PROVISION` today) until the CLI emits the distinct code **and populates `backupPath` on that failure** (the restore-then-retry relies on it). This mirrors the stacked-on picker PR's own posture. No end-to-end test is added for that reason. ## Testing - `test:unit`: 1126 passing. New coverage: 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-`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. Stacked on #2179 — review/merge that first. This pull request and its description were written by Isaac. --------- Co-authored-by: Isaac <no-reply@databricks.com>
Merged
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The uv-native "set up Python environment" flow always ran the Full preset — it hardcoded a flag-free
setup-localinvocation. Users had no way to pick a lighter tier, even though the CLI already exposes the orthogonal--no-constraints/--no-dbconnectflags.Separately, the two-value telemetry
modedimension (default|constraints-only, derived fromskipDbconnect) cannot represent a--no-constraints-only run: a DB Connect run would reportmode: defaultdespite skipping the pins. A picker that sets the two axes orthogonally makes that gap actionable.What
pythonSetupPresetPicker.ts:SetupPreset = full | dbconnect | pythonandpresetToFlags(full → no flags; dbconnect →--no-constraints; python →--no-constraints --no-dbconnect).buildPresetPickItems— the three rows (Full starred and first), copy verbatim from the spec.computeTargetLabel—serverless v5/Runtime 17.3/ a generic fallback when the runtime is unknown.pickSetupPreset— single-select, explicitcreateQuickPicklifecycle (onDidAcceptresolves the row,onDidHide= dismissed);createQuickPickinjected as a seam for tests.pickSetupPresetdep is invoked after compute resolves (so the title names the target). Dismissing it bails out silently with no attempt recorded, mirroring a dismissed serverless-version prompt. The invocation's skip flags come from the chosen preset.computeTargetLabel+ the injectedcreateQuickPick;extension.tsresolves the cluster's DBR (reusing the attached cluster, else fetching by id) so the title always carries the runtime.setupPresetdimension onpython_env.setup.attempt, disambiguating the two orthogonal skip axes. The legacymodefield is retained, derived as before, for dashboard continuity.Testing
test:unit: 1098 passing. New coverage: preset→flags mapping, verbatim row copy, compute-label formatting, picker accept/dismiss, controller flag-threading + dismissal +setupPreset/modetelemetry, wiring composition (title from serverless/cluster DBR), and the telemetry emitter allowlist.tsc+eslintclean on changed files.This pull request and its description were written by Isaac.