Build list of teams from YAML file
Render the YAML file contents as the list of official teams and create a directive to render the list of projects with a given tag to avoid having to update that data in two places. Change-Id: I7c6effe6e440f2147f8c68df090152e716c38fba
This commit is contained in:
parent
53c0ee30e7
commit
72b8b9a74d
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
||||
doc/build
|
||||
*.egg-info
|
||||
pbr*.egg
|
||||
reference/projects/*.rst
|
||||
|
@ -1,3 +1,15 @@
|
||||
# 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.
|
||||
|
||||
"""Build a table of the current members of the TC.
|
||||
"""
|
||||
|
||||
|
41
doc/source/_exts/projects.py
Normal file
41
doc/source/_exts/projects.py
Normal file
@ -0,0 +1,41 @@
|
||||
# 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.
|
||||
|
||||
"""Load the projects.yaml file.
|
||||
"""
|
||||
|
||||
import copy
|
||||
import os.path
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
_projects_yaml = {}
|
||||
|
||||
|
||||
def get_project_data():
|
||||
"""Return a copy of the project data."""
|
||||
return copy.deepcopy(_projects_yaml)
|
||||
|
||||
|
||||
def slugify(name):
|
||||
"""Convert name to slug form for references."""
|
||||
return name.lower().replace(' ', '-')
|
||||
|
||||
|
||||
def setup(app):
|
||||
global _projects_yaml
|
||||
|
||||
filename = os.path.abspath('reference/projects.yaml')
|
||||
app.info('reading %s' % filename)
|
||||
with open(filename, 'r') as f:
|
||||
_projects_yaml = yaml.load(f.read())
|
82
doc/source/_exts/tags.py
Normal file
82
doc/source/_exts/tags.py
Normal file
@ -0,0 +1,82 @@
|
||||
# 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.
|
||||
|
||||
"""Show information about tagged projects.
|
||||
"""
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers import rst
|
||||
from docutils.statemachine import ViewList
|
||||
from sphinx.util.nodes import nested_parse_with_titles
|
||||
|
||||
import projects
|
||||
|
||||
_projects_by_tag = {}
|
||||
|
||||
|
||||
class TaggedProjectsDirective(rst.Directive):
|
||||
"""List the projects tagged with the given tag.
|
||||
"""
|
||||
|
||||
has_content = True
|
||||
|
||||
def run(self):
|
||||
env = self.state.document.settings.env
|
||||
app = env.app
|
||||
|
||||
tagname = ' '.join(self.content)
|
||||
app.info('building list of projects tagged %r' % tagname)
|
||||
if not tagname:
|
||||
error = self.state_machine.reporter.error(
|
||||
'No tagname in tagged-projects directive',
|
||||
nodes.literal_block(self.block_text, self.block_text),
|
||||
line=self.lineno)
|
||||
return [error]
|
||||
|
||||
# Build the view of the data to be parsed for rendering.
|
||||
result = ViewList()
|
||||
project_data = _projects_by_tag.get(tagname)
|
||||
source_name = '<' + __name__ + '>'
|
||||
if not project_data:
|
||||
result.append(
|
||||
'.. note:: No projects are using %s, yet.' % tagname,
|
||||
source_name,
|
||||
)
|
||||
else:
|
||||
for team_name, repo in sorted(project_data):
|
||||
line = '- :ref:`project-%s` -- :repo:`%s`' % (
|
||||
projects.slugify(team_name),
|
||||
repo,
|
||||
)
|
||||
result.append(line, source_name)
|
||||
|
||||
# Parse what we have into a new section.
|
||||
node = nodes.section()
|
||||
node.document = self.state.document
|
||||
nested_parse_with_titles(self.state, result, node)
|
||||
|
||||
return node.children
|
||||
|
||||
|
||||
def _build_projects_by_tag():
|
||||
for proj_name, info in projects.get_project_data().items():
|
||||
for repo in info.get('projects', []):
|
||||
for tag in repo.get('tags', []):
|
||||
tn = tag['name']
|
||||
l = _projects_by_tag.setdefault(tn, [])
|
||||
l.append((proj_name, repo['repo']))
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.info('loading tags extension')
|
||||
_build_projects_by_tag()
|
||||
app.add_directive('tagged-projects', TaggedProjectsDirective)
|
98
doc/source/_exts/teams.py
Normal file
98
doc/source/_exts/teams.py
Normal file
@ -0,0 +1,98 @@
|
||||
# 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.
|
||||
|
||||
"""Report on the current list of projects.
|
||||
"""
|
||||
|
||||
import yaml
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers import rst
|
||||
from docutils.statemachine import ViewList
|
||||
from sphinx.util.nodes import nested_parse_with_titles
|
||||
|
||||
import projects
|
||||
|
||||
|
||||
def _team_to_rst(name, info):
|
||||
yield '.. _project-%s:' % projects.slugify(name)
|
||||
yield ''
|
||||
yield '=' * len(name)
|
||||
yield name.title()
|
||||
yield '=' * len(name)
|
||||
yield ''
|
||||
yield ':Home Page: ' + info.get('url', '')
|
||||
yield ':PTL: ' + info.get('ptl', '')
|
||||
service = info.get('service')
|
||||
if service:
|
||||
yield ':Service: ' + service
|
||||
yield ''
|
||||
mission = info.get('mission', '').rstrip()
|
||||
if mission:
|
||||
yield mission
|
||||
yield ''
|
||||
for project in info.get('projects', []):
|
||||
tags = [
|
||||
':ref:`tag-%s`' % t['name']
|
||||
for t in project.get('tags', [])
|
||||
]
|
||||
if tags:
|
||||
tag_references = '(%s)' % ', '.join(tags)
|
||||
else:
|
||||
tag_references = ''
|
||||
yield '- :repo:`%s` %s' % (project['repo'], tag_references)
|
||||
yield ''
|
||||
yield ''
|
||||
|
||||
|
||||
def _write_team_pages(app):
|
||||
all_teams = projects.get_project_data()
|
||||
files = []
|
||||
for team, info in all_teams.items():
|
||||
slug = projects.slugify(team)
|
||||
filename = 'reference/projects/%s.rst' % slug
|
||||
app.info('generating team page for %s' % team)
|
||||
with open(filename, 'w') as f:
|
||||
f.write('\n'.join(_team_to_rst(team, info)))
|
||||
files.append(filename)
|
||||
return files
|
||||
|
||||
|
||||
class TeamsListDirective(rst.Directive):
|
||||
|
||||
has_content = False
|
||||
|
||||
def run(self):
|
||||
env = self.state.document.settings.env
|
||||
app = env.app
|
||||
|
||||
all_teams = projects.get_project_data()
|
||||
|
||||
# Build the view of the data to be parsed for rendering.
|
||||
result = ViewList()
|
||||
for team_name in sorted(all_teams.keys()):
|
||||
team_info = all_teams[team_name]
|
||||
for line in _team_to_rst(team_name, team_info):
|
||||
result.append(line, '<' + __name__ + '>')
|
||||
|
||||
# Parse what we have into a new section.
|
||||
node = nodes.section()
|
||||
node.document = self.state.document
|
||||
nested_parse_with_titles(self.state, result, node)
|
||||
|
||||
return node.children
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.info('loading teams extension')
|
||||
app.add_directive('teamslist', TeamsListDirective)
|
||||
_write_team_pages(app)
|
@ -27,12 +27,21 @@ sys.path.insert(0, os.path.join(os.path.abspath('.'), '_exts'))
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = [
|
||||
'sphinx.ext.extlinks',
|
||||
'oslosphinx',
|
||||
'members',
|
||||
'projects',
|
||||
'teams',
|
||||
'tags',
|
||||
]
|
||||
|
||||
todo_include_todos = True
|
||||
|
||||
# Define shorthand roles for making links to common destinations.
|
||||
extlinks = {
|
||||
'repo': ('http://git.openstack.org/cgit/%s', ''),
|
||||
}
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
|
@ -23,7 +23,7 @@ Reference documents and Resolutions
|
||||
===================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:maxdepth: 2
|
||||
:glob:
|
||||
:titlesonly:
|
||||
|
||||
|
@ -5,9 +5,10 @@
|
||||
Reference documents which need to be revised over time.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
charter
|
||||
projects/index
|
||||
new-projects-requirements
|
||||
project-testing-interface
|
||||
tags/index
|
||||
|
8
reference/projects/index.rst
Normal file
8
reference/projects/index.rst
Normal file
@ -0,0 +1,8 @@
|
||||
=========================
|
||||
OpenStack Project Teams
|
||||
=========================
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
|
||||
*
|
@ -91,3 +91,5 @@ the proposed tag to at least some subset of the current project list. This
|
||||
will serve as an example of how the tag should be applied in the real world.
|
||||
You may also submit (as a subsequent change) the corresponding governance
|
||||
change to immediately apply the proposed tag to projects.
|
||||
|
||||
.. tagged-projects:: <tag name>
|
||||
|
@ -4,6 +4,8 @@
|
||||
Unported License.
|
||||
http://creativecommons.org/licenses/by/3.0/legalcode
|
||||
|
||||
.. _tag-integrated-release:
|
||||
|
||||
==================
|
||||
integrated-release
|
||||
==================
|
||||
@ -67,18 +69,4 @@ The following code repositories would get the proposed tag. Those match the
|
||||
contents of the Kilo release as decided at the end of the Juno cycle, and
|
||||
take into account the recent Neutron advanced services code split:
|
||||
|
||||
* openstack/nova
|
||||
* openstack/swift
|
||||
* openstack/glance
|
||||
* openstack/keystone
|
||||
* openstack/horizon
|
||||
* openstack/neutron
|
||||
* openstack/neutron-fwaas
|
||||
* openstack/neutron-lbaas
|
||||
* openstack/neutron-vpnaas
|
||||
* openstack/cinder
|
||||
* openstack/ceilometer
|
||||
* openstack/heat
|
||||
* openstack/trove
|
||||
* openstack/ironic
|
||||
* openstack/sahara
|
||||
.. tagged-projects:: integrated-release
|
||||
|
@ -1,3 +1,4 @@
|
||||
# needed for doc build
|
||||
sphinx>=1.1.2,!=1.2.0,<1.3
|
||||
oslosphinx>=2.2.0 # Apache-2.0
|
||||
PyYAML>=3.1.0
|
||||
|
Loading…
Reference in New Issue
Block a user