From 97257cfab2c9879d622cb4ba5595c845e4182138 Mon Sep 17 00:00:00 2001 From: Dana Dahlstrom Date: Tue, 28 Nov 2023 18:00:00 -0800 Subject: [PATCH] Accept Git trailer Build-Id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … in place of Piper tag BUILD_NUMBER, to avoid corrupting Git trailers. Issue: 296119824 Reviewed-on: https://github.com/youtube/cobalt/pull/2013 (cherry picked from commit 0e24f1d5c0d71c523c22541dd5192c8e762d21d7) --- cobalt/build/build_info.py | 132 +++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100755 cobalt/build/build_info.py diff --git a/cobalt/build/build_info.py b/cobalt/build/build_info.py new file mode 100755 index 000000000000..51172faeed9b --- /dev/null +++ b/cobalt/build/build_info.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# Copyright 2023 The Cobalt Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Generates a Cobalt Build Info json.""" + +import datetime +import json +import os +import re +import subprocess +import sys + +FILE_DIR = os.path.dirname(__file__) +COMMIT_COUNT_BUILD_ID_OFFSET = 1000000 + +_BUILD_ID_PATTERN = '^(Build-Id: |BUILD_NUMBER=)([1-9][0-9]{6,})$' +_GIT_REV_PATTERN = '^GitOrigin-RevId: ([0-9a-f]{40})$' +_COBALT_VERSION_PATTERN = '^#define COBALT_VERSION "(.*)"$' + + +def get_build_id_and_git_rev_from_commits(cwd): + # Build id and git rev must come from the same commit. + output = subprocess.check_output( + ['git', 'log', '--grep', _BUILD_ID_PATTERN, '-1', '-E', '--pretty=%b'], + cwd=cwd).decode() + + # Gets build id. + compiled_build_id_pattern = re.compile(_BUILD_ID_PATTERN, flags=re.MULTILINE) + match_build_id = compiled_build_id_pattern.search(output) + if not match_build_id: + return None, None + build_id = match_build_id.group(2) + + # Gets git rev. + compiled_git_rev_pattern = re.compile(_GIT_REV_PATTERN, flags=re.MULTILINE) + match_git_rev = compiled_git_rev_pattern.search(output) + if not match_git_rev: + git_rev = '' + else: + git_rev = match_git_rev.group(1) + + return build_id, git_rev + + +def get_build_id_from_commit_count(cwd): + output = subprocess.check_output(['git', 'rev-list', '--count', 'HEAD'], + cwd=cwd) + build_id = int(output.strip().decode()) + COMMIT_COUNT_BUILD_ID_OFFSET + return str(build_id) + + +def _get_last_commit_with_format(placeholder, cwd): + output = subprocess.check_output( + ['git', 'log', '-1', f'--pretty=format:{placeholder}'], cwd=cwd) + return output.strip().decode() + + +def _get_hash_from_last_commit(cwd): + return _get_last_commit_with_format(r'%H', cwd=cwd) + + +def _get_author_from_last_commit(cwd): + return _get_last_commit_with_format(r'%an', cwd=cwd) + + +def _get_subject_from_last_commit(cwd): + return _get_last_commit_with_format(r'%s', cwd=cwd) + + +def _get_cobalt_version(): + version_header_path = os.path.join(os.path.dirname(FILE_DIR), 'version.h') + contents = '' + with open(version_header_path, 'r', encoding='utf-8') as f: + contents = f.read() + compiled_cobalt_version_pattern = re.compile( + _COBALT_VERSION_PATTERN, flags=re.MULTILINE) + return compiled_cobalt_version_pattern.search(contents).group(1) + + +def main(output_path, cwd=FILE_DIR): + """Writes a Cobalt build_info json file.""" + build_rev = _get_hash_from_last_commit(cwd=cwd) + build_id, git_rev = get_build_id_and_git_rev_from_commits(cwd=cwd) + if build_id is None: + build_id = get_build_id_from_commit_count(cwd=cwd) + git_rev = build_rev + cobalt_version = _get_cobalt_version() + build_time = datetime.datetime.now().ctime() + author = _get_author_from_last_commit(cwd=cwd) + commit = _get_subject_from_last_commit(cwd=cwd) + + info_json = { + 'build_id': build_id, + 'build_rev': build_rev, + 'git_rev': git_rev, + 'cobalt_version': cobalt_version, + 'build_time': build_time, + 'author': author, + 'commit': commit + } + + with open(output_path, 'w', encoding='utf-8') as f: + f.write(json.dumps(info_json, indent=4)) + + # Supports legacy build_info.txt. + output_text_path = os.path.join( + os.path.dirname(output_path), 'build_info.txt') + with open(output_text_path, 'w', encoding='utf-8') as f: + f.write(f'''\ +Build ID: {build_id} +Build Rev: {build_rev} +Git Rev: {git_rev} +Cobalt Version: {cobalt_version} +Build Time: {build_time} +Author: {author} +Commit: {commit} +''') + + +if __name__ == '__main__': + main(sys.argv[1])