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 a61da3cc87 Add verificationy that provider docs are as expected 
(#35424)
a61da3cc87 is described below

commit a61da3cc8792db9944721874bbc172c2e96b27c0
Author: Jarek Potiuk <[email protected]>
AuthorDate: Sat Nov 4 14:01:51 2023 +0100

    Add verificationy that provider docs are as expected (#35424)
    
    Validate that documentation in provider files is properly added
    and adds missing documentation if not there.
    
    The provider documentation for all community providers follows
    the same structure. This PR adds pre-commit that verifies that
    some common structure for all provider documentation is in place
    and is properly indexed. Since we are adding a lot of providers
    now, it's worth making a common pre-commit that will verify, and
    if needed update and regenerate the content to follow the same
    patterns.
    
    It also turned out that Kubernetes and AWS executors were missing
    and entry for those in provider.yaml file - which made them
    not discoverable via "airflow providers executors" CLI - this is also
    verified now.
    
    List of providers that are contributing their configuration is
    removed from Airflow - instead the documentation points to the
    common "providers" documentation where list of packages and links
    to their configuration are generated automatically.
    
    
https://airflow.apache.org/docs/apache-airflow-providers/core-extensions/configurations.html
---
 .pre-commit-config.yaml                            |   7 +
 STATIC_CODE_CHECKS.rst                             |   2 +
 airflow/providers/amazon/provider.yaml             |   3 +
 airflow/providers/cncf/kubernetes/provider.yaml    |   3 +
 dev/breeze/src/airflow_breeze/pre_commit_ids.py    |   1 +
 docs/apache-airflow/configurations-ref.rst         |  27 ++-
 docs/exts/operators_and_hooks_ref.py               |   4 +-
 docs/exts/templates/configuration.rst.jinja2       |   4 +-
 images/breeze/output-commands-hash.txt             |   2 +-
 images/breeze/output_static-checks.svg             | 112 ++++-----
 .../pre_commit/pre_commit_check_provider_docs.py   | 261 +++++++++++++++++++++
 11 files changed, 355 insertions(+), 71 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index e6b59100bf..640995a1a9 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -972,6 +972,13 @@ repos:
         entry: ./scripts/ci/pre_commit/pre_commit_check_deferrable_default.py
         pass_filenames: false
         files: ^airflow/.*/sensors/.*\.py$|^airflow/.*/operators/.*\.py$
+      - id: check-provider-docs-valid
+        name: Validate provider doc files
+        entry: ./scripts/ci/pre_commit/pre_commit_check_provider_docs.py
+        language: python
+        files: ^airflow/providers/.*/provider\.yaml|^docs/.*
+        additional_dependencies: ['rich>=12.4.4', 'pyyaml', 'jinja2']
+        require_serial: true
         ## ADD MOST PRE-COMMITS ABOVE THAT LINE
         # The below pre-commits are those requiring CI image to be built
       - id: mypy-dev
diff --git a/STATIC_CODE_CHECKS.rst b/STATIC_CODE_CHECKS.rst
index f496b56f16..af235cd2d5 100644
--- a/STATIC_CODE_CHECKS.rst
+++ b/STATIC_CODE_CHECKS.rst
@@ -215,6 +215,8 @@ require Breeze Docker image to be built locally.
 
+-----------------------------------------------------------+--------------------------------------------------------------+---------+
 | check-provide-create-sessions-imports                     | Check 
provide_session and create_session imports             |         |
 
+-----------------------------------------------------------+--------------------------------------------------------------+---------+
+| check-provider-docs-valid                                 | Validate 
provider doc files                                  |         |
++-----------------------------------------------------------+--------------------------------------------------------------+---------+
 | check-provider-yaml-valid                                 | Validate 
provider.yaml files                                 | *       |
 
+-----------------------------------------------------------+--------------------------------------------------------------+---------+
 | check-providers-init-file-missing                         | Provider init 
file is missing                                |         |
diff --git a/airflow/providers/amazon/provider.yaml 
b/airflow/providers/amazon/provider.yaml
index dda844ae71..24aa502403 100644
--- a/airflow/providers/amazon/provider.yaml
+++ b/airflow/providers/amazon/provider.yaml
@@ -894,3 +894,6 @@ config:
         type: boolean
         example: "True"
         default: "True"
+
+executors:
+  - airflow.providers.amazon.aws.executors.ecs.ecs_executor.AwsEcsExecutor
diff --git a/airflow/providers/cncf/kubernetes/provider.yaml 
b/airflow/providers/cncf/kubernetes/provider.yaml
index 185fca30cf..3502302458 100644
--- a/airflow/providers/cncf/kubernetes/provider.yaml
+++ b/airflow/providers/cncf/kubernetes/provider.yaml
@@ -342,3 +342,6 @@ config:
         type: string
         example: ~
         default: ""
+
+executors:
+  - airflow.providers.cncf.kubernetes.kubernetes_executor.KubernetesExecutor
diff --git a/dev/breeze/src/airflow_breeze/pre_commit_ids.py 
b/dev/breeze/src/airflow_breeze/pre_commit_ids.py
index d63651e1a0..8ef922f981 100644
--- a/dev/breeze/src/airflow_breeze/pre_commit_ids.py
+++ b/dev/breeze/src/airflow_breeze/pre_commit_ids.py
@@ -61,6 +61,7 @@ PRE_COMMIT_LIST = [
     "check-persist-credentials-disabled-in-github-workflows",
     "check-pre-commit-information-consistent",
     "check-provide-create-sessions-imports",
+    "check-provider-docs-valid",
     "check-provider-yaml-valid",
     "check-providers-init-file-missing",
     "check-providers-subpackages-init-file-exist",
diff --git a/docs/apache-airflow/configurations-ref.rst 
b/docs/apache-airflow/configurations-ref.rst
index f36b71659c..1648ab1674 100644
--- a/docs/apache-airflow/configurations-ref.rst
+++ b/docs/apache-airflow/configurations-ref.rst
@@ -32,20 +32,21 @@ generated using the secret key has a short expiry time 
though - make sure that t
 that you run airflow components on is synchronized (for example using ntpd) 
otherwise you might get
 "forbidden" errors when the logs are accessed.
 
-Some of the providers have their own configuration options, you will find 
details of their configuration
-in the provider's documentation. The pre-installed providers that you may want 
to configure are:
-
-* :doc:`Configuration Reference for Celery Provider 
<apache-airflow-providers-celery:configurations-ref>`
-* :doc:`Configuration Reference for Apache Hive Provider 
<apache-airflow-providers-apache-hive:configurations-ref>`
-* :doc:`Configuration Reference for CNCF Kubernetes Provider 
<apache-airflow-providers-cncf-kubernetes:configurations-ref>`
-* :doc:`Configuration Reference for SMTP Provider 
<apache-airflow-providers-smtp:configurations-ref>`
-* :doc:`Configuration Reference for IMAP Provider 
<apache-airflow-providers-imap:configurations-ref>`
-* :doc:`Configuration Reference for OpenLineage Provider 
<apache-airflow-providers-openlineage:configurations-ref>`
-* :doc:`Configuration Reference for Elasticsearch Provider 
<apache-airflow-providers-elasticsearch:configurations-ref>`
-* :doc:`Configuration Reference for Amazon Provider 
<apache-airflow-providers-amazon:configurations-ref>`
-* :doc:`Configuration Reference for Yandex Provider 
<apache-airflow-providers-yandex:configurations-ref>`
-
 .. note::
     For more information see :doc:`/howto/set-config`.
 
+
+Provider-specific configuration options
+---------------------------------------
+
+Some of the providers have their own configuration options, you will find 
details of their configuration
+in the provider's documentation.
+
+You can find all the provider configuration in
+:doc:`configurations specific for provider packages 
<apache-airflow-providers:core-extensions/configurations>`
+
+Airflow configuration options
+-----------------------------
+
+
 .. include:: ../exts/includes/sections-and-options.rst
diff --git a/docs/exts/operators_and_hooks_ref.py 
b/docs/exts/operators_and_hooks_ref.py
index 5fc919baaf..e6ed70f259 100644
--- a/docs/exts/operators_and_hooks_ref.py
+++ b/docs/exts/operators_and_hooks_ref.py
@@ -314,7 +314,9 @@ class AuthConfigurations(BaseJinjaReferenceDirective):
         self, *, tags: set[str] | None, header_separator: str = 
DEFAULT_HEADER_SEPARATOR
     ) -> str:
         tabular_data = [
-            provider["package-name"] for provider in load_package_data() if 
provider.get("config") is not None
+            (provider["name"], provider["package-name"])
+            for provider in load_package_data()
+            if provider.get("config") is not None
         ]
         return _render_template(
             "configuration.rst.jinja2", items=tabular_data, 
header_separator=header_separator
diff --git a/docs/exts/templates/configuration.rst.jinja2 
b/docs/exts/templates/configuration.rst.jinja2
index be43b4706c..afe84cc116 100644
--- a/docs/exts/templates/configuration.rst.jinja2
+++ b/docs/exts/templates/configuration.rst.jinja2
@@ -16,6 +16,6 @@
  specific language governing permissions and limitations
  under the License.
 #}
-{%for provider_package_name in items %}
-* :doc:`Configuration for {{ provider_package_name }} <{{ 
provider_package_name }}:configurations-ref>`
+{%for name, provider_package in items %}
+* :doc:`Configuration for {{ name }} ({{ provider_package }})<{{ 
provider_package }}:configurations-ref>`
 {% endfor %}
diff --git a/images/breeze/output-commands-hash.txt 
b/images/breeze/output-commands-hash.txt
index ed6d6340f7..33b24d1067 100644
--- a/images/breeze/output-commands-hash.txt
+++ b/images/breeze/output-commands-hash.txt
@@ -65,7 +65,7 @@ setup:version:be116d90a21c2afe01087f7609774e1e
 setup:f60eda462f5bc70fee369806fedad538
 shell:aa92fe60473e4b5d0f41b5b182c02468
 start-airflow:f09871892c61bc889e6b56791115c923
-static-checks:8ed3127b97b5b56dae600aa4b15d4002
+static-checks:06290ff4d6f24bbda96421385ba29ca2
 testing:db-tests:e08e3f30ddc34d95ae56de5222392b59
 testing:docker-compose-tests:fd154a058082fcfda12eb877a9a89338
 testing:helm-tests:98a9ba6631249762b1633b76a29f4461
diff --git a/images/breeze/output_static-checks.svg 
b/images/breeze/output_static-checks.svg
index 388f02b7e8..3c623b9948 100644
--- a/images/breeze/output_static-checks.svg
+++ b/images/breeze/output_static-checks.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 1904.3999999999999" 
xmlns="http://www.w3.org/2000/svg";>
+<svg class="rich-terminal" viewBox="0 0 1482 1928.8" 
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="1853.3999999999999" />
+      <rect x="0" y="0" width="1463.0" height="1877.8" />
     </clipPath>
     <clipPath id="breeze-static-checks-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -270,9 +270,12 @@
 <clipPath id="breeze-static-checks-line-74">
     <rect x="0" y="1807.1" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="breeze-static-checks-line-75">
+    <rect x="0" y="1831.5" 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="1902.4" 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="1926.8" 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"/>
@@ -307,57 +310,58 @@
 </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-no-relative-imports&#160;|&#160;check-only-new-session-with-provide-session&#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" 
clip-path="url [...]
 </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-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="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-pre-commit-information-consistent&#160;|&#160;check-provide-create-sessions-imports&#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)">check-provider-yaml-valid&#160;|&#160;check-providers-init-file-missing&#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="1451 [...]
-</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-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="654.4" textLength="12.2" 
clip-path="url [...]
-</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-revision-heads-map&#160;|&#160;check-safe-filter-usage-in-html&#160;|&#160;check-setup-order&#160;|&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="678.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-li [...]
-</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-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="703.2" textLen [...]
-</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-system-tests-tocs&#160;|&#160;check-tests-unittest-testcase&#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="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-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="752" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-30) [...]
-</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)">|&#160;compile-www-assets&#160;|&#160;compile-www-assets-dev&#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="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)">create-missing-init-py-files-tests&#160;|&#160;debug-statements&#160;|&#160;detect-private-key&#160;|&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="800.8" textLength="12.2" 
clip-path="url(#bre [...]
-</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)">doctoc&#160;|&#160;end-of-file-fixer&#160;|&#160;fix-encoding-pragma&#160;|&#160;flynt&#160;|&#160;generate-pypi-readme&#160;|</text><text
 class="breeze-static-checks-r5" x="1451.8" y="825.2" textLength="12.2" 
