From 6eed684a8b417aab3e402a110792b6152bca8cb5 Mon Sep 17 00:00:00 2001 From: Brian Sheedy Date: Tue, 16 May 2023 23:36:12 +0000 Subject: [PATCH] Add milestones script Adds a script to help with adding or removing Dawn milestones. Bug: chromium:1432491 Change-Id: I0882503f4ceb7ba3454e13ec1669c053055ac975 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/133165 Kokoro: Kokoro Commit-Queue: Brian Sheedy Reviewed-by: Garrett Beaty Reviewed-by: Austin Eng --- infra/config/scripts/milestones.py | 143 +++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100755 infra/config/scripts/milestones.py diff --git a/infra/config/scripts/milestones.py b/infra/config/scripts/milestones.py new file mode 100755 index 0000000000..4fe71f73f6 --- /dev/null +++ b/infra/config/scripts/milestones.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 +# +# Copyright 2023 The Dawn Authors +# +# 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. +"""Script for updating the active milestones for the Dawn project. + +This is largely based on the Chromium equivalent in +chromium/src/infra/config/scripts/milestones.py. + +To activate a new branch, run the following from the root of the repo (where MMM +is the milestone number and BBBB is the branch number): +``` +infra/config/scripts/milestones.py activate --milestone MMM --branch BBBB +infra/config/global/main.star +``` + +To deactivate a branch, run the following from the root of the repo (where MMM +is the milestone number): +``` +infra/config/scripts/milestones.py deactivate --milestone MMM +infra/config/global/main.star +``` +""" + +import argparse +import json +import os + +INFRA_CONFIG_GLOBAL_DIR = os.path.realpath( + os.path.join(os.path.dirname(__file__), '..', 'global')) + + +def parse_args(): + parser = argparse.ArgumentParser( + description='Update the active milestones for the Dawn project') + parser.set_defaults(func=None) + parser.add_argument('--milestones-json', + default=os.path.join(INFRA_CONFIG_GLOBAL_DIR, + 'milestones.json'), + help='Path to the milestones.json file to modify') + + subparsers = parser.add_subparsers() + + activate_parser = subparsers.add_parser( + 'activate', help='Add an additional active milestone.') + activate_parser.set_defaults(func=cmd_activate) + activate_parser.add_argument( + '--milestone', + required=True, + type=int, + help='The milestone identifier/release channel number') + activate_parser.add_argument( + '--branch', + required=True, + help='The branch name, which should correspond to a ref in refs/heads') + + deactivate_parser = subparsers.add_parser( + 'deactivate', help='Remove an active milestone') + deactivate_parser.set_defaults(func=cmd_deactivate) + deactivate_parser.add_argument( + '--milestone', + required=True, + type=int, + help='The milestone identifier/release channel number') + + args = parser.parse_args() + if not args.func: + parser.error('No sub-command specified') + return args + + +def _sort_milestones(milestones): + # We have to manually sort here instead of relying on + # json.dump(..., sort_keys=True) later since we only want to sort the top + # level keys, not all keys. + milestones = { + str(k): milestones[str(k)] + for k in sorted([int(s) for s in milestones]) + } + return milestones + + +def add_milestone(milestones, milestone_num, branch): + if str(milestone_num) in milestones: + raise RuntimeError('Milestone %d already exists' % milestone_num) + + milestones[str(milestone_num)] = { + 'name': f'm{milestone_num}', + 'chromium_project': f'chromium-m{milestone_num}', + 'ref': f'refs/heads/{branch}', + 'platforms': [ + 'linux', + 'mac', + 'win', + ], + } + + return _sort_milestones(milestones) + + +def remove_milestone(milestones, milestone_num): + if str(milestone_num) not in milestones: + raise RuntimeError('Milestone %d does not exist' % milestone_num) + del milestones[str(milestone_num)] + # Not strictly necessary, but returning a value keeps this consistent with + # add_milestone. + return milestones + + +def cmd_activate(args): + with open(args.milestones_json) as infile: + milestones = json.load(infile) + milestones = add_milestone(milestones, args.milestone, args.branch) + with open(args.milestones_json, 'w') as outfile: + json.dump(milestones, outfile, indent=4) + + +def cmd_deactivate(args): + with open(args.milestones_json) as infile: + milestones = json.load(infile) + milestones = remove_milestone(milestones, args.milestone) + with open(args.milestones_json, 'w') as outfile: + json.dump(milestones, outfile, indent=4) + + +def main(): + args = parse_args() + args.func(args) + + +if __name__ == '__main__': + main()