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

potiuk pushed a commit to branch v3-2-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-2-test by this push:
     new ab2b50e0d5b [v3-2-test] Exclude text non-doc files from triggering 
full CI test runs (#64584) (#64809)
ab2b50e0d5b is described below

commit ab2b50e0d5bc2af420b24b064bd7941f43a850ad
Author: Jarek Potiuk <[email protected]>
AuthorDate: Mon Apr 6 22:39:13 2026 +0200

    [v3-2-test] Exclude text non-doc files from triggering full CI test runs 
(#64584) (#64809)
    
    Changes to .txt and .md files that are not part of the doc build
    should not trigger the full test suite. This adds a new
    TEXT_NON_DOC_FILES file group to selective checks and an
    only_text_non_doc_files_changed property so these files are
    subtracted from the "remaining files" set, avoiding unnecessary
    CI runs for text-only, non-doc-build changes.
    
    Also removes the overly broad `^dev/.*` pattern from the
    test-always file group since dev/ changes should be evaluated
    by more specific file group patterns.
    (cherry picked from commit aca2d59ffa7b471738e868a8aea8d2dc69fa8174)
---
 .../src/airflow_breeze/utils/selective_checks.py   |  21 ++++-
 dev/breeze/tests/test_selective_checks.py          | 101 +++++++++++++++------
 2 files changed, 94 insertions(+), 28 deletions(-)

diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py 
b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
index 5167505275a..99e74fcfa50 100644
--- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py
+++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
@@ -113,6 +113,7 @@ class FileGroupForCi(Enum):
     HELM_FILES = auto()
     DEPENDENCY_FILES = auto()
     DOC_FILES = auto()
+    TEXT_NON_DOC_FILES = auto()
     UI_FILES = auto()
     SYSTEM_TEST_FILES = auto()
     KUBERNETES_FILES = auto()
@@ -257,6 +258,10 @@ CI_FILE_GROUP_MATCHES: HashableDict[FileGroupForCi] = 
HashableDict(
             r"^chart/values\.json",
             r"^RELEASE_NOTES\.rst",
         ],
+        FileGroupForCi.TEXT_NON_DOC_FILES: [
+            r"^.*\.txt",
+            r"^.*\.md",
+        ],
         FileGroupForCi.UI_FILES: [
             r"^airflow-core/src/airflow/ui/",
             r"^airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/",
@@ -304,7 +309,6 @@ CI_FILE_GROUP_MATCHES: HashableDict[FileGroupForCi] = 
HashableDict(
             r"^helm-tests/tests/.*",
             r"^kubernetes-tests/tests/.*",
             r"^docker-tests/tests/.*",
-            r"^dev/.*",
         ],
         FileGroupForCi.SYSTEM_TEST_FILES: [
             r"^airflow-core/tests/system/",
@@ -589,6 +593,11 @@ class SelectiveChecks:
 
     def _should_run_all_tests_and_versions(self) -> bool:
         if self._github_event in [GithubEvents.PUSH, GithubEvents.SCHEDULE, 
GithubEvents.WORKFLOW_DISPATCH]:
+            if self.only_text_non_doc_files_changed:
+                console_print(
+                    f"[warning]Only text non doc files changed in 
{self._github_event}, skip full tests[/]"
+                )
+                return False
             console_print(f"[warning]Running everything because event is 
{self._github_event}[/]")
             return True
         if not self._commit_ref:
@@ -1056,6 +1065,13 @@ class SelectiveChecks:
     def only_pyproject_toml_files_changed(self) -> bool:
         return all(Path(file).name == "pyproject.toml" for file in self._files)
 
+    @cached_property
+    def only_text_non_doc_files_changed(self) -> bool:
+        text_non_doc_files = set(
+            self._matching_files(FileGroupForCi.TEXT_NON_DOC_FILES, 
CI_FILE_GROUP_MATCHES)
+        )
+        return len(self._files) > 0 and set(self._files) <= text_non_doc_files
+
     @cached_property
     def ci_image_build(self) -> bool:
         # in case pyproject.toml changed, CI image should be built - even if 
no build dependencies
@@ -1125,11 +1141,13 @@ class SelectiveChecks:
         test_always_files = 
self._matching_files(FileGroupForCi.ALWAYS_TESTS_FILES, CI_FILE_GROUP_MATCHES)
         test_ui_files = self._matching_files(FileGroupForCi.UI_FILES, 
CI_FILE_GROUP_MATCHES)
 
+        text_non_doc_files = 
self._matching_files(FileGroupForCi.TEXT_NON_DOC_FILES, CI_FILE_GROUP_MATCHES)
         remaining_files = (
             set(all_source_files)
             - set(all_providers_source_files)
             - set(all_providers_distribution_config_files)
             - set(matched_files)
+            - set(text_non_doc_files)
             - set(kubernetes_files)
             - set(system_test_files)
             - set(test_always_files)
@@ -1735,6 +1753,7 @@ class SelectiveChecks:
         return (
             self._github_event in [GithubEvents.SCHEDULE, GithubEvents.PUSH, 
GithubEvents.WORKFLOW_DISPATCH]
             and self._github_repository == APACHE_AIRFLOW_GITHUB_REPOSITORY
+            and not self.only_text_non_doc_files_changed
         ) or CANARY_LABEL in self._pr_labels
 
     @cached_property
diff --git a/dev/breeze/tests/test_selective_checks.py 
b/dev/breeze/tests/test_selective_checks.py
index 6135a9f7739..5d6ff376872 100644
--- a/dev/breeze/tests/test_selective_checks.py
+++ b/dev/breeze/tests/test_selective_checks.py
@@ -1358,6 +1358,53 @@ def test_full_test_needed_when_pyproject_toml_changes(
     assert_outputs_are_printed(expected_outputs, str(stderr))
 
 
[email protected](
+    ("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",),
@@ -1870,44 +1917,44 @@ def test_expected_output_pull_request_v2_7(
             (),
             "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",
-                "docs-list-as-string": ALL_DOCS_SELECTED_FOR_BUILD,
-                "skip-prek-hooks": 
ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED,
+                "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",
-                "core-test-types-list-as-strings-in-json": 
ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON,
-                "run-mypy": "true",
-                "mypy-checks": ALL_MYPY_CHECKS,
+                "skip-prek-hooks": 
ALL_SKIPPED_COMMITS_IF_NOT_IMPORTANT_FILES_CHANGED,
+                "core-test-types-list-as-strings-in-json": None,
+                "run-mypy": "false",
+                "mypy-checks": "[]",
             },
-            id="All tests run on push even if unimportant file changed",
+            id="No tests run on push if only text non-doc files changed",
         ),
         pytest.param(
             ("INTHEWILD.md",),
             (),
             "v2-3-stable",
             {
-                "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",
+                "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": "true",
-                "docs-build": "true",
-                "skip-prek-hooks": All_SKIPPED_COMMITS_IF_NON_MAIN_BRANCH,
-                "docs-list-as-string": "apache-airflow docker-stack",
+                "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": 
ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON,
-                "run-mypy": "true",
-                "mypy-checks": ALL_MYPY_CHECKS_EXCEPT_PROVIDERS,
+                "core-test-types-list-as-strings-in-json": None,
+                "run-mypy": "false",
+                "mypy-checks": "[]",
             },
-            id="All tests except Providers and Helm run on push"
-            " even if unimportant file changed in non-main branch",
+            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",),

Reply via email to