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

bugraoz93 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 67a2cc38a89 Exclude ibm.mq from ARM test matrix via excluded-platforms 
(#67757)
67a2cc38a89 is described below

commit 67a2cc38a8991beb01d55a3f1cf55a39ade6a23a
Author: Bugra Ozturk <[email protected]>
AuthorDate: Sat May 30 01:17:37 2026 +0200

    Exclude ibm.mq from ARM test matrix via excluded-platforms (#67757)
---
 airflow-core/src/airflow/provider.yaml.schema.json |  7 +++
 .../src/airflow_breeze/utils/selective_checks.py   | 49 +++++++++++++++
 dev/breeze/tests/test_selective_checks.py          | 72 ++++++++++++++++++++++
 providers/ibm/mq/provider.yaml                     |  8 +++
 scripts/ci/prek/update_providers_dependencies.py   |  2 +
 5 files changed, 138 insertions(+)

diff --git a/airflow-core/src/airflow/provider.yaml.schema.json 
b/airflow-core/src/airflow/provider.yaml.schema.json
index 5714b8db658..2f020b27330 100644
--- a/airflow-core/src/airflow/provider.yaml.schema.json
+++ b/airflow-core/src/airflow/provider.yaml.schema.json
@@ -58,6 +58,13 @@
                 "type": "string"
             }
         },
+        "excluded-platforms": {
+            "description": "List of platforms (e.g. linux/arm64) excluded for 
that provider. Used to skip providers whose native dependencies are unavailable 
on a given architecture.",
+            "type": "array",
+            "items": {
+                "type": "string"
+            }
+        },
         "integrations": {
             "description": "List of integrations supported by the provider.",
             "type": "array",
diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py 
b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
index 9176fed4183..3514c558476 100644
--- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py
+++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
@@ -1319,6 +1319,53 @@ class SelectiveChecks:
         list_of_list_of_types = _split_list(current_test_types, 
NUMBER_OF_CORE_SLICES)
         return json.dumps(_get_test_list_as_json(list_of_list_of_types))
 
+    @cached_property
+    def _platform_excluded_providers(self) -> set[str]:
+        """Provider ids that opt out of the current ``self.platform`` via 
provider.yaml.
+
+        Mirrors the ``excluded-python-versions`` mechanism but keyed by Docker 
platform
+        string (e.g. ``linux/arm64``) so providers whose native dependencies 
are unavailable
+        on a given architecture can be removed from the test matrix at 
planning time.
+        """
+        excluded: set[str] = set()
+        for provider_id, provider_info in get_provider_dependencies().items():
+            if self.platform in provider_info.get("excluded-platforms", []):
+                excluded.add(provider_id)
+        return excluded
+
+    def _filter_platform_excluded_test_types(self, current_test_types: 
set[str]) -> None:
+        """Rewrite ``Providers[...]`` entries in-place to honor 
``excluded-platforms``.
+
+        Handles three shapes produced upstream:
+
+        * ``Providers[foo]`` — dropped entirely when ``foo`` is excluded.
+        * ``Providers[a,foo,b]`` — rewritten to ``Providers[a,b]``; dropped if 
empty.
+        * ``Providers[-amazon,celery,google,standard]`` (negative, "all 
except") —
+          excluded providers are appended to the negation so they remain 
skipped.
+        """
+        excluded = self._platform_excluded_providers
+        if not excluded:
+            return
+        for original in tuple(current_test_types):
+            if not original.startswith("Providers[") or not 
original.endswith("]"):
+                continue
+            inner = original[len("Providers[") : -1]
+            if inner.startswith("-"):
+                negated = [p for p in inner[1:].split(",") if p]
+                additions = sorted(p for p in excluded if p not in negated)
+                if not additions:
+                    continue
+                current_test_types.remove(original)
+                current_test_types.add(f"Providers[-{','.join(sorted(negated + 
additions))}]")
+                continue
+            providers_in = [p for p in inner.split(",") if p]
+            kept = [p for p in providers_in if p not in excluded]
+            if kept == providers_in:
+                continue
+            current_test_types.remove(original)
+            if kept:
+                current_test_types.add(f"Providers[{','.join(kept)}]")
+
     @cached_property
     def providers_test_types_list_as_strings_in_json(self) -> str:
         if not self.run_unit_tests:
@@ -1335,6 +1382,7 @@ class SelectiveChecks:
                     test_types_to_remove.add(test_type)
             current_test_types = current_test_types - test_types_to_remove
         self._extract_long_provider_tests(current_test_types)
+        self._filter_platform_excluded_test_types(current_test_types)
         return json.dumps(_get_test_list_as_json([sorted(current_test_types)]))
 
     def _get_individual_providers_list(self):
@@ -1344,6 +1392,7 @@ class SelectiveChecks:
             current_test_types.update(
                 {f"Providers[{provider}]" for provider in 
get_available_distributions(include_not_ready=True)}
             )
+        self._filter_platform_excluded_test_types(current_test_types)
         return current_test_types
 
     @cached_property
diff --git a/dev/breeze/tests/test_selective_checks.py 
b/dev/breeze/tests/test_selective_checks.py
index 3ab02987358..79ce05ecd35 100644
--- a/dev/breeze/tests/test_selective_checks.py
+++ b/dev/breeze/tests/test_selective_checks.py
@@ -3178,6 +3178,78 @@ def 
test_testable_providers_integrations_excludes_arm_disabled_on_arm():
             assert "ydb" not in result
 
 
