requirements/playbooks/files/project-requirements-change.py
Doug Hellmann e25260fcdb skip virtualenv setup when there is already a virtualenv
Support local use more easily by skipping the installation step if it
looks like the user has already done that once manually. This makes
running the script multiple times much much faster.

Change-Id: Id2a139c9d68c2ebcee558cbc493b47167d2a2e1d
Signed-off-by: Doug Hellmann <doug@doughellmann.com>
2018-04-11 20:09:56 +00:00

164 lines
5.4 KiB
Python
Executable File

#! /usr/bin/env python
# Copyright (C) 2011 OpenStack, LLC.
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
# Copyright (c) 2013 OpenStack Foundation
#
# 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.
import argparse
import contextlib
import os
import shlex
import shutil
import subprocess
import sys
import tempfile
requirement = None
project = None
check = None
def run_command(cmd):
print(cmd)
cmd_list = shlex.split(str(cmd))
p = subprocess.Popen(cmd_list, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(out, err) = p.communicate()
if p.returncode != 0:
raise SystemError(err)
return (out.strip(), err.strip())
_DEFAULT_REQS_DIR = os.path.expanduser(
'~/src/git.openstack.org/openstack/requirements')
def grab_args():
"""Grab and return arguments"""
parser = argparse.ArgumentParser(
description="Check if project requirements have changed"
)
parser.add_argument('--local', action='store_true',
help='check local changes (not yet in git)')
parser.add_argument('src_dir', help='directory to process')
parser.add_argument('branch', nargs='?', default='master',
help='target branch for diffs')
parser.add_argument('--zc', help='what zuul cloner to call')
parser.add_argument('--reqs', help='use a specified requirements tree',
default=None)
return parser.parse_args()
@contextlib.contextmanager
def tempdir():
try:
reqroot = tempfile.mkdtemp()
yield reqroot
finally:
shutil.rmtree(reqroot)
def install_and_load_requirements(reqroot, reqdir):
if os.environ.get('VIRTUAL_ENV'):
print('It looks like we are running from a virtualenv.')
print('SKIPPING INSTALLATION')
else:
sha = run_command("git --git-dir %s/.git rev-parse HEAD" % reqdir)[0]
print("requirements git sha: %s" % sha)
req_venv = os.path.join(reqroot, 'venv')
req_pip = os.path.join(req_venv, 'bin/pip')
req_lib = os.path.join(req_venv, 'lib/python2.7/site-packages')
out, err = run_command("virtualenv " + req_venv)
out, err = run_command(req_pip + " install " + reqdir)
sys.path.append(req_lib)
global check
global project
global requirement
from openstack_requirements import check # noqa
from openstack_requirements import project # noqa
from openstack_requirements import requirement # noqa
def main():
args = grab_args()
branch = args.branch
os.chdir(args.src_dir)
reqdir = args.reqs
if reqdir is None:
if args.local:
print('selecting default requirements directory for local mode')
reqdir = os.path.dirname(
os.path.dirname(
os.path.dirname(sys.argv[0])))
else:
print('selecting default requirements directory for normal mode')
reqdir = _DEFAULT_REQS_DIR
print('Branch: {}'.format(branch))
print('Source: {}'.format(args.src_dir))
print('Requirements: {}'.format(reqdir))
sha, _ = run_command('git log -n 1 --format=%H')
print('Patch under test: {}'.format(sha))
# build a list of requirements from the global list in the
# openstack/requirements project so we can match them to the changes
with tempdir() as reqroot:
install_and_load_requirements(reqroot, reqdir)
with open(reqdir + '/global-requirements.txt', 'rt') as f:
global_reqs = check.get_global_reqs(f.read())
blacklist = requirement.parse(
open(reqdir + '/blacklist.txt', 'rt').read())
cwd = os.getcwd()
# build a list of requirements in the proposed change,
# and check them for style violations while doing so
head_proj = project.read(cwd)
head_reqs = check.RequirementsList(sha, head_proj)
# Don't apply strict parsing rules to stable branches.
# Reasoning is:
# - devstack etc protect us from functional issues
# - we're backporting to stable, so guarding against
# aesthetics and DRY concerns is not our business anymore
# - if in future we have other not-functional linty style
# things to add, we don't want them to affect stable
# either.
head_strict = not branch.startswith('stable/')
head_reqs.process(strict=head_strict)
failed = check.validate(head_reqs, blacklist, global_reqs)
failed = (
check.validate_lower_constraints(
head_reqs,
head_proj['lower-constraints.txt'],
blacklist,
)
or failed
)
# report the results
if failed or head_reqs.failed:
print("*** Incompatible requirement found!")
print("*** See http://docs.openstack.org/developer/requirements")
sys.exit(1)
print("Updated requirements match openstack/requirements.")
if __name__ == '__main__':
main()