diff --git a/recipes/recipe_proto/turboci/README.md b/recipes/recipe_proto/turboci/README.md new file mode 100644 index 0000000000..b221686c33 --- /dev/null +++ b/recipes/recipe_proto/turboci/README.md @@ -0,0 +1,3 @@ +Generated by update.py. DO NOT EDIT. +These protos were copied from: +https://chromium.googlesource.com/infra/turboci/proto/+/0e5449fab915537e38bcc2e7fae25d54614d7c78/turboci/data/chrome/depot_tools diff --git a/recipes/recipe_proto/turboci/data/chrome/depot_tools/v1/bot_update_results.proto b/recipes/recipe_proto/turboci/data/chrome/depot_tools/v1/bot_update_results.proto new file mode 100644 index 0000000000..e2c3a82732 --- /dev/null +++ b/recipes/recipe_proto/turboci/data/chrome/depot_tools/v1/bot_update_results.proto @@ -0,0 +1,35 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto3"; +package turboci.data.chrome.depot_tools.v1; + +option go_package = "go.chromium.org/turboci/proto/go/data/chrome/depot_tools/v1;depot_toolspb"; +option java_multiple_files = true; + +// BotUpdateResults provides details about all of the repositories that were +// checked out. bot_update checks out one or more repositories to a common +// directory, each of which can have have additional repos checked out either +// via DEPS files or submodules and so on recursively. Any repo in the tree can +// have its revision overridden. +message BotUpdateResults { + // Information about the commit checked out for a repo (ignoring any patch + // applied). + message GitCommit { + // GoB host without the ".googlesource.com" hostname suffix as the + // suffix may be different depending on how it's accessed (eg. + // ".git.corp.google.com") while still referring to the same repo. + optional string host = 1; + // Repository name on the host, e.g. "chromium/src". + optional string project = 2; + // Commit ID (eg. HEX SHA1). + optional string id = 3; + } + + // The revision information for all git repos that bot_update checked out. The + // key is the path from the common directory where the checkout was performed, + // with the value providing information about the repository and revision that + // was checked out. + map manifest = 1; +} diff --git a/recipes/recipe_proto/turboci/update.py b/recipes/recipe_proto/turboci/update.py new file mode 100755 index 0000000000..b750ab9c5d --- /dev/null +++ b/recipes/recipe_proto/turboci/update.py @@ -0,0 +1,95 @@ +#!/usr/bin/env vpython3 +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Automatically updates the .proto files in this directory.""" + +import json +import os +import re +import tarfile + +from pathlib import Path + +import requests + +BASE_URL = 'https://chromium.googlesource.com/infra/turboci/proto' +LOG_URL = BASE_URL + '/+log/main/{}?format=JSON&n=1' +TAR_URL = BASE_URL + '/+archive/{}/{}.tar.gz' + +REPO_PATH = 'turboci/data/chrome/depot_tools' + + +def print_commit_message(prev_commit: str, target: str): + print('{0:=^80}'.format(' START[Commit Message] ')) + print('[TurboCI] Import latest protos.') + print() + changelog = f'{BASE_URL}/+log/{prev_commit}..{target}' + print(f'Changelog: {changelog}') + print() + clog = json.loads(requests.get(f'{changelog}?format=JSON').text[4:]) + for commit in clog['log']: + first_line = commit['message'].split('\n')[0] + print(f'{commit["commit"][:8]} {first_line}') + print() + print('{0:=^80}'.format(' END[Commit Message] ')) + + +def main(): + """Automatically updates the .proto files in this directory.""" + this_dir = Path(__file__).parent + + readme_path = this_dir / 'README.md' + + with open(readme_path, 'r') as rmd: + prev_commit = re.match(r'.*/([a-f0-9]{40})/.*', rmd.read(), + re.MULTILINE | re.DOTALL).group(1) + + to_remove = set() + for root, _, files in os.walk(this_dir): + for file in files: + if file.endswith('.proto'): + to_remove.add(Path(root) / file) + + resp = requests.get(LOG_URL.format(REPO_PATH)) + target = str(json.loads(resp.text[4:])['log'][0]['commit']) + + if prev_commit == target: + print('Nothing to update.') + return + + print(f'Updating to {target!r}') + + base_dir = this_dir.parent / REPO_PATH + resp = requests.get(TAR_URL.format(target, REPO_PATH), stream=True).raw + with tarfile.open(mode='r', fileobj=resp) as tar: + for item in tar: + if not item.name.endswith('.proto'): + continue + if item.name.endswith('_test.proto'): + print(f'Skipping {item.name!r}') + continue + if 'internal' in item.name or 'googleapis' in item.name: + print(f'Skipping {item.name!r}') + continue + print(f'Extracting {item.name!r}') + tar.extract(item, path=base_dir) + to_remove.discard(base_dir / item.name) + + if to_remove: + print('Removing stale proto') + for file in to_remove: + os.remove(file) + + with open(readme_path, 'w') as rmd: + print('Generated by update.py. DO NOT EDIT.', file=rmd) + print('These protos were copied from:', file=rmd) + print(f'{BASE_URL}/+/{target}/{REPO_PATH}', file=rmd) + + print_commit_message(prev_commit, target) + + print('Done.') + + +if __name__ == '__main__': + main()