From 8a3f32a01dad40c8f8f3e491d3dbbbd5a9c8a1e7 Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Thu, 26 Jul 2018 11:48:34 +1000 Subject: [PATCH] Add a new tool meant for CI to validate all files under candidates The new tool validates the current release looks to exist ; assuming it does it performs the following checks against every file found: 1. The file looks like an email address (currently contains an '@') 2. The email address is found in the OSF directory 3. The email address has a merged commit in the expected timeframe for a deliverable under the governance of the project team the candidate is nominating for. While this is meant to be used in CI, the output should be reasonably readable by a person, either official or candidate. Change-Id: I51e80f5d185e3ef0be53fd8c9fba19338d9a049a --- .../cmds/ci_check_all_candidate_files.py | 115 ++++++++++++++++++ setup.cfg | 1 + 2 files changed, 116 insertions(+) create mode 100755 openstack_election/cmds/ci_check_all_candidate_files.py diff --git a/openstack_election/cmds/ci_check_all_candidate_files.py b/openstack_election/cmds/ci_check_all_candidate_files.py new file mode 100755 index 00000000..b87e3702 --- /dev/null +++ b/openstack_election/cmds/ci_check_all_candidate_files.py @@ -0,0 +1,115 @@ +# 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. + +from __future__ import absolute_import +from __future__ import print_function +from __future__ import unicode_literals + +import argparse +import glob +import os + +from openstack_election import check_candidacy +from openstack_election import utils + + +def validate_release(release): + print('Validate Release') + print('----------------') + + release_path = os.path.join(utils.CANDIDATE_PATH, release) + is_valid = (os.path.exists(release_path) and os.path.isdir(release_path)) + + print('Release: %s [%s] is %sok' % (release, release_path, + {True: '', False: 'not '}[is_valid])) + print('') + return is_valid + + +def validate_filename(filepath): + print('Validate file name looks like an email address') + print('----------------------------------------------') + + file_name = utils.get_email(filepath) + is_valid = '@' in file_name + + print('Filename: %s [%s] is %sok' % (file_name, filepath, + {True: '', False: 'not '}[is_valid])) + print('') + return is_valid + + +def validate_member(filepath): + print('Validate email address is OSF member') + print('------------------------------------') + + email = utils.get_email(filepath) + member = utils.lookup_member(email) + is_valid = member.get('data', []) != [] + + print('Email address: %s is %sok' % (email, + {True: '', False: 'not '}[is_valid])) + print('') + return is_valid + + +def check_for_changes(projects, filepath, limit): + print('Looking for validating changes') + print('------------------------------') + + email = utils.get_email(filepath) + project_name = os.path.basename(os.path.dirname(filepath)) + project_name = utils.dir2name(project_name, projects) + + changes_found = check_candidacy.check_candidate(project_name, email, + projects, limit) + print('') + return bool(changes_found) + + +def main(): + description = ('Check all files under the current open election are valid') + parser = argparse.ArgumentParser(description) + + parser.add_argument('--limit', dest='limit', type=int, default=1, + help=('How many validating changes to report. ' + 'A negative value means report many. ' + 'Default: %(default)s')) + parser.add_argument('--tag', dest='tag', default=utils.conf['tag'], + help=('The governance tag to validate against. ' + 'Default: %(default)s')) + parser.add_argument('--release', dest='release', + default=utils.conf['release'], + help=('The relase to validate candidates against. ' + 'Default: %(default)s')) + + args = parser.parse_args() + errors = False + + if not validate_release(args.release): + return 1 + + projects = utils.get_projects(tag=args.tag, fallback_to_master=True) + + for filepath in glob.glob(os.path.join(utils.CANDIDATE_PATH, + args.release, '*', '*')): + candiate_ok = True + + candiate_ok &= validate_filename(filepath) + candiate_ok &= validate_member(filepath) + + if candiate_ok and utils.is_tc_election: + candiate_ok &= check_for_changes(projects, filepath, args.limit) + + errors |= not candiate_ok + + return 1 if errors else 0 diff --git a/setup.cfg b/setup.cfg index 26f9b074..e359f2ee 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,6 +20,7 @@ packages = openstack_election [entry_points] console_scripts = + ci-check-all-candidate-files = openstack_election.cmds.ci_check_all_candidate_files:main check-all-candidacies = openstack_election.cmds.check_all_candidacies:main check-candidacy = openstack_election.cmds.check_candidacy:main check-candidacy-manual = openstack_election.cmds.check_manual:main