+def test_individual_providers_excludes_platform_excluded_on_arm():
+    """ibm.mq declares `excluded-platforms: [linux/arm64]`, so it must be 
absent from
+    the ARM individual-providers matrix (used by the Low-dep ARM canary job) 
and
+    present on AMD."""
+    arm_checks = SelectiveChecks(
+        files=("airflow-core/tests/test_example.py",),
+        commit_ref=NEUTRAL_COMMIT,
+        github_event=GithubEvents.SCHEDULE,
+        github_context_dict={"ref_name": "main"},
+        default_branch="main",
+        pr_labels=("full tests needed",),
+    )
+    with patch.object(
+        SelectiveChecks, "runner_type", new_callable=lambda: property(lambda 
self: '["ubuntu-22.04-arm"]')
+    ):
+        assert arm_checks.platform == "linux/arm64"
+        arm_output = 
arm_checks.individual_providers_test_types_list_as_strings_in_json
+        assert arm_output is not None
+        assert "Providers[ibm.mq]" not in arm_output
+
+    amd_checks = SelectiveChecks(
+        files=("airflow-core/tests/test_example.py",),
+        commit_ref=NEUTRAL_COMMIT,
+        github_event=GithubEvents.SCHEDULE,
+        github_context_dict={"ref_name": "main"},
+        default_branch="main",
+        pr_labels=("full tests needed",),
+    )
+    with patch.object(
+        SelectiveChecks, "runner_type", new_callable=lambda: property(lambda 
self: PUBLIC_AMD_RUNNERS)
+    ):
+        assert amd_checks.platform == "linux/amd64"
+        amd_output = 
amd_checks.individual_providers_test_types_list_as_strings_in_json
+        assert amd_output is not None
+        assert "Providers[ibm.mq]" in amd_output
+
+
+def test_filter_platform_excluded_test_types_handles_all_shapes():
+    """Direct unit check of the in-place filter for the three Providers[...] 
shapes."""
+    checks = SelectiveChecks(
+        files=(),
+        commit_ref=NEUTRAL_COMMIT,
+        github_event=GithubEvents.SCHEDULE,
+        github_context_dict={"ref_name": "main"},
+        default_branch="main",
+    )
+    with patch.object(
+        SelectiveChecks,
+        "_platform_excluded_providers",
+        new_callable=lambda: property(lambda self: {"ibm.mq"}),
+    ):
+        # Bare match drops entry.
+        ts = {"Providers[ibm.mq]"}
+        checks._filter_platform_excluded_test_types(ts)
+        assert ts == set()
+
+        # Combined positive form drops just the excluded id.
+        ts = {"Providers[amazon,ibm.mq,google]"}
+        checks._filter_platform_excluded_test_types(ts)
+        assert ts == {"Providers[amazon,google]"}
+
+        # Negative form gets the excluded id appended.
+        ts = {"Providers[-amazon,celery,google,standard]"}
+        checks._filter_platform_excluded_test_types(ts)
+        assert ts == {"Providers[-amazon,celery,google,ibm.mq,standard]"}
+
+        # Non-Providers entries are untouched.
+        ts = {"Core", "Always"}
+        checks._filter_platform_excluded_test_types(ts)
+        assert ts == {"Core", "Always"}
+
+
 @patch("airflow_breeze.utils.selective_checks.run_command")
 def test_provider_dependency_bump_check_no_changes(mock_run_command):
     """Test that provider dependency bump check passes when no pyproject.toml 
files are changed."""
diff --git a/providers/ibm/mq/provider.yaml b/providers/ibm/mq/provider.yaml
index d1c56376f2f..341980678aa 100644
--- a/providers/ibm/mq/provider.yaml
+++ b/providers/ibm/mq/provider.yaml
@@ -24,6 +24,14 @@ lifecycle: incubation
 source-date-epoch: 1758787200
 description: |
   `IBM MQ  <https://www.ibm.com/products/mq/>`__
+# IBM MQ ships its native C client library only for Linux x86_64, Windows x64 
and Java
+# (https://www.ibm.com/support/pages/downloading-ibm-mq-94 — Redist clients). 
The
+# `ibmmq` Python bindings link against that C client at build time, so `uv sync
+# --resolution lowest-direct --all-extras` fails to build the sdist on aarch64.
+# Exclude the provider from the linux/arm64 test matrix until IBM publishes an 
aarch64
+# redistributable.
+excluded-platforms:
+  - linux/arm64
 # Note that those versions are maintained by release manager - do not update 
them manually
 # with the exception of case where other provider in sources has >= new 
provider version.
 # In such case adding >= NEW_VERSION and bumping to NEW_VERSION in a provider 
have
diff --git a/scripts/ci/prek/update_providers_dependencies.py 
b/scripts/ci/prek/update_providers_dependencies.py
index b114e55a047..41b0c4fe79f 100755
--- a/scripts/ci/prek/update_providers_dependencies.py
+++ b/scripts/ci/prek/update_providers_dependencies.py
@@ -218,6 +218,8 @@ if __name__ == "__main__":
         )
         excluded_versions = ALL_PROVIDERS[key].get("excluded-python-versions")
         unique_sorted_dependencies[key]["excluded-python-versions"] = 
excluded_versions or []
+        excluded_platforms = ALL_PROVIDERS[key].get("excluded-platforms")
+        unique_sorted_dependencies[key]["excluded-platforms"] = 
excluded_platforms or []
         unique_sorted_dependencies[key]["state"] = STATES[key]
     if errors:
         console.print()

Reply via email to