This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch v3-2-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-2-test by this push:
new 485bbfdbfad Adds the DAG run ID to the grid bar tooltip and also
surfaces it in the task instance tooltip in the grid view. (#65626) (#66871)
485bbfdbfad is described below
commit 485bbfdbfad51cf4057fbcdb991ef4f393720d7c
Author: Rahul Vats <[email protected]>
AuthorDate: Thu May 14 19:56:13 2026 +0530
Adds the DAG run ID to the grid bar tooltip and also surfaces it in the
task instance tooltip in the grid view. (#65626) (#66871)
* Add run ID to grid tooltips
* Format GridTI after run ID tooltip update
---------
(cherry picked from commit 2d4eb59b352affcd488344096080748bd691f004)
Co-authored-by: PrithviBadiga
<[email protected]>
Co-authored-by: Prithvi Badiga <[email protected]>
---
.../ui/src/components/TaskInstanceTooltip.test.tsx | 21 +++++++++
.../ui/src/components/TaskInstanceTooltip.tsx | 7 +--
.../src/layouts/Details/Grid/GridButton.test.tsx | 55 ++++++++++++++++++++++
.../ui/src/layouts/Details/Grid/GridButton.tsx | 2 +
.../airflow/ui/src/layouts/Details/Grid/GridTI.tsx | 7 ++-
5 files changed, 88 insertions(+), 4 deletions(-)
diff --git
a/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.test.tsx
b/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.test.tsx
index 51058868003..3f3d17a95de 100644
--- a/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.test.tsx
+++ b/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.test.tsx
@@ -196,4 +196,25 @@ describe("TaskInstanceTooltip", () => {
expect(screen.getAllByText(/state/iu).length).toBeGreaterThan(0);
expect(screen.getByText(/startDate/iu)).toBeInTheDocument();
});
+
+ it("shows run ID when provided explicitly for grid summaries", () => {
+ const taskInstance: LightGridTaskInstanceSummary = {
+ child_states: null,
+ max_end_date: "2025-01-01T02:00:00Z",
+ min_start_date: "2025-01-01T00:00:00Z",
+ state: "success",
+ task_display_name: "My Task",
+ task_id: "my_task",
+ };
+
+ render(
+ <TaskInstanceTooltip open runId="manual__2025-01-01T00:00:00+00:00"
taskInstance={taskInstance}>
+ <span>trigger</span>
+ </TaskInstanceTooltip>,
+ { wrapper: Wrapper },
+ );
+
+ expect(screen.getByText(/runId/iu)).toBeInTheDocument();
+
expect(screen.getByText(/manual__2025-01-01T00:00:00\+00:00/iu)).toBeInTheDocument();
+ });
});
diff --git a/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.tsx
b/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.tsx
index 8162c02a7c3..8f89c910247 100644
--- a/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.tsx
+++ b/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.tsx
@@ -29,11 +29,12 @@ import { Tooltip, type TooltipProps } from
"src/components/ui";
import { getDuration, renderDuration, sortStateEntries } from "src/utils";
type Props = {
+ readonly runId?: string | null;
readonly taskInstance?: LightGridTaskInstanceSummary |
TaskInstanceHistoryResponse | TaskInstanceResponse;
readonly tooltip?: string | null;
} & Omit<TooltipProps, "content">;
-const TaskInstanceTooltip = ({ children, positioning, taskInstance, tooltip,
...rest }: Props) => {
+const TaskInstanceTooltip = ({ children, positioning, runId, taskInstance,
tooltip, ...rest }: Props) => {
const { t: translate } = useTranslation("common");
const hasTooltip = tooltip !== undefined && tooltip !== null;
@@ -62,9 +63,9 @@ const TaskInstanceTooltip = ({ children, positioning,
taskInstance, tooltip, ...
? translate(`common:states.${taskInstance.state}`)
: translate("common:states.no_status")}
</Text>
- {"dag_run_id" in taskInstance ? (
+ {"dag_run_id" in taskInstance || (runId !== undefined && runId
!== null && runId !== "") ? (
<Text>
- {translate("runId")}: {taskInstance.dag_run_id}
+ {translate("runId")}: {"dag_run_id" in taskInstance ?
taskInstance.dag_run_id : runId}
</Text>
) : undefined}
{"start_date" in taskInstance ? (
diff --git
a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.test.tsx
b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.test.tsx
new file mode 100644
index 00000000000..6164573e68c
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.test.tsx
@@ -0,0 +1,55 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import "@testing-library/jest-dom";
+import { act, fireEvent, render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+import { Wrapper } from "src/utils/Wrapper";
+
+import { GridButton } from "./GridButton";
+
+describe("GridButton", () => {
+ it("shows run ID in the grid tooltip", () => {
+ vi.useFakeTimers();
+
+ render(
+ <GridButton
+ dagId="example_dag"
+ label="2026-04-21T00:00:00+00:00"
+ runId="manual__2026-04-21T00:00:00+00:00"
+ searchParams=""
+ state="success"
+ >
+ <span>bar</span>
+ </GridButton>,
+ { wrapper: Wrapper },
+ );
+
+ act(() => {
+ fireEvent.mouseEnter(screen.getByText("bar"));
+ vi.advanceTimersByTime(500);
+ });
+
+ expect(screen.getByTestId("basic-tooltip")).toHaveTextContent(
+ "common:runId: manual__2026-04-21T00:00:00+00:00",
+ );
+
+ vi.useRealTimers();
+ });
+});
diff --git
a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.tsx
b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.tsx
index c452cf43a79..488ccffd0d0 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.tsx
@@ -50,6 +50,8 @@ export const GridButton = ({
<>
{label}
<br />
+ {translate("common:runId")}: {runId}
+ <br />
{translate("state")}:{" "}
{state ? translate(`common:states.${state}`) :
translate("common:states.no_status")}
</>
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx
b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx
index ede81eccbb0..6cd21d252f9 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx
@@ -80,7 +80,12 @@ export const GridTI = ({ dagId, instance, isGroup, isMapped,
onClick, runId, tas
py={0}
transition="background-color 0.2s"
>
- <TaskInstanceTooltip openDelay={500} positioning={{ placement: "bottom"
}} taskInstance={instance}>
+ <TaskInstanceTooltip
+ openDelay={500}
+ positioning={{ placement: "bottom" }}
+ runId={runId}
+ taskInstance={instance}
+ >
<Box as="span" display="inline-block">
<Link
data-testid={`grid-${runId}-${taskId}`}