clip-path="url(#breeze-s [...]
-</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)">identity&#160;|&#160;insert-license&#160;|&#160;lint-chart-schema&#160;|&#160;lint-css&#160;|&#160;lint-dockerfile&#160;|&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="849.6" textLength="12.2" [...]
-</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)">lint-helm-chart&#160;|&#160;lint-json-schema&#160;|&#160;lint-markdown&#160;|&#160;lint-openapi&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451 [...]
-</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)">mixed-line-ending&#160;|&#160;mypy-core&#160;|&#160;mypy-dev&#160;|&#160;mypy-docs&#160;|&#160;mypy-providers&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y= [...]
-</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)">pretty-format-json&#160;|&#160;python-no-log-warn&#160;|&#160;replace-bad-characters&#160;|&#160;rst-backticks&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="922.8" textLength="12.2" 
clip-path="url(#breeze-static-chec [...]
-</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;ruff&#160;|&#160;ruff-format&#160;|&#160;shellcheck&#160;|&#160;trailing-whitespace&#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="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)">ts-compile-format-lint-www&#160;|&#160;update-black-version&#160;|&#160;update-breeze-cmd-output&#160;|&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="971.6" textLength="12.2" 
clip-path="url(#breeze-static [...]
-</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)">update-breeze-readme-config-hash&#160;|&#160;update-common-sql-api-stubs&#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="1451.8" y [...]
-</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)">update-er-diagram&#160;|&#160;update-extras&#160;|&#160;update-in-the-wild-to-be-sorted&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1020.4" [...]
-</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)">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="1044.8" textLength="12.2" 
clip-path="url(#breeze-static-c [...]
-</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)">update-local-yml-file&#160;|&#160;update-migration-references&#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="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)">update-providers-dependencies&#160;|&#160;update-spelling-wordlist-to-be-sorted&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1093.6" textLength="12.2" c [...]
-</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)">update-supported-versions&#160;|&#160;update-vendored-in-k8s-json-schema&#160;|&#160;update-version&#160;|</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1118" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-45)"> [...]
-</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)">validate-pyproject&#160;|&#160;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;
 [...]
