Commit efd97bc9 authored by Garrett Beaty's avatar Garrett Beaty Committed by Chromium LUCI CQ

Add a script for updating the configuration for branch projects.

Bug: 1165826
Change-Id: Ie08cc5bcfa6ad53cf92e00f95a0564842f0ff6c9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2625272
Commit-Queue: Garrett Beaty <gbeaty@chromium.org>
Reviewed-by: default avatarMichael Moss <mmoss@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843794}
parent 8d99429f
...@@ -34,19 +34,7 @@ def _project_settings( ...@@ -34,19 +34,7 @@ def _project_settings(
ref = ref, ref = ref,
) )
settings = _project_settings( settings = _project_settings(**json.decode(io.read_file("./settings.json")))
# Set this to the name of the milestone's project
project = "chromium",
# Set this to how the project should be referred to in a title context (e.g.
# for project chromium-mXX, the project title would be Chromium MXX)
project_title = "Chromium",
# Set this to False for branches
is_master = True,
# Set this to True for LTC/LTS branches
is_lts_branch = False,
# Set this to the branch ref for branches
ref = "refs/heads/master",
)
def _generate_project_pyl(ctx): def _generate_project_pyl(ctx):
ctx.output["project.pyl"] = "\n".join([ ctx.output["project.pyl"] = "\n".join([
......
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""PRESUBMIT for scripts.
See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details on the presubmit API built into depot_tools.
"""
PRESUBMIT_VERSION = '2.0.0'
def CheckTests(input_api, output_api):
glob = input_api.os_path.join(
input_api.PresubmitLocalPath(), 'tests', '*_test.py')
tests = input_api.canned_checks.GetUnitTests(
input_api, output_api, input_api.glob(glob), run_on_python2=False)
return input_api.RunTests(tests)
#!/usr/bin/env python3
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Script for updating the project settings for a chromium branch.
To initialize a new chromium branch, run the following from the root of
the repo (where MM is the milestone number and BBBB is the branch
number):
```
infra/config/scripts/branch.py initialize --milestone MM --branch BBBB
infra/config/main.star
infra/config/dev.star
```
Usage:
branch.py initialize --milestone XX --branch YYYY
"""
import argparse
import json
import os
import sys
INFRA_CONFIG_DIR = os.path.abspath(os.path.join(__file__, '..', '..'))
def parse_args(args=None, *, parser_type=None):
parser_type = parser_type or argparse.ArgumentParser
parser = parser_type(
description='Update the project settings for a chromium branch')
parser.set_defaults(func=None)
parser.add_argument('--settings-json',
help='Path to the settings.json file',
default=os.path.join(INFRA_CONFIG_DIR, 'settings.json'))
subparsers = parser.add_subparsers()
init_parser = subparsers.add_parser(
'initialize', help='Initialize the settings for a branch')
init_parser.set_defaults(func=initialize_cmd)
init_parser.add_argument(
'--milestone',
required=True,
help=('The milestone identifier '
'(e.g. the milestone number for standard release channel)'))
init_parser.add_argument(
'--branch',
required=True,
help='The branch name, must correspond to a ref in refs/branch-heads')
args = parser.parse_args(args)
if args.func is None:
parser.error('no sub-command specified')
return args
def initial_settings(milestone, branch):
settings = dict(
project=f'chromium-m{milestone}',
project_title=f'Chromium M{milestone}',
is_master=False,
is_lts_branch=False,
ref=f'refs/branch-heads/{branch}',
)
return json.dumps(settings, indent=4) + '\n'
def initialize_cmd(args):
settings = initial_settings(args.milestone, args.branch)
with open(args.settings_json, 'w') as f:
f.write(settings)
def main():
args = parse_args()
args.func(args)
if __name__ == '__main__':
main()
\ No newline at end of file
#!/usr/bin/env python3
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Integration test for branch.py"""
import json
import os
import subprocess
import tempfile
import textwrap
import unittest
INFRA_CONFIG_DIR = os.path.abspath(os.path.join(__file__, '..', '..', '..'))
BRANCH_PY = os.path.join(INFRA_CONFIG_DIR, 'scripts', 'branch.py')
class BranchIntegrationTest(unittest.TestCase):
def setUp(self):
self._temp_dir = tempfile.TemporaryDirectory()
self._settings_json = os.path.join(self._temp_dir.name, 'settings.json')
def tearDown(self):
self._temp_dir.cleanup()
def _execute_branch_py(self, args):
return subprocess.run(
[BRANCH_PY, '--settings-json', self._settings_json] + (args or []),
text=True, capture_output=True)
def test_initialize_fails_when_missing_required_args(self):
result = self._execute_branch_py(['initialize'])
self.assertNotEqual(result.returncode, 0)
self.assertIn(
'the following arguments are required: --milestone, --branch',
result.stderr)
def test_initialize_rewrites_settings_json(self):
result = self._execute_branch_py(
['initialize', '--milestone', 'XX', '--branch', 'YYYY'])
self.assertEqual(
result.returncode, 0,
(f'subprocess failed\n***COMMAND***\n{result.args}\n'
f'***STDERR***\n{result.stderr}\n'))
with open(self._settings_json) as f:
settings = f.read()
self.assertEqual(settings, textwrap.dedent("""\
{
"project": "chromium-mXX",
"project_title": "Chromium MXX",
"is_master": false,
"is_lts_branch": false,
"ref": "refs/branch-heads/YYYY"
}
"""))
if __name__ == '__main__':
unittest.main()
\ No newline at end of file
#!/usr/bin/env python3
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit test for branch.py"""
import argparse
import os
import sys
import textwrap
import unittest
INFRA_CONFIG_DIR = os.path.abspath(os.path.join(__file__, '..', '..', '..'))
sys.path.append(os.path.join(INFRA_CONFIG_DIR, 'scripts'))
import branch
class ParseError(Exception):
pass
class ArgumentParser(argparse.ArgumentParser):
"""Test version of ArgumentParser
This behaves the same as argparse.ArgumentParser except that the error
method raises an instance of ParseError rather than printing output
and exiting. This simplifies testing for error conditions and puts the
actual error information in the traceback for unexpectedly failing
tests.
"""
def error(self, message):
raise ParseError(message)
class BranchUnitTest(unittest.TestCase):
def test_parse_args_fails_without_subcommand(self):
with self.assertRaises(ParseError) as caught:
branch.parse_args([], parser_type=ArgumentParser)
self.assertEqual(str(caught.exception), 'no sub-command specified')
def test_initialize_parse_args_fails_when_missing_required_args(self):
with self.assertRaises(ParseError) as caught:
branch.parse_args(['initialize'], parser_type=ArgumentParser)
self.assertEqual(
str(caught.exception),
'the following arguments are required: --milestone, --branch')
def test_initialize_parse_args(self):
args = branch.parse_args(
['initialize', '--milestone', 'MM', '--branch', 'BBBB'],
parser_type=ArgumentParser)
self.assertEqual(args.milestone, 'MM')
self.assertEqual(args.branch, 'BBBB')
def test_initial_settings(self):
output = branch.initial_settings(milestone='MM', branch='BBBB')
self.assertEqual(output, textwrap.dedent("""\
{
"project": "chromium-mMM",
"project_title": "Chromium MMM",
"is_master": false,
"is_lts_branch": false,
"ref": "refs/branch-heads/BBBB"
}
"""))
if __name__ == '__main__':
unittest.main()
\ No newline at end of file
{
"project": "chromium",
"project_title": "Chromium",
"is_master": true,
"is_lts_branch": false,
"ref": "refs/heads/master"
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment