This is an automated email from the ASF dual-hosted git repository.
ephraimanierobi 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 0224303bc68 Fix backfill run_on_latest_version defaulting to False
instead of True (#59304)
0224303bc68 is described below
commit 0224303bc68d30573d87cc141c1d246806db906f
Author: Ephraim Anierobi <[email protected]>
AuthorDate: Thu Dec 11 17:40:08 2025 +0100
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
---
.../api_fastapi/core_api/datamodels/backfills.py | 1 +
.../core_api/openapi/v2-rest-api-generated.yaml | 4 +++
.../core_api/routes/public/backfills.py | 1 +
airflow-core/src/airflow/cli/cli_config.py | 5 +--
.../airflow/ui/openapi-gen/requests/schemas.gen.ts | 5 +++
.../airflow/ui/openapi-gen/requests/types.gen.ts | 1 +
.../src/components/DagActions/RunBackfillForm.tsx | 42 +++++++++-------------
.../unit/cli/commands/test_backfill_command.py | 6 ++--
.../src/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 94a2c032a39..869c4ba38a8 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
@@ -36,6 +36,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 fb07b23aabc..5bcc026a26e 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
@@ -8965,6 +8965,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 3684776784a..adbac360247 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
@@ -242,6 +242,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 0a02680a136..80e00a38423 100644
--- a/airflow-core/src/airflow/cli/cli_config.py
+++ b/airflow-core/src/airflow/cli/cli_config.py
@@ -346,10 +346,11 @@ ARG_BACKFILL_REPROCESS_BEHAVIOR = Arg(
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 440ea0b902b..419f3b2da63 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
@@ -458,6 +458,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 da93b544463..05391098ac1 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
@@ -126,6 +126,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 6d15801a05f..5155e482751 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<BackfillPostBody,
"dag_run_conf">;
+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 }) => (
- <RadioCardRoot
- defaultValue={field.value}
- onChange={(event) => {
- field.onChange(event);
- }}
- >
+ <RadioCardRoot defaultValue={field.value}
onChange={field.onChange}>
<RadioCardLabel fontSize="md" fontWeight="semibold" mb={3}>
{translate("backfill.reprocessBehavior")}
</RadioCardLabel>
@@ -230,6 +213,16 @@ const RunBackfillForm = ({ dag, onClose }:
RunBackfillFormProps) => {
)}
/>
<Spacer />
+ <Controller
+ control={control}
+ name="run_on_latest_version"
+ render={({ field }) => (
+ <Checkbox checked={field.value} colorPalette="brand"
onChange={field.onChange}>
+ {translate("dags:runAndTaskActions.options.runOnLatestVersion")}
+ </Checkbox>
+ )}
+ />
+ <Spacer />
{dag.is_paused ? (
<>
<Checkbox
@@ -243,7 +236,6 @@ const RunBackfillForm = ({ dag, onClose }:
RunBackfillFormProps) => {
<Spacer />
</>
) : undefined}
-
<ConfigForm
control={control}
errors={errors}
diff --git a/airflow-core/tests/unit/cli/commands/test_backfill_command.py
b/airflow-core/tests/unit/cli/commands/test_backfill_command.py
index 3e756bfefd2..79d133f84c8 100644
--- a/airflow-core/tests/unit/cli/commands/test_backfill_command.py
+++ b/airflow-core/tests/unit/cli/commands/test_backfill_command.py
@@ -101,7 +101,7 @@ class TestCliBackfill:
dag_run_conf=None,
reprocess_behavior=expected_repro,
triggering_user_name="root",
- run_on_latest_version=False,
+ run_on_latest_version=True,
)
@mock.patch("airflow.cli.commands.backfill_command._create_backfill")
@@ -189,7 +189,7 @@ class TestCliBackfill:
dag_run_conf={"example_key": "example_value"},
reprocess_behavior=None,
triggering_user_name="root",
- run_on_latest_version=False,
+ run_on_latest_version=True,
)
def test_backfill_with_invalid_dag_run_conf(self):
@@ -235,5 +235,5 @@ class TestCliBackfill:
dag_run_conf={},
reprocess_behavior=None,
triggering_user_name="root",
- run_on_latest_version=False,
+ run_on_latest_version=True,
)
diff --git a/airflow-ctl/src/airflowctl/api/datamodels/generated.py
b/airflow-ctl/src/airflowctl/api/datamodels/generated.py
index 2833a681132..5e2c2078025 100644
--- a/airflow-ctl/src/airflowctl/api/datamodels/generated.py
+++ b/airflow-ctl/src/airflowctl/api/datamodels/generated.py
@@ -1092,6 +1092,7 @@ class BackfillPostBody(BaseModel):
dag_run_conf: Annotated[dict[str, Any] | None, Field(title="Dag Run
Conf")] = {}
reprocess_behavior: ReprocessBehavior | None = "none"
max_active_runs: Annotated[int | None, Field(title="Max Active Runs")] = 10
+ run_on_latest_version: Annotated[bool | None, Field(title="Run On Latest
Version")] = True
class BackfillResponse(BaseModel):