-</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-r4" x="24.4" y="1166.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-47)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1166.8" textLength="61" 
clip-path="url(#breeze-static-checks-line-47)">-show</text><text 
class="breeze-static-checks-r4" x="97.6" y="1166.8" textLength="195.2" 
clip-path="url(# [...]
-</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-r4" x="24.4" y="1191.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-48)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1191.2" textLength="134.2" 
clip-path="url(#breeze-static-checks-line-48)">-initialize</text><text 
class="breeze-static-checks-r4" x="170.8" y="1191.2" textLength="146.4" clip-p 
[...]
-</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-r4" x="24.4" y="1215.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-49)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1215.6" textLength="48.8" 
clip-path="url(#breeze-static-checks-line-49)">-max</text><text 
class="breeze-static-checks-r4" x="85.4" y="1215.6" textLength="292.8" 
clip-path="url( [...]
-</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="854" 
clip-path="url(#breeze-static-checks-line-50)">(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;&#160;&#
 [...]
-</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-r5" x="451.4" y="1264.4" textLength="854" 
clip-path="url(#breeze-static-checks-line-51)">[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="1288.8" 
textLength="1464" 
clip-path="url(#breeze-static-checks-line-52)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="1288.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-52)">
-</text><text class="breeze-static-checks-r5" x="0" y="1313.2" 
textLength="24.4" clip-path="url(#breeze-static-checks-line-53)">╭─</text><text 
class="breeze-static-checks-r5" x="24.4" y="1313.2" textLength="463.6" 
clip-path="url(#breeze-static-checks-line-53)">&#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="1313.2" textLength="951.6" 
clip-path="url(#breeze-static-checks-line-53)">──────────────────────── [...]
-</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-r4" x="24.4" y="1337.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-54)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1337.6" textLength="61" 
clip-path="url(#breeze-static-checks-line-54)">-file</text><text 
class="breeze-static-checks-r6" x="256.2" y="1337.6" textLength="24.4" 
clip-path="url(# [...]
-</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-r4" x="24.4" y="1362" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-55)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1362" textLength="48.8" 
clip-path="url(#breeze-static-checks-line-55)">-all</text><text 
class="breeze-static-checks-r4" x="85.4" y="1362" textLength="73.2" 
clip-path="url(#breeze-s [...]
-</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-r4" x="24.4" y="1386.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-56)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1386.4" textLength="85.4" 
clip-path="url(#breeze-static-checks-line-56)">-commit</text><text 
class="breeze-static-checks-r4" x="122" y="1386.4" textLength="48.8" 
clip-path="url [...]
-</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-r1" x="305" y="1410.8" textLength="183" 
clip-path="url(#breeze-static-checks-line-57)">exclusive&#160;with&#160;</text><text
 class="breeze-static-checks-r4" x="488" y="1410.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-57)">-</text><text 
class="breeze-static-checks-r4" x="500.2" y="1410.8" textLength="61" [...]
-</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="305" y="1435.2" textLength="1134.6" 
clip-path="url(#breeze-static-checks-line-58)">(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="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="12.2" 
clip-path="url(#breeze-static-checks-line-59)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1459.6" textLength="61" 
clip-path="url(#breeze-static-checks-line-59)">-last</text><text 
class="breeze-static-checks-r4" x="97.6" y="1459.6" textLength="85.4" 
clip-path="url(#b [...]
-</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="12.2" 
clip-path="url(#breeze-static-checks-line-60)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1484" textLength="61" 
clip-path="url(#breeze-static-checks-line-60)">-only</text><text 
class="breeze-static-checks-r4" x="97.6" y="1484" textLength="134.2" 
clip-path="url(#breeze-s [...]
-</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-r1" x="305" y="1508.4" textLength="1134.6" 
clip-path="url(#breeze-static-checks-line-61)">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="1532.8" 
textLength="1464" 
clip-path="url(#breeze-static-checks-line-62)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="1532.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-62)">
-</text><text class="breeze-static-checks-r5" x="0" y="1557.2" 
textLength="24.4" clip-path="url(#breeze-static-checks-line-63)">╭─</text><text 
class="breeze-static-checks-r5" x="24.4" y="1557.2" textLength="463.6" 
clip-path="url(#breeze-static-checks-line-63)">&#160;Building&#160;image&#160;before&#160;running&#160;checks&#160;</text><text
 class="breeze-static-checks-r5" x="488" y="1557.2" textLength="951.6" 
clip-path="url(#breeze-static-checks-line-63)">──────────────────────────────────
 [...]
-</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-r4" x="24.4" y="1581.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-64)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1581.6" textLength="61" 
clip-path="url(#breeze-static-checks-line-64)">-skip</text><text 
class="breeze-static-checks-r4" x="97.6" y="1581.6" textLength="146.4" 
clip-path="url(# [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1606" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-65)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1606" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-65)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1606" textLength="73.2" 
clip-path="url(#breeze-static-checks-line-65)">-force</text><text 
class="breeze-static-checks-r4" x="109.8" y="1606" textLength="73.2" 
clip-path="url(#breez [...]
-</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="12.2" 
clip-path="url(#breeze-static-checks-line-66)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1630.4" textLength="73.2" 
clip-path="url(#breeze-static-checks-line-66)">-image</text><text 
class="breeze-static-checks-r4" x="109.8" y="1630.4" textLength="48.8" 
clip-path="ur [...]
-</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-r5" x="329.4" y="1654.8" textLength="963.8" 
clip-path="url(#breeze-static-checks-line-67)">[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="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="12.2" 
clip-path="url(#breeze-static-checks-line-68)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1679.2" textLength="85.4" 
clip-path="url(#breeze-static-checks-line-68)">-github</text><text 
class="breeze-static-checks-r4" x="122" y="1679.2" textLength="134.2" 
clip-path="ur [...]
-</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="12.2" 
clip-path="url(#breeze-static-checks-line-69)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1703.6" textLength="97.6" 
clip-path="url(#breeze-static-checks-line-69)">-builder</text><text 
class="breeze-static-checks-r1" x="329.4" y="1703.6" textLength="756.4" 
clip-path= [...]
-</text><text class="breeze-static-checks-r5" x="0" y="1728" textLength="1464" 
clip-path="url(#breeze-static-checks-line-70)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="1728" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-70)">
-</text><text class="breeze-static-checks-r5" x="0" y="1752.4" 
textLength="24.4" clip-path="url(#breeze-static-checks-line-71)">╭─</text><text 
class="breeze-static-checks-r5" x="24.4" y="1752.4" textLength="195.2" 
clip-path="url(#breeze-static-checks-line-71)">&#160;Common&#160;options&#160;</text><text
 class="breeze-static-checks-r5" x="219.6" y="1752.4" textLength="1220" 
clip-path="url(#breeze-static-checks-line-71)">──────────────────────────────────────────────────────────────────────
 [...]
-</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="12.2" 
clip-path="url(#breeze-static-checks-line-72)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1776.8" textLength="97.6" 
clip-path="url(#breeze-static-checks-line-72)">-verbose</text><text 
class="breeze-static-checks-r6" x="158.6" y="1776.8" textLength="24.4" 
clip-path=" [...]
-</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="12.2" 
clip-path="url(#breeze-static-checks-line-73)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1801.2" textLength="48.8" 
clip-path="url(#breeze-static-checks-line-73)">-dry</text><text 
class="breeze-static-checks-r4" x="85.4" y="1801.2" textLength="48.8" 
clip-path="url(# [...]
-</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-r4" x="24.4" y="1825.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-74)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1825.6" textLength="61" 
clip-path="url(#breeze-static-checks-line-74)">-help</text><text 
class="breeze-static-checks-r6" x="158.6" y="1825.6" textLength="24.4" 
clip-path="url(# [...]
-</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="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-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="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-providers-init-file-missing&#160;|&#160;check-providers-subpackages-init-file-exist&#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-pydevd-left-in-code&#160;|&#160;check-revision-heads-map&#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;</t
 [...]
+</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-safe-filter-usage-in-html&#160;|&#160;check-setup-order&#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="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-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="727.6" textLen [...]
+</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-system-tests-tocs&#160;|&#160;check-tests-unittest-testcase&#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="br [...]
+</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-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="776.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-li [...]
+</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)">|&#160;compile-www-assets&#160;|&#160;compile-www-assets-dev&#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)">create-missing-init-py-files-tests&#160;|&#160;debug-statements&#160;|&#160;detect-private-key&#160;|&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="825.2" textLength="12.2" 
clip-path="url(#bre [...]
+</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)">doctoc&#160;|&#160;end-of-file-fixer&#160;|&#160;fix-encoding-pragma&#160;|&#160;flynt&#160;|&#160;generate-pypi-readme&#160;|</text><text
 class="breeze-static-checks-r5" x="1451.8" y="849.6" textLength="12.2" 
clip-path="url(#breeze-s [...]
+</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)">identity&#160;|&#160;insert-license&#160;|&#160;lint-chart-schema&#160;|&#160;lint-css&#160;|&#160;lint-dockerfile&#160;|&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="874" textLength="12.2" clip- 
[...]
+</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)">lint-helm-chart&#160;|&#160;lint-json-schema&#160;|&#160;lint-markdown&#160;|&#160;lint-openapi&#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="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)">mixed-line-ending&#160;|&#160;mypy-core&#160;|&#160;mypy-dev&#160;|&#160;mypy-docs&#160;|&#160;mypy-providers&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y= [...]
+</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)">pretty-format-json&#160;|&#160;python-no-log-warn&#160;|&#160;replace-bad-characters&#160;|&#160;rst-backticks&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="947.2" textLength="12.2" 
clip-path="url(#breeze-static-chec [...]
+</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;ruff&#160;|&#160;ruff-format&#160;|&#160;shellcheck&#160;|&#160;trailing-whitespace&#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="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)">ts-compile-format-lint-www&#160;|&#160;update-black-version&#160;|&#160;update-breeze-cmd-output&#160;|&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="996" textLength="12.2" 
clip-path="url(#breeze-static-check [...]
+</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)">update-breeze-readme-config-hash&#160;|&#160;update-common-sql-api-stubs&#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="145 [...]
+</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)">update-er-diagram&#160;|&#160;update-extras&#160;|&#160;update-in-the-wild-to-be-sorted&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1044.8" [...]
+</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)">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="1069.2" textLength="12.2" 
clip-path="url(#breeze-static-c [...]
+</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)">update-local-yml-file&#160;|&#160;update-migration-references&#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="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)">update-providers-dependencies&#160;|&#160;update-spelling-wordlist-to-be-sorted&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1118" textLength="12.2" clip-pa 
[...]
+</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)">update-supported-versions&#160;|&#160;update-vendored-in-k8s-json-schema&#160;|&#160;update-version&#160;|</text><text
 class="breeze-static-checks-r5" x="1451.8" y="1142.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line [...]
+</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)">validate-pyproject&#160;|&#160;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;
 [...]
