Skip to content

Commit 5258e09

Browse files
authored
Merge branch 'main' into feature/add-xcoms-keys-route
2 parents 0e7e400 + b0f8d26 commit 5258e09

120 files changed

Lines changed: 4091 additions & 580 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.pre-commit-config.yaml‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,20 @@ repos:
10141014
^scripts/ci/prek/generate_agent_skills\.py$
10151015
pass_filenames: false
10161016
additional_dependencies: ['pyyaml', 'rich>=13.6.0']
1017+
- id: check-documented-commands
1018+
name: Check documented breeze and prek commands exist
1019+
entry: ./scripts/ci/prek/check_documented_commands.py
1020+
language: python
1021+
files: >
1022+
(?x)
1023+
^AGENTS\.md$|
1024+
^contributing-docs/.*\.rst$|
1025+
^dev/breeze/src/airflow_breeze/commands/|
1026+
^(?:.*/)?\.pre-commit-config\.yaml$|
1027+
^scripts/ci/prek/check_documented_commands\.py$
1028+
pass_filenames: false
1029+
require_serial: true
1030+
additional_dependencies: ['pyyaml', 'rich>=13.6.0']
10171031
- id: run-skill-eval
10181032
name: Run skill-eval against AGENTS.md and cases
10191033
entry: ./dev/skill-evals/eval.py

‎airflow-core/docs/faq.rst‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ configuration option:
416416
* ``error`` — Treats detected issues as Dag import errors, preventing the Dag from loading.
417417

418418
Additionally, you can catch these issues earlier in your development workflow by using the
419-
`AIR302 <https://docs.astral.sh/ruff/rules/airflow3-dag-dynamic-value/>`_ ruff rule, which detects
419+
`AIR304 <https://docs.astral.sh/ruff/rules/airflow3-dag-dynamic-value/>`_ ruff rule, which detects
420420
dynamic values in Dag and Task constructors as part of static linting. See
421421
:ref:`best_practices/code_quality_and_linting` for how to set up ruff with Airflow-specific rules.
422422

‎airflow-core/src/airflow/api_fastapi/common/db/dags.py‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,14 @@ def generate_dag_with_latest_run_query(
7070
break
7171

7272
requested_order_by_set = set(order_by.value) if order_by.value is not None else set()
73-
dag_run_order_by_set = set(
74-
["last_run_state", "last_run_start_date", "-last_run_state", "-last_run_start_date"],
75-
)
73+
dag_run_order_by_set = {
74+
"last_run_state",
75+
"-last_run_state",
76+
"last_run_start_date",
77+
"-last_run_start_date",
78+
"last_run_run_after",
79+
"-last_run_run_after",
80+
}
7681

7782
if has_max_run_filter or (requested_order_by_set & dag_run_order_by_set):
7883
query = query.join(

‎airflow-core/src/airflow/api_fastapi/common/parameters.py‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
from airflow.models.dag import DagModel, DagTag
6363
from airflow.models.dag_favorite import DagFavorite
6464
from airflow.models.dag_version import DagVersion
65+
from airflow.models.dagbundle import DagBundleModel
6566
from airflow.models.dagrun import DagRun
6667
from airflow.models.errors import ParseImportError
6768
from airflow.models.hitl import HITLDetail
@@ -1020,6 +1021,29 @@ def depends(cls, owners: list[str] = Query(default_factory=list)) -> _OwnersFilt
10201021
return cls().set_value(owners)
10211022

10221023

1024+
class _TeamsFilter(BaseParam[list[str]]):
1025+
"""Filter Dags by team name (via bundle association)."""
1026+
1027+
def to_orm(self, select: Select) -> Select:
1028+
if self.skip_none is False:
1029+
raise ValueError(f"Cannot set 'skip_none' to False on a {type(self)}")
1030+
1031+
if not self.value:
1032+
return select
1033+
1034+
from airflow.models.team import Team
1035+
1036+
return select.where(
1037+
DagModel.bundle_name.in_(
1038+
sql_select(DagBundleModel.name).join(DagBundleModel.teams).where(Team.name.in_(self.value))
1039+
)
1040+
)
1041+
1042+
@classmethod
1043+
def depends(cls, teams: list[str] = Query(default_factory=list)) -> _TeamsFilter:
1044+
return cls().set_value(teams)
1045+
1046+
10231047
def _safe_parse_datetime(date_to_check: str) -> datetime:
10241048
"""
10251049
Parse datetime and raise error for invalid dates.
@@ -1268,6 +1292,7 @@ def depends_float(
12681292
]
12691293
QueryTagsFilter = Annotated[_TagsFilter, Depends(_TagsFilter.depends)]
12701294
QueryOwnersFilter = Annotated[_OwnersFilter, Depends(_OwnersFilter.depends)]
1295+
QueryTeamsFilter = Annotated[_TeamsFilter, Depends(_TeamsFilter.depends)]
12711296

12721297

12731298
class _HasAssetScheduleFilter(BaseParam[bool]):

‎airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/dags.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class DAGWithLatestDagRunsResponse(DAGResponse):
3232
latest_dag_runs: list[DAGRunLightResponse]
3333
pending_actions: list[HITLDetail]
3434
is_favorite: bool
35+
team_name: str | None = None
3536

3637

3738
class DAGWithLatestDagRunsCollectionResponse(BaseModel):

‎airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,14 @@ paths:
338338
items:
339339
type: string
340340
title: Owners
341+
- name: teams
342+
in: query
343+
required: false
344+
schema:
345+
type: array
346+
items:
347+
type: string
348+
title: Teams
341349
- name: dag_ids
342350
in: query
343351
required: false
@@ -510,13 +518,13 @@ paths:
510518
type: string
511519
description: 'Attributes to order by, multi criteria sort is supported.
512520
Prefix with `-` for descending order. Supported attributes: `dag_id, dag_display_name,
513-
next_dagrun, state, start_date, last_run_state, last_run_start_date`'
521+
next_dagrun, state, start_date, last_run_state, last_run_start_date, last_run_run_after`'
514522
default:
515523
- dag_id
516524
title: Order By
517525
description: 'Attributes to order by, multi criteria sort is supported. Prefix
518526
with `-` for descending order. Supported attributes: `dag_id, dag_display_name,
519-
next_dagrun, state, start_date, last_run_state, last_run_start_date`'
527+
next_dagrun, state, start_date, last_run_state, last_run_start_date, last_run_run_after`'
520528
- name: is_favorite
521529
in: query
522530
required: false
@@ -2629,6 +2637,11 @@ components:
26292637
is_favorite:
26302638
type: boolean
26312639
title: Is Favorite
2640+
team_name:
2641+
anyOf:
2642+
- type: string
2643+
- type: 'null'
2644+
title: Team Name
26322645
is_backfillable:
26332646
type: boolean
26342647
title: Is Backfillable

‎airflow-core/src/airflow/api_fastapi/core_api/routes/ui/dags.py‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
QueryPausedFilter,
5252
QueryPendingActionsFilter,
5353
QueryTagsFilter,
54+
QueryTeamsFilter,
5455
SortParam,
5556
filter_param_factory,
5657
)
@@ -96,6 +97,7 @@ def get_dags(
9697
offset: QueryOffset,
9798
tags: QueryTagsFilter,
9899
owners: QueryOwnersFilter,
100+
teams: QueryTeamsFilter,
99101
dag_ids: Annotated[
100102
FilterParam[list[str] | None],
101103
Depends(filter_param_factory(DagModel.dag_id, list[str] | None, FilterOptionEnum.IN, "dag_ids")),
@@ -117,7 +119,11 @@ def get_dags(
117119
SortParam(
118120
["dag_id", "dag_display_name", "next_dagrun", "state", "start_date"],
119121
DagModel,
120-
{"last_run_state": DagRun.state, "last_run_start_date": DagRun.start_date},
122+
{
123+
"last_run_state": DagRun.state,
124+
"last_run_start_date": DagRun.start_date,
125+
"last_run_run_after": DagRun.run_after,
126+
},
121127
).dynamic_depends()
122128
),
123129
],
@@ -153,6 +159,7 @@ def get_dags(
153159
dag_display_name_prefix_pattern,
154160
tags,
155161
owners,
162+
teams,
156163
last_dag_run_state,
157164
dag_run_state,
158165
is_favorite,
@@ -228,6 +235,13 @@ def get_dags(
228235
for dag_id, hitl_detail in pending_actions:
229236
pending_actions_by_dag_id[dag_id].append(hitl_detail)
230237

238+
# Fetch team names when multi-team is enabled
239+
team_names_by_dag_id: dict[str, str | None] = {}
240+
if conf.getboolean("core", "multi_team") and dags:
241+
team_names_by_dag_id = DagModel.get_dag_id_to_team_name_mapping(
242+
[dag.dag_id for dag in dags], session=session
243+
)
244+
231245
# aggregate rows by dag_id
232246
# Build the dict dynamically from DAGResponse.model_fields so that new fields
233247
# added to DAGResponse are picked up automatically without code changes here.
@@ -245,6 +259,7 @@ def get_dags(
245259
"latest_dag_runs": [],
246260
"pending_actions": pending_actions_by_dag_id[dag.dag_id],
247261
"is_favorite": dag.dag_id in favorite_dag_ids,
262+
"team_name": team_names_by_dag_id.get(dag.dag_id),
248263
}
249264
)
250265
dag_runs_by_dag_id[dag.dag_id] = DAGWithLatestDagRunsResponse.model_validate(dag_data)

‎airflow-core/src/airflow/cli/commands/task_command.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from airflow import settings
3131
from airflow._shared.timezones import timezone
3232
from airflow.cli.simple_table import AirflowConsole
33-
from airflow.cli.utils import fetch_dag_run_from_run_id_or_logical_date_string
33+
from airflow.cli.utils import deprecated_for_airflowctl, fetch_dag_run_from_run_id_or_logical_date_string
3434
from airflow.exceptions import AirflowConfigException, DagRunNotFound, NotMapped, TaskInstanceNotFound
3535
from airflow.models import TaskInstance
3636
from airflow.models.dag_version import DagVersion
@@ -354,6 +354,7 @@ def _guess_debugger() -> _SupportedDebugger:
354354
raise exc
355355

356356

357+
@deprecated_for_airflowctl("airflowctl tasks states-for-dag-run")
357358
@cli_utils.action_cli(check_db=False)
358359
@suppress_logs_and_warning
359360
@providers_configuration_loaded

0 commit comments

Comments
 (0)