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

potiuk 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 490b5e816b8 Consistent way of checking Airflow version in providers 
(#44686)
490b5e816b8 is described below

commit 490b5e816b804f338b0eb97f240ae874d4e15810
Author: Jarek Potiuk <[email protected]>
AuthorDate: Tue Dec 10 08:35:51 2024 +0100

    Consistent way of checking Airflow version in providers (#44686)
    
    This PR introduces consistent way of checking version of Airflow
    by Airflow providers. So far there were about 6 different ways on
    how Providers checked for Airflow version - this PR aims to unify
    this approach for now and in the future - at least until minimum
    version of Airflow set to 2.11 where we are likely to introduce
    a simpler check via #44607. Until then all providers are going
    to have `version_references.py` module copied in their sources
    that they will be importing the constants from.
    
    This PR also adds pre-commit that checks if the
    ``version_compat.py`` module is imported from local package copy
    or maybe from another provider or test code - both causing
    unneeded dependencies from the provider - to another package or
    to test code respectively.
---
 .pre-commit-config.yaml                            |   7 +
 contributing-docs/08_static_code_checks.rst        |   2 +
 dev/breeze/doc/images/output_static-checks.svg     | 148 +++++++++++----------
 dev/breeze/doc/images/output_static-checks.txt     |   2 +-
 dev/breeze/src/airflow_breeze/pre_commit_ids.py    |   1 +
 .../providers/MANAGING_PROVIDERS_LIFECYCLE.rst     |  25 ++++
 .../amazon/aws/auth_manager/aws_auth_manager.py    |   8 +-
 .../providers/amazon/aws/hooks/redshift_sql.py     |   8 +-
 .../providers/amazon/aws/transfers/gcs_to_s3.py    |   4 +-
 .../airflow/providers/amazon/aws/utils/__init__.py |  16 +--
 .../airflow/providers/amazon}/version_compat.py    |   7 +-
 .../cncf/kubernetes/cli/kubernetes_command.py      |   6 +-
 .../providers/cncf/kubernetes}/version_compat.py   |   7 +-
 .../providers/common/compat/assets/__init__.py     |   7 +-
 .../providers/common/compat/lineage/hook.py        |   2 +-
 .../providers/common/compat/standard/operators.py  |   8 +-
 .../providers/common/compat}/version_compat.py     |   7 +-
 .../providers/common/compat/version_references.py  |  27 ----
 .../src/airflow/providers/common/io/assets/file.py |   6 +-
 .../airflow/providers/common/io}/version_compat.py |   7 +-
 .../airflow/providers/common/io/xcom/backend.py    |   7 +-
 .../src/airflow/providers/edge/cli/edge_command.py |   4 +-
 .../providers/edge/plugins/edge_executor_plugin.py |   6 +-
 .../src/airflow/providers/edge}/version_compat.py  |   7 +-
 .../providers/edge/worker_api/routes/_v2_compat.py |   7 +-
 .../providers/elasticsearch/log/es_task_handler.py |   6 +-
 .../providers/elasticsearch}/version_compat.py     |   7 +-
 .../src/airflow/providers/google/assets/gcs.py     |   8 +-
 .../google/cloud/log/stackdriver_task_handler.py   |   6 +-
 .../airflow/providers/google}/version_compat.py    |   7 +-
 .../providers/openlineage/extractors/base.py       |   4 +-
 .../providers/openlineage/plugins/listener.py      |  10 +-
 .../providers/openlineage/plugins/openlineage.py   |   4 +-
 .../airflow/providers/openlineage/utils/utils.py   |  23 +---
 .../providers/openlineage}/version_compat.py       |   7 +-
 .../providers/opensearch/log/os_task_handler.py    |   6 +-
 .../providers/opensearch}/version_compat.py        |   7 +-
 .../src/airflow/providers/presto/hooks/presto.py   |   6 +-
 .../airflow/providers/presto}/version_compat.py    |   7 +-
 .../airflow/providers/standard/operators/python.py |   5 +-
 .../src/airflow/providers/standard/provider.yaml   |   1 -
 .../providers/standard/sensors/date_time.py        |   2 +-
 .../src/airflow/providers/standard/sensors/time.py |   2 +-
 .../providers/standard/sensors/time_delta.py       |   2 +-
 .../providers/standard/triggers/external_task.py   |   2 +-
 .../providers/standard/triggers/temporal.py        |   2 +-
 .../providers/standard/utils/version_references.py |  26 ----
 .../airflow/providers/standard}/version_compat.py  |   7 +-
 .../src/airflow/providers/trino/hooks/trino.py     |   6 +-
 .../src/airflow/providers/trino}/version_compat.py |   7 +-
 .../amazon/aws/operators/test_redshift_sql.py      |   4 +-
 .../tests/openlineage/extractors/test_base.py      |   2 +-
 providers/tests/standard/triggers/test_temporal.py |   3 +-
 .../ci/pre_commit/check_imports_in_providers.py    |  96 +++++++++++++
 scripts/ci/pre_commit/common_precommit_utils.py    |  21 +++
 tests_common/test_utils/version_compat.py          |   7 +-
 56 files changed, 360 insertions(+), 279 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 49e74d453d0..65e3a0895b2 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -174,6 +174,13 @@ repos:
         language: python
         additional_dependencies: ['rich>=12.4.4']
         require_serial: true
+      - id: check-imports-in-providers
+        name: Check imports in providers
+        entry: ./scripts/ci/pre_commit/check_imports_in_providers.py
+        language: python
+        additional_dependencies: ['rich>=12.4.4', "ruff==0.8.1"]
+        files: ^providers/src/airflow/providers/.*\.py$
+        require_serial: true
       - id: update-common-sql-api-stubs
         name: Check and update common.sql API stubs
         entry: ./scripts/ci/pre_commit/update_common_sql_api_stubs.py
diff --git a/contributing-docs/08_static_code_checks.rst 
b/contributing-docs/08_static_code_checks.rst
index 01d8f9d303e..0775c83ef06 100644
--- a/contributing-docs/08_static_code_checks.rst
+++ b/contributing-docs/08_static_code_checks.rst
@@ -182,6 +182,8 @@ require Breeze Docker image to be built locally.
 
+-----------------------------------------------------------+--------------------------------------------------------+---------+
 | check-hooks-apply                                         | Check if all 
hooks apply to the repository             |         |
 
+-----------------------------------------------------------+--------------------------------------------------------+---------+
+| check-imports-in-providers                                | Check imports in 
providers                             |         |
++-----------------------------------------------------------+--------------------------------------------------------+---------+
 | check-incorrect-use-of-LoggingMixin                       | Make sure 
LoggingMixin is not used alone               |         |
 
+-----------------------------------------------------------+--------------------------------------------------------+---------+
 | check-init-decorator-arguments                            | Sync model 
__init__ and decorator arguments            |         |
diff --git a/dev/breeze/doc/images/output_static-checks.svg 
b/dev/breeze/doc/images/output_static-checks.svg
index 4a51fad1626..8d78c5924b4 100644
--- a/dev/breeze/doc/images/output_static-checks.svg
+++ b/dev/breeze/doc/images/output_static-checks.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 2246.0" 
xmlns="http://www.w3.org/2000/svg";>
+<svg class="rich-terminal" viewBox="0 0 1482 2270.4" 
xmlns="http://www.w3.org/2000/svg";>
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -43,7 +43,7 @@
 
     <defs>
     <clipPath id="breeze-static-checks-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="2195.0" />
+      <rect x="0" y="0" width="1463.0" height="2219.4" />
     </clipPath>
     <clipPath id="breeze-static-checks-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -312,9 +312,12 @@
 <clipPath id="breeze-static-checks-line-88">
     <rect x="0" y="2148.7" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="breeze-static-checks-line-89">
+    <rect x="0" y="2173.1" width="1464" height="24.65"/>
+            </clipPath>
     </defs>
 
-    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="2244" rx="8"/><text 
class="breeze-static-checks-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Command:&#160;static-checks</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="2268.4" rx="8"/><text 
class="breeze-static-checks-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Command:&#160;static-checks</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -345,75 +348,76 @@
 </text><text class="breeze-static-checks-r5" x="0" y="459.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-18)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="459.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-18)">check-executables-have-shebangs&#160;|&#160;check-extra-packages-references&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="459.2" te [...]
 </text><text class="breeze-static-checks-r5" x="0" y="483.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-19)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="483.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-19)">check-extras-order&#160;|&#160;check-fab-migrations&#160;|&#160;check-for-inclusive-language&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="483.6" textLength="12.2" 
clip-path [...]
 </text><text class="breeze-static-checks-r5" x="0" y="508" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-20)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="508" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-20)">check-get-lineage-collector-providers&#160;|&#160;check-google-re2-as-dependency&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="508" textLength="12.2" 
clip-path="url( [...]
-</text><text class="breeze-static-checks-r5" x="0" y="532.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-21)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="532.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-21)">check-hatch-build-order&#160;|&#160;check-hooks-apply&#160;|&#160;check-incorrect-use-of-LoggingMixin</text><text
 class="breeze-static-checks-r5" x="1451.8" y="532.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-21)">│< [...]
-</text><text class="breeze-static-checks-r5" x="0" y="556.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-22)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="556.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-22)">|&#160;check-init-decorator-arguments&#160;|&#160;check-integrations-list-consistent&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="556.8" textLength="12.2" [...]
-</text><text class="breeze-static-checks-r5" x="0" y="581.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-23)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="581.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-23)">check-lazy-logging&#160;|&#160;check-links-to-example-dags-do-not-use-hardcoded-versions&#160;|&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="581.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-23)">│< [...]
-</text><text class="breeze-static-checks-r5" x="0" y="605.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-24)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="605.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-24)">check-merge-conflict&#160;|&#160;check-min-python-version&#160;|&#160;check-newsfragments-are-valid&#160;|</text><text
 class="breeze-static-checks-r5" x="1451.8" y="605.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-24 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="630" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-25)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="630" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-25)">check-no-airflow-deprecation-in-providers&#160;|&#160;check-no-providers-in-core-examples&#160;|</text><text
 class="breeze-static-checks-r5" x="1451.8" y="630" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-25)">│</text><text [...]
-</text><text class="breeze-static-checks-r5" x="0" y="654.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-26)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="654.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-26)">check-only-new-session-with-provide-session&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="678.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-27)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="678.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-27)">check-persist-credentials-disabled-in-github-workflows&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="bre [...]
-</text><text class="breeze-static-checks-r5" x="0" y="703.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-28)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="703.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-28)">check-pre-commit-information-consistent&#160;|&#160;check-provide-create-sessions-imports&#160;|</text><text
 class="breeze-static-checks-r5" x="1451.8" y="703.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-28)">│</text [...]
-</text><text class="breeze-static-checks-r5" x="0" y="727.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-29)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="727.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-29)">check-provider-docs-valid&#160;|&#160;check-provider-yaml-valid&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="752" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-30)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="752" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-30)">check-providers-subpackages-init-file-exist&#160;|&#160;check-pydevd-left-in-code&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="752" textLength="12.2" 
clip-path="url(#bree [...]
-</text><text class="breeze-static-checks-r5" x="0" y="776.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-31)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="776.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-31)">check-revision-heads-map&#160;|&#160;check-safe-filter-usage-in-html&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static [...]
-</text><text class="breeze-static-checks-r5" x="0" y="800.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-32)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="800.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-32)">check-sql-dependency-common-data-structure&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="825.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-33)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="825.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-33)">check-start-date-not-used-in-defaults&#160;|&#160;check-system-tests-present&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="825.2" textLen [...]
-</text><text class="breeze-static-checks-r5" x="0" y="849.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-34)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="849.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-34)">check-system-tests-tocs&#160;|&#160;check-taskinstance-tis-attrs&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
  [...]
-</text><text class="breeze-static-checks-r5" x="0" y="874" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-35)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="874" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-35)">check-template-context-variable-in-sync&#160;|&#160;check-template-fields-valid&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="874" textLength="12.2" 
clip-path= [...]
-</text><text class="breeze-static-checks-r5" x="0" y="898.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-36)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="898.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-36)">check-tests-in-the-right-folders&#160;|&#160;check-tests-unittest-testcase&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="898. [...]
-</text><text class="breeze-static-checks-r5" x="0" y="922.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-37)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="922.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-37)">check-urlparse-usage-in-code&#160;|&#160;check-usage-of-re2-over-re&#160;|&#160;check-xml&#160;|&#160;codespell</text><text
 class="breeze-static-checks-r5" x="1451.8" y="922.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-li [...]
