diff --git a/airflow-core/src/airflow/ui/src/components/Clear/Run/ClearRunDialog.tsx b/airflow-core/src/airflow/ui/src/components/Clear/Run/ClearRunDialog.tsx index 425ce9f82364c..3e29580127771 100644 --- a/airflow-core/src/airflow/ui/src/components/Clear/Run/ClearRunDialog.tsx +++ b/airflow-core/src/airflow/ui/src/components/Clear/Run/ClearRunDialog.tsx @@ -24,6 +24,7 @@ import { CgRedo } from "react-icons/cg"; import { useDagServiceGetDagDetails } from "openapi/queries"; import type { DAGRunResponse } from "openapi/requests/types.gen"; import { ActionAccordion } from "src/components/ActionAccordion"; +import { shouldShowRunOnLatestVersionForRun } from "src/components/Clear/Run/runOnLatestVersion"; import { useRerunWithLatestVersion } from "src/components/Clear/useRerunWithLatestVersion"; import { Checkbox, Dialog } from "src/components/ui"; import SegmentedControl from "src/components/ui/SegmentedControl"; @@ -91,14 +92,12 @@ const ClearRunDialog = ({ dagRun, onClose, open }: Props) => { onSuccessConfirm: handleClose, }); - // Check if DAG versions differ (works for both bundle-versioned and local bundles) - const latestDagVersionNumber = dagDetails?.latest_dag_version?.version_number; - const dagRunVersionNumber = dagRun.dag_versions.at(-1)?.version_number; - const versionsDiffer = - latestDagVersionNumber !== undefined && - dagRunVersionNumber !== undefined && - latestDagVersionNumber !== dagRunVersionNumber; - const shouldShowBundleVersionOption = versionsDiffer && !onlyNew; + const shouldShowBundleVersionOption = shouldShowRunOnLatestVersionForRun({ + bundleVersion: dagRun.bundle_version, + latestDagVersionNumber: dagDetails?.latest_dag_version?.version_number, + onlyNew, + runDagVersionNumber: dagRun.dag_versions.at(-1)?.version_number, + }); return ( { + it.each([ + { + bundleVersion: "git-sha-2", + expected: true, + latestDagVersionNumber: 3, + name: "shows for a version-pinned run whose Dag version is behind the latest", + onlyNew: false, + runDagVersionNumber: 2, + }, + { + bundleVersion: null, + expected: false, + latestDagVersionNumber: 3, + name: "hides for a non-versioning bundle (null bundle_version) even when Dag versions differ", + onlyNew: false, + runDagVersionNumber: 2, + }, + { + bundleVersion: "git-sha-3", + expected: false, + latestDagVersionNumber: 3, + name: "hides when the run is already on the latest Dag version", + onlyNew: false, + runDagVersionNumber: 3, + }, + { + bundleVersion: "git-sha-2", + expected: false, + latestDagVersionNumber: 3, + name: "hides when only queueing new tasks", + onlyNew: true, + runDagVersionNumber: 2, + }, + { + bundleVersion: "git-sha-2", + expected: false, + latestDagVersionNumber: undefined, + name: "hides when the latest Dag version number is not loaded", + onlyNew: false, + runDagVersionNumber: 2, + }, + { + bundleVersion: "git-sha-2", + expected: false, + latestDagVersionNumber: 3, + name: "hides when the run's Dag version number is unknown", + onlyNew: false, + runDagVersionNumber: undefined, + }, + ])("$name", ({ bundleVersion, expected, latestDagVersionNumber, onlyNew, runDagVersionNumber }) => { + expect( + shouldShowRunOnLatestVersionForRun({ + bundleVersion, + latestDagVersionNumber, + onlyNew, + runDagVersionNumber, + }), + ).toBe(expected); + }); +}); diff --git a/airflow-core/src/airflow/ui/src/components/Clear/Run/runOnLatestVersion.ts b/airflow-core/src/airflow/ui/src/components/Clear/Run/runOnLatestVersion.ts new file mode 100644 index 0000000000000..3a1241852bbdf --- /dev/null +++ b/airflow-core/src/airflow/ui/src/components/Clear/Run/runOnLatestVersion.ts @@ -0,0 +1,47 @@ +/*! + * 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. + */ + +type RunOnLatestVersionForRunParams = { + readonly bundleVersion: string | null; + readonly latestDagVersionNumber?: number; + readonly onlyNew: boolean; + readonly runDagVersionNumber?: number; +}; + +/** + * Whether to show the "run with latest bundle version" option when clearing a Dag run. + * + * It only has an effect when the run is pinned to a specific bundle version (versioning-capable + * bundles such as GitDagBundle). Non-versioning bundles like LocalDagBundle have a null + * bundle_version and always resolve to the latest serialized Dag, so the option is hidden there + * rather than offering a choice that does nothing. + */ +export const shouldShowRunOnLatestVersionForRun = ({ + bundleVersion, + latestDagVersionNumber, + onlyNew, + runDagVersionNumber, +}: RunOnLatestVersionForRunParams): boolean => { + const versionsDiffer = + latestDagVersionNumber !== undefined && + runDagVersionNumber !== undefined && + latestDagVersionNumber !== runDagVersionNumber; + + return versionsDiffer && !onlyNew && bundleVersion !== null; +};