+</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-r4" x="24.4" y="1191.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-48)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1191.2" textLength="61" 
clip-path="url(#breeze-static-checks-line-48)">-show</text><text 
class="breeze-static-checks-r4" x="97.6" y="1191.2" textLength="195.2" 
clip-path="url(# [...]
+</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-r4" x="24.4" y="1215.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-49)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1215.6" textLength="134.2" 
clip-path="url(#breeze-static-checks-line-49)">-initialize</text><text 
class="breeze-static-checks-r4" x="170.8" y="1215.6" textLength="146.4" clip-p 
[...]
+</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-r4" x="24.4" y="1240" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-50)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1240" textLength="48.8" 
clip-path="url(#breeze-static-checks-line-50)">-max</text><text 
class="breeze-static-checks-r4" x="85.4" y="1240" textLength="292.8" 
clip-path="url(#breeze- [...]
+</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="854" 
clip-path="url(#breeze-static-checks-line-51)">(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="1288.8" 
textLength="12.2" clip-path="url(#breeze-static-checks-line-52)">│</text><text 
class="breeze-static-checks-r5" x="451.4" y="1288.8" textLength="854" 
clip-path="url(#breeze-static-checks-line-52)">[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="1313.2" 
textLength="1464" 
clip-path="url(#breeze-static-checks-line-53)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="1313.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-53)">
+</text><text class="breeze-static-checks-r5" x="0" y="1337.6" 
textLength="24.4" clip-path="url(#breeze-static-checks-line-54)">╭─</text><text 
class="breeze-static-checks-r5" x="24.4" y="1337.6" textLength="463.6" 
clip-path="url(#breeze-static-checks-line-54)">&#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="1337.6" textLength="951.6" 
clip-path="url(#breeze-static-checks-line-54)">──────────────────────── [...]
+</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-r4" x="24.4" y="1362" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-55)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1362" textLength="61" 
clip-path="url(#breeze-static-checks-line-55)">-file</text><text 
class="breeze-static-checks-r6" x="256.2" y="1362" textLength="24.4" 
clip-path="url(#breeze-s [...]
+</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-r4" x="24.4" y="1386.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-56)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1386.4" textLength="48.8" 
clip-path="url(#breeze-static-checks-line-56)">-all</text><text 
class="breeze-static-checks-r4" x="85.4" y="1386.4" textLength="73.2" 
clip-path="url(# [...]
+</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-r4" x="24.4" y="1410.8" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-57)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1410.8" textLength="85.4" 
clip-path="url(#breeze-static-checks-line-57)">-commit</text><text 
class="breeze-static-checks-r4" x="122" y="1410.8" textLength="48.8" 
clip-path="url [...]
+</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-r1" x="305" y="1435.2" textLength="183" 
clip-path="url(#breeze-static-checks-line-58)">exclusive&#160;with&#160;</text><text
 class="breeze-static-checks-r4" x="488" y="1435.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-58)">-</text><text 
class="breeze-static-checks-r4" x="500.2" y="1435.2" textLength="61" [...]
+</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="305" y="1459.6" textLength="1134.6" 
clip-path="url(#breeze-static-checks-line-59)">(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="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="12.2" 
clip-path="url(#breeze-static-checks-line-60)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1484" textLength="61" 
clip-path="url(#breeze-static-checks-line-60)">-last</text><text 
class="breeze-static-checks-r4" x="97.6" y="1484" textLength="85.4" 
clip-path="url(#breeze-st [...]
+</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="12.2" 
clip-path="url(#breeze-static-checks-line-61)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1508.4" textLength="61" 
clip-path="url(#breeze-static-checks-line-61)">-only</text><text 
class="breeze-static-checks-r4" x="97.6" y="1508.4" textLength="134.2" 
clip-path="url(# [...]
+</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-r1" x="305" y="1532.8" textLength="1134.6" 
clip-path="url(#breeze-static-checks-line-62)">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="1557.2" 
textLength="1464" 
clip-path="url(#breeze-static-checks-line-63)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="1557.2" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-63)">
+</text><text class="breeze-static-checks-r5" x="0" y="1581.6" 
textLength="24.4" clip-path="url(#breeze-static-checks-line-64)">╭─</text><text 
class="breeze-static-checks-r5" x="24.4" y="1581.6" textLength="463.6" 
clip-path="url(#breeze-static-checks-line-64)">&#160;Building&#160;image&#160;before&#160;running&#160;checks&#160;</text><text
 class="breeze-static-checks-r5" x="488" y="1581.6" textLength="951.6" 
clip-path="url(#breeze-static-checks-line-64)">──────────────────────────────────
 [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1606" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-65)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1606" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-65)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1606" textLength="61" 
clip-path="url(#breeze-static-checks-line-65)">-skip</text><text 
class="breeze-static-checks-r4" x="97.6" y="1606" textLength="146.4" 
clip-path="url(#breeze-s [...]
+</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="12.2" 
clip-path="url(#breeze-static-checks-line-66)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1630.4" textLength="73.2" 
clip-path="url(#breeze-static-checks-line-66)">-force</text><text 
class="breeze-static-checks-r4" x="109.8" y="1630.4" textLength="73.2" 
clip-path="ur [...]
+</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="12.2" 
clip-path="url(#breeze-static-checks-line-67)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1654.8" textLength="73.2" 
clip-path="url(#breeze-static-checks-line-67)">-image</text><text 
class="breeze-static-checks-r4" x="109.8" y="1654.8" textLength="48.8" 
clip-path="ur [...]
+</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-r5" x="329.4" y="1679.2" textLength="963.8" 
clip-path="url(#breeze-static-checks-line-68)">[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="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="12.2" 
clip-path="url(#breeze-static-checks-line-69)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1703.6" textLength="85.4" 
clip-path="url(#breeze-static-checks-line-69)">-github</text><text 
class="breeze-static-checks-r4" x="122" y="1703.6" textLength="134.2" 
clip-path="ur [...]
+</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-r4" x="24.4" y="1728" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-70)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1728" textLength="97.6" 
clip-path="url(#breeze-static-checks-line-70)">-builder</text><text 
class="breeze-static-checks-r1" x="329.4" y="1728" textLength="756.4" 
clip-path="url(#br [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1752.4" 
textLength="1464" 
clip-path="url(#breeze-static-checks-line-71)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="1752.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-71)">
+</text><text class="breeze-static-checks-r5" x="0" y="1776.8" 
textLength="24.4" clip-path="url(#breeze-static-checks-line-72)">╭─</text><text 
class="breeze-static-checks-r5" x="24.4" y="1776.8" textLength="195.2" 
clip-path="url(#breeze-static-checks-line-72)">&#160;Common&#160;options&#160;</text><text
 class="breeze-static-checks-r5" x="219.6" y="1776.8" textLength="1220" 
clip-path="url(#breeze-static-checks-line-72)">──────────────────────────────────────────────────────────────────────
 [...]
+</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="12.2" 
clip-path="url(#breeze-static-checks-line-73)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1801.2" textLength="97.6" 
clip-path="url(#breeze-static-checks-line-73)">-verbose</text><text 
class="breeze-static-checks-r6" x="158.6" y="1801.2" textLength="24.4" 
clip-path=" [...]
+</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-r4" x="24.4" y="1825.6" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-74)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1825.6" textLength="48.8" 
clip-path="url(#breeze-static-checks-line-74)">-dry</text><text 
class="breeze-static-checks-r4" x="85.4" y="1825.6" textLength="48.8" 
clip-path="url(# [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1850" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-75)">│</text><text 
class="breeze-static-checks-r4" x="24.4" y="1850" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-75)">-</text><text 
class="breeze-static-checks-r4" x="36.6" y="1850" textLength="61" 
clip-path="url(#breeze-static-checks-line-75)">-help</text><text 
class="breeze-static-checks-r6" x="158.6" y="1850" textLength="24.4" 
clip-path="url(#breeze-s [...]
+</text><text class="breeze-static-checks-r5" x="0" y="1874.4" 
textLength="1464" 
clip-path="url(#breeze-static-checks-line-76)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-static-checks-r1" x="1464" y="1874.4" textLength="12.2" 
clip-path="url(#breeze-static-checks-line-76)">
 </text>
     </g>
     </g>
