@@ -294,7 +294,7 @@ class StackEntry:
294294 _pr : str | None = None
295295 _base : str | None = None
296296 _head : str | None = None
297- need_update : bool = False
297+ is_tmp_draft : bool = False
298298
299299 @property
300300 def pr (self ) -> str :
@@ -783,7 +783,7 @@ def toc_entry(se: StackEntry) -> str:
783783 return f"Stacked PRs:\n { '' .join (entries )} \n "
784784
785785
786- def get_current_pr_body (e : StackEntry ) -> str :
786+ def get_pr_body (e : StackEntry ) -> str :
787787 out = get_command_output (
788788 ["gh" , "pr" , "view" , e .pr , "--json" , "body" ],
789789 )
@@ -815,7 +815,7 @@ def add_cross_links(st: list[StackEntry], *, keep_body: bool, verbose: bool) ->
815815
816816 if keep_body :
817817 # Keep current body of the PR after the cross links component
818- current_pr_body = get_current_pr_body (e )
818+ current_pr_body = get_pr_body (e )
819819 body_content = current_pr_body .split (CROSS_LINKS_DELIMETER , 1 )[- 1 ].lstrip ()
820820
821821 pr_body = [* header , body_content ]
@@ -831,6 +831,13 @@ def add_cross_links(st: list[StackEntry], *, keep_body: bool, verbose: bool) ->
831831 raise RuntimeError
832832
833833
834+ def is_draft_pr (e : StackEntry ) -> bool :
835+ out = get_command_output (
836+ ["gh" , "pr" , "view" , e .pr , "--json" , "isDraft" ],
837+ )
838+ return json .loads (out )["isDraft" ]
839+
840+
834841# Temporarily set base branches of existing PRs to the bottom of the stack.
835842# This needs to be done to avoid PRs getting closed when commits are
836843# rearranged.
@@ -852,14 +859,21 @@ def add_cross_links(st: list[StackEntry], *, keep_body: bool, verbose: bool) ->
852859# stack/2. If we push stack/1, then PR #2 gets automatically closed, since its
853860# head branch will contain all the commits from its base branch.
854861#
855- # To avoid this, we temporarily set all base branches to point to 'main' - once
856- # all the branches are pushed we can set the actual base branches.
862+ # To avoid this, we temporarily set all base branches to point to 'main'. To ensure
863+ # we don't accidentally notify reviewers in this transient state (where the PRs are
864+ # pointing to 'main'), we mark the PRs as draft - once all the branches are pushed
865+ # we can set the actual base branches and undraft the PRs.
857866def reset_remote_base_branches (
858867 st : list [StackEntry ], target : str , * , verbose : bool
859868) -> None :
860869 log (h ("Resetting remote base branches" ), level = 2 )
861870
862871 for e in filter (lambda e : e .has_pr (), st ):
872+ # We need to check if the PR is already draft, otherwise we would
873+ # unintentionally undo the draft status later.
874+ if not is_draft_pr (e ):
875+ run_shell_command (["gh" , "pr" , "ready" , e .pr , "--undo" ], quiet = not verbose )
876+ e .is_tmp_draft = True
863877 run_shell_command (["gh" , "pr" , "edit" , e .pr , "-B" , target ], quiet = not verbose )
864878
865879
@@ -1117,6 +1131,12 @@ def command_submit(
11171131 log (h ("Adding cross-links to PRs" ), level = 1 )
11181132 add_cross_links (st , keep_body = keep_body , verbose = args .verbose )
11191133
1134+ # Undraft the PRs if they were marked as temporary drafts.
1135+ for e in st :
1136+ if e .is_tmp_draft :
1137+ run_shell_command (["gh" , "pr" , "ready" , e .pr ], quiet = not args .verbose )
1138+ e .is_tmp_draft = False
1139+
11201140 if need_to_rebase_current :
11211141 log (h (f"Rebasing the original branch '{ current_branch } '" ), level = 2 )
11221142 run_shell_command (
0 commit comments