-</text><text class="breeze-static-checks-r5" x="0" y="947.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-38)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="947.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-38)">|&#160;compile-ui-assets&#160;|&#160;compile-ui-assets-dev&#160;|&#160;compile-www-assets&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x=" [...]
-</text><text class="breeze-static-checks-r5" x="0" y="971.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-39)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="971.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-39)">compile-www-assets-dev&#160;|&#160;create-missing-init-py-files-tests&#160;|&#160;debug-statements&#160;|&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="971.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-li [...]
-</text><text class="breeze-static-checks-r5" x="0" y="996" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-40)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="996" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-40)">detect-private-key&#160;|&#160;doctoc&#160;|&#160;end-of-file-fixer&#160;|&#160;fix-encoding-pragma&#160;|&#160;flynt&#160;|&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="996" textLength="12.2" 
clip-path="url(#bree [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1020.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-41)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1020.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-41)">generate-airflow-diagrams&#160;|&#160;generate-openapi-spec&#160;|&#160;generate-pypi-readme&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1020.4" textLength="12.2" clip-p 
[...]
-</text><text class="breeze-static-checks-r5" x="0" y="1044.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-42)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1044.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-42)">identity&#160;|&#160;insert-license&#160;|&#160;kubeconform&#160;|&#160;lint-chart-schema&#160;|&#160;lint-css&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="10 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1069.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-43)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1069.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-43)">lint-dockerfile&#160;|&#160;lint-helm-chart&#160;|&#160;lint-json-schema&#160;|&#160;lint-markdown&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="10 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1093.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-44)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1093.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-44)">lint-openapi&#160;|&#160;mixed-line-ending&#160;|&#160;mypy-airflow&#160;|&#160;mypy-dev&#160;|&#160;mypy-docs&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="10 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1118" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-45)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1118" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-45)">mypy-providers&#160;|&#160;mypy-task-sdk&#160;|&#160;pretty-format-json&#160;|&#160;pylint&#160;|&#160;python-no-log-warn</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1118" textLength="12.2" 
clip-path="url(#breeze-static-ch [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1142.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-46)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1142.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-46)">|&#160;replace-bad-characters&#160;|&#160;rst-backticks&#160;|&#160;ruff&#160;|&#160;ruff-format&#160;|&#160;shellcheck&#160;|&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1142.4" textLengt [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1166.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-47)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1166.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-47)">trailing-whitespace&#160;|&#160;ts-compile-format-lint-ui&#160;|&#160;ts-compile-format-lint-www&#160;|&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1166.8" textLength="12.2" 
clip-path="url(#breeze-sta [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1191.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-48)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1191.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-48)">update-black-version&#160;|&#160;update-breeze-cmd-output&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1215.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-49)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1215.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-49)">update-breeze-readme-config-hash&#160;|&#160;update-build-dependencies&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks- [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1240" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-50)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1240" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-50)">update-chart-dependencies&#160;|&#160;update-common-sql-api-stubs&#160;|&#160;update-er-diagram&#160;|&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1240" textLength="12.2" 
clip-path="url(#breeze-stat [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1264.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-51)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1264.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-51)">update-extras&#160;|&#160;update-in-the-wild-to-be-sorted&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1288.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-52)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1288.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-52)">update-inlined-dockerfile-scripts&#160;|&#160;update-installed-providers-to-be-sorted&#160;|&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1288.8" textLength="12.2" 
clip-path="url(#breeze-static-c [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1313.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-53)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1313.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-53)">update-installers&#160;|&#160;update-local-yml-file&#160;|&#160;update-migration-references&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1313.2" textLength="12.2" c [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1337.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-54)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1337.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-54)">update-openapi-spec-tags-to-be-sorted&#160;|&#160;update-providers-dependencies&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1337.6" textLength="12.2" c [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1362" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-55)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1362" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-55)">update-providers-init-py&#160;|&#160;update-reproducible-source-date-epoch&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1362"  [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1386.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-56)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1386.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-56)">update-spelling-wordlist-to-be-sorted&#160;|&#160;update-supported-versions&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1386.4" [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1410.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-57)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1410.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-57)">update-vendored-in-k8s-json-schema&#160;|&#160;update-version&#160;|&#160;validate-operators-init&#160;|&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1410.8" textLength="12.2" 
clip-path="url(#breeze-static-c [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1435.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-58)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1435.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-58)">yamllint)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1459.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-59)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1459.6" textLength="268.4" 
clip-path="url(#breeze-static-checks-line-59)">--show-diff-on-failure</text><text
 class="breeze-static-checks-r6" x="402.6" y="1459.6" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-59)">-s</text><text 
class="breeze-static-checks-r1" x="451.4" y="1459.6" textLength=" [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1484" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-60)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1484" textLength="292.8" 
clip-path="url(#breeze-static-checks-line-60)">--initialize-environment</text><text
 class="breeze-static-checks-r1" x="451.4" y="1484" textLength="549" 
clip-path="url(#breeze-static-checks-line-60)">Initialize&#160;environment&#160;before&#160;running&#160;checks.</text><text
 class=" [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1508.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-61)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1508.4" textLength="353.8" 
clip-path="url(#breeze-static-checks-line-61)">--max-initialization-attempts</text><text
 class="breeze-static-checks-r1" x="451.4" y="1508.4" textLength="854" 
clip-path="url(#breeze-static-checks-line-61)">Maximum&#160;number&#160;of&#160;attempts&#160;to&#160;initialize&#160;env
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1532.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-62)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1532.8" textLength="854" 
clip-path="url(#breeze-static-checks-line-62)">(INTEGER&#160;RANGE)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1557.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-63)">│</text><text 
class="breeze-static-checks-r5" x="451.4" y="1557.2" textLength="854" 
clip-path="url(#breeze-static-checks-line-63)">[default:&#160;3;&#160;1&lt;=x&lt;=10]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1581.6" 
textLength="1464" 
clip-path="url(#breeze-static-checks-line-64)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="1581.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-64)">
-</text><text class="breeze-static-checks-r5" x="0" y="1606" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-65)">╭─</text><text 
class="breeze-static-checks-r5" x="24.4" y="1606" textLength="463.6" 
clip-path="url(#breeze-static-checks-line-65)">&#160;Selecting&#160;files&#160;to&#160;run&#160;the&#160;checks&#160;on&#160;</text><text
 class="breeze-static-checks-r5" x="488" y="1606" textLength="951.6" 
clip-path="url(#breeze-static-checks-line-65)">────────────────────────────── 
[...]
-</text><text class="breeze-static-checks-r5" x="0" y="1630.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-66)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1630.4" textLength="73.2" 
clip-path="url(#breeze-static-checks-line-66)">--file</text><text 
class="breeze-static-checks-r6" x="256.2" y="1630.4" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-66)">-f</text><text 
class="breeze-static-checks-r1" x="305" y="1630.4" textLength="427" 
clip-path="url [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1654.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-67)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1654.8" textLength="134.2" 
clip-path="url(#breeze-static-checks-line-67)">--all-files</text><text 
class="breeze-static-checks-r6" x="256.2" y="1654.8" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-67)">-a</text><text 
class="breeze-static-checks-r1" x="305" y="1654.8" textLength="292.8" clip-p 
[...]
-</text><text class="breeze-static-checks-r5" x="0" y="1679.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-68)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1679.2" textLength="146.4" 
clip-path="url(#breeze-static-checks-line-68)">--commit-ref</text><text 
class="breeze-static-checks-r6" x="256.2" y="1679.2" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-68)">-r</text><text 
class="breeze-static-checks-r1" x="305" y="1679.2" textLength="1134.6" clip 
[...]
-</text><text class="breeze-static-checks-r5" x="0" y="1703.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-69)">│</text><text 
class="breeze-static-checks-r1" x="305" y="1703.6" textLength="183" 
clip-path="url(#breeze-static-checks-line-69)">exclusive&#160;with&#160;</text><text
 class="breeze-static-checks-r4" x="488" y="1703.6" textLength="158.6" 
clip-path="url(#breeze-static-checks-line-69)">--last-commit</text><text 
class="breeze-static-checks-r1" x="646.6" y="1703.6" te [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1728" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-70)">│</text><text 
class="breeze-static-checks-r7" x="305" y="1728" textLength="1134.6" 
clip-path="url(#breeze-static-checks-line-70)">(TEXT)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1752.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-71)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1752.4" textLength="158.6" 
clip-path="url(#breeze-static-checks-line-71)">--last-commit</text><text 
class="breeze-static-checks-r6" x="256.2" y="1752.4" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-71)">-c</text><text 
class="breeze-static-checks-r1" x="305" y="1752.4" textLength="793" clip-p [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1776.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-72)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1776.8" textLength="207.4" 
clip-path="url(#breeze-static-checks-line-72)">--only-my-changes</text><text 
class="breeze-static-checks-r6" x="256.2" y="1776.8" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-72)">-m</text><text 
class="breeze-static-checks-r1" x="305" y="1776.8" textLength="1134.6" [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1801.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-73)">│</text><text 
class="breeze-static-checks-r1" x="305" y="1801.2" textLength="1134.6" 
clip-path="url(#breeze-static-checks-line-73)">branch&#160;and&#160;HEAD&#160;of&#160;your&#160;branch.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1825.6" 
textLength="1464" 
clip-path="url(#breeze-static-checks-line-74)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="1825.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-74)">
-</text><text class="breeze-static-checks-r5" x="0" y="1850" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-75)">╭─</text><text 
class="breeze-static-checks-r5" x="24.4" y="1850" textLength="463.6" 
clip-path="url(#breeze-static-checks-line-75)">&#160;Building&#160;image&#160;before&#160;running&#160;checks&#160;</text><text
 class="breeze-static-checks-r5" x="488" y="1850" textLength="951.6" 
clip-path="url(#breeze-static-checks-line-75)">────────────────────────────────────────
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1874.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-76)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1874.4" textLength="317.2" 
clip-path="url(#breeze-static-checks-line-76)">--skip-image-upgrade-check</text><text
 class="breeze-static-checks-r1" x="414.8" y="1874.4" textLength="536.8" 
clip-path="url(#breeze-static-checks-line-76)">Skip&#160;checking&#160;if&#160;the&#160;CI&#160;image&#160;is&#160;up&#160
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1898.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-77)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1898.8" textLength="158.6" 
clip-path="url(#breeze-static-checks-line-77)">--force-build</text><text 
class="breeze-static-checks-r1" x="414.8" y="1898.8" textLength="707.6" 
clip-path="url(#breeze-static-checks-line-77)">Force&#160;image&#160;build&#160;no&#160;matter&#160;if&#160;it&#160;is&#160;determined&
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1923.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-78)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1923.2" textLength="134.2" 
clip-path="url(#breeze-static-checks-line-78)">--image-tag</text><text 
class="breeze-static-checks-r1" x="414.8" y="1923.2" textLength="695.4" 
clip-path="url(#breeze-static-checks-line-78)">Tag&#160;of&#160;the&#160;image&#160;which&#160;is&#160;used&#160;to&#160;run&#160;the&#16
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1947.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-79)">│</text><text 
class="breeze-static-checks-r7" x="414.8" y="1947.6" textLength="963.8" 
clip-path="url(#breeze-static-checks-line-79)">(TEXT)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1972" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-80)">│</text><text 
class="breeze-static-checks-r5" x="414.8" y="1972" textLength="963.8" 
clip-path="url(#breeze-static-checks-line-80)">[default:&#160;latest]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1996.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-81)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1996.4" textLength="231.8" 
clip-path="url(#breeze-static-checks-line-81)">--github-repository</text><text 
class="breeze-static-checks-r6" x="366" y="1996.4" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-81)">-g</text><text 
class="breeze-static-checks-r1" x="414.8" y="1996.4" textLength="585.6 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="2020.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-82)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="2020.8" textLength="109.8" 
clip-path="url(#breeze-static-checks-line-82)">--builder</text><text 
class="breeze-static-checks-r1" x="414.8" y="2020.8" textLength="756.4" 
clip-path="url(#breeze-static-checks-line-82)">Buildx&#160;builder&#160;used&#160;to&#160;perform&#160;`docker&#160;buildx&#160;build`&#160
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="2045.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-83)">│</text><text 
class="breeze-static-checks-r5" x="414.8" y="2045.2" textLength="756.4" 
clip-path="url(#breeze-static-checks-line-83)">[default:&#160;autodetect]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="2069.6" 
textLength="1464" 
clip-path="url(#breeze-static-checks-line-84)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="2069.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-84)">
-</text><text class="breeze-static-checks-r5" x="0" y="2094" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-85)">╭─</text><text 
class="breeze-static-checks-r5" x="24.4" y="2094" textLength="195.2" 
clip-path="url(#breeze-static-checks-line-85)">&#160;Common&#160;options&#160;</text><text
 class="breeze-static-checks-r5" x="219.6" y="2094" textLength="1220" 
clip-path="url(#breeze-static-checks-line-85)">────────────────────────────────────────────────────────────────────────────
 [...]
