From 905712968522278dd2ac6dd8dc0bd9635140e1e5 Mon Sep 17 00:00:00 2001 From: Ephraim Anierobi Date: Thu, 11 Dec 2025 17:40:08 +0100 Subject: [PATCH] [v3-1-test] Fix backfill run_on_latest_version defaulting to False instead of True (#59304) The run_on_latest_version parameter for backfills was incorrectly defaulting to False in the CLI, API, and UI. This fix ensures that backfills default to using the latest bundle version, which is the intended behavior. Changes: - Set ARG_BACKFILL_RUN_ON_LATEST_VERSION default to True in CLI - Add run_on_latest_version field with default=True to BackfillPostBody API model - Update API route to use request body value instead of hardcoded True - Update UI form to include run_on_latest_version: true in defaultValues - Update tests to reflect the new default behavior - Refactor RunBackfillForm to reduce line count below 250 to comply with max-lines linting rule (cherry picked from commit 0224303bc68d30573d87cc141c1d246806db906f) Co-authored-by: Ephraim Anierobi --- .../core_api/datamodels/backfills.py | 1 + .../openapi/v2-rest-api-generated.yaml | 4 ++ .../core_api/routes/public/backfills.py | 1 + airflow-core/src/airflow/cli/cli_config.py | 5 ++- .../ui/openapi-gen/requests/schemas.gen.ts | 5 +++ .../ui/openapi-gen/requests/types.gen.ts | 1 + .../components/DagActions/RunBackfillForm.tsx | 42 ++++++++----------- .../cli/commands/test_backfill_command.py | 6 +-- .../airflowctl/api/datamodels/generated.py | 1 + 9 files changed, 36 insertions(+), 30 deletions(-) diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/backfills.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/backfills.py index aa3a7fd0ef9b7..6b37b9e381694 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/backfills.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/backfills.py @@ -35,6 +35,7 @@ class BackfillPostBody(StrictBaseModel): dag_run_conf: dict = {} reprocess_behavior: ReprocessBehavior = ReprocessBehavior.NONE max_active_runs: int = 10 + run_on_latest_version: bool = True class BackfillResponse(BaseModel): diff --git a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml index ceaf90b60f805..5f7d5144e7ed8 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml +++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml @@ -8770,6 +8770,10 @@ components: type: integer title: Max Active Runs default: 10 + run_on_latest_version: + type: boolean + title: Run On Latest Version + default: true additionalProperties: false type: object required: diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.py index 30efea4d79ab8..b9c1416b2ce72 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.py @@ -243,6 +243,7 @@ def create_backfill( dag_run_conf=backfill_request.dag_run_conf, triggering_user_name=user.get_name(), reprocess_behavior=backfill_request.reprocess_behavior, + run_on_latest_version=backfill_request.run_on_latest_version, ) return BackfillResponse.model_validate(backfill_obj) diff --git a/airflow-core/src/airflow/cli/cli_config.py b/airflow-core/src/airflow/cli/cli_config.py index 5c8497ead6e4f..a5062545e86bc 100644 --- a/airflow-core/src/airflow/cli/cli_config.py +++ b/airflow-core/src/airflow/cli/cli_config.py @@ -344,10 +344,11 @@ def string_lower_type(val): ARG_BACKFILL_RUN_ON_LATEST_VERSION = Arg( ("--run-on-latest-version",), help=( - "(Experimental) If set, the backfill will run tasks using the latest bundle version instead of " - "the version that was active when the original Dag run was created." + "(Experimental) The backfill will run tasks using the latest bundle version instead of " + "the version that was active when the original Dag run was created. Defaults to True." ), action="store_true", + default=True, ) diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts index e45ee585988d8..c2bc9a822d373 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts @@ -418,6 +418,11 @@ export const $BackfillPostBody = { type: 'integer', title: 'Max Active Runs', default: 10 + }, + run_on_latest_version: { + type: 'boolean', + title: 'Run On Latest Version', + default: true } }, additionalProperties: false, diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts index 006f33286fdd3..1a1bf0f50e9ac 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts @@ -115,6 +115,7 @@ export type BackfillPostBody = { }; reprocess_behavior?: ReprocessBehavior; max_active_runs?: number; + run_on_latest_version?: boolean; }; /** diff --git a/airflow-core/src/airflow/ui/src/components/DagActions/RunBackfillForm.tsx b/airflow-core/src/airflow/ui/src/components/DagActions/RunBackfillForm.tsx index 6d15801a05fcd..5155e48275112 100644 --- a/airflow-core/src/airflow/ui/src/components/DagActions/RunBackfillForm.tsx +++ b/airflow-core/src/airflow/ui/src/components/DagActions/RunBackfillForm.tsx @@ -43,9 +43,8 @@ type RunBackfillFormProps = { readonly dag: DAGResponse | DAGWithLatestDagRunsResponse; readonly onClose: () => void; }; -const today = new Date().toISOString().slice(0, 16); - type BackfillFormProps = DagRunTriggerParams & Omit; +const today = new Date().toISOString().slice(0, 16); const RunBackfillForm = ({ dag, onClose }: RunBackfillFormProps) => { const { t: translate } = useTranslation(["components", "common"]); @@ -62,6 +61,7 @@ const RunBackfillForm = ({ dag, onClose }: RunBackfillFormProps) => { max_active_runs: 1, reprocess_behavior: "none", run_backwards: false, + run_on_latest_version: true, to_date: "", }, mode: "onBlur", @@ -78,6 +78,7 @@ const RunBackfillForm = ({ dag, onClose }: RunBackfillFormProps) => { max_active_runs: values.max_active_runs ?? 1, reprocess_behavior: values.reprocess_behavior, run_backwards: values.run_backwards ?? false, + run_on_latest_version: values.run_on_latest_version ?? true, to_date: values.to_date ?? "", }, }, @@ -92,16 +93,11 @@ const RunBackfillForm = ({ dag, onClose }: RunBackfillFormProps) => { setErrors((prev) => ({ ...prev, date: dateValidationError })); } }, [dateValidationError]); - useEffect(() => { if (conf) { - reset((prevValues) => ({ - ...prevValues, - conf, - })); + reset((prevValues) => ({ ...prevValues, conf })); } }, [conf, reset]); - const dataIntervalStart = watch("from_date"); const dataIntervalEnd = watch("to_date"); const noDataInterval = !Boolean(dataIntervalStart) || !Boolean(dataIntervalEnd); @@ -128,16 +124,8 @@ const RunBackfillForm = ({ dag, onClose }: RunBackfillFormProps) => { reset(fdata); onClose(); }; - - const resetDateError = () => { - setErrors((prev) => ({ ...prev, date: undefined })); - }; - - const affectedTasks = data ?? { - backfills: [], - total_entries: 0, - }; - + const resetDateError = () => setErrors((prev) => ({ ...prev, date: undefined })); + const affectedTasks = data ?? { backfills: [], total_entries: 0 }; const inlineMessage = getInlineMessage(isPendingDryRun, affectedTasks.total_entries, translate); return ( @@ -178,12 +166,7 @@ const RunBackfillForm = ({ dag, onClose }: RunBackfillFormProps) => { control={control} name="reprocess_behavior" render={({ field }) => ( - { - field.onChange(event); - }} - > + {translate("backfill.reprocessBehavior")} @@ -230,6 +213,16 @@ const RunBackfillForm = ({ dag, onClose }: RunBackfillFormProps) => { )} /> + ( + + {translate("dags:runAndTaskActions.options.runOnLatestVersion")} + + )} + /> + {dag.is_paused ? ( <> { ) : undefined} -