Add legacy repository validation

This patch improves the legacy repository validation by ensuring that we
actually make sure the repository is properly retired.  This job will
only run on changes to the legacy.yaml file to avoid a high number of
API calls.

Change-Id: I40f1818955eaa0a2037f239aeced86c3faf3281e
This commit is contained in:
Mohammed Naser
2020-06-23 11:09:49 -04:00
parent cf2872a1e8
commit d5a9229ec2
4 changed files with 109 additions and 25 deletions

View File

@@ -8,12 +8,26 @@
vars: vars:
tox_envlist: validate_atcs 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: - project:
templates: templates:
- build-openstack-docs-pti - build-openstack-docs-pti
- openstack-python3-ussuri-jobs - openstack-python3-ussuri-jobs
check: check:
jobs: jobs:
- governance-validate-legacy
- openstack-tox-validate_atcs: - openstack-tox-validate_atcs:
voting: false voting: false
- openstack-tox-linters: - openstack-tox-linters:
@@ -24,6 +38,7 @@
- openstack-tox-validate - openstack-tox-validate
gate: gate:
jobs: jobs:
- governance-validate-legacy
- openstack-tox-linters: - openstack-tox-linters:
required-projects: required-projects:
- openstack/project-config - openstack/project-config

89
tools/validate-legacy.py Executable file
View File

@@ -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)

View File

@@ -45,8 +45,6 @@ args = parser.parse_args()
with open(args.projects, 'r', encoding='utf-8') as f: with open(args.projects, 'r', encoding='utf-8') as f:
projects = yaml.safe_load(f.read()) 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): if os.path.exists(args.project_config):
projects_yaml = '%s/gerrit/projects.yaml' % 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)) repo_name, deliverable_name, team_name))
errors += 1 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) sys.exit(1 if errors else 0)

View File

@@ -38,6 +38,11 @@ commands =
whereto {toxinidir}/doc/source/_extra/.htaccess {toxinidir}/doc/test/redirect-tests.txt whereto {toxinidir}/doc/source/_extra/.htaccess {toxinidir}/doc/test/redirect-tests.txt
{toxinidir}/tools/validate_repositories.py {toxinidir}/tools/validate_repositories.py
[testenv:validate-legacy]
envdir = {toxworkdir}/linters
commands =
{toxinidir}/tools/validate-legacy.py
[testenv:validate_atcs] [testenv:validate_atcs]
commands = {toxinidir}/tools/validate_atcs.py commands = {toxinidir}/tools/validate_atcs.py