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

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


The following commit(s) were added to refs/heads/v3-3-test by this push:
     new 6ad3c2c5eb1 [v3-3-test] Don't force full CI tests for non-test 
workflow and prek-only changes (#68802) (#68999)
6ad3c2c5eb1 is described below

commit 6ad3c2c5eb143007e77a2fbcdd48e215aa1be86d
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Jun 26 14:48:16 2026 -0400

    [v3-3-test] Don't force full CI tests for non-test workflow and prek-only 
changes (#68802) (#68999)
    
    ENVIRONMENT_FILES forced the full test matrix on any .github/workflows
    change and on any scripts/ci/prek change. Those over-match: non-test
    workflows (security scans, doc publishing, notifications, backporting,
    stale/calendar bots) cannot affect test outcomes, and prek hooks drive
    static checks rather than the test matrix.
    
    Exclude non-test workflows from ENVIRONMENT_FILES (test/CI-config
    workflows like ci-amd, run-unit-tests, k8s-tests still force full), and
    move scripts/ci/prek to a new PREK_FILES group that triggers only the CI
    image build (so mypy-scripts and image-based static checks still run for
    a prek-only change) without forcing the full matrix.
    
    Static checks still run on every PR regardless; this only stops the
    unnecessary full test matrix for changes that cannot affect tests.
    (cherry picked from commit a4c269a6f9e0176995fbea971dd4e01ac9ae3123)
    
    Co-authored-by: Jarek Potiuk <[email protected]>
---
 dev/breeze/doc/ci/04_selective_checks.md           | 23 ++++++++---
 .../src/airflow_breeze/utils/selective_checks.py   | 23 ++++++++++-
 dev/breeze/tests/test_selective_checks.py          | 48 +++++++++++++++++++++-
 3 files changed, 85 insertions(+), 9 deletions(-)

diff --git a/dev/breeze/doc/ci/04_selective_checks.md 
b/dev/breeze/doc/ci/04_selective_checks.md
index fb081df0aa1..5dbaf289f9e 100644
--- a/dev/breeze/doc/ci/04_selective_checks.md
+++ b/dev/breeze/doc/ci/04_selective_checks.md
@@ -160,7 +160,7 @@ not matter because any single hit forces the full matrix:
 flowchart TD
     A([full_tests_needed]) --> M{_should_run_all_tests_and_versions?}
     M -->|yes| T[TRUE - full matrix]
-    M -->|no| E1{environment files?<br/>.github/workflows, 
dev/breeze/src,<br/>Dockerfile, scripts/ci, ...}
+    M -->|no| E1{environment files?<br/>test workflows, 
dev/breeze/src,<br/>Dockerfile, scripts/ci/docker-compose+kubernetes, 
...<br/>excl. prek + non-test workflows}
     E1 -->|yes| T
     E1 -->|no| E2{API contract / codegen?<br/>generated OpenAPI spec or 
generator}
     E2 -->|yes| T
@@ -240,6 +240,8 @@ representative examples (file → effect):
 | `airflow-core/src/airflow/jobs/scheduler_job_runner.py` | unit tests with 
**all** core test types                            | a core/other file → escape 
hatch runs all core types |
 | `pyproject.toml`                                       | **full matrix, all 
versions**                                        | dependency surface changed 
→ `_should_run_all_tests_and_versions` |
 | `.github/workflows/ci-amd.yml` or `dev/breeze/src/...` | **full matrix**     
                                                 | environment files → can 
change the whole CI environment |
+| `.github/workflows/codeql-analysis.yml` (non-test workflow) | **basic checks 
only**                                           | non-test workflow → cannot 
affect tests (env-files carve-out) |
+| `scripts/ci/prek/check_*.py` (static-check hook)       | CI image + static 
checks, **no full matrix**                         | prek hooks are static 
checks → `Prek files` carve-out |
 | the generated OpenAPI spec                             | **full matrix**     
                                                 | the API *contract* ripples 
to UI codegen + every client |
 | `chart/templates/...yaml` (on `main`)                  | `run_helm_tests` (+ 
PROD image)                                      | matches `HELM_FILES`; Helm 
tests only on `main` |
 | `airflow-core/src/airflow/ui/...tsx` only              | `run_ui_tests`, 
**no** unit tests                                    | "only new-UI files" 
short-circuit skips Python unit tests |
@@ -279,9 +281,11 @@ flowchart TD
 2. **Pull request, core change** (`scheduler_job_runner.py`). Still 
`full_tests_needed=False`, but the
    core/other escape hatch adds **all core test types**. Providers are not 
pulled in (no provider files
    changed). Default versions.
-3. **Pull request that changes `pyproject.toml`** (or `.github/workflows/...`, 
or the OpenAPI spec).
-   `full_tests_needed=True` (and for `pyproject.toml` also 
`all_versions=True`). The PR runs the **full
-   matrix** — same as a canary — because the change can affect everything.
+3. **Pull request that changes `pyproject.toml`** (or a *test* workflow like 
`.github/workflows/ci-amd.yml`,
+   or the OpenAPI spec). `full_tests_needed=True` (and for `pyproject.toml` 
also `all_versions=True`). The
+   PR runs the **full matrix** — same as a canary — because the change can 
affect everything. (A *non-test*
+   workflow such as `codeql-analysis.yml`, or a `scripts/ci/prek/...` 
static-check hook, does **not** force
+   the full matrix — see the `Environment files` carve-outs above.)
 4. **Push / merge to `main`.** `_should_run_all_tests_and_versions()` is true 
for PUSH on `main` →
    `full_tests_needed=True`, `all_versions=True`, `is_canary_run=True`. The 
full matrix plus all
    canary-only jobs run. This is the safety net that backstops aggressive 
PR-time optimisation.
@@ -333,7 +337,16 @@ The authoritative, exhaustive rule list (kept in sync with 
the code) is in
 We have the following Groups of files for CI that determine which tests are 
run:
 
 * `Environment files` - if any of those changes, that forces 'full tests 
needed' mode, because changes
-  there might simply change the whole environment of what is going on in CI 
(Container image, dependencies)
+  there might simply change the whole environment of what is going on in CI 
(Container image, dependencies).
+  Two deliberate carve-outs do **not** force full tests: **static-check 
hooks** (`scripts/ci/prek/...`)
+  drive prek static checks rather than the test matrix, so they only trigger 
the CI image build (via the
+  `Prek files` group) — `mypy-scripts` and the image-based static checks still 
run, but the full test
+  matrix does not; and **non-test workflows** (`.github/workflows/` for 
security scans, doc publishing,
+  notifications, backporting, calendar/stale bots, …) cannot change test 
outcomes. Workflows that run or
+  configure the test suite (`ci-amd`, `ci-arm`, `run-unit-tests`, `k8s-tests`, 
`helm-tests`, image builds,
+  …) still force the full matrix.
+* `Prek files` - `scripts/ci/prek/...` static-check hooks. They do not force 
full tests, but they trigger
+  the CI image build so `mypy-scripts` and the image-based static checks run 
for a prek-only change.
 * `Python production files` and `Javascript production files` - this area is 
useful in CodeQL Security scanning
   - if any of the python or javascript files for airflow "production" changed, 
this means that the security
     scans should run
diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py 
b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
index 8d4c512ff1a..fcaf8ae5c0a 100644
--- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py
+++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
@@ -149,6 +149,7 @@ class FileGroupForCi(Enum):
     DEVEL_TOML_FILES = auto()
     SCRIPTS_FILES = auto()
     UV_LOCK_FILE = auto()
+    PREK_FILES = auto()
     KERBEROS_FILES = auto()
     OTEL_FILES = auto()
     CELERY_FILES = auto()
@@ -171,7 +172,15 @@ class HashableDict(dict[T, list[str]]):
 CI_FILE_GROUP_MATCHES: HashableDict[FileGroupForCi] = HashableDict(
     {
         FileGroupForCi.ENVIRONMENT_FILES: [
-            r"^.github/workflows",
+            # Only workflows that actually run or configure the test suite 
force the full
+            # matrix. Non-test workflows (security scans, doc publishing, 
notifications,
+            # backporting, stale/calendar bots, …) cannot affect test 
outcomes, so they
+            # are excluded here to avoid accidental full-matrix runs.
+            r"^\.github/workflows/(?!("
+            
r"asf-allowlist-check|automatic-backport|backport-cli|ci-duration-monitor|ci-notification|"
+            
r"codeql-analysis|e2e-flaky-tests-report|milestone-tag-assistant|notify-uv-lock-conflicts|"
+            
r"publish-docs-to-s3|recheck-old-bug-report|scheduled-verify-release-calendar|stale"
+            r")\.yml$)",
             r"^dev/breeze/src",
             r"^dev/breeze/pyproject\.toml",
             r"^dev/breeze/uv\.lock",
@@ -179,7 +188,10 @@ CI_FILE_GROUP_MATCHES: HashableDict[FileGroupForCi] = 
HashableDict(
             r"^Dockerfile",
             r"^scripts/ci/docker-compose",
             r"^scripts/ci/kubernetes",
-            r"^scripts/ci/prek",
+            # NOTE: scripts/ci/prek (static-check hooks) is intentionally NOT 
here. prek
+            # hooks drive static checks, not the test matrix, so they must not 
force the
+            # full matrix. They still build the CI image via 
FileGroupForCi.PREK_FILES
+            # below (so mypy-scripts and all static checks still run).
             r"^scripts/docker",
             r"^scripts/in_container",
         ],
@@ -438,6 +450,9 @@ CI_FILE_GROUP_MATCHES: HashableDict[FileGroupForCi] = 
HashableDict(
             r"^scripts/tools/.*\.py$",
             r"^scripts/tests/.*\.py$",
         ],
+        FileGroupForCi.PREK_FILES: [
+            r"^scripts/ci/prek",
+        ],
         FileGroupForCi.UV_LOCK_FILE: [
             r"^uv\.lock$",
         ],
@@ -1100,6 +1115,10 @@ class SelectiveChecks:
             or self.pyproject_toml_changed
             or self.any_provider_yaml_or_pyproject_toml_changed
             or self.prod_image_build
+            # prek hooks no longer force the full test matrix (they are static 
checks, not
+            # tests), but they still need the CI image so mypy-scripts and the 
image-based
+            # static checks run for a prek-only change.
+            or bool(self._matching_files(FileGroupForCi.PREK_FILES, 
CI_FILE_GROUP_MATCHES))
         )
 
     @cached_property
diff --git a/dev/breeze/tests/test_selective_checks.py 
b/dev/breeze/tests/test_selective_checks.py
index 98cf2333a46..7b2848a6f46 100644
--- a/dev/breeze/tests/test_selective_checks.py
+++ b/dev/breeze/tests/test_selective_checks.py
@@ -1768,9 +1768,13 @@ def test_excluded_providers():
             pytest.param(
                 ("scripts/ci/prek/file.sh",),
                 {
-                    "full-tests-needed": "true",
+                    # 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="Full tests needed when prek scripts change",
+                id="prek scripts build the CI image but do not force full 
tests",
             )
         ),
         (
@@ -1812,6 +1816,46 @@ def test_full_test_needed_when_scripts_changes(files: 
tuple[str, ...], expected_
     assert_outputs_are_printed(expected_outputs, str(stderr))
 
 
[email protected](
+    ("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"),
     [

Reply via email to