镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

localenv: add venv-folder and per-file pyproject seams to setup-local - #7017

Merged
rugpanov merged 5 commits into
mainfrom
uv-workspace-setup-local
Oct 13, 2026
Merged

rugpanov merged 5 commits into
mainfrom
uv-workspace-setup-local

Conversation

@rugpanov

@rugpanov rugpanov commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Stack (merge in this order):

  1. localenv: add venv-folder and per-file pyproject seams to setup-local #7017 localenv: add venv-folder and per-file pyproject seams to setup-local (see diff) <- this PR
  2. Support uv workspace members in environments setup-local #7018 Support uv workspace members in environments setup-local (see diff)
  3. Honor UV_PROJECT_ENVIRONMENT in environments setup-local #7026 Honor UV_PROJECT_ENVIRONMENT in environments setup-local (see diff)

Changes

This PR is a refactor in libs/localenv. It does not change behavior. It adds two seams that #7018 uses for uv workspace members:

  • PostProvision and Validate take the project folder and the venv folder. uv and the validate probe still run in the project folder. Preflight sets the venv folder; for every project it is still .venv.
  • The pyproject.toml backup, write, and dry-run diff are per-file helpers (writePyproject, pyprojectDiff, and backup helpers that take a folder). This lets Support uv workspace members in environments setup-local #7018 write a second file, the workspace root pyproject.toml.

Why

In a uv workspace member, uv sync puts the venv at the workspace root, and uv reads the constraint pins only from the root pyproject.toml (databricks/databricks-vscode#2157). The pipeline used one fixed venv path and one pyproject.toml. This PR makes both locations parameters, so #7018 can change them for a member without a mixed refactor-and-feature diff.

Tests

  • Unit tests: the helpers write the backup next to the file, a no-op merge writes nothing, and uv and the probe run in the project folder.
  • All existing unit and acceptance tests pass with no golden change. This shows that the output does not change.

Known limitations

  • None. This PR changes no behavior.

This pull request and its description were written by Isaac.

rugpanov and others added 2 commits October 12, 2026 13:08
Co-authored-by: Isaac <no-reply@databricks.com>
…elpers

Co-authored-by: Isaac <no-reply@databricks.com>
…ath at preflight

Co-authored-by: Isaac <no-reply@databricks.com>
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 3bc7249

Run: 38275498396

Env 🔄​flaky ✅​pass 🙈​skip Time
✅​ aws linux-2core-8gb 276 16 5:32
✅​ aws-windows-latest-4core-16gb 278 14 4:15
🔄​ azure linux-2core-8gb 2 273 16 5:21
✅​ azure-windows-latest-4core-16gb 277 14 3:23
✅​ gcp linux-2core-8gb 276 16 5:29
✅​ gcp-windows-latest-4core-16gb 278 14 4:15
Test Name azure linux-2core-8gb
🔄​ TestFsCpDir 🔄​f
🔄​ TestFsCpDir/uc-volumes_to_dbfs 🔄​f
Top 6 slowest tests (at least 2 minutes):
duration env testname
4:13 gcp-windows-latest-4core-16gb TestAccept
4:13 aws-windows-latest-4core-16gb TestAccept
3:56 gcp linux-2core-8gb TestAccept
3:52 aws linux-2core-8gb TestAccept
3:50 azure linux-2core-8gb TestAccept
3:22 azure-windows-latest-4core-16gb TestAccept

Co-authored-by: Isaac <no-reply@databricks.com>
@rugpanov
rugpanov marked this pull request as ready for review October 12, 2026 15:42
@rugpanov
rugpanov requested review from a team as code owners October 12, 2026 15:42
Co-authored-by: Isaac <no-reply@databricks.com>
@rugpanov
rugpanov requested a review from misha-db October 12, 2026 16:40
@rugpanov
rugpanov added this pull request to the merge queue Oct 13, 2026
Merged via the queue into main with commit 5e8d8f9 Oct 13, 2026
25 checks passed
@rugpanov
rugpanov deleted the uv-workspace-setup-local branch October 13, 2026 12:31
yuri-rod pushed a commit to yuri-rod/cli that referenced this pull request Oct 13, 2026
…7018)

**Stack** (merge in this order):

