| #!/usr/bin/env python3 |
| # Copyright 2023 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """A script to update the code base with new features for what's new. |
| |
| Sample use: |
| |
| python3 tools/whats_new/upload_whats_new_features.py |
| --milestone-absolute-path="/Users/foo/Downloads/M123" |
| |
| Run with --help to get a complete list of options this script runs with. |
| """ |
| |
| import os |
| import subprocess |
| import pandas as pd |
| import sys |
| import whats_new_util |
| import argparse |
| import time |
| |
| |
| def _CreateBranch(milestone: str) -> None: |
| try: |
| start = time.time() |
| command_git = ['git', 'checkout', '-b', f'whats_new_{milestone}'] |
| subprocess.run(command_git, check=True) |
| end = time.time() |
| execution_time = _GetExecutionTime(start, end) |
| print(f'The time of execution to create a branch: {execution_time}') |
| except subprocess.CalledProcessError as exc: |
| raise Exception(f'Failed to create a branch: {exc}') |
| |
| |
| def _FormatChanges() -> None: |
| try: |
| start = time.time() |
| command_git = ['git', 'cl', 'format'] |
| subprocess.run(command_git, check=True) |
| end = time.time() |
| execution_time = _GetExecutionTime(start, end) |
| print(f'The time of execution to format the changes: {execution_time}') |
| except subprocess.CalledProcessError as exc: |
| raise Exception(f'Failed to format changes: {exc}') |
| |
| |
| def _AddChangesToBranch() -> None: |
| command_git = ['git', 'add', '-A'] |
| try: |
| start = time.time() |
| subprocess.run(command_git, check=True) |
| end = time.time() |
| execution_time = _GetExecutionTime(start, end) |
| print('The time of execution to add the changes to the branch: ' |
| f'{execution_time}') |
| except subprocess.CalledProcessError as exc: |
| raise Exception(f'Failed to add changes to a branch: {exc}') |
| |
| |
| def _CommitChangesToBranch() -> None: |
| try: |
| start = time.time() |
| command_git = [ |
| 'git', 'commit', '-m', 'Add new features to What\'s New' |
| ] |
| subprocess.run(command_git, check=True) |
| end = time.time() |
| execution_time = _GetExecutionTime(start, end) |
| print('The time of execution to commit the changes to the branch: ' |
| f'{execution_time}') |
| except subprocess.CalledProcessError as exc: |
| raise Exception(f'Failed to commit the changes to a branch: {exc}') |
| |
| |
| def _UploadChangesToCL(message: str) -> None: |
| try: |
| start = time.time() |
| command_git = [ |
| 'git', 'cl', 'upload', '--bypass-hooks', '--bypass-watchlists', |
| '--force', '--message', message, '--cq-dry-run', '--auto-submit', |
| '-o', 'uploadvalidator~skip' |
| ] |
| subprocess.run(command_git, check=True) |
| end = time.time() |
| execution_time = _GetExecutionTime(start, end) |
| print('The time of execution to upload the changes to a cl: ' |
| f'{execution_time}') |
| except subprocess.CalledProcessError as exc: |
| raise Exception(f'Failed to upload the changes to a branch: {exc}') |
| |
| |
| def _AddFeature(index: int, feature_dict: dict[str, str], |
| path_to_milestone_folder: str) -> None: |
| start = time.time() |
| new_enum = whats_new_util.UpdateWhatsNewItemAndGetNewTypeValue( |
| feature_dict) |
| whats_new_util.UpdateWhatsNewPlist(feature_dict, new_enum) |
| whats_new_util.UpdateWhatsNewUtils(feature_dict) |
| whats_new_util.CopyAnimationFilesToResources(feature_dict, |
| path_to_milestone_folder) |
| whats_new_util.UpdateResourcesBuildFile(feature_dict) |
| whats_new_util.AddStrings(feature_dict, path_to_milestone_folder) |
| whats_new_util.UploadScreenshots(feature_dict, path_to_milestone_folder) |
| end = time.time() |
| execution_time = _GetExecutionTime(start, end) |
| print(f'The time of execution to add feature {index}: {execution_time}') |
| |
| |
| def _GetExecutionTime(start: float, end: float) -> str: |
| return f'{(end-start)*10**3:.03f}ms' |
| |
| |
| def main(): |
| start = time.time() |
| print('Start...') |
| parser = parser = argparse.ArgumentParser( |
| description=__doc__, |
| formatter_class=argparse.RawDescriptionHelpFormatter) |
| parser.add_argument( |
| '--milestone-absolute-path', |
| required=True, |
| help='Specify the absolute path to the milestone directory.') |
| args = parser.parse_args() |
| if not args.milestone_absolute_path: |
| raise ValueError('Missing input through --milestone-absolute-path.') |
| |
| milestone_folder_absolute_path = args.milestone_absolute_path |
| xlsx_file_path = os.path.join(milestone_folder_absolute_path, |
| 'whats_new_features.xlsx') |
| xlsx_content = pd.read_excel(xlsx_file_path) |
| milestone = xlsx_content.iloc[0]['Milestone'] |
| |
| #Create branch |
| _CreateBranch(milestone.lower()) |
| |
| # Delete existing features from the plist |
| whats_new_util.CleanUpFeaturesPlist() |
| features_name = [] |
| for index, feature_row in pd.DataFrame(xlsx_content).iterrows(): |
| feature_row.fillna('', inplace=True) |
| _AddFeature(index, feature_row, milestone_folder_absolute_path) |
| features_name.append(feature_row['Feature name']) |
| |
| # Update FET event |
| whats_new_util.UpdateWhatsNewFETEvent(milestone.lower()) |
| |
| # Prepare and upload changes |
| _FormatChanges() |
| _AddChangesToBranch() |
| _CommitChangesToBranch() |
| |
| comment_builder = [] |
| comment_builder.append( |
| f'[iOS][WhatsNew] Add new features for {milestone}\n') |
| comment_builder.append( |
| 'This CL adds the following features to What\'s New:') |
| comment_builder.append('\n'.join(features_name)) |
| _UploadChangesToCL('\n'.join(comment_builder)) |
| |
| end = time.time() |
| execution_time = _GetExecutionTime(start, end) |
| print(f'The total time of execution: {execution_time}') |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |