| # Copyright 2022 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. |
| """Recipe module to post comments on Gerrit CLs. |
| |
| This module provides a `maybe_post` method that can be used to post a comment |
| on a Gerrit CL associated with the current build. The behavior of the comment |
| posting (e.g., whether to comment on success, failure, or always) can be |
| configured through an `Options` proto message. It also allows specifying |
| a list of allowed Gerrit hosts to prevent accidental commenting on unintended |
| repositories. |
| """ |
| |
| from __future__ import annotations |
| |
| from recipe_engine import recipe_api |
| |
| from PB.recipe_modules.pigweed.gerrit_comment.options import ( |
| CommentBehavior, |
| Options, |
| ) |
| |
| from RECIPE_MODULES.recipe_engine.defer import api as defer_api |
| |
| |
| class GerritCommentApi(recipe_api.RecipeApi): |
| def maybe_post(self, options: Options, result: defer_api.DeferredResult): |
| """Maybe post a comment on a Gerrit CL. |
| |
| Post a comment on the CL associated with this build (or not, depending |
| on the options). |
| |
| Args: |
| options: Options. |
| result: DeferredResult object. |
| """ |
| if options.comment_behavior == CommentBehavior.COMMENT_UNSPECIFIED: |
| return |
| |
| with self.m.step.nest('maybe post') as pres: |
| if ( |
| options.comment_behavior == CommentBehavior.COMMENT_ON_FAILURE |
| and result.is_ok() |
| ): |
| pres.step_summary_text = ( |
| 'No-op: Comments requested only on failures, ' |
| 'but the step passed.' |
| ) |
| return |
| |
| changes = self.m.buildbucket.build.input.gerrit_changes |
| if len(changes) == 0: |
| pres.step_summary_text = ( |
| 'No-op: no Gerrit change to comment on ' |
| '(expected for CI builds).' |
| ) |
| return |
| |
| change = changes[-1] |
| if ( |
| self.m.gerrit.normalize_host(change.host) |
| not in options.allowed_gerrit_hosts |
| ): |
| pres.step_summary_text = ( |
| 'No-op: ' |
| "the change is on a host that's not explicitly allowlisted." |
| ) |
| return |
| |
| # If we made it here, we should post a comment on the CL. |
| pres.step_summary_text = 'Posting CL comment' |
| if result.is_ok(): |
| status = 'OK' |
| else: |
| try: |
| result.result() |
| assert False, "shouldn't get here" # pragma: no cover |
| except Exception as exc: |
| status = str(exc) |
| |
| self.m.gerrit.set_review( |
| 'post CL comment', |
| change.change, |
| host=change.host, |
| message='{} completed with status {}: http://go/bbid/{}'.format( |
| self.m.buildbucket.builder_name, |
| status, |
| self.m.buildbucket.build.id, |
| ), |
| notify='OWNER', |
| ) |