gecko-dev/tools/tryselect/push.py
Tom Prince 770166e1f5 Bug 1562287: Allow setting other try_task_config settings than templates; r=ahal
Templates invoke the `morph` logic, which is somewhat confusing and inflexible.
Update the machinery to support setting other `try_task_config` values.

Differential Revision: https://phabricator.services.mozilla.com/D36364

--HG--
extra : moz-landing-system : lando
2019-07-04 06:25:18 +00:00

146 lines
4.2 KiB
Python

# 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
import json
import os
import sys
from mozboot.util import get_state_dir
from mozbuild.base import MozbuildObject
from mozversioncontrol import get_repository_object, MissingVCSExtension
GIT_CINNABAR_NOT_FOUND = """
Could not detect `git-cinnabar`.
The `mach try` command requires git-cinnabar to be installed when
pushing from git. Please install it by running:
$ ./mach vcs-setup
""".lstrip()
HG_PUSH_TO_TRY_NOT_FOUND = """
Could not detect `push-to-try`.
The `mach try` command requires the push-to-try extension enabled
when pushing from hg. Please install it by running:
$ ./mach vcs-setup
""".lstrip()
VCS_NOT_FOUND = """
Could not detect version control. Only `hg` or `git` are supported.
""".strip()
UNCOMMITTED_CHANGES = """
ERROR please commit changes before continuing
""".strip()
MAX_HISTORY = 10
here = os.path.abspath(os.path.dirname(__file__))
build = MozbuildObject.from_environment(cwd=here)
vcs = get_repository_object(build.topsrcdir)
history_path = os.path.join(get_state_dir(srcdir=True), 'history', 'try_task_configs.json')
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=4, separators=(',', ': '), sort_keys=True)
fh.write('\n')
return config_path
def write_task_config_history(msg, try_task_config):
if not os.path.isfile(history_path):
if not os.path.isdir(os.path.dirname(history_path)):
os.makedirs(os.path.dirname(history_path))
history = []
else:
with open(history_path, 'r') as fh:
history = fh.read().strip().splitlines()
history.insert(0, json.dumps([msg, try_task_config]))
history = history[:MAX_HISTORY]
with open(history_path, 'w') as fh:
fh.write('\n'.join(history))
def check_working_directory(push=True):
if not push:
return
if not vcs.working_directory_clean():
print(UNCOMMITTED_CHANGES)
sys.exit(1)
def generate_try_task_config(method, labels, try_config=None):
try_task_config = try_config or {}
templates = try_task_config.setdefault('templates', {})
templates.setdefault('env', {}).update({'TRY_SELECTOR': method})
try_task_config.update({
'version': 1,
'tasks': sorted(labels),
})
return try_task_config
def push_to_try(method, msg, try_task_config=None,
push=True, closed_tree=False, files_to_change=None):
check_working_directory(push)
# Format the commit message
closed_tree_string = " ON A CLOSED TREE" if closed_tree else ""
commit_message = ('%s%s\n\nPushed via `mach try %s`' %
(msg, closed_tree_string, method))
config_path = None
changed_files = []
if try_task_config:
if push and method != 'again':
write_task_config_history(msg, 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_path:
print("Calculated try_task_config.json:")
with open(config_path) as fh:
print(fh.read())
return
for path in changed_files:
vcs.add_remove_files(path)
try:
vcs.push_to_try(commit_message)
except MissingVCSExtension as e:
if e.ext == 'push-to-try':
print(HG_PUSH_TO_TRY_NOT_FOUND)
elif e.ext == 'cinnabar':
print(GIT_CINNABAR_NOT_FOUND)
else:
raise
sys.exit(1)
finally:
if config_path and os.path.isfile(config_path):
os.remove(config_path)