]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
doc: render release with mermaid gantt 46664/head
authorKefu Chai <tchaikov@gmail.com>
Wed, 15 Jun 2022 04:30:34 +0000 (00:30 -0400)
committerKefu Chai <tchaikov@gmail.com>
Wed, 15 Jun 2022 04:38:22 +0000 (00:38 -0400)
for better readability

Signed-off-by: Kefu Chai <tchaikov@gmail.com>
admin/doc-requirements.txt
doc/_ext/ceph_releases.py
doc/conf.py
doc/releases/index.rst

index e094742424cdc06e909be503fc182128ff6903b0..2f4970e3fbb31047dabf30d3d979aab359d1b603 100644 (file)
@@ -13,6 +13,7 @@ sphinx-prompt
 sphinx_rtd_theme == 1.0.0
 Sphinx-Substitution-Extensions
 typed-ast
+sphinxcontrib-mermaid
 sphinxcontrib-openapi
 sphinxcontrib-seqdiag
 mistune < 2.0.0
index bf8a5dca172253519c61d59e0dc8e2f5598b4a8c..9208bd23850df22535961345138143c1b20bd240 100644 (file)
@@ -6,12 +6,16 @@
 # into the glory that follows:
 import json
 import yaml
+import jinja2
 import sphinx
 import datetime
 from docutils.parsers.rst import Directive
 from docutils import nodes
 from sphinx.util import logging
 
+logger = logging.getLogger(__name__)
+
+
 class CephReleases(Directive):
     has_content = False
     required_arguments = 2
@@ -114,6 +118,77 @@ class CephReleases(Directive):
 
         return [table]
 
+
+RELEASES_TEMPLATE = '''
+.. mermaid::
+
+   gantt
+       dateFormat  YYYY-MM-DD
+       axisFormat  %Y
+       section Active Releases
+{% for release in active_releases %}
+       {{ release.code_name }} (latest {{ release.last_version }}): done, {{ release.debute_date }},{{ release.lifetime }}d
+{% endfor %}
+       section Archived Releases
+{% for release in archived_releases %}
+       {{ release.code_name }} (latest {{ release.last_version }}): done, {{ release.debute_date }},{{ release.lifetime }}d
+{% endfor %}
+'''
+
+
+class ReleasesGantt(Directive):
+    has_content = True
+    required_arguments = 1
+    optional_arguments = 0
+    final_argument_whitespace = False
+
+    template = jinja2.Environment().from_string(RELEASES_TEMPLATE)
+
+    def _render_time_line(self, filename):
+        try:
+            with open(filename) as f:
+                releases = yaml.safe_load(f)['releases']
+        except Exception as e:
+            message = f'Unable read release file: "{filename}": {e}'
+            self.error(message)
+
+        active_releases = []
+        archived_releases = []
+        # just update `releases` with extracted info
+        for code_name, info in releases.items():
+            last_release = info['releases'][0]
+            first_release = info['releases'][-1]
+            last_version = last_release['version']
+            debute_date = first_release['released']
+            if 'actual_eol' in info:
+                lifetime = info['actual_eol'] - first_release['released']
+            else:
+                lifetime = info['target_eol'] - first_release['released']
+            release = dict(code_name=code_name,
+                           last_version=last_version,
+                           debute_date=debute_date,
+                           lifetime=lifetime.days)
+            if 'actual_eol' in info:
+                archived_releases.append(release)
+            else:
+                active_releases.append(release)
+        rendered = self.template.render(active_releases=active_releases,
+                                        archived_releases=archived_releases)
+        return rendered.splitlines()
+
+    def run(self):
+        filename = self.arguments[0]
+        document = self.state.document
+        env = document.settings.env
+        rel_filename, filename = env.relfn2path(filename)
+        env.note_dependency(filename)
+        lines = self._render_time_line(filename)
+        lineno = self.lineno - self.state_machine.input_offset - 1
+        source = self.state_machine.input_lines.source(lineno)
+        self.state_machine.insert_input(lines, source)
+        return []
+
+
 class CephTimeline(Directive):
     has_content = False
     required_arguments = 4
@@ -207,9 +282,69 @@ class CephTimeline(Directive):
 
         return [table]
 
+
+TIMELINE_TEMPLATE = '''
+.. mermaid::
+
+   gantt
+       dateFormat  YYYY-MM-DD
+       axisFormat  %Y-%m
+{% if title %}
+       title       {{title}}
+{% endif %}
+{% for display_release in display_releases %}
+       section {{ display_release }}
+{%if releases[display_release].actual_eol %}
+       End of life:             crit,            {{ releases[display_release].actual_eol }},4d
+{% else %}
+       End of life (estimated): crit,            {{ releases[display_release].target_eol }},4d
+{% endif %}
+{% for release in releases[display_release].releases %}
+       {{ release.version }}:   milestone, done, {{ release.released }},0d
+{% endfor %}
+{% endfor %}
+'''
+
+
+class TimeLineGantt(Directive):
+    has_content = True
+    required_arguments = 2
+    optional_arguments = 0
+    final_argument_whitespace = True
+
+    template = jinja2.Environment().from_string(TIMELINE_TEMPLATE)
+
+    def _render_time_line(self, filename, display_releases):
+        try:
+            with open(filename) as f:
+                releases = yaml.safe_load(f)['releases']
+        except Exception as e:
+            message = f'Unable read release file: "{filename}": {e}'
+            self.error(message)
+
+        rendered = self.template.render(display_releases=display_releases,
+                                        releases=releases)
+        return rendered.splitlines()
+
+    def run(self):
+        filename = self.arguments[0]
+        display_releases = self.arguments[1].split()
+        document = self.state.document
+        env = document.settings.env
+        rel_filename, filename = env.relfn2path(filename)
+        env.note_dependency(filename)
+        lines = self._render_time_line(filename, display_releases)
+        lineno = self.lineno - self.state_machine.input_offset - 1
+        source = self.state_machine.input_lines.source(lineno)
+        self.state_machine.insert_input(lines, source)
+        return []
+
+
 def setup(app):
     app.add_directive('ceph_releases', CephReleases)
+    app.add_directive('ceph_releases_gantt', ReleasesGantt)
     app.add_directive('ceph_timeline', CephTimeline)
+    app.add_directive('ceph_timeline_gantt', TimeLineGantt)
     return {
         'parallel_read_safe': True,
         'parallel_write_safe': True
index 71d24d61104e4ad76534da1e6e3e713340070214..b972e5a77ba86344f7d2361a3fda3056b9620115 100644 (file)
@@ -124,6 +124,7 @@ extensions = [
     'ceph_commands',
     'ceph_releases',
     'ceph_confval',
+    'sphinxcontrib.mermaid',
     'sphinxcontrib.openapi',
     'sphinxcontrib.seqdiag',
     ]
index 0c04ecacfbaa0043ee2ce00ecc5ac035e6c82e86..bc4fe582116efa47a4385b8946181f9f4f58b283 100644 (file)
@@ -7,6 +7,8 @@ Ceph Releases (index)
 .. toctree::
    :maxdepth: 1
 
+.. ceph_releases_gantt:: releases.yml
+
 .. _active-releases:
 
 Active Releases
@@ -56,6 +58,7 @@ receive bug fixes or backports).
 Release timeline
 ----------------
 
+.. ceph_timeline_gantt:: releases.yml quincy pacific octopus
 .. ceph_timeline:: releases.yml quincy pacific octopus
 
 .. _Quincy: quincy