Add support for project-templates
Change-Id: I0f86acd7fb5e049e5368249de52f9d81a99936d8
This commit is contained in:
parent
15afdbadc8
commit
4122b0b8f0
|
@ -0,0 +1,12 @@
|
||||||
|
Auto Doc
|
||||||
|
========
|
||||||
|
|
||||||
|
Auto Jobs
|
||||||
|
---------
|
||||||
|
|
||||||
|
.. autojobs::
|
||||||
|
|
||||||
|
Auto Project Templates
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
.. autoproject_templates::
|
|
@ -0,0 +1,20 @@
|
||||||
|
Example Project Templates
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Project Templates
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. project_template:: example
|
||||||
|
|
||||||
|
This is an example project template. It contains the following jobs:
|
||||||
|
|
||||||
|
**check**
|
||||||
|
|
||||||
|
* :job:`example`
|
||||||
|
* :job:`example`
|
||||||
|
|
||||||
|
**gate**
|
||||||
|
|
||||||
|
* :job:`example`
|
||||||
|
|
||||||
|
This is a project_template role: :project_template:`example`
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
examples
|
examples
|
||||||
example-jobs
|
example-jobs
|
||||||
|
example-templates
|
||||||
example-roles
|
example-roles
|
||||||
|
example-autodoc
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
- job:
|
||||||
|
name: test-autodoc
|
||||||
|
description: |
|
||||||
|
This is a test job.
|
||||||
|
|
||||||
|
- job:
|
||||||
|
name: test-autodoc
|
||||||
|
branches: stable
|
||||||
|
description: |
|
||||||
|
This is a test job variant on a stable branch.
|
||||||
|
|
||||||
|
- project-template:
|
||||||
|
name: test-autotemplate
|
||||||
|
description: |
|
||||||
|
This is a test project template.
|
||||||
|
check:
|
||||||
|
jobs:
|
||||||
|
- test-autodoc
|
||||||
|
- example
|
||||||
|
- does-not-exist-in-this-repo
|
||||||
|
gate:
|
||||||
|
jobs:
|
||||||
|
- example
|
||||||
|
- does-not-exist-in-this-repo
|
|
@ -12,6 +12,9 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from collections import OrderedDict
|
||||||
|
import os
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from docutils.parsers.rst import Directive
|
from docutils.parsers.rst import Directive
|
||||||
from sphinx.domains import Domain, ObjType
|
from sphinx.domains import Domain, ObjType
|
||||||
|
@ -19,14 +22,37 @@ from sphinx.roles import XRefRole
|
||||||
from sphinx.directives import ObjectDescription
|
from sphinx.directives import ObjectDescription
|
||||||
from sphinx.util.nodes import make_refnode
|
from sphinx.util.nodes import make_refnode
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
import os
|
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTemplate(object):
|
||||||
|
def __init__(self, conf):
|
||||||
|
self.name = conf['name']
|
||||||
|
self.description = conf.get('description', '')
|
||||||
|
self.pipelines = OrderedDict()
|
||||||
|
self.parse(conf)
|
||||||
|
|
||||||
|
def parse(self, conf):
|
||||||
|
for k in sorted(conf.keys()):
|
||||||
|
v = conf[k]
|
||||||
|
if not isinstance(v, dict):
|
||||||
|
continue
|
||||||
|
if 'jobs' not in v:
|
||||||
|
continue
|
||||||
|
jobs = []
|
||||||
|
for job in v['jobs']:
|
||||||
|
if isinstance(job, dict):
|
||||||
|
job = list(dict.keys())[0]
|
||||||
|
jobs.append(job)
|
||||||
|
if jobs:
|
||||||
|
self.pipelines[k] = jobs
|
||||||
|
|
||||||
|
|
||||||
class Layout(object):
|
class Layout(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.jobs = []
|
self.jobs = []
|
||||||
|
self.project_templates = []
|
||||||
|
|
||||||
|
|
||||||
class ZuulDirective(Directive):
|
class ZuulDirective(Directive):
|
||||||
|
@ -51,6 +77,9 @@ class ZuulDirective(Directive):
|
||||||
for obj in data:
|
for obj in data:
|
||||||
if 'job' in obj:
|
if 'job' in obj:
|
||||||
layout.jobs.append(obj['job'])
|
layout.jobs.append(obj['job'])
|
||||||
|
if 'project-template' in obj:
|
||||||
|
layout.project_templates.append(
|
||||||
|
ProjectTemplate(obj['project-template']))
|
||||||
return layout
|
return layout
|
||||||
|
|
||||||
def parse_zuul_d(self, path):
|
def parse_zuul_d(self, path):
|
||||||
|
@ -61,6 +90,9 @@ class ZuulDirective(Directive):
|
||||||
for obj in data:
|
for obj in data:
|
||||||
if 'job' in obj:
|
if 'job' in obj:
|
||||||
layout.jobs.append(obj['job'])
|
layout.jobs.append(obj['job'])
|
||||||
|
if 'project-template' in obj:
|
||||||
|
layout.project_templates.append(
|
||||||
|
ProjectTemplate(obj['project-template']))
|
||||||
return layout
|
return layout
|
||||||
|
|
||||||
def _parse_zuul_layout(self):
|
def _parse_zuul_layout(self):
|
||||||
|
@ -103,6 +135,22 @@ class ZuulDirective(Directive):
|
||||||
lines.append('')
|
lines.append('')
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
def generate_zuul_project_template_content(self, name):
|
||||||
|
lines = []
|
||||||
|
for template in self.zuul_layout.project_templates:
|
||||||
|
if template.name == name:
|
||||||
|
lines.append('.. zuul:project_template:: %s' % name)
|
||||||
|
lines.append('')
|
||||||
|
for l in template.description.split('\n'):
|
||||||
|
lines.append(' ' + l)
|
||||||
|
for pipeline, jobs in template.pipelines.items():
|
||||||
|
lines.append('')
|
||||||
|
lines.append(' **'+pipeline+'**')
|
||||||
|
for job in jobs:
|
||||||
|
lines.append(' * :zuul:xjob:`' + job + '`')
|
||||||
|
lines.append('')
|
||||||
|
return lines
|
||||||
|
|
||||||
def find_zuul_roles(self):
|
def find_zuul_roles(self):
|
||||||
root = os.path.dirname(self.zuul_layout_path)
|
root = os.path.dirname(self.zuul_layout_path)
|
||||||
roledir = os.path.join(root, 'roles')
|
roledir = os.path.join(root, 'roles')
|
||||||
|
@ -210,6 +258,22 @@ class ZuulJobDirective(ZuulObjectDescription):
|
||||||
return sig
|
return sig
|
||||||
|
|
||||||
|
|
||||||
|
class ZuulProjectTemplateDirective(ZuulObjectDescription):
|
||||||
|
def before_content(self):
|
||||||
|
path = self.env.ref_context.setdefault('zuul:attr_path', [])
|
||||||
|
element = self.names[-1]
|
||||||
|
path.append(element)
|
||||||
|
|
||||||
|
def after_content(self):
|
||||||
|
path = self.env.ref_context.get('zuul:attr_path')
|
||||||
|
if path:
|
||||||
|
path.pop()
|
||||||
|
|
||||||
|
def handle_signature(self, sig, signode):
|
||||||
|
signode += addnodes.desc_name(sig, sig)
|
||||||
|
return sig
|
||||||
|
|
||||||
|
|
||||||
class ZuulRoleDirective(ZuulObjectDescription):
|
class ZuulRoleDirective(ZuulObjectDescription):
|
||||||
def before_content(self):
|
def before_content(self):
|
||||||
path = self.env.ref_context.setdefault('zuul:attr_path', [])
|
path = self.env.ref_context.setdefault('zuul:attr_path', [])
|
||||||
|
@ -409,6 +473,29 @@ class ZuulAutoJobsDirective(ZuulDirective):
|
||||||
self.state_machine.insert_input(lines, self.zuul_layout_path)
|
self.state_machine.insert_input(lines, self.zuul_layout_path)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
class ZuulAutoProjectTemplateDirective(ZuulDirective):
|
||||||
|
def run(self):
|
||||||
|
name = self.content[0]
|
||||||
|
lines = self.generate_zuul_project_template_content(name)
|
||||||
|
self.state_machine.insert_input(lines, self.zuul_layout_path)
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
class ZuulAutoProjectTemplatesDirective(ZuulDirective):
|
||||||
|
has_content = False
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
lines = []
|
||||||
|
names = set()
|
||||||
|
for template in self.zuul_layout.project_templates:
|
||||||
|
name = template.name
|
||||||
|
if name in names:
|
||||||
|
continue
|
||||||
|
lines.extend(self.generate_zuul_project_template_content(name))
|
||||||
|
names.add(name)
|
||||||
|
self.state_machine.insert_input(lines, self.zuul_layout_path)
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
class ZuulAutoRoleDirective(ZuulDirective):
|
class ZuulAutoRoleDirective(ZuulDirective):
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -447,6 +534,7 @@ class ZuulDomain(Domain):
|
||||||
directives = {
|
directives = {
|
||||||
# Object description directives
|
# Object description directives
|
||||||
'job': ZuulJobDirective,
|
'job': ZuulJobDirective,
|
||||||
|
'project_template': ZuulProjectTemplateDirective,
|
||||||
'role': ZuulRoleDirective,
|
'role': ZuulRoleDirective,
|
||||||
'attr': ZuulAttrDirective,
|
'attr': ZuulAttrDirective,
|
||||||
'value': ZuulValueDirective,
|
'value': ZuulValueDirective,
|
||||||
|
@ -457,6 +545,8 @@ class ZuulDomain(Domain):
|
||||||
# Autodoc directives
|
# Autodoc directives
|
||||||
'autojob': ZuulAutoJobDirective,
|
'autojob': ZuulAutoJobDirective,
|
||||||
'autojobs': ZuulAutoJobsDirective,
|
'autojobs': ZuulAutoJobsDirective,
|
||||||
|
'autoproject_template': ZuulAutoProjectTemplateDirective,
|
||||||
|
'autoproject_templates': ZuulAutoProjectTemplatesDirective,
|
||||||
'autorole': ZuulAutoRoleDirective,
|
'autorole': ZuulAutoRoleDirective,
|
||||||
'autoroles': ZuulAutoRolesDirective,
|
'autoroles': ZuulAutoRolesDirective,
|
||||||
}
|
}
|
||||||
|
@ -464,6 +554,11 @@ class ZuulDomain(Domain):
|
||||||
roles = {
|
roles = {
|
||||||
'job': XRefRole(innernodeclass=nodes.inline, # type: ignore
|
'job': XRefRole(innernodeclass=nodes.inline, # type: ignore
|
||||||
warn_dangling=True),
|
warn_dangling=True),
|
||||||
|
'xjob': XRefRole(innernodeclass=nodes.inline, # type: ignore
|
||||||
|
warn_dangling=False),
|
||||||
|
'project_template':
|
||||||
|
XRefRole(innernodeclass=nodes.inline, # type: ignore
|
||||||
|
warn_dangling=True),
|
||||||
'role': XRefRole(innernodeclass=nodes.inline, # type: ignore
|
'role': XRefRole(innernodeclass=nodes.inline, # type: ignore
|
||||||
warn_dangling=True),
|
warn_dangling=True),
|
||||||
'attr': XRefRole(innernodeclass=nodes.inline, # type: ignore
|
'attr': XRefRole(innernodeclass=nodes.inline, # type: ignore
|
||||||
|
@ -491,6 +586,8 @@ class ZuulDomain(Domain):
|
||||||
def resolve_xref(self, env, fromdocname, builder, type, target,
|
def resolve_xref(self, env, fromdocname, builder, type, target,
|
||||||
node, contnode):
|
node, contnode):
|
||||||
objects = self.data['objects']
|
objects = self.data['objects']
|
||||||
|
if type == 'xjob':
|
||||||
|
type = 'job'
|
||||||
name = type + '-' + target
|
name = type + '-' + target
|
||||||
obj = objects.get(name)
|
obj = objects.get(name)
|
||||||
if obj:
|
if obj:
|
||||||
|
|
Loading…
Reference in New Issue