-</text><text class="breeze-static-checks-r5" x="0" y="2118.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-86)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="2118.4" textLength="109.8" 
clip-path="url(#breeze-static-checks-line-86)">--dry-run</text><text 
class="breeze-static-checks-r6" x="158.6" y="2118.4" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-86)">-D</text><text 
class="breeze-static-checks-r1" x="207.4" y="2118.4" textLength="719.8" clip-p 
[...]
-</text><text class="breeze-static-checks-r5" x="0" y="2142.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-87)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="2142.8" textLength="109.8" 
clip-path="url(#breeze-static-checks-line-87)">--verbose</text><text 
class="breeze-static-checks-r6" x="158.6" y="2142.8" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-87)">-v</text><text 
class="breeze-static-checks-r1" x="207.4" y="2142.8" textLength="585.6" clip-p 
[...]
-</text><text class="breeze-static-checks-r5" x="0" y="2167.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-88)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="2167.2" textLength="73.2" 
clip-path="url(#breeze-static-checks-line-88)">--help</text><text 
class="breeze-static-checks-r6" x="158.6" y="2167.2" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-88)">-h</text><text 
class="breeze-static-checks-r1" x="207.4" y="2167.2" textLength="329.4" 
clip-path= [...]
-</text><text class="breeze-static-checks-r5" x="0" y="2191.6" 
textLength="1464" 
clip-path="url(#breeze-static-checks-line-89)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="2191.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-89)">
+</text><text class="breeze-static-checks-r5" x="0" y="532.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-21)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="532.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-21)">check-hatch-build-order&#160;|&#160;check-hooks-apply&#160;|&#160;check-imports-in-providers&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="532.4" textLength="12.2" 
clip-path [...]
+</text><text class="breeze-static-checks-r5" x="0" y="556.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-22)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="556.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-22)">check-incorrect-use-of-LoggingMixin&#160;|&#160;check-init-decorator-arguments&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="556.8" textLength="12.2" [...]
+</text><text class="breeze-static-checks-r5" x="0" y="581.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-23)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="581.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-23)">check-integrations-list-consistent&#160;|&#160;check-lazy-logging&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class [...]
+</text><text class="breeze-static-checks-r5" x="0" y="605.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-24)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="605.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-24)">check-links-to-example-dags-do-not-use-hardcoded-versions&#160;|&#160;check-merge-conflict&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="605.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-24)">│</text [...]
+</text><text class="breeze-static-checks-r5" x="0" y="630" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-25)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="630" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-25)">|&#160;check-min-python-version&#160;|&#160;check-newsfragments-are-valid&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-stati [...]
+</text><text class="breeze-static-checks-r5" x="0" y="654.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-26)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="654.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-26)">check-no-airflow-deprecation-in-providers&#160;|&#160;check-no-providers-in-core-examples&#160;|</text><text
 class="breeze-static-checks-r5" x="1451.8" y="654.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-26)">│</text [...]
+</text><text class="breeze-static-checks-r5" x="0" y="678.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-27)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="678.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-27)">check-only-new-session-with-provide-session&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="703.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-28)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="703.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-28)">check-persist-credentials-disabled-in-github-workflows&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="bre [...]
+</text><text class="breeze-static-checks-r5" x="0" y="727.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-29)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="727.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-29)">check-pre-commit-information-consistent&#160;|&#160;check-provide-create-sessions-imports&#160;|</text><text
 class="breeze-static-checks-r5" x="1451.8" y="727.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-29)">│</text [...]
+</text><text class="breeze-static-checks-r5" x="0" y="752" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-30)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="752" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-30)">check-provider-docs-valid&#160;|&#160;check-provider-yaml-valid&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="776.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-31)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="776.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-31)">check-providers-subpackages-init-file-exist&#160;|&#160;check-pydevd-left-in-code&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="776.4" textLength="12.2" 
clip-path="url [...]
+</text><text class="breeze-static-checks-r5" x="0" y="800.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-32)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="800.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-32)">check-revision-heads-map&#160;|&#160;check-safe-filter-usage-in-html&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static [...]
+</text><text class="breeze-static-checks-r5" x="0" y="825.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-33)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="825.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-33)">check-sql-dependency-common-data-structure&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="849.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-34)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="849.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-34)">check-start-date-not-used-in-defaults&#160;|&#160;check-system-tests-present&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="849.6" textLen [...]
+</text><text class="breeze-static-checks-r5" x="0" y="874" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-35)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="874" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-35)">check-system-tests-tocs&#160;|&#160;check-taskinstance-tis-attrs&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 clas [...]
+</text><text class="breeze-static-checks-r5" x="0" y="898.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-36)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="898.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-36)">check-template-context-variable-in-sync&#160;|&#160;check-template-fields-valid&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="898.4" textLength="12.2" clip 
[...]
+</text><text class="breeze-static-checks-r5" x="0" y="922.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-37)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="922.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-37)">check-tests-in-the-right-folders&#160;|&#160;check-tests-unittest-testcase&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="922. [...]
+</text><text class="breeze-static-checks-r5" x="0" y="947.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-38)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="947.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-38)">check-urlparse-usage-in-code&#160;|&#160;check-usage-of-re2-over-re&#160;|&#160;check-xml&#160;|&#160;codespell</text><text
 class="breeze-static-checks-r5" x="1451.8" y="947.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-li [...]
+</text><text class="breeze-static-checks-r5" x="0" y="971.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-39)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="971.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-39)">|&#160;compile-ui-assets&#160;|&#160;compile-ui-assets-dev&#160;|&#160;compile-www-assets&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x=" [...]
+</text><text class="breeze-static-checks-r5" x="0" y="996" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-40)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="996" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-40)">compile-www-assets-dev&#160;|&#160;create-missing-init-py-files-tests&#160;|&#160;debug-statements&#160;|&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="996" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-40) [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1020.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-41)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1020.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-41)">detect-private-key&#160;|&#160;doctoc&#160;|&#160;end-of-file-fixer&#160;|&#160;fix-encoding-pragma&#160;|&#160;flynt&#160;|&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1020.4" textLength="12.2" 
clip-path=" [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1044.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-42)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1044.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-42)">generate-airflow-diagrams&#160;|&#160;generate-openapi-spec&#160;|&#160;generate-pypi-readme&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1044.8" textLength="12.2" clip-p 
[...]
+</text><text class="breeze-static-checks-r5" x="0" y="1069.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-43)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1069.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-43)">identity&#160;|&#160;insert-license&#160;|&#160;kubeconform&#160;|&#160;lint-chart-schema&#160;|&#160;lint-css&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="10 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1093.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-44)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1093.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-44)">lint-dockerfile&#160;|&#160;lint-helm-chart&#160;|&#160;lint-json-schema&#160;|&#160;lint-markdown&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="10 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1118" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-45)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1118" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-45)">lint-openapi&#160;|&#160;mixed-line-ending&#160;|&#160;mypy-airflow&#160;|&#160;mypy-dev&#160;|&#160;mypy-docs&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1118"  [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1142.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-46)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1142.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-46)">mypy-providers&#160;|&#160;mypy-task-sdk&#160;|&#160;pretty-format-json&#160;|&#160;pylint&#160;|&#160;python-no-log-warn</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1142.4" textLength="12.2" 
clip-path="url(#breeze-sta [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1166.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-47)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1166.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-47)">|&#160;replace-bad-characters&#160;|&#160;rst-backticks&#160;|&#160;ruff&#160;|&#160;ruff-format&#160;|&#160;shellcheck&#160;|&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1166.8" textLengt [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1191.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-48)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1191.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-48)">trailing-whitespace&#160;|&#160;ts-compile-format-lint-ui&#160;|&#160;ts-compile-format-lint-www&#160;|&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1191.2" textLength="12.2" 
clip-path="url(#breeze-sta [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1215.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-49)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1215.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-49)">update-black-version&#160;|&#160;update-breeze-cmd-output&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1240" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-50)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1240" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-50)">update-breeze-readme-config-hash&#160;|&#160;update-build-dependencies&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5"  [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1264.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-51)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1264.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-51)">update-chart-dependencies&#160;|&#160;update-common-sql-api-stubs&#160;|&#160;update-er-diagram&#160;|&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1264.4" textLength="12.2" 
clip-path="url(#breez [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1288.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-52)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1288.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-52)">update-extras&#160;|&#160;update-in-the-wild-to-be-sorted&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1313.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-53)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1313.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-53)">update-inlined-dockerfile-scripts&#160;|&#160;update-installed-providers-to-be-sorted&#160;|&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1313.2" textLength="12.2" 
clip-path="url(#breeze-static-c [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1337.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-54)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1337.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-54)">update-installers&#160;|&#160;update-local-yml-file&#160;|&#160;update-migration-references&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1337.6" textLength="12.2" c [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1362" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-55)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1362" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-55)">update-openapi-spec-tags-to-be-sorted&#160;|&#160;update-providers-dependencies&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1362" textLength="12.2" clip-pa 
[...]
+</text><text class="breeze-static-checks-r5" x="0" y="1386.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-56)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1386.4" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-56)">update-providers-init-py&#160;|&#160;update-reproducible-source-date-epoch&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="13 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1410.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-57)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1410.8" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-57)">update-spelling-wordlist-to-be-sorted&#160;|&#160;update-supported-versions&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1410.8" [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1435.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-58)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1435.2" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-58)">update-vendored-in-k8s-json-schema&#160;|&#160;update-version&#160;|&#160;validate-operators-init&#160;|&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1435.2" textLength="12.2" 
clip-path="url(#breeze-static-c [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1459.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-59)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1459.6" textLength="988.2" 
clip-path="url(#breeze-static-checks-line-59)">yamllint)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1484" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-60)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1484" textLength="268.4" 
clip-path="url(#breeze-static-checks-line-60)">--show-diff-on-failure</text><text
 class="breeze-static-checks-r6" x="402.6" y="1484" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-60)">-s</text><text 
class="breeze-static-checks-r1" x="451.4" y="1484" textLength="524.6" c [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1508.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-61)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1508.4" textLength="292.8" 
clip-path="url(#breeze-static-checks-line-61)">--initialize-environment</text><text
 class="breeze-static-checks-r1" x="451.4" y="1508.4" textLength="549" 
clip-path="url(#breeze-static-checks-line-61)">Initialize&#160;environment&#160;before&#160;running&#160;checks.</text><text
 c [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1532.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-62)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1532.8" textLength="353.8" 
clip-path="url(#breeze-static-checks-line-62)">--max-initialization-attempts</text><text
 class="breeze-static-checks-r1" x="451.4" y="1532.8" textLength="854" 
clip-path="url(#breeze-static-checks-line-62)">Maximum&#160;number&#160;of&#160;attempts&#160;to&#160;initialize&#160;env
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1557.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-63)">│</text><text 
class="breeze-static-checks-r7" x="451.4" y="1557.2" textLength="854" 
clip-path="url(#breeze-static-checks-line-63)">(INTEGER&#160;RANGE)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1581.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-64)">│</text><text 
class="breeze-static-checks-r5" x="451.4" y="1581.6" textLength="854" 
clip-path="url(#breeze-static-checks-line-64)">[default:&#160;3;&#160;1&lt;=x&lt;=10]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1606" textLength="1464" 
clip-path="url(#breeze-static-checks-line-65)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="1606" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-65)">
+</text><text class="breeze-static-checks-r5" x="0" y="1630.4" 
textLength="24.4" clip-path="url(#breeze-static-checks-line-66)">╭─</text><text 
class="breeze-static-checks-r5" x="24.4" y="1630.4" textLength="463.6" 
clip-path="url(#breeze-static-checks-line-66)">&#160;Selecting&#160;files&#160;to&#160;run&#160;the&#160;checks&#160;on&#160;</text><text
 class="breeze-static-checks-r5" x="488" y="1630.4" textLength="951.6" 
clip-path="url(#breeze-static-checks-line-66)">──────────────────────── [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1654.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-67)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1654.8" textLength="73.2" 
clip-path="url(#breeze-static-checks-line-67)">--file</text><text 
class="breeze-static-checks-r6" x="256.2" y="1654.8" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-67)">-f</text><text 
class="breeze-static-checks-r1" x="305" y="1654.8" textLength="427" 
clip-path="url [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1679.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-68)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1679.2" textLength="134.2" 
clip-path="url(#breeze-static-checks-line-68)">--all-files</text><text 
class="breeze-static-checks-r6" x="256.2" y="1679.2" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-68)">-a</text><text 
class="breeze-static-checks-r1" x="305" y="1679.2" textLength="292.8" clip-p 
[...]
+</text><text class="breeze-static-checks-r5" x="0" y="1703.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-69)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1703.6" textLength="146.4" 
clip-path="url(#breeze-static-checks-line-69)">--commit-ref</text><text 
class="breeze-static-checks-r6" x="256.2" y="1703.6" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-69)">-r</text><text 
class="breeze-static-checks-r1" x="305" y="1703.6" textLength="1134.6" clip 
[...]
+</text><text class="breeze-static-checks-r5" x="0" y="1728" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-70)">│</text><text 
class="breeze-static-checks-r1" x="305" y="1728" textLength="183" 
clip-path="url(#breeze-static-checks-line-70)">exclusive&#160;with&#160;</text><text
 class="breeze-static-checks-r4" x="488" y="1728" textLength="158.6" 