1. databricks#7017 localenv: add venv-folder and per-file pyproject seams to
setup-local ([see
diff](databricks/cli@main...uv-workspace-setup-local))
2. databricks#7018 Support uv workspace members in environments setup-local ([see
diff](databricks/cli@uv-workspace-setup-local...uv-workspace-setup-local-2))
**<- this PR**
3. databricks#7026 Honor UV_PROJECT_ENVIRONMENT in environments setup-local ([see
diff](databricks/cli@uv-workspace-setup-local-2...uv-workspace-setup-local-3))

## Changes

`databricks environments setup-local` now works in a member of a uv
workspace (one shared venv for several bundles):

- The command asks uv for the workspace root (`uv workspace dir`, uv
0.9.9 or later). It compares folders by identity, so symlinks and letter
case do not change the result.
- For a member, the venv is `<root>/.venv`. `venvPath` stays relative to
the project folder, for example `../../.venv`.
- The `[tool.uv]` constraint block goes to the root `pyproject.toml`,
because uv reads constraints only from there. `requires-python` and
`databricks-connect` stay in the member. A stale constraint block in the
member is removed.
- The command does not write a root file that uv cannot read. It rejects
a root that defines `[tool.uv]` without a `[tool.uv]` header, and the
merged root must parse as TOML.
- New warning `W_UV_WORKSPACE_CONSTRAINTS_REPLACED`: the run replaced
root pins that an earlier run or the user wrote. All members share these
pins.
- New `omitempty` JSON fields: `uvWorkspaceRoot`,
`uvWorkspaceBackupPath`, `plan.wouldWriteUvWorkspace`,
`plan.wouldBackupUvWorkspace` (the `uv` prefix keeps them apart from a
Databricks workspace). The output for other projects does not change.
- The text summary shows the workspace root. The help text explains the
shared venv.
- An interrupt during discovery stops the run at preflight, before any
file is written.

## Why

