Move the script for running pre-releases into oslotest

Rather than maintaining the pre-release runner in oslo-incubator, put it
in oslotest where it can be installed with the rest of the library.

Change-Id: Idd58bfe3950d01725e239608f263dab5a0c9c908
This commit is contained in:
Doug Hellmann 2015-01-30 15:03:09 -05:00
parent e50b8b390e
commit c69ddb9396
2 changed files with 212 additions and 0 deletions

View File

@ -25,6 +25,7 @@ packages =
scripts =
tools/oslo_debug_helper
tools/oslo_run_cross_tests
tools/oslo_run_pre_release_tests
[global]
setup-hooks =

211
tools/oslo_run_pre_release_tests Executable file
View File

@ -0,0 +1,211 @@
#!/usr/bin/env python
#
# 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.
"""Run unit tests for projects that use a library.
"""
from __future__ import print_function
import glob
import os
import subprocess
import sys
from oslo_config import cfg
import oslo_tool_config as tconfig
from pbr import packaging
import pkg_resources
def find_all_projects(repo_root):
"""Scan the checked out repositories for all available projects.
"""
pattern = os.path.join(repo_root, 'openstack/*')
candidates = glob.glob(pattern)
prefix_len = len(repo_root)
return [
c[prefix_len:].lstrip('/')
for c in candidates
if os.path.isdir(c)
]
def find_consuming_projects(lib_name, repo_root, projects):
"""Filter the list of projects to only include entries that use the library.
"""
for p in projects:
consumer = False
for base in packaging.get_requirements_files():
req_file = os.path.join(repo_root, p, base)
for req in packaging.parse_requirements([req_file]):
try:
parsed_req = pkg_resources.Requirement.parse(req)
req_name = parsed_req.project_name
except ValueError:
continue
if req_name == lib_name:
consumer = True
yield p
break
if consumer:
break
def main():
conf = tconfig.get_config_parser()
conf.register_cli_opt(
cfg.StrOpt(
'library-under-test',
short='l',
default='',
help=('the name of the library being tested; '
'defaults to current dir'),
)
)
conf.register_cli_opt(
cfg.BoolOpt(
'update',
short='u',
default=False,
help='update consumers before running tests',
)
)
conf.register_cli_opt(
cfg.BoolOpt(
'verbose',
short='v',
default=False,
help='print verbose output',
)
)
conf.register_cli_opt(
cfg.StrOpt(
'ref',
short='r',
default='HEAD',
help='the commit reference to test; defaults to HEAD',
)
)
conf.register_cli_opt(
cfg.MultiStrOpt(
'env',
short='e',
default=['py27', 'pep8'],
help=('the name of the tox environment to test; '
'defaults to py27 and pep8'),
)
)
conf.register_cli_opt(
cfg.MultiStrOpt(
'consumer',
positional=True,
default=[],
help='the name of a project to test with; may be repeated',
)
)
tconfig.parse_arguments(conf)
repo_root = os.path.expanduser(conf.repo_root)
# Figure out which library is being tested
lib_name = conf.library_under_test
if not lib_name:
if conf.verbose:
print('finding library name')
lib_name = subprocess.check_output(
['python', 'setup.py', '--name']
).strip()
lib_dir = os.getcwd()
else:
lib_dir = os.path.join(repo_root, 'openstack', lib_name)
print('testing %s in %s' % (lib_name, lib_dir))
projects = set(conf.consumer)
if not projects:
# TODO(dhellmann): Need to update this to look at gerrit, so
# we can check out the projects we want to test with.
if conf.verbose:
print('defaulting to all projects under %s/openstack' % repo_root)
projects = find_all_projects(repo_root)
# Filter out projects that do not require the library under test
before = len(projects)
projects = list(find_consuming_projects(lib_name, repo_root, projects))
after = len(projects)
if (after < before) and conf.verbose:
print('ignoring %s projects that do not use %s'
% (before - after, lib_name))
projects = list(sorted(projects))
if not projects:
print('ERROR: found no projects using %s' % lib_name)
return 1
if conf.verbose:
print('preparing to test %s projects' % after)
# Make sure the lib being tested is set to the reference intended.
if conf.ref != 'HEAD':
if conf.verbose:
print('ensuring %s is updated to %s' % (lib_name, conf.ref))
subprocess.check_call(
['git', 'checkout', conf.ref],
cwd=lib_dir,
)
git_quiet = ['-q'] if not conf.verbose else []
failures = []
for p in projects:
if conf.verbose:
print()
proj_dir = os.path.join(repo_root, p)
if conf.update:
if conf.verbose:
print('updating %s with "git pull"' % p)
subprocess.Popen(
['git', 'pull'] + git_quiet,
cwd=proj_dir,
).communicate()
p_log_name = p.split('/')[-1].replace('.', '-')
for e in conf.env:
log_name = 'cross-test-%s-%s.log' % (p_log_name, e)
with open(log_name, 'w') as log_file:
print('testing %s in %s, logging to %s' % (e, p, log_name),
end=' ')
sys.stdout.flush()
command = ['oslo_run_cross_tests', proj_dir, e]
log_file.write('running: %s\n' % ' '.join(command))
log_file.flush() # since Popen is going to use the fd directly
cmd = subprocess.Popen(
command,
cwd=lib_dir,
stdout=log_file,
stderr=log_file
)
cmd.communicate()
log_file.write('\nexit code: %s\n' % cmd.returncode)
if cmd.returncode:
print('FAIL')
failures.append((p, e, cmd.returncode))
else:
print('PASS')
if failures:
print('\nFAILED %d jobs' % len(failures))
return 1
print('\nPASSED all jobs')
return 0
if __name__ == '__main__':
sys.exit(main())