From 1398a8e28fff7cea7ad3b13ffc84bd2c26d60348 Mon Sep 17 00:00:00 2001 From: Tom Prince Date: Tue, 16 Oct 2018 23:04:03 +0000 Subject: [PATCH] Bug 1497575: [staging-release] Add try subcommand to create a push for staging releases; r=aki,ahal This adds `mach try release` which adds temporary changes to enable staging release to run. Differential Revision: https://phabricator.services.mozilla.com/D8625 --HG-- extra : moz-landing-system : lando --- taskcluster/taskgraph/decision.py | 16 +++++--- tools/moz.build | 3 ++ tools/tryselect/mach_commands.py | 10 +++++ tools/tryselect/push.py | 34 +++++++++++----- tools/tryselect/selectors/release.py | 61 ++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 16 deletions(-) create mode 100644 tools/tryselect/selectors/release.py diff --git a/taskcluster/taskgraph/decision.py b/taskcluster/taskgraph/decision.py index eb5090045520..2a16c17314c9 100644 --- a/taskcluster/taskgraph/decision.py +++ b/taskcluster/taskgraph/decision.py @@ -282,14 +282,20 @@ def get_decision_parameters(config, options): def set_try_config(parameters, task_config_file): - parameters['try_mode'] = None if os.path.isfile(task_config_file): logger.info("using try tasks from {}".format(task_config_file)) - parameters['try_mode'] = 'try_task_config' with open(task_config_file, 'r') as fh: - parameters['try_task_config'] = json.load(fh) - else: - parameters['try_task_config'] = None + task_config = json.load(fh) + task_config_version = task_config.get('version', 1) + if task_config_version == 1: + parameters['try_mode'] = 'try_task_config' + parameters['try_task_config'] = task_config + elif task_config_version == 2: + parameters.update(task_config['parameters']) + return + else: + raise Exception( + "Unknown `try_task_config.json` version: {}".format(task_config_version)) if 'try:' in parameters['message']: parameters['try_mode'] = 'try_option_syntax' diff --git a/tools/moz.build b/tools/moz.build index 94e94a48bce9..f59433eaf78c 100644 --- a/tools/moz.build +++ b/tools/moz.build @@ -41,6 +41,9 @@ with Files("rewriting/**"): with Files("tryselect/**"): BUG_COMPONENT = ("Testing", "General") +with Files("tryselect/selectors/release.py"): + BUG_COMPONENT = ("Release Engineering", "General") + with Files("update-packaging/**"): BUG_COMPONENT = ("Release Engineering", "Other") diff --git a/tools/tryselect/mach_commands.py b/tools/tryselect/mach_commands.py index 25dc1cb867e1..2089c2fadd86 100644 --- a/tools/tryselect/mach_commands.py +++ b/tools/tryselect/mach_commands.py @@ -234,3 +234,13 @@ class TrySelect(MachCommandBase): at = AutoTry(self.topsrcdir, self._mach_context) return at.run(**kwargs) + + @SubCommand('try', + 'release', + description='Push the current tree to try, configured for a staging release.', + parser=get_parser('release')) + def try_release(self, **kwargs): + """Push the current tree to try, configured for a staging release. + """ + from tryselect.selectors.release import run_try_release + return run_try_release(**kwargs) diff --git a/tools/tryselect/push.py b/tools/tryselect/push.py index 6e95d618c217..f36abf99437d 100644 --- a/tools/tryselect/push.py +++ b/tools/tryselect/push.py @@ -52,7 +52,7 @@ old_history_path = os.path.join(get_state_dir()[0], 'history', 'try_task_configs def write_task_config(try_task_config): config_path = os.path.join(vcs.path, 'try_task_config.json') with open(config_path, 'w') as fh: - json.dump(try_task_config, fh, indent=2, separators=(',', ':')) + json.dump(try_task_config, fh, indent=4, separators=(',', ': ')) fh.write('\n') return config_path @@ -82,7 +82,7 @@ def check_working_directory(push=True): def push_to_try(method, msg, labels=None, templates=None, try_task_config=None, - push=True, closed_tree=False): + push=True, closed_tree=False, files_to_change=None): check_working_directory(push) # Format the commit message @@ -91,28 +91,40 @@ def push_to_try(method, msg, labels=None, templates=None, try_task_config=None, (msg, closed_tree_string, method)) if labels or labels == []: - try_task_config = {'tasks': sorted(labels)} + try_task_config = { + 'version': 1, + 'tasks': sorted(labels), + } if templates: try_task_config['templates'] = templates if push: write_task_config_history(msg, try_task_config) - config = None + config_path = None + changed_files = [] if try_task_config: - config = write_task_config(try_task_config) + config_path = write_task_config(try_task_config) + changed_files.append(config_path) + + if files_to_change: + for path, content in files_to_change.items(): + path = os.path.join(vcs.path, path) + with open(path, 'w') as fh: + fh.write(content) + changed_files.append(path) try: if not push: print("Commit message:") print(commit_message) - if config: + if config_path: print("Calculated try_task_config.json:") - with open(config) as fh: + with open(config_path) as fh: print(fh.read()) return - if config: - vcs.add_remove_files(config) + for path in changed_files: + vcs.add_remove_files(path) try: vcs.push_to_try(commit_message) @@ -125,5 +137,5 @@ def push_to_try(method, msg, labels=None, templates=None, try_task_config=None, raise sys.exit(1) finally: - if config and os.path.isfile(config): - os.remove(config) + if config_path and os.path.isfile(config_path): + os.remove(config_path) diff --git a/tools/tryselect/selectors/release.py b/tools/tryselect/selectors/release.py new file mode 100644 index 000000000000..716b33b86977 --- /dev/null +++ b/tools/tryselect/selectors/release.py @@ -0,0 +1,61 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +from __future__ import absolute_import, print_function, unicode_literals + +import attr +from mozilla_version.gecko import FirefoxVersion + +from ..cli import BaseTryParser +from ..push import push_to_try + + +class ReleaseParser(BaseTryParser): + name = 'release' + arguments = [ + [['-v', '--version'], + {'metavar': 'STR', + 'required': True, + 'action': 'store', + 'type': FirefoxVersion.parse, + 'help': "The version number to use for the staging release.", + }], + ] + common_groups = ['push'] + + +def run_try_release(version, push=True, message='{msg}', **kwargs): + + if version.is_beta: + app_version = attr.evolve(version, beta_number=None) + else: + app_version = version + + files_to_change = { + 'browser/config/version.txt': '{}\n'.format(app_version), + 'browser/config/version_display.txt': '{}\n'.format(version), + } + + release_type = version.version_type.name.lower() + if release_type not in ('beta', 'release', 'esr'): + raise Exception( + "Can't do staging release for version: {} type: {}".format( + version, version.version_type)) + task_config = { + 'version': 2, + 'parameters': { + 'target_tasks_method': 'staging_release_builds', + 'optimize_target_tasks': True, + 'include_nightly': True, + 'release_type': release_type, + }, + } + + msg = 'staging release: {}'.format(version) + return push_to_try( + 'release', message.format(msg=msg), + push=push, closed_tree=kwargs["closed_tree"], + try_task_config=task_config, + files_to_change=files_to_change, + )