Skip to content

[VPEX][1/8] Add local-env foundation: result types and env-key mapping#5823

Open
rugpanov wants to merge 5 commits into
mainfrom
dbconnect/01-engine
Open

[VPEX][1/8] Add local-env foundation: result types and env-key mapping#5823
rugpanov wants to merge 5 commits into
mainfrom
dbconnect/01-engine

Conversation

@rugpanov

@rugpanov rugpanov commented Jul 3, 2026

Copy link
Copy Markdown

Context

This is PR 1 of 8 in a stacked series adding the databricks local-env python sync command, which provisions a local Python environment (Python version, databricks-connect pin, and dependency constraints) matched to a selected Databricks compute target. An earlier revision carried the whole engine (~2.3k lines) in one diff — too large to review — so it has been decomposed into small, single-concern PRs:

  1. This PR — foundation: result types + env-key mapping (~270 lines)
  2. target resolution (target.go)
  3. constraint fetch + cache (constraints.go)
  4. pyproject TOML merge (merge.go)
  5. pipeline + detection + package-manager interface
  6. uv backend + CLI command (Hidden: true)
  7. acceptance tests
  8. unveil (unhide + help + changelog)

The feature is not reachable by users until the final PR, so nothing here changes CLI behavior.

What this PR contains

The foundation the rest of the stack builds on:

  • result.go — the result types and the --json / E_* error contract that every phase reports through: Result, PipelineError, ErrorCode, PhaseName, PhaseStatus, Mode, TargetInfo, ResolvedInfo, Plan, Warning. It also defines the command-path constants (local-env / python / sync) in one place.
  • envkey.go — mapping a compute target to an environment key (EnvKeyForServerless, EnvKeyForSparkVersion, NormalizeServerless) and parsing the Python minor from a requires-python specifier.

Dormant by construction

Nothing imports this package (libs/localenv) yet, so the CLI is unchanged. The unexported filesystem/artifact constants and the canonical phase-order slice live with the pipeline that consumes them (PR 5), keeping this layer to just the contract types — which is also what keeps it unused- and deadcode-clean on its own.

This pull request and its description were written by Isaac.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Waiting for approval

Could not determine reviewers from git history.
Round-robin suggestion: @renaudhartert-db

Eligible reviewers: @andrewnester, @anton-107, @denik, @janniklasrose, @pietern, @renaudhartert-db, @shreyas-goenka, @simonfaltum

Suggestions based on git history. See OWNERS for ownership rules.

@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: be61b7d

Run: 28679324759

Env 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
💚​ aws linux 4 15 230 1045 3:56
💚​ aws windows 4 15 232 1043 3:53
💚​ aws-ucws linux 4 15 314 963 5:26
💚​ aws-ucws windows 4 15 316 961 3:49
💚​ azure linux 4 15 230 1044 4:16
💚​ azure windows 4 15 232 1042 4:07
💚​ azure-ucws linux 4 15 316 960 5:01
💚​ azure-ucws windows 4 15 318 958 3:43
💚​ gcp linux 4 15 229 1046 3:46
💚​ gcp windows 4 15 231 1044 3:27
19 interesting tests: 15 SKIP, 4 RECOVERED
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
💚​ TestAccept 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/invariant/no_drift 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/permissions 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/replace_existing 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/update_protected 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/without_branch_id 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_endpoints/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_projects/update_display_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/synced_database_tables/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_indexes/recreate/embedding_dimension 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
💚​ TestFetchRepositoryInfoAPI_FromRepo 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
💚​ TestFetchRepositoryInfoAPI_FromRepo/root 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
💚​ TestFetchRepositoryInfoAPI_FromRepo/subdir 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
Top 5 slowest tests (at least 2 minutes):
duration env testname
3:14 azure windows TestAccept
2:57 aws windows TestAccept
2:49 aws-ucws windows TestAccept
2:45 gcp windows TestAccept
2:40 azure-ucws windows TestAccept

First of a stacked series adding `databricks local-env python sync`, which
provisions a local Python environment matched to a Databricks compute
target. The feature lands across small, single-concern PRs; each layer is
independently reviewable and adds no user-facing surface until the final PR
wires the command in.

This PR is the foundation the rest of the stack builds on:

- result.go: the result types and the --json / E_* error contract that
  every phase reports through (Result, PipelineError, ErrorCode, PhaseName,
  PhaseStatus, Mode, TargetInfo, ResolvedInfo, Plan, Warning), plus the
  command-path constants (local-env / python / sync) defined once.
- envkey.go: mapping a compute target to an environment key and parsing the
  Python minor from a requires-python specifier.

Nothing imports this package yet, so the CLI is unchanged. The unexported
filesystem/artifact constants and the canonical phase-order slice live with
the pipeline that consumes them (a later PR in the stack).

Co-authored-by: Isaac
@rugpanov rugpanov force-pushed the dbconnect/01-engine branch from 865a2cd to 22f99d9 Compare July 3, 2026 13:20
@rugpanov rugpanov changed the title Add dbconnect foundation: result types and env-key mapping [VPEX][1/8] Add local-env foundation: result types and env-key mapping Jul 3, 2026
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 13:20 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 13:20 — with GitHub Actions Inactive
…pecifiers

Review of the foundation layer flagged that PythonMinorFromRequires took the
first MAJOR.MINOR in the string via first-match regex. For a multi-clause
requires-python where the exclusive upper bound comes first — e.g.
"<3.13,>=3.10" — it returned 3.13, the version the "<3.13" clause forbids,
because PEP 440 clause order is arbitrary. The result feeds
PM.EnsurePython, so the tool could target a Python the constraint excludes.

Prefer a lower-bound / pinning clause (>=, >, ==, ~=, ===) and only fall
back to the first version when none is present. Adds multi-clause test
coverage; the prior tests exercised only single-bound specifiers.

Co-authored-by: Isaac
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 15:27 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 15:27 — with GitHub Actions Inactive
…dden version

Round-2 review of the foundation layer noted that when a requires-python has
no lower-bound/pin clause at all (only upper-bound or exclusion, e.g.
"<3.13,!=3.12"), PythonMinorFromRequires fell back to the first number and
returned 3.13 — a version the specifier forbids. Such a spec has no floor to
install from, so it now errors rather than guessing. A bare "3.12" (no
operator) is still accepted as a valid floor.

Co-authored-by: Isaac
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 18:15 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 18:15 — with GitHub Actions Inactive
…ower bound

Round-3 review found two edge cases in the regex-based PythonMinorFromRequires:
with multiple lower bounds (">=3.8,>=3.11") it returned the first (3.8) rather
than the effective floor (3.11), and a bare floor alongside an exclusion
("!=3.11,3.12") was wrongly rejected as having no floor.

Replaced the layered regexes with a small clause parser: split on commas,
classify each clause by operator (>=,>,==,~=,=== and bare = floor; <,<=,!=
never a floor), and return the highest floor. A spec with no floor clause
("<3.13", "!=3.12") still errors. Covers multi-lower-bound, bare-floor +
exclusion, ordering, and whitespace.

Co-authored-by: Isaac
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 18:27 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 18:27 — with GitHub Actions Inactive
Round-4 review noted PythonMinorFromRequires returned 3.10 for ">3.10", but
PEP 440's ">" excludes the entire given release series (neither 3.10 nor any
3.10.x satisfies ">3.10"), so the lowest installable minor is 3.11. The clause
parser now bumps the minor by one for a strict ">" bound.

Co-authored-by: Isaac
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 19:14 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 19:14 — with GitHub Actions Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants