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: 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: 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 | check-only-new-session-with-provide-session |        </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 |                         </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 | check-provide-create-sessions-imports |</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 | check-providers-init-file-missing |                  </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 | check-pydevd-left-in-code |        </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 | check-safe-filter-usage-in-html | check-setup-order | </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 | check-system-tests-present |             </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 | check-tests-unittest-testcase |                        </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 | check-usage-of-re2-over-re | check-xml | 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)">| compile-www-assets | compile-www-assets-dev |                            
[...]
-</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 | debug-statements | detect-private-key |     </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 | end-of-file-fixer | fix-encoding-pragma | flynt | generate-pypi-readme |</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 | insert-license | lint-chart-schema | lint-css | lint-dockerfile |     </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 | lint-json-schema | lint-markdown | lint-openapi |              </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 | mypy-core | mypy-dev | mypy-docs | mypy-providers |          </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 | python-no-log-warn | replace-bad-characters | rst-backticks </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)">| ruff | ruff-format | shellcheck | trailing-whitespace |                       
[...]
-</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 | update-black-version | update-breeze-cmd-output |   </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 | update-common-sql-api-stubs |                 </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 | update-extras | update-in-the-wild-to-be-sorted |            </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 | update-installed-providers-to-be-sorted |    </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 | update-migration-references |                           &#
[...]
-</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 | update-spelling-wordlist-to-be-sorted |          </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 | update-vendored-in-k8s-json-schema | update-version |</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 | yamllint)                                
[...]
-</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 RANGE)                                    &#
[...]
-</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: 3; 1<=x<=10]                                
[...]
-</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)"> Selecting files to run the checks on </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 with </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)                                      
[...]
-</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 and HEAD of your branch.                             
[...]
-</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)"> Building image before running checks </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: latest]                                   
[...]
-</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)"> Common options </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 | check-provider-yaml-valid |                          </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 | check-providers-subpackages-init-file-exist |</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 | check-revision-heads-map |                           </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 | check-setup-order |                           
[...]
+</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 | check-system-tests-present |             </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 | check-tests-unittest-testcase |                        </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 | check-usage-of-re2-over-re | check-xml | 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)">| compile-www-assets | compile-www-assets-dev |                            
[...]
+</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 | debug-statements | detect-private-key |     </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 | end-of-file-fixer | fix-encoding-pragma | flynt | generate-pypi-readme |</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 | insert-license | lint-chart-schema | lint-css | lint-dockerfile |     </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 | lint-json-schema | lint-markdown | lint-openapi |              </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 | mypy-core | mypy-dev | mypy-docs | mypy-providers |          </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 | python-no-log-warn | replace-bad-characters | rst-backticks </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)">| ruff | ruff-format | shellcheck | trailing-whitespace |                       
[...]
+</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 | update-black-version | update-breeze-cmd-output |   </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 | update-common-sql-api-stubs |                 </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 | update-extras | update-in-the-wild-to-be-sorted |            </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 | update-installed-providers-to-be-sorted |    </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 | update-migration-references |                           &#
[...]
+</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 | update-spelling-wordlist-to-be-sorted |          </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 | update-vendored-in-k8s-json-schema | update-version |</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 | yamllint)                                
[...]
+</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 RANGE)                                   
[...]
+</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: 3; 1<=x<=10]                                
[...]
+</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)"> Selecting files to run the checks on </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 with </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)                                      
[...]
+</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 and HEAD of your branch.                             
[...]
+</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)"> Building image before running checks </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: latest]                                   
[...]
+</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)"> Common options </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)