diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/dependency_updater/tools/toolbox.py | 76 |
1 files changed, 46 insertions, 30 deletions
diff --git a/util/dependency_updater/tools/toolbox.py b/util/dependency_updater/tools/toolbox.py index 34bb783..3e3ba2d 100644 --- a/util/dependency_updater/tools/toolbox.py +++ b/util/dependency_updater/tools/toolbox.py @@ -574,33 +574,25 @@ def stage_update(config: Config, repo: Repo) -> bool: """Perform a 'safe stage' on the update by attempting to stage all updates together, but cancel the attempt and unstage if a conflict is generated during staging.""" - if repo.proposal.gerrit_status in ["STAGED", "INTEGRATING", "MERGED"]: - print(f"{repo.id} update is already {repo.proposal.gerrit_status}. Skipping.") - return False - if repo.proposal.change_id not in repo.to_stage: - repo.to_stage.append(repo.proposal.change_id) - if config.args.sweep_changes: - repo.to_stage = list(set(repo.to_stage).union(gather_costaging_changes(config, repo))) - print(f"Preparing to stage changes for {repo.id}: {repo.to_stage}") - error = False - # Create a list of links for each change staged. - gerrit_link_self = " ".join(gerrit_link_maker(config, repo)) - costaging_changes_links = "\n" + "\n".join( - [" ".join(gerrit_link_maker(config, repo, change_override=make_full_id(repo, change_id))) for change_id in repo.to_stage if change_id != repo.proposal.change_id]) - for change_id in repo.to_stage: + + def _do_staging(change_id, is_retry=False) -> bool: + "Stage a change or add failed stage to the retry list if it hasn't been." if repo.proposal.change_id == change_id: if len(repo.to_stage) > 1: message = f"Staging this update with other changes:\n{costaging_changes_links}" else: message = "" else: - message = ("Staging this change automatically with the dependency update for this" - f" module:\n" - f"{gerrit_link_self}") - if stage_change(config, change_id, message): + message = "Staging this change automatically with the dependency update for this" \ + f" module:\n" \ + f"{gerrit_link_self}" + stage_success, retry_stage = stage_change(config, change_id, message, is_retry) + if stage_success: print(f"{repo.id}: Staged " f"{'submodule update' if repo.proposal.change_id == change_id else 'related change'}" f" {change_id}") + elif retry_stage: + needs_staging_retry.append(change_id) else: if repo.proposal.change_id == change_id: post_gerrit_comment(config, change_id, @@ -612,7 +604,26 @@ def stage_update(config: Config, repo: Repo) -> bool: " It probably created a merge conflict." " Please review.\n" f"See: {gerrit_link_self}.") - error = True + return True + + if repo.proposal.gerrit_status in ["STAGED", "INTEGRATING", "MERGED"]: + print(f"{repo.id} update is already {repo.proposal.gerrit_status}. Skipping.") + return False + if repo.proposal.change_id not in repo.to_stage: + repo.to_stage.append(repo.proposal.change_id) + if config.args.sweep_changes: + repo.to_stage = list(set(repo.to_stage).union(gather_costaging_changes(config, repo))) + print(f"Preparing to stage changes for {repo.id}: {repo.to_stage}") + error = False + # Create a list of links for each change staged. + gerrit_link_self = " ".join(gerrit_link_maker(config, repo)) + costaging_changes_links = "\n" + "\n".join( + [" ".join(gerrit_link_maker(config, repo, change_override=make_full_id(repo, change_id))) for change_id in repo.to_stage if change_id != repo.proposal.change_id]) + needs_staging_retry = list() + for change_id in repo.to_stage: + _do_staging(change_id, False) + for change_id in needs_staging_retry: + error = _do_staging(change_id, True) if error: print(f"failed to stage {repo.id}: {repo.to_stage}\n") config.teams_connector.send_teams_webhook_failed_stage(repo) @@ -625,11 +636,15 @@ def stage_update(config: Config, repo: Repo) -> bool: return True -def stage_change(config: Config, change_id: str, comment: str = "") -> bool: - """Stage a change in gerrit. Requires the QtStage permission.""" +def stage_change(config: Config, change_id: str, comment: str = "", + is_retry = False) -> tuple[bool, bool]: + """Stage a change in gerrit. Requires the QtStage permission. + + Return a tuple of bools: Success, Retry + """ if config.args.simulate: print(f"SIM: Simulated successful staging of {change_id}") - return True + return True, False change = config.datasources.gerrit_client.changes.get(change_id) # Sleep for one second to give gerrit a second to cool off. If the change was just # created, sometimes gerrit can be slow to release the lock, resulting in a 409 response code. @@ -638,16 +653,17 @@ def stage_change(config: Config, change_id: str, comment: str = "") -> bool: change.stage() if comment: post_gerrit_comment(config, change_id, comment) - except GerritExceptions.NotAllowedError: + except (GerritExceptions.NotAllowedError, GerritExceptions.AuthError): print(f"WARN: Unable to stage {change_id} automatically.\n" f"Either you do not have permissions to stage this change, or the branch is closed.") - return False + return False, False except GerritExceptions.ConflictError: - print(f"ERROR: Unable to stage {change_id} automatically.\n" - "The change contains conflicts and cannot be staged. Please verify that no other\n" - "changes currently staged conflict with this update.") - return False - return True + print(f"ERROR: Unable to stage {change_id} automatically.") + if is_retry: + print("The change creates a conflict and cannot be staged. Please verify that no" + "other changes currently staged conflict with this update.") + return False, not is_retry + return True, False def unstage_change(config: Config, change_id: str) -> bool: @@ -1179,7 +1195,7 @@ def approve_change_id(change: GerritChange, repo_name: str) -> bool: } }) return True - except GerritExceptions.NotAllowedError: + except (GerritExceptions.NotAllowedError, GerritExceptions.AuthError): print(f"WARN: You do not have self-approval rights to auto-approve in {repo_name}\n" f"You must have change ID {change.change_id} approved and" f" manually stage it.") |