diff --git a/.zuul.yaml b/.zuul.yaml index b580cef9f..976b1d883 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -8,12 +8,26 @@ vars: tox_envlist: validate_atcs +- job: + name: governance-validate-legacy + parent: openstack-tox + description: | + Run a job to validate the legacy.yaml file to ensure that projects are + properly retired. This job only runs on legacy.yaml changes to ensure + that we don't hit OpenDev.org with too many requests without changes. + files: + - tools/validate-legacy.py + - reference/legacy.yaml + vars: + tox_envlist: validate-legacy + - project: templates: - build-openstack-docs-pti - openstack-python3-ussuri-jobs check: jobs: + - governance-validate-legacy - openstack-tox-validate_atcs: voting: false - openstack-tox-linters: @@ -24,6 +38,7 @@ - openstack-tox-validate gate: jobs: + - governance-validate-legacy - openstack-tox-linters: required-projects: - openstack/project-config diff --git a/tools/validate-legacy.py b/tools/validate-legacy.py new file mode 100755 index 000000000..231be1093 --- /dev/null +++ b/tools/validate-legacy.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 + +# Copyright 2020 VEXXHOST, Inc. +# +# 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 sys + +import requests +import yaml + +FILES_URL = "https://opendev.org/api/v1/repos/{}/git/trees/master" +IGNORED_REPOS = [ + 'openstack/python-dracclient', + 'openstack/networking-l2gw', + 'openstack/networking-l2gw-tempest-plugin' +] + +parser = argparse.ArgumentParser() +parser.add_argument( + '-l', '--legacy-projects', + default='./reference/legacy.yaml', + help='legacy.yaml file path (%(default)s)' +) +args = parser.parse_args() + +with open(args.legacy_projects, 'r', encoding='utf-8') as f: + legacy_projects = yaml.safe_load(f.read()) + +errors = 0 +for team_name, team_data in legacy_projects.items(): + # Check if the team has been retired + if 'retired-on' in team_data: + continue + + deliverables = team_data.get('deliverables') + + # Team has no deliverables, retired with no retired-on date + if not deliverables: + print('{} team has no deliverables with no retired-on date'.format( + team_name + )) + errors += 1 + continue + + # In this case, team is not retired but has retired projects + for deliverable_name, deliverable_data in deliverables.items(): + # Retired-on date missing for a deliverable + if 'retired-on' not in deliverable_data: + print('{} is missing a retired-on date'.format(deliverable_name)) + errors += 1 + continue + + # Ensure that the repositories has no content. + for repo in deliverable_data['repos']: + if repo in IGNORED_REPOS: + msg = '{} is ignored'.format(repo) + print(msg) + continue + + if repo.startswith('opendev/'): + msg = '{} not in openstack namespace, ignoring.'.format(repo) + print(msg) + continue + + url = FILES_URL.format(repo) + files = requests.get(url).json() + file_names = sorted([f['path'] for f in files['tree']]) + + if file_names != ['.gitreview', 'README.rst']: + msg = '{} is not properly retired, files: {}.'.format( + repo, file_names) + print(msg) + errors += 1 + continue + + +sys.exit(1 if errors else 0) diff --git a/tools/validate_repositories.py b/tools/validate_repositories.py index d39d052bf..4d6e3a48c 100755 --- a/tools/validate_repositories.py +++ b/tools/validate_repositories.py @@ -45,8 +45,6 @@ args = parser.parse_args() with open(args.projects, 'r', encoding='utf-8') as f: projects = yaml.safe_load(f.read()) -with open(args.legacy_projects, 'r', encoding='utf-8') as f: - legacy_projects = yaml.safe_load(f.read()) if os.path.exists(args.project_config): projects_yaml = '%s/gerrit/projects.yaml' % args.project_config @@ -70,27 +68,4 @@ for team_name, team_data in projects.items(): repo_name, deliverable_name, team_name)) errors += 1 -for team_name, team_data in legacy_projects.items(): - # Check if the team has been retired - if 'retired-on' in team_data: - continue - - deliverables = team_data.get('deliverables') - - # Team has no deliverables, retired with no retired-on date - if not deliverables: - print('{} team has no deliverables with no retired-on date'.format( - team_name - )) - errors += 1 - continue - - # In this case, team is not retired but has retired projects - for deliverable_name, deliverable_data in deliverables.items(): - # Retired-on date missing for a deliverable - if 'retired-on' not in deliverable_data: - print('{} is missing a retired-on date'.format(deliverable_name)) - errors += 1 - continue - sys.exit(1 if errors else 0) diff --git a/tox.ini b/tox.ini index 30ba10d37..ba671ac84 100644 --- a/tox.ini +++ b/tox.ini @@ -38,6 +38,11 @@ commands = whereto {toxinidir}/doc/source/_extra/.htaccess {toxinidir}/doc/test/redirect-tests.txt {toxinidir}/tools/validate_repositories.py +[testenv:validate-legacy] +envdir = {toxworkdir}/linters +commands = + {toxinidir}/tools/validate-legacy.py + [testenv:validate_atcs] commands = {toxinidir}/tools/validate_atcs.py