Mike Frysinger | f1ba7ad | 2022-09-12 05:42:57 -0400 | [diff] [blame] | 1 | # Copyright 2019 The ChromiumOS Authors |
Tiancong Wang | af05017 | 2019-07-10 11:52:03 -0700 | [diff] [blame] | 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
| 5 | """Toolchain-related operations.""" |
| 6 | |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 7 | import collections |
Chris McDonald | 1672ddb | 2021-07-21 11:48:23 -0600 | [diff] [blame] | 8 | import logging |
Alex Klein | cd03a5e | 2021-10-18 13:23:47 -0600 | [diff] [blame] | 9 | from pathlib import Path |
Jack Neus | 4ee7b1d | 2022-06-27 19:54:18 +0000 | [diff] [blame] | 10 | from typing import TYPE_CHECKING |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 11 | |
LaMont Jones | 5d2edcb | 2019-12-23 11:32:03 -0700 | [diff] [blame] | 12 | from chromite.api import controller |
Alex Klein | 076841b | 2019-08-29 15:19:39 -0600 | [diff] [blame] | 13 | from chromite.api import faux |
Alex Klein | 231d2da | 2019-07-22 16:44:45 -0600 | [diff] [blame] | 14 | from chromite.api import validate |
LaMont Jones | 5d2edcb | 2019-12-23 11:32:03 -0700 | [diff] [blame] | 15 | from chromite.api.controller import controller_util |
Tiancong Wang | 24a3df7 | 2019-08-20 15:48:51 -0700 | [diff] [blame] | 16 | from chromite.api.gen.chromite.api import toolchain_pb2 |
LaMont Jones | fd68cb1 | 2020-04-29 16:43:06 -0600 | [diff] [blame] | 17 | from chromite.api.gen.chromite.api.artifacts_pb2 import PrepareForBuildResponse |
Chris McDonald | 1672ddb | 2021-07-21 11:48:23 -0600 | [diff] [blame] | 18 | from chromite.api.gen.chromiumos.builder_config_pb2 import BuilderConfig |
Jack Neus | 4ee7b1d | 2022-06-27 19:54:18 +0000 | [diff] [blame] | 19 | from chromite.lib import toolchain as toolchain_lib |
Chris McDonald | 1672ddb | 2021-07-21 11:48:23 -0600 | [diff] [blame] | 20 | from chromite.lib import toolchain_util |
Ryan Beltran | f2a5dcc | 2022-04-19 20:34:00 +0000 | [diff] [blame] | 21 | from chromite.service import toolchain |
Ryan Beltran | 7d19180 | 2021-11-24 00:08:17 +0000 | [diff] [blame] | 22 | |
Mike Frysinger | ea11fdd | 2022-05-06 22:59:33 -0400 | [diff] [blame] | 23 | |
Jack Neus | 4ee7b1d | 2022-06-27 19:54:18 +0000 | [diff] [blame] | 24 | if TYPE_CHECKING: |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 25 | from chromite.api import api_config |
Jack Neus | 4ee7b1d | 2022-06-27 19:54:18 +0000 | [diff] [blame] | 26 | |
Ryan Beltran | f2a5dcc | 2022-04-19 20:34:00 +0000 | [diff] [blame] | 27 | # TODO(b/229665884): Move the implementation details for most/all endpoints to: |
| 28 | # chromite/services/toolchain.py |
| 29 | # This migration has been done for linting endpoints but not yet for others. |
Chris McDonald | 1672ddb | 2021-07-21 11:48:23 -0600 | [diff] [blame] | 30 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 31 | _Handlers = collections.namedtuple("_Handlers", ["name", "prepare", "bundle"]) |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 32 | _TOOLCHAIN_ARTIFACT_HANDLERS = { |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 33 | BuilderConfig.Artifacts.UNVERIFIED_CHROME_LLVM_ORDERFILE: _Handlers( |
| 34 | "UnverifiedChromeLlvmOrderfile", |
| 35 | toolchain_util.PrepareForBuild, |
| 36 | toolchain_util.BundleArtifacts, |
| 37 | ), |
| 38 | BuilderConfig.Artifacts.VERIFIED_CHROME_LLVM_ORDERFILE: _Handlers( |
| 39 | "VerifiedChromeLlvmOrderfile", |
| 40 | toolchain_util.PrepareForBuild, |
| 41 | toolchain_util.BundleArtifacts, |
| 42 | ), |
| 43 | BuilderConfig.Artifacts.CHROME_CLANG_WARNINGS_FILE: _Handlers( |
| 44 | "ChromeClangWarningsFile", |
| 45 | toolchain_util.PrepareForBuild, |
| 46 | toolchain_util.BundleArtifacts, |
| 47 | ), |
| 48 | BuilderConfig.Artifacts.UNVERIFIED_LLVM_PGO_FILE: _Handlers( |
| 49 | "UnverifiedLlvmPgoFile", |
| 50 | toolchain_util.PrepareForBuild, |
| 51 | toolchain_util.BundleArtifacts, |
| 52 | ), |
| 53 | BuilderConfig.Artifacts.UNVERIFIED_CHROME_BENCHMARK_AFDO_FILE: _Handlers( |
| 54 | "UnverifiedChromeBenchmarkAfdoFile", |
| 55 | toolchain_util.PrepareForBuild, |
| 56 | toolchain_util.BundleArtifacts, |
| 57 | ), |
| 58 | BuilderConfig.Artifacts.CHROME_DEBUG_BINARY: _Handlers( |
| 59 | "ChromeDebugBinary", |
| 60 | toolchain_util.PrepareForBuild, |
| 61 | toolchain_util.BundleArtifacts, |
| 62 | ), |
| 63 | BuilderConfig.Artifacts.UNVERIFIED_CHROME_BENCHMARK_PERF_FILE: _Handlers( |
| 64 | "UnverifiedChromeBenchmarkPerfFile", |
| 65 | toolchain_util.PrepareForBuild, |
| 66 | toolchain_util.BundleArtifacts, |
| 67 | ), |
| 68 | BuilderConfig.Artifacts.VERIFIED_CHROME_BENCHMARK_AFDO_FILE: _Handlers( |
| 69 | "VerifiedChromeBenchmarkAfdoFile", |
| 70 | toolchain_util.PrepareForBuild, |
| 71 | toolchain_util.BundleArtifacts, |
| 72 | ), |
| 73 | BuilderConfig.Artifacts.UNVERIFIED_KERNEL_CWP_AFDO_FILE: _Handlers( |
| 74 | "UnverifiedKernelCwpAfdoFile", |
| 75 | toolchain_util.PrepareForBuild, |
| 76 | toolchain_util.BundleArtifacts, |
| 77 | ), |
| 78 | BuilderConfig.Artifacts.VERIFIED_KERNEL_CWP_AFDO_FILE: _Handlers( |
| 79 | "VerifiedKernelCwpAfdoFile", |
| 80 | toolchain_util.PrepareForBuild, |
| 81 | toolchain_util.BundleArtifacts, |
| 82 | ), |
| 83 | BuilderConfig.Artifacts.UNVERIFIED_CHROME_CWP_AFDO_FILE: _Handlers( |
| 84 | "UnverifiedChromeCwpAfdoFile", |
| 85 | toolchain_util.PrepareForBuild, |
| 86 | toolchain_util.BundleArtifacts, |
| 87 | ), |
| 88 | BuilderConfig.Artifacts.VERIFIED_CHROME_CWP_AFDO_FILE: _Handlers( |
| 89 | "VerifiedChromeCwpAfdoFile", |
| 90 | toolchain_util.PrepareForBuild, |
| 91 | toolchain_util.BundleArtifacts, |
| 92 | ), |
| 93 | BuilderConfig.Artifacts.VERIFIED_RELEASE_AFDO_FILE: _Handlers( |
| 94 | "VerifiedReleaseAfdoFile", |
| 95 | toolchain_util.PrepareForBuild, |
| 96 | toolchain_util.BundleArtifacts, |
| 97 | ), |
| 98 | BuilderConfig.Artifacts.TOOLCHAIN_WARNING_LOGS: _Handlers( |
| 99 | "ToolchainWarningLogs", |
| 100 | toolchain_util.PrepareForBuild, |
| 101 | toolchain_util.BundleArtifacts, |
| 102 | ), |
| 103 | BuilderConfig.Artifacts.CHROME_AFDO_PROFILE_FOR_ANDROID_LINUX: _Handlers( |
| 104 | "ChromeAFDOProfileForAndroidLinux", |
| 105 | toolchain_util.PrepareForBuild, |
| 106 | toolchain_util.BundleArtifacts, |
| 107 | ), |
| 108 | BuilderConfig.Artifacts.CLANG_CRASH_DIAGNOSES: _Handlers( |
| 109 | "ClangCrashDiagnoses", |
| 110 | toolchain_util.PrepareForBuild, |
| 111 | toolchain_util.BundleArtifacts, |
| 112 | ), |
| 113 | BuilderConfig.Artifacts.COMPILER_RUSAGE_LOG: _Handlers( |
| 114 | "CompilerRusageLogs", |
| 115 | toolchain_util.PrepareForBuild, |
| 116 | toolchain_util.BundleArtifacts, |
| 117 | ), |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 118 | } |
| 119 | |
Tiancong Wang | d521413 | 2021-01-12 10:43:57 -0800 | [diff] [blame] | 120 | _TOOLCHAIN_COMMIT_HANDLERS = { |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 121 | BuilderConfig.Artifacts.VERIFIED_KERNEL_CWP_AFDO_FILE: "VerifiedKernelCwpAfdoFile" |
Tiancong Wang | d521413 | 2021-01-12 10:43:57 -0800 | [diff] [blame] | 122 | } |
| 123 | |
LaMont Jones | e782167 | 2020-04-09 08:56:26 -0600 | [diff] [blame] | 124 | |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 125 | # TODO(crbug/1031213): When @faux is expanded to have more than success/failure, |
| 126 | # this should be changed. |
| 127 | @faux.all_empty |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 128 | @validate.require("artifact_types") |
LaMont Jones | 5d2edcb | 2019-12-23 11:32:03 -0700 | [diff] [blame] | 129 | # Note: chroot and sysroot are unspecified the first time that the build_target |
| 130 | # recipe calls PrepareForBuild. The second time, they are specified. No |
| 131 | # validation check because "all" values are valid. |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 132 | @validate.validation_complete |
Jack Neus | 4ee7b1d | 2022-06-27 19:54:18 +0000 | [diff] [blame] | 133 | def PrepareForBuild( |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 134 | input_proto: "toolchain_pb2.PrepareForToolchainBuildRequest", |
| 135 | output_proto: "toolchain_pb2.PrepareForToolchainBuildResponse", |
| 136 | _config: "api_config.ApiConfig", |
| 137 | ): |
| 138 | """Prepare to build toolchain artifacts. |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 139 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 140 | The handlers (from _TOOLCHAIN_ARTIFACT_HANDLERS above) are called with: |
| 141 | artifact_name (str): name of the artifact type. |
| 142 | chroot (chroot_lib.Chroot): chroot. Will be None if the chroot has not |
| 143 | yet been created. |
| 144 | sysroot_path (str): sysroot path inside the chroot (e.g., /build/atlas). |
| 145 | Will be an empty string if the sysroot has not yet been created. |
| 146 | build_target_name (str): name of the build target (e.g., atlas). Will be |
| 147 | an empty string if the sysroot has not yet been created. |
| 148 | input_artifacts ({(str) name:[str gs_locations]}): locations for possible |
| 149 | input artifacts. The handler is expected to know which keys it should |
| 150 | be using, and ignore any keys that it does not understand. |
| 151 | profile_info ({(str) name: (str) value}) Dictionary containing profile |
| 152 | information. |
LaMont Jones | a215f1e | 2019-12-06 10:18:58 -0700 | [diff] [blame] | 153 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 154 | They locate and modify any ebuilds and/or source required for the artifact |
| 155 | being created, then return a value from toolchain_util.PrepareForBuildReturn. |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 156 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 157 | This function sets output_proto.build_relevance to the result. |
LaMont Jones | 5d2edcb | 2019-12-23 11:32:03 -0700 | [diff] [blame] | 158 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 159 | Args: |
Alex Klein | 611dddd | 2022-10-11 17:02:01 -0600 | [diff] [blame] | 160 | input_proto: The input proto |
| 161 | output_proto: The output proto |
| 162 | _config): The API call config. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 163 | """ |
| 164 | if input_proto.chroot.path: |
| 165 | chroot = controller_util.ParseChroot(input_proto.chroot) |
| 166 | else: |
| 167 | chroot = None |
LaMont Jones | 4579e8c | 2019-12-06 14:20:37 -0700 | [diff] [blame] | 168 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 169 | input_artifacts = collections.defaultdict(list) |
| 170 | for art in input_proto.input_artifacts: |
| 171 | item = _TOOLCHAIN_ARTIFACT_HANDLERS.get(art.input_artifact_type) |
| 172 | if item: |
| 173 | input_artifacts[item.name].extend( |
| 174 | ["gs://%s" % str(x) for x in art.input_artifact_gs_locations] |
| 175 | ) |
LaMont Jones | 5d2edcb | 2019-12-23 11:32:03 -0700 | [diff] [blame] | 176 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 177 | profile_info = _GetProfileInfoDict(input_proto.profile_info) |
LaMont Jones | 45ca6c4 | 2020-02-05 09:39:09 -0700 | [diff] [blame] | 178 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 179 | results = set() |
| 180 | sysroot_path = input_proto.sysroot.path |
| 181 | build_target = input_proto.sysroot.build_target.name |
| 182 | for artifact_type in input_proto.artifact_types: |
| 183 | # Unknown artifact_types are an error. |
| 184 | handler = _TOOLCHAIN_ARTIFACT_HANDLERS[artifact_type] |
| 185 | if handler.prepare: |
| 186 | results.add( |
| 187 | handler.prepare( |
| 188 | handler.name, |
| 189 | chroot, |
| 190 | sysroot_path, |
| 191 | build_target, |
| 192 | input_artifacts, |
| 193 | profile_info, |
| 194 | ) |
| 195 | ) |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 196 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 197 | # Translate the returns from the handlers we called. |
| 198 | # If any NEEDED => NEEDED |
| 199 | # elif any UNKNOWN => UNKNOWN |
| 200 | # elif any POINTLESS => POINTLESS |
| 201 | # else UNKNOWN. |
| 202 | if toolchain_util.PrepareForBuildReturn.NEEDED in results: |
| 203 | output_proto.build_relevance = PrepareForBuildResponse.NEEDED |
| 204 | elif toolchain_util.PrepareForBuildReturn.UNKNOWN in results: |
| 205 | output_proto.build_relevance = PrepareForBuildResponse.UNKNOWN |
| 206 | elif toolchain_util.PrepareForBuildReturn.POINTLESS in results: |
| 207 | output_proto.build_relevance = PrepareForBuildResponse.POINTLESS |
| 208 | else: |
| 209 | output_proto.build_relevance = PrepareForBuildResponse.UNKNOWN |
| 210 | return controller.RETURN_CODE_SUCCESS |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 211 | |
| 212 | |
| 213 | # TODO(crbug/1031213): When @faux is expanded to have more than success/failure, |
| 214 | # this should be changed. |
| 215 | @faux.all_empty |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 216 | @validate.require("chroot.path", "output_dir", "artifact_types") |
| 217 | @validate.exists("output_dir") |
LaMont Jones | 5d2edcb | 2019-12-23 11:32:03 -0700 | [diff] [blame] | 218 | @validate.validation_complete |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 219 | def BundleArtifacts( |
| 220 | input_proto: "toolchain_pb2.BundleToolchainRequest", |
| 221 | output_proto: "toolchain_pb2.BundleToolchainResponse", |
| 222 | _config: "api_config.ApiConfig", |
| 223 | ): |
| 224 | """Bundle valid toolchain artifacts. |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 225 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 226 | The handlers (from _TOOLCHAIN_ARTIFACT_HANDLERS above) are called with: |
| 227 | artifact_name (str): name of the artifact type |
| 228 | chroot (chroot_lib.Chroot): chroot |
| 229 | sysroot_path (str): sysroot path inside the chroot (e.g., /build/atlas), |
| 230 | or None. |
| 231 | chrome_root (str): path to chrome root. (e.g., /b/s/w/ir/k/chrome) |
Alex Klein | 611dddd | 2022-10-11 17:02:01 -0600 | [diff] [blame] | 232 | build_target_name (str): name of the build target (e.g. atlas), or None. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 233 | output_dir (str): absolute path where artifacts are being bundled. |
Alex Klein | 611dddd | 2022-10-11 17:02:01 -0600 | [diff] [blame] | 234 | (e.g., /b/s/w/ir/k/recipe_cleanup/artifactssptfMU) |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 235 | profile_info ({(str) name: (str) value}) Dictionary containing profile |
| 236 | information. |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 237 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 238 | Note: the actual upload to GS is done by CI, not here. |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 239 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 240 | Args: |
Alex Klein | 611dddd | 2022-10-11 17:02:01 -0600 | [diff] [blame] | 241 | input_proto: The input proto |
| 242 | output_proto: The output proto |
| 243 | _config: The API call config. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 244 | """ |
| 245 | chroot = controller_util.ParseChroot(input_proto.chroot) |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 246 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 247 | profile_info = _GetProfileInfoDict(input_proto.profile_info) |
LaMont Jones | 45ca6c4 | 2020-02-05 09:39:09 -0700 | [diff] [blame] | 248 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 249 | output_path = Path(input_proto.output_dir) |
Alex Klein | cd03a5e | 2021-10-18 13:23:47 -0600 | [diff] [blame] | 250 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 251 | for artifact_type in input_proto.artifact_types: |
| 252 | if artifact_type not in _TOOLCHAIN_ARTIFACT_HANDLERS: |
| 253 | logging.error("%s not understood", artifact_type) |
| 254 | return controller.RETURN_CODE_UNRECOVERABLE |
Alex Klein | cd03a5e | 2021-10-18 13:23:47 -0600 | [diff] [blame] | 255 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 256 | handler = _TOOLCHAIN_ARTIFACT_HANDLERS[artifact_type] |
| 257 | if not handler or not handler.bundle: |
| 258 | logging.warning( |
| 259 | "%s does not have a handler with a bundle function.", |
| 260 | artifact_type, |
| 261 | ) |
| 262 | continue |
Alex Klein | cd03a5e | 2021-10-18 13:23:47 -0600 | [diff] [blame] | 263 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 264 | artifacts = handler.bundle( |
| 265 | handler.name, |
| 266 | chroot, |
| 267 | input_proto.sysroot.path, |
| 268 | input_proto.sysroot.build_target.name, |
| 269 | input_proto.output_dir, |
| 270 | profile_info, |
| 271 | ) |
| 272 | if not artifacts: |
| 273 | continue |
Alex Klein | cd03a5e | 2021-10-18 13:23:47 -0600 | [diff] [blame] | 274 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 275 | # Filter out artifacts that do not exist or are empty. |
| 276 | usable_artifacts = [] |
| 277 | for artifact in artifacts: |
| 278 | artifact_path = output_path / artifact |
| 279 | if not artifact_path.exists(): |
| 280 | logging.warning("%s is not in the output directory.", artifact) |
| 281 | elif not artifact_path.stat().st_size: |
| 282 | logging.warning("%s is empty.", artifact) |
| 283 | else: |
| 284 | usable_artifacts.append(artifact) |
Alex Klein | cd03a5e | 2021-10-18 13:23:47 -0600 | [diff] [blame] | 285 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 286 | if not usable_artifacts: |
| 287 | logging.warning( |
| 288 | "No usable artifacts for artifact type %s", artifact_type |
| 289 | ) |
| 290 | continue |
Alex Klein | cd03a5e | 2021-10-18 13:23:47 -0600 | [diff] [blame] | 291 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 292 | # Add all usable artifacts. |
| 293 | art_info = output_proto.artifacts_info.add() |
| 294 | art_info.artifact_type = artifact_type |
| 295 | for artifact in usable_artifacts: |
| 296 | art_info.artifacts.add().path = artifact |
LaMont Jones | b20b3d9 | 2019-11-23 11:47:48 -0700 | [diff] [blame] | 297 | |
| 298 | |
Tiancong Wang | d521413 | 2021-01-12 10:43:57 -0800 | [diff] [blame] | 299 | def _GetUpdatedFilesResponse(_input_proto, output_proto, _config): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 300 | """Add successful status to the faux response.""" |
| 301 | file_info = output_proto.updated_files.add() |
| 302 | file_info.path = "/any/modified/file" |
| 303 | output_proto.commit_message = "Commit message" |
Tiancong Wang | d521413 | 2021-01-12 10:43:57 -0800 | [diff] [blame] | 304 | |
| 305 | |
| 306 | @faux.empty_error |
| 307 | @faux.success(_GetUpdatedFilesResponse) |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 308 | @validate.require("uploaded_artifacts") |
Tiancong Wang | d521413 | 2021-01-12 10:43:57 -0800 | [diff] [blame] | 309 | @validate.validation_complete |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 310 | def GetUpdatedFiles( |
| 311 | input_proto: "toolchain_pb2.GetUpdatedFilesRequest", |
| 312 | output_proto: "toolchain_pb2.GetUpdatedFilesResponse", |
| 313 | _config: "api_config.ApiConfig", |
| 314 | ): |
| 315 | """Use uploaded artifacts to update some updates in a chromeos checkout. |
Tiancong Wang | d521413 | 2021-01-12 10:43:57 -0800 | [diff] [blame] | 316 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 317 | The function will call toolchain_util.GetUpdatedFiles using the type of |
| 318 | uploaded artifacts to make some changes in a checkout, and return the list |
| 319 | of change files together with commit message. |
Alex Klein | 611dddd | 2022-10-11 17:02:01 -0600 | [diff] [blame] | 320 | updated_artifacts: A list of UpdatedArtifacts type which contains a |
| 321 | tuple of artifact info and profile info. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 322 | Note: the actual creation of the commit is done by CI, not here. |
Tiancong Wang | d521413 | 2021-01-12 10:43:57 -0800 | [diff] [blame] | 323 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 324 | Args: |
Alex Klein | 611dddd | 2022-10-11 17:02:01 -0600 | [diff] [blame] | 325 | input_proto: The input proto |
| 326 | output_proto: The output proto |
| 327 | _config: The API call config. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 328 | """ |
| 329 | commit_message = "" |
| 330 | for artifact in input_proto.uploaded_artifacts: |
| 331 | artifact_type = artifact.artifact_info.artifact_type |
| 332 | if artifact_type not in _TOOLCHAIN_COMMIT_HANDLERS: |
| 333 | logging.error("%s not understood", artifact_type) |
| 334 | return controller.RETURN_CODE_UNRECOVERABLE |
| 335 | artifact_name = _TOOLCHAIN_COMMIT_HANDLERS[artifact_type] |
| 336 | if artifact_name: |
| 337 | assert ( |
| 338 | len(artifact.artifact_info.artifacts) == 1 |
| 339 | ), "Only one file to update per each artifact" |
| 340 | updated_files, message = toolchain_util.GetUpdatedFiles( |
| 341 | artifact_name, |
| 342 | artifact.artifact_info.artifacts[0].path, |
| 343 | _GetProfileInfoDict(artifact.profile_info), |
| 344 | ) |
| 345 | for f in updated_files: |
| 346 | file_info = output_proto.updated_files.add() |
| 347 | file_info.path = f |
Tiancong Wang | d521413 | 2021-01-12 10:43:57 -0800 | [diff] [blame] | 348 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 349 | commit_message += message + "\n" |
| 350 | output_proto.commit_message = commit_message |
| 351 | # No commit footer is added for now. Can add more here if needed |
Tiancong Wang | d521413 | 2021-01-12 10:43:57 -0800 | [diff] [blame] | 352 | |
| 353 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 354 | def _GetProfileInfoDict(profile_info: "toolchain_pb2.ArtifactProfileInfo"): |
| 355 | """Convert profile_info to a dict. |
Ryan Beltran | f2a5dcc | 2022-04-19 20:34:00 +0000 | [diff] [blame] | 356 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 357 | Args: |
Alex Klein | 611dddd | 2022-10-11 17:02:01 -0600 | [diff] [blame] | 358 | profile_info: The artifact profile_info. |
Ryan Beltran | f2a5dcc | 2022-04-19 20:34:00 +0000 | [diff] [blame] | 359 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 360 | Returns: |
Alex Klein | 611dddd | 2022-10-11 17:02:01 -0600 | [diff] [blame] | 361 | A dictionary containing profile info. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 362 | """ |
| 363 | ret = {} |
| 364 | which = profile_info.WhichOneof("artifact_profile_info") |
| 365 | if which: |
| 366 | value = getattr(profile_info, which) |
| 367 | # If it is a message, then use the contents of the message. This works as |
| 368 | # long as simple types do not have a 'DESCRIPTOR' attribute. (And protobuf |
| 369 | # messages do.) |
| 370 | if getattr(value, "DESCRIPTOR", None): |
| 371 | ret.update({k.name: v for k, v in value.ListFields()}) |
| 372 | else: |
| 373 | ret[which] = value |
| 374 | return ret |
Ryan Beltran | f2a5dcc | 2022-04-19 20:34:00 +0000 | [diff] [blame] | 375 | |
| 376 | |
| 377 | LINTER_CODES = { |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 378 | "clang_tidy": toolchain_pb2.LinterFinding.CLANG_TIDY, |
| 379 | "cargo_clippy": toolchain_pb2.LinterFinding.CARGO_CLIPPY, |
| 380 | "go_lint": toolchain_pb2.LinterFinding.GO_LINT, |
Ryan Beltran | f2a5dcc | 2022-04-19 20:34:00 +0000 | [diff] [blame] | 381 | } |
| 382 | |
| 383 | |
Ryan Beltran | 0df7fb0 | 2021-11-10 20:58:51 +0000 | [diff] [blame] | 384 | @faux.all_empty |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 385 | @validate.exists("sysroot.path") |
| 386 | @validate.require("packages") |
Ryan Beltran | 0df7fb0 | 2021-11-10 20:58:51 +0000 | [diff] [blame] | 387 | @validate.validation_complete |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 388 | def EmergeWithLinting( |
| 389 | input_proto: "toolchain_pb2.LinterRequest", |
| 390 | output_proto: "toolchain_pb2.LinterResponse", |
| 391 | _config: "api_config.ApiConfig", |
| 392 | ): |
| 393 | """Emerge packages with linter features enabled and retrieves all findings. |
Ryan Beltran | 0df7fb0 | 2021-11-10 20:58:51 +0000 | [diff] [blame] | 394 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 395 | Args: |
Alex Klein | 611dddd | 2022-10-11 17:02:01 -0600 | [diff] [blame] | 396 | input_proto: The nput proto with package and sysroot info. |
| 397 | output_proto: The output proto where findings are stored. |
| 398 | _config: The API call config (unused). |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 399 | """ |
| 400 | packages = [ |
| 401 | controller_util.deserialize_package_info(package) |
| 402 | for package in input_proto.packages |
| 403 | ] |
Ryan Beltran | 7d19180 | 2021-11-24 00:08:17 +0000 | [diff] [blame] | 404 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 405 | build_linter = toolchain.BuildLinter( |
| 406 | packages, |
| 407 | input_proto.sysroot.path, |
| 408 | differential=input_proto.filter_modified, |
| 409 | ) |
Ryan Beltran | 7d19180 | 2021-11-24 00:08:17 +0000 | [diff] [blame] | 410 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 411 | use_clippy = ( |
| 412 | toolchain_pb2.LinterFinding.CARGO_CLIPPY |
| 413 | not in input_proto.disabled_linters |
| 414 | ) |
| 415 | use_tidy = ( |
| 416 | toolchain_pb2.LinterFinding.CLANG_TIDY |
| 417 | not in input_proto.disabled_linters |
| 418 | ) |
| 419 | use_golint = ( |
| 420 | toolchain_pb2.LinterFinding.GO_LINT not in input_proto.disabled_linters |
| 421 | ) |
Ryan Beltran | 1277cb8 | 2022-11-27 03:15:36 +0000 | [diff] [blame^] | 422 | use_iwyu = ( |
| 423 | toolchain_pb2.LinterFinding.IWYU not in input_proto.disabled_linters |
| 424 | ) |
Ryan Beltran | 4425d5f | 2022-07-20 18:34:33 +0000 | [diff] [blame] | 425 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 426 | findings = build_linter.emerge_with_linting( |
Ryan Beltran | 1277cb8 | 2022-11-27 03:15:36 +0000 | [diff] [blame^] | 427 | use_clippy=use_clippy, |
| 428 | use_tidy=use_tidy, |
| 429 | use_golint=use_golint, |
| 430 | use_iwyu=use_iwyu, |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 431 | ) |
Ryan Beltran | f9a86f4 | 2022-04-13 20:58:18 +0000 | [diff] [blame] | 432 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 433 | for finding in findings: |
| 434 | locations = [] |
| 435 | for location in finding.locations: |
| 436 | locations.append( |
| 437 | toolchain_pb2.LinterFindingLocation( |
| 438 | filepath=location.filepath, |
| 439 | line_start=location.line_start, |
| 440 | line_end=location.line_end, |
| 441 | ) |
| 442 | ) |
| 443 | output_proto.findings.append( |
| 444 | toolchain_pb2.LinterFinding( |
| 445 | message=finding.message, |
| 446 | locations=locations, |
| 447 | linter=LINTER_CODES[finding.linter], |
| 448 | ) |
| 449 | ) |
Jack Neus | 4ee7b1d | 2022-06-27 19:54:18 +0000 | [diff] [blame] | 450 | |
| 451 | |
| 452 | @faux.all_empty |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 453 | @validate.require("board") |
Jack Neus | 4ee7b1d | 2022-06-27 19:54:18 +0000 | [diff] [blame] | 454 | @validate.validation_complete |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 455 | def GetToolchainsForBoard( |
| 456 | input_proto: "toolchain_pb2.ToolchainsRequest", |
| 457 | output_proto: "toolchain_pb2.ToolchainsReponse", |
| 458 | _config: "api_config.ApiConfig", |
| 459 | ): |
| 460 | """Gets the default and non-default toolchains for a board. |
Jack Neus | 4ee7b1d | 2022-06-27 19:54:18 +0000 | [diff] [blame] | 461 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 462 | Args: |
Alex Klein | 611dddd | 2022-10-11 17:02:01 -0600 | [diff] [blame] | 463 | input_proto: The input proto with board and sysroot info. |
| 464 | output_proto: The output proto where findings are stored. |
| 465 | _config: The API call config (unused). |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 466 | """ |
| 467 | toolchains = toolchain_lib.GetToolchainsForBoard(input_proto.board) |
| 468 | output_proto.default_toolchains.extend( |
| 469 | list(toolchain_lib.FilterToolchains(toolchains, "default", True)) |
| 470 | ) |
| 471 | output_proto.nondefault_toolchains.extend( |
| 472 | list(toolchain_lib.FilterToolchains(toolchains, "default", False)) |
| 473 | ) |