38902dbba8
If autoroles is used to document all roles - which is not the case in this repo but in opendev/base-jobs, the linter would complain about missing roles. Fix the linter to not complain. This change is here to sync the two variants and avoid others that copy it to run into the problem. Change-Id: I25411157ff18858e4f4c121a6d3f0ba6ec793be0
146 lines
4.6 KiB
Python
Executable File
146 lines
4.6 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# Copyright 2019 Red Hat, 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.
|
|
|
|
# Ensure that all jobs and roles appear in the documentation.
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
import yaml
|
|
|
|
|
|
class ZuulSafeLoader(yaml.SafeLoader):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(ZuulSafeLoader, self).__init__(*args, **kwargs)
|
|
self.add_multi_constructor('!encrypted/', self.construct_encrypted)
|
|
|
|
@classmethod
|
|
def construct_encrypted(cls, loader, tag_suffix, node):
|
|
return loader.construct_sequence(node)
|
|
|
|
|
|
class Layout(object):
|
|
def __init__(self):
|
|
self.jobs = []
|
|
|
|
|
|
class ZuulConfig(object):
|
|
def find_zuul_yaml(self):
|
|
root = os.getcwd()
|
|
while root:
|
|
for fn in ['zuul.yaml', '.zuul.yaml', 'zuul.d', '.zuul.d']:
|
|
path = os.path.join(root, fn)
|
|
if os.path.exists(path):
|
|
return path
|
|
root = os.path.split(root)[0]
|
|
raise Exception(
|
|
"Unable to find zuul config in zuul.yaml, .zuul.yaml,"
|
|
" zuul.d or .zuul.d")
|
|
|
|
def parse_zuul_yaml(self, path):
|
|
with open(path) as f:
|
|
data = yaml.load(f, Loader=ZuulSafeLoader)
|
|
layout = Layout()
|
|
for obj in data:
|
|
if 'job' in obj:
|
|
layout.jobs.append(obj['job'])
|
|
return layout
|
|
|
|
def parse_zuul_d(self, path):
|
|
layout = Layout()
|
|
for conf in os.listdir(path):
|
|
with open(os.path.join(path, conf)) as f:
|
|
data = yaml.load(f, Loader=ZuulSafeLoader)
|
|
for obj in data:
|
|
if 'job' in obj:
|
|
layout.jobs.append(obj['job'])
|
|
return layout
|
|
|
|
def parse_zuul_layout(self):
|
|
path = self.find_zuul_yaml()
|
|
if path.endswith('zuul.d'):
|
|
layout = self.parse_zuul_d(path)
|
|
else:
|
|
layout = self.parse_zuul_yaml(path)
|
|
return layout
|
|
|
|
def __init__(self):
|
|
self.layout = self.parse_zuul_layout()
|
|
|
|
|
|
class Docs(object):
|
|
def __init__(self):
|
|
self.jobs = set()
|
|
self.roles = set()
|
|
self.autojobs = False
|
|
self.autoroles = False
|
|
self.walk(os.path.join(os.getcwd(), 'doc', 'source'))
|
|
|
|
def walk(self, path):
|
|
for root, dirs, files in os.walk(path):
|
|
for fn in files:
|
|
if fn.endswith('.rst'):
|
|
with open(os.path.join(root, fn)) as f:
|
|
for line in f:
|
|
m = re.match(r'.*\.\. zuul:job:: (.*)$', line)
|
|
if m:
|
|
self.jobs.add(m.group(1))
|
|
m = re.match(r'.*\.\. zuul:autojob:: (.*)$', line)
|
|
if m:
|
|
self.jobs.add(m.group(1))
|
|
m = re.match(r'.*\.\. zuul:autojobs::.*$', line)
|
|
if m:
|
|
self.autojobs = True
|
|
m = re.match(r'.*\.\. zuul:role:: (.*)$', line)
|
|
if m:
|
|
self.roles.add(m.group(1))
|
|
m = re.match(r'.*\.\. zuul:autorole:: (.*)$', line)
|
|
if m:
|
|
self.roles.add(m.group(1))
|
|
m = re.match(r'.*\.\. zuul:autoroles::.*$', line)
|
|
if m:
|
|
self.autoroles = True
|
|
|
|
|
|
class Roles(object):
|
|
def __init__(self):
|
|
self.roles = set()
|
|
self.walk(os.path.join(os.getcwd(), 'roles'))
|
|
|
|
def walk(self, path):
|
|
for role in os.listdir(path):
|
|
if os.path.isdir(os.path.join(path, role, 'tasks')):
|
|
self.roles.add(role)
|
|
|
|
|
|
z = ZuulConfig()
|
|
r = Roles()
|
|
d = Docs()
|
|
|
|
ret = 0
|
|
if not d.autoroles:
|
|
for role in r.roles:
|
|
if role not in d.roles:
|
|
print("Role %s not included in document tree" % (role,))
|
|
ret = 1
|
|
for job in [x['name'] for x in z.layout.jobs]:
|
|
if job not in d.jobs:
|
|
print("Job %s not included in document tree" % (job,))
|
|
ret = 1
|
|
|
|
sys.exit(ret)
|