diff --git a/scripts/ci/pre_commit/pre_commit_check_provider_docs.py 
b/scripts/ci/pre_commit/pre_commit_check_provider_docs.py
new file mode 100755
index 0000000000..7814581100
--- /dev/null
+++ b/scripts/ci/pre_commit/pre_commit_check_provider_docs.py
@@ -0,0 +1,261 @@
+#!/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 os
+import sys
+from collections import defaultdict
+from pathlib import Path
+
+import yaml
+from jinja2 import BaseLoader, Environment
+from rich.console import Console
+
+console = Console(color_system="standard", width=200)
+
+AIRFLOW_PROVIDERS_IMPORT_PREFIX = "airflow.providers."
+
+AIRFLOW_SOURCES_ROOT = Path(__file__).parents[3].resolve()
+
+AIRFLOW_PROVIDERS_DIR = AIRFLOW_SOURCES_ROOT / "airflow" / "providers"
+AIRFLOW_DOC_FILES = AIRFLOW_SOURCES_ROOT / "docs"
+AIRFLOW_DOC_AIRFLOW_BASE_FOLDER = AIRFLOW_DOC_FILES / "apache-airflow"
+
+sys.path.insert(0, str(AIRFLOW_SOURCES_ROOT))  # make sure setup is imported 
from Airflow
+
+warnings: list[str] = []
+errors: list[str] = []
+
+suspended_paths: list[str] = []
+
+ALL_DEPENDENCIES: dict[str, dict[str, list[str]]] = defaultdict(lambda: 
defaultdict(list))
+
+ALL_PROVIDERS: dict[str, dict[str, dict]] = defaultdict(lambda: defaultdict())
+
+# Allow AST to parse the files.
+sys.path.append(str(AIRFLOW_SOURCES_ROOT))
+
+LICENCE_CONTENT_RST = """
+ .. 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.
+"""
+
+CONFIGURATION_CONTENT_RST = """
+.. include:: ../exts/includes/providers-configurations-ref.rst
+"""
+
+SECURITY_CONTENT_RST = """
+.. include:: ../exts/includes/security.rst
+"""
+
+INSTALLING_PROVIDERS_FROM_SOURCES_CONTENT_RST = """
+.. include:: ../exts/includes/installing-providers-from-sources.rst
+"""
+
+CHANGELOG_CONTENT_RST = """
+.. include:: ../../airflow/providers/{{provider_id | replace ('.', 
'/')}}/CHANGELOG.rst
+"""
+
+COMMIT_CONTENT_RST = """
+ .. THIS FILE IS UPDATED AUTOMATICALLY_AT_RELEASE_TIME
+"""
+
+
+def find_all_providers():
+    for provider_file in AIRFLOW_PROVIDERS_DIR.rglob("provider.yaml"):
+        provider_name = 
str(provider_file.parent.relative_to(AIRFLOW_PROVIDERS_DIR)).replace(os.sep, 
".")
+        provider_info = yaml.safe_load(provider_file.read_text())
+        if not provider_info["suspended"]:
+            ALL_PROVIDERS[provider_name] = provider_info
+
+
+find_all_providers()
+
+fail_pre_commit = False
+
+
+def process_content_to_write(content: str) -> str:
+    """Allow content to be defined with leading empty lines and strip/add 
EOL"""
+    if not content:
+        return content
+    content_lines = content.splitlines()
+    if content_lines and content_lines[0] == "":
+        content_lines = content_lines[1:]
+    content_to_write = "\n".join(content_lines) + "\n"
+    return content_to_write
+
+
+def check_provider_doc_exists_and_in_index(
+    *,
+    provider_id: str,
+    index_link: str,
+    file_name: str,
+    generated_content: str = "",
+    missing_ok: bool = False,
+    check_content: bool = True,
+) -> None:
+    global fail_pre_commit
+    provider_docs_file = get_provider_doc_folder(provider_id)
+    file_path = provider_docs_file / file_name
+    index_file = provider_docs_file / "index.rst"
+    content_to_write = process_content_to_write(generated_content)
+    regenerate_file = False
+    if file_path.exists():
+        if check_content and not generated_content:
+            if file_path.read_text() != content_to_write:
+                console.print()
+                console.print(f"[yellow]Content of the file will be 
regenerated: [/]{file_path}")
+                console.print()
+                regenerate_file = True
+    else:
+        if missing_ok:
+            # Fine - we do not check anything else
+            return
+        if not generated_content:
+            console.print()
+            console.print(f"[yellow]Missing file: [/]{file_path}")
+            console.print("[bright_blue]Please create the file looking at 
other providers as example [/]")
+            console.print()
+        else:
+            regenerate_file = True
+    if regenerate_file:
+        fail_pre_commit = True
+        file_path.write_text(content_to_write)
+        console.print()
+        console.print(f"[yellow]Content updated in file: [/]{file_path}")
+        console.print()
+    if index_link not in index_file.read_text():
+        fail_pre_commit = True
+        console.print()
+        console.print(
+            f"[red]ERROR! Missing index link![/]\n"
+            f"The index file: {index_file} should have this link:\n"
+            f"{index_link}\n\n"
+            f"[bright_blue]Please add the entry in the index!"
+        )
+        console.print()
+
+
+def check_documentation_link_exists(link: str, doc_file_name: str):
+    global fail_pre_commit
+    docs_file = AIRFLOW_DOC_AIRFLOW_BASE_FOLDER / doc_file_name
+    if link not in docs_file.read_text():
+        fail_pre_commit = True
+        console.print()
+        console.print(
+            f"[red]ERROR! The {docs_file} does not contain:\n:[/]" f"{link}\n" 
f"[bright_blue]Please add it!"
+        )
+        console.print()
+
+
+def get_provider_doc_folder(provider_id: str) -> Path:
+    return AIRFLOW_DOC_FILES / 
f"apache-airflow-providers-{provider_id.replace('.', '-')}"
+
+
+def has_executor_package_defined(provider_id: str):
+    provider_sources = AIRFLOW_PROVIDERS_DIR / provider_id.replace(".", "/")
+    for executors_folder in provider_sources.rglob("executors"):
+        if executors_folder.is_dir() and (executors_folder / 
"__init__.py").is_file():
+            return True
+    return False
+
+
+JINJA_LOADER = Environment(loader=BaseLoader())
+
+for provider_id, provider_info in ALL_PROVIDERS.items():
+    provider_docs_folder = get_provider_doc_folder(provider_id)
+    if not provider_docs_folder.exists():
+        provider_docs_folder.mkdir(parents=True)
+
+    check_provider_doc_exists_and_in_index(
+        provider_id=provider_id,
+        index_link="Detailed list of commits <commits>",
+        file_name="commits.rst",
+        generated_content=LICENCE_CONTENT_RST + COMMIT_CONTENT_RST,
+        # Only create commit content if it is missing, otherwise leave what is 
there
+        check_content=False,
+    )
+
+    check_provider_doc_exists_and_in_index(
+        provider_id=provider_id,
+        index_link="Security <security>",
+        file_name="security.rst",
+        generated_content=LICENCE_CONTENT_RST + SECURITY_CONTENT_RST,
+    )
+
+    check_provider_doc_exists_and_in_index(
+        provider_id=provider_id,
+        index_link="Installing from sources 
<installing-providers-from-sources>",
+        file_name="installing-providers-from-sources.rst",
+        generated_content=LICENCE_CONTENT_RST + 
INSTALLING_PROVIDERS_FROM_SOURCES_CONTENT_RST,
+    )
+
+    check_provider_doc_exists_and_in_index(
+        provider_id=provider_id,
+        index_link="Changelog <changelog>",
+        file_name="changelog.rst",
+        generated_content=LICENCE_CONTENT_RST
+        + 
JINJA_LOADER.from_string(CHANGELOG_CONTENT_RST).render(provider_id=provider_id),
+    )
+
+    if has_executor_package_defined(provider_id) and not 
provider_info.get("executors"):
+        provider_yaml = AIRFLOW_PROVIDERS_DIR / provider_id.replace(".", "/") 
/ "provider.yaml"
+        console.print()
+        console.print(
+            f"[red]ERROR! The {provider_id} provider has executor package but "
+            f"does not have `executors` defined in {provider_yaml}."
+        )
+        console.print(f"\nPlease add executor class to `executors` array in 
{provider_yaml}")
+        fail_pre_commit = True
+
+    if provider_info.get("executors"):
+        check_provider_doc_exists_and_in_index(
+            provider_id=provider_id,
+            index_link="CLI <cli-ref>",
+            file_name="cli-ref.rst",
+            missing_ok=True,
+            check_content=False,
+        )
+        if (get_provider_doc_folder(provider_id) / "cli-ref.rst").exists():
+            check_documentation_link_exists(
+                link=f"and related CLI commands: 
:doc:`{get_provider_doc_folder(provider_id).name}:cli-ref`",
+                doc_file_name="cli-and-env-variables-ref.rst",
+            )
+    if provider_info.get("config"):
+        check_provider_doc_exists_and_in_index(
+            provider_id=provider_id,
+            index_link="Configuration <configurations-ref>",
+            file_name="configurations-ref.rst",
+            generated_content=LICENCE_CONTENT_RST + CONFIGURATION_CONTENT_RST,
+        )
+if fail_pre_commit:
+    sys.exit(1)

Reply via email to