Refactor validation script

Move some of the validation code into a real python package so we can
more easily reuse it.

Make the validation script reprint all errors, for cases where it has
checked a lot of files and the original messages might have been mixed
in with other output.

Fix the launchpad project name for tooz so the validation script will
pass.

Change-Id: I17534d460dd9ed19d10e48a0ef5d28dac3ab0fe7
This commit is contained in:
Doug Hellmann 2015-07-23 17:18:50 +00:00
parent cbd2b375b0
commit 7fb906f6d4
7 changed files with 87 additions and 43 deletions

View File

@ -1,5 +1,5 @@
--- ---
launchpad: tooz launchpad: python-tooz
releases: releases:
- version: 1.19.0 - version: 1.19.0
projects: projects:

View File

View File

View File

@ -1,5 +1,3 @@
#!/usr/bin/env python
#
# All Rights Reserved. # All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -23,8 +21,6 @@ from __future__ import print_function
import argparse import argparse
import glob import glob
import re import re
import subprocess
import sys
import requests import requests
import yaml import yaml
@ -33,23 +29,11 @@ import yaml
from requests.packages import urllib3 from requests.packages import urllib3
urllib3.disable_warnings() urllib3.disable_warnings()
from openstack_releases import gitutils
DEFAULT_RELEASE = 'liberty' DEFAULT_RELEASE = 'liberty'
CGIT_TEMPLATE = 'http://git.openstack.org/cgit/%s/commit/?id=%s'
def find_modified_deliverable_files():
"Return a list of files modified by the most recent commit."
results = subprocess.check_output(
['git', 'show', '--name-only', '--pretty=format:']
)
filenames = [
l.strip()
for l in results.splitlines()
if l.startswith('deliverables/')
]
return filenames
def is_a_hash(val): def is_a_hash(val):
"Return bool indicating if val looks like a valid hash." "Return bool indicating if val looks like a valid hash."
@ -66,13 +50,13 @@ def main():
) )
args = parser.parse_args() args = parser.parse_args()
filenames = args.input or find_modified_deliverable_files() filenames = args.input or gitutils.find_modified_deliverable_files()
if not filenames: if not filenames:
print('no modified deliverable files, validating all releases from %s' print('no modified deliverable files, validating all releases from %s'
% DEFAULT_RELEASE) % DEFAULT_RELEASE)
filenames = glob.glob('deliverables/' + DEFAULT_RELEASE + '/*.yaml') filenames = glob.glob('deliverables/' + DEFAULT_RELEASE + '/*.yaml')
num_errors = 0 errors = []
for filename in filenames: for filename in filenames:
print('\nChecking %s' % filename) print('\nChecking %s' % filename)
@ -83,14 +67,14 @@ def main():
try: try:
lp_name = deliverable_info['launchpad'] lp_name = deliverable_info['launchpad']
except KeyError: except KeyError:
num_errors += 1 errors.append('No launchpad project given in %s' % filename)
print('no launchpad project name given') print('no launchpad project name given')
else: else:
print('launchpad project %s ' % lp_name, end='') print('launchpad project %s ' % lp_name, end='')
lp_resp = requests.get('https://api.launchpad.net/1.0/' + lp_name) lp_resp = requests.get('https://api.launchpad.net/1.0/' + lp_name)
if (lp_resp.status_code // 100) == 4: if (lp_resp.status_code // 100) == 4:
print('MISSING') print('MISSING')
num_errors += 1 errors.append('Launchpad project %s does not exist' % lp_name)
else: else:
print('found') print('found')
@ -103,24 +87,24 @@ def main():
if not is_a_hash(project['hash']): if not is_a_hash(project['hash']):
print('NOT A SHA HASH') print('NOT A SHA HASH')
num_errors += 1 errors.append(
else: ('%(repo)s version %(version)s release from '
url = CGIT_TEMPLATE % (project['repo'], '%(hash)r, which is not a hash') % project
project['hash'])
response = requests.get(url)
missing_commit = (
(response.status_code // 100 != 2)
or 'Bad object id' in response.text
) )
print('MISSING' if missing_commit else 'found') else:
if missing_commit: exists = gitutils.commit_has_merged(
num_errors += 1 project['repo'], project['hash'],
)
if not exists:
print('MISSING')
errors.append('No commit %(hash)r in %(repo)r'
% project)
else:
print('found')
if num_errors: if errors:
print('\n%s errors found' % num_errors) print('\n%s errors found' % len(errors))
for e in errors:
print(e)
return 1 if num_errors else 0 return 1 if errors else 0
if __name__ == '__main__':
sys.exit(main())

View File

@ -0,0 +1,53 @@
# All Rights Reserved.
#
# 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 subprocess
import requests
# Disable warnings about insecure connections.
from requests.packages import urllib3
urllib3.disable_warnings()
CGIT_TEMPLATE = 'http://git.openstack.org/cgit/%s/commit/?id=%s'
def find_modified_deliverable_files():
"Return a list of files modified by the most recent commit."
results = subprocess.check_output(
['git', 'show', '--name-only', '--pretty=format:']
)
filenames = [
l.strip()
for l in results.splitlines()
if l.startswith('deliverables/')
]
return filenames
def commit_has_merged(repo, hash):
"""Return boolean specifying whether the hash exists in the repository.
Uses a cgit query instead of looking locally to avoid cloning a
repository or having Depends-On settings in a commit message allow
someone to fool the check.
"""
url = CGIT_TEMPLATE % (repo, hash)
response = requests.get(url)
missing_commit = (
(response.status_code // 100 != 2)
or 'Bad object id' in response.text
)
return not missing_commit

View File

@ -16,3 +16,10 @@ classifier =
Programming Language :: Python :: 2 Programming Language :: Python :: 2
Programming Language :: Python :: 2.7 Programming Language :: Python :: 2.7
Programming Language :: Python :: 2.6 Programming Language :: Python :: 2.6
[files]
packages = openstack_releases
[entry_points]
console_scripts =
validate-request = openstack_releases.cmds.validate:main

View File

@ -13,7 +13,7 @@ setenv =
deps = -r{toxinidir}/requirements.txt deps = -r{toxinidir}/requirements.txt
[testenv:validate] [testenv:validate]
commands = {toxinidir}/tools/validate.py {posargs} commands = validate-request {posargs}
[testenv:pep8] [testenv:pep8]
deps = flake8 deps = flake8