bbovenzi commented on code in PR #74278:
URL: https://github.com/apache/airflow/pull/74278#discussion_r4211022695


##########
airflow-core/docs/administration-and-deployment/plugins.rst:
##########
@@ -404,52 +406,107 @@ relevant instead of appearing on every Dag:
 .. code-block:: python
 
     "applies_to": {
-        "dag_tags": ["ml"],  # Dag carries any of these tags
-        "dag_ids": ["train_pipeline"],  # exact dag_id
-        "task_ids": ["train_model"],  # exact task_id
-        "operators": ["KubernetesPodOperator"],  # operator class name
+        "state": ["failed", "upstream_failed"],  # the entity's own field
+        "dag.tags.name": ["ml"],  # a related record, array-aware
+        "dag.dag_id": ["train_pipeline"],
     }
 
-All keys are optional. ``operators`` and ``operator_names`` are matched 
separately, the same
-way the task instance filters treat them: ``operators`` is the operator class 
name, while
-``operator_names`` is the display name shown in the UI (an operator's
-``custom_operator_name``). For a plain operator the two are identical, so 
either key works.
-They differ for decorator-based tasks: a ``@task.bash`` task has the display 
name
-``@task.bash`` but the private class name ``_BashDecoratedOperator``, so use
-``operator_names`` to target it.
+Keys are **dotted field paths** into the records the page has, not a fixed set 
of criteria, so
+anything the REST API returns for an entity is addressable — ``state``, 
``operator``, ``pool``,
+``queue``, ``try_number``, and so on. Values are matched for equality, and are 
compared as
+strings, so numeric and boolean fields work without quoting rules of their own
+(``"try_number": ["2"]``, ``"is_paused": ["false"]``).
 
-Criteria combine like Kubernetes label selectors — **OR within a key, AND 
across keys**. A
-Dag matching any listed tag satisfies ``dag_tags``, and a view configured with 
both
-``dag_tags`` and ``operators`` requires both to match.
+An **unqualified path is rooted at the entity the destination is about** — on 
``dag_run``,
+``state`` is the run's state; on ``task_instance``, the task instance's. A 
path may instead
+name a related record as its first segment: ``dag``, ``dag_run``, ``task`` or
+``task_instance``. Traversing a list fans out across it, so ``dag.tags.name`` 
collects every
+tag name and matches if any of them is listed.
 
-Crucially, the AND applies **only across criteria the current page can 
evaluate**. A
-``task_ids`` criterion cannot be judged on a Dag-level page, so it is skipped 
there rather
+Paths combine like Kubernetes label selectors — **OR within a path, AND across 
paths**. A Dag
+matching any listed tag satisfies ``dag.tags.name``, and a view configured 
with both
+``dag.tags.name`` and ``state`` requires both to match.
+
+Crucially, the AND applies **only across paths the current page can 
evaluate**. A
+``task_instance.*`` path cannot be judged on a Dag-level page, so it is 
skipped there rather
 than failing the match. This lets one ``applies_to`` block be shared by a 
plugin's Dag- and
-task-level destinations. Which criteria each destination can evaluate:
+task-level destinations. Which records each destination resolves:
 
 .. list-table::
    :header-rows: 1
 
    * - Destination
-     - ``dag_tags`` / ``dag_ids``
-     - ``task_ids`` / ``operators`` / ``operator_names``
-   * - ``dag``, ``dag_run``, ``dag_overview``
-     - evaluated
-     - skipped
-   * - ``task``, ``task_overview``, ``task_instance``
-     - evaluated
-     - evaluated
+     - Unqualified path is rooted at
+     - Records a qualified path can reach
+   * - ``dag``, ``dag_overview``
+     - ``dag``
+     - ``dag``
+   * - ``dag_run``
+     - ``dag_run``
+     - ``dag``, ``dag_run``
+   * - ``task``, ``task_overview``
+     - ``task``
+     - ``dag``, ``task``
+   * - ``task_instance``
+     - ``task_instance``
+     - ``dag``, ``dag_run``, ``task``, ``task_instance``
    * - ``nav``, ``base``, ``dashboard``, ``asset``
-     - skipped
-     - skipped
+     - —
+     - none, so every path is skipped
+
+If none of the configured paths can be evaluated on a given page, the view is 
shown. On task
+group pages the task-level records are absent, since a group is not a task.
+
+A path is also skipped when the record exists but has no such field. That 
means a **bad path
+widens the scope rather than narrowing it**, so paths are checked against the 
API response
+models when plugins load and a path naming no field is logged with a suggested 
correction.
+The check stops at a field whose contents the models do not describe — the 
dict behind
+``class_ref``, or a Dag Run's ``conf`` — so a path below one of those is still 
accepted and
+still widens silently. If a view appears in more places than you expect, check 
the API server
+log first, then the path against the REST API response for that entity.
+
+An empty list is different from a missing field: a Dag with no tags has 
definitively answered
+``dag.tags.name``, so the view is not shown. A path that stops short of a leaf 
is likewise a
+decided answer rather than a skip: ``dag.tags`` resolves to a list of objects, 
which have no
+comparable value, so the view is hidden. Address the field you mean to compare
+(``dag.tags.name``).
+
+Targeting operators
+^^^^^^^^^^^^^^^^^^^
+
+``operator_name`` is spelled the same way on a task and on a task instance, so 
**one
+unqualified path targets an operator on either page**:
+
+.. code-block:: python
+
+    "applies_to": {"operator_name": ["KubernetesPodOperator"]}
+
+``operator_name`` is the display name shown in the UI (an operator's
+``custom_operator_name``). For a plain operator it is the class name, but the 
two differ for
+decorator-based tasks: a ``@task.bash`` task has the display name 
``@task.bash`` and the
+private class name ``_BashDecoratedOperator``, so ``operator_name`` is the one 
to match on.
+
+If you specifically need the operator *class* name, the two records spell it 
differently — a
+task instance has ``operator``, while a task carries it through 
``class_ref.class_name``. The
+skip rule is what lets one block cover both, by naming each source:
+
+.. code-block:: python
+
+    "applies_to": {
+        # On a task page the first is skipped and the second decides; on a 
task instance
+        # page, the reverse. Prefer `operator_name` unless you need the 
private class name.
+        "task_instance.operator": ["KubernetesPodOperator"],
+        "task.class_ref.class_name": ["KubernetesPodOperator"],

Review Comment:
   Also we can rebase with https://github.com/apache/airflow/pull/74365 to 
fetch the specific task at that dag version



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to