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