mirror of
https://github.com/apache/airflow.git
synced 2026-11-04 07:12:48 +00:00
Stop parallel prek hooks racing on __pycache__ cleanup (#73823)
* Stop parallel prek hooks racing on __pycache__ cleanup prek runs hooks in parallel and every breeze invocation removes all __pycache__ directories in the checkout on start-up. Any other hook process importing from the source tree (breeze itself, prek hook scripts, local mypy runs) can write a fresh .pyc between rmtree emptying a directory and removing it, which fails the breeze hook with "OSError: [Errno 39] Directory not empty" - a flaky Static checks failure in CI. Redirecting bytecode of every hook into a hidden, gitignored .build/ directory keeps the source tree free of new .pyc files while hooks run, and a new check keeps future hooks from reintroducing the race. The cleanup additionally tolerates ENOTEMPTY for writers prek does not control, such as an IDE. Generated-by: Claude Opus 5 * Set PYTHONPYCACHEPREFIX on the hooks added since the branch was cut Eight hooks that landed on main after this branch was created did not redirect their bytecode, so the new check-prek-hooks-pycache-prefix hook failed after the rebase. Generated-by: Claude Opus 5 * Update scripts/ci/prek/check_prek_hooks_pycache_prefix.py Co-authored-by: Wei Lee <hello@wei-lee.me> --------- Co-authored-by: Wei Lee <hello@wei-lee.me>
This commit is contained in:
1 parent
89ce7a4ff7
commit
0cde487d42
42 files changed
+789
-3
No files matched your search
+321
-3
File diff suppressed because it is too large.
Load diff
@@ -26,12 +26,16 @@ repos:
|
||||
hooks:
|
||||
- id: check-first-limit
|
||||
name: Check single-row lookups have an explicit limit
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_first_limit.py
|
||||
language: python
|
||||
files: ^src/airflow/.*\.py$
|
||||
pass_filenames: true
|
||||
- id: check-airflow-k8s-not-used
|
||||
name: Check airflow.kubernetes imports are not used
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
files: ^src/airflow/.*\.py$
|
||||
require_serial: true
|
||||
@@ -41,6 +45,8 @@ repos:
|
||||
--message "You should only import kubernetes code from `airflow.providers.cncf.kubernetes`."
|
||||
- id: check-common-compat-used-for-openlineage
|
||||
name: Check common.compat is used for OL deprecated classes
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
files: ^src/airflow/.*\.py$
|
||||
require_serial: true
|
||||
@@ -50,6 +56,8 @@ repos:
|
||||
--message "You should import from `airflow.providers.common.compat.openlineage.facet` instead."
|
||||
- id: check-cncf-k8s-only-for-executors
|
||||
name: Check cncf.kubernetes imports used for executors only
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
files: ^src/airflow/.*\.py$
|
||||
require_serial: true
|
||||
@@ -66,12 +74,16 @@ repos:
|
||||
"Only few k8s executors exceptions are allowed to use `airflow.providers.cncf.kubernetes`."
|
||||
- id: check-extra-packages-references
|
||||
name: Checks setup extra packages
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: Checks if extras defined in hatch_build.py are listed in extra-packages-ref.rst file
|
||||
language: python
|
||||
files: ^docs/extra-packages-ref\.rst$|^hatch_build\.py$
|
||||
pass_filenames: false
|
||||
entry: ../scripts/ci/prek/check_extra_packages_ref.py
|
||||
- id: check-no-providers-in-core-examples
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: pygrep
|
||||
name: No providers imports in core example DAGs
|
||||
description: The core example DAGs have no dependencies other than standard provider or core Airflow
|
||||
@@ -80,6 +92,8 @@ repos:
|
||||
files: ^src/airflow/example_dags/.*\.py$
|
||||
- id: check-only-new-session-with-provide-session
|
||||
name: Check NEW_SESSION is only used with @provide_session
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/new_session_in_provide_session.py
|
||||
pass_filenames: true
|
||||
@@ -87,18 +101,24 @@ repos:
|
||||
exclude: ^src/airflow/serialization/pydantic/.*
|
||||
- id: check-base-operator-partial-arguments
|
||||
name: Check BaseOperator and partial() arguments
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/check_base_operator_partial_arguments.py
|
||||
pass_filenames: false
|
||||
files: ^src/airflow/models/(?:base|mapped)operator\.py$
|
||||
- id: check-decorated-operator-implements-custom-name
|
||||
name: Check @task decorator implements custom_operator_name
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/decorator_operator_implements_custom_name.py
|
||||
pass_filenames: true
|
||||
files: ^src/airflow/.*\.py$
|
||||
- id: compile-ui-assets
|
||||
name: Compile ui assets (manual)
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: node
|
||||
stages: ['manual']
|
||||
types_or: [javascript, ts, tsx]
|
||||
@@ -111,6 +131,8 @@ repos:
|
||||
additional_dependencies: ['pnpm@10.25.0']
|
||||
- id: compile-ui-assets-dev
|
||||
name: Compile ui assets in dev mode (manual)
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: node
|
||||
stages: ['manual']
|
||||
types_or: [javascript, ts, tsx]
|
||||
@@ -123,6 +145,8 @@ repos:
|
||||
additional_dependencies: ['pnpm@10.25.0']
|
||||
- id: check-tests-in-the-right-folders
|
||||
name: Check if tests are in the right folders
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_tests_in_right_folders.py
|
||||
language: python
|
||||
files: ^tests/.*\.py$
|
||||
@@ -130,6 +154,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: lint-json-schema
|
||||
name: Lint config_templates/config.yml
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/lint_json_schema.py
|
||||
args:
|
||||
- --spec-file
|
||||
@@ -140,12 +166,16 @@ repos:
|
||||
require_serial: true
|
||||
- id: check-code-deprecations
|
||||
name: Check deprecations categories in decorators
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_deprecations.py
|
||||
language: python
|
||||
pass_filenames: true
|
||||
files: ^src/airflow/.*\.py$
|
||||
- id: check-http-exception-import-from-fastapi
|
||||
name: Check HTTPException is imported from fastapi
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_http_exception_import_from_fastapi.py
|
||||
language: python
|
||||
pass_filenames: true
|
||||
@@ -157,24 +187,32 @@ repos:
|
||||
^tests/unit/utils/test_serve_logs\.py$
|
||||
- id: check-openapi-exception-doc-in-sync
|
||||
name: Check API routes declare the HTTP statuses they raise
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_openapi_exception_doc_in_sync.py
|
||||
language: python
|
||||
pass_filenames: true
|
||||
files: ^src/airflow/api_fastapi/.*/routes/.*\.py$
|
||||
- id: create-missing-init-py-files-tests
|
||||
name: Create missing init.py files in tests
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_init_in_tests.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
files: ^tests/.*\.py$
|
||||
- id: check-tests-unittest-testcase
|
||||
name: Unit tests do not inherit from unittest.TestCase
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: Check that unit tests do not inherit from unittest.TestCase
|
||||
entry: ../scripts/ci/prek/unittest_testcase.py
|
||||
language: python
|
||||
pass_filenames: true
|
||||
files: ^tests/.*\.py$
|
||||
- id: check-no-fab-migrations
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: pygrep
|
||||
name: Check no migration is done on FAB related table
|
||||
description: >
|
||||
@@ -202,6 +240,8 @@ repos:
|
||||
^src/airflow/migrations/versions/0028_3_0_0_drop_ab_user_id_foreign_key\.py$
|
||||
- id: ts-compile-lint-ui
|
||||
name: Compile / format / lint UI
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: TS types generation / ESLint / Prettier new UI files
|
||||
language: node
|
||||
files: |
|
||||
@@ -218,6 +258,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: ts-compile-lint-simple-auth-manager-ui
|
||||
name: Compile / format / lint simple auth manager UI
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: TS types generation / ESLint / Prettier new UI files
|
||||
language: node
|
||||
files: |
|
||||
@@ -235,6 +277,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: mypy-airflow-core
|
||||
name: Run mypy for airflow-core
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py airflow-core
|
||||
pass_filenames: false
|
||||
@@ -244,6 +288,8 @@ repos:
|
||||
# The below prek hooks are those requiring CI image to be built
|
||||
- id: generate-openapi-spec
|
||||
name: Generate the FastAPI API spec
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/generate_openapi_spec.py
|
||||
pass_filenames: false
|
||||
@@ -254,6 +300,8 @@ repos:
|
||||
exclude: ^src/airflow/api_fastapi/execution_api/.*
|
||||
- id: check-i18n-json
|
||||
name: Check i18n files validity
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: Check i18n files are valid json, have no TODOs, and auto-format them
|
||||
language: python
|
||||
files: ^src/airflow/ui/public/i18n/locales/.*\.json$
|
||||
@@ -261,6 +309,8 @@ repos:
|
||||
pass_filenames: false
|
||||
- id: update-migration-references
|
||||
name: Update migration ref doc
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/migration_reference.py
|
||||
args: ["--app", "airflow"]
|
||||
@@ -271,6 +321,8 @@ repos:
|
||||
^docs/migrations-ref\.rst$
|
||||
- id: migration-round-trip
|
||||
name: Migration round-trip SQLite FK enforcement
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/migration_round_trip.py
|
||||
pass_filenames: false
|
||||
@@ -279,6 +331,8 @@ repos:
|
||||
files: ^src/airflow/migrations/versions/.*\.py$
|
||||
- id: check-default-configuration
|
||||
name: Check the default configuration
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_default_configuration.py
|
||||
language: python
|
||||
require_serial: true
|
||||
@@ -286,6 +340,8 @@ repos:
|
||||
files: ^src/airflow/config_templates/config\.yml$
|
||||
- id: check-security-doc-constants
|
||||
name: Check security docs match config.yml constants
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_security_doc_constants.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
@@ -295,6 +351,8 @@ repos:
|
||||
^docs/security/jwt_token_authentication\.rst$|
|
||||
^docs/security/security_model\.rst$
|
||||
- id: check-airflow-version-checks-in-core
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: pygrep
|
||||
name: No AIRFLOW_V_* imports in airflow-core
|
||||
entry: "import AIRFLOW_V_"
|
||||
@@ -312,6 +370,8 @@ repos:
|
||||
^tests/unit/models/test_variable\.py$
|
||||
- id: check-sdk-imports-in-core
|
||||
name: Check for SDK imports in core files
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_sdk_imports_in_core.py
|
||||
language: python
|
||||
types: [python]
|
||||
@@ -319,6 +379,8 @@ repos:
|
||||
## ONLY ADD PREK HOOKS HERE THAT REQUIRE CI IMAGE
|
||||
- id: check-schema-defaults
|
||||
name: Check schema defaults match server-side defaults
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_schema_defaults.py
|
||||
language: python
|
||||
files:
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: check-airflowctl-command-coverage
|
||||
name: Check airflowctl CLI command test coverage
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_airflowctl_command_coverage.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
@@ -32,6 +34,8 @@ repos:
|
||||
^tests/airflowctl_tests/.*\.py$
|
||||
- id: mypy-airflow-ctl-tests
|
||||
name: Run mypy for airflow-ctl-tests
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py airflow-ctl-tests
|
||||
pass_filenames: false
|
||||
|
||||
@@ -26,6 +26,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-airflow-ctl
|
||||
name: Run mypy for airflow-ctl
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py airflow-ctl
|
||||
pass_filenames: false
|
||||
@@ -33,6 +35,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: generate-airflowctl-help-images
|
||||
name: Generate SVG from Airflow CTL Commands
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/capture_airflowctl_help.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
@@ -43,6 +47,8 @@ repos:
|
||||
^src/airflowctl/ctl/commands/.*\.py$
|
||||
- id: check-airflowctl-command-coverage
|
||||
name: Check airflowctl CLI command test coverage
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_airflowctl_command_coverage.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
@@ -52,6 +58,8 @@ repos:
|
||||
^docs/images/command_hashes.txt$
|
||||
- id: check-airflowctl-help-texts
|
||||
name: Check airflowctl CLI commands have help texts
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_airflowctl_help_texts.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-airflow-e2e-tests
|
||||
name: Run mypy for airflow-e2e-tests
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py airflow-e2e-tests
|
||||
pass_filenames: false
|
||||
|
||||
@@ -27,6 +27,8 @@ repos:
|
||||
hooks:
|
||||
- id: insert-license
|
||||
name: Add license for all Helm template files
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
files: ^templates/.*
|
||||
args:
|
||||
- --comment-style
|
||||
@@ -38,6 +40,8 @@ repos:
|
||||
hooks:
|
||||
- id: update-chart-dependencies
|
||||
name: Update chart dependencies to latest (manual)
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/update_chart_dependencies.py
|
||||
stages: ['manual']
|
||||
language: python
|
||||
@@ -46,6 +50,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: mypy-helm-tests
|
||||
name: Run mypy for helm-tests
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py chart/tests
|
||||
pass_filenames: false
|
||||
@@ -56,6 +62,8 @@ repos:
|
||||
hooks:
|
||||
- id: pretty-format-json
|
||||
name: Format JSON files
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
args:
|
||||
- --autofix
|
||||
- --no-sort-keys
|
||||
@@ -70,6 +78,8 @@ repos:
|
||||
hooks:
|
||||
- id: lint-helm-chart
|
||||
name: Lint Helm Chart
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/lint_helm.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
@@ -77,12 +87,16 @@ repos:
|
||||
require_serial: true
|
||||
- id: validate-chart-annotations
|
||||
name: Validate chart annotations
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/validate_chart_annotations.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
files: ^Chart\.yaml$
|
||||
- id: kubeconform
|
||||
name: Kubeconform check on our helm chart
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_kubeconform.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
@@ -90,6 +104,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: build-kustomize-overlays
|
||||
name: Build and smoke-test Kustomize overlays
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/build_kustomize_overlays.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
@@ -97,6 +113,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: sort-helm-values-schema-file-type-field
|
||||
name: Sort Helm Values Schema File (type field)
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/sort_helm_values_schema_file_type_field.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
@@ -104,6 +122,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: update-helm-values-schema-schema-file-type-field-match
|
||||
name: Update Helm Values Schema Schema File (type field match)
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/update_helm_schema_schema_type_fields_match.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
@@ -111,6 +131,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: lint-json-schema
|
||||
name: Lint chart/values.schema.json
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/lint_json_schema.py
|
||||
args:
|
||||
- --spec-file
|
||||
@@ -122,11 +144,15 @@ repos:
|
||||
require_serial: true
|
||||
- id: update-vendored-in-k8s-json-schema
|
||||
name: Vendor k8s definitions into values.schema.json
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/vendor_k8s_json_schema.py
|
||||
language: python
|
||||
files: ^values\.schema\.json$
|
||||
- id: lint-json-schema
|
||||
name: Lint chart/values.yaml
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/lint_json_schema.py
|
||||
args:
|
||||
- --enforce-defaults
|
||||
@@ -139,6 +165,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: lint-chart-schema
|
||||
name: Lint chart/values.schema.json file
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/chart_schema.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-dev
|
||||
name: Run mypy for dev
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py dev
|
||||
pass_filenames: false
|
||||
|
||||
@@ -21,6 +21,7 @@ Useful tools for various Paths used inside Airflow Sources.
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import errno
|
||||
import hashlib
|
||||
import os
|
||||
import platform
|
||||
@@ -622,6 +623,11 @@ def cleanup_python_generated_files():
|
||||
pass
|
||||
except PermissionError:
|
||||
permission_errors.append(Path(dirpath))
|
||||
except OSError as e:
|
||||
# A concurrent breeze process (e.g. parallel prek hooks) can write a fresh .pyc
|
||||
# between rmtree emptying the directory and removing it.
|
||||
if e.errno != errno.ENOTEMPTY:
|
||||
raise
|
||||
dirnames.clear()
|
||||
if permission_errors:
|
||||
if platform.uname().system.lower() == "linux":
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# 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 errno
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from airflow_breeze.utils import path_utils
|
||||
from airflow_breeze.utils.path_utils import cleanup_python_generated_files
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def root_with_pycache(tmp_path, monkeypatch):
|
||||
pycache = tmp_path / "pkg" / "__pycache__"
|
||||
pycache.mkdir(parents=True)
|
||||
(pycache / "mod.cpython-310.pyc").write_bytes(b"")
|
||||
monkeypatch.setattr(path_utils, "AIRFLOW_ROOT_PATH", tmp_path)
|
||||
return pycache
|
||||
|
||||
|
||||
@mock.patch.object(path_utils.shutil, "rmtree", autospec=True)
|
||||
def test_cleanup_ignores_pycache_repopulated_concurrently(mock_rmtree, root_with_pycache):
|
||||
mock_rmtree.side_effect = OSError(errno.ENOTEMPTY, "Directory not empty")
|
||||
|
||||
cleanup_python_generated_files()
|
||||
|
||||
mock_rmtree.assert_called_once_with(str(root_with_pycache))
|
||||
|
||||
|
||||
@mock.patch.object(path_utils.shutil, "rmtree", autospec=True)
|
||||
def test_cleanup_reraises_other_os_errors(mock_rmtree, root_with_pycache):
|
||||
mock_rmtree.side_effect = OSError(errno.EIO, "I/O error")
|
||||
|
||||
with pytest.raises(OSError, match="I/O error"):
|
||||
cleanup_python_generated_files()
|
||||
@@ -25,6 +25,8 @@ repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: mypy-airflow-mypy
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
stages: ['pre-push']
|
||||
name: Run mypy for airflow-mypy plugins
|
||||
language: python
|
||||
@@ -35,6 +37,8 @@ repos:
|
||||
^tests/.*\.py$
|
||||
require_serial: true
|
||||
- id: mypy-airflow-mypy-manual
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
stages: ['manual']
|
||||
name: Run mypy for airflow-mypy (manual)
|
||||
language: python
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-docker-tests
|
||||
name: Run mypy for docker-tests
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py docker-tests
|
||||
pass_filenames: false
|
||||
|
||||
@@ -26,14 +26,20 @@ repos:
|
||||
hooks:
|
||||
- id: identity
|
||||
name: Print checked files
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: Print input to the static check hooks for troubleshooting
|
||||
- id: check-hooks-apply
|
||||
name: Check if all hooks apply to the repository
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: ad1b27d73581aa16cca06fc4a0761fc563ffe8e8 # frozen: v1.5.6
|
||||
hooks:
|
||||
- id: insert-license
|
||||
name: Add license for all Go files
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
types: [go]
|
||||
exclude: mocks/.*\.go$|\.pb\.go$
|
||||
args:
|
||||
@@ -48,6 +54,8 @@ repos:
|
||||
hooks:
|
||||
- id: go-mod-tidy
|
||||
name: Run go mod tidy
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: go mod tidy
|
||||
types: [go]
|
||||
exclude: mocks/.*\.go$
|
||||
@@ -55,6 +63,8 @@ repos:
|
||||
language: golang
|
||||
- id: imports
|
||||
name: Consistent import ordering for Go files
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: goimports-reviser -rm-unused -set-exit-status
|
||||
additional_dependencies: [github.com/incu6us/goimports-reviser/v3@v3.10.0]
|
||||
types: [go]
|
||||
@@ -62,12 +72,16 @@ repos:
|
||||
require_serial: true
|
||||
- id: gofmt
|
||||
name: Format go code
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: golines --base-formatter=gofumpt --write-output --max-len=100 --chain-split-dots
|
||||
additional_dependencies: [github.com/segmentio/golines@latest, mvdan.cc/gofumpt@v0.8.0]
|
||||
types: [go]
|
||||
language: golang
|
||||
- id: staticcheck
|
||||
name: Check naming in Go code
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: staticcheck -checks ST1003 ./...
|
||||
additional_dependencies: [honnef.co/go/tools/cmd/staticcheck@v0.7.0]
|
||||
types: [go]
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-kubernetes-tests
|
||||
name: Run mypy for kubernetes-tests
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py kubernetes-tests
|
||||
pass_filenames: false
|
||||
|
||||
@@ -26,12 +26,16 @@ repos:
|
||||
hooks:
|
||||
- id: check-deferrable-default
|
||||
name: Check and fix default value of default_deferrable
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/check_deferrable_default.py
|
||||
pass_filenames: false
|
||||
files: ^(.*/)?airflow/.*/(sensors|operators)/.*\.py$
|
||||
- id: check-trigger-serialize-init
|
||||
name: Check trigger __init__ and serialize() are in sync
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: Every trigger __init__ parameter must appear in its serialize() return dict
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/check_trigger_serialize_init.py
|
||||
@@ -39,6 +43,8 @@ repos:
|
||||
files: ^.*/src/airflow/providers/.*/triggers/[^/]+\.py$
|
||||
- id: check-deferred-hook-configuration
|
||||
name: Check deferred AWS tasks pass their hook configuration
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: An operator that defers must hand region_name, verify and botocore_config to its trigger
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/check_deferred_hook_configuration.py
|
||||
@@ -46,6 +52,8 @@ repos:
|
||||
files: ^amazon/src/airflow/providers/amazon/aws/.*\.py$
|
||||
- id: check-migration-patterns
|
||||
name: Check migration files for anti-patterns and style (MIG001-MIG004)
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_migration_patterns.py
|
||||
language: python
|
||||
pass_filenames: true
|
||||
@@ -54,12 +62,16 @@ repos:
|
||||
require_serial: true
|
||||
- id: update-providers-dependencies
|
||||
name: Update dependencies for providers
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/update_providers_dependencies.py
|
||||
language: python
|
||||
always_run: true
|
||||
pass_filenames: false
|
||||
- id: validate-operators-init
|
||||
name: Validate templated fields in operator __init__
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: Require plain assignment of templated fields and forbid reading their un-rendered values
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/validate_operators_init.py
|
||||
@@ -67,6 +79,8 @@ repos:
|
||||
files: ^.*/src/airflow/providers/.*/(operators|transfers|sensors)/.*\.py$
|
||||
- id: check-conn-id-templated
|
||||
name: Check connection ids accepted by operators are in template_fields
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: Every *conn_id argument an operator, sensor or notifier accepts must be templated
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/check_conn_id_templated.py
|
||||
@@ -76,6 +90,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: update-providers-build-files
|
||||
name: Update providers build files
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/update_providers_build_files.py
|
||||
language: python
|
||||
pass_filenames: true
|
||||
@@ -91,24 +107,32 @@ repos:
|
||||
require_serial: true
|
||||
- id: check-airflow-v-imports-in-tests
|
||||
name: Check AIRFLOW_V imports in tests
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/check_airflow_v_imports_in_tests.py
|
||||
pass_filenames: true
|
||||
files: ^.*/tests/.+\.py$
|
||||
- id: check-sql-dependency-common-data-structure
|
||||
name: Check dependency of SQL providers
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: Check dependency of SQL Providers with common data structure
|
||||
entry: ../scripts/ci/prek/check_common_sql_dependency.py
|
||||
language: python
|
||||
files: ^.*/src/airflow/providers/.*/hooks/.*\.py$
|
||||
- id: generate-volumes-for-sources
|
||||
name: Generate volumes for docker compose
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/generate_volumes_for_sources.py
|
||||
language: python
|
||||
files: ^.*/provider\.yaml$
|
||||
pass_filenames: false
|
||||
require_serial: true
|
||||
- id: check-pytest-mark-db-test-in-providers
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: pygrep
|
||||
name: Check pytest.mark.db_test use in providers
|
||||
entry: pytest\.mark\.db_test
|
||||
@@ -169,6 +193,8 @@ repos:
|
||||
^zendesk/.*\.py$
|
||||
- id: check-links-to-example-dags-do-not-use-hardcoded-versions
|
||||
name: Verify no hard-coded version in example dags
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: The links to example dags should use |version| as version specification
|
||||
language: pygrep
|
||||
entry: >
|
||||
@@ -178,6 +204,8 @@ repos:
|
||||
pass_filenames: true
|
||||
files: ^.*/docs/.*\.rst
|
||||
- id: check-no-airflow-deprecation-in-providers
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: pygrep
|
||||
name: Do not use DeprecationWarning in providers
|
||||
description: Use AirflowProviderDeprecationWarning in providers
|
||||
@@ -185,6 +213,8 @@ repos:
|
||||
pass_filenames: true
|
||||
files: ^.*/src/airflow/providers/.*\.py$
|
||||
- id: check-base-operator-usage
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: pygrep
|
||||
name: Check BaseOperator other imports
|
||||
description: Make sure BaseOperator is imported from airflow.models outside of core
|
||||
@@ -193,6 +223,8 @@ repos:
|
||||
files: ^.*/src/airflow/providers/.*\.py$
|
||||
exclude: ^standard/.*/.*\.py$
|
||||
- id: check-get-lineage-collector-providers
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
name: Check providers import hook lineage code from compat
|
||||
description: Make sure you import from airflow.provider.common.compat.lineage.hook instead of
|
||||
@@ -205,6 +237,8 @@ repos:
|
||||
exclude: ^common/compat/src/airflow/providers/common/compat/.*\.py$
|
||||
- id: check-aiobotocore-optional
|
||||
name: Check if aiobotocore is an optional dependency only
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_aiobotocore_optional.py
|
||||
language: python
|
||||
files: ^.*/provider\.yaml$
|
||||
@@ -212,6 +246,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: check-providers-subpackages-init-file-exist
|
||||
name: Provider subpackage init files are there
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
pass_filenames: false
|
||||
always_run: true
|
||||
entry: ../scripts/ci/prek/check_providers_subpackages_all_have_init.py
|
||||
@@ -219,12 +255,16 @@ repos:
|
||||
require_serial: true
|
||||
- id: check-system-tests-tocs
|
||||
name: Check that system tests is properly added
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_system_tests_hidden_in_index.py
|
||||
language: python
|
||||
pass_filenames: true
|
||||
files: ^.*/docs/index\.rst$
|
||||
- id: check-provider-docs-valid
|
||||
name: Validate provider doc files
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_provider_docs.py
|
||||
language: python
|
||||
files: ^.*/provider\.yaml$|^.*/docs/.*
|
||||
@@ -232,6 +272,8 @@ repos:
|
||||
pass_filenames: false
|
||||
- id: check-connection-doc-labels
|
||||
name: Validate connection doc labels match provider.yaml
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_connection_doc_labels.py
|
||||
language: python
|
||||
files: ^.*/provider\.yaml$|^.*/docs/.*/connections.*\.rst$|^.*/docs/connections\.rst$
|
||||
@@ -239,12 +281,16 @@ repos:
|
||||
pass_filenames: false
|
||||
- id: check-common-ai-operators-index
|
||||
name: Check common.ai operators are listed in the docs index
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_common_ai_operators_index.py
|
||||
language: python
|
||||
files: ^common/ai/(src/airflow/providers/common/ai/operators/.*\.py|docs/operators/index\.rst)$
|
||||
require_serial: true
|
||||
pass_filenames: false
|
||||
- id: mypy-providers
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
stages: ['pre-push']
|
||||
name: Run mypy for providers
|
||||
language: python
|
||||
@@ -252,6 +298,8 @@ repos:
|
||||
files: ^.*\.py$
|
||||
require_serial: true
|
||||
- id: mypy-providers
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
stages: ['manual']
|
||||
name: Run mypy for providers (manual)
|
||||
language: python
|
||||
@@ -261,6 +309,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: check-provider-yaml-valid
|
||||
name: Validate provider.yaml files
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_provider_yaml_files.py
|
||||
language: python
|
||||
files: >
|
||||
@@ -271,18 +321,24 @@ repos:
|
||||
require_serial: true
|
||||
- id: check-cli-definition-imports
|
||||
name: Check CLI definition files only import allowed modules
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_cli_definition_imports.py
|
||||
language: python
|
||||
files: ^.*/cli/definition\.py$
|
||||
require_serial: false
|
||||
- id: check-imports-in-providers
|
||||
name: Check imports in providers
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_imports_in_providers.py
|
||||
language: python
|
||||
files: ^.*/src/airflow/providers/.*version_compat.*\.py$
|
||||
require_serial: true
|
||||
- id: check-conf-import-in-providers
|
||||
name: Check conf is imported from compat SDK in providers
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_conf_import_in_providers.py
|
||||
language: python
|
||||
types: [python]
|
||||
@@ -291,6 +347,8 @@ repos:
|
||||
require_serial: false
|
||||
- id: provider-version-compat
|
||||
name: Check for correct version_compat imports in providers
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_provider_version_compat.py
|
||||
language: python
|
||||
types: [python]
|
||||
@@ -301,6 +359,8 @@ repos:
|
||||
hooks:
|
||||
- id: ast-grep
|
||||
name: Check providers import httpx2 rather than httpx
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
types: [python]
|
||||
# Pinned to the providers config rather than relying on ast-grep walking up
|
||||
# from the working directory, so a future root sgconfig.yml cannot shadow it.
|
||||
|
||||
@@ -26,6 +26,8 @@ repos:
|
||||
hooks:
|
||||
- id: check-http-exception-import-from-fastapi
|
||||
name: Check HTTPException is imported from fastapi
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../../scripts/ci/prek/check_http_exception_import_from_fastapi.py
|
||||
language: python
|
||||
pass_filenames: true
|
||||
|
||||
@@ -26,6 +26,8 @@ repos:
|
||||
hooks:
|
||||
- id: ts-compile-lint-hitl-review-ui
|
||||
name: Compile / format / lint HITL Review UI
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: TS types generation / ESLint / Prettier new UI files in HITL Review
|
||||
language: node
|
||||
files: |
|
||||
@@ -41,6 +43,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: compile-common-ai-provider-assets
|
||||
name: Compile Common AI provider assets
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: node
|
||||
stages: ['pre-commit', 'manual']
|
||||
files: ^src/airflow/providers/common/ai/plugins/www/
|
||||
@@ -49,6 +53,8 @@ repos:
|
||||
additional_dependencies: ['pnpm@10.25.0']
|
||||
- id: check-http-exception-import-from-fastapi
|
||||
name: Check HTTPException is imported from fastapi
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../../../scripts/ci/prek/check_http_exception_import_from_fastapi.py
|
||||
language: python
|
||||
pass_filenames: true
|
||||
|
||||
@@ -26,6 +26,8 @@ repos:
|
||||
hooks:
|
||||
- id: check-common-compat-sdk-imports-in-sync
|
||||
name: Check common.compat sdk TYPE_CHECKING matches runtime maps
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
files: ^src/airflow/providers/common/compat/sdk\.py$
|
||||
pass_filenames: false
|
||||
|
||||
@@ -26,12 +26,16 @@ repos:
|
||||
hooks:
|
||||
- id: generate-openapi-spec-edge
|
||||
name: Generate the FastAPI API spec for Edge
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/generate_openapi_spec_providers.py edge
|
||||
pass_filenames: false
|
||||
files: ^src/airflow/providers/edge3/worker_api/.*\.py$
|
||||
- id: check-http-exception-import-from-fastapi
|
||||
name: Check HTTPException is imported from fastapi
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../../scripts/ci/prek/check_http_exception_import_from_fastapi.py
|
||||
language: python
|
||||
pass_filenames: true
|
||||
@@ -41,6 +45,8 @@ repos:
|
||||
^tests/unit/edge3/(worker_api|plugins)/.*\.py$
|
||||
- id: ts-compile-lint-edge-ui
|
||||
name: Compile / format / lint edge UI
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: TS types generation / ESLint / Prettier new UI files in Edge Provider
|
||||
language: node
|
||||
files: |
|
||||
@@ -57,6 +63,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: update-migration-references-edge3
|
||||
name: Update migration ref doc for Edge3
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/migration_reference.py
|
||||
args: ["--app", "edge3"]
|
||||
@@ -67,6 +75,8 @@ repos:
|
||||
^(providers/edge3/)?docs/migrations-ref\.rst$
|
||||
- id: check-revision-heads-map-edge3
|
||||
name: Check that the REVISION_HEADS_MAP is up-to-date
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/check_revision_heads_map.py
|
||||
pass_filenames: false
|
||||
@@ -76,6 +86,8 @@ repos:
|
||||
^(providers/edge3/)?src/airflow/providers/edge3/models/db\.py$
|
||||
- id: compile-edge-assets
|
||||
name: Compile Edge provider assets
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: node
|
||||
stages: ['pre-commit', 'manual']
|
||||
files: ^src/airflow/providers/edge3/plugins/www
|
||||
|
||||
@@ -26,6 +26,8 @@ repos:
|
||||
hooks:
|
||||
- id: compile-fab-assets
|
||||
name: Compile FAB provider assets
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: node
|
||||
stages: ['pre-commit', 'manual']
|
||||
files: ^src/airflow/providers/fab/www/
|
||||
@@ -38,12 +40,16 @@ repos:
|
||||
additional_dependencies: ['pnpm@10.25.0']
|
||||
- id: generate-openapi-spec-fab
|
||||
name: Generate the FastAPI API spec for FAB
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/generate_openapi_spec_providers.py fab
|
||||
pass_filenames: false
|
||||
files: ^src/airflow/providers/fab/auth_manager/api_fastapi/.*\.py$
|
||||
- id: check-http-exception-import-from-fastapi
|
||||
name: Check HTTPException is imported from fastapi
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../../scripts/ci/prek/check_http_exception_import_from_fastapi.py
|
||||
language: python
|
||||
pass_filenames: true
|
||||
@@ -53,6 +59,8 @@ repos:
|
||||
^tests/unit/fab/auth_manager/api_fastapi/.*\.py$
|
||||
- id: update-migration-references-fab
|
||||
name: Update migration ref doc for FAB
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/migration_reference.py
|
||||
args: ["--app", "fab"]
|
||||
@@ -63,6 +71,8 @@ repos:
|
||||
^(providers/fab/)?docs/migrations-ref\.rst$
|
||||
- id: check-revision-heads-map-fab
|
||||
name: Check that the REVISION_HEADS_MAP is up-to-date
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/check_revision_heads_map.py
|
||||
pass_filenames: false
|
||||
@@ -72,6 +82,8 @@ repos:
|
||||
^(providers/fab/)?src/airflow/providers/fab/auth_manager/models/db\.py$
|
||||
- id: prevent-deprecated-sqlalchemy-usage-fab
|
||||
name: Prevent deprecated sqlalchemy usage
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../../scripts/ci/prek/prevent_deprecated_sqlalchemy_usage.py
|
||||
language: python
|
||||
files: ^.*\.py$
|
||||
|
||||
@@ -26,12 +26,16 @@ repos:
|
||||
hooks:
|
||||
- id: generate-openapi-spec-keycloak
|
||||
name: Generate the FastAPI API spec for Keycloak
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/generate_openapi_spec_providers.py keycloak
|
||||
pass_filenames: false
|
||||
files: ^src/airflow/providers/keycloak/auth_manager/.*\.py$
|
||||
- id: check-http-exception-import-from-fastapi
|
||||
name: Check HTTPException is imported from fastapi
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../../scripts/ci/prek/check_http_exception_import_from_fastapi.py
|
||||
language: python
|
||||
pass_filenames: true
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-scripts
|
||||
name: Run mypy for scripts
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ./ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py scripts
|
||||
pass_filenames: false
|
||||
|
||||
@@ -32,3 +32,7 @@ When adding a new breeze-dependent hook:
|
||||
- Register the script in the appropriate `.pre-commit-config.yaml` (`/.pre-commit-config.yaml`
|
||||
for repo-wide hooks, `/airflow-core/.pre-commit-config.yaml` for core-specific hooks, or a
|
||||
provider-level config).
|
||||
- Give every hook `env: {PYTHONPYCACHEPREFIX: .build/pycache}`. Hooks run in parallel and
|
||||
breeze deletes `__pycache__` directories on start-up, so a hook writing `.pyc` next to the
|
||||
sources can make a concurrent breeze hook fail with `Directory not empty`.
|
||||
`check-prek-hooks-pycache-prefix` enforces this.
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
#!/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.
|
||||
# /// script
|
||||
# requires-python = ">=3.11"
|
||||
# dependencies = [
|
||||
# "pyyaml>=6.0.3",
|
||||
# ]
|
||||
# ///
|
||||
"""Fail when a prek hook does not redirect Python bytecode out of the source tree.
|
||||
|
||||
prek runs hooks in parallel, and breeze removes every ``__pycache__`` under the
|
||||
repository on start-up. A hook that writes ``.pyc`` files next to the sources can
|
||||
refill a directory while a concurrent breeze is removing it, failing that hook
|
||||
with ``Directory not empty``. Every hook therefore sets ``PYTHONPYCACHEPREFIX``
|
||||
to a hidden ``.build/`` directory, which breeze skips and git ignores.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
PYCACHE_PREFIX = ".build/pycache"
|
||||
|
||||
|
||||
def find_hooks_without_pycache_prefix(config_path: Path) -> list[str]:
|
||||
config = yaml.safe_load(config_path.read_text()) or {}
|
||||
return [
|
||||
hook["id"]
|
||||
for repo in config.get("repos", [])
|
||||
for hook in repo.get("hooks", [])
|
||||
if (hook.get("env") or {}).get("PYTHONPYCACHEPREFIX") != PYCACHE_PREFIX
|
||||
]
|
||||
|
||||
|
||||
def main() -> int:
|
||||
config_paths = subprocess.check_output(
|
||||
["git", "ls-files", "*.pre-commit-config.yaml", ".pre-commit-config.yaml"], text=True
|
||||
).split()
|
||||
errors = [
|
||||
f"{config_path}: {hook_id}"
|
||||
for config_path in config_paths
|
||||
for hook_id in find_hooks_without_pycache_prefix(Path(config_path))
|
||||
]
|
||||
if errors:
|
||||
print("ERROR: These prek hooks do not set PYTHONPYCACHEPREFIX:\n")
|
||||
print("\n".join(f" {error}" for error in errors))
|
||||
print(
|
||||
"\nAdd the following to each of them, right after `name:`:\n\n"
|
||||
" env:\n"
|
||||
f" PYTHONPYCACHEPREFIX: {PYCACHE_PREFIX}\n"
|
||||
)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -47,6 +47,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-{dist}
|
||||
name: Run mypy for shared-{dist}
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: >-
|
||||
../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from __future__ import annotations
|
||||
|
||||
from check_prek_hooks_pycache_prefix import find_hooks_without_pycache_prefix
|
||||
|
||||
CONFIG = """\
|
||||
repos:
|
||||
- repo: meta
|
||||
hooks:
|
||||
- id: with-prefix
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: no-env
|
||||
- id: other-env
|
||||
env:
|
||||
FOO: bar
|
||||
- id: wrong-prefix
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: /tmp/pycache
|
||||
"""
|
||||
|
||||
|
||||
def test_find_hooks_without_pycache_prefix(tmp_path):
|
||||
config = tmp_path / ".pre-commit-config.yaml"
|
||||
config.write_text(CONFIG)
|
||||
|
||||
assert find_hooks_without_pycache_prefix(config) == ["no-env", "other-env", "wrong-prefix"]
|
||||
|
||||
|
||||
def test_find_hooks_without_pycache_prefix_empty_config(tmp_path):
|
||||
config = tmp_path / ".pre-commit-config.yaml"
|
||||
config.write_text("")
|
||||
|
||||
assert find_hooks_without_pycache_prefix(config) == []
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-configuration
|
||||
name: Run mypy for shared-configuration
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py shared/configuration
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-dagnode
|
||||
name: Run mypy for shared-dagnode
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py shared/dagnode
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-listeners
|
||||
name: Run mypy for shared-listeners
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py shared/listeners
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-logging
|
||||
name: Run mypy for shared-logging
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py shared/logging
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-module_loading
|
||||
name: Run mypy for shared-module_loading
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py shared/module_loading
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-observability
|
||||
name: Run mypy for shared-observability
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py shared/observability
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-plugins_manager
|
||||
name: Run mypy for shared-plugins_manager
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py shared/plugins_manager
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-providers_discovery
|
||||
name: Run mypy for shared-providers_discovery
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: >-
|
||||
../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-secrets_backend
|
||||
name: Run mypy for shared-secrets_backend
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py shared/secrets_backend
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-secrets_masker
|
||||
name: Run mypy for shared-secrets_masker
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py shared/secrets_masker
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-serialization
|
||||
name: Run mypy for shared-serialization
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py shared/serialization
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-state
|
||||
name: Run mypy for shared-state
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py shared/state
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-template_rendering
|
||||
name: Run mypy for shared-template_rendering
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: >-
|
||||
../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-shared-timezones
|
||||
name: Run mypy for shared-timezones
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py shared/timezones
|
||||
pass_filenames: false
|
||||
|
||||
@@ -24,6 +24,8 @@ repos:
|
||||
hooks:
|
||||
- id: mypy-task-sdk-integration-tests
|
||||
name: Run mypy for task-sdk-integration-tests
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py task-sdk-integration-tests
|
||||
pass_filenames: false
|
||||
|
||||
@@ -26,6 +26,8 @@ repos:
|
||||
hooks:
|
||||
- id: check-core-imports
|
||||
name: Check for core imports in task-sdk files
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_core_imports_in_sdk.py
|
||||
language: python
|
||||
types: [python]
|
||||
@@ -54,12 +56,16 @@ repos:
|
||||
^src/airflow/sdk/types.py$
|
||||
- id: check-init-decorator-arguments
|
||||
name: Sync model __init__ and decorator arguments
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/check_init_decorator_arguments.py
|
||||
pass_filenames: false
|
||||
files: ^src/airflow/sdk/definitions/dag\.py$|^src/airflow/sdk/definitions/decorators/task_group\.py$
|
||||
- id: mypy-task-sdk
|
||||
name: Run mypy for task-sdk
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
language: python
|
||||
entry: ../scripts/ci/prek/run_mypy_full_dist_local_venv_or_breeze_in_ci.py task-sdk
|
||||
pass_filenames: false
|
||||
|
||||
@@ -25,6 +25,8 @@ repos:
|
||||
hooks:
|
||||
- id: ts-sdk-lint
|
||||
name: Lint TypeScript SDK
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ./scripts/ci/prek/ts_sdk_lint.py
|
||||
language: node
|
||||
files: |
|
||||
@@ -40,6 +42,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: check-ts-sdk-supervisor-schema
|
||||
name: Check TypeScript SDK supervisor schema is up to date
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ./scripts/ci/prek/check_supervisor_schema.py
|
||||
language: node
|
||||
files: >
|
||||
@@ -52,6 +56,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: check-ts-sdk-dag-schema
|
||||
name: Check TypeScript SDK Dag schema fields are up to date
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ./scripts/ci/prek/check_dag_schema.py
|
||||
language: node
|
||||
files: >
|
||||
@@ -64,6 +70,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: check-ts-sdk-serialization-conformance
|
||||
name: Check the TS SDK serializes Dags the way Airflow does
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
description: "Serialize the shared test Dags with the TS SDK and with Airflow, and compare the two"
|
||||
entry: ./scripts/ci/prek/check_serialization_conformance.py
|
||||
language: node
|
||||
@@ -78,6 +86,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: check-ts-sdk-docs-package-version-in-sync
|
||||
name: Check ts-sdk/docs package.json versions match ts-sdk/package.json
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ../scripts/ci/prek/check_ts_sdk_docs_package_version_in_sync.py
|
||||
language: python
|
||||
files: >
|
||||
@@ -88,6 +98,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: compile-ts-sdk
|
||||
name: Compile TypeScript SDK
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ./scripts/ci/prek/compile_ts_sdk.py
|
||||
language: node
|
||||
stages: [manual]
|
||||
@@ -103,6 +115,8 @@ repos:
|
||||
require_serial: true
|
||||
- id: verify-ts-sdk-package
|
||||
name: Verify TypeScript SDK package artifact
|
||||
env:
|
||||
PYTHONPYCACHEPREFIX: .build/pycache
|
||||
entry: ./scripts/ci/prek/verify_ts_sdk_package.py
|
||||
language: node
|
||||
stages: [manual]
|
||||
|
||||
Reference in new issue
Block a user