| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| from __future__ import annotations |
| |
| import json |
| import re |
| from typing import Any |
| from unittest.mock import Mock, patch |
| |
| import pytest |
| from rich.console import Console |
| |
| from airflow_breeze.global_constants import ( |
| ALLOWED_KUBERNETES_VERSIONS, |
| ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS, |
| CI_AMD_PLATFORM, |
| CI_ARM_PLATFORM, |
| CURRENT_PYTHON_MAJOR_MINOR_VERSIONS, |
| DEFAULT_KUBERNETES_VERSION, |
| DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| JAVA_SDK_VERSION, |
| NUMBER_OF_CORE_SLICES, |
| NUMBER_OF_LOW_DEP_SLICES, |
| PROVIDERS_COMPATIBILITY_TESTS_MATRIX, |
| GithubEvents, |
| ) |
| from airflow_breeze.utils.functools_cache import clearable_cache |
| from airflow_breeze.utils.packages import get_available_distributions |
| from airflow_breeze.utils.path_utils import AIRFLOW_ROOT_PATH |
| from airflow_breeze.utils.selective_checks import ( |
| ALL_CI_SELECTIVE_TEST_TYPES, |
| SelectiveChecks, |
| _get_test_list_as_json, |
| _split_list, |
| ) |
| |
| ANSI_COLORS_MATCHER = re.compile(r"(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]") |
| |
| ALL_DOCS_SELECTED_FOR_BUILD = "" |
| ALL_PROVIDERS_AFFECTED = "" |
| |
| ALL_KUBERNETES_VERSIONS_AS_STRING = " ".join(ALLOWED_KUBERNETES_VERSIONS) |
| ALL_KUBERNETES_VERSIONS_AS_LIST = "[" + ", ".join([f"'{v}'" for v in ALLOWED_KUBERNETES_VERSIONS]) + "]" |
| ALL_PYTHON_VERSIONS_AS_STRING = " ".join(ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS) |
| ALL_PYTHON_VERSIONS_AS_LIST = "[" + ", ".join([f"'{v}'" for v in ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS]) + "]" |
| CURRENT_PYTHON_VERSIONS_AS_LIST = ( |
| "[" + ", ".join([f"'{v}'" for v in CURRENT_PYTHON_MAJOR_MINOR_VERSIONS]) + "]" |
| ) |
| |
| DEFAULT_HELM_K8S_VERSION = ALLOWED_KUBERNETES_VERSIONS[0].lstrip("v") |
| LAST_HELM_K8S_VERSION = ALLOWED_KUBERNETES_VERSIONS[-1].lstrip("v") |
| DEFAULT_HELM_K8S_VERSIONS_JSON = json.dumps([DEFAULT_HELM_K8S_VERSION]) |
| ALL_HELM_K8S_VERSIONS_JSON = json.dumps( |
| [DEFAULT_HELM_K8S_VERSION] |
| if DEFAULT_HELM_K8S_VERSION == LAST_HELM_K8S_VERSION |
| else [DEFAULT_HELM_K8S_VERSION, LAST_HELM_K8S_VERSION] |
| ) |
| |
| PYTHON_K8S_COMBO_LENGTH = max(len(ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS), len(ALLOWED_KUBERNETES_VERSIONS)) |
| PYTHON_VERSIONS_MAX = (ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS * 2)[:PYTHON_K8S_COMBO_LENGTH] |
| KUBERNETES_VERSIONS_MAX = (ALLOWED_KUBERNETES_VERSIONS * 2)[:PYTHON_K8S_COMBO_LENGTH] |
| |
| ZIP_PYTHON_AND_KUBERNETES_VERSIONS_AS_STRING = " ".join( |
| [f"{t[0]}-{t[1]}" for t in zip(PYTHON_VERSIONS_MAX, KUBERNETES_VERSIONS_MAX)] |
| ) |
| ZIP_PYTHON_AND_KUBERNETES_VERSIONS_AS_LIST = ( |
| "[" + ", ".join([f"'{t[0]}-{t[1]}'" for t in zip(PYTHON_VERSIONS_MAX, KUBERNETES_VERSIONS_MAX)]) + "]" |
| ) |
| |
| |
| ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON = json.dumps( |
| _get_test_list_as_json(_split_list(sorted(ALL_CI_SELECTIVE_TEST_TYPES.split()), NUMBER_OF_CORE_SLICES)) |
| ) |
| |
| ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON = json.dumps( |
| [ |
| { |
| "description": "-amazon,celer...standard", |
| "test_types": "Providers[-amazon,celery,google,standard] " |
| "Providers[amazon] Providers[celery] Providers[google] Providers[standard]", |
| } |
| ] |
| ) |
| |
| LIST_OF_ALL_PROVIDER_TESTS = [ |
| f"Providers[{provider}]" for provider in get_available_distributions(include_not_ready=True) |
| ] |
| |
| LIST_OF_ALL_PROVIDER_TESTS_AS_JSON = json.dumps( |
| _get_test_list_as_json(_split_list(sorted(LIST_OF_ALL_PROVIDER_TESTS), 5)) |
| ) |
| |
| |
| ALL_SKIPPED_COMMITS_ON_NO_CI_IMAGE = ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,flynt,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ) |
| |
| ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED = "identity,update-uv-lock" |
| |
| ALL_SKIPPED_COMMITS_IF_ONLY_UI_OPENAPI_CHANGED = ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,flynt,identity,ktlint," |
| "lint-helm-chart,mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests," |
| "mypy-airflow-e2e-tests,mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests," |
| "mypy-kubernetes-tests,mypy-scripts,mypy-shared-configuration,mypy-shared-dagnode," |
| "mypy-shared-listeners,mypy-shared-logging,mypy-shared-module_loading," |
| "mypy-shared-observability,mypy-shared-plugins_manager,mypy-shared-providers_discovery," |
| "mypy-shared-secrets_backend,mypy-shared-secrets_masker,mypy-shared-serialization," |
| "mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk," |
| "mypy-task-sdk-integration-tests,update-uv-lock" |
| ) |
| |
| ALL_SKIPPED_COMMITS_IF_NO_UI = ( |
| "check-ts-sdk-supervisor-schema,identity,ktlint,mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ) |
| ALL_SKIPPED_COMMITS_IF_NO_HELM_TESTS = ( |
| "check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,update-uv-lock" |
| ) |
| |
| ALL_SKIPPED_COMMITS_IF_NO_UI_AND_HELM_TESTS = ( |
| "check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ) |
| |
| # API source/test change with NO OpenAPI spec change: the full matrix is no longer |
| # forced. airflow-core Python changed (so mypy-airflow-core + flynt run); no |
| # provider.yaml, helm, or UI files changed, so those checks stay skipped. |
| ALL_SKIPPED_COMMITS_IF_ONLY_API_SOURCE_CHANGED = ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones," |
| "mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ) |
| |
| ALL_SKIPPED_COMMITS_IF_NO_PROVIDERS_AND_UI = ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,identity,ktlint," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ) |
| |
| ALL_SKIPPED_COMMITS_IF_NO_PROVIDERS = ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ) |
| |
| |
| ALL_SKIPPED_COMMITS_IF_NO_PROVIDERS_UI_AND_HELM_TESTS = ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ) |
| |
| ALL_SKIPPED_COMMITS_IF_NO_CODE_PROVIDERS_AND_HELM_TESTS = ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,flynt,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests,update-uv-lock" |
| ) |
| |
| ALL_SKIPPED_COMMITS_IF_NOT_IMPORTANT_FILES_CHANGED = ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,flynt,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ) |
| |
| |
| All_SKIPPED_COMMITS_IF_NON_MAIN_BRANCH = ( |
| "check-airflow-provider-compatibility,check-airflow-providers-bug-report-template," |
| "check-extra-packages-references,check-provider-yaml-valid," |
| "compile-fab-assets,generate-openapi-spec-fab,identity," |
| "lint-helm-chart,update-uv-lock,validate-operators-init" |
| ) |
| |
| |
| # commit that is neutral - allows to keep pyproject.toml-changing PRS neutral for unit tests |
| NEUTRAL_COMMIT = "938f0c1f3cc4cbe867123ee8aa9f290f9f18100a" |
| |
| |
| def escape_ansi_colors(line): |
| return ANSI_COLORS_MATCHER.sub("", line) |
| |
| |
| @clearable_cache |
| def get_rich_console() -> Console: |
| return Console(color_system="truecolor", force_terminal=True) |
| |
| |
| def print_in_color(s: Any = ""): |
| get_rich_console().print(s) |
| |
| |
| def get_outputs_from_stderr(stderr: str) -> dict[str, str]: |
| escaped_stderr = escape_ansi_colors(stderr) |
| return dict(line.split("=", 1) for line in escaped_stderr.splitlines() if "=" in line) |
| |
| |
| def assert_outputs_are_printed(expected_outputs: dict[str, str], stderr: str): |
| received_output_as_dict = get_outputs_from_stderr(stderr) |
| for expected_key, expected_value in expected_outputs.items(): |
| if expected_value is None: |
| if expected_key in received_output_as_dict: |
| print_in_color(f"\n[red]ERROR: The '{expected_key}' should not be present in:[/]") |
| print_in_color(received_output_as_dict) |
| print_in_color("\n") |
| assert expected_key is not None |
| |
| else: |
| received_value = received_output_as_dict.get(expected_key) |
| if received_value != expected_value: |
| if received_value is not None: |
| print_in_color(f"\n[red]ERROR: The key '{expected_key}' has unexpected value:") |
| print( |
| received_value, |
| ) |
| print_in_color("Expected value:\n") |
| print(expected_value) |
| print_in_color("\nOutput received:") |
| print_in_color(received_output_as_dict) |
| print_in_color() |
| assert received_value == expected_value, f"Correct value for {expected_key!r}" |
| else: |
| print_in_color( |
| f"\n[red]ERROR: The key '{expected_key}' missing but it is expected. Expected value:" |
| ) |
| print_in_color(expected_value) |
| print_in_color("\nOutput received:") |
| print(received_output_as_dict) |
| print_in_color() |
| print(received_output_as_dict) |
| print_in_color() |
| assert received_value is not None |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "expected_outputs"), |
| [ |
| ( |
| pytest.param( |
| ("INTHEWILD.md",), |
| { |
| "selected-providers-list-as-string": None, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "false", |
| "run-amazon-tests": "false", |
| "docs-build": "false", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_ON_NO_CI_IMAGE, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": None, |
| "providers-test-types-list-as-strings-in-json": None, |
| "individual-providers-test-types-list-as-strings-in-json": None, |
| "run-mypy-providers": "false", |
| }, |
| id="No tests on simple change", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("pyproject.toml",), |
| { |
| "ci-image-build": "true", |
| }, |
| id="CI image build and when pyproject.toml change", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("airflow-core/src/airflow/api/file.py",), |
| { |
| "full-tests-needed": "false", |
| "selected-providers-list-as-string": "common.compat fab", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "false", |
| "run-api-tests": "true", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_ONLY_API_SOURCE_CHANGED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "API...Always", "test_types": "API Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "common.compat,fab", "test_types": "Providers[common.compat,fab]"}] |
| ), |
| "individual-providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "common.compat...fab", |
| "test_types": "Providers[common.compat] Providers[fab]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "false", |
| }, |
| id="API source change (no spec) runs API + fab only, not the full matrix", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("airflow-core/src/airflow/api_fastapi/file.py",), |
| { |
| "full-tests-needed": "false", |
| "selected-providers-list-as-string": "common.compat fab", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "false", |
| "run-api-tests": "true", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_ONLY_API_SOURCE_CHANGED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "API...Always", "test_types": "API Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "common.compat,fab", "test_types": "Providers[common.compat,fab]"}] |
| ), |
| "individual-providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "common.compat...fab", |
| "test_types": "Providers[common.compat] Providers[fab]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "false", |
| }, |
| id="fastapi source change (no spec) runs API + fab only, not the full matrix", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("airflow-core/tests/unit/api/file.py",), |
| { |
| "full-tests-needed": "false", |
| "selected-providers-list-as-string": "common.compat fab", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "false", |
| "run-api-tests": "true", |
| "docs-build": "false", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_ONLY_API_SOURCE_CHANGED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "API...Always", "test_types": "API Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "common.compat,fab", "test_types": "Providers[common.compat,fab]"}] |
| ), |
| "individual-providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "common.compat...fab", |
| "test_types": "Providers[common.compat] Providers[fab]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "false", |
| }, |
| id="API test change (no spec) runs API + fab only, not the full matrix", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("airflow-core/src/airflow/serialization/python.py",), |
| { |
| "selected-providers-list-as-string": None, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "false", |
| "docs-build": "true", |
| "skip-prek-hooks": ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ), |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| _get_test_list_as_json( |
| _split_list(sorted(["Always", "Core", "Serialization"]), NUMBER_OF_CORE_SLICES) |
| ) |
| ), |
| "providers-test-types-list-as-strings-in-json": None, |
| "individual-providers-test-types-list-as-strings-in-json": None, |
| "run-mypy-providers": "false", |
| "skip-providers-tests": "true", |
| }, |
| id="Only Serialization tests", |
| ) |
| ), |
| ( |
| pytest.param( |
| ( |
| "airflow-core/src/airflow/api/file.py", |
| "providers/postgres/tests/unit/postgres/file.py", |
| ), |
| { |
| "full-tests-needed": "false", |
| "selected-providers-list-as-string": "amazon common.compat common.sql fab google " |
| "microsoft.azure openlineage pgvector postgres", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "true", |
| "run-api-tests": "true", |
| "docs-build": "true", |
| "skip-prek-hooks": ( |
| "check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering," |
| "mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ), |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "API...Always", "test_types": "API Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "amazon...google", |
| "test_types": "Providers[amazon] " |
| "Providers[common.compat,common.sql,fab,microsoft.azure,openlineage,pgvector,postgres] " |
| "Providers[google]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "true", |
| }, |
| id="API source + provider change runs API + affected providers, not the full matrix", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("providers/apache/beam/tests/unit/apache/beam/file.py",), |
| { |
| "selected-providers-list-as-string": "common.compat google", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "false", |
| "docs-build": "false", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NO_UI_AND_HELM_TESTS, |
| "run-kubernetes-tests": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "common.compat...google", |
| "test_types": "Providers[common.compat] Providers[google]", |
| } |
| ] |
| ), |
| "individual-providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "common.compat...google", |
| "test_types": "Providers[common.compat] Providers[google]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "true", |
| }, |
| id="Selected Providers and docs should run", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("providers/apache/beam/tests/unit/apache/beam/file.py",), |
| { |
| "selected-providers-list-as-string": "common.compat google", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "false", |
| "docs-build": "false", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NO_UI_AND_HELM_TESTS, |
| "run-kubernetes-tests": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "common.compat...google", |
| "test_types": "Providers[common.compat] Providers[google]", |
| } |
| ] |
| ), |
| "individual-providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "common.compat...google", |
| "test_types": "Providers[common.compat] Providers[google]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "true", |
| "skip-providers-tests": "false", |
| }, |
| id="Selected Providers should run when system tests are modified", |
| ) |
| ), |
| ( |
| pytest.param( |
| ( |
| "providers/apache/beam/tests/system/apache/beam/file.py", |
| "providers/apache/beam/tests/unit/apache/beam/file.py", |
| ), |
| { |
| "selected-providers-list-as-string": "common.compat google", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "false", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NO_UI_AND_HELM_TESTS, |
| "run-kubernetes-tests": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "common.compat...google", |
| "test_types": "Providers[common.compat] Providers[google]", |
| } |
| ] |
| ), |
| "individual-providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "common.compat...google", |
| "test_types": "Providers[common.compat] Providers[google]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "true", |
| "skip-providers-tests": "false", |
| }, |
| id="Selected Providers and docs should run when both system tests and tests are modified", |
| ) |
| ), |
| ( |
| pytest.param( |
| ( |
| "providers/apache/beam/tests/system/apache/beam/file.py", |
| "providers/apache/beam/tests/unit/apache/beam/file.py", |
| ), |
| { |
| "selected-providers-list-as-string": "common.compat google", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "false", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NO_UI_AND_HELM_TESTS, |
| "run-kubernetes-tests": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "common.compat...google", |
| "test_types": "Providers[common.compat] Providers[google]", |
| } |
| ] |
| ), |
| "individual-providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "common.compat...google", |
| "test_types": "Providers[common.compat] Providers[google]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "true", |
| "skip-providers-tests": "false", |
| }, |
| id="Selected Providers and docs should run when both system tests and tests are modified for more than one provider", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("docs/file.rst",), |
| { |
| "selected-providers-list-as-string": None, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "false", |
| "run-amazon-tests": "false", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_ON_NO_CI_IMAGE, |
| "run-kubernetes-tests": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": None, |
| "providers-test-types-list-as-strings-in-json": None, |
| "run-mypy-providers": "false", |
| }, |
| id="Only docs builds should run - no tests needed", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("task-sdk/src/airflow/sdk/random.py",), |
| { |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-api-tests": "false", |
| "run-helm-tests": "false", |
| "run-kubernetes-tests": "false", |
| "run-unit-tests": "true", |
| "run-task-sdk-tests": "true", |
| "run-task-sdk-integration-tests": "true", |
| "docs-build": "true", |
| "full-tests-needed": "false", |
| "skip-prek-hooks": ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ), |
| "skip-providers-tests": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| id="Task SDK source file changed - Task SDK, Core and provider tests should run", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("task-sdk-integration-tests/tests/airflow/sdk/random.py",), |
| { |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-api-tests": "false", |
| "run-helm-tests": "false", |
| "run-kubernetes-tests": "false", |
| "run-unit-tests": "false", |
| "run-task-sdk-tests": "false", |
| "run-task-sdk-integration-tests": "true", |
| "docs-build": "false", |
| "full-tests-needed": "false", |
| "skip-prek-hooks": ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ), |
| "skip-providers-tests": "true", |
| "upgrade-to-newer-dependencies": "false", |
| "run-mypy-providers": "false", |
| }, |
| id="Task SDK integration tests files changed - " |
| "Task SDK integration tests and prod image build should run but no other tests", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("ts-sdk/src/coordinator/runtime.ts",), |
| { |
| "prod-image-build": "true", |
| "run-unit-tests": "false", |
| "run-task-sdk-tests": "false", |
| "run-task-sdk-integration-tests": "false", |
| "run-ts-sdk-e2e-tests": "true", |
| "run-go-sdk-e2e-tests": "false", |
| "full-tests-needed": "false", |
| }, |
| id="TypeScript SDK files changed - TS SDK e2e tests and prod image build should run", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("ts-sdk/README.md",), |
| { |
| "prod-image-build": "false", |
| "run-ts-sdk-e2e-tests": "false", |
| "full-tests-needed": "false", |
| }, |
| id="TypeScript SDK README-only change - TS SDK e2e tests should be skipped", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("airflow-ctl/src/airflowctl/random.py",), |
| { |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-api-tests": "false", |
| "run-helm-tests": "false", |
| "run-kubernetes-tests": "false", |
| "run-unit-tests": "true", |
| "run-airflow-ctl-tests": "true", |
| "run-airflow-ctl-integration-tests": "true", |
| "docs-build": "true", |
| "full-tests-needed": "false", |
| "skip-prek-hooks": ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-core,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ), |
| "skip-providers-tests": "true", |
| "upgrade-to-newer-dependencies": "false", |
| "run-mypy-providers": "false", |
| }, |
| id="Airflow CTL source file changed - Airflow CTL tests should run", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("airflow-ctl-tests/tests/random.py",), |
| { |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-api-tests": "false", |
| "run-helm-tests": "false", |
| "run-kubernetes-tests": "false", |
| "run-unit-tests": "false", |
| "run-airflow-ctl-tests": "false", |
| "run-airflow-ctl-integration-tests": "true", |
| "docs-build": "false", |
| "full-tests-needed": "false", |
| "skip-prek-hooks": ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ), |
| "skip-providers-tests": "true", |
| "upgrade-to-newer-dependencies": "false", |
| "run-mypy-providers": "false", |
| }, |
| id="Airflow CTL integration tests files changed - " |
| "Airflow CTL integration tests and prod image build should run but no other tests", |
| ) |
| ), |
| ( |
| pytest.param( |
| ( |
| "chart/aaaa.txt", |
| "providers/postgres/tests/unit/postgres/file.py", |
| ), |
| { |
| "selected-providers-list-as-string": "amazon common.compat common.sql google " |
| "microsoft.azure openlineage pgvector postgres", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "true", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NO_UI, |
| "run-kubernetes-tests": "true", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "amazon...google", |
| "test_types": "Providers[amazon] " |
| "Providers[common.compat,common.sql,microsoft.azure,openlineage,pgvector,postgres] " |
| "Providers[google]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "true", |
| }, |
| id="Helm tests, providers (both upstream and downstream)," |
| "kubernetes tests and docs should run", |
| ) |
| ), |
| ( |
| pytest.param( |
| ( |
| "INTHEWILD.md", |
| "chart/aaaa.txt", |
| "providers/http/tests/file.py", |
| ), |
| { |
| "selected-providers-list-as-string": "amazon apache.livy atlassian.jira common.compat dbt.cloud dingding discord google http informatica pagerduty", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "true", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NO_UI, |
| "run-kubernetes-tests": "true", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "amazon...google", |
| "test_types": "Providers[amazon] Providers[apache.livy,atlassian.jira,common.compat,dbt.cloud,dingding,discord,http,informatica,pagerduty] Providers[google]", |
| } |
| ] |
| ), |
| "individual-providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "amazon...atlassian.jir", |
| "test_types": "Providers[amazon] Providers[apache.livy] Providers[atlassian.jira]", |
| }, |
| { |
| "description": "common.compat...dbt.cloud", |
| "test_types": "Providers[common.compat] Providers[dbt.cloud]", |
| }, |
| { |
| "description": "dingding...discord", |
| "test_types": "Providers[dingding] Providers[discord]", |
| }, |
| { |
| "description": "google...http", |
| "test_types": "Providers[google] Providers[http]", |
| }, |
| { |
| "description": "informatica...pagerduty", |
| "test_types": "Providers[informatica] Providers[pagerduty]", |
| }, |
| ] |
| ), |
| "run-mypy-providers": "true", |
| }, |
| id="Helm tests, http and all relevant providers, kubernetes tests and " |
| "docs should run even if unimportant files were added", |
| ) |
| ), |
| ( |
| pytest.param( |
| ( |
| "INTHEWILD.md", |
| "chart/aaaa.txt", |
| "providers/airbyte/tests/file.py", |
| ), |
| { |
| "selected-providers-list-as-string": "airbyte common.compat", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "false", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NO_UI, |
| "run-kubernetes-tests": "true", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "airbyte,common.compat", |
| "test_types": "Providers[airbyte,common.compat]", |
| } |
| ] |
| ), |
| }, |
| id="Helm tests, airbyte providers, kubernetes tests and " |
| "docs should run even if unimportant files were added", |
| ) |
| ), |
| ( |
| pytest.param( |
| ( |
| "INTHEWILD.md", |
| "chart/aaaa.txt", |
| "foo/other.py", |
| ), |
| { |
| "selected-providers-list-as-string": None, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "false", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NO_PROVIDERS_AND_UI, |
| "run-amazon-tests": "false", |
| "run-kubernetes-tests": "true", |
| "upgrade-to-newer-dependencies": "false", |
| "providers-test-types-list-as-strings-in-json": None, |
| "run-mypy-providers": "false", |
| }, |
| id="Docs should run even if unimportant files were added and prod image " |
| "should be build for chart changes", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("pyproject.toml",), |
| { |
| "selected-providers-list-as-string": ALL_PROVIDERS_AFFECTED, |
| "all-python-versions": ALL_PYTHON_VERSIONS_AS_LIST, |
| "all-python-versions-list-as-string": ALL_PYTHON_VERSIONS_AS_STRING, |
| "python-versions": ALL_PYTHON_VERSIONS_AS_LIST, |
| "python-versions-list-as-string": ALL_PYTHON_VERSIONS_AS_STRING, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "true", |
| "docs-build": "true", |
| "full-tests-needed": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": "true", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| id="Everything should run and upgrading to newer requirements as dependencies change", |
| ) |
| ), |
| pytest.param( |
| ("providers/amazon/src/airflow/providers/amazon/provider.yaml",), |
| { |
| "selected-providers-list-as-string": "amazon apache.hive cncf.kubernetes " |
| "common.compat common.messaging common.sql databricks exasol ftp google http imap microsoft.azure " |
| "mongo mysql openlineage postgres salesforce ssh teradata", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "docs-build": "false", |
| # no python files changed so flynt should not run |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NO_UI_AND_HELM_TESTS.replace( |
| "check-ts-sdk-supervisor-schema,", "check-ts-sdk-supervisor-schema,flynt,", 1 |
| ), |
| "run-kubernetes-tests": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "run-amazon-tests": "true", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "amazon...google", |
| "test_types": "Providers[amazon] Providers[apache.hive,cncf.kubernetes," |
| "common.compat,common.messaging,common.sql,databricks,exasol,ftp,http,imap," |
| "microsoft.azure,mongo,mysql,openlineage,postgres,salesforce,ssh,teradata] " |
| "Providers[google]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "true", |
| }, |
| id="Providers tests run including amazon tests if only amazon provider.yaml files changed", |
| ), |
| pytest.param( |
| ("providers/airbyte/tests/airbyte/__init__.py",), |
| { |
| "selected-providers-list-as-string": "airbyte common.compat", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "false", |
| "docs-build": "false", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NO_UI_AND_HELM_TESTS, |
| "run-kubernetes-tests": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "airbyte,common.compat", |
| "test_types": "Providers[airbyte,common.compat]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "true", |
| }, |
| id="Providers tests run without amazon tests if no amazon file changed", |
| ), |
| pytest.param( |
| ("providers/amazon/src/airflow/providers/amazon/file.py",), |
| { |
| "selected-providers-list-as-string": "amazon apache.hive cncf.kubernetes " |
| "common.compat common.messaging common.sql databricks exasol ftp google http imap microsoft.azure " |
| "mongo mysql openlineage postgres salesforce ssh teradata", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "true", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NO_UI_AND_HELM_TESTS, |
| "run-kubernetes-tests": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "amazon...google", |
| "test_types": "Providers[amazon] Providers[apache.hive,cncf.kubernetes," |
| "common.compat,common.messaging,common.sql,databricks,exasol,ftp,http,imap," |
| "microsoft.azure,mongo,mysql,openlineage,postgres,salesforce,ssh,teradata] " |
| "Providers[google]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "true", |
| }, |
| id="Providers tests run including amazon tests if amazon provider files changed", |
| ), |
| pytest.param( |
| ( |
| "airflow-core/tests/unit/always/test_project_structure.py", |
| "providers/common/io/tests/operators/__init__.py", |
| "providers/common/io/tests/operators/test_file_transfer.py", |
| ), |
| { |
| "selected-providers-list-as-string": "common.compat common.io openlineage", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| # common providers feed OpenLineage e2e tests, which need the PROD image. |
| "prod-image-build": "true", |
| "run-openlineage-e2e-tests": "true", |
| # ordinary OL PR (no canary, no "full tests needed" label): compat matrix stays off. |
| "run-openlineage-e2e-compat-tests": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "false", |
| "docs-build": "false", |
| "run-kubernetes-tests": "false", |
| "skip-prek-hooks": ( |
| "check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ), |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "common.compat,common.io,openl", |
| "test_types": "Providers[common.compat,common.io,openlineage]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "true", |
| }, |
| id="Only Always and common providers tests should run when only common.io and tests/always changed", |
| ), |
| pytest.param( |
| ("providers/standard/src/airflow/providers/standard/operators/bash.py",), |
| { |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "true", |
| "docs-build": "true", |
| "run-kubernetes-tests": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| id="All tests to run when standard operator changed", |
| ), |
| ( |
| pytest.param( |
| ("airflow-core/tests/unit/utils/test_cli_util.py",), |
| { |
| "selected-providers-list-as-string": ALL_PROVIDERS_AFFECTED, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "true", |
| "docs-build": "true", |
| "full-tests-needed": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| id="All tests should be run when tests/utils/ change", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("devel-common/src/tests_common/test_utils/__init__.py",), |
| { |
| "selected-providers-list-as-string": ALL_PROVIDERS_AFFECTED, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "true", |
| "run-amazon-tests": "true", |
| "docs-build": "true", |
| "full-tests-needed": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, |
| "testable-core-integrations": "['kerberos', 'otel', 'redis']", |
| "testable-providers-integrations": "['celery', 'cassandra', 'drill', 'elasticsearch', 'tinkerpop', 'kafka', " |
| "'mongo', 'pinot', 'qdrant', 'redis', 'trino', 'ydb']", |
| "run-mypy-providers": "true", |
| }, |
| id="All tests should be run when devel-common/ change", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("airflow-core/src/airflow/ui/src/index.tsx",), |
| { |
| "selected-providers-list-as-string": None, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "docs-build": "false", |
| "full-tests-needed": "false", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NO_CODE_PROVIDERS_AND_HELM_TESTS, |
| "upgrade-to-newer-dependencies": "false", |
| "run-mypy-providers": "false", |
| "run-helm-tests": "false", |
| "run-ui-tests": "true", |
| "run-ui-e2e-tests": "true", |
| "run-unit-tests": "false", |
| "run-go-sdk-tests": "false", |
| "run-airflow-ctl-tests": "false", |
| "run-amazon-tests": "false", |
| }, |
| id="Run only ui tests for PR with new UI only changes.", |
| ) |
| ), |
| pytest.param( |
| ("RELEASE_NOTES.rst",), |
| { |
| "selected-providers-list-as-string": None, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "run-helm-tests": "false", |
| "run-unit-tests": "false", |
| "run-amazon-tests": "false", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_ON_NO_CI_IMAGE, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": None, |
| "providers-test-types-list-as-strings-in-json": None, |
| "individual-providers-test-types-list-as-strings-in-json": None, |
| "run-mypy-providers": "false", |
| }, |
| id="Run docs-build for RELEASE_NOTES.rst", |
| ), |
| pytest.param( |
| ("chart/RELEASE_NOTES.rst",), |
| { |
| "selected-providers-list-as-string": None, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "false", |
| "run-amazon-tests": "false", |
| "docs-build": "true", |
| "skip-prek-hooks": ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,flynt,identity,ktlint," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ), |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": None, |
| "providers-test-types-list-as-strings-in-json": None, |
| "individual-providers-test-types-list-as-strings-in-json": None, |
| "run-mypy-providers": "false", |
| }, |
| id="Run docs-build for chart/RELEASE_NOTES.rst", |
| ), |
| pytest.param( |
| (".github/SECURITY.md",), |
| { |
| "selected-providers-list-as-string": None, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "run-helm-tests": "false", |
| "run-unit-tests": "false", |
| "run-amazon-tests": "false", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_ON_NO_CI_IMAGE, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": None, |
| "providers-test-types-list-as-strings-in-json": None, |
| "individual-providers-test-types-list-as-strings-in-json": None, |
| "run-mypy-providers": "false", |
| }, |
| id="Run docs-build for SECURITY.md", |
| ), |
| pytest.param( |
| ("go-sdk/sdk/variable.go",), |
| { |
| "run-go-sdk-tests": "true", |
| "run-java-sdk-e2e-tests": "false", |
| }, |
| id="Run go tests for go-sdk and skip java e2e tests for non-java change", |
| ), |
| pytest.param( |
| ("java-sdk/sdk/build.gradle.kts",), |
| { |
| "run-java-sdk-tests": "true", |
| "run-java-sdk-e2e-tests": "true", |
| "prod-image-build": "true", |
| }, |
| id="Run java unit and e2e tests for java-sdk source change", |
| ), |
| pytest.param( |
| ("java-sdk/README.md",), |
| { |
| "run-java-sdk-tests": "false", |
| "run-java-sdk-e2e-tests": "false", |
| "prod-image-build": "false", |
| }, |
| id="Skip java unit and e2e tests for java-sdk README-only change", |
| ), |
| pytest.param( |
| ("airflow-e2e-tests/docker/java.yml",), |
| { |
| "run-java-sdk-tests": "false", |
| "run-java-sdk-e2e-tests": "true", |
| "prod-image-build": "true", |
| }, |
| id="Run java e2e tests when java compose override changes", |
| ), |
| pytest.param( |
| ("task-sdk/src/airflow/sdk/coordinators/java/coordinator.py",), |
| { |
| "run-java-sdk-e2e-tests": "true", |
| "prod-image-build": "true", |
| }, |
| id="Run java e2e tests when JavaCoordinator changes", |
| ), |
| pytest.param( |
| ("go-sdk/sdk/variable.go",), |
| { |
| "run-go-sdk-tests": "true", |
| "run-go-sdk-e2e-tests": "true", |
| "prod-image-build": "true", |
| }, |
| id="Run go unit and e2e tests for go-sdk source change", |
| ), |
| pytest.param( |
| ("go-sdk/go.mod",), |
| { |
| "run-go-sdk-tests": "true", |
| "run-go-sdk-e2e-tests": "true", |
| "prod-image-build": "true", |
| }, |
| id="Run go unit and e2e tests for go-sdk dependency change", |
| ), |
| pytest.param( |
| ("go-sdk/README.md",), |
| { |
| "run-go-sdk-tests": "false", |
| "run-go-sdk-e2e-tests": "false", |
| "prod-image-build": "false", |
| }, |
| id="Skip go unit and e2e tests for go-sdk README-only change", |
| ), |
| pytest.param( |
| ("go-sdk/adr/0001-bundle-packing-options.md",), |
| { |
| "run-go-sdk-tests": "false", |
| "run-go-sdk-e2e-tests": "false", |
| "prod-image-build": "false", |
| }, |
| id="Skip go unit and e2e tests for go-sdk ADR-only change", |
| ), |
| pytest.param( |
| ("airflow-e2e-tests/docker/go.yml",), |
| { |
| "run-go-sdk-tests": "false", |
| "run-go-sdk-e2e-tests": "true", |
| "prod-image-build": "true", |
| }, |
| id="Run go e2e tests when go compose override changes", |
| ), |
| pytest.param( |
| ("task-sdk/src/airflow/sdk/coordinators/executable/coordinator.py",), |
| { |
| "run-go-sdk-e2e-tests": "true", |
| "prod-image-build": "true", |
| }, |
| id="Run go e2e tests when ExecutableCoordinator changes", |
| ), |
| pytest.param( |
| ("providers/openlineage/src/airflow/providers/openlineage/plugins/adapter.py",), |
| { |
| "run-openlineage-e2e-tests": "true", |
| "prod-image-build": "true", |
| }, |
| id="Run OpenLineage e2e tests for openlineage provider change", |
| ), |
| pytest.param( |
| ("providers/common/compat/src/airflow/providers/common/compat/sdk.py",), |
| { |
| "run-openlineage-e2e-tests": "true", |
| "prod-image-build": "true", |
| }, |
| id="Run OpenLineage e2e tests for common provider change", |
| ), |
| pytest.param( |
| ("airflow-e2e-tests/tests/airflow_e2e_tests/openlineage_tests/harness.py",), |
| { |
| "run-openlineage-e2e-tests": "true", |
| "run-openlineage-e2e-compat-tests": "false", |
| "prod-image-build": "true", |
| }, |
| id="Run OpenLineage e2e tests (not the costly compat matrix) when the OL e2e suite changes", |
| ), |
| pytest.param( |
| ("providers/ftp/src/airflow/providers/ftp/hooks/ftp.py",), |
| { |
| "run-openlineage-e2e-tests": "false", |
| "run-openlineage-e2e-compat-tests": "false", |
| "prod-image-build": "false", |
| }, |
| id="Do not run OpenLineage e2e tests for unrelated provider change", |
| ), |
| pytest.param( |
| ("airflow-e2e-tests/tests/airflow_e2e_tests/conftest.py",), |
| { |
| "run-openlineage-e2e-tests": "false", |
| "run-openlineage-e2e-compat-tests": "true", |
| "full-tests-needed": "false", |
| "prod-image-build": "true", |
| }, |
| id="Run OpenLineage e2e compat tests when the shared e2e harness (conftest) changes", |
| ), |
| pytest.param( |
| ("airflow-e2e-tests/docker/openlineage-compat.Dockerfile",), |
| { |
| "run-openlineage-e2e-tests": "false", |
| "run-openlineage-e2e-compat-tests": "true", |
| "full-tests-needed": "false", |
| "prod-image-build": "true", |
| }, |
| id="Run OpenLineage e2e compat tests when the compat Dockerfile changes", |
| ), |
| pytest.param( |
| (".github/workflows/openlineage-e2e-compat-tests.yml",), |
| { |
| # The compat workflow matches ENVIRONMENT_FILES, so it forces the full matrix. |
| # The compat therefore runs via full_tests_needed, not via OPENLINEAGE_E2E_COMPAT_FILES. |
| "run-openlineage-e2e-tests": "true", |
| "run-openlineage-e2e-compat-tests": "true", |
| "full-tests-needed": "true", |
| }, |
| id="Compat workflow change forces the full matrix (compat runs via full_tests_needed)", |
| ), |
| ( |
| pytest.param( |
| ("devel-common/pyproject.toml",), |
| { |
| "run-mypy-providers": "true", |
| }, |
| id="All mypy checks should run when devel-common/pyproject.toml changes", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("providers/amazon/src/airflow/providers/amazon/aws/log/s3_task_handler.py",), |
| { |
| "run-remote-logging-s3-e2e-tests": "true", |
| "run-remote-logging-elasticsearch-e2e-tests": "false", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| }, |
| id="S3 remote logging changes enable only S3 e2e", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("providers/elasticsearch/src/airflow/providers/elasticsearch/log/es_task_handler.py",), |
| { |
| "run-remote-logging-s3-e2e-tests": "false", |
| "run-remote-logging-elasticsearch-e2e-tests": "true", |
| "run-remote-logging-opensearch-e2e-tests": "false", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| }, |
| id="Elasticsearch remote logging changes enable only Elasticsearch e2e", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("providers/elasticsearch/src/airflow/providers/elasticsearch/log/es_json_formatter.py",), |
| { |
| "run-remote-logging-s3-e2e-tests": "false", |
| "run-remote-logging-elasticsearch-e2e-tests": "true", |
| "run-remote-logging-opensearch-e2e-tests": "false", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| }, |
| id="Elasticsearch helper changes enable Elasticsearch e2e", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("providers/opensearch/src/airflow/providers/opensearch/log/os_task_handler.py",), |
| { |
| "run-remote-logging-s3-e2e-tests": "false", |
| "run-remote-logging-elasticsearch-e2e-tests": "false", |
| "run-remote-logging-opensearch-e2e-tests": "true", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| }, |
| id="OpenSearch remote logging changes enable only OpenSearch e2e", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("providers/opensearch/src/airflow/providers/opensearch/log/os_json_formatter.py",), |
| { |
| "run-remote-logging-s3-e2e-tests": "false", |
| "run-remote-logging-elasticsearch-e2e-tests": "false", |
| "run-remote-logging-opensearch-e2e-tests": "true", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| }, |
| id="OpenSearch helper changes enable OpenSearch e2e", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("airflow-core/src/airflow/config_templates/airflow_local_settings.py",), |
| { |
| "run-remote-logging-s3-e2e-tests": "true", |
| "run-remote-logging-elasticsearch-e2e-tests": "true", |
| "run-remote-logging-opensearch-e2e-tests": "true", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| }, |
| id="Shared remote logging changes enable both remote logging e2e jobs", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("shared/logging/src/airflow_shared/logging/remote.py",), |
| { |
| "run-remote-logging-s3-e2e-tests": "true", |
| "run-remote-logging-elasticsearch-e2e-tests": "true", |
| "run-remote-logging-opensearch-e2e-tests": "true", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| }, |
| id="Shared logging library changes enable both remote logging e2e jobs", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("shared/timezones/src/airflow_shared/timezones/timezone.py",), |
| { |
| "ci-image-build": "true", |
| "run-unit-tests": "true", |
| }, |
| id="Shared library python changes trigger unit tests", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("shared/logging/src/airflow_shared/logging/remote.py",), |
| { |
| "skip-prek-hooks": ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-core,mypy-airflow-ctl,mypy-airflow-ctl-tests," |
| "mypy-airflow-e2e-tests,mypy-dev,mypy-devel-common,mypy-docker-tests," |
| "mypy-helm-tests,mypy-kubernetes-tests,mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners," |
| "mypy-shared-module_loading,mypy-shared-observability," |
| "mypy-shared-plugins_manager,mypy-shared-providers_discovery," |
| "mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering," |
| "mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ), |
| }, |
| id=("Shared logging change keeps only mypy-shared-logging among the mypy-shared-* hooks"), |
| ) |
| ), |
| ], |
| ) |
| def test_expected_output_pull_request_main( |
| files: tuple[str, ...], |
| expected_outputs: dict[str, str], |
| ): |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| pr_labels=tuple(), |
| default_branch="main", |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "ktlint_skipped"), |
| [ |
| pytest.param( |
| ("java-sdk/sdk/build.gradle.kts",), |
| False, |
| id="ktlint runs when java-sdk files change", |
| ), |
| pytest.param( |
| ("SECURITY.md",), |
| True, |
| id="ktlint skipped when no java-sdk files change", |
| ), |
| pytest.param( |
| ("java-sdk/README.md",), |
| True, |
| id="ktlint skipped when only java-sdk docs change", |
| ), |
| ], |
| ) |
| def test_ktlint_hook_only_runs_for_java_sdk_changes(files: tuple[str, ...], ktlint_skipped: bool): |
| # ktlint downloads the Gradle distribution, so it must be skipped unless java-sdk changed. |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| pr_labels=tuple(), |
| default_branch="main", |
| ) |
| skipped_hooks = get_outputs_from_stderr(str(stderr))["skip-prek-hooks"].split(",") |
| assert ("ktlint" in skipped_hooks) is ktlint_skipped |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "hook_skipped"), |
| [ |
| pytest.param( |
| ("ts-sdk/src/generated/supervisor.ts",), |
| False, |
| id="runs when ts-sdk files change", |
| ), |
| pytest.param( |
| ("task-sdk/src/airflow/sdk/execution_time/schema/schema.json",), |
| True, |
| id="skipped when only the supervisor schema changes", |
| ), |
| pytest.param( |
| ("SECURITY.md",), |
| True, |
| id="skipped when no ts-sdk files change", |
| ), |
| pytest.param( |
| ("ts-sdk/README.md",), |
| True, |
| id="skipped when only ts-sdk docs change", |
| ), |
| pytest.param( |
| ("ts-sdk/example/README.md",), |
| True, |
| id="skipped when only nested ts-sdk docs change", |
| ), |
| ], |
| ) |
| def test_check_ts_sdk_supervisor_schema_hook_only_runs_for_relevant_changes( |
| files: tuple[str, ...], hook_skipped: bool |
| ): |
| # This hook regenerates and diffs ts-sdk/src/generated/supervisor.ts. Only ts-sdk changes |
| # trigger it; regenerating after a wire-schema bump is the ts-sdk follow-up PR's job. |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| pr_labels=tuple(), |
| default_branch="main", |
| ) |
| skipped_hooks = get_outputs_from_stderr(str(stderr))["skip-prek-hooks"].split(",") |
| assert ("check-ts-sdk-supervisor-schema" in skipped_hooks) is hook_skipped |
| |
| |
| def test_java_sdk_version_is_emitted_as_output(): |
| # The lang-SDK k8s job reads this to pick the JDK for the native Java build via actions/setup-java. |
| stderr = SelectiveChecks( |
| files=("README.md",), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| pr_labels=tuple(), |
| default_branch="main", |
| ) |
| assert get_outputs_from_stderr(str(stderr))["java-sdk-version"] == JAVA_SDK_VERSION |
| |
| |
| @pytest.mark.skipif( |
| not (AIRFLOW_ROOT_PATH / ".git").exists(), |
| reason="This test should not run if .git folder is missing (for example by default in breeze container)", |
| ) |
| @pytest.mark.parametrize( |
| ("files", "commit_ref", "expected_outputs"), |
| [ |
| ( |
| pytest.param( |
| ("pyproject.toml",), |
| "c381fdaff42bbda480eee70fb15c5b26a2a3a77d", |
| { |
| "full-tests-needed": "true", |
| "all-versions": "true", |
| }, |
| id="Full tests needed / all versions when build-system changes in pyproject.toml", |
| ) |
| ), |
| ], |
| ) |
| def test_full_test_needed_when_pyproject_toml_changes( |
| files: tuple[str, ...], commit_ref: str, expected_outputs: dict[str, str] |
| ): |
| stderr = SelectiveChecks( |
| files=files, |
| github_event=GithubEvents.PULL_REQUEST, |
| commit_ref=commit_ref, |
| default_branch="main", |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "github_event", "expected_outputs"), |
| [ |
| pytest.param( |
| ("README.md",), |
| GithubEvents.PULL_REQUEST, |
| { |
| "run-unit-tests": "false", |
| "ci-image-build": "false", |
| "docs-build": "false", |
| }, |
| id="Only .md file changed in PR - no tests needed", |
| ), |
| pytest.param( |
| ("requirements.txt", "NOTICE.txt"), |
| GithubEvents.PULL_REQUEST, |
| { |
| "run-unit-tests": "false", |
| "ci-image-build": "false", |
| "docs-build": "false", |
| }, |
| id="Only .txt files changed in PR - no tests needed", |
| ), |
| pytest.param( |
| ("README.md", "airflow-core/src/airflow/api.py"), |
| GithubEvents.PULL_REQUEST, |
| { |
| "run-unit-tests": "true", |
| "ci-image-build": "true", |
| }, |
| id="Mixed .md and source file changed - tests needed", |
| ), |
| ], |
| ) |
| def test_text_non_doc_files_do_not_trigger_tests( |
| files: tuple[str, ...], github_event: str, expected_outputs: dict[str, str] |
| ): |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=github_event, |
| pr_labels=(), |
| default_branch="main", |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| def test_list_splitting(): |
| stderr = SelectiveChecks( |
| pr_labels=("full tests needed",), |
| default_branch="main", |
| ) |
| output_dict = get_outputs_from_stderr(str(stderr)) |
| individual_providers_test_types_list_as_string = json.loads( |
| output_dict["individual-providers-test-types-list-as-strings-in-json"] |
| ) |
| all_providers_in_sub_lists = [ |
| list_of_types["test_types"].split(" ") |
| for list_of_types in individual_providers_test_types_list_as_string |
| ] |
| assert len(all_providers_in_sub_lists) == NUMBER_OF_LOW_DEP_SLICES |
| assert sum([len(list_of_types) for list_of_types in all_providers_in_sub_lists]) == len( |
| LIST_OF_ALL_PROVIDER_TESTS |
| ) |
| |
| |
| def test_excluded_providers(): |
| stderr = SelectiveChecks( |
| files=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ) |
| assert_outputs_are_printed( |
| { |
| "excluded-providers-as-string": json.dumps( |
| { |
| "3.14": [ |
| "apache.cassandra", # Enable when the next release after 3.29.3 is available |
| ], |
| } |
| ), |
| }, |
| str(stderr), |
| ) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "expected_outputs"), |
| [ |
| ( |
| pytest.param( |
| ("scripts/ci/prek/file.sh",), |
| { |
| # prek hooks are static checks, not tests: they must not force the full |
| # test matrix, but they still build the CI image so mypy-scripts and the |
| # image-based static checks run. |
| "full-tests-needed": "false", |
| "ci-image-build": "true", |
| }, |
| id="prek scripts build the CI image but do not force full tests", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("scripts/docker-compose/test.yml",), |
| { |
| "full-tests-needed": "true", |
| }, |
| id="Full tests needed when docker-compose changes", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("scripts/ci/kubernetes/some_file.txt",), |
| { |
| "full-tests-needed": "true", |
| }, |
| id="Full tests needed when ci/kubernetes changes", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("scripts/in_container/script.sh",), |
| { |
| "full-tests-needed": "true", |
| }, |
| id="Full tests needed when in_container script changes", |
| ) |
| ), |
| ], |
| ) |
| def test_full_test_needed_when_scripts_changes(files: tuple[str, ...], expected_outputs: dict[str, str]): |
| stderr = SelectiveChecks( |
| files=files, |
| github_event=GithubEvents.PULL_REQUEST, |
| commit_ref=NEUTRAL_COMMIT, |
| default_branch="main", |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| "files", |
| [ |
| pytest.param( |
| ("scripts/ci/prek/check_provider_yaml_files.py",), |
| id="provider yaml check script changed", |
| ), |
| pytest.param( |
| ("providers/.pre-commit-config.yaml",), |
| id="providers prek config changed", |
| ), |
| pytest.param( |
| ( |
| "scripts/ci/prek/check_provider_yaml_files.py", |
| "providers/.pre-commit-config.yaml", |
| ), |
| id="provider yaml check script and providers prek config changed together", |
| ), |
| ], |
| ) |
| def test_provider_yaml_check_not_skipped_when_check_scripts_change(files: tuple[str, ...]): |
| stderr = SelectiveChecks( |
| files=files, |
| github_event=GithubEvents.PULL_REQUEST, |
| commit_ref=NEUTRAL_COMMIT, |
| default_branch="main", |
| ) |
| skip_prek_hooks = str(stderr).split("skip-prek-hooks=")[1].split("\n")[0] |
| assert "check-provider-yaml-valid" not in skip_prek_hooks.split(",") |
| |
| |
| @pytest.mark.parametrize( |
| "files", |
| [ |
| pytest.param( |
| ("airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml",), |
| id="private UI spec changed", |
| ), |
| pytest.param( |
| ( |
| "airflow-core/src/airflow/api_fastapi/auth/managers/simple/openapi/v2-simple-auth-manager-generated.yaml", |
| ), |
| id="simple auth manager spec changed", |
| ), |
| ], |
| ) |
| def test_ui_compile_hooks_not_skipped_when_ui_openapi_spec_changes(files: tuple[str, ...]): |
| stderr = SelectiveChecks( |
| files=files, |
| github_event=GithubEvents.PULL_REQUEST, |
| commit_ref=NEUTRAL_COMMIT, |
| default_branch="main", |
| ) |
| skip_prek_hooks = str(stderr).split("skip-prek-hooks=")[1].split("\n")[0] |
| assert "ts-compile-lint-ui" not in skip_prek_hooks.split(",") |
| assert "ts-compile-lint-simple-auth-manager-ui" not in skip_prek_hooks.split(",") |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "expected_outputs"), |
| [ |
| pytest.param( |
| (".github/workflows/ci-amd.yml",), |
| {"full-tests-needed": "true"}, |
| id="Test workflow (ci-amd) forces full tests", |
| ), |
| pytest.param( |
| (".github/workflows/run-unit-tests.yml",), |
| {"full-tests-needed": "true"}, |
| id="Test workflow (run-unit-tests) forces full tests", |
| ), |
| pytest.param( |
| (".github/workflows/codeql-analysis.yml",), |
| {"full-tests-needed": "false"}, |
| id="Non-test workflow (codeql) does not force full tests", |
| ), |
| pytest.param( |
| (".github/workflows/publish-docs-to-s3.yml",), |
| {"full-tests-needed": "false"}, |
| id="Non-test workflow (publish-docs-to-s3) does not force full tests", |
| ), |
| pytest.param( |
| (".github/workflows/ci-notification.yml",), |
| {"full-tests-needed": "false"}, |
| id="Non-test workflow (ci-notification) does not force full tests", |
| ), |
| ], |
| ) |
| def test_non_test_workflows_do_not_force_full_tests(files: tuple[str, ...], expected_outputs: dict[str, str]): |
| stderr = SelectiveChecks( |
| files=files, |
| github_event=GithubEvents.PULL_REQUEST, |
| commit_ref=NEUTRAL_COMMIT, |
| default_branch="main", |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "pr_labels", "default_branch", "expected_outputs"), |
| [ |
| ( |
| pytest.param( |
| ("providers/git/src/airflow/providers/git/test_file.py",), |
| (), |
| "main", |
| { |
| "selected-providers-list-as-string": ALL_PROVIDERS_AFFECTED, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "all-versions": "false", |
| "mysql-versions": "['8.0']", |
| "postgres-versions": "['14']", |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "kubernetes-versions": f"['{DEFAULT_KUBERNETES_VERSION}']", |
| "kubernetes-versions-list-as-string": DEFAULT_KUBERNETES_VERSION, |
| "kubernetes-combos-list-as-string": f"{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}-{DEFAULT_KUBERNETES_VERSION}", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "false", |
| "docs-build": "true", |
| "docs-list-as-string": ALL_DOCS_SELECTED_FOR_BUILD, |
| "full-tests-needed": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| id="Everything should run including all providers when git provider is changed" |
| "(special case for now)", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("INTHEWILD.md",), |
| ("full tests needed", "all versions"), |
| "main", |
| { |
| "selected-providers-list-as-string": ALL_PROVIDERS_AFFECTED, |
| "all-versions": "true", |
| "all-python-versions": ALL_PYTHON_VERSIONS_AS_LIST, |
| "all-python-versions-list-as-string": ALL_PYTHON_VERSIONS_AS_STRING, |
| "mysql-versions": "['8.0', '8.4']", |
| "postgres-versions": "['14', '15', '16', '17', '18']", |
| "python-versions": ALL_PYTHON_VERSIONS_AS_LIST, |
| "python-versions-list-as-string": ALL_PYTHON_VERSIONS_AS_STRING, |
| "kubernetes-versions": ALL_KUBERNETES_VERSIONS_AS_LIST, |
| "kubernetes-versions-list-as-string": ALL_KUBERNETES_VERSIONS_AS_STRING, |
| "kubernetes-combos-list-as-string": ZIP_PYTHON_AND_KUBERNETES_VERSIONS_AS_STRING, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "false", |
| "docs-build": "true", |
| "docs-list-as-string": ALL_DOCS_SELECTED_FOR_BUILD, |
| "full-tests-needed": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| id="Everything should run including all providers when full tests are needed, " |
| "and all versions are required.", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("INTHEWILD.md",), |
| ("full tests needed", "default versions only"), |
| "main", |
| { |
| "selected-providers-list-as-string": ALL_PROVIDERS_AFFECTED, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "all-versions": "false", |
| "mysql-versions": "['8.0']", |
| "postgres-versions": "['14']", |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "kubernetes-versions": f"['{DEFAULT_KUBERNETES_VERSION}']", |
| "kubernetes-versions-list-as-string": DEFAULT_KUBERNETES_VERSION, |
| "kubernetes-combos-list-as-string": f"{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}-{DEFAULT_KUBERNETES_VERSION}", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "false", |
| "docs-build": "true", |
| "docs-list-as-string": ALL_DOCS_SELECTED_FOR_BUILD, |
| "full-tests-needed": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| id="Everything should run including all providers when full tests are needed " |
| "but with single python and kubernetes if `default versions only` label is set", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("INTHEWILD.md",), |
| ("full tests needed",), |
| "main", |
| { |
| "selected-providers-list-as-string": ALL_PROVIDERS_AFFECTED, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "all-versions": "false", |
| "mysql-versions": "['8.0']", |
| "postgres-versions": "['14']", |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "kubernetes-versions": f"['{DEFAULT_KUBERNETES_VERSION}']", |
| "kubernetes-versions-list-as-string": DEFAULT_KUBERNETES_VERSION, |
| "kubernetes-combos-list-as-string": f"{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}-{DEFAULT_KUBERNETES_VERSION}", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "false", |
| "docs-build": "true", |
| "docs-list-as-string": ALL_DOCS_SELECTED_FOR_BUILD, |
| "full-tests-needed": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| "run-ui-e2e-tests": "true", |
| "run-openlineage-e2e-compat-tests": "true", |
| }, |
| id="Everything should run including all providers when full tests are needed " |
| "but with single python and kubernetes if no version label is set", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("INTHEWILD.md",), |
| ("full tests needed", "latest versions only"), |
| "main", |
| { |
| "selected-providers-list-as-string": ALL_PROVIDERS_AFFECTED, |
| "all-python-versions": f"['{ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS[-1]}']", |
| "all-python-versions-list-as-string": f"{ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS[-1]}", |
| "all-versions": "false", |
| "default-python-version": f"{ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS[-1]}", |
| "mysql-versions": "['8.4']", |
| "postgres-versions": "['18']", |
| "python-versions": f"['{ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS[-1]}']", |
| "python-versions-list-as-string": f"{ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS[-1]}", |
| "kubernetes-versions": f"['{ALLOWED_KUBERNETES_VERSIONS[-1]}']", |
| "kubernetes-versions-list-as-string": f"{ALLOWED_KUBERNETES_VERSIONS[-1]}", |
| "kubernetes-combos-list-as-string": f"{ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS[-1]}-{ALLOWED_KUBERNETES_VERSIONS[-1]}", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "false", |
| "docs-build": "true", |
| "docs-list-as-string": ALL_DOCS_SELECTED_FOR_BUILD, |
| "full-tests-needed": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| id="Everything should run including all providers when full tests are needed " |
| "but with single python and kubernetes if `latest versions only` label is set", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("INTHEWILD.md",), |
| ( |
| "another label", |
| "full tests needed", |
| ), |
| "main", |
| { |
| "selected-providers-list-as-string": ALL_PROVIDERS_AFFECTED, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "all-versions": "false", |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "kubernetes-versions": f"['{DEFAULT_KUBERNETES_VERSION}']", |
| "kubernetes-versions-list-as-string": DEFAULT_KUBERNETES_VERSION, |
| "kubernetes-combos-list-as-string": f"{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}-{DEFAULT_KUBERNETES_VERSION}", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "false", |
| "docs-build": "true", |
| "docs-list-as-string": ALL_DOCS_SELECTED_FOR_BUILD, |
| "full-tests-needed": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| id="Everything should run including full providers when full " |
| "tests are needed even with different label set as well", |
| ) |
| ), |
| ( |
| pytest.param( |
| (), |
| ("full tests needed",), |
| "main", |
| { |
| "selected-providers-list-as-string": ALL_PROVIDERS_AFFECTED, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "all-versions": "false", |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "kubernetes-versions": f"['{DEFAULT_KUBERNETES_VERSION}']", |
| "kubernetes-versions-list-as-string": DEFAULT_KUBERNETES_VERSION, |
| "kubernetes-combos-list-as-string": f"{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}-{DEFAULT_KUBERNETES_VERSION}", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "false", |
| "docs-build": "true", |
| "docs-list-as-string": ALL_DOCS_SELECTED_FOR_BUILD, |
| "full-tests-needed": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": ALL_PROVIDERS_SELECTIVE_TEST_TYPES_AS_JSON, |
| "individual-providers-test-types-list-as-strings-in-json": LIST_OF_ALL_PROVIDER_TESTS_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| id="Everything should run including full providers when " |
| "full tests are needed even if no files are changed", |
| ) |
| ), |
| ( |
| pytest.param( |
| ("INTHEWILD.md", "providers/asana/tests/asana.py"), |
| ("full tests needed",), |
| "v2-7-stable", |
| { |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "all-versions": "false", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "true", |
| "docs-build": "true", |
| "docs-list-as-string": "apache-airflow docker-stack", |
| "full-tests-needed": "true", |
| "skip-prek-hooks": All_SKIPPED_COMMITS_IF_NON_MAIN_BRANCH, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "false", |
| }, |
| id="Everything should run except Providers and lint prek " |
| "when full tests are needed for non-main branch", |
| ) |
| ), |
| ], |
| ) |
| def test_expected_output_full_tests_needed( |
| files: tuple[str, ...], |
| pr_labels: tuple[str, ...], |
| default_branch: str, |
| expected_outputs: dict[str, str], |
| ): |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| pr_labels=pr_labels, |
| default_branch=default_branch, |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "expected_outputs"), |
| [ |
| pytest.param( |
| ("INTHEWILD.md",), |
| { |
| "selected-providers-list-as-string": None, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "false", |
| "skip-providers-tests": "true", |
| "docs-build": "false", |
| "docs-list-as-string": None, |
| "full-tests-needed": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": None, |
| "run-mypy-providers": "false", |
| }, |
| id="Nothing should run if only non-important files changed", |
| ), |
| pytest.param( |
| ( |
| "chart/aaaa.txt", |
| "providers/google/tests/unit/google/file.py", |
| ), |
| { |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "run-helm-tests": "false", |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "true", |
| "docs-build": "true", |
| "docs-list-as-string": "apache-airflow docker-stack", |
| "full-tests-needed": "false", |
| "run-kubernetes-tests": "true", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "run-mypy-providers": "false", |
| }, |
| id="No Helm tests, No providers no lint charts, should run if " |
| "only chart/providers changed in non-main but PROD image should be built", |
| ), |
| pytest.param( |
| ( |
| "airflow-core/src/airflow/cli/test.py", |
| "chart/aaaa.txt", |
| "providers/google/tests/unit/google/file.py", |
| ), |
| { |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "true", |
| "docs-build": "true", |
| "docs-list-as-string": "apache-airflow docker-stack", |
| "full-tests-needed": "false", |
| "run-kubernetes-tests": "true", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always...CLI", "test_types": "Always CLI"}] |
| ), |
| "run-mypy-providers": "false", |
| }, |
| id="Only CLI tests and Kubernetes tests should run if cli/chart files changed in non-main branch", |
| ), |
| pytest.param( |
| ( |
| "airflow-core/src/airflow/file.py", |
| "providers/google/tests/unit/google/file.py", |
| ), |
| { |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "true", |
| "docs-build": "true", |
| "docs-list-as-string": "apache-airflow docker-stack", |
| "full-tests-needed": "false", |
| "run-kubernetes-tests": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "false", |
| }, |
| id="All tests except Providers and helm lint prek " |
| "should run if core file changed in non-main branch", |
| ), |
| ], |
| ) |
| def test_expected_output_pull_request_v2_7( |
| files: tuple[str, ...], |
| expected_outputs: dict[str, str], |
| ): |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| pr_labels=(), |
| default_branch="v2-7-stable", |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "pr_labels", "default_branch", "expected_outputs"), |
| [ |
| pytest.param( |
| ("INTHEWILD.md",), |
| (), |
| "main", |
| { |
| "selected-providers-list-as-string": None, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "false", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "false", |
| "skip-providers-tests": "true", |
| "docs-build": "false", |
| "docs-list-as-string": None, |
| "upgrade-to-newer-dependencies": "false", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NOT_IMPORTANT_FILES_CHANGED, |
| "core-test-types-list-as-strings-in-json": None, |
| "run-mypy-providers": "false", |
| }, |
| id="No tests run on push if only text non-doc files changed", |
| ), |
| pytest.param( |
| ("INTHEWILD.md",), |
| (), |
| "v2-3-stable", |
| { |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "false", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "false", |
| "skip-providers-tests": "true", |
| "docs-build": "false", |
| "docs-list-as-string": None, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": None, |
| "run-mypy-providers": "false", |
| }, |
| id="No tests run on push if only text non-doc files changed in non-main branch", |
| ), |
| pytest.param( |
| ("airflow-core/src/airflow/api.py",), |
| (), |
| "main", |
| { |
| "selected-providers-list-as-string": ALL_PROVIDERS_AFFECTED, |
| "all-python-versions": ALL_PYTHON_VERSIONS_AS_LIST, |
| "all-python-versions-list-as-string": ALL_PYTHON_VERSIONS_AS_STRING, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "true", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "docs-list-as-string": ALL_DOCS_SELECTED_FOR_BUILD, |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| "run-ui-e2e-tests": "false", |
| }, |
| id="All tests run on push if core file changed", |
| ), |
| ], |
| ) |
| def test_expected_output_push( |
| files: tuple[str, ...], |
| pr_labels: tuple[str, ...], |
| default_branch: str, |
| expected_outputs: dict[str, str], |
| ): |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PUSH, |
| pr_labels=pr_labels, |
| default_branch=default_branch, |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "expected_outputs"), |
| [ |
| pytest.param( |
| ("INTHEWILD.md",), |
| { |
| "selected-providers-list-as-string": None, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "false", |
| "skip-providers-tests": "true", |
| "docs-build": "false", |
| "docs-list-as-string": None, |
| "upgrade-to-newer-dependencies": "false", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NOT_IMPORTANT_FILES_CHANGED, |
| "core-test-types-list-as-strings-in-json": None, |
| "run-mypy-providers": "false", |
| }, |
| id="Nothing should run if only non-important files changed", |
| ), |
| pytest.param( |
| ("airflow-core/tests/system/any_file.py",), |
| { |
| "selected-providers-list-as-string": None, |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "true", |
| "docs-build": "true", |
| "docs-list-as-string": ALL_DOCS_SELECTED_FOR_BUILD, |
| "skip-prek-hooks": ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ), |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always", "test_types": "Always"}] |
| ), |
| "run-mypy-providers": "false", |
| }, |
| id="Only Always and docs build should run if only system tests changed", |
| ), |
| pytest.param( |
| ( |
| "airflow-core/src/airflow/cli/test.py", |
| "chart/aaaa.txt", |
| "providers/google/tests/unit/google/file.py", |
| ), |
| { |
| "selected-providers-list-as-string": "amazon apache.cassandra apache.kafka " |
| "cncf.kubernetes common.compat common.messaging common.sql databricks " |
| "facebook google hashicorp http microsoft.azure microsoft.mssql mongo mysql " |
| "openlineage oracle postgres presto salesforce samba sftp ssh standard trino", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "false", |
| "docs-build": "true", |
| "docs-list-as-string": "apache-airflow helm-chart amazon apache.cassandra " |
| "apache.kafka cncf.kubernetes common.compat common.messaging common.sql databricks facebook google hashicorp http microsoft.azure " |
| "microsoft.mssql mongo mysql openlineage oracle postgres " |
| "presto salesforce samba sftp ssh standard trino", |
| "skip-prek-hooks": ( |
| "check-ts-sdk-supervisor-schema,identity,ktlint,mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ), |
| "run-kubernetes-tests": "true", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": json.dumps( |
| [{"description": "Always...CLI", "test_types": "Always CLI"}] |
| ), |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "amazon...standard", |
| "test_types": "Providers[amazon] Providers[apache.cassandra," |
| "apache.kafka,cncf.kubernetes,common.compat,common.messaging,common.sql,databricks,facebook," |
| "hashicorp,http,microsoft.azure,microsoft.mssql,mongo,mysql," |
| "openlineage,oracle,postgres,presto,salesforce,samba,sftp,ssh,trino] " |
| "Providers[google] " |
| "Providers[standard]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "true", |
| }, |
| id="CLI tests and Google-related provider tests should run if cli/chart files changed but " |
| "prod image should be build too and k8s tests too", |
| ), |
| pytest.param( |
| ("airflow-core/src/airflow/models/test.py",), |
| { |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "true", |
| "docs-build": "true", |
| "docs-list-as-string": "apache-airflow", |
| "skip-prek-hooks": ( |
| "check-provider-yaml-valid,check-ts-sdk-supervisor-schema,identity,ktlint,lint-helm-chart," |
| "mypy-airflow-ctl,mypy-airflow-ctl-tests,mypy-airflow-e2e-tests," |
| "mypy-dev,mypy-devel-common,mypy-docker-tests,mypy-helm-tests,mypy-kubernetes-tests," |
| "mypy-scripts," |
| "mypy-shared-configuration,mypy-shared-dagnode,mypy-shared-listeners,mypy-shared-logging," |
| "mypy-shared-module_loading,mypy-shared-observability,mypy-shared-plugins_manager," |
| "mypy-shared-providers_discovery,mypy-shared-secrets_backend,mypy-shared-secrets_masker," |
| "mypy-shared-serialization,mypy-shared-state,mypy-shared-template_rendering,mypy-shared-timezones,mypy-task-sdk,mypy-task-sdk-integration-tests," |
| "ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui,update-uv-lock" |
| ), |
| "run-kubernetes-tests": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "false", |
| }, |
| id="Tests for all airflow core types except providers should run if model file changed", |
| ), |
| pytest.param( |
| ("airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml",), |
| { |
| # The OpenAPI spec IS the API contract — changing it ripples to the UI |
| # codegen and generated clients, so it still forces the full matrix. |
| "full-tests-needed": "true", |
| "selected-providers-list-as-string": "", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "false", |
| "docs-build": "true", |
| "docs-list-as-string": "", |
| "upgrade-to-newer-dependencies": "false", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| id="OpenAPI spec change still forces the full matrix", |
| ), |
| pytest.param( |
| ("airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml",), |
| { |
| # Rationale on the UI_OPENAPI_FILES group in selective_checks.py. One param per |
| # spec directory so each pattern of the group is pinned individually - with both |
| # files in one param, dropping either pattern would still pass via the other file. |
| "full-tests-needed": "false", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_ONLY_UI_OPENAPI_CHANGED, |
| }, |
| id="Private UI OpenAPI spec change runs the UI compile hooks without the full matrix", |
| ), |
| pytest.param( |
| ( |
| "airflow-core/src/airflow/api_fastapi/auth/managers/simple/openapi/v2-simple-auth-manager-generated.yaml", |
| ), |
| { |
| "full-tests-needed": "false", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_ONLY_UI_OPENAPI_CHANGED, |
| }, |
| id="Simple auth manager OpenAPI spec change runs the UI compile hooks", |
| ), |
| pytest.param( |
| ( |
| "airflow-core/src/airflow/assets/", |
| "airflow-core/src/airflow/models/assets/", |
| "task-sdk/src/airflow/sdk/definitions/asset/", |
| "airflow-core/src/airflow/datasets/", |
| ), |
| { |
| "selected-providers-list-as-string": "amazon common.compat common.io common.sql " |
| "databricks dbt.cloud ftp google jdbc microsoft.azure microsoft.mssql mysql " |
| "openlineage oracle postgres sftp snowflake standard trino", |
| "all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']", |
| "all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION, |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| "run-unit-tests": "true", |
| "skip-providers-tests": "false", |
| "docs-build": "false", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_ON_NO_CI_IMAGE, |
| "run-kubernetes-tests": "false", |
| "upgrade-to-newer-dependencies": "false", |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "providers-test-types-list-as-strings-in-json": json.dumps( |
| [ |
| { |
| "description": "amazon...standard", |
| "test_types": "Providers[amazon] Providers[common.compat,common.io,common.sql," |
| "databricks,dbt.cloud,ftp,jdbc,microsoft.azure,microsoft.mssql,mysql,openlineage,oracle," |
| "postgres,sftp,snowflake,trino] Providers[google] Providers[standard]", |
| } |
| ] |
| ), |
| "run-mypy-providers": "false", |
| }, |
| id="Trigger openlineage and related providers tests when Assets files changed", |
| ), |
| ], |
| ) |
| def test_expected_output_pull_request_target( |
| files: tuple[str, ...], |
| expected_outputs: dict[str, str], |
| ): |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST_TARGET, |
| pr_labels=(), |
| default_branch="main", |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| "github_event", |
| [ |
| GithubEvents.PUSH, |
| GithubEvents.PULL_REQUEST, |
| GithubEvents.PULL_REQUEST_TARGET, |
| GithubEvents.PULL_REQUEST_WORKFLOW, |
| GithubEvents.SCHEDULE, |
| ], |
| ) |
| def test_no_commit_provided_trigger_full_build_for_any_event_type(github_event): |
| stderr = SelectiveChecks( |
| files=(), |
| commit_ref="", |
| github_event=github_event, |
| pr_labels=(), |
| default_branch="main", |
| ) |
| assert_outputs_are_printed( |
| { |
| "all-python-versions": ALL_PYTHON_VERSIONS_AS_LIST, |
| "all-python-versions-list-as-string": ALL_PYTHON_VERSIONS_AS_STRING, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "true", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": ("true" if github_event == GithubEvents.SCHEDULE else "false"), |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| str(stderr), |
| ) |
| |
| |
| # The image cache is pushed for `python-versions`, so a narrowed list leaves the remaining |
| # versions with no cache and they build from scratch on every run. `refresh-image-registry-cache.yml` |
| # forces the label below for exactly that reason; this pins the behaviour it relies on. |
| |
| |
| def test_all_python_versions_with_all_versions_label(): |
| """Set on the event that would otherwise narrow: a text-only push.""" |
| stderr = SelectiveChecks( |
| files=("INTHEWILD.md",), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PUSH, |
| pr_labels=("all versions",), |
| default_branch="main", |
| ) |
| assert_outputs_are_printed({"python-versions": CURRENT_PYTHON_VERSIONS_AS_LIST}, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| "github_event", |
| [ |
| GithubEvents.PUSH, |
| GithubEvents.SCHEDULE, |
| ], |
| ) |
| def test_files_provided_trigger_full_build_for_any_event_type(github_event): |
| stderr = SelectiveChecks( |
| files=( |
| "airflow-core/src/airflow/ui/src/pages/Run/Details.tsx", |
| "airflow-core/src/airflow/ui/src/router.tsx", |
| ), |
| commit_ref="", |
| github_event=github_event, |
| pr_labels=(), |
| default_branch="main", |
| ) |
| assert_outputs_are_printed( |
| { |
| "all-python-versions": ALL_PYTHON_VERSIONS_AS_LIST, |
| "all-python-versions-list-as-string": ALL_PYTHON_VERSIONS_AS_STRING, |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| "run-unit-tests": "true", |
| "docs-build": "true", |
| "skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED, |
| "upgrade-to-newer-dependencies": ("true" if github_event == GithubEvents.SCHEDULE else "false"), |
| "core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON, |
| "run-mypy-providers": "true", |
| }, |
| str(stderr), |
| ) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "expected_outputs", "pr_labels", "commit_ref"), |
| [ |
| pytest.param( |
| ("airflow-core/src/airflow/models/dag.py",), |
| { |
| "upgrade-to-newer-dependencies": "false", |
| }, |
| (), |
| None, |
| id="Regular source changed", |
| ), |
| pytest.param( |
| ("providers/microsoft/azure/src/airflow/providers/microsoft/azure/provider.yaml",), |
| { |
| "upgrade-to-newer-dependencies": "false", |
| }, |
| (), |
| None, |
| id="Provider.yaml changed", |
| ), |
| pytest.param( |
| ("airflow-core/src/airflow/models/dag.py",), |
| { |
| "upgrade-to-newer-dependencies": "true", |
| }, |
| ("upgrade to newer dependencies",), |
| None, |
| id="Regular source changed", |
| ), |
| ], |
| ) |
| def test_upgrade_to_newer_dependencies( |
| files: tuple[str, ...], |
| expected_outputs: dict[str, str], |
| pr_labels: tuple[str, ...], |
| commit_ref: str | None, |
| ): |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=commit_ref, |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| pr_labels=pr_labels, |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "expected_outputs"), |
| [ |
| pytest.param( |
| ("providers/google/docs/some_file.rst",), |
| { |
| "docs-list-as-string": "amazon apache.cassandra apache.kafka " |
| "cncf.kubernetes common.compat common.messaging common.sql databricks facebook google hashicorp http " |
| "microsoft.azure microsoft.mssql mongo mysql openlineage oracle " |
| "postgres presto salesforce samba sftp ssh standard trino", |
| }, |
| id="Google provider docs changed", |
| ), |
| pytest.param( |
| ("providers/common/sql/src/airflow/providers/common/sql/common_sql_python.py",), |
| { |
| "docs-list-as-string": "amazon apache.drill apache.druid apache.hive apache.iceberg " |
| "apache.impala apache.pinot clickhousedb common.ai common.compat common.sql databricks elasticsearch " |
| "exasol google informatica jdbc microsoft.mssql mysql odbc openlineage " |
| "oracle pgvector postgres presto slack snowflake sqlite teradata trino vertica ydb", |
| }, |
| id="Common SQL provider package python files changed", |
| ), |
| pytest.param( |
| ("providers/airbyte/docs/some_file.rst",), |
| { |
| "docs-list-as-string": "airbyte common.compat", |
| }, |
| id="Airbyte provider docs changed", |
| ), |
| pytest.param( |
| ("providers/airbyte/docs/some_file.rst", "airflow-core/docs/docs.rst"), |
| { |
| "docs-list-as-string": "apache-airflow airbyte common.compat", |
| }, |
| id="Airbyte provider and airflow core docs changed", |
| ), |
| pytest.param( |
| ( |
| "providers/airbyte/docs/some_file.rst", |
| "airflow-core/docs/docs.rst", |
| "providers-summary-docs/docs.rst", |
| ), |
| { |
| "docs-list-as-string": "apache-airflow apache-airflow-providers airbyte common.compat", |
| }, |
| id="Airbyte provider and airflow core and common provider docs changed", |
| ), |
| pytest.param( |
| ("airflow-core/docs/docs.rst",), |
| { |
| "docs-list-as-string": "apache-airflow", |
| }, |
| id="Only Airflow docs changed", |
| ), |
| pytest.param( |
| ("providers/celery/src/airflow/providers/celery/file.py",), |
| {"docs-list-as-string": "celery cncf.kubernetes common.compat"}, |
| id="Celery python files changed", |
| ), |
| pytest.param( |
| ("docs/conf.py",), |
| { |
| "docs-list-as-string": ALL_DOCS_SELECTED_FOR_BUILD, |
| }, |
| id="Docs conf.py changed", |
| ), |
| pytest.param( |
| ("airflow-core/src/airflow/test.py",), |
| { |
| "docs-list-as-string": "apache-airflow", |
| }, |
| id="Core files changed. Apache-Airflow docs should also be built", |
| ), |
| pytest.param( |
| ("docker-stack-docs/test.rst",), |
| {"docs-list-as-string": "docker-stack"}, |
| id="Docker stack files changed. No provider docs to build", |
| ), |
| pytest.param( |
| ("airflow-core/src/airflow/test.py", "chart/airflow/values.yaml"), |
| { |
| "docs-list-as-string": "apache-airflow helm-chart", |
| }, |
| id="Core files and helm chart files changed. Apache Airflow and helm chart docs to build", |
| ), |
| pytest.param( |
| ("chart/airflow/values.yaml",), |
| { |
| "docs-list-as-string": "helm-chart", |
| }, |
| id="Helm chart files changed. No provider, airflow docs to build", |
| ), |
| pytest.param( |
| ("chart/docs/airflow/values.yaml",), |
| { |
| "docs-list-as-string": "helm-chart", |
| }, |
| id="Docs helm chart files changed. No provider, airflow docs to build", |
| ), |
| ], |
| ) |
| def test_docs_filter(files: tuple[str, ...], expected_outputs: dict[str, str]): |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| pr_labels=(), |
| default_branch="main", |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "expected_outputs"), |
| [ |
| pytest.param( |
| ("chart/tests/helm_tests/random_helm_test.py",), |
| { |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "true", |
| }, |
| id="Only helm test files changed", |
| ) |
| ], |
| ) |
| def test_helm_tests_trigger_ci_build(files: tuple[str, ...], expected_outputs: dict[str, str]): |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| pr_labels=(), |
| default_branch="main", |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "expected_outputs"), |
| [ |
| pytest.param( |
| ("providers/amazon/provider.yaml",), |
| { |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| }, |
| id="Amazon provider.yaml", |
| ), |
| pytest.param( |
| ("providers/amazon/pyproject.toml",), |
| { |
| "ci-image-build": "true", |
| "prod-image-build": "false", |
| "run-helm-tests": "false", |
| }, |
| id="Amazon pyproject.toml", |
| ), |
| pytest.param( |
| ("providers/cncf/kubernetes/provider.yaml",), |
| { |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "false", |
| }, |
| id="CNCF Kubernetes provider.yaml", |
| ), |
| pytest.param( |
| ("providers/cncf/kubernetes/pyproject.toml",), |
| { |
| "ci-image-build": "true", |
| "prod-image-build": "true", |
| "run-helm-tests": "false", |
| }, |
| id="CNCF Kubernetes pyproject.toml", |
| ), |
| ], |
| ) |
| def test_provider_yaml_or_pyproject_toml_changes_trigger_ci_build( |
| files: tuple[str, ...], expected_outputs: dict[str, str] |
| ): |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| pr_labels=(), |
| default_branch="main", |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "has_migrations"), |
| [ |
| pytest.param( |
| ("airflow-core/src/airflow/test.py",), |
| False, |
| id="No migrations", |
| ), |
| pytest.param( |
| ("airflow-core/src/airflow/migrations/test_sql", "airflow-core/src/airflow/test.py"), |
| True, |
| id="With migrations", |
| ), |
| ], |
| ) |
| def test_has_migrations(files: tuple[str, ...], has_migrations: bool): |
| stderr = str( |
| SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ) |
| ) |
| assert_outputs_are_printed({"has-migrations": str(has_migrations).lower()}, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("labels", "expected_outputs"), |
| [ |
| pytest.param( |
| (), |
| { |
| "providers-compatibility-tests-matrix": json.dumps( |
| [ |
| check |
| for check in PROVIDERS_COMPATIBILITY_TESTS_MATRIX |
| if check["python-version"] == DEFAULT_PYTHON_MAJOR_MINOR_VERSION |
| ] |
| ), |
| }, |
| id="Regular tests", |
| ), |
| pytest.param( |
| ("all versions",), |
| {"providers-compatibility-tests-matrix": json.dumps(PROVIDERS_COMPATIBILITY_TESTS_MATRIX)}, |
| id="full tests", |
| ), |
| ], |
| ) |
| def test_provider_compatibility_checks(labels: tuple[str, ...], expected_outputs: dict[str, str]): |
| stderr = SelectiveChecks( |
| files=(), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| pr_labels=labels, |
| default_branch="main", |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "expected_outputs", "default_branch", "pr_labels"), |
| [ |
| pytest.param( |
| ("README.md",), |
| { |
| "run-mypy-providers": "false", |
| }, |
| "main", |
| (), |
| id="No mypy checks on non-python files", |
| ), |
| pytest.param( |
| ("airflow-core/src/airflow/cli/file.py",), |
| { |
| "run-mypy-providers": "false", |
| }, |
| "main", |
| (), |
| id="Airflow mypy checks on airflow regular files", |
| ), |
| pytest.param( |
| ("airflow-core/src/airflow/models/file.py",), |
| { |
| "run-mypy-providers": "false", |
| }, |
| "main", |
| (), |
| id="Airflow mypy checks on airflow files with model changes.", |
| ), |
| pytest.param( |
| ("task-sdk/src/airflow/sdk/a_file.py",), |
| { |
| "run-mypy-providers": "true", |
| }, |
| "main", |
| (), |
| id="Airflow mypy checks on Task SDK files (implies providers)", |
| ), |
| pytest.param( |
| ("dev/a_package/a_file.py",), |
| { |
| "run-mypy-providers": "true", |
| }, |
| "main", |
| (), |
| id="All mypy checks on def files changed (full tests needed are implicit)", |
| ), |
| pytest.param( |
| ("readme.md",), |
| { |
| "run-mypy-providers": "true", |
| }, |
| "main", |
| ("full tests needed",), |
| id="All mypy checks on full tests needed", |
| ), |
| ], |
| ) |
| def test_mypy_matches( |
| files: tuple[str, ...], expected_outputs: dict[str, str], default_branch: str, pr_labels: tuple[str, ...] |
| ): |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| default_branch=default_branch, |
| github_event=GithubEvents.PULL_REQUEST, |
| pr_labels=pr_labels, |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |
| |
| |
| @pytest.mark.parametrize( |
| ("integration", "platform", "expected_result"), |
| [ |
| # Test integrations disabled for all CI environments |
| pytest.param( |
| "mssql", |
| CI_AMD_PLATFORM, |
| True, |
| id="mssql_disabled_on_amd", |
| ), |
| pytest.param( |
| "localstack", |
| CI_ARM_PLATFORM, |
| True, |
| id="localstack_disabled_on_arm", |
| ), |
| # Test integrations disabled only for ARM runners |
| pytest.param( |
| "kerberos", |
| CI_ARM_PLATFORM, |
| True, |
| id="kerberos_disabled_on_arm", |
| ), |
| pytest.param( |
| "drill", |
| CI_ARM_PLATFORM, |
| True, |
| id="drill_disabled_on_arm", |
| ), |
| pytest.param( |
| "tinkerpop", |
| CI_ARM_PLATFORM, |
| True, |
| id="tinkerpop_disabled_on_arm", |
| ), |
| pytest.param( |
| "pinot", |
| CI_ARM_PLATFORM, |
| True, |
| id="pinot_disabled_on_arm", |
| ), |
| pytest.param( |
| "trino", |
| CI_ARM_PLATFORM, |
| True, |
| id="trino_disabled_on_arm", |
| ), |
| pytest.param( |
| "ydb", |
| CI_ARM_PLATFORM, |
| True, |
| id="ydb_disabled_on_arm", |
| ), |
| # Test integrations that are NOT disabled on AMD runners |
| pytest.param( |
| "kerberos", |
| CI_AMD_PLATFORM, |
| False, |
| id="kerberos_enabled_on_amd", |
| ), |
| pytest.param( |
| "drill", |
| CI_AMD_PLATFORM, |
| False, |
| id="drill_enabled_on_amd", |
| ), |
| pytest.param( |
| "tinkerpop", |
| CI_AMD_PLATFORM, |
| False, |
| id="tinkerpop_enabled_on_amd", |
| ), |
| # Test an integration that is not in any disabled list |
| pytest.param( |
| "postgres", |
| CI_AMD_PLATFORM, |
| False, |
| id="postgres_enabled_on_amd", |
| ), |
| pytest.param( |
| "postgres", |
| CI_ARM_PLATFORM, |
| False, |
| id="postgres_enabled_on_arm", |
| ), |
| pytest.param( |
| "redis", |
| CI_AMD_PLATFORM, |
| False, |
| id="redis_enabled_on_amd", |
| ), |
| pytest.param( |
| "redis", |
| CI_ARM_PLATFORM, |
| False, |
| id="redis_enabled_on_arm", |
| ), |
| ], |
| ) |
| def test_is_disabled_integration(integration: str, platform: str, expected_result: bool): |
| """Test that _is_disabled_integration correctly identifies disabled integrations.""" |
| selective_checks = SelectiveChecks( |
| files=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| github_repository="apache/airflow", |
| github_context_dict={}, |
| platform=platform, |
| ) |
| |
| assert selective_checks._is_disabled_integration(integration) == expected_result |
| |
| |
| def test_testable_core_integrations_excludes_disabled(): |
| """Test that testable_core_integrations excludes disabled integrations.""" |
| with patch( |
| "airflow_breeze.utils.selective_checks.TESTABLE_CORE_INTEGRATIONS", |
| ["postgres", "kerberos"], |
| ): |
| # Test with AMD runner |
| selective_checks_amd = SelectiveChecks( |
| files=("airflow-core/tests/test_example.py",), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| platform=CI_AMD_PLATFORM, |
| ) |
| with patch.object( |
| SelectiveChecks, "full_tests_needed", new_callable=lambda: property(lambda self: True) |
| ): |
| result = selective_checks_amd.testable_core_integrations |
| assert "postgres" in result |
| assert "kerberos" in result |
| |
| |
| def test_testable_core_integrations_excludes_arm_disabled_on_arm(): |
| """Test that testable_core_integrations excludes ARM-disabled integrations on ARM runners.""" |
| with patch( |
| "airflow_breeze.utils.selective_checks.TESTABLE_CORE_INTEGRATIONS", ["postgres", "kerberos", "drill"] |
| ): |
| selective_checks_arm = SelectiveChecks( |
| files=("airflow-core/tests/test_example.py",), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.SCHEDULE, |
| github_context_dict={"ref_name": "main"}, |
| platform=CI_ARM_PLATFORM, |
| ) |
| with patch.object( |
| SelectiveChecks, "full_tests_needed", new_callable=lambda: property(lambda self: True) |
| ): |
| result = selective_checks_arm.testable_core_integrations |
| assert "postgres" in result |
| assert "kerberos" not in result |
| assert "drill" not in result |
| |
| |
| def test_testable_providers_integrations_excludes_disabled(): |
| """Test that testable_providers_integrations excludes disabled integrations.""" |
| with patch( |
| "airflow_breeze.utils.selective_checks.TESTABLE_PROVIDERS_INTEGRATIONS", |
| ["postgres", "mssql", "trino"], |
| ): |
| # Test with AMD runner - should exclude mssql (disabled for all CI) |
| selective_checks_amd = SelectiveChecks( |
| files=("providers/amazon/tests/test_example.py",), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| platform=CI_AMD_PLATFORM, |
| ) |
| with patch.object( |
| SelectiveChecks, "full_tests_needed", new_callable=lambda: property(lambda self: True) |
| ): |
| result = selective_checks_amd.testable_providers_integrations |
| assert "postgres" in result |
| assert "trino" in result |
| assert "mssql" not in result |
| |
| |
| def test_testable_providers_integrations_excludes_arm_disabled_on_arm(): |
| """Test that testable_providers_integrations excludes ARM-disabled integrations on ARM runners.""" |
| with patch( |
| "airflow_breeze.utils.selective_checks.TESTABLE_PROVIDERS_INTEGRATIONS", ["postgres", "trino", "ydb"] |
| ): |
| selective_checks_arm = SelectiveChecks( |
| files=("providers/tests/test_example.py",), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.SCHEDULE, |
| github_context_dict={"ref_name": "main"}, |
| platform=CI_ARM_PLATFORM, |
| ) |
| with patch.object( |
| SelectiveChecks, "full_tests_needed", new_callable=lambda: property(lambda self: True) |
| ): |
| result = selective_checks_arm.testable_providers_integrations |
| assert "postgres" in result |
| assert "trino" not in result |
| assert "ydb" not in result |
| |
| |
| @pytest.mark.parametrize( |
| ("changed_file", "expected_integration"), |
| [ |
| pytest.param("airflow-core/src/airflow/security/kerberos.py", "kerberos", id="kerberos-source"), |
| pytest.param("airflow-core/src/airflow/observability/stats.py", "otel", id="otel-source"), |
| pytest.param("airflow-core/tests/integration/otel/test_otel.py", "otel", id="otel-integration-tests"), |
| pytest.param("task-sdk/src/airflow/sdk/execution_time/task_runner.py", "otel", id="otel-task-runner"), |
| pytest.param("airflow-core/src/airflow/executors/executor_loader.py", "redis", id="celery-source"), |
| ], |
| ) |
| def test_testable_core_integrations_gated_by_source(changed_file, expected_integration): |
| """A core integration is only emitted when its corresponding core source group changed.""" |
| selective_checks = SelectiveChecks( |
| files=(changed_file,), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| platform=CI_AMD_PLATFORM, |
| ) |
| assert selective_checks.testable_core_integrations == [expected_integration] |
| |
| |
| def test_testable_core_integrations_empty_when_unrelated_source(): |
| """Unrelated core changes emit no core integrations (no full-tests / canary trigger).""" |
| selective_checks = SelectiveChecks( |
| files=("airflow-core/src/airflow/models/taskinstance.py",), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| platform=CI_AMD_PLATFORM, |
| ) |
| assert selective_checks.testable_core_integrations == [] |
| |
| |
| def test_testable_providers_integrations_gated_by_affected_provider(): |
| """A provider integration is only emitted when its owning provider is affected.""" |
| selective_checks = SelectiveChecks( |
| files=("providers/apache/cassandra/src/airflow/providers/apache/cassandra/hooks/cassandra.py",), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| platform=CI_AMD_PLATFORM, |
| ) |
| result = selective_checks.testable_providers_integrations |
| assert "cassandra" in result |
| # Unrelated integrations whose providers are not affected must be absent. |
| assert "mongo" not in result |
| assert "ydb" not in result |
| |
| |
| def test_individual_providers_excludes_platform_excluded_on_arm(): |
| """ibm.mq declares `excluded-platforms: [linux/arm64]`, so it must be absent from |
| the ARM individual-providers matrix (used by the Low-dep ARM canary job) and |
| present on AMD.""" |
| arm_checks = SelectiveChecks( |
| files=("airflow-core/tests/test_example.py",), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.SCHEDULE, |
| github_context_dict={"ref_name": "main"}, |
| default_branch="main", |
| pr_labels=("full tests needed",), |
| platform=CI_ARM_PLATFORM, |
| ) |
| arm_output = arm_checks.individual_providers_test_types_list_as_strings_in_json |
| assert arm_output is not None |
| assert "Providers[ibm.mq]" not in arm_output |
| |
| amd_checks = SelectiveChecks( |
| files=("airflow-core/tests/test_example.py",), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.SCHEDULE, |
| github_context_dict={"ref_name": "main"}, |
| default_branch="main", |
| pr_labels=("full tests needed",), |
| platform=CI_AMD_PLATFORM, |
| ) |
| amd_output = amd_checks.individual_providers_test_types_list_as_strings_in_json |
| assert amd_output is not None |
| assert "Providers[ibm.mq]" in amd_output |
| |
| |
| def test_run_kubernetes_tests_forced_by_label(): |
| """`area:kubernetes-tests` forces the Kubernetes tests job without pulling in |
| the full test matrix, unlike `full tests needed`.""" |
| checks = SelectiveChecks( |
| files=("INTHEWILD.md",), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| pr_labels=("area:kubernetes-tests",), |
| ) |
| assert checks.run_kubernetes_tests is True |
| assert checks.full_tests_needed is False |
| |
| |
| def test_run_kubernetes_tests_forced_by_label_with_no_changed_files(): |
| """The label still forces the Kubernetes tests job even when no files changed.""" |
| checks = SelectiveChecks( |
| files=(), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| pr_labels=("area:kubernetes-tests",), |
| ) |
| assert checks.run_kubernetes_tests is True |
| assert checks.full_tests_needed is False |
| |
| |
| @pytest.mark.parametrize("files", [("INTHEWILD.md",), ()], ids=["unrelated-file", "no-files"]) |
| def test_prod_image_build_forced_by_e2e_tests_label(files): |
| checks = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| pr_labels=("area:e2e-tests",), |
| ) |
| assert checks.prod_image_build is True |
| assert checks.full_tests_needed is False |
| |
| |
| def test_filter_platform_excluded_test_types_handles_all_shapes(): |
| """Direct unit check of the in-place filter for the three Providers[...] shapes.""" |
| checks = SelectiveChecks( |
| files=(), |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.SCHEDULE, |
| github_context_dict={"ref_name": "main"}, |
| default_branch="main", |
| ) |
| with patch.object( |
| SelectiveChecks, |
| "_platform_excluded_providers", |
| new_callable=lambda: property(lambda self: {"ibm.mq"}), |
| ): |
| # Bare match drops entry. |
| ts = {"Providers[ibm.mq]"} |
| checks._filter_platform_excluded_test_types(ts) |
| assert ts == set() |
| |
| # Combined positive form drops just the excluded id. |
| ts = {"Providers[amazon,ibm.mq,google]"} |
| checks._filter_platform_excluded_test_types(ts) |
| assert ts == {"Providers[amazon,google]"} |
| |
| # Negative form gets the excluded id appended. |
| ts = {"Providers[-amazon,celery,google,standard]"} |
| checks._filter_platform_excluded_test_types(ts) |
| assert ts == {"Providers[-amazon,celery,google,ibm.mq,standard]"} |
| |
| # Non-Providers entries are untouched. |
| ts = {"Core", "Always"} |
| checks._filter_platform_excluded_test_types(ts) |
| assert ts == {"Core", "Always"} |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_provider_dependency_bump_check_no_changes(mock_run_command): |
| """Test that provider dependency bump check passes when no pyproject.toml files are changed.""" |
| selective_checks = SelectiveChecks( |
| files=("some_other_file.py",), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ) |
| result = selective_checks.provider_dependency_bump |
| assert result is False |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_provider_dependency_bump_check_fails_on_provider_version_bump(mock_run_command): |
| """Test that provider dependency bump check fails when provider version is bumped without label.""" |
| old_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow-providers-common-sql>=1.0.0", |
| ] |
| """ |
| new_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow-providers-common-sql>=1.1.0", |
| ] |
| """ |
| |
| def side_effect(*args, **kwargs): |
| result = Mock() |
| result.returncode = 0 |
| if "^:" in args[0][2]: |
| result.stdout = old_toml |
| else: |
| result.stdout = new_toml |
| return result |
| |
| mock_run_command.side_effect = side_effect |
| |
| with pytest.raises(SystemExit): |
| SelectiveChecks( |
| files=("providers/amazon/pyproject.toml",), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ).provider_dependency_bump |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_provider_dependency_bump_check_works_on_provider_version_bump_when_pushed(mock_run_command): |
| """Test that provider dependency bump check fails when provider version is bumped without label.""" |
| old_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow-providers-common-sql>=1.0.0", |
| ] |
| """ |
| new_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow-providers-common-sql>=1.1.0", |
| ] |
| """ |
| |
| def side_effect(*args, **kwargs): |
| result = Mock() |
| result.returncode = 0 |
| if "^:" in args[0][2]: |
| result.stdout = old_toml |
| else: |
| result.stdout = new_toml |
| return result |
| |
| mock_run_command.side_effect = side_effect |
| assert not SelectiveChecks( |
| files=("providers/amazon/pyproject.toml",), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=(), |
| github_event=GithubEvents.PUSH, |
| default_branch="main", |
| ).provider_dependency_bump |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_provider_dependency_bump_check_skipped_on_release_branch(mock_run_command): |
| """Test that provider dependency bump check is a no-op on release branches (v3-X-test).""" |
| old_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow-providers-common-sql>=1.0.0", |
| ] |
| """ |
| new_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow-providers-common-sql>=1.1.0", |
| ] |
| """ |
| |
| def side_effect(*args, **kwargs): |
| result = Mock() |
| result.returncode = 0 |
| if "^:" in args[0][2]: |
| result.stdout = old_toml |
| else: |
| result.stdout = new_toml |
| return result |
| |
| mock_run_command.side_effect = side_effect |
| |
| assert not SelectiveChecks( |
| files=("providers/amazon/pyproject.toml",), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="v3-2-test", |
| ).provider_dependency_bump |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_provider_dependency_bump_check_passes_with_label(mock_run_command): |
| """Test that provider dependency bump check passes when label is set.""" |
| old_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow-providers-common-sql>=1.0.0", |
| ] |
| """ |
| new_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow-providers-common-sql>=1.1.0", |
| ] |
| """ |
| |
| def side_effect(*args, **kwargs): |
| result = Mock() |
| result.returncode = 0 |
| if "^:" in args[0][2]: |
| result.stdout = old_toml |
| else: |
| result.stdout = new_toml |
| return result |
| |
| mock_run_command.side_effect = side_effect |
| |
| selective_checks = SelectiveChecks( |
| files=("providers/amazon/pyproject.toml",), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=("allow provider dependency bump",), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ) |
| result = selective_checks.provider_dependency_bump |
| assert result is True |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_provider_dependency_bump_check_passes_on_non_provider_dependency_changes(mock_run_command): |
| """Test that provider dependency bump check passes when non-provider dependencies change.""" |
| old_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow>=2.11.0", |
| "boto3>=1.37.0", |
| ] |
| """ |
| new_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow>=2.11.0", |
| "boto3>=1.38.0", |
| ] |
| """ |
| |
| def side_effect(*args, **kwargs): |
| result = Mock() |
| result.returncode = 0 |
| if "^:" in args[0][2]: |
| result.stdout = old_toml |
| else: |
| result.stdout = new_toml |
| return result |
| |
| mock_run_command.side_effect = side_effect |
| |
| selective_checks = SelectiveChecks( |
| files=("providers/amazon/pyproject.toml",), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ) |
| result = selective_checks.provider_dependency_bump |
| assert result is False |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_provider_dependency_bump_check_in_optional_dependencies(mock_run_command): |
| """Test that provider dependency bump check works for optional-dependencies section.""" |
| old_toml = """ |
| [project.optional-dependencies] |
| "cncf.kubernetes" = [ |
| "apache-airflow-providers-cncf-kubernetes>=7.0.0", |
| ] |
| """ |
| new_toml = """ |
| [project.optional-dependencies] |
| "cncf.kubernetes" = [ |
| "apache-airflow-providers-cncf-kubernetes>=7.2.0", |
| ] |
| """ |
| |
| def side_effect(*args, **kwargs): |
| result = Mock() |
| result.returncode = 0 |
| if "^:" in args[0][2]: |
| result.stdout = old_toml |
| else: |
| result.stdout = new_toml |
| return result |
| |
| mock_run_command.side_effect = side_effect |
| |
| with pytest.raises(SystemExit): |
| _ = SelectiveChecks( |
| files=("providers/amazon/pyproject.toml",), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ).provider_dependency_bump |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_common_compat_changed_with_next_version_passes(mock_run_command): |
| """Test that check passes when common.compat changes and other provider has '# use next version'.""" |
| provider_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow>=2.11.0", |
| "apache-airflow-providers-common-compat>=1.8.0", # use next version |
| ] |
| """ |
| |
| def side_effect(*args, **kwargs): |
| result = Mock() |
| result.returncode = 0 |
| result.stdout = provider_toml |
| return result |
| |
| mock_run_command.side_effect = side_effect |
| |
| selective_checks = SelectiveChecks( |
| files=( |
| "providers/common/compat/src/airflow/providers/common/compat/file.py", |
| "providers/ftp/src/airflow/providers/ftp/hooks/ftp.py", |
| ), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ) |
| result = selective_checks.common_compat_changed_without_next_version |
| assert result is False |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_common_compat_changed_without_next_version_fails(mock_run_command): |
| """Test that check fails when common.compat changes and other provider doesn't have '# use next version'.""" |
| provider_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow>=2.11.0", |
| "apache-airflow-providers-common-compat>=1.8.0", |
| ] |
| """ |
| |
| def side_effect(*args, **kwargs): |
| result = Mock() |
| result.returncode = 0 |
| result.stdout = provider_toml |
| return result |
| |
| mock_run_command.side_effect = side_effect |
| |
| with pytest.raises(SystemExit): |
| _ = SelectiveChecks( |
| files=( |
| "providers/common/compat/src/airflow/providers/common/compat/file.py", |
| "providers/ftp/src/airflow/providers/ftp/hooks/ftp.py", |
| ), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ).common_compat_changed_without_next_version |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_common_compat_only_changed_passes(mock_run_command): |
| """Test that check passes when only common.compat provider changes.""" |
| selective_checks = SelectiveChecks( |
| files=("providers/common/compat/src/airflow/providers/common/compat/file.py",), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ) |
| result = selective_checks.common_compat_changed_without_next_version |
| assert result is False |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_common_compat_not_changed_passes(mock_run_command): |
| """Test that check passes when common.compat provider doesn't change.""" |
| selective_checks = SelectiveChecks( |
| files=("providers/ftp/src/airflow/providers/ftp/hooks/ftp.py",), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ) |
| result = selective_checks.common_compat_changed_without_next_version |
| assert result is False |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_common_compat_changed_with_provider_without_dependency_passes(mock_run_command): |
| """Test that check passes when other provider doesn't depend on common-compat.""" |
| provider_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow>=2.11.0", |
| "some-other-package>=1.0.0", |
| ] |
| """ |
| |
| def side_effect(*args, **kwargs): |
| result = Mock() |
| result.returncode = 0 |
| result.stdout = provider_toml |
| return result |
| |
| mock_run_command.side_effect = side_effect |
| |
| selective_checks = SelectiveChecks( |
| files=( |
| "providers/common/compat/src/airflow/providers/common/compat/file.py", |
| "providers/ftp/src/airflow/providers/ftp/hooks/ftp.py", |
| ), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ) |
| result = selective_checks.common_compat_changed_without_next_version |
| assert result is False |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_common_compat_changed_without_next_version_skipped_on_release_branch(mock_run_command): |
| """Test that common.compat next-version check is a no-op on release branches (v3-X-test).""" |
| provider_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow>=2.11.0", |
| "apache-airflow-providers-common-compat>=1.8.0", |
| ] |
| """ |
| |
| def side_effect(*args, **kwargs): |
| result = Mock() |
| result.returncode = 0 |
| result.stdout = provider_toml |
| return result |
| |
| mock_run_command.side_effect = side_effect |
| |
| assert not SelectiveChecks( |
| files=( |
| "providers/common/compat/src/airflow/providers/common/compat/file.py", |
| "providers/ftp/src/airflow/providers/ftp/hooks/ftp.py", |
| ), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=(), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="v3-2-test", |
| ).common_compat_changed_without_next_version |
| |
| |
| @patch("airflow_breeze.utils.selective_checks.run_command") |
| def test_common_compat_changed_without_next_version_bypassed_with_label(mock_run_command): |
| """Test that check can be bypassed with 'skip common compat check' label.""" |
| provider_toml = """ |
| [project] |
| dependencies = [ |
| "apache-airflow>=2.11.0", |
| "apache-airflow-providers-common-compat>=1.8.0", |
| ] |
| """ |
| |
| def side_effect(*args, **kwargs): |
| result = Mock() |
| result.returncode = 0 |
| result.stdout = provider_toml |
| return result |
| |
| mock_run_command.side_effect = side_effect |
| |
| selective_checks = SelectiveChecks( |
| files=( |
| "providers/common/compat/src/airflow/providers/common/compat/file.py", |
| "providers/ftp/src/airflow/providers/ftp/hooks/ftp.py", |
| ), |
| commit_ref=NEUTRAL_COMMIT, |
| pr_labels=("skip common compat check",), |
| github_event=GithubEvents.PULL_REQUEST, |
| default_branch="main", |
| ) |
| # Should pass with the skip label |
| result = selective_checks.common_compat_changed_without_next_version |
| assert result is True |
| |
| |
| @pytest.mark.parametrize( |
| ("files", "pr_labels", "expected_outputs"), |
| [ |
| pytest.param( |
| ("chart/tests/helm_tests/random_helm_test.py",), |
| (), |
| { |
| "helm-test-kubernetes-versions": DEFAULT_HELM_K8S_VERSIONS_JSON, |
| }, |
| id="Default K8s version when no all-versions label", |
| ), |
| pytest.param( |
| ("chart/tests/helm_tests/random_helm_test.py",), |
| ("all versions",), |
| { |
| "helm-test-kubernetes-versions": ALL_HELM_K8S_VERSIONS_JSON, |
| }, |
| id="First and last K8s versions when all-versions label is set", |
| ), |
| pytest.param( |
| ("INTHEWILD.md",), |
| ("full tests needed", "all versions"), |
| { |
| "helm-test-kubernetes-versions": ALL_HELM_K8S_VERSIONS_JSON, |
| "all-versions": "true", |
| }, |
| id="First and last K8s versions when full tests needed with all versions", |
| ), |
| pytest.param( |
| ("INTHEWILD.md",), |
| ("full tests needed",), |
| { |
| "helm-test-kubernetes-versions": DEFAULT_HELM_K8S_VERSIONS_JSON, |
| "all-versions": "false", |
| }, |
| id="Default K8s version when full tests needed but no all-versions label", |
| ), |
| ], |
| ) |
| def test_helm_test_kubernetes_versions( |
| files: tuple[str, ...], pr_labels: tuple[str, ...], expected_outputs: dict[str, str] |
| ): |
| stderr = SelectiveChecks( |
| files=files, |
| commit_ref=NEUTRAL_COMMIT, |
| github_event=GithubEvents.PULL_REQUEST, |
| pr_labels=pr_labels, |
| default_branch="main", |
| ) |
| assert_outputs_are_printed(expected_outputs, str(stderr)) |