Skip to content

Commit 6d58df0

Browse files
committed
[v3-2-test] Exclude text non-doc files from triggering full CI test runs (apache#64584)
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 aca2d59) Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
1 parent 2eaed23 commit 6d58df0

2 files changed

Lines changed: 94 additions & 28 deletions

File tree

dev/breeze/src/airflow_breeze/utils/selective_checks.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class FileGroupForCi(Enum):
113113
HELM_FILES = auto()
114114
DEPENDENCY_FILES = auto()
115115
DOC_FILES = auto()
116+
TEXT_NON_DOC_FILES = auto()
116117
UI_FILES = auto()
117118
SYSTEM_TEST_FILES = auto()
118119
KUBERNETES_FILES = auto()
@@ -257,6 +258,10 @@ def __hash__(self):
257258
r"^chart/values\.json",
258259
r"^RELEASE_NOTES\.rst",
259260
],
261+
FileGroupForCi.TEXT_NON_DOC_FILES: [
262+
r"^.*\.txt",
263+
r"^.*\.md",
264+
],
260265
FileGroupForCi.UI_FILES: [
261266
r"^airflow-core/src/airflow/ui/",
262267
r"^airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/",
@@ -304,7 +309,6 @@ def __hash__(self):
304309
r"^helm-tests/tests/.*",
305310
r"^kubernetes-tests/tests/.*",
306311
r"^docker-tests/tests/.*",
307-
r"^dev/.*",
308312
],
309313
FileGroupForCi.SYSTEM_TEST_FILES: [
310314
r"^airflow-core/tests/system/",
@@ -589,6 +593,11 @@ def default_constraints_branch(self) -> str:
589593

590594
def _should_run_all_tests_and_versions(self) -> bool:
591595
if self._github_event in [GithubEvents.PUSH, GithubEvents.SCHEDULE, GithubEvents.WORKFLOW_DISPATCH]:
596+
if self.only_text_non_doc_files_changed:
597+
console_print(
598+
f"[warning]Only text non doc files changed in {self._github_event}, skip full tests[/]"
599+
)
600+
return False
592601
console_print(f"[warning]Running everything because event is {self._github_event}[/]")
593602
return True
594603
if not self._commit_ref:
@@ -1056,6 +1065,13 @@ def run_system_tests(self) -> bool:
10561065
def only_pyproject_toml_files_changed(self) -> bool:
10571066
return all(Path(file).name == "pyproject.toml" for file in self._files)
10581067

1068+
@cached_property
1069+
def only_text_non_doc_files_changed(self) -> bool:
1070+
text_non_doc_files = set(
1071+
self._matching_files(FileGroupForCi.TEXT_NON_DOC_FILES, CI_FILE_GROUP_MATCHES)
1072+
)
1073+
return len(self._files) > 0 and set(self._files) <= text_non_doc_files
1074+
10591075
@cached_property
10601076
def ci_image_build(self) -> bool:
10611077
# in case pyproject.toml changed, CI image should be built - even if no build dependencies
@@ -1125,11 +1141,13 @@ def _get_core_test_types_to_run(self) -> list[str]:
11251141
test_always_files = self._matching_files(FileGroupForCi.ALWAYS_TESTS_FILES, CI_FILE_GROUP_MATCHES)
11261142
test_ui_files = self._matching_files(FileGroupForCi.UI_FILES, CI_FILE_GROUP_MATCHES)
11271143

1144+
text_non_doc_files = self._matching_files(FileGroupForCi.TEXT_NON_DOC_FILES, CI_FILE_GROUP_MATCHES)
11281145
remaining_files = (
11291146
set(all_source_files)
11301147
- set(all_providers_source_files)
11311148
- set(all_providers_distribution_config_files)
11321149
- set(matched_files)
1150+
- set(text_non_doc_files)
11331151
- set(kubernetes_files)
11341152
- set(system_test_files)
11351153
- set(test_always_files)
@@ -1735,6 +1753,7 @@ def _is_canary_run(self):
17351753
return (
17361754
self._github_event in [GithubEvents.SCHEDULE, GithubEvents.PUSH, GithubEvents.WORKFLOW_DISPATCH]
17371755
and self._github_repository == APACHE_AIRFLOW_GITHUB_REPOSITORY
1756+
and not self.only_text_non_doc_files_changed
17381757
) or CANARY_LABEL in self._pr_labels
17391758

17401759
@cached_property

dev/breeze/tests/test_selective_checks.py

Lines changed: 74 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,53 @@ def test_full_test_needed_when_pyproject_toml_changes(
13581358
assert_outputs_are_printed(expected_outputs, str(stderr))
13591359

13601360

1361+
@pytest.mark.parametrize(
1362+
("files", "github_event", "expected_outputs"),
1363+
[
1364+
pytest.param(
1365+
("README.md",),
1366+
GithubEvents.PULL_REQUEST,
1367+
{
1368+
"run-unit-tests": "false",
1369+
"ci-image-build": "false",
1370+
"docs-build": "false",
1371+
},
1372+
id="Only .md file changed in PR - no tests needed",
1373+
),
1374+
pytest.param(
1375+
("requirements.txt", "NOTICE.txt"),
1376+
GithubEvents.PULL_REQUEST,
1377+
{
1378+
"run-unit-tests": "false",
1379+
"ci-image-build": "false",
1380+
"docs-build": "false",
1381+
},
1382+
id="Only .txt files changed in PR - no tests needed",
1383+
),
1384+
pytest.param(
1385+
("README.md", "airflow-core/src/airflow/api.py"),
1386+
GithubEvents.PULL_REQUEST,
1387+
{
1388+
"run-unit-tests": "true",
1389+
"ci-image-build": "true",
1390+
},
1391+
id="Mixed .md and source file changed - tests needed",
1392+
),
1393+
],
1394+
)
1395+
def test_text_non_doc_files_do_not_trigger_tests(
1396+
files: tuple[str, ...], github_event: str, expected_outputs: dict[str, str]
1397+
):
1398+
stderr = SelectiveChecks(
1399+
files=files,
1400+
commit_ref=NEUTRAL_COMMIT,
1401+
github_event=github_event,
1402+
pr_labels=(),
1403+
default_branch="main",
1404+
)
1405+
assert_outputs_are_printed(expected_outputs, str(stderr))
1406+
1407+
13611408
def test_list_splitting():
13621409
stderr = SelectiveChecks(
13631410
pr_labels=("full tests needed",),
@@ -1870,44 +1917,44 @@ def test_expected_output_pull_request_v2_7(
18701917
(),
18711918
"main",
18721919
{
1873-
"selected-providers-list-as-string": ALL_PROVIDERS_AFFECTED,
1874-
"all-python-versions": ALL_PYTHON_VERSIONS_AS_LIST,
1875-
"all-python-versions-list-as-string": ALL_PYTHON_VERSIONS_AS_STRING,
1876-
"ci-image-build": "true",
1877-
"prod-image-build": "true",
1878-
"run-helm-tests": "true",
1879-
"run-unit-tests": "true",
1880-
"docs-build": "true",
1881-
"docs-list-as-string": ALL_DOCS_SELECTED_FOR_BUILD,
1882-
"skip-prek-hooks": ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED,
1920+
"selected-providers-list-as-string": None,
1921+
"all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']",
1922+
"all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION,
1923+
"ci-image-build": "false",
1924+
"prod-image-build": "false",
1925+
"run-helm-tests": "false",
1926+
"run-unit-tests": "false",
1927+
"skip-providers-tests": "true",
1928+
"docs-build": "false",
1929+
"docs-list-as-string": None,
18831930
"upgrade-to-newer-dependencies": "false",
1884-
"core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON,
1885-
"run-mypy": "true",
1886-
"mypy-checks": ALL_MYPY_CHECKS,
1931+
"skip-prek-hooks": ALL_SKIPPED_COMMITS_IF_NOT_IMPORTANT_FILES_CHANGED,
1932+
"core-test-types-list-as-strings-in-json": None,
1933+
"run-mypy": "false",
1934+
"mypy-checks": "[]",
18871935
},
1888-
id="All tests run on push even if unimportant file changed",
1936+
id="No tests run on push if only text non-doc files changed",
18891937
),
18901938
pytest.param(
18911939
("INTHEWILD.md",),
18921940
(),
18931941
"v2-3-stable",
18941942
{
1895-
"all-python-versions": ALL_PYTHON_VERSIONS_AS_LIST,
1896-
"all-python-versions-list-as-string": ALL_PYTHON_VERSIONS_AS_STRING,
1897-
"ci-image-build": "true",
1898-
"prod-image-build": "true",
1943+
"all-python-versions": f"['{DEFAULT_PYTHON_MAJOR_MINOR_VERSION}']",
1944+
"all-python-versions-list-as-string": DEFAULT_PYTHON_MAJOR_MINOR_VERSION,
1945+
"ci-image-build": "false",
1946+
"prod-image-build": "false",
18991947
"run-helm-tests": "false",
1900-
"run-unit-tests": "true",
1901-
"docs-build": "true",
1902-
"skip-prek-hooks": All_SKIPPED_COMMITS_IF_NON_MAIN_BRANCH,
1903-
"docs-list-as-string": "apache-airflow docker-stack",
1948+
"run-unit-tests": "false",
1949+
"skip-providers-tests": "true",
1950+
"docs-build": "false",
1951+
"docs-list-as-string": None,
19041952
"upgrade-to-newer-dependencies": "false",
1905-
"core-test-types-list-as-strings-in-json": ALL_CI_SELECTIVE_TEST_TYPES_AS_JSON,
1906-
"run-mypy": "true",
1907-
"mypy-checks": ALL_MYPY_CHECKS_EXCEPT_PROVIDERS,
1953+
"core-test-types-list-as-strings-in-json": None,
1954+
"run-mypy": "false",
1955+
"mypy-checks": "[]",
19081956
},
1909-
id="All tests except Providers and Helm run on push"
1910-
" even if unimportant file changed in non-main branch",
1957+
id="No tests run on push if only text non-doc files changed in non-main branch",
19111958
),
19121959
pytest.param(
19131960
("airflow-core/src/airflow/api.py",),

0 commit comments

Comments
 (0)