You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by "dheerajturaga (via GitHub)" <gi...@apache.org> on 2026/09/13 00:26:26 UTC

[PR] Add a bulk pause/drain action to the Dags list [airflow]

dheerajturaga opened a new pull request, #73055:
URL: https://github.com/apache/airflow/pull/73055

   Adds a way to pause or drain several Dags at once from the Dags list table view: select rows with the new checkbox column, then trigger the bulk action once. If any selected Dag has unfinished runs, the drain-vs-pause choice is shown a single time for the whole batch instead of once per Dag.
   
   Depends on #72407 (draining state), which hasn't merged yet — draining introduced the per-Dag choice this bulk action collapses back down to one click for a whole selection. Until #72407 merges, this PR's diff includes its changes too; it will shrink automatically to just this PR's commit once #72407 lands on `main`.
   
   - New `PATCH /dags/bulk` endpoint (`BulkDAGBody` + `BulkDagService` + `requires_access_dag_bulk`), following the same `Bulk*` pattern already used for Task Instances, Dag Runs, Variables, Connections, and Pools.
   - Row selection + bulk action bar on the Dags list table view, reusing the existing `useRowSelection`/`SelectionProvider`/`ActionBar` primitives from Task Instances and Dag Runs.
   - The pause-vs-drain choice dialog is extracted out of the single-Dag `TogglePause` toggle into a shared `PauseOrDrainChoiceModal`, so both flows show identical behavior/copy.
   - Two incidental doc-generation script fixes surfaced by the new permission dependency: `extract_permissions.py` needed a resource mapping for `requires_access_dag_bulk`, and `fab_permissions_doc.py` had a gap where a bare-`DAG`-resource bulk permission (no explicit HTTP method) defaulted to the wrong FAB action.
   
   ## Test plan
   
   - [x] Backend: `TestBulkDags` in `test_dags.py` — bulk pause, bulk drain, legacy `is_paused`, missing-id fail/skip semantics, unsupported create/delete, 401/403, and per-Dag authorization rejection. Full `test_dags.py` suite passes (153 passed, 6 pre-existing skips).
   - [x] Frontend: new bulk-selection test in `DagsList.test.tsx`; `TogglePause.test.tsx` passes unchanged, confirming the extracted choice dialog is behavior-preserving.
   - [x] `prek run --stage pre-commit` passes with 0 failures (includes mypy, ruff, the regenerated OpenAPI spec/TS client, and the regenerated permission-reference docs).
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes — Claude Sonnet 5
   
   Generated-by: Claude Sonnet 5 following [the guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   
   https://claude.ai/code/session_01QEsvWxemkjXqw7GE69YLPk


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] UI: Add a bulk pause/drain action to the Dags list [airflow]

Posted by "dheerajturaga (via GitHub)" <gi...@apache.org>.
dheerajturaga commented on code in PR #73055:
URL: https://github.com/apache/airflow/pull/73055#discussion_r4108865938


##########
airflow-core/src/airflow/ui/src/pages/DagsList/BulkPauseDrainDagsButton.tsx:
##########
@@ -0,0 +1,97 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { Button, useDisclosure } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
+
+import type { DAGWithLatestDagRunsResponse, DagSchedulingState } from "openapi/requests/types.gen";
+
+import { ActionErrors } from "src/components/ActionErrors";
+import { ConfirmationModal } from "src/components/ConfirmationModal";
+import { PauseOrDrainChoiceModal } from "src/components/PauseOrDrainChoiceModal";
+
+import { useBulkPauseDrainDags } from "src/queries/useBulkPauseDrainDags";
+
+type Props = {
+  readonly deselectKeys: (keys: Array<string>) => void;
+  readonly selectedDags: Array<DAGWithLatestDagRunsResponse>;
+};
+
+const BulkPauseDrainDagsButton = ({ deselectKeys, selectedDags }: Props) => {
+  const { t: translate } = useTranslation(["common", "dags"]);
+  const { onClose, onOpen, open } = useDisclosure();
+  const { bulkAction, data, error, isPending, reset } = useBulkPauseDrainDags({
+    deselectKeys,
+    onSuccessConfirm: onClose,
+  });
+
+  // Nothing is running in any selected Dag, so draining and pausing now are equivalent
+  // for the whole batch — skip the drain-vs-pause choice, same as the single-Dag toggle does.
+  const allIdle = selectedDags.every((dag) => !dag.has_unfinished_runs);

Review Comment:
   Added  "skips the drain choice and pauses every selected Dag when …" in `DagsList.test.tsx` checks that an all-idle selection gets the plain confirm dialog instead of the drain choice, and that every Dag is sent as `paused`.
   
   Writing it turned up a bug: an already-paused Dag with unfinished runs counted as not idle, and picking Drain would have unpaused it, letting the scheduler resume its runs. Paused Dags are now left out of `allIdle` and always sent as `paused`; the test's second case covers that.
   
   ---
   Drafted-by: Claude Code (Opus 5.5); reviewed by @dheerajturaga before posting
   



##########
airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.test.tsx:
##########
@@ -102,6 +102,50 @@ describe("Dag Filters", () => {
   });
 });
 
