This is an automated email from the ASF dual-hosted git repository.

ashb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new efb49f5e36d Stop prek hooks changing uv.lock and fail CI when it is 
stale (#74803)
efb49f5e36d is described below

commit efb49f5e36df9f580b1eaf62a6080cf8b38709be
Author: Ash Berlin-Taylor <[email protected]>
AuthorDate: Thu Oct 15 20:10:53 2026 +0100

    Stop prek hooks changing uv.lock and fail CI when it is stale (#74803)
    
    Several hooks ran uv without --frozen, so a commit could re-lock with
    whichever uv was on PATH (seen: lock format revision and environment
    markers rewritten by an unrelated commit). Set UV_FROZEN=1 through prek's
    default_env (needs prek 0.4.8); the manual upgrade hooks set UV_FROZEN=0
    because they need real resolution. default_env only applies to hooks in
    the root config, so check-provider-yaml-valid, which runs `uv sync` inside
    breeze against the bind-mounted host uv.lock, now passes --frozen itself.
    
    update-uv-lock ran `uv lock --frozen`, which exits 0 on a stale lock, and
    CI always skipped it, so the 2026-10-14 providers release merged with
    version bumps that were never re-locked. Run `uv lock --check` with
    UV_FROZEN=0 and stop skipping it in CI.
    
    The breeze shim passes --locked, which older uv rejects together with an
    inherited UV_FROZEN. Unset UV_FROZEN in the shim and bump SHIM_VERSION to 3
    so existing installs are told to re-run setup_breeze.
    
    test_get_expected_shim_version_reads_real_setup_script asserted the exact
    SHIM_VERSION, so it failed on every bump without saying what broke. It now
    only asserts that the real setup_breeze still yields an integer version,
    which is what ties the parser to the real file.
---
 .pre-commit-config.yaml                            | 20 ++++++---
 contributing-docs/07_local_virtualenv.rst          |  8 +++-
 .../src/airflow_breeze/utils/selective_checks.py   |  1 -
 dev/breeze/tests/test_selective_checks.py          | 50 +++++++++++-----------
 dev/breeze/tests/test_shim_version_check.py        |  4 +-
 .../in_container/run_provider_yaml_files_check.py  | 10 ++++-
 scripts/tools/setup_breeze                         |  5 ++-
 7 files changed, 58 insertions(+), 40 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 79b45df6646..5bb9518083d 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -17,11 +17,15 @@
 ---
 default_stages: [pre-commit, pre-push]
 default_install_hook_types: [pre-commit, commit-msg]
-minimum_prek_version: '0.3.4'
+minimum_prek_version: '0.4.8'
 default_language_version:
   python: python3
   node: 22.19.0
   golang: 1.25.0
+default_env:
+  # Unless overridden, no hook defined in this file should change the 
resolutions in uv.lock; they use
+  # the committed ones. Hooks in nested configs do not inherit this and must 
pass --frozen to uv themselves.
+  UV_FROZEN: "1"
 exclude: ^.*/.*_vendor/
 repos:
   - repo: meta
@@ -565,6 +569,7 @@ repos:
         name: Upgrade important versions (manual)
         entry: ./scripts/ci/prek/upgrade_important_versions.py
         stages: ['manual']
+        env: {UV_FROZEN: "0"}
         language: python
         files: >
           (?x)
@@ -577,6 +582,7 @@ repos:
         name: Upgrade curated dependency floors (manual)
         entry: ./scripts/ci/prek/upgrade_dependency_floors.py
         stages: ['manual']
+        env: {UV_FROZEN: "0"}
         language: python
         files: >
           (?x)
@@ -1585,13 +1591,15 @@ repos:
         files: ^dev/breeze/src/airflow_breeze/global_constants\.py$
         require_serial: true
         # This is a fast regular hook that runs when any pyproject.toml 
changes.
-        # It runs locally with `--frozen` so the lock is only verified against 
pyproject.toml,
-        # never silently rewritten during a commit. If a pyproject.toml change 
makes the lock
-        # stale, the hook fails and the contributor must run `uv lock` 
explicitly and commit
-        # the refreshed uv.lock — which keeps lock updates intentional and 
reviewable.
+        # It runs `uv lock --check`, so the lock is verified against 
pyproject.toml but never
+        # rewritten during a commit. If a pyproject.toml change makes the lock 
stale, the hook
+        # fails and the contributor must run `uv lock` explicitly and commit 
the refreshed
+        # uv.lock — which keeps lock updates intentional and reviewable. 
UV_FROZEN is disabled
+        # because under it `--check` only validates the lock, it does not 
detect staleness.
       - id: update-uv-lock
         name: Update uv.lock
-        entry: uv lock --frozen
+        entry: uv lock --check
+        env: {UV_FROZEN: "0"}
         language: system
         files: >
           (?x)
diff --git a/contributing-docs/07_local_virtualenv.rst 
b/contributing-docs/07_local_virtualenv.rst
index 7577e74b71c..fc73068ac4a 100644
--- a/contributing-docs/07_local_virtualenv.rst
+++ b/contributing-docs/07_local_virtualenv.rst
@@ -287,8 +287,12 @@ or when running tests), you can pass the ``--frozen`` flag:
 
     uv sync --frozen
 
-This will fail if the lock file is out of date with respect to 
``pyproject.toml``, rather than
-silently updating it. This is useful when you want to guarantee fully 
reproducible environments.
+This never resolves or writes to the lock file, even when it is out of date 
with respect to
+``pyproject.toml``. Use ``--locked`` (or ``uv lock --check``) to fail on a 
stale lock file instead.
+
+A change to a ``pyproject.toml`` (including a workspace member's version) must 
be committed together
+with the refreshed ``uv.lock``: run ``uv lock``. The ``update-uv-lock`` prek 
hook, which also runs in CI,
+fails otherwise. All other prek hooks run ``uv`` frozen and never change 
``uv.lock``.
 
 Cooldown via ``exclude-newer``
 ..............................
diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py 
b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
index 246107a835d..511ebc96e01 100644
--- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py
+++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
@@ -1925,7 +1925,6 @@ class SelectiveChecks:
     def skip_prek_hooks(self) -> str:
         prek_hooks_to_skip = set()
         prek_hooks_to_skip.add("identity")
-        prek_hooks_to_skip.add("update-uv-lock")
         if self._default_branch != "main":
             # Skip those tests on all "release" branches
             prek_hooks_to_skip.update(
diff --git a/dev/breeze/tests/test_selective_checks.py 
b/dev/breeze/tests/test_selective_checks.py
index 5533390a721..a4846a09756 100644
--- a/dev/breeze/tests/test_selective_checks.py
+++ b/dev/breeze/tests/test_selective_checks.py
@@ -121,10 +121,10 @@ ALL_SKIPPED_COMMITS_ON_NO_CI_IMAGE = (
     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
 )
 
-ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED = "identity,update-uv-lock"
+ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED = "identity"
 
 ALL_SKIPPED_COMMITS_IF_ONLY_UI_OPENAPI_CHANGED = (
     
"check-java-sdk-serialization-conformance,check-provider-yaml-valid,check-ts-sdk-supervisor-schema,flynt,identity,ktlint,"
@@ -135,7 +135,7 @@ ALL_SKIPPED_COMMITS_IF_ONLY_UI_OPENAPI_CHANGED = (
     
"mypy-shared-observability,mypy-shared-plugins_manager,mypy-shared-providers_discovery,"
     
"mypy-shared-secrets_backend,mypy-shared-secrets_masker,mypy-shared-serialization,"
     
"mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,"
-    
"mypy-task-sdk-integration-tests,regenerate-java-sdk-verification-metadata,update-uv-lock"
+    "mypy-task-sdk-integration-tests,regenerate-java-sdk-verification-metadata"
 )
 
 ALL_SKIPPED_COMMITS_IF_NO_UI = (
@@ -146,7 +146,7 @@ ALL_SKIPPED_COMMITS_IF_NO_UI = (
     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
 )
 ALL_SKIPPED_COMMITS_IF_NO_HELM_TESTS = (
     
"check-java-sdk-serialization-conformance,check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart,"
@@ -156,7 +156,7 @@ ALL_SKIPPED_COMMITS_IF_NO_HELM_TESTS = (
     
"mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging,"
     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
-    
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,regenerate-java-sdk-verification-metadata,update-uv-lock"
+    
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,regenerate-java-sdk-verification-metadata"
 )
 
 ALL_SKIPPED_COMMITS_IF_NO_UI_AND_HELM_TESTS = (
@@ -168,7 +168,7 @@ ALL_SKIPPED_COMMITS_IF_NO_UI_AND_HELM_TESTS = (
     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
 )
 
 # API source/test change with NO OpenAPI spec change: the full matrix is no 
longer
@@ -184,7 +184,7 @@ ALL_SKIPPED_COMMITS_IF_ONLY_API_SOURCE_CHANGED = (
     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,"
     "mypy-task-sdk,mypy-task-sdk-integration-tests,"
-    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
 )
 
 ALL_SKIPPED_COMMITS_IF_NO_PROVIDERS_AND_UI = (
@@ -196,7 +196,7 @@ ALL_SKIPPED_COMMITS_IF_NO_PROVIDERS_AND_UI = (
     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
 )
 
 ALL_SKIPPED_COMMITS_IF_NO_PROVIDERS = (
@@ -208,7 +208,7 @@ ALL_SKIPPED_COMMITS_IF_NO_PROVIDERS = (
     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
 )
 
 
@@ -221,7 +221,7 @@ ALL_SKIPPED_COMMITS_IF_NO_PROVIDERS_UI_AND_HELM_TESTS = (
     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
 )
 
 ALL_SKIPPED_COMMITS_IF_NO_CODE_PROVIDERS_AND_HELM_TESTS = (
@@ -232,7 +232,7 @@ ALL_SKIPPED_COMMITS_IF_NO_CODE_PROVIDERS_AND_HELM_TESTS = (
     
"mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging,"
     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
-    
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,regenerate-java-sdk-verification-metadata,update-uv-lock"
+    
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,regenerate-java-sdk-verification-metadata"
 )
 
 ALL_SKIPPED_COMMITS_IF_NOT_IMPORTANT_FILES_CHANGED = (
@@ -244,7 +244,7 @@ ALL_SKIPPED_COMMITS_IF_NOT_IMPORTANT_FILES_CHANGED = (
     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
 )
 
 
@@ -252,7 +252,7 @@ All_SKIPPED_COMMITS_IF_NON_MAIN_BRANCH = (
     
"check-airflow-provider-compatibility,check-airflow-providers-bug-report-template,"
     "check-extra-packages-references,check-provider-yaml-valid,"
     "compile-fab-assets,generate-openapi-spec-fab,identity,"
-    "lint-helm-chart,update-uv-lock,validate-operators-init"
+    "lint-helm-chart,validate-operators-init"
 )
 
 
@@ -489,7 +489,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                         
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
                         
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
                         
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
                     ),
                     "upgrade-to-newer-dependencies": "false",
                     "core-test-types-list-as-strings-in-json": json.dumps(
@@ -536,7 +536,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                         
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
                         
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,"
                         
"mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
                     ),
                     "upgrade-to-newer-dependencies": "false",
                     "core-test-types-list-as-strings-in-json": json.dumps(
@@ -790,7 +790,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                         
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
                         
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
                         
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk-integration-tests,"
-                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
                     ),
                     "skip-providers-tests": "false",
                     "upgrade-to-newer-dependencies": "false",
@@ -828,7 +828,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                         
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
                         
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
                         
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,"
-                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
                     ),
                     "skip-providers-tests": "true",
                     "upgrade-to-newer-dependencies": "false",
@@ -891,7 +891,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                         
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
                         
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
                         
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
                     ),
                     "skip-providers-tests": "true",
                     "upgrade-to-newer-dependencies": "false",
@@ -927,7 +927,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                         
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
                         
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
                         
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
                     ),
                     "skip-providers-tests": "true",
                     "upgrade-to-newer-dependencies": "false",
@@ -1276,7 +1276,7 @@ def assert_outputs_are_printed(expected_outputs: 
dict[str, str], stderr: str):
                     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
                     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
                     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-                    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+                    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
                 ),
                 "upgrade-to-newer-dependencies": "false",
                 "core-test-types-list-as-strings-in-json": json.dumps(
@@ -1483,7 +1483,7 @@ def assert_outputs_are_printed(expected_outputs: 
dict[str, str], stderr: str):
                     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
                     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
                     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-                    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+                    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
                 ),
                 "upgrade-to-newer-dependencies": "false",
                 "core-test-types-list-as-strings-in-json": None,
@@ -1971,7 +1971,7 @@ def assert_outputs_are_printed(expected_outputs: 
dict[str, str], stderr: str):
                         
"mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
                         
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,"
                         
"mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+                        
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
                     ),
                 },
                 id=("Shared logging change keeps only mypy-shared-logging 
among the mypy-shared-* hooks"),
@@ -2958,7 +2958,7 @@ def test_expected_output_push(
                     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
                     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
                     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-                    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+                    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
                 ),
                 "upgrade-to-newer-dependencies": "false",
                 "core-test-types-list-as-strings-in-json": json.dumps(
@@ -2999,7 +2999,7 @@ def test_expected_output_push(
                     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
                     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
                     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-                    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+                    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
                 ),
                 "run-kubernetes-tests": "true",
                 "upgrade-to-newer-dependencies": "false",
@@ -3045,7 +3045,7 @@ def test_expected_output_push(
                     
"mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager,"
                     
"mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker,"
                     
"mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,"
-                    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock"
+                    
"regenerate-java-sdk-verification-metadata,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
                 ),
                 "run-kubernetes-tests": "false",
                 "upgrade-to-newer-dependencies": "false",
diff --git a/dev/breeze/tests/test_shim_version_check.py 
b/dev/breeze/tests/test_shim_version_check.py
index 953852419e1..3364ddf951d 100644
--- a/dev/breeze/tests/test_shim_version_check.py
+++ b/dev/breeze/tests/test_shim_version_check.py
@@ -60,9 +60,7 @@ def test_parse_shim_version(version_line, expected):
 
 
 def test_get_expected_shim_version_reads_real_setup_script():
-    # The real setup_breeze in the sources is the source of truth — keep this 
test in sync
-    # with the SHIM_VERSION it declares.
-    assert get_expected_shim_version(ACTUAL_AIRFLOW_SOURCES) == 2
+    assert isinstance(get_expected_shim_version(ACTUAL_AIRFLOW_SOURCES), int)
 
 
 def test_get_expected_shim_version_from_fake_sources(tmp_path):
diff --git a/scripts/in_container/run_provider_yaml_files_check.py 
b/scripts/in_container/run_provider_yaml_files_check.py
index 2363ffbaeae..ab88b9ebd83 100755
--- a/scripts/in_container/run_provider_yaml_files_check.py
+++ b/scripts/in_container/run_provider_yaml_files_check.py
@@ -125,7 +125,15 @@ def sync_dependencies_without_dev() -> None:
     """
     console.print("[magenta]Running uv sync --no-dev to strip development 
dependencies...[/]")
     result = subprocess.run(
-        ["uv", "sync", "--no-dev", "--all-packages", "--no-python-downloads", 
"--no-managed-python"],
+        [
+            "uv",
+            "sync",
+            "--frozen",
+            "--no-dev",
+            "--all-packages",
+            "--no-python-downloads",
+            "--no-managed-python",
+        ],
         capture_output=True,
         text=True,
         cwd=AIRFLOW_ROOT_PATH,
diff --git a/scripts/tools/setup_breeze b/scripts/tools/setup_breeze
index 85eef32cd04..54e8e759b1f 100755
--- a/scripts/tools/setup_breeze
+++ b/scripts/tools/setup_breeze
@@ -41,7 +41,7 @@ SHIM_MARKER="# Apache Airflow breeze shim — managed by 
scripts/tools/setup_bre
 # into the installed shim; if the installed shim is older it warns the user to
 # re-run this script. See warn_if_shim_outdated() in
 # dev/breeze/src/airflow_breeze/utils/path_utils.py.
-SHIM_VERSION="2"
+SHIM_VERSION="3"
 
 # The shim itself. Runs breeze via 'uv run' against the dev/breeze folder of 
the
 # *current* git worktree, so multiple checkouts / agentic worktrees never
@@ -84,7 +84,8 @@ else
     echo "breeze: not inside an Airflow worktree, AIRFLOW_REPO_ROOT is unset 
or not an Airflow worktree, and the install-time fallback 
'\${fallback_root}/dev/breeze' is missing — re-run scripts/tools/setup_breeze" 
>&2
     exit 1
 fi
-exec env AIRFLOW_ROOT_PATH="\${breeze_root}" SKIP_BREEZE_SELF_UPGRADE_CHECK=1 
\\
+# '--locked' already guarantees no rewrite; an inherited UV_FROZEN conflicts 
with it on older uv.
+exec env -u UV_FROZEN AIRFLOW_ROOT_PATH="\${breeze_root}" 
SKIP_BREEZE_SELF_UPGRADE_CHECK=1 \\
     uv run --project "\${breeze_root}/dev/breeze" --locked --quiet breeze "\$@"
 BREEZE_SHIM
 

Reply via email to