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

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


The following commit(s) were added to refs/heads/v3-0-test by this push:
     new 9b7af2d95b4 [v3-0-test] Adding some intelligence to classifying 
provider commits (#52407) (#52412)
9b7af2d95b4 is described below

commit 9b7af2d95b48efa69d2c2695a94b19c4b1529a50
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Sat Jun 28 16:28:28 2025 +0200

    [v3-0-test] Adding some intelligence to classifying provider commits 
(#52407) (#52412)
    
    (cherry picked from commit bbe711e7345578455292c7d6d41b6221f76abaa8)
    
    Co-authored-by: Amogh Desai <[email protected]>
---
 .../prepare_providers/provider_documentation.py    | 87 +++++++++++++---------
 dev/breeze/tests/test_provider_documentation.py    | 52 +++++++++++++
 2 files changed, 104 insertions(+), 35 deletions(-)

diff --git 
a/dev/breeze/src/airflow_breeze/prepare_providers/provider_documentation.py 
b/dev/breeze/src/airflow_breeze/prepare_providers/provider_documentation.py
index 1eded073327..c330047b7cd 100644
--- a/dev/breeze/src/airflow_breeze/prepare_providers/provider_documentation.py
+++ b/dev/breeze/src/airflow_breeze/prepare_providers/provider_documentation.py
@@ -195,6 +195,49 @@ TYPE_OF_CHANGE_DESCRIPTION = {
 }
 
 
+def classification_result(changed_files):
+    if not changed_files:
+        return "other"
+
+    has_docs = any(re.match(r"^providers/[^/]+/docs/", f) and 
f.endswith(".rst") for f in changed_files)
+
+    has_test_or_example_only = all(
+        re.match(r"^providers/[^/]+/tests/", f)
+        or 
re.match(r"^providers/[^/]+/src/airflow/providers/[^/]+/example_dags/", f)
+        for f in changed_files
+    )
+
+    if has_docs:
+        return "documentation"
+    if has_test_or_example_only:
+        return "test_or_example_only"
+    return "other"
+
+
+def classify_provider_pr_files(commit_hash: str) -> str:
+    """
+    Classify a provider commit based on changed files.
+
+    - Returns 'documentation' if any provider doc files are present.
+    - Returns 'test_or_example_only' if only test/example DAGs changed.
+    - Returns 'other' otherwise.
+    """
+    try:
+        result = run_command(
+            ["git", "diff", "--name-only", f"{commit_hash}^", commit_hash],
+            cwd=AIRFLOW_ROOT_PATH,
+            capture_output=True,
+            text=True,
+            check=True,
+        )
+        changed_files = result.stdout.strip().splitlines()
+    except subprocess.CalledProcessError:
+        # safe to return other here
+        return "other"
+
+    return classification_result(changed_files)
+
+
 def _get_git_log_command(
     folder_paths: list[Path] | None = None, from_commit: str | None = None, 
to_commit: str | None = None
 ) -> list[str]:
@@ -715,39 +758,6 @@ def _update_commits_rst(
     )
 
 
-def _is_test_or_example_dag_only_changes(commit_hash: str) -> bool:
-    """
-    Check if a commit contains only test-related or example DAG changes
-    by using the git diff command.
-
-    Considers files in airflow/providers/{provider}/tests/
-    and 
airflow/providers/{provider}/src/airflow/providers/{provider}/example_dags/
-    as test/example-only files.
-
-    :param commit_hash: The full commit hash to check
-    :return: True if changes are only in test/example files, False otherwise
-    """
-    try:
-        result = run_command(
-            ["git", "diff", "--name-only", f"{commit_hash}^", commit_hash],
-            cwd=AIRFLOW_ROOT_PATH,
-            capture_output=True,
-            text=True,
-            check=True,
-        )
-        changed_files = result.stdout.strip().splitlines()
-
-        for file_path in changed_files:
-            if not (
-                re.match(r"providers/[^/]+/tests/", file_path)
-                or 
re.match(r"providers/[^/]+/src/airflow/providers/[^/]+/example_dags/", 
file_path)
-            ):
-                return False
-        return True
-    except subprocess.CalledProcessError:
-        return False
-
-
 def update_release_notes(
     provider_id: str,
     reapply_templates_only: bool,
@@ -817,9 +827,16 @@ def update_release_notes(
                 )
                 change = list_of_list_of_changes[0][table_iter]
 
-                if change.pr and 
_is_test_or_example_dag_only_changes(change.full_hash):
+                classification = classify_provider_pr_files(change.full_hash)
+                if classification == "documentation":
+                    get_console().print(
+                        f"[green]Automatically classifying change as 
DOCUMENTATION since it contains only doc changes:[/]\n"
+                        f"[blue]{formatted_message}[/]"
+                    )
+                    type_of_change = TypeOfChange.DOCUMENTATION
+                elif classification == "test_or_example_only":
                     get_console().print(
-                        f"[green]Automatically classifying change as SKIPPED 
since it only contains test changes:[/]\n"
+                        f"[green]Automatically classifying change as SKIPPED 
since it only contains test/example changes:[/]\n"
                         f"[blue]{formatted_message}[/]"
                     )
                     type_of_change = TypeOfChange.SKIP
diff --git a/dev/breeze/tests/test_provider_documentation.py 
b/dev/breeze/tests/test_provider_documentation.py
index 43a058c9981..b55088987c6 100644
--- a/dev/breeze/tests/test_provider_documentation.py
+++ b/dev/breeze/tests/test_provider_documentation.py
@@ -33,6 +33,7 @@ from airflow_breeze.prepare_providers.provider_documentation 
import (
     _get_change_from_line,
     _get_changes_classified,
     _get_git_log_command,
+    classification_result,
     get_most_impactful_change,
     get_version_tag,
 )
@@ -391,3 +392,54 @@ def 
test_version_bump_for_provider_documentation(initial_version, bump_index, ex
 )
 def test_get_most_impactful_change(changes, expected):
     assert get_most_impactful_change(changes) == expected
+
+
[email protected](
+    "changed_files, expected",
+    [
+        pytest.param(["providers/slack/docs/slack.rst"], "documentation", 
id="only_docs"),
+        pytest.param(["providers/slack/tests/test_slack.py"], 
"test_or_example_only", id="only_tests"),
+        pytest.param(
+            
["providers/slack/src/airflow/providers/slack/example_dags/example_notify.py"],
+            "test_or_example_only",
+            id="only_example_dags",
+        ),
+        pytest.param(
+            [
+                "providers/slack/tests/test_slack.py",
+                
"providers/slack/src/airflow/providers/slack/example_dags/example_notify.py",
+            ],
+            "test_or_example_only",
+            id="tests_and_example_dags",
+        ),
+        pytest.param(
+            [
+                "providers/slack/tests/test_slack.py",
+                "providers/slack/docs/slack.rst",
+            ],
+            "documentation",
+            id="docs_and_tests",
+        ),
+        pytest.param(
+            [
+                "providers/slack/src/airflow/providers/slack/hooks/slack.py",
+                "providers/slack/docs/slack.rst",
+            ],
+            "documentation",
+            id="docs_and_real_code",
+        ),
+        pytest.param(
+            [
+                "providers/slack/src/airflow/providers/slack/hooks/slack.py",
+                "providers/slack/tests/test_slack.py",
+            ],
+            "other",
+            id="real_code_and_tests",
+        ),
+        pytest.param(["airflow/utils/db.py"], "other", id="non_provider_file"),
+        pytest.param([], "other", id="empty_commit"),
+    ],
+)
+def test_classify_provider_pr_files_logic(changed_files, expected):
+    result = classification_result(changed_files)
+    assert result == expected

Reply via email to