This is an automated email from the ASF dual-hosted git repository.
henry3260 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 b5414588d3e Fix airflowctl list operations ignoring the requested
offset (#70989)
b5414588d3e is described below
commit b5414588d3ef97512cbe0b3595e6fc9f042a5861
Author: rjgoyln <[email protected]>
AuthorDate: Wed Aug 5 02:02:01 2026 +0800
Fix airflowctl list operations ignoring the requested offset (#70989)
---
airflow-ctl/src/airflowctl/api/operations.py | 2 +-
.../tests/airflow_ctl/api/test_operations.py | 23 ++++++++++++++++++++++
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/airflow-ctl/src/airflowctl/api/operations.py
b/airflow-ctl/src/airflowctl/api/operations.py
index 94b31010abb..0e561027887 100644
--- a/airflow-ctl/src/airflowctl/api/operations.py
+++ b/airflow-ctl/src/airflowctl/api/operations.py
@@ -220,7 +220,7 @@ class BaseOperations:
raw = fill_missing_fields(json.loads(content), data_model)
return data_model.model_validate(raw) # type:
ignore[union-attr]
- self.response = self.client.get(path, params=shared_params)
+ self.response = self.client.get(path, params={**shared_params,
"offset": offset})
first_pass = safe_validate(self.response.content)
total_entries = first_pass.total_entries # type: ignore[attr-defined]
if total_entries < limit:
diff --git a/airflow-ctl/tests/airflow_ctl/api/test_operations.py
b/airflow-ctl/tests/airflow_ctl/api/test_operations.py
index 4868841bc2f..952068c86aa 100644
--- a/airflow-ctl/tests/airflow_ctl/api/test_operations.py
+++ b/airflow-ctl/tests/airflow_ctl/api/test_operations.py
@@ -250,6 +250,29 @@ class TestBaseOperations:
for call in mock_client.get.call_args_list:
assert call.kwargs["params"]["limit"] == 2
+ def test_execute_list_sends_offset_to_server(self):
+ """``offset`` must reach the server on the first request, not only on
subsequent pages."""
+ rows = [{"name": name} for name in "abcdef"]
+
+ def paged(path, params):
+ # An absent ``offset`` is what the server would see as its own
default of 0.
+ start = params.get("offset", 0)
+ return Mock(
+ content=json.dumps(
+ {"hellos": rows[start : start + params["limit"]],
"total_entries": len(rows)}
+ )
+ )
+
+ mock_client = Mock()
+ mock_client.get.side_effect = paged
+ base_operation = BaseOperations(client=mock_client)
+
+ response = base_operation.execute_list(
+ path="hello", data_model=HelloCollectionResponse, offset=2, limit=2
+ )
+
+ assert [hello.name for hello in response.hellos] == ["c", "d", "e",
"f"]
+
@pytest.mark.parametrize("limit", [0, -1])
def test_execute_list_rejects_non_positive_limit(self, limit):
mock_client = Mock()