clip-path="url(#breeze-static-checks-line-70)">--last-commit</text><text 
class="breeze-static-checks-r1" x="646.6" y="1728" textLength [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1752.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-71)">│</text><text 
class="breeze-static-checks-r7" x="305" y="1752.4" textLength="1134.6" 
clip-path="url(#breeze-static-checks-line-71)">(TEXT)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1776.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-72)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1776.8" textLength="158.6" 
clip-path="url(#breeze-static-checks-line-72)">--last-commit</text><text 
class="breeze-static-checks-r6" x="256.2" y="1776.8" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-72)">-c</text><text 
class="breeze-static-checks-r1" x="305" y="1776.8" textLength="793" clip-p [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1801.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-73)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1801.2" textLength="207.4" 
clip-path="url(#breeze-static-checks-line-73)">--only-my-changes</text><text 
class="breeze-static-checks-r6" x="256.2" y="1801.2" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-73)">-m</text><text 
class="breeze-static-checks-r1" x="305" y="1801.2" textLength="1134.6" [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1825.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-74)">│</text><text 
class="breeze-static-checks-r1" x="305" y="1825.6" textLength="1134.6" 
clip-path="url(#breeze-static-checks-line-74)">branch&#160;and&#160;HEAD&#160;of&#160;your&#160;branch.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1850" textLength="1464" 
clip-path="url(#breeze-static-checks-line-75)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="1850" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-75)">
+</text><text class="breeze-static-checks-r5" x="0" y="1874.4" 
textLength="24.4" clip-path="url(#breeze-static-checks-line-76)">╭─</text><text 
class="breeze-static-checks-r5" x="24.4" y="1874.4" textLength="463.6" 
clip-path="url(#breeze-static-checks-line-76)">&#160;Building&#160;image&#160;before&#160;running&#160;checks&#160;</text><text
 class="breeze-static-checks-r5" x="488" y="1874.4" textLength="951.6" 
clip-path="url(#breeze-static-checks-line-76)">──────────────────────────────────
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1898.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-77)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1898.8" textLength="317.2" 
clip-path="url(#breeze-static-checks-line-77)">--skip-image-upgrade-check</text><text
 class="breeze-static-checks-r1" x="414.8" y="1898.8" textLength="536.8" 
clip-path="url(#breeze-static-checks-line-77)">Skip&#160;checking&#160;if&#160;the&#160;CI&#160;image&#160;is&#160;up&#160
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1923.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-78)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1923.2" textLength="158.6" 
clip-path="url(#breeze-static-checks-line-78)">--force-build</text><text 
class="breeze-static-checks-r1" x="414.8" y="1923.2" textLength="707.6" 
clip-path="url(#breeze-static-checks-line-78)">Force&#160;image&#160;build&#160;no&#160;matter&#160;if&#160;it&#160;is&#160;determined&
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1947.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-79)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1947.6" textLength="134.2" 
clip-path="url(#breeze-static-checks-line-79)">--image-tag</text><text 
class="breeze-static-checks-r1" x="414.8" y="1947.6" textLength="695.4" 
clip-path="url(#breeze-static-checks-line-79)">Tag&#160;of&#160;the&#160;image&#160;which&#160;is&#160;used&#160;to&#160;run&#160;the&#16
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1972" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-80)">│</text><text 
class="breeze-static-checks-r7" x="414.8" y="1972" textLength="963.8" 
clip-path="url(#breeze-static-checks-line-80)">(TEXT)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1996.4" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-81)">│</text><text 
class="breeze-static-checks-r5" x="414.8" y="1996.4" textLength="963.8" 
clip-path="url(#breeze-static-checks-line-81)">[default:&#160;latest]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="2020.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-82)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="2020.8" textLength="231.8" 
clip-path="url(#breeze-static-checks-line-82)">--github-repository</text><text 
class="breeze-static-checks-r6" x="366" y="2020.8" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-82)">-g</text><text 
class="breeze-static-checks-r1" x="414.8" y="2020.8" textLength="585.6 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="2045.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-83)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="2045.2" textLength="109.8" 
clip-path="url(#breeze-static-checks-line-83)">--builder</text><text 
class="breeze-static-checks-r1" x="414.8" y="2045.2" textLength="756.4" 
clip-path="url(#breeze-static-checks-line-83)">Buildx&#160;builder&#160;used&#160;to&#160;perform&#160;`docker&#160;buildx&#160;build`&#160
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="2069.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-84)">│</text><text 
class="breeze-static-checks-r5" x="414.8" y="2069.6" textLength="756.4" 
clip-path="url(#breeze-static-checks-line-84)">[default:&#160;autodetect]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="2094" textLength="1464" 
clip-path="url(#breeze-static-checks-line-85)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="2094" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-85)">
+</text><text class="breeze-static-checks-r5" x="0" y="2118.4" 
textLength="24.4" clip-path="url(#breeze-static-checks-line-86)">╭─</text><text 
class="breeze-static-checks-r5" x="24.4" y="2118.4" textLength="195.2" 
clip-path="url(#breeze-static-checks-line-86)">&#160;Common&#160;options&#160;</text><text
 class="breeze-static-checks-r5" x="219.6" y="2118.4" textLength="1220" 
clip-path="url(#breeze-static-checks-line-86)">──────────────────────────────────────────────────────────────────────
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="2142.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-87)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="2142.8" textLength="109.8" 
clip-path="url(#breeze-static-checks-line-87)">--dry-run</text><text 
class="breeze-static-checks-r6" x="158.6" y="2142.8" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-87)">-D</text><text 
class="breeze-static-checks-r1" x="207.4" y="2142.8" textLength="719.8" clip-p 
[...]
+</text><text class="breeze-static-checks-r5" x="0" y="2167.2" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-88)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="2167.2" textLength="109.8" 
clip-path="url(#breeze-static-checks-line-88)">--verbose</text><text 
class="breeze-static-checks-r6" x="158.6" y="2167.2" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-88)">-v</text><text 
class="breeze-static-checks-r1" x="207.4" y="2167.2" textLength="585.6" clip-p 
[...]
+</text><text class="breeze-static-checks-r5" x="0" y="2191.6" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-89)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="2191.6" textLength="73.2" 
clip-path="url(#breeze-static-checks-line-89)">--help</text><text 
class="breeze-static-checks-r6" x="158.6" y="2191.6" textLength="24.4" 
clip-path="url(#breeze-static-checks-line-89)">-h</text><text 
class="breeze-static-checks-r1" x="207.4" y="2191.6" textLength="329.4" 
clip-path= [...]
+</text><text class="breeze-static-checks-r5" x="0" y="2216" textLength="1464" 
clip-path="url(#breeze-static-checks-line-90)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="2216" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-90)">
 </text>
     </g>
     </g>
diff --git a/dev/breeze/doc/images/output_static-checks.txt 
b/dev/breeze/doc/images/output_static-checks.txt
index 83697252d59..5eafd7bd8a7 100644
--- a/dev/breeze/doc/images/output_static-checks.txt
+++ b/dev/breeze/doc/images/output_static-checks.txt
@@ -1 +1 @@
-f9eb3d902f6df6f3bcf01be469d958e3
+1fd1ce1703cb27b2fd042f55f5aa6ddd
diff --git a/dev/breeze/src/airflow_breeze/pre_commit_ids.py 
b/dev/breeze/src/airflow_breeze/pre_commit_ids.py
index 657559b601f..a3b1ba37266 100644
--- a/dev/breeze/src/airflow_breeze/pre_commit_ids.py
+++ b/dev/breeze/src/airflow_breeze/pre_commit_ids.py
@@ -56,6 +56,7 @@ PRE_COMMIT_LIST = [
     "check-google-re2-as-dependency",
     "check-hatch-build-order",
     "check-hooks-apply",
+    "check-imports-in-providers",
     "check-incorrect-use-of-LoggingMixin",
     "check-init-decorator-arguments",
     "check-integrations-list-consistent",
diff --git a/providers/src/airflow/providers/MANAGING_PROVIDERS_LIFECYCLE.rst 
b/providers/src/airflow/providers/MANAGING_PROVIDERS_LIFECYCLE.rst
index 2ad00656a5a..867f45edf9f 100644
--- a/providers/src/airflow/providers/MANAGING_PROVIDERS_LIFECYCLE.rst
+++ b/providers/src/airflow/providers/MANAGING_PROVIDERS_LIFECYCLE.rst
@@ -433,6 +433,31 @@ the compatibility checks should be updated when min 
airflow version is updated.
 Details on how this should be done are described in
 `Provider policies 
<https://github.com/apache/airflow/blob/main/dev/README_RELEASE_PROVIDER_PACKAGES.md>`_
 
+Conditional provider variants
+=============================
+
+Sometimes providers need to have different variants for different versions of 
Airflow. This is done by:
+
+* copying ``version_compat.py`` from one of the providers that already have 
conditional variants to
+  the root package of the provider you are working on
+
+* importing the ``AIRFLOW_V_X_Y_PLUS`` that you need from that imported 
``version_compat.py`` file.
+
+The main reasons we are doing it in this way:
+
+* checking version >= in Python has a non-obvious problem that the pre-release 
version is always considered
+  lower than the final version. This is why we are using 
``AIRFLOW_V_X_Y_PLUS`` to check for the version
+  that is greater or equal to the version we are checking against - because we 
want the RC candidates
+  to be considered as equal to the final version (because those RC candidates 
already contain the feature
+  that is added in the final version).
+* We do not want to add dependencies to another provider (say 
``common.compat``) without strong need
+* Even if the code is duplicated, it is just one ``version_compat.py`` file 
that is wholly copied
+  and it is not a big deal to maintain it.
+* There is a potential risk of one provider importing the same 
``AIRFLOW_V_X_Y_PLUS`` from another provider
+  (and introduce accidental dependency) or from test code (which should not 
happen), but we are preventing it
+  via pre-commit check ``check-imports-in-providers`` that will fail if the
+  ``version_compat`` module is imported from another provider or from test 
code.
+
 Releasing pre-installed providers for the first time
 ====================================================
 
diff --git 
a/providers/src/airflow/providers/amazon/aws/auth_manager/aws_auth_manager.py 
b/providers/src/airflow/providers/amazon/aws/auth_manager/aws_auth_manager.py
index fb32a37f573..4f1e62e726f 100644
--- 
a/providers/src/airflow/providers/amazon/aws/auth_manager/aws_auth_manager.py
+++ 
b/providers/src/airflow/providers/amazon/aws/auth_manager/aws_auth_manager.py
@@ -39,6 +39,7 @@ from 
airflow.providers.amazon.aws.auth_manager.security_manager.aws_security_man
     AwsSecurityManagerOverride,
 )
 from airflow.providers.amazon.aws.auth_manager.views.auth import 
AwsAuthManagerAuthenticationViews
+from airflow.providers.amazon.version_compat import AIRFLOW_V_2_9_PLUS
 
 try:
     from airflow.auth.managers.base_auth_manager import BaseAuthManager, 
ResourceMethod
@@ -81,12 +82,7 @@ class AwsAuthManager(BaseAuthManager):
     """
 
     def __init__(self, appbuilder: AirflowAppBuilder) -> None:
-        from packaging.version import Version
-
-        from airflow.version import version
-
-        # TODO: remove this if block when min_airflow_version is set to higher 
than 2.9.0
-        if Version(version) < Version("2.9"):
+        if not AIRFLOW_V_2_9_PLUS:
             raise AirflowOptionalProviderFeatureException(
                 "``AwsAuthManager`` is compatible with Airflow versions >= 
2.9."
             )
diff --git a/providers/src/airflow/providers/amazon/aws/hooks/redshift_sql.py 
b/providers/src/airflow/providers/amazon/aws/hooks/redshift_sql.py
index bfdf807318a..23b9555def8 100644
--- a/providers/src/airflow/providers/amazon/aws/hooks/redshift_sql.py
+++ b/providers/src/airflow/providers/amazon/aws/hooks/redshift_sql.py
@@ -20,19 +20,15 @@ from functools import cached_property
 from typing import TYPE_CHECKING
 
 import redshift_connector
-from packaging.version import Version
 from redshift_connector import Connection as RedshiftConnection
 from sqlalchemy import create_engine
 from sqlalchemy.engine.url import URL
 
-from airflow import __version__ as AIRFLOW_VERSION
 from airflow.exceptions import AirflowException
 from airflow.providers.amazon.aws.hooks.base_aws import AwsBaseHook
+from airflow.providers.amazon.version_compat import AIRFLOW_V_2_10_PLUS
 from airflow.providers.common.sql.hooks.sql import DbApiHook
 
-_IS_AIRFLOW_2_10_OR_HIGHER = Version(Version(AIRFLOW_VERSION).base_version) >= 
Version("2.10.0")
-
-
 if TYPE_CHECKING:
     from airflow.models.connection import Connection
     from airflow.providers.openlineage.sqlparser import DatabaseInfo
@@ -265,6 +261,6 @@ class RedshiftSQLHook(DbApiHook):
 
     def get_openlineage_default_schema(self) -> str | None:
         """Return current schema. This is usually changed with ``SEARCH_PATH`` 
