Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 1 | # Copyright 2021 The Pigweed Authors |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| 4 | # use this file except in compliance with the License. You may obtain a copy of |
| 5 | # the License at |
| 6 | # |
| 7 | # https://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 12 | # License for the specific language governing permissions and limitations under |
| 13 | # the License. |
| 14 | """Utility functions common to multiple recipes that don't fit elsewhere.""" |
| 15 | |
Rob Mohr | 2f31ceb | 2024-08-13 19:17:44 +0000 | [diff] [blame] | 16 | from __future__ import annotations |
| 17 | |
Rob Mohr | 34a1f8e | 2021-08-19 08:37:43 -0700 | [diff] [blame] | 18 | import json |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 19 | import re |
Rob Mohr | 8653154 | 2024-08-13 19:33:21 +0000 | [diff] [blame] | 20 | from typing import TYPE_CHECKING |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 21 | |
Rob Mohr | aab5166 | 2023-11-10 22:45:09 +0000 | [diff] [blame] | 22 | import attrs |
Rob Mohr | 34a1f8e | 2021-08-19 08:37:43 -0700 | [diff] [blame] | 23 | from google.protobuf import json_format |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 24 | from recipe_engine import recipe_api |
| 25 | |
Rob Mohr | 8653154 | 2024-08-13 19:33:21 +0000 | [diff] [blame] | 26 | if TYPE_CHECKING: # pragma: no cover |
| 27 | from typing import Any, Sequence |
| 28 | from PB.go.chromium.org.luci.buildbucket.proto import ( |
| 29 | build as build_pb2, |
| 30 | common as common_pb2, |
| 31 | ) |
| 32 | |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 33 | |
Rob Mohr | aab5166 | 2023-11-10 22:45:09 +0000 | [diff] [blame] | 34 | @attrs.define |
Rob Mohr | 82c0e35 | 2022-07-27 20:57:40 +0000 | [diff] [blame] | 35 | class ChangeWithComments: |
Rob Mohr | aab5166 | 2023-11-10 22:45:09 +0000 | [diff] [blame] | 36 | change: common_pb2.GerritChange |
| 37 | details: dict[str, Any] |
| 38 | commit_message: str |
| 39 | comments: Sequence[str] |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 40 | |
| 41 | |
| 42 | class UtilApi(recipe_api.RecipeApi): |
Rob Mohr | 298f5b3 | 2023-11-17 20:16:51 +0000 | [diff] [blame] | 43 | ChangeWithComments = ChangeWithComments |
| 44 | |
Rob Mohr | aab5166 | 2023-11-10 22:45:09 +0000 | [diff] [blame] | 45 | def get_change_with_comments(self) -> ChangeWithComments: |
Rob Mohr | 298f5b3 | 2023-11-17 20:16:51 +0000 | [diff] [blame] | 46 | input_: build_pb2.Build.Input = self.m.buildbucket.build.input |
| 47 | change: common_pb2.GerritChange = input_.gerrit_changes[0] |
| 48 | change_id: str = str(change.change) |
| 49 | details: dict[str, Any] = self.m.gerrit.change_details( |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 50 | 'change details', |
| 51 | change_id=change_id, |
| 52 | host=input_.gerrit_changes[0].host, |
Rob Mohr | 807f3ce | 2021-09-08 11:16:04 -0700 | [diff] [blame] | 53 | query_params=['ALL_COMMITS', 'ALL_REVISIONS', 'ALL_FILES'], |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 54 | test_data=self.m.json.test_api.output( |
| 55 | { |
Rob Mohr | 336d335 | 2024-02-14 19:27:51 +0000 | [diff] [blame] | 56 | 'owner': { |
| 57 | 'email': 'coder@example.com', |
| 58 | }, |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 59 | 'current_revision': 'a' * 40, |
| 60 | 'revisions': { |
Rob Mohr | 5a79c0f | 2021-07-26 12:27:35 -0700 | [diff] [blame] | 61 | 'a' |
| 62 | * 40: { |
| 63 | 'files': [], |
Rob Mohr | 336d335 | 2024-02-14 19:27:51 +0000 | [diff] [blame] | 64 | 'commit': { |
| 65 | 'message': '', |
| 66 | }, |
Rob Mohr | 5a79c0f | 2021-07-26 12:27:35 -0700 | [diff] [blame] | 67 | 'description': 'description', |
| 68 | } |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 69 | }, |
| 70 | 'revert_of': 0, |
| 71 | } |
| 72 | ), |
| 73 | ).json.output |
| 74 | |
Rob Mohr | 336d335 | 2024-02-14 19:27:51 +0000 | [diff] [blame] | 75 | current_revision: str = details['revisions'][ |
| 76 | details['current_revision'] |
| 77 | ] |
Rob Mohr | 298f5b3 | 2023-11-17 20:16:51 +0000 | [diff] [blame] | 78 | commit_message: str = current_revision['commit']['message'] |
Rob Mohr | 5acf39e | 2021-11-11 08:10:58 -0800 | [diff] [blame] | 79 | |
Rob Mohr | 298f5b3 | 2023-11-17 20:16:51 +0000 | [diff] [blame] | 80 | comments: list[str] = [] |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 81 | |
Rob Mohr | 753e183 | 2021-07-30 15:04:45 -0700 | [diff] [blame] | 82 | for revision in details['revisions'].values(): |
Rob Mohr | 5a79c0f | 2021-07-26 12:27:35 -0700 | [diff] [blame] | 83 | if revision.get('description'): |
| 84 | comments.append(revision['description']) |
| 85 | |
Rob Mohr | 298f5b3 | 2023-11-17 20:16:51 +0000 | [diff] [blame] | 86 | comments_result: dict[str, Any] = self.m.gerrit.list_change_comments( |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 87 | "list change comments", |
| 88 | change_id, |
| 89 | test_data=self.m.json.test_api.output( |
Rob Mohr | 336d335 | 2024-02-14 19:27:51 +0000 | [diff] [blame] | 90 | { |
| 91 | '/PATCHSET_LEVEL': [{'message': ''}], |
| 92 | } |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 93 | ), |
| 94 | ).json.output |
| 95 | |
Rob Mohr | 3445395 | 2021-08-04 06:46:54 -0700 | [diff] [blame] | 96 | for _, comment_data in comments_result.items(): |
| 97 | comments.extend(x['message'] for x in comment_data) |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 98 | |
Rob Mohr | 5acf39e | 2021-11-11 08:10:58 -0800 | [diff] [blame] | 99 | return ChangeWithComments(change, details, commit_message, comments) |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 100 | |
Rob Mohr | aab5166 | 2023-11-10 22:45:09 +0000 | [diff] [blame] | 101 | def find_matching_comment( |
| 102 | self, rx: re.Pattern, comments: Sequence[str] |
Rob Mohr | 1457cf9 | 2024-03-06 20:39:59 +0000 | [diff] [blame] | 103 | ) -> str | None: |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 104 | """Find a comment in comments that matches regex object rx.""" |
Rob Mohr | 1457cf9 | 2024-03-06 20:39:59 +0000 | [diff] [blame] | 105 | result: str | None = None |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 106 | with self.m.step.nest('checking comments'): |
| 107 | for i, comment in enumerate(comments): |
Rob Mohr | 4806b6b | 2023-02-03 18:03:32 +0000 | [diff] [blame] | 108 | with self.m.step.nest(f'comment ({i})') as pres: |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 109 | pres.step_summary_text = comment |
Rob Mohr | aab5166 | 2023-11-10 22:45:09 +0000 | [diff] [blame] | 110 | match: re.Match = re.search(rx, comment) |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 111 | if match: |
Rob Mohr | 4806b6b | 2023-02-03 18:03:32 +0000 | [diff] [blame] | 112 | pres.step_summary_text = f'MATCH: {comment}' |
Rob Mohr | aab5166 | 2023-11-10 22:45:09 +0000 | [diff] [blame] | 113 | result: str = match.group(0) |
Rob Mohr | 038bf99 | 2021-06-18 13:03:35 -0700 | [diff] [blame] | 114 | break |
| 115 | |
| 116 | if result: |
| 117 | with self.m.step.nest('found'): |
| 118 | pass |
| 119 | |
| 120 | return result |
Rob Mohr | 34a1f8e | 2021-08-19 08:37:43 -0700 | [diff] [blame] | 121 | |
Rob Mohr | aab5166 | 2023-11-10 22:45:09 +0000 | [diff] [blame] | 122 | def build_metadata(self) -> dict[str, Any]: |
Rob Mohr | 34a1f8e | 2021-08-19 08:37:43 -0700 | [diff] [blame] | 123 | return { |
| 124 | 'bb_id': self.m.buildbucket.build.id, |
| 125 | 'swarming_id': self.m.swarming.task_id, |
| 126 | 'builder': self.m.buildbucket_util.full_builder_name(), |
Rob Mohr | 9865cec | 2024-10-17 18:13:50 +0000 | [diff] [blame] | 127 | 'url': self.m.buildbucket.build_url(), |
Rob Mohr | 34a1f8e | 2021-08-19 08:37:43 -0700 | [diff] [blame] | 128 | 'triggers': [ |
| 129 | json.loads(json_format.MessageToJson(x)) |
| 130 | for x in self.m.scheduler.triggers |
| 131 | ], |
| 132 | } |