Extract JIRA issues 54/93254/24
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 22 Oct 2020 11:23:21 +0000 (13:23 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 23 Sep 2021 11:59:20 +0000 (13:59 +0200)
We want to capture a table of JIRA issues for a number of MRI project
versions.

Nothing in upstream fits the bill, so we introduce our own Sphinx
extension, which uses the jira module to extract information from JIRA
and embed it into our RTD site.

Since there is no spell checker running on JIRA, we exclude files in
release-notes/projects/ from the Sphinx spell checker.

Change-Id: I5b0ac293dca2442776753078dbd1c79a52684677
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
docs/conf.py
docs/ext/README.md [new file with mode: 0644]
docs/ext/odl-jira.py [new file with mode: 0644]
docs/release-notes/projects/controller.rst
docs/requirements.txt

index bb48fddb14de9257fe1e80ccb824d09939fb8cee..7d526ac427ff13e8f2d4afea8580ad0d2c9699e4 100755 (executable)
@@ -11,6 +11,7 @@
 ##############################################################################
 
 from docs_conf.conf import *
+import sys, os
 
 # Append to intersphinx_mapping
 intersphinx_mapping['aaa'] = ('https://docs.opendaylight.org/projects/aaa/en/latest/', None)
@@ -81,11 +82,15 @@ nitpicky = True
 release = version
 
 spelling_warning = True
-spelling_exclude_patterns = ['release-notes/release-notes-*']
+spelling_exclude_patterns = ['release-notes/release-notes-*', 'release-notes/projects/*']
 
 html_context = {
     'version_status': 'supported',
 }
 
+# Helper for JIRA references
+sys.path.append(os.path.abspath('ext'))
+extensions.append('odl-jira')
+
 def setup(app):
     app.add_css_file("css/ribbon.css")
diff --git a/docs/ext/README.md b/docs/ext/README.md
new file mode 100644 (file)
index 0000000..a7b18f3
--- /dev/null
@@ -0,0 +1,3 @@
+Sphinx extensions
+
+TODO: add proper linking
diff --git a/docs/ext/odl-jira.py b/docs/ext/odl-jira.py
new file mode 100644 (file)
index 0000000..400eba8
--- /dev/null
@@ -0,0 +1,175 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v1.0 which accompanies this distribution,
+# and is available at http://www.eclipse.org/legal/epl-v10.html
+"""
+
+Embeds a simple table with issues.
+
+"""
+
+from docutils import nodes
+from docutils.parsers.rst import directives, Directive
+from jira import JIRA
+import re
+import sphinx
+
+__copyright__ = "Copyright(c) 2021 PANTHEON.tech, s.r.o."
+__license__ = "Eclipse Public License v1.0"
+
+class JiraFixedIssuesDirective(Directive):
+    """
+    JIRA Fixed Issues directive
+    """
+    has_content = True
+    required_arguments = 0
+    optional_arguments = 0
+
+    option_spec = {
+        "project": directives.unchanged_required,
+        "versions": directives.unchanged_required,
+    }
+
+    def run(self):
+        jira = JIRA(server="https://jira.opendaylight.org")
+        prj = jira.project(self.options.get('project'))
+        (from_ver, to_ver) = self.options.get('versions').split('-', 1)
+
+        versions = set()
+        for ver in jira.project_versions(prj):
+            if ver.name >= from_ver and ver.name <= to_ver:
+                versions.add(ver.name)
+        versions = ", ".join(versions)
+
+        # FIXME: this is not quite nice: can we emit the table markup directly
+        table = [
+            '.. list-table:: Issues resolved in versions %s through %s' % (from_ver, to_ver),
+            # FIXME: bind to https://datatables.net/
+            '   :class: datatable',
+            '   :header-rows: 1',
+            '   :widths: auto',
+            '',
+            '   * - Type',
+            '     - Key',
+            '     - Summary',
+            '     - Resolution',
+            '     - Fix Version(s)',
+        ]
+
+        issues = jira.search_issues('project = %s AND resolution is not EMPTY AND fixVersion in (%s) ORDER BY type ASC' % (prj, versions))
+        for issue in issues:
+            # Groom fixVersions
+            fixVersions = set()
+            for version in issue.fields.fixVersions:
+                fixVersions.add(version.name)
+            fixVersions = list(fixVersions)
+            fixVersions.sort()
+
+            table.append('   * - .. image:: %s' % issue.fields.issuetype.iconUrl)
+            table.append('          :align: center')
+            table.append('          :alt: %s' % issue.fields.issuetype.name)
+            table.append('     - `%s <https://jira.opendaylight.org/browse/%s>`_' % (issue.key, issue.key))
+            table.append('     - %s' % issue.fields.summary)
+            table.append('     - %s' % issue.fields.resolution)
+            table.append('     - %s' % ", ".join(fixVersions))
+
+        table.append('')
+
+        for idx, line in enumerate(table):
+            self.content.data.insert(idx, line)
+            self.content.items.insert(idx, (None, idx))
+
+        node = nodes.container()
+        self.state.nested_parse(self.content, self.content_offset, node)
+        return node.children
+
+class JiraKnownIssuesDirective(Directive):
+    """
+    JIRA Known Issues directive
+    """
+    has_content = True
+    required_arguments = 0
+    optional_arguments = 0
+
+    option_spec = {
+        "project": directives.unchanged_required,
+        "versions": directives.unchanged_required,
+    }
+
+    def run(self):
+        jira = JIRA(server="https://jira.opendaylight.org")
+        prj = jira.project(self.options.get('project'))
+        (from_ver, to_ver) = self.options.get('versions').split('-', 1)
+
+        versions = set()
+        for ver in jira.project_versions(prj):
+            if ver.name >= from_ver and ver.name <= to_ver:
+                versions.add(ver.name)
+        versions = ", ".join(versions)
+
+        # FIXME: this is not quite nice: can we emit the table markup directly
+        table = [
+            '.. list-table:: Issues affecting versions %s through %s' % (from_ver, to_ver),
+            # FIXME: bind to https://datatables.net/
+            '   :class: datatable',
+            '   :header-rows: 1',
+            '   :widths: auto',
+            '',
+            '   * - Type',
+            '     - Key',
+            '     - Summary',
+            '     - Status',
+            '     - Affected Version(s)',
+            '     - Fix Version(s)',
+        ]
+
+        issues = jira.search_issues('project = %s AND affectedVersion in (%s) AND fixVersion NOT in (%s) ORDER BY type ASC' % (prj, versions, versions))
+        for issue in issues:
+            # Groom fixVersions
+            fixVersions = set()
+            for version in issue.fields.fixVersions:
+                fixVersions.add(version.name)
+            fixVersions = list(fixVersions)
+            fixVersions.sort()
+
+            # Groom affectedVersions
+            affectedVersions = set()
+            for version in issue.fields.versions:
+                affectedVersions.add(version.name)
+            affectedVersions = list(affectedVersions)
+            affectedVersions.sort()
+
+            table.append('   * - .. image:: %s' % issue.fields.issuetype.iconUrl)
+            table.append('          :align: center')
+            table.append('          :alt: %s' % issue.fields.issuetype.name)
+            table.append('     - `%s <https://jira.opendaylight.org/browse/%s>`_' % (issue.key, issue.key))
+            table.append('     - %s' % issue.fields.summary)
+            table.append('     - %s' % issue.fields.status)
+            table.append('     - %s' % ", ".join(affectedVersions))
+            table.append('     - %s' % ", ".join(fixVersions))
+
+        table.append('')
+
+        for idx, line in enumerate(table):
+            self.content.data.insert(idx, line)
+            self.content.items.insert(idx, (None, idx))
+
+        node = nodes.container()
+        self.state.nested_parse(self.content, self.content_offset, node)
+        return node.children
+
+def setup(app):
+    """
+    :type app: sphinx.application.Sphinx
+    """
+    app.add_directive('jira_fixed_issues', JiraFixedIssuesDirective)
+    app.add_directive('jira_known_issues', JiraKnownIssuesDirective)
+
+    return {
+        'version': '0.1',
+        'parallel_read_safe': True,
+        'parallel_write_safe': True,
+    }
+
index 0fbe8c87bd8a191b19753f13a5a8d3814287b0ba..c891f289a9e290f8179bd380985c8134407edeac 100644 (file)
@@ -9,12 +9,6 @@ The Controller project is an infrastructure service that supports other OpenDayl
 It does not have user-facing features.
 
 
-Changes in Phosphorus release stream
-====================================
-There is a comprehensive list of JIRA issues
-`resolved in this release <https://jira.opendaylight.org/issues/?jql=project%20%3D%20CONTROLLER%20AND%20fixVersion%20in%20(4.0.0%2C%204.0.1%2C%204.0.2%2C%204.0.3)>`__
-
-
 Behavior/Feature Changes
 ========================
 
@@ -36,9 +30,21 @@ There are no deprecated features in this release, but there is a large number of
 * prefix-based shards have been completely removed
 * the proof-of-concept ``messagebus`` component was removed
 
+Resolved Issues
+===============
+
+The following table lists the issues resolved in this release.
+
+.. jira_fixed_issues::
+   :project: CONTROLLER
+   :versions: 4.0.0-4.0.3
+
 Known Issues
 ============
 
-Here is the link to the known issues exist in this release:
+The following table lists the known issues that exist in this release.
+
+.. jira_known_issues::
+   :project: CONTROLLER
+   :versions: 4.0.0-4.0.3
 
-`OpenDaylight JIRA Tickets - Known Issue <https://jira.opendaylight.org/issues/?jql=project+%3D+controller+AND+type+%3D+Bug+AND+status+not+in+%28Resolved%2C+Done%2C+Closed%29+ORDER+BY+issuetype+DESC%2C+key+ASC>`_
index a92da717a964cb993c219248a421bb60f6e1a215..dd1e40f76996886e640151946c5ac33c8ec55af7 100644 (file)
@@ -1 +1,2 @@
 lfdocs-conf>0.6.1
+jira