diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py index 5420a34c9a9d0..b56f92262c39c 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py @@ -28,6 +28,7 @@ AliasGenerator, ConfigDict, computed_field, + field_serializer, field_validator, ) @@ -84,6 +85,11 @@ class DAGResponse(BaseModel): next_dagrun_run_after: datetime | None owners: list[str] + @field_serializer("tags") + def serialize_tags(self, tags: list[DagTagResponse]) -> list[DagTagResponse]: + """Sort tags alphabetically by name.""" + return sorted(tags, key=lambda tag: tag.name) + @field_validator("owners", mode="before") @classmethod def get_owners(cls, v: Any) -> list[str] | None: diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dags.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dags.py index 15a7395181557..b0dc432ceedc1 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dags.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dags.py @@ -1214,6 +1214,33 @@ def test_get_dag( } assert res_json == expected + def test_get_dag_tags_sorted_alphabetically(self, session, test_client, dag_maker): + """Test that tags are returned in alphabetical order for a single DAG.""" + dag_id = "test_dag_single_sorted_tags" + + # Create a DAG using dag_maker + with dag_maker(dag_id=dag_id, schedule=None): + EmptyOperator(task_id="task1") + + dag_maker.sync_dagbag_to_db() + + # Add tags in non-alphabetical order + tag_names = ["zebra", "alpha", "mike", "bravo"] + for tag_name in tag_names: + tag = DagTag(name=tag_name, dag_id=dag_id) + session.add(tag) + + session.commit() + + response = test_client.get(f"/dags/{dag_id}") + assert response.status_code == 200 + res_json = response.json() + + # Verify tags are sorted alphabetically + tag_names_in_response = [tag["name"] for tag in res_json["tags"]] + expected_sorted_tags = sorted(tag_names) + assert tag_names_in_response == expected_sorted_tags + def test_get_dag_should_response_401(self, unauthenticated_test_client): response = unauthenticated_test_client.get(f"/dags/{DAG1_ID}") assert response.status_code == 401