This is an automated email from the ASF dual-hosted git repository.
potiuk 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 92954d87415 Add `breeze issues unassign` command to clean up
non-collaborator assignees (#62585)
92954d87415 is described below
commit 92954d87415f5fa436ba4eb0a98b1b284c230665
Author: Jarek Potiuk <[email protected]>
AuthorDate: Fri Feb 27 21:49:08 2026 +0100
Add `breeze issues unassign` command to clean up non-collaborator assignees
(#62585)
Co-authored-by: Claude Opus 4.6 <[email protected]>
---
dev/breeze/doc/10_ui_tasks.rst | 4 +-
dev/breeze/doc/11_issues_tasks.rst | 58 +++++++
...ze_topics.rst => 12_advanced_breeze_topics.rst} | 0
dev/breeze/doc/README.rst | 3 +-
dev/breeze/doc/images/output-commands.svg | 22 ++-
dev/breeze/doc/images/output_issues.svg | 103 ++++++++++++
dev/breeze/doc/images/output_issues.txt | 1 +
dev/breeze/doc/images/output_issues_unassign.svg | 132 ++++++++++++++++
dev/breeze/doc/images/output_issues_unassign.txt | 1 +
.../output_setup_check-all-params-in-groups.svg | 10 +-
.../output_setup_check-all-params-in-groups.txt | 2 +-
.../output_setup_regenerate-command-images.svg | 22 +--
.../output_setup_regenerate-command-images.txt | 2 +-
dev/breeze/src/airflow_breeze/breeze.py | 2 +
.../src/airflow_breeze/commands/issues_commands.py | 174 +++++++++++++++++++++
.../commands/issues_commands_config.py | 35 +++++
.../src/airflow_breeze/configure_rich_click.py | 7 +
17 files changed, 552 insertions(+), 26 deletions(-)
diff --git a/dev/breeze/doc/10_ui_tasks.rst b/dev/breeze/doc/10_ui_tasks.rst
index b5e5f88fe32..904fb5f2891 100644
--- a/dev/breeze/doc/10_ui_tasks.rst
+++ b/dev/breeze/doc/10_ui_tasks.rst
@@ -89,5 +89,5 @@ Example usage:
-----
-Next step: Follow the `Advanced Breeze topics
<11_advanced_breeze_topics.rst>`__ instructions to learn more
-about advanced Breeze topics and internals.
+Next step: Follow the `Issues tasks <11_issues_tasks.rst>`__ instructions to
learn about
+Breeze commands for managing GitHub issues.
diff --git a/dev/breeze/doc/11_issues_tasks.rst
b/dev/breeze/doc/11_issues_tasks.rst
new file mode 100644
index 00000000000..de4ab617d48
--- /dev/null
+++ b/dev/breeze/doc/11_issues_tasks.rst
@@ -0,0 +1,58 @@
+ .. 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.
+
+Issues tasks
+------------
+
+There are some Breeze commands that are used to manage GitHub issues for the
Apache Airflow project.
+
+Those are all of the available issues commands:
+
+.. image:: ./images/output_issues.svg
+ :target:
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/doc/images/output_issues.svg
+ :width: 100%
+ :alt: Breeze issues commands
+
+Unassigning non-collaborators
+"""""""""""""""""""""""""""""
+
+The ``breeze issues unassign`` command finds open issues that have assignees
who are not repository
+collaborators, and removes those assignees. This is useful for maintainers to
clean up stale assignments.
+
+.. image:: ./images/output_issues_unassign.svg
+ :target:
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/doc/images/output_issues_unassign.svg
+ :width: 100%
+ :alt: Breeze issues unassign
+
+Example usage:
+
+.. code-block:: bash
+
+ # Dry run to see which assignees would be removed
+ breeze issues unassign --dry-run
+
+ # Run with confirmation prompts per batch
+ breeze issues unassign
+
+ # Use a custom batch size
+ breeze issues unassign --batch-size 50
+
+
+-----
+
+Next step: Follow the `Advanced Breeze topics
<12_advanced_breeze_topics.rst>`__ instructions to learn more
+about advanced Breeze topics and internals.
diff --git a/dev/breeze/doc/11_advanced_breeze_topics.rst
b/dev/breeze/doc/12_advanced_breeze_topics.rst
similarity index 100%
rename from dev/breeze/doc/11_advanced_breeze_topics.rst
rename to dev/breeze/doc/12_advanced_breeze_topics.rst
diff --git a/dev/breeze/doc/README.rst b/dev/breeze/doc/README.rst
index 026482f9055..03df38bae1c 100644
--- a/dev/breeze/doc/README.rst
+++ b/dev/breeze/doc/README.rst
@@ -49,7 +49,8 @@ The following documents describe how to use the Breeze
environment:
* `CI tasks <08_ci_tasks.rst>`_ - describes how Breeze commands are used in
our CI.
* `Release management tasks <09_release_management_tasks.rst>`_ - describes
how to use Breeze for release management tasks.
* `UI tasks <10_ui_tasks.rst>`_ - describes how Breeze commands are used to
support Apache Airflow project UI.
-* `Advanced Breeze topics <11_advanced_breeze_topics.rst>`_ - describes
advanced Breeze topics/internals of Breeze.
+* `Issues tasks <11_issues_tasks.rst>`_ - describes how Breeze commands are
used to manage GitHub issues.
+* `Advanced Breeze topics <12_advanced_breeze_topics.rst>`_ - describes
advanced Breeze topics/internals of Breeze.
You can also learn more context and Architecture Decisions taken when
developing Breeze in the
`Architecture Decision Records <adr>`_.
diff --git a/dev/breeze/doc/images/output-commands.svg
b/dev/breeze/doc/images/output-commands.svg
index c71eb234607..f970ad85743 100644
--- a/dev/breeze/doc/images/output-commands.svg
+++ b/dev/breeze/doc/images/output-commands.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 2148.4"
xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 2221.6"
xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@@ -43,7 +43,7 @@
<defs>
<clipPath id="breeze-help-clip-terminal">
- <rect x="0" y="0" width="1463.0" height="2097.4" />
+ <rect x="0" y="0" width="1463.0" height="2170.6" />
</clipPath>
<clipPath id="breeze-help-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -300,9 +300,18 @@
<clipPath id="breeze-help-line-84">
<rect x="0" y="2051.1" width="1464" height="24.65"/>
</clipPath>
+<clipPath id="breeze-help-line-85">
+ <rect x="0" y="2075.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-help-line-86">
+ <rect x="0" y="2099.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-help-line-87">
+ <rect x="0" y="2124.3" width="1464" height="24.65"/>
+ </clipPath>
</defs>
- <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="2146.4" rx="8"/><text
class="breeze-help-title" fill="#c5c8c6" text-anchor="middle" x="740"
y="27">Breeze commands</text>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="2219.6" rx="8"/><text
class="breeze-help-title" fill="#c5c8c6" text-anchor="middle" x="740"
y="27">Breeze commands</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -395,9 +404,12 @@
</text><text class="breeze-help-r5" x="0" y="1972" textLength="24.4"
clip-path="url(#breeze-help-line-80)">╭─</text><text class="breeze-help-r5"
x="24.4" y="1972" textLength="158.6"
clip-path="url(#breeze-help-line-80)"> UI commands </text><text
class="breeze-help-r5" x="183" y="1972" textLength="1256.6"
clip-path="url(#breeze-help-line-80)">───────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze-hel [...]
</text><text class="breeze-help-r5" x="0" y="1996.4" textLength="12.2"
clip-path="url(#breeze-help-line-81)">│</text><text class="breeze-help-r4"
x="24.4" y="1996.4" textLength="85.4"
clip-path="url(#breeze-help-line-81)">ui     </text><text
class="breeze-help-r1" x="134.2" y="1996.4" textLength="1305.4"
clip-path="url(#breeze-help-line-81)">Tools for UI development and maintenance         
[...]
</text><text class="breeze-help-r5" x="0" y="2020.8" textLength="1464"
clip-path="url(#breeze-help-line-82)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="2020.8" textLength="12.2"
clip-path="url(#breeze-help-line-82)">
-</text><text class="breeze-help-r5" x="0" y="2045.2" textLength="24.4"
clip-path="url(#breeze-help-line-83)">╭─</text><text class="breeze-help-r5"
x="24.4" y="2045.2" textLength="195.2"
clip-path="url(#breeze-help-line-83)"> Setup commands </text><text
class="breeze-help-r5" x="219.6" y="2045.2" textLength="1220"
clip-path="url(#breeze-help-line-83)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="bree [...]
-</text><text class="breeze-help-r5" x="0" y="2069.6" textLength="12.2"
clip-path="url(#breeze-help-line-84)">│</text><text class="breeze-help-r4"
x="24.4" y="2069.6" textLength="146.4"
clip-path="url(#breeze-help-line-84)">setup       </text><text
class="breeze-help-r1" x="195.2" y="2069.6" textLength="1244.4"
clip-path="url(#breeze-help-line-84)">Tools that developers can use to configure Breeze    
[...]
+</text><text class="breeze-help-r5" x="0" y="2045.2" textLength="24.4"
clip-path="url(#breeze-help-line-83)">╭─</text><text class="breeze-help-r5"
x="24.4" y="2045.2" textLength="207.4"
clip-path="url(#breeze-help-line-83)"> Issues commands </text><text
class="breeze-help-r5" x="231.8" y="2045.2" textLength="1207.8"
clip-path="url(#breeze-help-line-83)">───────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="br [...]
+</text><text class="breeze-help-r5" x="0" y="2069.6" textLength="12.2"
clip-path="url(#breeze-help-line-84)">│</text><text class="breeze-help-r4"
x="24.4" y="2069.6" textLength="231.8"
clip-path="url(#breeze-help-line-84)">issues             </text><text
class="breeze-help-r1" x="280.6" y="2069.6" textLength="1159"
clip-path="url(#breeze-help-line-84)">Tools for managing GitHub issues.   &
[...]
</text><text class="breeze-help-r5" x="0" y="2094" textLength="1464"
clip-path="url(#breeze-help-line-85)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="2094" textLength="12.2"
clip-path="url(#breeze-help-line-85)">
+</text><text class="breeze-help-r5" x="0" y="2118.4" textLength="24.4"
clip-path="url(#breeze-help-line-86)">╭─</text><text class="breeze-help-r5"
x="24.4" y="2118.4" textLength="195.2"
clip-path="url(#breeze-help-line-86)"> Setup commands </text><text
class="breeze-help-r5" x="219.6" y="2118.4" textLength="1220"
clip-path="url(#breeze-help-line-86)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="bree [...]
+</text><text class="breeze-help-r5" x="0" y="2142.8" textLength="12.2"
clip-path="url(#breeze-help-line-87)">│</text><text class="breeze-help-r4"
x="24.4" y="2142.8" textLength="146.4"
clip-path="url(#breeze-help-line-87)">setup       </text><text
class="breeze-help-r1" x="195.2" y="2142.8" textLength="1244.4"
clip-path="url(#breeze-help-line-87)">Tools that developers can use to configure Breeze    
[...]
+</text><text class="breeze-help-r5" x="0" y="2167.2" textLength="1464"
clip-path="url(#breeze-help-line-88)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="2167.2" textLength="12.2"
clip-path="url(#breeze-help-line-88)">
</text>
</g>
</g>
diff --git a/dev/breeze/doc/images/output_issues.svg
b/dev/breeze/doc/images/output_issues.svg
new file mode 100644
index 00000000000..6e42c770808
--- /dev/null
+++ b/dev/breeze/doc/images/output_issues.svg
@@ -0,0 +1,103 @@
+<svg class="rich-terminal" viewBox="0 0 1482 318.4"
xmlns="http://www.w3.org/2000/svg">
+ <!-- Generated with Rich https://www.textualize.io -->
+ <style>
+
+ @font-face {
+ font-family: "Fira Code";
+ src: local("FiraCode-Regular"),
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2")
format("woff2"),
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff")
format("woff");
+ font-style: normal;
+ font-weight: 400;
+ }
+ @font-face {
+ font-family: "Fira Code";
+ src: local("FiraCode-Bold"),
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2")
format("woff2"),
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff")
format("woff");
+ font-style: bold;
+ font-weight: 700;
+ }
+
+ .breeze-issues-matrix {
+ font-family: Fira Code, monospace;
+ font-size: 20px;
+ line-height: 24.4px;
+ font-variant-east-asian: full-width;
+ }
+
+ .breeze-issues-title {
+ font-size: 18px;
+ font-weight: bold;
+ font-family: arial;
+ }
+
+ .breeze-issues-r1 { fill: #c5c8c6 }
+.breeze-issues-r2 { fill: #d0b344 }
+.breeze-issues-r3 { fill: #c5c8c6;font-weight: bold }
+.breeze-issues-r4 { fill: #68a0b3;font-weight: bold }
+.breeze-issues-r5 { fill: #868887 }
+.breeze-issues-r6 { fill: #98a84b;font-weight: bold }
+ </style>
+
+ <defs>
+ <clipPath id="breeze-issues-clip-terminal">
+ <rect x="0" y="0" width="1463.0" height="267.4" />
+ </clipPath>
+ <clipPath id="breeze-issues-line-0">
+ <rect x="0" y="1.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-line-1">
+ <rect x="0" y="25.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-line-2">
+ <rect x="0" y="50.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-line-3">
+ <rect x="0" y="74.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-line-4">
+ <rect x="0" y="99.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-line-5">
+ <rect x="0" y="123.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-line-6">
+ <rect x="0" y="147.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-line-7">
+ <rect x="0" y="172.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-line-8">
+ <rect x="0" y="196.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-line-9">
+ <rect x="0" y="221.1" width="1464" height="24.65"/>
+ </clipPath>
+ </defs>
+
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="316.4" rx="8"/><text
class="breeze-issues-title" fill="#c5c8c6" text-anchor="middle" x="740"
y="27">Command: issues</text>
+ <g transform="translate(26,22)">
+ <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
+ <circle cx="22" cy="0" r="7" fill="#febc2e"/>
+ <circle cx="44" cy="0" r="7" fill="#28c840"/>
+ </g>
+
+ <g transform="translate(9, 41)"
clip-path="url(#breeze-issues-clip-terminal)">
+
+ <g class="breeze-issues-matrix">
+ <text class="breeze-issues-r1" x="1464" y="20" textLength="12.2"
clip-path="url(#breeze-issues-line-0)">
+</text><text class="breeze-issues-r2" x="12.2" y="44.4" textLength="73.2"
clip-path="url(#breeze-issues-line-1)">Usage:</text><text
class="breeze-issues-r3" x="97.6" y="44.4" textLength="158.6"
clip-path="url(#breeze-issues-line-1)">breeze issues</text><text
class="breeze-issues-r1" x="268.4" y="44.4" textLength="12.2"
clip-path="url(#breeze-issues-line-1)">[</text><text class="breeze-issues-r4"
x="280.6" y="44.4" textLength="85.4"
clip-path="url(#breeze-issues-line-1)">OPTIONS</tex [...]
+</text><text class="breeze-issues-r1" x="1464" y="68.8" textLength="12.2"
clip-path="url(#breeze-issues-line-2)">
+</text><text class="breeze-issues-r1" x="12.2" y="93.2" textLength="402.6"
clip-path="url(#breeze-issues-line-3)">Tools for managing GitHub issues.</text><text
class="breeze-issues-r1" x="1464" y="93.2" textLength="12.2"
clip-path="url(#breeze-issues-line-3)">
+</text><text class="breeze-issues-r1" x="1464" y="117.6" textLength="12.2"
clip-path="url(#breeze-issues-line-4)">
+</text><text class="breeze-issues-r5" x="0" y="142" textLength="24.4"
clip-path="url(#breeze-issues-line-5)">╭─</text><text class="breeze-issues-r5"
x="24.4" y="142" textLength="195.2"
clip-path="url(#breeze-issues-line-5)"> Common options </text><text
class="breeze-issues-r5" x="219.6" y="142" textLength="1220"
clip-path="url(#breeze-issues-line-5)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="bree [...]
+</text><text class="breeze-issues-r5" x="0" y="166.4" textLength="12.2"
clip-path="url(#breeze-issues-line-6)">│</text><text class="breeze-issues-r4"
x="24.4" y="166.4" textLength="73.2"
clip-path="url(#breeze-issues-line-6)">--help</text><text
class="breeze-issues-r6" x="122" y="166.4" textLength="24.4"
clip-path="url(#breeze-issues-line-6)">-h</text><text class="breeze-issues-r1"
x="170.8" y="166.4" textLength="329.4"
clip-path="url(#breeze-issues-line-6)">Show this message&# [...]
+</text><text class="breeze-issues-r5" x="0" y="190.8" textLength="1464"
clip-path="url(#breeze-issues-line-7)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-issues-r1" x="1464" y="190.8" textLength="12.2"
clip-path="url(#breeze-issues-line-7)">
+</text><text class="breeze-issues-r5" x="0" y="215.2" textLength="24.4"
clip-path="url(#breeze-issues-line-8)">╭─</text><text class="breeze-issues-r5"
x="24.4" y="215.2" textLength="207.4"
clip-path="url(#breeze-issues-line-8)"> Issues commands </text><text
class="breeze-issues-r5" x="231.8" y="215.2" textLength="1207.8"
clip-path="url(#breeze-issues-line-8)">───────────────────────────────────────────────────────────────────────────────────────────────────</text><text
cla [...]
+</text><text class="breeze-issues-r5" x="0" y="239.6" textLength="12.2"
clip-path="url(#breeze-issues-line-9)">│</text><text class="breeze-issues-r4"
x="24.4" y="239.6" textLength="231.8"
clip-path="url(#breeze-issues-line-9)">unassign           </text><text
class="breeze-issues-r1" x="280.6" y="239.6" textLength="1159"
clip-path="url(#breeze-issues-line-9)">Unassign non-collaborators from open issues.  
[...]
+</text><text class="breeze-issues-r5" x="0" y="264" textLength="1464"
clip-path="url(#breeze-issues-line-10)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-issues-r1" x="1464" y="264" textLength="12.2"
clip-path="url(#breeze-issues-line-10)">
+</text>
+ </g>
+ </g>
+</svg>
diff --git a/dev/breeze/doc/images/output_issues.txt
b/dev/breeze/doc/images/output_issues.txt
new file mode 100644
index 00000000000..da883723ae0
--- /dev/null
+++ b/dev/breeze/doc/images/output_issues.txt
@@ -0,0 +1 @@
+7c38e417044e5a65c0158611c74a4a73
diff --git a/dev/breeze/doc/images/output_issues_unassign.svg
b/dev/breeze/doc/images/output_issues_unassign.svg
new file mode 100644
index 00000000000..03e25e031c2
--- /dev/null
+++ b/dev/breeze/doc/images/output_issues_unassign.svg
@@ -0,0 +1,132 @@
+<svg class="rich-terminal" viewBox="0 0 1482 489.2"
xmlns="http://www.w3.org/2000/svg">
+ <!-- Generated with Rich https://www.textualize.io -->
+ <style>
+
+ @font-face {
+ font-family: "Fira Code";
+ src: local("FiraCode-Regular"),
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2")
format("woff2"),
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff")
format("woff");
+ font-style: normal;
+ font-weight: 400;
+ }
+ @font-face {
+ font-family: "Fira Code";
+ src: local("FiraCode-Bold"),
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2")
format("woff2"),
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff")
format("woff");
+ font-style: bold;
+ font-weight: 700;
+ }
+
+ .breeze-issues-unassign-matrix {
+ font-family: Fira Code, monospace;
+ font-size: 20px;
+ line-height: 24.4px;
+ font-variant-east-asian: full-width;
+ }
+
+ .breeze-issues-unassign-title {
+ font-size: 18px;
+ font-weight: bold;
+ font-family: arial;
+ }
+
+ .breeze-issues-unassign-r1 { fill: #c5c8c6 }
+.breeze-issues-unassign-r2 { fill: #d0b344 }
+.breeze-issues-unassign-r3 { fill: #c5c8c6;font-weight: bold }
+.breeze-issues-unassign-r4 { fill: #68a0b3;font-weight: bold }
+.breeze-issues-unassign-r5 { fill: #868887 }
+.breeze-issues-unassign-r6 { fill: #8d7b39 }
+.breeze-issues-unassign-r7 { fill: #98a84b;font-weight: bold }
+ </style>
+
+ <defs>
+ <clipPath id="breeze-issues-unassign-clip-terminal">
+ <rect x="0" y="0" width="1463.0" height="438.2" />
+ </clipPath>
+ <clipPath id="breeze-issues-unassign-line-0">
+ <rect x="0" y="1.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-1">
+ <rect x="0" y="25.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-2">
+ <rect x="0" y="50.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-3">
+ <rect x="0" y="74.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-4">
+ <rect x="0" y="99.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-5">
+ <rect x="0" y="123.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-6">
+ <rect x="0" y="147.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-7">
+ <rect x="0" y="172.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-8">
+ <rect x="0" y="196.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-9">
+ <rect x="0" y="221.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-10">
+ <rect x="0" y="245.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-11">
+ <rect x="0" y="269.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-12">
+ <rect x="0" y="294.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-13">
+ <rect x="0" y="318.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-14">
+ <rect x="0" y="343.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-15">
+ <rect x="0" y="367.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-issues-unassign-line-16">
+ <rect x="0" y="391.9" width="1464" height="24.65"/>
+ </clipPath>
+ </defs>
+
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="487.2" rx="8"/><text
class="breeze-issues-unassign-title" fill="#c5c8c6" text-anchor="middle"
x="740" y="27">Command: issues unassign</text>
+ <g transform="translate(26,22)">
+ <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
+ <circle cx="22" cy="0" r="7" fill="#febc2e"/>
+ <circle cx="44" cy="0" r="7" fill="#28c840"/>
+ </g>
+
+ <g transform="translate(9, 41)"
clip-path="url(#breeze-issues-unassign-clip-terminal)">
+
+ <g class="breeze-issues-unassign-matrix">
+ <text class="breeze-issues-unassign-r1" x="1464" y="20" textLength="12.2"
clip-path="url(#breeze-issues-unassign-line-0)">
+</text><text class="breeze-issues-unassign-r2" x="12.2" y="44.4"
textLength="73.2"
clip-path="url(#breeze-issues-unassign-line-1)">Usage:</text><text
class="breeze-issues-unassign-r3" x="97.6" y="44.4" textLength="268.4"
clip-path="url(#breeze-issues-unassign-line-1)">breeze issues unassign</text><text
class="breeze-issues-unassign-r1" x="378.2" y="44.4" textLength="12.2"
clip-path="url(#breeze-issues-unassign-line-1)">[</text><text
class="breeze-issues-unassign-r4" x="390.4" y [...]
+</text><text class="breeze-issues-unassign-r1" x="1464" y="68.8"
textLength="12.2" clip-path="url(#breeze-issues-unassign-line-2)">
+</text><text class="breeze-issues-unassign-r1" x="12.2" y="93.2"
textLength="536.8"
clip-path="url(#breeze-issues-unassign-line-3)">Unassign non-collaborators from open issues.</text><text
class="breeze-issues-unassign-r1" x="1464" y="93.2" textLength="12.2"
clip-path="url(#breeze-issues-unassign-line-3)">
+</text><text class="breeze-issues-unassign-r1" x="1464" y="117.6"
textLength="12.2" clip-path="url(#breeze-issues-unassign-line-4)">
+</text><text class="breeze-issues-unassign-r5" x="0" y="142" textLength="24.4"
clip-path="url(#breeze-issues-unassign-line-5)">╭─</text><text
class="breeze-issues-unassign-r5" x="24.4" y="142" textLength="231.8"
clip-path="url(#breeze-issues-unassign-line-5)"> GitHub parameters </text><text
class="breeze-issues-unassign-r5" x="256.2" y="142" textLength="1183.4"
clip-path="url(#breeze-issues-unassign-line-5)">─────────────────────────────────────────────────────────────────
[...]
+</text><text class="breeze-issues-unassign-r5" x="0" y="166.4"
textLength="12.2" clip-path="url(#breeze-issues-unassign-line-6)">│</text><text
class="breeze-issues-unassign-r4" x="24.4" y="166.4" textLength="231.8"
clip-path="url(#breeze-issues-unassign-line-6)">--github-token     </text><text
class="breeze-issues-unassign-r1" x="329.4" y="166.4" textLength="512.4"
clip-path="url(#breeze-issues-unassign-line-6)">The token used to authenticate&
[...]
+</text><text class="breeze-issues-unassign-r5" x="0" y="190.8"
textLength="12.2" clip-path="url(#breeze-issues-unassign-line-7)">│</text><text
class="breeze-issues-unassign-r4" x="24.4" y="190.8" textLength="231.8"
clip-path="url(#breeze-issues-unassign-line-7)">--github-repository</text><text
class="breeze-issues-unassign-r7" x="280.6" y="190.8" textLength="24.4"
clip-path="url(#breeze-issues-unassign-line-7)">-g</text><text
class="breeze-issues-unassign-r1" x="329.4" y="190.8" textLeng [...]
+</text><text class="breeze-issues-unassign-r5" x="0" y="215.2"
textLength="1464"
clip-path="url(#breeze-issues-unassign-line-8)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-issues-unassign-r1" x="1464" y="215.2" textLength="12.2"
clip-path="url(#breeze-issues-unassign-line-8)">
+</text><text class="breeze-issues-unassign-r5" x="0" y="239.6"
textLength="24.4"
clip-path="url(#breeze-issues-unassign-line-9)">╭─</text><text
class="breeze-issues-unassign-r5" x="24.4" y="239.6" textLength="219.6"
clip-path="url(#breeze-issues-unassign-line-9)"> Unassign options </text><text
class="breeze-issues-unassign-r5" x="244" y="239.6" textLength="1195.6"
clip-path="url(#breeze-issues-unassign-line-9)">──────────────────────────────────────────────────────────────
[...]
+</text><text class="breeze-issues-unassign-r5" x="0" y="264" textLength="12.2"
clip-path="url(#breeze-issues-unassign-line-10)">│</text><text
class="breeze-issues-unassign-r4" x="24.4" y="264" textLength="146.4"
clip-path="url(#breeze-issues-unassign-line-10)">--batch-size</text><text
class="breeze-issues-unassign-r1" x="195.2" y="264" textLength="695.4"
clip-path="url(#breeze-issues-unassign-line-10)">Number of flagged issues to accumulate before promp
[...]
+</text><text class="breeze-issues-unassign-r5" x="0" y="288.4"
textLength="1464"
clip-path="url(#breeze-issues-unassign-line-11)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-issues-unassign-r1" x="1464" y="288.4" textLength="12.2"
clip-path="url(#breeze-issues-unassign-line-11)">
+</text><text class="breeze-issues-unassign-r5" x="0" y="312.8"
textLength="24.4"
clip-path="url(#breeze-issues-unassign-line-12)">╭─</text><text
class="breeze-issues-unassign-r5" x="24.4" y="312.8" textLength="195.2"
clip-path="url(#breeze-issues-unassign-line-12)"> Common options </text><text
class="breeze-issues-unassign-r5" x="219.6" y="312.8" textLength="1220"
clip-path="url(#breeze-issues-unassign-line-12)">─────────────────────────────────────────────────────────────
[...]
+</text><text class="breeze-issues-unassign-r5" x="0" y="337.2"
textLength="12.2"
clip-path="url(#breeze-issues-unassign-line-13)">│</text><text
class="breeze-issues-unassign-r4" x="24.4" y="337.2" textLength="109.8"
clip-path="url(#breeze-issues-unassign-line-13)">--dry-run</text><text
class="breeze-issues-unassign-r7" x="158.6" y="337.2" textLength="24.4"
clip-path="url(#breeze-issues-unassign-line-13)">-D</text><text
class="breeze-issues-unassign-r1" x="207.4" y="337.2" textLength="719 [...]
+</text><text class="breeze-issues-unassign-r5" x="0" y="361.6"
textLength="12.2"
clip-path="url(#breeze-issues-unassign-line-14)">│</text><text
class="breeze-issues-unassign-r4" x="24.4" y="361.6" textLength="109.8"
clip-path="url(#breeze-issues-unassign-line-14)">--verbose</text><text
class="breeze-issues-unassign-r7" x="158.6" y="361.6" textLength="24.4"
clip-path="url(#breeze-issues-unassign-line-14)">-v</text><text
class="breeze-issues-unassign-r1" x="207.4" y="361.6" textLength="585 [...]
+</text><text class="breeze-issues-unassign-r5" x="0" y="386" textLength="12.2"
clip-path="url(#breeze-issues-unassign-line-15)">│</text><text
class="breeze-issues-unassign-r4" x="24.4" y="386" textLength="109.8"
clip-path="url(#breeze-issues-unassign-line-15)">--answer </text><text
class="breeze-issues-unassign-r7" x="158.6" y="386" textLength="24.4"
clip-path="url(#breeze-issues-unassign-line-15)">-a</text><text
class="breeze-issues-unassign-r1" x="207.4" y="386" textLength="329.4" [...]
+</text><text class="breeze-issues-unassign-r5" x="0" y="410.4"
textLength="12.2"
clip-path="url(#breeze-issues-unassign-line-16)">│</text><text
class="breeze-issues-unassign-r4" x="24.4" y="410.4" textLength="109.8"
clip-path="url(#breeze-issues-unassign-line-16)">--help   </text><text
class="breeze-issues-unassign-r7" x="158.6" y="410.4" textLength="24.4"
clip-path="url(#breeze-issues-unassign-line-16)">-h</text><text
class="breeze-issues-unassign-r1" x="207.4" y="410.4" [...]
+</text><text class="breeze-issues-unassign-r5" x="0" y="434.8"
textLength="1464"
clip-path="url(#breeze-issues-unassign-line-17)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-issues-unassign-r1" x="1464" y="434.8" textLength="12.2"
clip-path="url(#breeze-issues-unassign-line-17)">
+</text>
+ </g>
+ </g>
+</svg>
diff --git a/dev/breeze/doc/images/output_issues_unassign.txt
b/dev/breeze/doc/images/output_issues_unassign.txt
new file mode 100644
index 00000000000..4afb5f5c856
--- /dev/null
+++ b/dev/breeze/doc/images/output_issues_unassign.txt
@@ -0,0 +1 @@
+03b6c243f4fbc43abcdfc4e7f2dca76c
diff --git a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
index 11f9f680dd3..ff5d3ffb122 100644
--- a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
+++ b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
@@ -196,11 +196,11 @@
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="190.8" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-7)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="190.8"
textLength="1134.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-7)">ci-image:build | ci-image:export-mount-cache | ci-image:import-mount-cache | ci-image:load | </text><text
class="breeze [...]
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="215.2" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-8)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="215.2"
textLength="1281"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-8)">ci-image:pull | ci-image:save | ci-image:verify | ci:fix-ownership | ci:free-space | ci:get-workflow-info</text
[...]
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="239.6" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-9)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="239.6"
textLength="1281"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-9)">| ci:resource-check | ci:selective-check | ci:set-milestone | ci:upgrade | cleanup | doctor | do
[...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="264"
textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="264"
textLength="1232.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">| generate-migration-file | k8s | k8s:build-k8s-image | k8s:configure-cluster | k8s:create-cluster | </tex
[...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="288.4" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="288.4"
textLength="1195.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">k8s:delete-cluster | k8s:deploy-airflow | k8s:dev | k8s:k9s | k8s:logs | k8s:run-complete-tests | 
[...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="312.8" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="312.8"
textLength="1281"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">k8s:setup-env | k8s:shell | k8s:status | k8s:tests | k8s:upload-k8s-image | prod-image | prod-image
[...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="337.2" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="337.2"
textLength="1183.4"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">| prod-image:load | prod-image:pull | prod-image:save | prod-image:verify | release-management | </tex
[...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="361.6" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="361.6"
textLength="1000.4"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">release-management:add-back-references | release-management:check-release-files | </text><text
class="breeze-setup-check-all-params-in-gr [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="264"
textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="264"
textLength="1281"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">| generate-migration-file | issues | issues:unassign | k8s | k8s:build-k8s-image | k8s:configure-cluster
[...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="288.4" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="288.4"
textLength="1171.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">| k8s:create-cluster | k8s:delete-cluster | k8s:deploy-airflow | k8s:dev | k8s:k9s | k8s:logs |&#
[...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="312.8" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="312.8"
textLength="1232.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">k8s:run-complete-tests | k8s:setup-env | k8s:shell | k8s:status | k8s:tests | k8s:upload-k8s-image |&#
[...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="337.2" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="337.2"
textLength="1281"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">prod-image | prod-image:build | prod-image:load | prod-image:pull | prod-image:save | prod-image:verify 
[...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="361.6" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="361.6"
textLength="1256.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">release-management | release-management:add-back-references | release-management:check-release-files | </text><text
class="bree [...]
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="386"
textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="386"
textLength="1183.4"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">release-management:clean-old-provider-artifacts | release-management:constraints-version-check | </text><text
class="breeze-setup-check-all-p [...]
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="410.4" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="410.4"
textLength="1012.6"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">release-management:create-minor-branch | release-management:generate-constraints | </text><text
class="breeze-setup-check-all-params-in-g [...]
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0"
y="434.8" textLength="12.2"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">│</text><text
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="434.8"
textLength="1268.8"
clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">release-management:generate-issue-content-core | release-management:generate-issue-content-helm-chart | </text><text
class="breeze-setup- [...]
diff --git a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
index d50a5e8b320..3821e7107ab 100644
--- a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
+++ b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
@@ -1 +1 @@
-3bd93619bb2ae3508dd86849f3fbe4b1
+167f3cf881f8043affa52ef3819b3813
diff --git a/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
b/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
index 91a13c44ed6..a744bd3efb3 100644
--- a/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
+++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
@@ -215,17 +215,17 @@
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="215.2"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-8)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="215.2"
textLength="1134.6"
clip-path="url(#breeze-setup-regenerate-command-images-line-8)">ci-image:build | ci-image:export-mount-cache | ci-image:import-mount-cache | ci-image:load | </text><text
class="breeze-set [...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="239.6"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-9)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="239.6"
textLength="1037"
clip-path="url(#breeze-setup-regenerate-command-images-line-9)">ci-image:pull | ci-image:save | ci-image:verify | ci:fix-ownership | ci:free-space | </text><text
class="breeze-set [...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="264"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-10)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="264"
textLength="1171.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-10)">ci:get-workflow-info | ci:resource-check | ci:selective-check | ci:set-milestone | ci:upgrade | </text><text
class= [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="288.4"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-11)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="288.4"
textLength="1061.4"
clip-path="url(#breeze-setup-regenerate-command-images-line-11)">cleanup | doctor | down | exec | generate-migration-file | k8s | k8s:build-k8s-image | </te
[...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="312.8"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-12)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="312.8"
textLength="1183.4"
clip-path="url(#breeze-setup-regenerate-command-images-line-12)">k8s:configure-cluster | k8s:create-cluster | k8s:delete-cluster | k8s:deploy-airflow | k8s:dev | </text><text
c [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="337.2"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-13)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="337.2"
textLength="1207.8"
clip-path="url(#breeze-setup-regenerate-command-images-line-13)">k8s:k9s | k8s:logs | k8s:run-complete-tests | k8s:setup-env | k8s:shell | k8s:status | k8s:tests 
[...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="361.6"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-14)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="361.6"
textLength="1110.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-14)">k8s:upload-k8s-image | prod-image | prod-image:build | prod-image:load | prod-image:pull | </text><text
class=" [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="386"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-15)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="386"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-15)">prod-image:save | prod-image:verify | release-management | release-management:add-back-references | </text><text
class="breeze- [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="410.4"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-16)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="410.4"
textLength="1110.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-16)">release-management:check-release-files | release-management:clean-old-provider-artifacts | </text><text
class="breeze-setup-regenerate-comman [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="434.8"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-17)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="434.8"
textLength="1073.6"
clip-path="url(#breeze-setup-regenerate-command-images-line-17)">release-management:constraints-version-check | release-management:create-minor-branch | </text><text
class="breeze-setup-regenerate-command-i [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="459.2"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-18)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="459.2"
textLength="1110.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-18)">release-management:generate-constraints | release-management:generate-issue-content-core | </text><text
class="breeze-setup-regenerate-comman [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="483.6"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-19)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="483.6"
textLength="671"
clip-path="url(#breeze-setup-regenerate-command-images-line-19)">release-management:generate-issue-content-helm-chart | </text><text
class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="483.6"
textLength="12. [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="508"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-20)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="508"
textLength="1244.4"
clip-path="url(#breeze-setup-regenerate-command-images-line-20)">release-management:generate-issue-content-providers | release-management:generate-providers-metadata |</text><text
class="breeze-setup-regenerate-comm [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="532.4"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="532.4"
textLength="1110.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-21)">release-management:install-provider-distributions | release-management:merge-prod-images | </text><text
class="breeze-setup-regenerate-comman [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="288.4"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-11)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="288.4"
textLength="1122.4"
clip-path="url(#breeze-setup-regenerate-command-images-line-11)">cleanup | doctor | down | exec | generate-migration-file | issues | issues:unassign | k8s&#
[...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="312.8"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-12)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="312.8"
textLength="1073.6"
clip-path="url(#breeze-setup-regenerate-command-images-line-12)">k8s:build-k8s-image | k8s:configure-cluster | k8s:create-cluster | k8s:delete-cluster | </text><text
class="breeze-setup- [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="337.2"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-13)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="337.2"
textLength="1244.4"
clip-path="url(#breeze-setup-regenerate-command-images-line-13)">k8s:deploy-airflow | k8s:dev | k8s:k9s | k8s:logs | k8s:run-complete-tests | k8s:setup-env | k8s:shel
[...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="361.6"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-14)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="361.6"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-14)">| k8s:status | k8s:tests | k8s:upload-k8s-image | prod-image | prod-image:build | prod-image:load |
[...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="386"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-15)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="386"
textLength="939.4"
clip-path="url(#breeze-setup-regenerate-command-images-line-15)">prod-image:pull | prod-image:save | prod-image:verify | release-management | </text><text
class="breeze-setup-regenerate-comma [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="410.4"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-16)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="410.4"
textLength="1000.4"
clip-path="url(#breeze-setup-regenerate-command-images-line-16)">release-management:add-back-references | release-management:check-release-files | </text><text
class="breeze-setup-regenerate-command-images- [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="434.8"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-17)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="434.8"
textLength="1183.4"
clip-path="url(#breeze-setup-regenerate-command-images-line-17)">release-management:clean-old-provider-artifacts | release-management:constraints-version-check | </text><text
class="breeze-setup-regenerate- [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="459.2"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-18)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="459.2"
textLength="1012.6"
clip-path="url(#breeze-setup-regenerate-command-images-line-18)">release-management:create-minor-branch | release-management:generate-constraints | </text><text
class="breeze-setup-regenerate-command-images [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="483.6"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-19)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="483.6"
textLength="1244.4"
clip-path="url(#breeze-setup-regenerate-command-images-line-19)">release-management:generate-issue-content-core | release-management:generate-issue-content-helm-chart </text><text
class="breeze-setup-regenerate- [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="508"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-20)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="508"
textLength="1244.4"
clip-path="url(#breeze-setup-regenerate-command-images-line-20)">| release-management:generate-issue-content-providers | release-management:generate-providers-metadata</text><text
class="breeze-setup-regenerate-comm [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="532.4"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="532.4"
textLength="1134.6"
clip-path="url(#breeze-setup-regenerate-command-images-line-21)">| release-management:install-provider-distributions | release-management:merge-prod-images | </text><text
class="breeze-setup-regenerate [...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="556.8"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-22)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="556.8"
textLength="671"
clip-path="url(#breeze-setup-regenerate-command-images-line-22)">release-management:prepare-airflow-ctl-distributions | </text><text
class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="556.8"
textLength="12. [...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="581.2"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-23)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="581.2"
textLength="1207.8"
clip-path="url(#breeze-setup-regenerate-command-images-line-23)">release-management:prepare-airflow-distributions | release-management:prepare-helm-chart-package | </text><text
class="breeze-setup-regenerat [...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="605.6"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="605.6"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-24)">release-management:prepare-helm-chart-tarball | release-management:prepare-provider-distributions | </text><text
class="breeze-setup-regenerate [...]
diff --git a/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
b/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
index 98088450668..79a72330784 100644
--- a/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
+++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
@@ -1 +1 @@
-6b4f955fd531841d67223b6c86f69c77
+f1a78722cc5f42f258f90a11005d5900
diff --git a/dev/breeze/src/airflow_breeze/breeze.py
b/dev/breeze/src/airflow_breeze/breeze.py
index aad4d64fe17..9ccdb30cc7e 100755
--- a/dev/breeze/src/airflow_breeze/breeze.py
+++ b/dev/breeze/src/airflow_breeze/breeze.py
@@ -33,6 +33,7 @@ create_directories_and_files()
from airflow_breeze.commands import developer_commands # noqa: I001, E402,
F401
from airflow_breeze.commands.ci_commands import ci_group # noqa: E402
from airflow_breeze.commands.ci_image_commands import ci_image_group # noqa:
E402
+from airflow_breeze.commands.issues_commands import issues_group # noqa: E402
from airflow_breeze.commands.kubernetes_commands import kubernetes_group #
noqa: E402
from airflow_breeze.commands.production_image_commands import prod_image_group
# noqa: E402
from airflow_breeze.commands.minor_release_command import
create_minor_version_branch # noqa: E402, F401
@@ -53,6 +54,7 @@ main.add_command(setup_group)
main.add_command(release_management_group)
main.add_command(sbom_group)
main.add_command(ui_group)
+main.add_command(issues_group)
main.add_command(workflow_run_group)
if __name__ == "__main__":
diff --git a/dev/breeze/src/airflow_breeze/commands/issues_commands.py
b/dev/breeze/src/airflow_breeze/commands/issues_commands.py
new file mode 100644
index 00000000000..98669534030
--- /dev/null
+++ b/dev/breeze/src/airflow_breeze/commands/issues_commands.py
@@ -0,0 +1,174 @@
+# 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.
+from __future__ import annotations
+
+import sys
+
+import click
+from rich.table import Table
+
+from airflow_breeze.commands.common_options import (
+ option_answer,
+ option_dry_run,
+ option_github_repository,
+ option_github_token,
+ option_verbose,
+)
+from airflow_breeze.utils.click_utils import BreezeGroup
+from airflow_breeze.utils.confirm import Answer, user_confirm
+from airflow_breeze.utils.console import get_console
+from airflow_breeze.utils.run_utils import run_command
+from airflow_breeze.utils.shared_options import get_dry_run
+
+
[email protected](cls=BreezeGroup, name="issues", help="Tools for managing GitHub
issues.")
+def issues_group():
+ pass
+
+
+def _resolve_github_token(github_token: str | None) -> str | None:
+ """Resolve GitHub token from option, environment, or gh CLI."""
+ if github_token:
+ return github_token
+ gh_token_result = run_command(
+ ["gh", "auth", "token"],
+ capture_output=True,
+ text=True,
+ check=False,
+ dry_run_override=False,
+ )
+ if gh_token_result.returncode == 0:
+ return gh_token_result.stdout.strip()
+ return None
+
+
+def _get_collaborator_logins(repo) -> set[str]:
+ """Fetch all collaborator logins for the repository."""
+ get_console().print("[info]Fetching repository collaborators...[/]")
+ collaborators = {c.login for c in repo.get_collaborators()}
+ get_console().print(f"[info]Found {len(collaborators)} collaborators.[/]")
+ return collaborators
+
+
+def _process_batch(
+ batch: list[tuple],
+ dry_run: bool,
+) -> int:
+ """Display a batch of proposed unassignments and handle confirmation.
+
+ Returns the number of issues actually unassigned.
+ """
+ if not batch:
+ return 0
+
+ table = Table(title="Proposed unassignments")
+ table.add_column("Issue #", style="cyan", justify="right")
+ table.add_column("Title", style="white")
+ table.add_column("Non-collaborator assignees", style="red")
+ for issue, non_collab_logins in batch:
+ table.add_row(
+ str(issue.number),
+ issue.title[:80],
+ ", ".join(sorted(non_collab_logins)),
+ )
+ get_console().print(table)
+
+ if dry_run:
+ get_console().print("[warning]Dry run — skipping actual
unassignment.[/]")
+ return 0
+
+ answer = user_confirm("Unassign the above non-collaborators?")
+ if answer == Answer.QUIT:
+ get_console().print("[warning]Quitting.[/]")
+ sys.exit(0)
+ if answer == Answer.NO:
+ get_console().print("[info]Skipping this batch.[/]")
+ return 0
+
+ unassigned_count = 0
+ for issue, non_collab_logins in batch:
+ for login in non_collab_logins:
+ get_console().print(f" Removing [red]{login}[/] from issue
#{issue.number}")
+ issue.remove_from_assignees(login)
+ unassigned_count += 1
+ return unassigned_count
+
+
+@issues_group.command(name="unassign", help="Unassign non-collaborators from
open issues.")
+@option_github_token
+@option_github_repository
[email protected](
+ "--batch-size",
+ type=int,
+ default=100,
+ show_default=True,
+ help="Number of flagged issues to accumulate before prompting.",
+)
+@option_dry_run
+@option_verbose
+@option_answer
+def unassign(
+ github_token: str | None,
+ github_repository: str,
+ batch_size: int,
+):
+ from github import Github
+
+ token = _resolve_github_token(github_token)
+ if not token:
+ get_console().print(
+ "[error]GitHub token not found. Provide --github-token, "
+ "set GITHUB_TOKEN, or authenticate with `gh auth login`.[/]"
+ )
+ sys.exit(1)
+
+ g = Github(token)
+ repo = g.get_repo(github_repository)
+ collaborators = _get_collaborator_logins(repo)
+
+ dry_run = get_dry_run()
+
+ batch: list[tuple] = []
+ total_issues_scanned = 0
+ total_flagged = 0
+ total_unassigned = 0
+
+ get_console().print(f"[info]Scanning open issues in
{github_repository}...[/]")
+
+ for issue in repo.get_issues(state="open"):
+ total_issues_scanned += 1
+ if not issue.assignees:
+ continue
+ non_collab = {a.login for a in issue.assignees if a.login not in
collaborators}
+ if not non_collab:
+ continue
+
+ batch.append((issue, non_collab))
+ total_flagged += 1
+
+ if len(batch) >= batch_size:
+ total_unassigned += _process_batch(batch, dry_run)
+ batch = []
+
+ # Process remaining batch
+ total_unassigned += _process_batch(batch, dry_run)
+
+ get_console().print()
+ get_console().print("[success]Done![/]")
+ get_console().print(f" Issues scanned: {total_issues_scanned}")
+ get_console().print(f" Issues flagged: {total_flagged}")
+ get_console().print(f" Assignees removed: {total_unassigned}")
diff --git a/dev/breeze/src/airflow_breeze/commands/issues_commands_config.py
b/dev/breeze/src/airflow_breeze/commands/issues_commands_config.py
new file mode 100644
index 00000000000..d674c364596
--- /dev/null
+++ b/dev/breeze/src/airflow_breeze/commands/issues_commands_config.py
@@ -0,0 +1,35 @@
+# 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.
+from __future__ import annotations
+
+ISSUES_COMMANDS: dict[str, str | list[str]] = {
+ "name": "Issues commands",
+ "commands": ["unassign"],
+}
+
+ISSUES_PARAMETERS: dict[str, list[dict[str, str | list[str]]]] = {
+ "breeze issues unassign": [
+ {
+ "name": "GitHub parameters",
+ "options": ["--github-token", "--github-repository"],
+ },
+ {
+ "name": "Unassign options",
+ "options": ["--batch-size"],
+ },
+ ],
+}
diff --git a/dev/breeze/src/airflow_breeze/configure_rich_click.py
b/dev/breeze/src/airflow_breeze/configure_rich_click.py
index 9d0e47e3f95..41308401567 100644
--- a/dev/breeze/src/airflow_breeze/configure_rich_click.py
+++ b/dev/breeze/src/airflow_breeze/configure_rich_click.py
@@ -16,6 +16,7 @@
# under the License.
from __future__ import annotations
+from airflow_breeze.commands.issues_commands_config import ISSUES_COMMANDS,
ISSUES_PARAMETERS
from airflow_breeze.commands.sbom_commands_config import SBOM_COMMANDS,
SBOM_PARAMETERS
from airflow_breeze.commands.ui_commands_config import UI_COMMANDS,
UI_PARAMETERS
from airflow_breeze.commands.workflow_commands_config import
WORKFLOW_RUN_COMMANDS, WORKFLOW_RUN_PARAMETERS
@@ -82,6 +83,7 @@ else:
**SBOM_PARAMETERS,
**WORKFLOW_RUN_PARAMETERS,
**UI_PARAMETERS,
+ **ISSUES_PARAMETERS,
}
click.rich_click.COMMAND_GROUPS = {
"breeze": [
@@ -106,6 +108,10 @@ else:
"name": "UI commands",
"commands": ["ui"],
},
+ {
+ "name": "Issues commands",
+ "commands": ["issues"],
+ },
{
"name": "Setup commands",
"commands": ["setup"],
@@ -132,4 +138,5 @@ else:
"breeze ci": [CI_COMMANDS],
"breeze workflow-run": [WORKFLOW_RUN_COMMANDS],
"breeze ui": [UI_COMMANDS],
+ "breeze issues": [ISSUES_COMMANDS],
}