In a member, `uv sync` creates the venv at the workspace root, but the
command validated `<member>/.venv` and failed. It also wrote the pins to
the member file, where uv ignores them
(databricks/databricks-vscode#2157).

## Tests

- Unit tests: discovery (member, standalone, greenfield, uv failure,
symlinks, letter case), the root merge and its guards, an idempotent
re-run, `--no-constraints`, and a read-only root.
- Acceptance tests with a fake uv: a dry run in a member, a real run and
a text-mode re-run in a member, and uv without `workspace dir`.
- Integration test with real uv and a two-member workspace (gated by
`DATABRICKS_LOCALENV_TEST_PROVISION`). It fails before this change and
passes after it. It also checks that `uv.lock` applies the root pin.

## Reviewer notes

- The VS Code extension needs a follow-up: resolve `venvPath` against
the project folder, and restore `uvWorkspaceBackupPath` after a failure.

## Known limitations

- With uv older than 0.9.9, discovery fails and the command keeps the
standalone behavior. A member then fails as before.
- A new folder with no `pyproject.toml` is not detected as a member. If
a `members` glob matches it, the first run fails and a second run works.
A follow-up fix is planned.
- The pre-sync conflict check reads only the current member. `uv sync`
still reports conflicts with other members or the root as
`E_PROVISION_CONFLICT`, after the root file changed.
- The command replaces `constraint-dependencies` that a user wrote in
the root `pyproject.toml`. It emits
`W_UV_WORKSPACE_CONSTRAINTS_REPLACED` and keeps a backup.
- `uv sync` is exact, so a run for one member removes packages that only
other members need. All members must target compatible compute.
- `venvPath` is counted from the symlink-resolved project folder. If a
symlink between the root and the member changes the folder depth, a
consumer that joins paths by text gets a wrong folder. `uvWorkspaceRoot`
+ `/.venv` is correct in all cases.
- On Windows, a member reached through a junction can get a wrong
relative `venvPath`, because Windows resolves `..` by text.

This pull request and its description were written by Isaac.

---------

Co-authored-by: Isaac <no-reply@databricks.com>
@eng-dev-ecosystem-bot

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 5e8d8f9

Run: 38397998910

Env ❌​FAIL 🔄​flaky ✅​pass 🙈​skip Time
❌​ aws linux-2core-8gb 8 6 1414 1140 132:46
❌​ aws-windows-latest-4core-16gb 7 1346 1165 145:45
❌​ azure linux-2core-8gb 8 2 1267 1192 115:10
❌​ azure-windows-latest-4core-16gb 7 2 1193 1217 127:49
❌​ gcp linux-2core-8gb 8 1258 1196 112:08
❌​ gcp-windows-latest-4core-16gb 7 1184 1221 133:45
18 interesting tests: 10 flaky, 8 FAIL
Test Name aws linux-2core-8gb aws-windows-latest-4core-16gb azure linux-2core-8gb azure-windows-latest-4core-16gb gcp linux-2core-8gb gcp-windows-latest-4core-16gb
❌​ TestAccept ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
🔄​ TestAccept/bundle/deploy/spark-jar-task 🔄​f ✅​p ✅​p ✅​p ✅​p ✅​p
🔄​ TestAccept/bundle/deploy/spark-jar-task/DMS= 🔄​f ✅​p ✅​p ✅​p ✅​p ✅​p
🔄​ TestAccept/bundle/invariant/no_drift ✅​p ✅​p 🔄​f ✅​p ✅​p ✅​p
🔄​ TestAccept/bundle/invariant/no_drift/DMS=/INPUT_CONFIG=genie_space.yml.tmpl/READPLAN= ✅​p ✅​p 🔄​f ✅​p ✅​p ✅​p
🔄​ TestAccept/bundle/resources/alerts/with_file ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p
🔄​ TestAccept/bundle/resources/alerts/with_file/DMS=true ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p
❌​ TestAccept/bundle/resources/genie_spaces/change-serialized-space ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/genie_spaces/change-serialized-space/DMS= ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/genie_spaces/change-serialized-space/DMS=true ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/genie_spaces/simple ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/genie_spaces/simple/DMS= ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/genie_spaces/simple/DMS=true ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
🔄​ TestAccept/bundle/resources/postgres_databases/update 🔄​f ✅​p 🙈​s 🙈​s 🙈​s 🙈​s
🔄​ TestAccept/bundle/resources/postgres_databases/update/DMS= 🔄​f ✅​p
🔄​ TestAccept/bundle/resources/postgres_endpoints/add_settings 🔄​f ✅​p 🙈​s 🙈​s 🙈​s 🙈​s
🔄​ TestAccept/bundle/resources/postgres_endpoints/add_settings/DMS=true 🔄​f ✅​p
❌​ TestAccept/ssh/bulk-transfer ❌​F 🙈​s ❌​F 🙈​s ❌​F 🙈​s
Top 50 slowest tests (at least 2 minutes):
duration env testname
18:59 azure-windows-latest-4core-16gb TestAccept/bundle/invariant/no_drift/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=
12:07 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=true
10:18 gcp linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
10:13 gcp linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
9:38 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=true
9:34 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
9:34 azure linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
9:31 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
9:28 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=
8:55 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=
8:52 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
8:51 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
8:46 aws linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=true
8:29 azure linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
8:28 aws-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
8:20 azure linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=true
8:10 azure linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=
7:50 aws-windows-latest-4core-16gb TestAccept/bundle/invariant/delete_idempotent/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=1
7:46 aws linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
7:38 gcp-windows-latest-4core-16gb TestAccept/bundle/invariant/delete_idempotent/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=
7:24 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=
7:12 gcp linux-2core-8gb TestAccept/bundle/invariant/no_drift/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=
7:01 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
7:00 azure-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
7:00 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
6:58 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
6:56 aws-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
6:54 aws linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
6:53 azure-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
6:52 azure linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
6:46 azure linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
6:37 gcp linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=true
6:33 gcp linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=
6:28 aws linux-2core-8gb TestAccept/bundle/resources/clusters/deploy/data_security_mode/DMS=
6:10 azure linux-2core-8gb TestAccept/bundle/deploy/spark-jar-task/DMS=true
6:04 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
5:54 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
5:37 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
5:33 azure-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
5:29 gcp linux-2core-8gb TestAccept/bundle/deploy/spark-jar-task/DMS=
5:03 aws linux-2core-8gb TestAccept/bundle/deploy/spark-jar-task/DMS=
4:59 azure-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
4:59 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=true
4:50 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started-omitted/DMS=true
4:49 aws-windows-latest-4core-16gb TestAccept/bundle/deploy/spark-jar-task/DMS=
4:48 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started-toggle/DMS=true
4:46 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started-toggle/DMS=
4:41 aws linux-2core-8gb TestAccept/bundle/deploy/spark-jar-task/DMS=true
4:41 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=true
4:39 azure linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=

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.

3 participants