From 19ce612fa98f98e30322686af2e9fa28e183abc4 Mon Sep 17 00:00:00 2001 From: "Jason(Zhe-You) Liu" <68415893+jason810496@users.noreply.github.com> Date: Fri, 3 Jul 2026 11:37:35 +0900 Subject: [PATCH] [v3-3-test] Run OTel integration tests when span-emitting task runner code changes (#69250) The otel core integration was only triggered by observability sources, so PRs changing the spans the task runner emits (like #67877) or the otel integration tests themselves passed CI without running the tests that assert the span hierarchy, and breakage surfaced only in canary builds. (cherry picked from commit 529843127c79e4c8a496275e4344f655b6661468) Co-authored-by: Jason(Zhe-You) Liu <68415893+jason810496@users.noreply.github.com> --- dev/breeze/doc/ci/04_selective_checks.md | 1 + dev/breeze/src/airflow_breeze/utils/selective_checks.py | 4 ++++ dev/breeze/tests/test_selective_checks.py | 2 ++ 3 files changed, 7 insertions(+) diff --git a/dev/breeze/doc/ci/04_selective_checks.md b/dev/breeze/doc/ci/04_selective_checks.md index 5dbaf289f9eb0..67374350dedd0 100644 --- a/dev/breeze/doc/ci/04_selective_checks.md +++ b/dev/breeze/doc/ci/04_selective_checks.md @@ -244,6 +244,7 @@ representative examples (file → effect): | `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` | +| `task-sdk/.../task_runner.py` or `airflow-core/tests/integration/otel/...` | the `otel` core integration | matches `OTEL_FILES`; the otel integration tests assert the span hierarchy task_runner emits | | `airflow-core/src/airflow/ui/...tsx` only | `run_ui_tests`, **no** unit tests | "only new-UI files" short-circuit skips Python unit tests | The "complexity" you feel reading the code is just *many* such rules stacked up — each one on its own diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py b/dev/breeze/src/airflow_breeze/utils/selective_checks.py index fcaf8ae5c0a27..93cd502df0478 100644 --- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py +++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py @@ -464,6 +464,10 @@ def __hash__(self): r"^airflow-core/src/airflow/observability/.*", r"^shared/observability/src/airflow_shared/observability/.*", r"^airflow-core/src/airflow/utils/span_status\.py$", + # The otel integration tests assert the exact span hierarchy that + # task_runner emits, so changes to either must exercise the integration. + r"^airflow-core/tests/integration/otel/.*", + r"^task-sdk/src/airflow/sdk/execution_time/task_runner\.py$", ], FileGroupForCi.CELERY_FILES: [ # Core executor sources - redis is celery's broker/result backend, so the diff --git a/dev/breeze/tests/test_selective_checks.py b/dev/breeze/tests/test_selective_checks.py index 7b2848a6f467f..552e0db77ed6e 100644 --- a/dev/breeze/tests/test_selective_checks.py +++ b/dev/breeze/tests/test_selective_checks.py @@ -3419,6 +3419,8 @@ def test_testable_providers_integrations_excludes_arm_disabled_on_arm(): [ 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"), ], )