skia2/infra/bots/recipes.py
Robert Iannucci 654dfeeace Manually roll recipes (trivial)
Also converts recipes.cfg to new JSONPB format.

build:
  https://crrev.com/cf2a231cfaea22f03affe7d3ccdf8634d35a855d flutter: rename libsky_shell.so to libflutter.so
  https://crrev.com/47f1d3af26e30e7120f18450f28dd9ad095f69ba Roll recipe dependencies (trivial).
  https://crrev.com/67b26be7760cdce0e165e39e3d7cc88101725429 Allow passing arg to `repo sync` in chromite module
  https://crrev.com/6b2f23904dfb05b0b382cea4a9db373ec1041696 chromium: Adding tansell@chromium.org as OWNER for Chromium recipes.
  https://crrev.com/3966f1d05c265be673d4a4e52983370680bd2741 Dart: Add gclient runhooks to SDK builder recipe.
  https://crrev.com/3f370ccee1f85de227a40a27f384b1fd47811148 Install goma for cbuildbots.
  https://crrev.com/c9ea42272c232c77bffb476a64243ca6663fff44 Roll recipe dependencies (trivial).
  https://crrev.com/2458a11e565207234a11f0745b6c04c042e7d636 Roll recipe dependencies (trivial).
  https://crrev.com/c255c84a5881e193dcc7c6037cc37badb35c26c9 flutter: rename sky_shell to flutter_tester
  https://crrev.com/49099195df9831c746bc6437aea4b50bce14965d chromite: Change cbuildbot/api to to cbuildbot_launch.
  https://crrev.com/0ce9a9f88802d6be5e016b8a4efc190a21441e29 Roll recipe dependencies (trivial).
  https://crrev.com/e2406a2458aa7697979d6df86e92892077f16822 Roll recipe dependencies (trivial).

depot_tools:
  https://crrev.com/2e401be12ef1ec44f4a81c6bc8acaf793c71e4de Roll recipe dependencies (trivial).
  https://crrev.com/8b5b594115480a6b4c4bbe384cc7afaecd814a4b add "generic" infra path config
  https://crrev.com/284e34ae2878ddd2cda671554b444db8512fa2ab Revert "add "generic" infra path config"
  https://crrev.com/f7023e7cf0a6606080d9f53c5a9e6e8271443914 Roll recipe dependencies (trivial).
  https://crrev.com/757f20796948ff4a9264dad5293bdff2f94d9c43 Reland: add "generic" infra path config
  https://crrev.com/e663133f6f2695efba0705e82ee581f6eb424e6c Roll recipe dependencies (trivial).

recipe_engine:
  https://crrev.com/51395b1ba1ea684f5e99d2bb03c934f2ac441984 [recipes.cfg] ONLY support jsonpb.
  https://crrev.com/230fcdf5d57a084071e3617885b3286353ab1350 [package.proto] add options for autoroller recipe to recipes.cfg.
  https://crrev.com/8ec7b6d3ca59e7c178ad1b03e4408da556fddafa [recipes.cfg] set canonical_url and autoroller options

Bug:

Change-Id: I8308cf3633258703a3bd24ab49bf6e0db6c87cc9
Reviewed-on: https://skia-review.googlesource.com/10242
Reviewed-by: Eric Boren <borenet@google.com>
Commit-Queue: Eric Boren <borenet@google.com>
2017-03-28 11:51:16 +00:00

172 lines
5.9 KiB
Python
Executable File