parameter."""
-        if _IS_AIRFLOW_2_10_OR_HIGHER:
+        if AIRFLOW_V_2_10_PLUS:
             return self.get_first("SELECT CURRENT_SCHEMA();")[0]
         return super().get_openlineage_default_schema()
diff --git a/providers/src/airflow/providers/amazon/aws/transfers/gcs_to_s3.py 
b/providers/src/airflow/providers/amazon/aws/transfers/gcs_to_s3.py
index c4ead1b58a7..6899f7daffc 100644
--- a/providers/src/airflow/providers/amazon/aws/transfers/gcs_to_s3.py
+++ b/providers/src/airflow/providers/amazon/aws/transfers/gcs_to_s3.py
@@ -124,9 +124,9 @@ class GCSToS3Operator(BaseOperator):
         self.s3_acl_policy = s3_acl_policy
         self.keep_directory_structure = keep_directory_structure
         try:
-            from airflow.providers.google import __version__
+            from airflow.providers.google import __version__ as 
_GOOGLE_PROVIDER_VERSION
 
-            if Version(__version__) >= Version("10.3.0"):
+            if Version(Version(_GOOGLE_PROVIDER_VERSION).base_version) >= 
Version("10.3.0"):
                 self.__is_match_glob_supported = True
             else:
                 self.__is_match_glob_supported = False
diff --git a/providers/src/airflow/providers/amazon/aws/utils/__init__.py 
b/providers/src/airflow/providers/amazon/aws/utils/__init__.py
index 74da7001b8c..35426ab865b 100644
--- a/providers/src/airflow/providers/amazon/aws/utils/__init__.py
+++ b/providers/src/airflow/providers/amazon/aws/utils/__init__.py
@@ -31,21 +31,7 @@ log = logging.getLogger(__name__)
 
 
 def trim_none_values(obj: dict):
-    from packaging.version import Version
-
-    from airflow.version import version
-
-    if Version(version) < Version("2.7"):
-        # before version 2.7, the behavior is not the same.
-        # Empty dict and lists are removed from the given dict.
-        return {key: val for key, val in obj.items() if val is not None}
-    else:
-        # once airflow 2.6 rolls out of compatibility support for provider 
packages,
-        # we can replace usages of this method with the core one in our code,
-        # and uncomment this warning for users who may use it.
-        # warnings.warn("use airflow.utils.helpers.prune_dict() instead",
-        #     AirflowProviderDeprecationWarning, stacklevel=2)
-        return prune_dict(obj)
+    return prune_dict(obj)
 
 
 def datetime_to_epoch(date_time: datetime) -> int:
diff --git a/tests_common/test_utils/version_compat.py 
b/providers/src/airflow/providers/amazon/version_compat.py
similarity index 77%
copy from tests_common/test_utils/version_compat.py
copy to providers/src/airflow/providers/amazon/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/providers/src/airflow/providers/amazon/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 
diff --git 
a/providers/src/airflow/providers/cncf/kubernetes/cli/kubernetes_command.py 
b/providers/src/airflow/providers/cncf/kubernetes/cli/kubernetes_command.py
index 1bca856fd32..ee629cc16e9 100644
--- a/providers/src/airflow/providers/cncf/kubernetes/cli/kubernetes_command.py
+++ b/providers/src/airflow/providers/cncf/kubernetes/cli/kubernetes_command.py
@@ -25,22 +25,18 @@ from datetime import datetime, timedelta
 from kubernetes import client
 from kubernetes.client.api_client import ApiClient
 from kubernetes.client.rest import ApiException
-from packaging.version import Version
 
-from airflow import __version__ as airflow_version
 from airflow.models import DagRun, TaskInstance
 from airflow.providers.cncf.kubernetes import pod_generator
 from airflow.providers.cncf.kubernetes.executors.kubernetes_executor import 
KubeConfig
 from airflow.providers.cncf.kubernetes.kube_client import get_kube_client
 from airflow.providers.cncf.kubernetes.kubernetes_helper_functions import 
create_unique_id
 from airflow.providers.cncf.kubernetes.pod_generator import PodGenerator
+from airflow.providers.cncf.kubernetes.version_compat import AIRFLOW_V_3_0_PLUS
 from airflow.utils import cli as cli_utils, yaml
 from airflow.utils.cli import get_dag
 from airflow.utils.providers_configuration_loader import 
providers_configuration_loaded
 
-AIRFLOW_VERSION = Version(airflow_version)
-AIRFLOW_V_3_0_PLUS = Version(AIRFLOW_VERSION.base_version) >= Version("3.0.0")
-
 
 @cli_utils.action_cli
 @providers_configuration_loaded
diff --git a/tests_common/test_utils/version_compat.py 
b/providers/src/airflow/providers/cncf/kubernetes/version_compat.py
similarity index 77%
copy from tests_common/test_utils/version_compat.py
copy to providers/src/airflow/providers/cncf/kubernetes/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/providers/src/airflow/providers/cncf/kubernetes/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 
diff --git a/providers/src/airflow/providers/common/compat/assets/__init__.py 
b/providers/src/airflow/providers/common/compat/assets/__init__.py
index b237b51c39f..41e2e65621a 100644
--- a/providers/src/airflow/providers/common/compat/assets/__init__.py
+++ b/providers/src/airflow/providers/common/compat/assets/__init__.py
@@ -19,8 +19,7 @@ from __future__ import annotations
 
 from typing import TYPE_CHECKING
 
-from airflow.providers.common.compat.version_references import (
-    AIRFLOW_V_2_8_PLUS,
+from airflow.providers.common.compat.version_compat import (
     AIRFLOW_V_2_9_PLUS,
     AIRFLOW_V_2_10_PLUS,
     AIRFLOW_V_3_0_PLUS,
@@ -37,11 +36,9 @@ else:
         from airflow.sdk.definitions.asset import Asset, AssetAlias, AssetAll, 
AssetAny
     else:
         # dataset is renamed to asset since Airflow 3.0
+        from airflow.auth.managers.models.resource_details import 
DatasetDetails as AssetDetails
         from airflow.datasets import Dataset as Asset
 
-        if AIRFLOW_V_2_8_PLUS:
-            from airflow.auth.managers.models.resource_details import 
DatasetDetails as AssetDetails
-
         if AIRFLOW_V_2_9_PLUS:
             from airflow.datasets import (
                 DatasetAll as AssetAll,
diff --git a/providers/src/airflow/providers/common/compat/lineage/hook.py 
b/providers/src/airflow/providers/common/compat/lineage/hook.py
index 10c22084fab..1b18723c457 100644
--- a/providers/src/airflow/providers/common/compat/lineage/hook.py
+++ b/providers/src/airflow/providers/common/compat/lineage/hook.py
@@ -16,7 +16,7 @@
 # under the License.
 from __future__ import annotations
 
-from airflow.providers.common.compat.version_references import 
AIRFLOW_V_2_10_PLUS, AIRFLOW_V_3_0_PLUS
+from airflow.providers.common.compat.version_compat import 
AIRFLOW_V_2_10_PLUS, AIRFLOW_V_3_0_PLUS
 
 
 def _get_asset_compat_hook_lineage_collector():
diff --git 
a/providers/src/airflow/providers/common/compat/standard/operators.py 
b/providers/src/airflow/providers/common/compat/standard/operators.py
index 1b319e1ff9f..0e34419043f 100644
--- a/providers/src/airflow/providers/common/compat/standard/operators.py
+++ b/providers/src/airflow/providers/common/compat/standard/operators.py
@@ -19,7 +19,7 @@ from __future__ import annotations
 
 from typing import TYPE_CHECKING
 
-from airflow import __version__ as AIRFLOW_VERSION
+from airflow.providers.common.compat.version_compat import AIRFLOW_V_2_10_PLUS
 
 if TYPE_CHECKING:
     from airflow.providers.standard.operators.python import (
@@ -37,17 +37,13 @@ else:
             get_current_context,
         )
     except ModuleNotFoundError:
-        from packaging.version import Version
-
-        _IS_AIRFLOW_2_10_OR_HIGHER = 
Version(Version(AIRFLOW_VERSION).base_version) >= Version("2.10.0")
-
         from airflow.operators.python import (
             PythonOperator,
             ShortCircuitOperator,
             get_current_context,
         )
 
-        if _IS_AIRFLOW_2_10_OR_HIGHER:
+        if AIRFLOW_V_2_10_PLUS:
             from airflow.operators.python import _SERIALIZERS
 
 
diff --git a/tests_common/test_utils/version_compat.py 
b/providers/src/airflow/providers/common/compat/version_compat.py
similarity index 77%
copy from tests_common/test_utils/version_compat.py
copy to providers/src/airflow/providers/common/compat/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/providers/src/airflow/providers/common/compat/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 
diff --git 
a/providers/src/airflow/providers/common/compat/version_references.py 
b/providers/src/airflow/providers/common/compat/version_references.py
deleted file mode 100644
index ac44d73ac22..00000000000
--- a/providers/src/airflow/providers/common/compat/version_references.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-from __future__ import annotations
-
-from packaging.version import Version
-
-from airflow import __version__ as AIRFLOW_VERSION
-
-AIRFLOW_V_3_0_PLUS = Version(Version(AIRFLOW_VERSION).base_version) >= 
Version("3.0.0")
-AIRFLOW_V_2_10_PLUS = Version(Version(AIRFLOW_VERSION).base_version) >= 
Version("2.10.0")
-AIRFLOW_V_2_9_PLUS = Version(Version(AIRFLOW_VERSION).base_version) >= 
Version("2.9.0")
-AIRFLOW_V_2_8_PLUS = Version(Version(AIRFLOW_VERSION).base_version) >= 
Version("2.8.0")
diff --git a/providers/src/airflow/providers/common/io/assets/file.py 
b/providers/src/airflow/providers/common/io/assets/file.py
index 28d990d5630..73b2ef0c953 100644
--- a/providers/src/airflow/providers/common/io/assets/file.py
+++ b/providers/src/airflow/providers/common/io/assets/file.py
@@ -19,12 +19,8 @@ from __future__ import annotations
 import urllib.parse
 from typing import TYPE_CHECKING
 
-from packaging.version import Version
+from airflow.providers.common.io.version_compat import AIRFLOW_V_3_0_PLUS
 
-from airflow import __version__ as AIRFLOW_VERSION
-
-# TODO: Remove version check block after bumping common provider to 1.3.0
-AIRFLOW_V_3_0_PLUS = Version(Version(AIRFLOW_VERSION).base_version) >= 
Version("3.0.0")
 if AIRFLOW_V_3_0_PLUS:
     from airflow.sdk.definitions.asset import Asset
 else:
diff --git a/tests_common/test_utils/version_compat.py 
b/providers/src/airflow/providers/common/io/version_compat.py
similarity index 77%
copy from tests_common/test_utils/version_compat.py
copy to providers/src/airflow/providers/common/io/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/providers/src/airflow/providers/common/io/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 
diff --git a/providers/src/airflow/providers/common/io/xcom/backend.py 
b/providers/src/airflow/providers/common/io/xcom/backend.py
index a41ab6a917e..addde4c6c10 100644
--- a/providers/src/airflow/providers/common/io/xcom/backend.py
+++ b/providers/src/airflow/providers/common/io/xcom/backend.py
@@ -25,12 +25,11 @@ from typing import TYPE_CHECKING, Any, TypeVar
 from urllib.parse import urlsplit
 
 import fsspec.utils
-from packaging.version import Version
 
-from airflow import __version__ as airflow_version
 from airflow.configuration import conf
 from airflow.io.path import ObjectStoragePath
 from airflow.models.xcom import BaseXCom
+from airflow.providers.common.io.version_compat import AIRFLOW_V_3_0_PLUS
 from airflow.utils.json import XComDecoder, XComEncoder
 
 if TYPE_CHECKING:
@@ -43,10 +42,6 @@ T = TypeVar("T")
 SECTION = "common.io"
 
 
-AIRFLOW_VERSION = Version(airflow_version)
-AIRFLOW_V_3_0_PLUS = Version(AIRFLOW_VERSION.base_version) >= Version("3.0.0")
-
-
 def _get_compression_suffix(compression: str) -> str:
     """
     Return the compression suffix for the given compression.
diff --git a/providers/src/airflow/providers/edge/cli/edge_command.py 
b/providers/src/airflow/providers/edge/cli/edge_command.py
index 7f110da38ea..8e89c835252 100644
--- a/providers/src/airflow/providers/edge/cli/edge_command.py
+++ b/providers/src/airflow/providers/edge/cli/edge_command.py
@@ -30,7 +30,6 @@ from typing import TYPE_CHECKING
 
 import psutil
 from lockfile.pidlockfile import read_pid_from_pidfile, 
remove_existing_pidfile, write_pid_to_pidfile
-from packaging.version import Version
 
 from airflow import __version__ as airflow_version, settings
 from airflow.cli.cli_config import ARG_PID, ARG_VERBOSE, ActionCommand, Arg
@@ -46,6 +45,7 @@ from airflow.providers.edge.cli.api_client import (
     worker_set_state,
 )
 from airflow.providers.edge.models.edge_worker import EdgeWorkerState, 
EdgeWorkerVersionException
+from airflow.providers.edge.version_compat import AIRFLOW_V_3_0_PLUS
 from airflow.utils import cli as cli_utils, timezone
 from airflow.utils.platform import IS_WINDOWS
 from airflow.utils.providers_configuration_loader import 
