go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/common/services/milo_internal.ts (about) 1 // Copyright 2020 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 import stableStringify from 'fast-json-stable-stringify'; 16 17 import { Build, BuilderID, BuilderItem } from '@/common/services/buildbucket'; 18 import { cached, CacheOption } from '@/generic_libs/tools/cached_fn'; 19 import { PrpcClientExt } from '@/generic_libs/tools/prpc_client_ext'; 20 21 import { GitilesCommit } from './common'; 22 23 /** 24 * Manually coded type definition and classes for milo internal service. 25 * TODO(weiweilin): To be replaced by code generated version once we have one. 26 * source: https://chromium.googlesource.com/infra/luci/luci-go/+/HEAD/milo/api/service/v1/rpc.proto 27 */ 28 29 export interface QueryBlamelistRequest { 30 readonly gitilesCommit: GitilesCommit; 31 readonly builder: BuilderID; 32 readonly pageSize?: number; 33 readonly pageToken?: string; 34 } 35 36 export interface CommitUser { 37 readonly name: string; 38 readonly email: string; 39 readonly time: string; 40 } 41 42 export const enum CommitTreeDiffChangeType { 43 Add = 'ADD', 44 Copy = 'COPY', 45 Delete = 'DELETE', 46 Modify = 'MODIFY', 47 Rename = 'RENAME', 48 } 49 50 export interface CommitTreeDiff { 51 readonly type: CommitTreeDiffChangeType; 52 readonly oldId: string; 53 readonly oldMode: number; 54 readonly oldPath: string; 55 readonly newId: string; 56 readonly newMode: number; 57 readonly newPath: string; 58 } 59 60 export interface GitCommit { 61 readonly id: string; 62 readonly tree: string; 63 readonly parents?: string[]; 64 readonly author: CommitUser; 65 readonly committer: CommitUser; 66 readonly message: string; 67 readonly treeDiff: CommitTreeDiff[]; 68 } 69 70 export interface QueryBlamelistResponse { 71 readonly commits?: GitCommit[]; 72 readonly nextPageToken?: string; 73 readonly precedingCommit?: GitCommit; 74 } 75 76 export interface GetProjectCfgRequest { 77 readonly project: string; 78 } 79 80 export interface Project { 81 readonly logoUrl?: string; 82 readonly bugUrlTemplate?: string; 83 readonly metadataConfig?: MetadataConfig; 84 } 85 86 export interface MetadataConfig { 87 readonly testMetadataProperties?: readonly DisplayRule[]; 88 } 89 export interface DisplayRule { 90 readonly schema: string; 91 readonly displayItems: readonly DisplayItem[]; 92 } 93 94 export interface DisplayItem { 95 readonly displayName: string; 96 readonly path: string; 97 } 98 99 export interface BugTemplate { 100 readonly summary?: string; 101 readonly description?: string; 102 readonly monorailProject?: string; 103 readonly components?: readonly string[]; 104 } 105 106 export interface QueryRecentBuildsRequest { 107 readonly builder: BuilderID; 108 readonly pageSize?: number; 109 readonly pageToken?: string; 110 } 111 112 export interface QueryRecentBuildsResponse { 113 readonly builds?: readonly Build[]; 114 readonly nextPageToken?: string; 115 } 116 117 export interface ListBuildersRequest { 118 readonly project?: string; 119 readonly group?: string; 120 readonly pageSize?: number; 121 readonly pageToken?: string; 122 } 123 124 export interface ListBuildersResponse { 125 readonly builders?: readonly BuilderItem[]; 126 readonly nextPageToken?: string; 127 } 128 129 export interface ProjectItem { 130 readonly id: string; 131 } 132 133 export interface ListProjectsRequest { 134 readonly pageSize?: number; 135 readonly pageToken?: string; 136 } 137 138 export interface ListProjectsResponse { 139 readonly projects?: readonly ProjectListItem[]; 140 readonly nextPageToken?: string; 141 } 142 143 export interface ProjectListItem { 144 readonly id: string; 145 readonly logoUrl?: string; 146 } 147 148 export interface QueryBuilderStatsRequest { 149 readonly builder: BuilderID; 150 } 151 152 export interface BuilderStats { 153 readonly builder: BuilderID; 154 readonly pendingBuildsCount?: number; 155 readonly runningBuildsCount?: number; 156 } 157 158 export interface BatchCheckPermissionsRequest { 159 readonly realm: string; 160 readonly permissions: readonly string[]; 161 } 162 163 export interface BatchCheckPermissionsResponse { 164 readonly results: { readonly [key: string]: boolean }; 165 } 166 167 export interface ConsolePredicate { 168 readonly project?: string; 169 readonly builder?: BuilderID; 170 } 171 172 export interface QueryConsolesRequest { 173 readonly predicate: ConsolePredicate; 174 readonly pageSize?: number; 175 readonly pageToken?: string; 176 } 177 178 export interface Builder { 179 readonly id: BuilderID; 180 readonly category?: string; 181 readonly shortName?: string; 182 } 183 184 export interface Console { 185 readonly id: string; 186 readonly name: string; 187 readonly realm: string; 188 readonly repoUrl: string; 189 readonly builders?: readonly Builder[]; 190 } 191 192 export interface QueryConsolesResponse { 193 readonly consoles?: readonly Console[]; 194 readonly nextPageToken?: string; 195 } 196 197 export interface QueryConsoleSnapshotsRequest { 198 readonly predicate: ConsolePredicate; 199 readonly pageSize?: number; 200 readonly pageToken?: string; 201 } 202 203 export interface BuilderSnapshot { 204 readonly builder: BuilderID; 205 readonly build?: Build; 206 } 207 208 export interface ConsoleSnapshot { 209 readonly console: Console; 210 readonly builderSnapshots?: readonly BuilderSnapshot[]; 211 } 212 213 export interface QueryConsoleSnapshotsResponse { 214 readonly snapshots?: readonly ConsoleSnapshot[]; 215 readonly nextPageToken?: string; 216 } 217 218 export class MiloInternal { 219 static readonly SERVICE = 'luci.milo.v1.MiloInternal'; 220 private readonly cachedCallFn: ( 221 opt: CacheOption, 222 method: string, 223 message: object, 224 ) => Promise<unknown>; 225 226 constructor(client: PrpcClientExt) { 227 this.cachedCallFn = cached( 228 (method: string, message: object) => 229 client.call(MiloInternal.SERVICE, method, message), 230 { 231 key: (method, message) => `${method}-${stableStringify(message)}`, 232 }, 233 ); 234 } 235 236 async queryBlamelist(req: QueryBlamelistRequest, cacheOpt: CacheOption = {}) { 237 return (await this.cachedCallFn( 238 cacheOpt, 239 'QueryBlamelist', 240 req, 241 )) as QueryBlamelistResponse; 242 } 243 244 async getProjectCfg(req: GetProjectCfgRequest, cacheOpt: CacheOption = {}) { 245 return (await this.cachedCallFn(cacheOpt, 'GetProjectCfg', req)) as Project; 246 } 247 248 async queryRecentBuilds( 249 req: QueryRecentBuildsRequest, 250 cacheOpt: CacheOption = {}, 251 ) { 252 return (await this.cachedCallFn( 253 cacheOpt, 254 'QueryRecentBuilds', 255 req, 256 )) as QueryRecentBuildsResponse; 257 } 258 259 async listBuilders(req: ListBuildersRequest, cacheOpt: CacheOption = {}) { 260 return (await this.cachedCallFn( 261 cacheOpt, 262 'ListBuilders', 263 req, 264 )) as ListBuildersResponse; 265 } 266 267 async listProjects(req: ListProjectsRequest, cacheOpt: CacheOption = {}) { 268 return (await this.cachedCallFn( 269 cacheOpt, 270 'ListProjects', 271 req, 272 )) as ListProjectsResponse; 273 } 274 275 async queryBuilderStats( 276 req: QueryBuilderStatsRequest, 277 cacheOpt: CacheOption = {}, 278 ) { 279 return (await this.cachedCallFn( 280 cacheOpt, 281 'QueryBuilderStats', 282 req, 283 )) as BuilderStats; 284 } 285 286 async batchCheckPermissions( 287 req: BatchCheckPermissionsRequest, 288 cacheOpt: CacheOption = {}, 289 ) { 290 return (await this.cachedCallFn( 291 cacheOpt, 292 'BatchCheckPermissions', 293 req, 294 )) as BatchCheckPermissionsResponse; 295 } 296 297 async queryConsoles(req: QueryConsolesRequest, cacheOpt: CacheOption = {}) { 298 return (await this.cachedCallFn( 299 cacheOpt, 300 'QueryConsoles', 301 req, 302 )) as QueryConsolesResponse; 303 } 304 305 async queryConsoleSnapshots( 306 req: QueryConsoleSnapshotsRequest, 307 cacheOpt: CacheOption = {}, 308 ) { 309 return (await this.cachedCallFn( 310 cacheOpt, 311 'QueryConsoleSnapshots', 312 req, 313 )) as QueryConsoleSnapshotsResponse; 314 } 315 }