| # Copyright 2024 The Pigweed Authors |
| # |
| # Licensed 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 |
| # |
| # https://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. |
| """Abandon old changes owned by the current service account.""" |
| |
| from __future__ import annotations |
| |
| from typing import TYPE_CHECKING |
| |
| from recipe_engine import recipe_api |
| |
| if TYPE_CHECKING: # pragma: no cover |
| from recipe_engine import config_types, engine_types |
| |
| |
| class AbandonOldChangesApi(recipe_api.RecipeApi): |
| """Abandon old changes owned by the current service account.""" |
| |
| def __call__( |
| self, |
| *, |
| host: str, |
| age_days: int = 30, |
| continue_on_failure: bool = True, |
| max_to_abandon: int = 10, |
| ): |
| with self.m.step.nest('abandon old changes'): |
| try: |
| self._abandon_old_changes( |
| host=self.m.gerrit.host_from_remote_url(host), |
| age_days=age_days, |
| max_to_abandon=max_to_abandon, |
| ) |
| self.m.step.empty('success') |
| |
| except self.m.step.StepFailure: |
| self.m.step.empty('failure') |
| if not continue_on_failure: |
| raise # pragma: no cover |
| |
| def _abandon_old_changes( |
| self, |
| *, |
| host: str, |
| age_days: int, |
| max_to_abandon: int, |
| ): |
| query_string = ( |
| f'is:open ' |
| f'owner:{self.m.buildbucket.build.infra.swarming.task_service_account} ' |
| f'age:{age_days}d ' |
| ) |
| |
| changes = self.m.gerrit.change_query( |
| name='get old changes', |
| query_string=query_string, |
| host=host, |
| max_attempts=1, |
| timeout=30, |
| test_data=self.m.json.test_api.output( |
| [ |
| {'_number': 1001}, |
| {'_number': 1002}, |
| ], |
| ), |
| ).json.output |
| |
| futures = [] |
| for change in changes[:max_to_abandon]: |
| self.m.futures.spawn( |
| self.m.gerrit.abandon, |
| f'abandon {change["_number"]}', |
| change['_number'], |
| 'Abandoning orphaned roll change.', |
| ) |
| |
| self.m.futures.wait(futures) |