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