providers_configuration_loaded
@@ -81,8 +81,6 @@ def force_use_internal_api_on_edge_worker():
     os.environ["_AIRFLOW__SKIP_DATABASE_EXECUTOR_COMPATIBILITY_CHECK"] = "1"
     os.environ["AIRFLOW_ENABLE_AIP_44"] = "True"
     if "airflow" in sys.argv[0] and sys.argv[1:3] == ["edge", "worker"]:
-        AIRFLOW_VERSION = Version(airflow_version)
-        AIRFLOW_V_3_0_PLUS = Version(AIRFLOW_VERSION.base_version) >= 
Version("3.0.0")
         if AIRFLOW_V_3_0_PLUS:
             # Obvious TODO Make EdgeWorker compatible with Airflow 3 (again)
             raise SystemExit(
diff --git 
a/providers/src/airflow/providers/edge/plugins/edge_executor_plugin.py 
b/providers/src/airflow/providers/edge/plugins/edge_executor_plugin.py
index d97176db259..19166e98a2c 100644
--- a/providers/src/airflow/providers/edge/plugins/edge_executor_plugin.py
+++ b/providers/src/airflow/providers/edge/plugins/edge_executor_plugin.py
@@ -23,15 +23,14 @@ from typing import TYPE_CHECKING, Any
 
 from flask import Blueprint
 from flask_appbuilder import BaseView, expose
-from packaging.version import Version
 from sqlalchemy import select
 
-from airflow import __version__ as airflow_version
 from airflow.auth.managers.models.resource_details import AccessView
 from airflow.configuration import conf
 from airflow.exceptions import AirflowConfigException
 from airflow.models.taskinstance import TaskInstanceState
 from airflow.plugins_manager import AirflowPlugin
+from airflow.providers.edge.version_compat import AIRFLOW_V_3_0_PLUS
 from airflow.utils.session import NEW_SESSION, provide_session
 from airflow.utils.yaml import safe_load
 from airflow.www import utils as wwwutils
@@ -42,9 +41,6 @@ from airflow.www.extensions.init_views import 
_CustomErrorRequestBodyValidator,
 if TYPE_CHECKING:
     from sqlalchemy.orm import Session
 
-AIRFLOW_VERSION = Version(airflow_version)
-AIRFLOW_V_3_0_PLUS = Version(AIRFLOW_VERSION.base_version) >= Version("3.0.0")
-
 
 def _get_airflow_2_api_endpoint() -> Blueprint:
     folder = Path(__file__).parents[1].resolve()  # this is 
airflow/providers/edge/
diff --git a/tests_common/test_utils/version_compat.py 
b/providers/src/airflow/providers/edge/version_compat.py
similarity index 77%
copy from tests_common/test_utils/version_compat.py
copy to providers/src/airflow/providers/edge/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/providers/src/airflow/providers/edge/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 
diff --git 
a/providers/src/airflow/providers/edge/worker_api/routes/_v2_compat.py 
b/providers/src/airflow/providers/edge/worker_api/routes/_v2_compat.py
index 553456d4108..afe4af0fbd8 100644
--- a/providers/src/airflow/providers/edge/worker_api/routes/_v2_compat.py
+++ b/providers/src/airflow/providers/edge/worker_api/routes/_v2_compat.py
@@ -18,12 +18,7 @@
 
 from __future__ import annotations
 
-from packaging.version import Version
-
-from airflow import __version__ as airflow_version
-
-AIRFLOW_VERSION = Version(airflow_version)
-AIRFLOW_V_3_0_PLUS = Version(AIRFLOW_VERSION.base_version) >= Version("3.0.0")
+from airflow.providers.edge.version_compat import AIRFLOW_V_3_0_PLUS
 
 if AIRFLOW_V_3_0_PLUS:
     # Just re-import the types from FastAPI and Airflow Core
diff --git 
a/providers/src/airflow/providers/elasticsearch/log/es_task_handler.py 
b/providers/src/airflow/providers/elasticsearch/log/es_task_handler.py
index 3fb68bc24e3..241fb14aa23 100644
--- a/providers/src/airflow/providers/elasticsearch/log/es_task_handler.py
+++ b/providers/src/airflow/providers/elasticsearch/log/es_task_handler.py
@@ -31,23 +31,19 @@ from urllib.parse import quote, urlparse
 import elasticsearch
 import pendulum
 from elasticsearch.exceptions import NotFoundError
-from packaging.version import Version
 
-from airflow import __version__ as airflow_version
 from airflow.configuration import conf
 from airflow.exceptions import AirflowException
 from airflow.models.dagrun import DagRun
 from airflow.providers.elasticsearch.log.es_json_formatter import 
ElasticsearchJSONFormatter
 from airflow.providers.elasticsearch.log.es_response import 
ElasticSearchResponse, Hit
+from airflow.providers.elasticsearch.version_compat import AIRFLOW_V_3_0_PLUS
 from airflow.utils import timezone
 from airflow.utils.log.file_task_handler import FileTaskHandler
 from airflow.utils.log.logging_mixin import ExternalLoggingMixin, LoggingMixin
 from airflow.utils.module_loading import import_string
 from airflow.utils.session import create_session
 
-AIRFLOW_VERSION = Version(airflow_version)
-AIRFLOW_V_3_0_PLUS = Version(AIRFLOW_VERSION.base_version) >= Version("3.0.0")
-
 if TYPE_CHECKING:
     from datetime import datetime
 
diff --git a/tests_common/test_utils/version_compat.py 
b/providers/src/airflow/providers/elasticsearch/version_compat.py
similarity index 77%
copy from tests_common/test_utils/version_compat.py
copy to providers/src/airflow/providers/elasticsearch/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/providers/src/airflow/providers/elasticsearch/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 
diff --git a/providers/src/airflow/providers/google/assets/gcs.py 
b/providers/src/airflow/providers/google/assets/gcs.py
index 22206e3f753..1d26fe8d3da 100644
--- a/providers/src/airflow/providers/google/assets/gcs.py
+++ b/providers/src/airflow/providers/google/assets/gcs.py
@@ -19,6 +19,7 @@ from __future__ import annotations
 from typing import TYPE_CHECKING
 
 from airflow.providers.google.cloud.hooks.gcs import _parse_gcs_url
+from airflow.providers.google.version_compat import AIRFLOW_V_3_0_PLUS
 
 if TYPE_CHECKING:
     from urllib.parse import SplitResult
@@ -26,16 +27,9 @@ if TYPE_CHECKING:
     from airflow.providers.common.compat.assets import Asset
     from airflow.providers.common.compat.openlineage.facet import Dataset as 
OpenLineageDataset
 else:
-    # TODO: Remove this try-exception block after bumping common provider to 
1.3.0
-    # This is due to common provider AssetDetails import error handling
     try:
         from airflow.providers.common.compat.assets import Asset
     except ImportError:
-        from packaging.version import Version
-
-        from airflow import __version__ as AIRFLOW_VERSION
-
-        AIRFLOW_V_3_0_PLUS = Version(Version(AIRFLOW_VERSION).base_version) >= 
Version("3.0.0")
         if AIRFLOW_V_3_0_PLUS:
             from airflow.sdk.definitions.asset import Asset
         else:
diff --git 
a/providers/src/airflow/providers/google/cloud/log/stackdriver_task_handler.py 
b/providers/src/airflow/providers/google/cloud/log/stackdriver_task_handler.py
index b26696d290e..9ade3b812f0 100644
--- 
a/providers/src/airflow/providers/google/cloud/log/stackdriver_task_handler.py
+++ 
b/providers/src/airflow/providers/google/cloud/log/stackdriver_task_handler.py
@@ -30,18 +30,14 @@ from google.cloud.logging import Resource
 from google.cloud.logging.handlers.transports import 
BackgroundThreadTransport, Transport
 from google.cloud.logging_v2.services.logging_service_v2 import 
LoggingServiceV2Client
 from google.cloud.logging_v2.types import ListLogEntriesRequest, 
ListLogEntriesResponse
-from packaging.version import Version
 
-from airflow import __version__ as airflow_version
 from airflow.exceptions import RemovedInAirflow3Warning
 from airflow.providers.google.cloud.utils.credentials_provider import 
get_credentials_and_project_id
 from airflow.providers.google.common.consts import CLIENT_INFO
+from airflow.providers.google.version_compat import AIRFLOW_V_3_0_PLUS
 from airflow.utils.log.trigger_handler import ctx_indiv_trigger
 from airflow.utils.types import NOTSET, ArgNotSet
 
-AIRFLOW_VERSION = Version(airflow_version)
-AIRFLOW_V_3_0_PLUS = Version(AIRFLOW_VERSION.base_version) >= Version("3.0.0")
-
 if TYPE_CHECKING:
     from google.auth.credentials import Credentials
 
diff --git a/tests_common/test_utils/version_compat.py 
b/providers/src/airflow/providers/google/version_compat.py
similarity index 77%
copy from tests_common/test_utils/version_compat.py
copy to providers/src/airflow/providers/google/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/providers/src/airflow/providers/google/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 
diff --git a/providers/src/airflow/providers/openlineage/extractors/base.py 
b/providers/src/airflow/providers/openlineage/extractors/base.py
index ceb10ff8b1d..2b85825d8c6 100644
--- a/providers/src/airflow/providers/openlineage/extractors/base.py
+++ b/providers/src/airflow/providers/openlineage/extractors/base.py
@@ -29,7 +29,7 @@ with warnings.catch_warnings():
     from openlineage.client.facet import BaseFacet as BaseFacet_V1
 from openlineage.client.facet_v2 import JobFacet, RunFacet
 
-from airflow.providers.openlineage.utils.utils import IS_AIRFLOW_2_10_OR_HIGHER
+from airflow.providers.openlineage.utils.utils import AIRFLOW_V_2_10_PLUS
 from airflow.utils.log.logging_mixin import LoggingMixin
 from airflow.utils.state import TaskInstanceState
 
@@ -117,7 +117,7 @@ class DefaultExtractor(BaseExtractor):
 
     def extract_on_complete(self, task_instance) -> OperatorLineage | None:
         failed_states = [TaskInstanceState.FAILED, 
TaskInstanceState.UP_FOR_RETRY]
-        if not IS_AIRFLOW_2_10_OR_HIGHER:  # todo: remove when min airflow 
version >= 2.10.0
+        if not AIRFLOW_V_2_10_PLUS:  # todo: remove when min airflow version 
>= 2.10.0
             # Before fix (#41053) implemented in Airflow 2.10 TaskInstance's 
state was still RUNNING when
             # being passed to listener's on_failure method. Since 
`extract_on_complete()` is only called
             # after task completion, RUNNING state means that we are dealing 
with FAILED task in < 2.10
diff --git a/providers/src/airflow/providers/openlineage/plugins/listener.py 
b/providers/src/airflow/providers/openlineage/plugins/listener.py
index 7f0073d8f95..aefd534f155 100644
--- a/providers/src/airflow/providers/openlineage/plugins/listener.py
+++ b/providers/src/airflow/providers/openlineage/plugins/listener.py
@@ -32,7 +32,7 @@ from airflow.providers.openlineage import conf
 from airflow.providers.openlineage.extractors import ExtractorManager
 from airflow.providers.openlineage.plugins.adapter import OpenLineageAdapter, 
RunState
 from airflow.providers.openlineage.utils.utils import (
-    IS_AIRFLOW_2_10_OR_HIGHER,
+    AIRFLOW_V_2_10_PLUS,
     get_airflow_dag_run_facet,
     get_airflow_debug_facet,
     get_airflow_job_facet,
@@ -61,7 +61,7 @@ _openlineage_listener: OpenLineageListener | None = None
 
 def _get_try_number_success(val):
     # todo: remove when min airflow version >= 2.10.0
-    if IS_AIRFLOW_2_10_OR_HIGHER:
+    if AIRFLOW_V_2_10_PLUS:
         return val.try_number
     return val.try_number - 1
 
@@ -273,7 +273,7 @@ class OpenLineageListener:
 
         self._execute(on_success, "on_success", use_fork=True)
 
-    if IS_AIRFLOW_2_10_OR_HIGHER:
+    if AIRFLOW_V_2_10_PLUS:
 
         @hookimpl
         def on_task_instance_failed(
@@ -496,7 +496,7 @@ class OpenLineageListener:
                 self.log.debug("Executor have not started before 
`on_dag_run_success`")
                 return
 
-            if IS_AIRFLOW_2_10_OR_HIGHER:
+            if AIRFLOW_V_2_10_PLUS:
                 task_ids = DagRun._get_partial_task_ids(dag_run.dag)
             else:
                 task_ids = dag_run.dag.task_ids if dag_run.dag and 
dag_run.dag.partial else None
@@ -529,7 +529,7 @@ class OpenLineageListener:
                 self.log.debug("Executor have not started before 
`on_dag_run_failed`")
                 return
 
-            if IS_AIRFLOW_2_10_OR_HIGHER:
+            if AIRFLOW_V_2_10_PLUS:
                 task_ids = DagRun._get_partial_task_ids(dag_run.dag)
             else:
                 task_ids = dag_run.dag.task_ids if dag_run.dag and 
dag_run.dag.partial else None
diff --git a/providers/src/airflow/providers/openlineage/plugins/openlineage.py 
b/providers/src/airflow/providers/openlineage/plugins/openlineage.py
index ce70f3a52a9..36c26657546 100644
--- a/providers/src/airflow/providers/openlineage/plugins/openlineage.py
+++ b/providers/src/airflow/providers/openlineage/plugins/openlineage.py
@@ -25,7 +25,7 @@ from airflow.providers.openlineage.plugins.macros import (
     lineage_parent_id,
     lineage_run_id,
 )
-from airflow.providers.openlineage.utils.utils import IS_AIRFLOW_2_10_OR_HIGHER
+from airflow.providers.openlineage.version_compat import AIRFLOW_V_2_10_PLUS
 
 
 class OpenLineageProviderPlugin(AirflowPlugin):
@@ -40,7 +40,7 @@ class OpenLineageProviderPlugin(AirflowPlugin):
     if not conf.is_disabled():
         macros = [lineage_job_namespace, lineage_job_name, lineage_run_id, 
lineage_parent_id]
         listeners = [get_openlineage_listener()]
-        if IS_AIRFLOW_2_10_OR_HIGHER:
+        if AIRFLOW_V_2_10_PLUS:
             from airflow.lineage.hook import HookLineageReader
 
             hook_lineage_readers = [HookLineageReader]
diff --git a/providers/src/airflow/providers/openlineage/utils/utils.py 
b/providers/src/airflow/providers/openlineage/utils/utils.py
index 8f9b00741ea..4408a833fba 100644
--- a/providers/src/airflow/providers/openlineage/utils/utils.py
+++ b/providers/src/airflow/providers/openlineage/utils/utils.py
@@ -27,14 +27,16 @@ from typing import TYPE_CHECKING, Any, Callable
 
 import attrs
 from openlineage.client.utils import RedactMixin
-from packaging.version import Version
 from sqlalchemy import exists
 
 from airflow import __version__ as AIRFLOW_VERSION
 
 # TODO: move this maybe to Airflow's logic?
 from airflow.models import DAG, BaseOperator, DagRun, MappedOperator, 
TaskReschedule
-from airflow.providers.openlineage import __version__ as 
OPENLINEAGE_PROVIDER_VERSION, conf
+from airflow.providers.openlineage import (
+    __version__ as OPENLINEAGE_PROVIDER_VERSION,
+    conf,
+)
 from airflow.providers.openlineage.plugins.facets import (
     AirflowDagRunFacet,
     AirflowDebugRunFacet,
@@ -49,6 +51,7 @@ from airflow.providers.openlineage.utils.selective_enable 
import (
     is_dag_lineage_enabled,
     is_task_lineage_enabled,
 )
+from airflow.providers.openlineage.version_compat import AIRFLOW_V_2_10_PLUS, 
AIRFLOW_V_3_0_PLUS
 from airflow.sensors.base import BaseSensorOperator
 from airflow.serialization.serialized_objects import SerializedBaseOperator
 from airflow.utils.context import AirflowContextDeprecationWarning
@@ -69,16 +72,9 @@ if TYPE_CHECKING:
     from airflow.providers.common.compat.assets import Asset
     from airflow.utils.state import DagRunState, TaskInstanceState
 else:
-    # TODO: Remove this try-exception block after bumping common provider to 
1.3.0
-    # This is due to common provider AssetDetails import error handling
     try:
         from airflow.providers.common.compat.assets import Asset
     except ImportError:
-        from packaging.version import Version
-
-        from airflow import __version__ as AIRFLOW_VERSION
-
-        AIRFLOW_V_3_0_PLUS = Version(Version(AIRFLOW_VERSION).base_version) >= 
Version("3.0.0")
         if AIRFLOW_V_3_0_PLUS:
             from airflow.sdk.definitions.asset import Asset
         else:
@@ -87,7 +83,6 @@ else:
 
 log = logging.getLogger(__name__)
 _NOMINAL_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ"
-IS_AIRFLOW_2_10_OR_HIGHER = Version(Version(AIRFLOW_VERSION).base_version) >= 
Version("2.10.0")
 
 
 def try_import_from_string(string: str) -> Any:
@@ -716,7 +711,7 @@ def get_filtered_unknown_operator_keys(operator: 
BaseOperator) -> dict:
 
 def should_use_external_connection(hook) -> bool:
     # If we're at Airflow 2.10, the execution is process-isolated, so we can 
safely run those again.
-    if not IS_AIRFLOW_2_10_OR_HIGHER:
+    if not AIRFLOW_V_2_10_PLUS:
         return hook.__class__.__name__ not in [
             "SnowflakeHook",
             "SnowflakeSqlApiHook",
@@ -732,12 +727,6 @@ def translate_airflow_asset(asset: Asset, lineage_context) 
-> OpenLineageDataset
     This function returns None if no URI normalizer is defined, no asset 
converter is found or
     some core Airflow changes are missing and ImportError is raised.
     """
-    # TODO: Remove version check block after bumping common provider to 1.3.0
-    from packaging.version import Version
-
-    from airflow import __version__ as AIRFLOW_VERSION
-
-    AIRFLOW_V_3_0_PLUS = Version(Version(AIRFLOW_VERSION).base_version) >= 
Version("3.0.0")
     if AIRFLOW_V_3_0_PLUS:
         from airflow.sdk.definitions.asset import _get_normalized_scheme
     else:
diff --git a/tests_common/test_utils/version_compat.py 
b/providers/src/airflow/providers/openlineage/version_compat.py
similarity index 77%
copy from tests_common/test_utils/version_compat.py
copy to providers/src/airflow/providers/openlineage/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/providers/src/airflow/providers/openlineage/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 
diff --git a/providers/src/airflow/providers/opensearch/log/os_task_handler.py 
b/providers/src/airflow/providers/opensearch/log/os_task_handler.py
index 7bbaecb1159..8e784076c5f 100644
--- a/providers/src/airflow/providers/opensearch/log/os_task_handler.py
+++ b/providers/src/airflow/providers/opensearch/log/os_task_handler.py
@@ -29,23 +29,19 @@ from typing import TYPE_CHECKING, Any, Callable, Literal
 import pendulum
 from opensearchpy import OpenSearch
 from opensearchpy.exceptions import NotFoundError
-from packaging.version import Version
 
-from airflow import __version__ as airflow_version
 from airflow.configuration import conf
 from airflow.exceptions import AirflowException
 from airflow.models import DagRun
 from airflow.providers.opensearch.log.os_json_formatter import 
OpensearchJSONFormatter
 from airflow.providers.opensearch.log.os_response import Hit, 
OpensearchResponse
+from airflow.providers.opensearch.version_compat import AIRFLOW_V_3_0_PLUS
 from airflow.utils import timezone
 from airflow.utils.log.file_task_handler import FileTaskHandler
 from airflow.utils.log.logging_mixin import ExternalLoggingMixin, LoggingMixin
 from airflow.utils.module_loading import import_string
 from airflow.utils.session import create_session
 
-AIRFLOW_VERSION = Version(airflow_version)
-AIRFLOW_V_3_0_PLUS = Version(AIRFLOW_VERSION.base_version) >= Version("3.0.0")
-
 if TYPE_CHECKING:
     from airflow.models.taskinstance import TaskInstance, TaskInstanceKey
 USE_PER_RUN_LOG_ID = hasattr(DagRun, "get_log_template")
diff --git a/tests_common/test_utils/version_compat.py 
b/providers/src/airflow/providers/opensearch/version_compat.py
similarity index 77%
copy from tests_common/test_utils/version_compat.py
copy to providers/src/airflow/providers/opensearch/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/providers/src/airflow/providers/opensearch/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 
diff --git a/providers/src/airflow/providers/presto/hooks/presto.py 
b/providers/src/airflow/providers/presto/hooks/presto.py
index c78361f73eb..7d98a3ad872 100644
--- a/providers/src/airflow/providers/presto/hooks/presto.py
+++ b/providers/src/airflow/providers/presto/hooks/presto.py
@@ -23,19 +23,15 @@ from collections.abc import Iterable, Mapping
 from typing import TYPE_CHECKING, Any, TypeVar
 
 import prestodb
-from packaging.version import Version
 from prestodb.exceptions import DatabaseError
 from prestodb.transaction import IsolationLevel
 
-from airflow import __version__ as airflow_version
 from airflow.configuration import conf
 from airflow.exceptions import AirflowException
 from airflow.providers.common.sql.hooks.sql import DbApiHook
+from airflow.providers.presto.version_compat import AIRFLOW_V_3_0_PLUS
 from airflow.utils.operator_helpers import AIRFLOW_VAR_NAME_FORMAT_MAPPING, 
DEFAULT_FORMAT_PREFIX
 
-AIRFLOW_VERSION = Version(airflow_version)
-AIRFLOW_V_3_0_PLUS = Version(AIRFLOW_VERSION.base_version) >= Version("3.0.0")
-
 if TYPE_CHECKING:
     from airflow.models import Connection
 
diff --git a/tests_common/test_utils/version_compat.py 
b/providers/src/airflow/providers/presto/version_compat.py
similarity index 77%
copy from tests_common/test_utils/version_compat.py
copy to providers/src/airflow/providers/presto/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/providers/src/airflow/providers/presto/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 
diff --git a/providers/src/airflow/providers/standard/operators/python.py 
b/providers/src/airflow/providers/standard/operators/python.py
index 83e61820514..ce1447769e1 100644
--- a/providers/src/airflow/providers/standard/operators/python.py
+++ b/providers/src/airflow/providers/standard/operators/python.py
@@ -47,7 +47,10 @@ from airflow.models.taskinstance import _CURRENT_CONTEXT
 from airflow.models.variable import Variable
 from airflow.operators.branch import BranchMixIn
 from airflow.providers.standard.utils.python_virtualenv import 
prepare_virtualenv, write_python_script
-from airflow.providers.standard.utils.version_references import 
AIRFLOW_V_2_10_PLUS, AIRFLOW_V_3_0_PLUS
+from airflow.providers.standard.version_compat import (
+    AIRFLOW_V_2_10_PLUS,
+    AIRFLOW_V_3_0_PLUS,
+)
 from airflow.typing_compat import Literal
 from airflow.utils import hashlib_wrapper
 from airflow.utils.context import context_copy_partial, context_merge
diff --git a/providers/src/airflow/providers/standard/provider.yaml 
b/providers/src/airflow/providers/standard/provider.yaml
index 6e5d7ba9e73..661f3f4f855 100644
--- a/providers/src/airflow/providers/standard/provider.yaml
+++ b/providers/src/airflow/providers/standard/provider.yaml
@@ -22,7 +22,6 @@ description: |
     Airflow Standard Provider
 state: ready
 source-date-epoch: 1732434919
-
 # note that those versions are maintained by release manager - do not update 
them manually
 versions:
   - 0.0.2
diff --git a/providers/src/airflow/providers/standard/sensors/date_time.py 
b/providers/src/airflow/providers/standard/sensors/date_time.py
index 65ca95da5cc..050c36239b2 100644
--- a/providers/src/airflow/providers/standard/sensors/date_time.py
+++ b/providers/src/airflow/providers/standard/sensors/date_time.py
@@ -23,7 +23,7 @@ from dataclasses import dataclass
 from typing import TYPE_CHECKING, Any, NoReturn
 
 from airflow.providers.standard.triggers.temporal import DateTimeTrigger
-from airflow.providers.standard.utils.version_references import 
AIRFLOW_V_3_0_PLUS
+from airflow.providers.standard.version_compat import AIRFLOW_V_3_0_PLUS
 from airflow.sensors.base import BaseSensorOperator
 
 try:
diff --git a/providers/src/airflow/providers/standard/sensors/time.py 
b/providers/src/airflow/providers/standard/sensors/time.py
index 6443f2a344a..273fda9d362 100644
--- a/providers/src/airflow/providers/standard/sensors/time.py
+++ b/providers/src/airflow/providers/standard/sensors/time.py
@@ -22,7 +22,7 @@ from dataclasses import dataclass
 from typing import TYPE_CHECKING, Any, NoReturn
 
 from airflow.providers.standard.triggers.temporal import DateTimeTrigger
-from airflow.providers.standard.utils.version_references import 
AIRFLOW_V_2_10_PLUS
+from airflow.providers.standard.version_compat import AIRFLOW_V_2_10_PLUS
 from airflow.sensors.base import BaseSensorOperator
 
 try:
diff --git a/providers/src/airflow/providers/standard/sensors/time_delta.py 
b/providers/src/airflow/providers/standard/sensors/time_delta.py
index 8e0f26ac249..6b09a361efa 100644
--- a/providers/src/airflow/providers/standard/sensors/time_delta.py
+++ b/providers/src/airflow/providers/standard/sensors/time_delta.py
@@ -26,7 +26,7 @@ from packaging.version import Version
 from airflow.configuration import conf
 from airflow.exceptions import AirflowSkipException
 from airflow.providers.standard.triggers.temporal import DateTimeTrigger, 
TimeDeltaTrigger
-from airflow.providers.standard.utils.version_references import 
AIRFLOW_V_3_0_PLUS
+from airflow.providers.standard.version_compat import AIRFLOW_V_3_0_PLUS
 from airflow.sensors.base import BaseSensorOperator
 from airflow.utils import timezone
 
diff --git a/providers/src/airflow/providers/standard/triggers/external_task.py 
b/providers/src/airflow/providers/standard/triggers/external_task.py
index ff99caf668d..a54729fa690 100644
--- a/providers/src/airflow/providers/standard/triggers/external_task.py
+++ b/providers/src/airflow/providers/standard/triggers/external_task.py
@@ -25,7 +25,7 @@ from sqlalchemy import func
 
 from airflow.models import DagRun
 from airflow.providers.standard.utils.sensor_helper import _get_count
-from airflow.providers.standard.utils.version_references import 
AIRFLOW_V_3_0_PLUS
+from airflow.providers.standard.version_compat import AIRFLOW_V_3_0_PLUS
 from airflow.triggers.base import BaseTrigger, TriggerEvent
 from airflow.utils.session import NEW_SESSION, provide_session
 
diff --git a/providers/src/airflow/providers/standard/triggers/temporal.py 
b/providers/src/airflow/providers/standard/triggers/temporal.py
index 032af6186d2..12834509b51 100644
--- a/providers/src/airflow/providers/standard/triggers/temporal.py
+++ b/providers/src/airflow/providers/standard/triggers/temporal.py
@@ -24,7 +24,7 @@ from typing import Any
 import pendulum
 
 from airflow.exceptions import AirflowException
-from airflow.providers.standard.utils.version_references import 
AIRFLOW_V_2_10_PLUS
+from airflow.providers.standard.version_compat import AIRFLOW_V_2_10_PLUS
 from airflow.triggers.base import BaseTrigger, TriggerEvent
 from airflow.utils import timezone
 
diff --git 
a/providers/src/airflow/providers/standard/utils/version_references.py 
b/providers/src/airflow/providers/standard/utils/version_references.py
deleted file mode 100644
index 47fc7a1e800..00000000000
--- a/providers/src/airflow/providers/standard/utils/version_references.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-from __future__ import annotations
-
-from packaging.version import Version
-
-from airflow import __version__ as airflow_version
-
-AIRFLOW_VERSION = Version(airflow_version)
-AIRFLOW_V_2_10_PLUS = Version(AIRFLOW_VERSION.base_version) >= 
Version("2.10.0")
-AIRFLOW_V_3_0_PLUS = Version(AIRFLOW_VERSION.base_version) >= Version("3.0.0")
diff --git a/tests_common/test_utils/version_compat.py 
b/providers/src/airflow/providers/standard/version_compat.py
similarity index 77%
copy from tests_common/test_utils/version_compat.py
copy to providers/src/airflow/providers/standard/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/providers/src/airflow/providers/standard/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 
diff --git a/providers/src/airflow/providers/trino/hooks/trino.py 
b/providers/src/airflow/providers/trino/hooks/trino.py
index 129f1288e4d..3e10d21051a 100644
--- a/providers/src/airflow/providers/trino/hooks/trino.py
+++ b/providers/src/airflow/providers/trino/hooks/trino.py
@@ -24,20 +24,16 @@ from pathlib import Path
 from typing import TYPE_CHECKING, Any, TypeVar
 
 import trino
-from packaging.version import Version
 from trino.exceptions import DatabaseError
 from trino.transaction import IsolationLevel
 
-from airflow import __version__ as airflow_version
 from airflow.configuration import conf
 from airflow.exceptions import AirflowException
 from airflow.providers.common.sql.hooks.sql import DbApiHook
+from airflow.providers.trino.version_compat import AIRFLOW_V_3_0_PLUS
 from airflow.utils.helpers import exactly_one
 from airflow.utils.operator_helpers import AIRFLOW_VAR_NAME_FORMAT_MAPPING, 
DEFAULT_FORMAT_PREFIX
 
-AIRFLOW_VERSION = Version(airflow_version)
-AIRFLOW_V_3_0_PLUS = Version(AIRFLOW_VERSION.base_version) >= Version("3.0.0")
-
 if TYPE_CHECKING:
     from airflow.models import Connection
 
diff --git a/tests_common/test_utils/version_compat.py 
b/providers/src/airflow/providers/trino/version_compat.py
similarity index 77%
copy from tests_common/test_utils/version_compat.py
copy to providers/src/airflow/providers/trino/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/providers/src/airflow/providers/trino/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 
diff --git a/providers/tests/amazon/aws/operators/test_redshift_sql.py 
b/providers/tests/amazon/aws/operators/test_redshift_sql.py
index d415f19ed4e..1b124ee2028 100644
--- a/providers/tests/amazon/aws/operators/test_redshift_sql.py
+++ b/providers/tests/amazon/aws/operators/test_redshift_sql.py
@@ -79,10 +79,10 @@ class TestRedshiftSQLOpenLineage:
         ],
     )
     @patch(
-        
"airflow.providers.amazon.aws.hooks.redshift_sql._IS_AIRFLOW_2_10_OR_HIGHER",
+        "airflow.providers.amazon.aws.hooks.redshift_sql.AIRFLOW_V_2_10_PLUS",
         new_callable=PropertyMock,
     )
-    
@patch("airflow.providers.openlineage.utils.utils.IS_AIRFLOW_2_10_OR_HIGHER", 
new_callable=PropertyMock)
+    @patch("airflow.providers.openlineage.utils.utils.AIRFLOW_V_2_10_PLUS", 
new_callable=PropertyMock)
     @patch("airflow.providers.amazon.aws.hooks.base_aws.AwsBaseHook.conn")
     def test_execute_openlineage_events(
         self,
diff --git a/providers/tests/openlineage/extractors/test_base.py 
b/providers/tests/openlineage/extractors/test_base.py
index aa1a2467a83..d2122e418be 100644
--- a/providers/tests/openlineage/extractors/test_base.py
+++ b/providers/tests/openlineage/extractors/test_base.py
@@ -260,7 +260,7 @@ def test_extract_on_failure(task_state, 
is_airflow_2_10_or_higher, should_call_o
     extractor = DefaultExtractor(operator=operator)
 
     with mock.patch(
-        
"airflow.providers.openlineage.extractors.base.IS_AIRFLOW_2_10_OR_HIGHER", 
is_airflow_2_10_or_higher
+        "airflow.providers.openlineage.extractors.base.AIRFLOW_V_2_10_PLUS", 
is_airflow_2_10_or_higher
     ):
         result = extractor.extract_on_complete(task_instance)
 
diff --git a/providers/tests/standard/triggers/test_temporal.py 
b/providers/tests/standard/triggers/test_temporal.py
index 7271d43f5d0..91e27298c50 100644
--- a/providers/tests/standard/triggers/test_temporal.py
+++ b/providers/tests/standard/triggers/test_temporal.py
@@ -24,12 +24,13 @@ import pendulum
 import pytest
 
 from airflow.providers.standard.triggers.temporal import DateTimeTrigger, 
TimeDeltaTrigger
-from airflow.providers.standard.utils.version_references import 
AIRFLOW_V_2_10_PLUS
 from airflow.triggers.base import TriggerEvent
 from airflow.utils import timezone
 from airflow.utils.state import TaskInstanceState
 from airflow.utils.timezone import utcnow
 
+from tests_common.test_utils.version_compat import AIRFLOW_V_2_10_PLUS
+
 
 def test_input_validation():
     """
diff --git a/scripts/ci/pre_commit/check_imports_in_providers.py 
b/scripts/ci/pre_commit/check_imports_in_providers.py
new file mode 100755
index 00000000000..2934b6402ed
--- /dev/null
+++ b/scripts/ci/pre_commit/check_imports_in_providers.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import json
+import os.path
+import subprocess
+import sys
+from pathlib import Path
+
+sys.path.insert(0, str(Path(__file__).parent.resolve()))
+from common_precommit_utils import (
+    AIRFLOW_SOURCES_ROOT_PATH,
+    console,
+    get_provider_dir,
+    get_provider_from_path,
+)
+
+errors_found = False
+
+
+def check_imports(folders_to_check: list[Path]):
+    global errors_found
+    import_tree_str = subprocess.check_output(
+        [
+            "ruff",
+            "analyze",
+            "graph",
+            *[folder_to_check.as_posix() for folder_to_check in 
folders_to_check],
+        ]
+    )
+    import_tree = json.loads(import_tree_str)
+    # Uncomment these if you want to debug strange dependencies and see if 
ruff gets it right
+    # console.print("Dependencies discovered by ruff:")
+    # console.print(import_tree)
+
+    for importing_file in sys.argv[1:]:
+        if not importing_file.startswith("providers/"):
+            console.print(f"[yellow]Skipping non-provider file: 
{importing_file}")
+            continue
+        imported_files = import_tree.get(importing_file, None)
+        if imported_files is None:
+            if importing_file != "providers/src/airflow/providers/__init__.py":
+                # providers/__init__.py should be ignored
+                console.print(f"[red]The file {importing_file} is not 
discovered by ruff analyze!")
+                errors_found = True
+            continue
+        for imported_file in imported_files:
+            if imported_file.endswith("/version_compat.py"):
+                # Note - this will check also imports from other places - not 
only from providers
+                # Which means that import from tests_common, and airflow will 
be also banned
+                common_path = os.path.commonpath([importing_file, 
imported_file])
+                imported_file_parent_dir = 
Path(imported_file).parent.as_posix()
+                if common_path != imported_file_parent_dir:
+                    provider_id = get_provider_from_path(Path(importing_file))
+                    provider_dir = get_provider_dir(provider_id)
+                    console.print(
+                        f"\n[red]Invalid import of `version_compat` module in 
provider {provider_id} in:\n"
+                    )
+                    console.print(f"[yellow]{importing_file}")
+                    console.print(
+                        f"\n[bright_blue]The AIRFLOW_V_X_Y_PLUS import should 
be "
+                        f"from the {provider_id} provider root directory 
({provider_dir}), but it is currently from:"
+                    )
+                    console.print(f"\n[yellow]{imported_file}\n")
+                    console.print(
+                        f"1. Copy `version_compat`.py to 
`{provider_dir}/version_compat.py` if not there.\n"
+                        f"2. Import the version constants you need as:\n\n"
+                        f"[yellow]from 
airflow.providers.{provider_id}.version_compat import ...[/]\n"
+                        f"\n"
+                    )
+                    errors_found = True
+
+
+check_imports([AIRFLOW_SOURCES_ROOT_PATH / "providers" / "src", 
AIRFLOW_SOURCES_ROOT_PATH / "tests_common"])
+
+if errors_found:
+    console.print("\n[red]Errors found in imports![/]\n")
+    sys.exit(1)
+else:
+    console.print("\n[green]All version_compat imports are correct![/]\n")
diff --git a/scripts/ci/pre_commit/common_precommit_utils.py 
b/scripts/ci/pre_commit/common_precommit_utils.py
index b8d29410db4..e6ba1547be0 100644
--- a/scripts/ci/pre_commit/common_precommit_utils.py
+++ b/scripts/ci/pre_commit/common_precommit_utils.py
@@ -231,3 +231,24 @@ def validate_cmd_result(cmd_result, 
include_ci_env_check=False):
             "run `breeze ci-image build --python 3.9` and try again."
         )
     sys.exit(cmd_result.returncode)
+
+
+def get_provider_from_path(file_path: Path) -> str | None:
+    """
+    Get the provider name from the path of the file it belongs to.
+    """
+    for parent in file_path.parents:
+        if (parent / "provider.yaml").exists():
+            for providers_candidate in parent.parents:
+                if providers_candidate.name == "providers":
+                    return 
parent.relative_to(providers_candidate).as_posix().replace("/", ".")
+            else:
+                return None
+    return None
+
+
+def get_provider_dir(provider_id: str) -> Path:
+    """
+    Get the provider directory from the provider =id.
+    """
+    return Path("providers") / "src" / "airflow" / "providers" / 
provider_id.replace(".", os.sep)
diff --git a/tests_common/test_utils/version_compat.py 
b/tests_common/test_utils/version_compat.py
index fd48d6863d3..5c9afb34ac7 100644
--- a/tests_common/test_utils/version_compat.py
+++ b/tests_common/test_utils/version_compat.py
@@ -14,7 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+#
+# NOTE! THIS FILE IS COPIED MANUALLY IN OTHER PROVIDERS DELIBERATELY TO AVOID 
ADDING UNNECESSARY
+# DEPENDENCIES BETWEEN PROVIDERS. IF YOU WANT TO ADD CONDITIONAL CODE IN YOUR 
PROVIDER THAT DEPENDS
+# ON AIRFLOW VERSION, PLEASE COPY THIS FILE TO THE ROOT PACKAGE OF YOUR 
PROVIDER AND IMPORT
+# THOSE CONSTANTS FROM IT RATHER THAN IMPORTING THEM FROM ANOTHER PROVIDER OR 
TEST CODE
+#
 from __future__ import annotations
 
 


Reply via email to