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