diff --git a/tools/base.py b/tools/base.py new file mode 100644 index 000000000..545ff7c5a --- /dev/null +++ b/tools/base.py @@ -0,0 +1,32 @@ +# 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 abc + + +class ValidatorBase(object): + __metaclass__ = abc.ABCMeta + + @staticmethod + @abc.abstractmethod + def get_tag_name(): + """Return tag name.""" + return + + @staticmethod + @abc.abstractmethod + def validate(name): + """Return True if name should have the tag. + + Where name can be a team or repo + """ + return diff --git a/tools/diversity.py b/tools/diversity.py index 169e32c95..ce14bb142 100755 --- a/tools/diversity.py +++ b/tools/diversity.py @@ -18,6 +18,8 @@ import sys import requests import yaml +import base + s = requests.session() @@ -85,6 +87,23 @@ def get_diversity(project): print '%-18s (%.2f%% | %.2f%% | %.2f%% | %.2f%%)' % ( '', commits_top2, reviews_top2, core_reviews_top2, core_reviewers_top2) + is_diverse = (commits_top <= 50 and reviews_top <= 50 and + core_reviews_top <= 50 and core_reviewers_top <= 50 and + commits_top2 <= 80 and reviews_top2 <= 80 and + core_reviews_top2 <= 80 and core_reviewers_top2 <= 80) + return is_diverse + + +class ValidateDiversity(base.ValidatorBase): + + @staticmethod + def validate(team): + """Return True of team should contain the tag 'team:diverse-affiliation'""" + return get_diversity(team) + + @staticmethod + def get_tag_name(): + return "team:diverse-affiliation" def main(): diff --git a/tools/validate_tags.py b/tools/validate_tags.py new file mode 100755 index 000000000..1766e61fc --- /dev/null +++ b/tools/validate_tags.py @@ -0,0 +1,96 @@ +#!/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. + +""" validate tag applications in projects.yaml + +Validate the application of tags that can be pragmatically applied. + +Note: Does not automatically update projects.yaml since doing so can reformat +and reorder projects.yaml + +""" + +import diversity + +import requests +import yaml + +import os +import sys +import urllib + +# List of modules to validate team based tags +team_validators = [ + diversity.ValidateDiversity, +] + +# List of modules to validate repository based tags +repo_validators = [ +] + + +def main(): + filename = os.path.abspath('reference/projects.yaml') + with open(filename, 'r') as f: + teams = yaml.load(f.read()) + for team in teams: + # Check team based tags + for validator in team_validators: + validate(team, teams[team], validator) + # Check repo based tags + for repo in teams[team]['projects']: + repo_name = repo['repo'] + if not repo_exists(repo_name): + continue + for validator in repo_validators: + validate(repo_name, repo, validator) + + +def validate(name, data, validator): + tag_name = validator.get_tag_name() + contains_tag = any([tag_name == tag['name'] for tag in + data.get('tags', [])]) + if validator.validate(name): + # should contain tag + if not contains_tag: + print_tag_missing(name, tag_name) + else: + # should not contain tag + if contains_tag: + print_bad_tag(name, tag_name) + + +def repo_exists(repo): + """Sometimes the governance docs can get out of sync with repo names.""" + response = requests.get( + 'https://review.openstack.org:443/projects/%s/' % + urllib.quote_plus(repo)) + # strip off first few chars because 'the JSON response body starts with + # a magic prefix line that must be stripped before feeding the rest of + # the response body to a JSON parser' + # https://review.openstack.org/Documentation/rest-api.html + if response.status_code == 404: + return False + return True + + +def print_tag_missing(name, tag): + print ("* %s should have the tag '%s'" % (name, tag)) + + +def print_bad_tag(name, tag): + print ("* %s should not have the tag '%s'" % (name, tag)) + +if __name__ == '__main__': + sys.exit(main())