#!/usr/bin/env python
# Copyright 2016 The LUCI Authors. All rights reserved.
# Use of this source code is governed under the Apache License, Version 2.0
# that can be found in the LICENSE file.
"""Bootstrap script to clone and forward to the recipe engine tool.
***********************************************************************
** DO NOT MODIFY EXCEPT IN THE PER-REPO CONFIGURATION SECTION BELOW. **
***********************************************************************
This is a copy of https://github.com/luci/recipes-py/blob/master/doc/recipes.py.
To fix bugs, fix in the github repo then copy it back to here and fix the
PER-REPO CONFIGURATION section to look like this one.
"""
import os
# IMPORTANT: Do not alter the header or footer line for the
# "PER-REPO CONFIGURATION" section below, or the autoroller will not be able
# to automatically update this file! All lines between the header and footer
# lines will be retained verbatim by the autoroller.
#### PER-REPO CONFIGURATION (editable) ####
# The root of the repository relative to the directory of this file.
REPO_ROOT = os.path.join(os.pardir, os.pardir)
# The path of the recipes.cfg file relative to the root of the repository.
RECIPES_CFG = os.path.join('infra', 'config', 'recipes.cfg')
#### END PER-REPO CONFIGURATION ####
BOOTSTRAP_VERSION = 1
import argparse
import json
import logging
import random
import subprocess
import sys
import time
import urlparse
from cStringIO import StringIO
def parse(repo_root, recipes_cfg_path):
"""Parse is transitional code which parses a recipes.cfg file as either jsonpb
or as textpb.
Args:
repo_root (str) - native path to the root of the repo we're trying to run
recipes for.
recipes_cfg_path (str) - native path to the recipes.cfg file to process.
Returns (as tuple):
engine_url (str) - the url to the engine repo we want to use.
engine_revision (str) - the git revision for the engine to get.
engine_subpath (str) - the subdirectory in the engine repo we should use to
find it's recipes.py entrypoint. This is here for completeness, but will
essentially always be empty. It would be used if the recipes-py repo was
merged as a subdirectory of some other repo and you depended on that
subdirectory.
recipes_path (str) - native path to where the recipes live inside of the
current repo (i.e. the folder containing `recipes/` and/or
`recipe_modules`)
"""
with open(recipes_cfg_path, 'rU') as fh:
pb = json.load(fh)
engine = next(
(d for d in pb['deps'] if d['project_id'] == 'recipe_engine'), None)
if engine is None:
raise ValueError('could not find recipe_engine dep in %r'
% recipes_cfg_path)
engine_url = engine['url']
engine_revision = engine.get('revision', '')
engine_subpath = engine.get('path_override', '')
recipes_path = pb.get('recipes_path', '')
recipes_path = os.path.join(repo_root, recipes_path.replace('/', os.path.sep))
return engine_url, engine_revision, engine_subpath, recipes_path
def _subprocess_call(argv, **kwargs):
logging.info('Running %r', argv)
return subprocess.call(argv, **kwargs)
def _subprocess_check_call(argv, **kwargs):
logging.info('Running %r', argv)
subprocess.check_call(argv, **kwargs)
def find_engine_override(argv):
"""Since the bootstrap process attempts to defer all logic to the recipes-py
repo, we need to be aware if the user is overriding the recipe_engine
dependency. This looks for and returns the overridden recipe_engine path, if
any, or None if the user didn't override it."""
PREFIX = 'recipe_engine='
p = argparse.ArgumentParser()
p.add_argument('-O', '--project-override', action='append')
args, _ = p.parse_known_args(argv)
for override in args.project_override or ():
if override.startswith(PREFIX):
return override[len(PREFIX):]
return None
def main():
if '--verbose' in sys.argv:
logging.getLogger().setLevel(logging.INFO)
if REPO_ROOT is None or RECIPES_CFG is None:
logging.error(
'In order to use this script, please copy it to your repo and '
'replace the REPO_ROOT and RECIPES_CFG values with approprite paths.')
sys.exit(1)
if sys.platform.startswith(('win', 'cygwin')):
git = 'git.bat'
else:
git = 'git'
# Find the repository and config file to operate on.
repo_root = os.path.abspath(
os.path.join(os.path.dirname(__file__), REPO_ROOT))
recipes_cfg_path = os.path.join(repo_root, RECIPES_CFG)
engine_url, engine_revision, engine_subpath, recipes_path = parse(
repo_root, recipes_cfg_path)
engine_path = find_engine_override(sys.argv[1:])
if not engine_path and engine_url.startswith('file://'):
engine_path = urlparse.urlparse(engine_url).path
if not engine_path:
deps_path = os.path.join(recipes_path, '.recipe_deps')
# Ensure that we have the recipe engine cloned.
engine_root_path = os.path.join(deps_path, 'recipe_engine')
engine_path = os.path.join(engine_root_path, engine_subpath)
def ensure_engine():
if not os.path.exists(deps_path):
os.makedirs(deps_path)
if not os.path.exists(engine_root_path):
_subprocess_check_call([git, 'clone', engine_url, engine_root_path])
needs_fetch = _subprocess_call(
[git, 'rev-parse', '--verify', '%s^{commit}' % engine_revision],
cwd=engine_root_path, stdout=open(os.devnull, 'w'))
if needs_fetch:
_subprocess_check_call([git, 'fetch'], cwd=engine_root_path)
_subprocess_check_call(
[git, 'checkout', '--quiet', engine_revision], cwd=engine_root_path)
try:
ensure_engine()
except subprocess.CalledProcessError:
logging.exception('ensure_engine failed')
# Retry errors.
time.sleep(random.uniform(2,5))
ensure_engine()
args = ['--package', recipes_cfg_path] + sys.argv[1:]
return _subprocess_call([
sys.executable, '-u',
os.path.join(engine_path, 'recipes.py')] + args)
if __name__ == '__main__':
sys.exit(main())