+describe("Bulk pause/drain Dags", () => {
+  it("pauses every selected Dag in one bulk request", async () => {

Review Comment:
   Added "offers the drain choice once for a mix of idle and running Dags …" selects a Dag with running runs, an idle Dag and an already-paused Dag. It checks that the drain choice is shown once instead of the confirm dialog, and, for both Drain and Pause now, that the running and idle Dags get that state while the paused one stays `paused`.
   
   ---
   Drafted-by: Claude Code (Opus 5.5); reviewed by @dheerajturaga before posting
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] UI: Add bulk pause, drain and unpause actions to the Dags list [airflow]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #73055:
URL: https://github.com/apache/airflow/pull/73055#issuecomment-5850076761

   ### Backport failed to create: airflow-ctl/v0-1-test. View the failure log <a href='https://github.com/apache/airflow/actions/runs/36273279601'> Run details </a>
   
   Note: As of [Merging PRs targeted for Airflow 3.X](https://github.com/apache/airflow/blob/main/dev/README_AIRFLOW3_DEV.md#merging-prs-targeted-for-airflow-3x)
   the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.
   
   In matter of doubt please ask in [#release-management](https://apache-airflow.slack.com/archives/C03G9H97MM2) Slack channel.
   
   <table>
       <tr>
           <th>Status</th>
           <th>Branch</th>
           <th>Result</th>
       </tr>
       <tr>
           <td>❌</td>
           <td>airflow-ctl/v0-1-test</td>
           <td><a href="https://github.com/apache/airflow/commit/18fe1c6098605e089dcb7571b3839183f7b32752"><img src='https://img.shields.io/badge/Commit-18fe1c6-red' alt='Commit Link'></a></td>
       </tr>
   </table>
   
   You can attempt to backport this manually by running:
   
   ```bash
   cherry_picker 18fe1c6 airflow-ctl/v0-1-test
   ```
   
   This should apply the commit to the airflow-ctl/v0-1-test branch and leave the commit in conflict state marking
   the files that need manual conflict resolution.
   
   After you have resolved the conflicts, you can continue the backport process by running:
   
   ```bash
   cherry_picker --continue
   ```
   
   If you don't have cherry-picker installed, see the [installation guide](https://github.com/apache/airflow/blob/main/dev/README.md#how-to-backport-pr-with-cherry-picker-cli).
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] UI: Add a bulk pause/drain action to the Dags list [airflow]

Posted by "dheerajturaga (via GitHub)" <gi...@apache.org>.
dheerajturaga commented on code in PR #73055:
URL: https://github.com/apache/airflow/pull/73055#discussion_r4108865938


##########
airflow-core/src/airflow/ui/src/pages/DagsList/BulkPauseDrainDagsButton.tsx:
##########
@@ -0,0 +1,97 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { Button, useDisclosure } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
+
+import type { DAGWithLatestDagRunsResponse, DagSchedulingState } from "openapi/requests/types.gen";
+
+import { ActionErrors } from "src/components/ActionErrors";
+import { ConfirmationModal } from "src/components/ConfirmationModal";
+import { PauseOrDrainChoiceModal } from "src/components/PauseOrDrainChoiceModal";
+
+import { useBulkPauseDrainDags } from "src/queries/useBulkPauseDrainDags";
+
+type Props = {
+  readonly deselectKeys: (keys: Array<string>) => void;
+  readonly selectedDags: Array<DAGWithLatestDagRunsResponse>;
+};
+
+const BulkPauseDrainDagsButton = ({ deselectKeys, selectedDags }: Props) => {
+  const { t: translate } = useTranslation(["common", "dags"]);
+  const { onClose, onOpen, open } = useDisclosure();
+  const { bulkAction, data, error, isPending, reset } = useBulkPauseDrainDags({
+    deselectKeys,
+    onSuccessConfirm: onClose,
+  });
+
+  // Nothing is running in any selected Dag, so draining and pausing now are equivalent
+  // for the whole batch — skip the drain-vs-pause choice, same as the single-Dag toggle does.
+  const allIdle = selectedDags.every((dag) => !dag.has_unfinished_runs);

Review Comment:
   Added in e391a9f: "skips the drain choice and pauses every selected Dag when …" in `DagsList.test.tsx` checks that an all-idle selection gets the plain confirm dialog instead of the drain choice, and that every Dag is sent as `paused`.
   
   Writing it turned up a bug: an already-paused Dag with unfinished runs counted as not idle, and picking Drain would have unpaused it, letting the scheduler resume its runs. Paused Dags are now left out of `allIdle` and always sent as `paused`; the test's second case covers that.
   
   ---
   Drafted-by: Claude Code (Opus 5.5); reviewed by @dheerajturaga before posting
   



##########
airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.test.tsx:
##########
@@ -102,6 +102,50 @@ describe("Dag Filters", () => {
   });
 });
 
+describe("Bulk pause/drain Dags", () => {
+  it("pauses every selected Dag in one bulk request", async () => {

Review Comment:
   Added in e391a9f: "offers the drain choice once for a mix of idle and running Dags …" selects a Dag with running runs, an idle Dag and an already-paused Dag. It checks that the drain choice is shown once instead of the confirm dialog, and, for both Drain and Pause now, that the running and idle Dags get that state while the paused one stays `paused`.
   
   ---
   Drafted-by: Claude Code (Opus 5.5); reviewed by @dheerajturaga before posting
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] UI: Add a bulk pause/drain action to the Dags list [airflow]

Posted by "bbovenzi (via GitHub)" <gi...@apache.org>.
bbovenzi commented on code in PR #73055:
URL: https://github.com/apache/airflow/pull/73055#discussion_r4106624833


##########
airflow-core/src/airflow/ui/src/pages/DagsList/BulkPauseDrainDagsButton.tsx:
##########
@@ -0,0 +1,97 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { Button, useDisclosure } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
+
+import type { DAGWithLatestDagRunsResponse, DagSchedulingState } from "openapi/requests/types.gen";
+
+import { ActionErrors } from "src/components/ActionErrors";
+import { ConfirmationModal } from "src/components/ConfirmationModal";
+import { PauseOrDrainChoiceModal } from "src/components/PauseOrDrainChoiceModal";
+
+import { useBulkPauseDrainDags } from "src/queries/useBulkPauseDrainDags";
+
+type Props = {
+  readonly deselectKeys: (keys: Array<string>) => void;
+  readonly selectedDags: Array<DAGWithLatestDagRunsResponse>;
+};
+
+const BulkPauseDrainDagsButton = ({ deselectKeys, selectedDags }: Props) => {
+  const { t: translate } = useTranslation(["common", "dags"]);
+  const { onClose, onOpen, open } = useDisclosure();
+  const { bulkAction, data, error, isPending, reset } = useBulkPauseDrainDags({
+    deselectKeys,
+    onSuccessConfirm: onClose,
+  });
+
+  // Nothing is running in any selected Dag, so draining and pausing now are equivalent
+  // for the whole batch — skip the drain-vs-pause choice, same as the single-Dag toggle does.
+  const allIdle = selectedDags.every((dag) => !dag.has_unfinished_runs);

Review Comment:
   Let's add a test for allIdle?



##########
airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.test.tsx:
##########
@@ -102,6 +102,50 @@ describe("Dag Filters", () => {
   });
 });
 
+describe("Bulk pause/drain Dags", () => {
+  it("pauses every selected Dag in one bulk request", async () => {

Review Comment:
   Can we add test coverage for  mix of idle dags and dags with active runs?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] UI: Add a bulk pause/drain action to the Dags list [airflow]

Posted by "dheerajturaga (via GitHub)" <gi...@apache.org>.
dheerajturaga commented on PR #73055:
URL: https://github.com/apache/airflow/pull/73055#issuecomment-5821484851

   @bbovenzi, it would be great to get your opinion on this. This is needed for drain feature to be feature complete intime for 3.4.0


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] UI: Add a bulk pause/drain action to the Dags list [airflow]

Posted by "dheerajturaga (via GitHub)" <gi...@apache.org>.
dheerajturaga commented on PR #73055:
URL: https://github.com/apache/airflow/pull/73055#issuecomment-5840075940

   @bbovenzi , I also updated the PR to also unpause the dags aswell. That was missing in my original implementation


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] UI: Add bulk pause, drain and unpause actions to the Dags list [airflow]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #73055:
URL: https://github.com/apache/airflow/pull/73055#issuecomment-5850075333

   ### Backport failed to create: v3-3-test. View the failure log <a href='https://github.com/apache/airflow/actions/runs/36273279601'> Run details </a>
   
   Note: As of [Merging PRs targeted for Airflow 3.X](https://github.com/apache/airflow/blob/main/dev/README_AIRFLOW3_DEV.md#merging-prs-targeted-for-airflow-3x)
   the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.
   
   In matter of doubt please ask in [#release-management](https://apache-airflow.slack.com/archives/C03G9H97MM2) Slack channel.
   
   <table>
       <tr>
           <th>Status</th>
           <th>Branch</th>
           <th>Result</th>
       </tr>
       <tr>
           <td>❌</td>
           <td>v3-3-test</td>
           <td><a href="https://github.com/apache/airflow/commit/18fe1c6098605e089dcb7571b3839183f7b32752"><img src='https://img.shields.io/badge/Commit-18fe1c6-red' alt='Commit Link'></a></td>
       </tr>
   </table>
   
   You can attempt to backport this manually by running:
   
   ```bash
   cherry_picker 18fe1c6 v3-3-test
   ```
   
   This should apply the commit to the v3-3-test branch and leave the commit in conflict state marking
   the files that need manual conflict resolution.
   
   After you have resolved the conflicts, you can continue the backport process by running:
   
   ```bash
   cherry_picker --continue
   ```
   
   If you don't have cherry-picker installed, see the [installation guide](https://github.com/apache/airflow/blob/main/dev/README.md#how-to-backport-pr-with-cherry-picker-cli).
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] UI: Add bulk pause, drain and unpause actions to the Dags list [airflow]

Posted by "bbovenzi (via GitHub)" <gi...@apache.org>.
bbovenzi merged PR #73055:
URL: https://github.com/apache/airflow/pull/73055


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org