From 729f31198c06194b5d198b92573c84ab25113042 Mon Sep 17 00:00:00 2001 From: Ron Stone Date: Wed, 4 Jun 2025 14:34:41 +0000 Subject: [PATCH] Reimplement table col/row conditionalization (r10) Reimplement table column and row removal to be output format agnostic. Change-Id: I4822d53d37fd4604bf45c4bc4a315c8fc904376a Signed-off-by: Ron Stone --- .../contributor/doc_contribute_guide.rst | 4158 ++++++++--------- remove-grid-columns.py | 476 ++ remove-list-columns.py | 153 + remove_empty-grid_rows.py | 68 + remove_empty-list_rows.py | 203 + tox.ini | 8 +- 6 files changed, 2985 insertions(+), 2081 deletions(-) create mode 100644 remove-grid-columns.py create mode 100644 remove-list-columns.py create mode 100644 remove_empty-grid_rows.py create mode 100644 remove_empty-list_rows.py diff --git a/doc/source/contributor/doc_contribute_guide.rst b/doc/source/contributor/doc_contribute_guide.rst index 93db67403..3bcbb4793 100644 --- a/doc/source/contributor/doc_contribute_guide.rst +++ b/doc/source/contributor/doc_contribute_guide.rst @@ -1,2080 +1,2080 @@ -.. include:: /_vendor/rl-strings.txt - -.. _doc_contribute_guide: - -=============================== -Documentation Contributor Guide -=============================== - -This section describes the guidelines for contributing to the StarlingX -documentation. - -.. contents:: - :local: - :depth: 1 - ----------- -Quickstart ----------- - -The StarlingX documentation uses reStructuredText (RST) markup syntax with -Sphinx extensions. It uses the same contribution setup and workflow as the -OpenStack documentation. - -* `OpenStack Documentation Contributor Guide `_. - -.. note:: - - The supported version of tox is currently pinned at 2.9.1. If possible, - using this version is recommended for local builds. - -********************** -Setup for contribution -********************** - -Follow the OpenStack instructions for `setting up for contribution -`_. - -************* -Make a change -************* - -#. Make changes following the OpenStack instructions for: - - #. `Starting a change `_ - #. `Committing a change `_. - - .. note:: - - StarlingX requires the use of a **Signed-off-by** header. Use the - :command:`-s` option with :command:`git commit`. - - -#. When writing documentation, follow `Writing style`_ and `RST conventions`_. - -#. Build the documentation locally to verify your changes before committing. - Follow the OpenStack instructions for - `Building documentation `_. - -#. If needed, follow up with edits to your patch following the OpenStack - instructions for `Responding to requests `_. - -.. build-singledoc-begin - -It can sometimes be useful to search the output globally for a string that may -not be reliably returned by the built-in search functionality. For example, you -may need to find and update all instances of a version number or container name. - -You can generate HTML output to a single page and use your browser's search -functionality to search globally. - -To build all documentation as a single page, run the following command from -your local clone of the documentation repository: - -.. code-block:: bash - - $ tox -e singledoc - -The output will be available in **/``doc/build/singlepage`` - -.. note:: - - The quality checks done at the end of the build scan the most recent output - from running :command:`tox -e docs` and do not reflect any errors or - corrections in ``singledoc`` output. - -.. build-singledoc-end - --------------------------- -Find tasks and help needed --------------------------- - -If you are looking for work to complete: - -* Refer to the `StarlingX documentation StoryBoard - `_ for topics that - need content. Many topics have stub pages in the documentation with a link to - the associated story. - -* Find open `documentation bugs on Launchpad - `_. - - -If you make a contribution that has an the associated story, task, or bug in the -comment, link to the related story or bug as described in the -:ref:`Code Submission Guidelines `. - ------------------ -Docs organization ------------------ - -Documentation for StarlingX is organized into the following sections: - -:ref:`Introduction ` - Overview of the StarlingX project. - -:ref:`Deployment Configurations ` - Supported deployment configuration options. - -:ref:`Planning ` - Requirements planning guidance. - -:ref:`Installation ` - Release-specific installation and deployment guides. - -:ref:`Security ` - Detailed discussion of security configuration. - -:ref:`System Configuration ` - Detailed discussion of various post-installation configuration changes. - -:ref:`Data Networks ` - Discussion of |prod| data network configuration and management. - -:ref:`Node Management ` - Discussion of |prod| node configuration and management. - -:ref:`Backup and Restore ` - Discussion of |prod| backup and restore procedures. - -:ref:`Updates and Upgrades ` - Discussion of |prod| update and upgrade procedures. - -:ref:`KubeVirt ` - Overview of |VM| support using KubeVirt. - -:ref:`Admin Tasks ` - Overview of common administrator tasks. - -:ref:`User Tasks ` - Overview of common user tasks. - -:ref:`Guest Integration ` - Overview of various guest integrations. - -:ref:`Distributed Cloud ` - Discussion of |prod| |prod-dc| for edge computing. - -:ref:`Sample Application Deployment ` - -:doc:`/archive/configuration/index` - Configuration references for post-installation StarlingX system configuration. - -:doc:`/operations/index` - System administration and maintenance guides. - -:doc:`/api-ref/index` - REST API references for the StarlingX project. For additional information - about where REST API documentation is located, see `API documentation`_. - -:doc:`/cli_ref/index` - Reference for the StarlingX project command line interface (CLI). - -:doc:`/developer_resources/index` - Resources for developers using or building StarlingX. - -:doc:`/releasenotes/index` - Release notes for all StarlingX releases. - -:doc:`/contributor/index` - Overview and guidelines for contributing to StarlingX documentation. - -***************** -API documentation -***************** - -The structure and location of the REST API documentation deserves extra -explanation. - -Most REST API content is generated from the StarlingX project associated with -the API. For example, the documentation for the StarlingX metal REST API is -generated from the `metal repository `_. - -API references for StarlingX extensions are part of the docs repository, located -in the ``api-ref`` project: - -* StarlingX extensions to the OpenStack Block Storage API -* StarlingX extensions to the OpenStack Compute API -* StarlingX extensions to the OpenStack Image API -* StarlingX extensions to the OpenStack Networking API - -The ``api-ref`` project also contains index pages used by Sphinx to -generate the final content tree. Note that the REST API landing page used to -render content in the generated website is found in the ``doc`` project. - -For additional information on the API documentation, refer to -:doc:`api_contribute_guide`. - -****************** -Spec documentation -****************** - -Spec documentation is found in the -`Starlingx specs project `_. - -The ``specs/2019.03`` directory contains the documentation files for approved -and implemented specs. - ------------------- -Document structure ------------------- - -.. begin-document-structure - -.. _index-rules: - -*********** -Index rules -*********** - -Each document consists of one main Sphinx index file, with two optional ones -for each of Kubernetes and OpenStack content, if applicable. - -The index file contains one or more *toctrees*, which define the manifest and -structure of topics to be included in the document. The index file must be at -the root of the document's folder structure. If your document contains a mix of -Kubernetes and OpenStack topics, create a subdirectory for each with an index -file for those topics and link it to the top-level index. - -For example: - -.. code-block:: bash - - $ mkdir -p doc/source/newbook - $ cd doc/source/newbook - $ mkdir kubernetes - $ mkdir opemstack - $ tox -e newfile # follow instructions for creating a new index stub - $ cd kubernetes - $ tox -e newfile # create an index stub for kubernetes content - $ cd ../openstack - $ tox -e newfile # create an index stub for OpenStack content - -See :ref:`create-rst-files` for details on using :command:`tox -e newfile` - -In the book's main index under :file:`doc/source/newbook`, create entries to -the two subindexes: - -.. code-block:: none - - ========== - Kubernetes - ========== - - .. toctree:: - - kubernetes/index-768a6e9aaeff - - ========= - OpenStack - ========= - - .. toctree:: - - openstack/index-1b466179efc3 - -Add your Kubernetes and OpenStack content to the -:file:`kubernetes/index-768a6e9aaeff.rst` and -:file:`openstack/index-1b466179efc3.rst` files respectively. (Note that the -random strings ``768a6e9aaeff`` and ``1b466179efc3`` were added by -:command:`tox -e newfile` and will differ in your usage.) - -.. important:: - - Additional indexes, either at the root of the document or in subfolders, are - not allowed. - - The following images provide examples of correct and incorrect layouts. - - .. figure:: figures/index-structure-ok-2.png - - **Correct Kubernetes/OpenStack layout** - - - .. figure:: figures/index-structure-wrong.png - - **Incorrect Kubernetes/OpenStack layout** - - - Use section headings in the index file to define document structure. For - example: - - .. code-block:: - - .. _contribute: - - ================== - Contributor Guides - ================== - - Welcome to the StarlingX community! We are glad you are here. - - If you are new to the project, take a moment to review the - `StarlingX wiki `_. - - --------------------------- - Contribute to documentation - --------------------------- - - .. toctree:: - :maxdepth: 1 - - doc_contribute_guide - api_contribute_guide - release_note_contribute_guide - blog_contribute_guide - website_contribute_guide - - - - ------------------ - Contribute to code - ------------------ - - StarlingX follows the `OpenStack developer contribution guidelines - `_. Additional - StarlingX-specific resources are listed below. - - .. toctree:: - :maxdepth: 1 - - development_process - /developer_resources/code-submission-guide - /developer_resources/debug_issues - - -------------------- - Additional resources - -------------------- - - * `StarlingX wiki `_ - * :doc:`/developer_resources/index` - -.. end-document-structure - -**************** -Folder structure -**************** - -For any new document, create a new directory under :file:`source`. Create a -subdirectory called :file:`figures` to hold images. - -* for short, simple documents, you can place index and topic files directly in - this new document directory. - -* for more complex documents with multiple chapters, create one subdirectory - for each chapter, for example, :file:`source//developer_resources`. - -* for documents that distinguish between Kubernetes and OpenStack, create one - subdirectory for each. Any chapter directory should be created under these. - For example: :file:`source//kubernetes/developer_resources`. - - See the section on :ref:`index-rules` for more information. - - -------------- -Writing style -------------- - -.. begin-writing-style - -StarlingX documentation follows many (but not all!) of the writing style -guidelines described in the `OpenStack documentation writing style guide -`_. -Differences between the StarlingX and OpenStack practices are highlighted -below. - -* Use Title Case for page titles. For example: - - :: - - =============================== - Documentation Contributor Guide - =============================== - -* Start section titles with an action verb. Do not use a gerund (word that ends - with -ing). For example: - - :: - - ------------------ - Configure endpoint - ------------------ - -.. end-writing-style - -.. _create-rst-files: - ----------------- -Create rST Files ----------------- - -.. begin-create-rst-files - -Use the :command:`tox -e newfile` command to create new |RST| files. - -.. rubric:: |context| - -All |RST| files created in StarlingX documentation repositories must have the -following characteristics: - -* They must have unique file names. -* They must have |RST| labels at the beginning of the files that match the file - names. - -.. important:: - These rules apply to *index* files as well as those containing user - documentation. - -A utility is available for use from within each documentation repository you -have installed to generate uniquely named files for you. - -.. rubric:: |prereq| - -You must have :program:`uuidgen` installed on your system. This program is -included by default on most modern Linux distributions. If it is not installed, -consult your distribution's documentation for instructions. - -.. rubric:: |proc| - -#. Change to the directory where you wish to create a new topic. - - Typically, this will be below the :file:`doc/source` directory of the - repository. - -#. Run the following :command:`tox` command. - - .. code-block:: bash - - tox -e newfile - -#. When prompted, enter a title for the new topic. - - .. code-block:: none - :emphasize-lines: 3 - - You are about to create a new reStructuredText file in - - /home/jdoe/starlingx/docs/doc/source/intro - - or a content fragment file in doc/source/_includes - - If this is not what you want, press CTL-C to quit and change to the directory - you want to create the file in. - - Enter a title for the new topic. The file name and topic label used for - linking will be based on this value. - - - Topic title: - - #. Review the directory (an example is highlighted above) that the utility - will create the new file in. - - .. note:: - This does not apply if you choose to create a content fragment using - the :kbd:`f` option when prompted. In that case, the file will be - saved to :file:`doc/source/_includes` regardless of your current - working directory. - - #. If this is not correct, press :kbd:`CTL-C` to quit, change to the correct - directory, and run the command again; otherwise, type the topic title and - press :kbd:`ENTER`. - -#. When prompted, select the type of |RST| stub file you want to create. - - .. code-block:: none - - Thanks. Now choose a topic type. Enter one of the following characters: - - t) A task topic. Will contain the outline of a procedure. - i) An index. - r) A reference topic. Will contain a minimal list-table definition. - g) A minimal generic topic. - f) A content fragment included in an rST file. Will be saved to doc/source/_includes. - Topic type: - - Each option creates a stub file with different templated content useful for - getting started. Press the corresponding key. - -.. rubric:: |result| - -The new |RST| file is created. - - -The title used in the new |RST| file matches what you typed exactly. However, -some changes have been made to the file name and topic label. - -For example, if you entered ``Architectural Considerations!`` as a title, -listing the directory will show a file similar to the following: - -.. code-block:: bash - - $ ls - -.. code-block:: none - - architectural-considerations--d9dd4c105700.rst - -The following changes were made. - -* All alphabetical characters were converted to lower case. -* *Not shown* The characters ``+``, ``-``, ``@``, and ``&`` are replaced with - ``plus``, ``minus``, ``at``, and ``and`` respectively. -* All spaces and other special characters, such as the ``!`` were replaced by - dashes. -* A final dash and 12 digit random string were appended to the file name. -* The extension :file:`.rst` was added for all options except :kbd:`f`, in - which case the extension :file:`.rest` was added. -* If you chose to create an ``index`` file by selecting :kbd:`i` when prompted, - :file:`index-` was prepended to the file name. - -Examining the file reveals that the label matches the file name, while the -title is preserved as typed. No label was added if you selected :kbd:`f`. - -.. code-block:: bash - - cat architectural-considerations--d9dd4c105700.rst - -.. code-block:: none - :emphasize-lines: 1,4 - - .. _architectural-considerations--d9dd4c105700: - - ============================= - Architectural Considerations! - ============================= - - .. content here - -When you reference this file in ``toctree`` and ``ref`` directives, use -the file name/label string like this: ``architectural-considerations--d9dd4c105700`` - -.. end-create-rst-files - --------------------- -Using tabbed content --------------------- - -Content on the master branch can take advantage of the ``sphinx-tabs`` -extension to organize content into tabs. - - -.. begin-using-tabbed-content - - -Tabs are useful for presenting alternate sets of content in a way that does not -require that the reader interact with sets that are not of interest. This is -particularly useful in procedures where some steps vary across two or more -variable factors. Rather than maintain two or more separate procedures, tabs -can be used to show one of the alternate sets of content. For example, the -|prod| installation procedures make heavy use of tabs to allow the reader to -switch between virtual and bare-metal versions of the procedures. - -.. only:: starlingx - - See :ref:`aio_simplex_install_kubernetes_r7` for an example. - -**Basic tabs** - -Basic tabs are stand-alone. They have no relationship to other tabbed content -on a page. - -.. code-block:: rst - - .. tabs:: - - .. tab:: Apples - - Apples are green, or sometimes red. - - .. tab:: Pears - - Pears are green. - - .. tab:: Oranges - - Oranges are orange. - -.. tabs:: - - .. tab:: Apples - - Apples are green, or sometimes red. - - .. tab:: Pears - - Pears are green. - - .. tab:: Oranges - - Oranges are orange. - -**Nested tabs** - -Tab sets can be defined within other tab sets. While this can be useful for -organizing logical hierarchies of information, care should be taken not to make -readers 'dig' for relevant content, making it unnecessarily difficult to find. - -.. tip:: - - Remember that the organizational goal of tabs is hide irrelevant information - while *making all relevant information visible*. - -.. code-block:: rst - - .. tabs:: - - .. tab:: Stars - - .. tabs:: - - .. tab:: The Sun - - The closest star to us. - - .. tab:: Proxima Centauri - - The second closest star to us. - - .. tab:: Polaris - - The North Star. - - .. tab:: Moons - - .. tabs:: - - .. tab:: The Moon - - Orbits the Earth - - .. tab:: Titan - - Orbits Jupiter - -.. tabs:: - - .. tab:: Stars - - .. tabs:: - - .. tab:: The Sun - - The closest star to us. - - .. tab:: Proxima Centauri - - The second closest star to us. - - .. tab:: Polaris - - The North Star. - - .. tab:: Moons - - .. tabs:: - - .. tab:: The Moon - - Orbits the Earth - - .. tab:: Titan - - Orbits Jupiter - -**Group tabs** - -Tab sets can be grouped so that switching to a tab with a certain name in one -set causes all other tab sets on the page to switch to the same tab. This can -be very useful when the same alternatives recur many times on the same page. -The reader only needs to select the tab that is relevant to them once to have -the entire page switch to the appropriate content. - -Do this by using the ``.. group-tab::`` directive in place of the ``.. tab::`` -directive and by being sure to label all tabs consistently across tab sets. - -In the example below, a reader can switch all tab sets to :guilabel:`Linux`, -:guilabel:`Mac OSX`, or :guilabel:`Windows` by making the selection once, in -any of the tab sets. - -.. code-block:: rst - - .. tabs:: - - .. group-tab:: Linux - - Linux tab content - tab set 1 - - .. group-tab:: Mac OSX - - Mac OSX tab content - tab set 1 - - .. group-tab:: Windows - - Windows tab content - tab set 1 - - .. tabs:: - - .. group-tab:: Linux - - Linux tab content - tab set 2 - - .. group-tab:: Mac OSX - - Mac OSX tab content - tab set 2 - - .. group-tab:: Windows - - Windows tab content - tab set 2 - - .. tabs:: - - .. group-tab:: Linux - - Linux tab content - tab set 3 - - .. group-tab:: Mac OSX - - Mac OSX tab content - tab set 3 - - .. group-tab:: Windows - - Windows tab content - tab set 3 - -Try it out for yourself here: - -.. tabs:: - - .. group-tab:: Linux - - Linux tab content - tab set 1 - - .. group-tab:: Mac OSX - - Mac OSX tab content - tab set 1 - - .. group-tab:: Windows - - Windows tab content - tab set 1 - -.. tabs:: - - .. group-tab:: Linux - - Linux tab content - tab set 2 - - .. group-tab:: Mac OSX - - Mac OSX tab content - tab set 2 - - .. group-tab:: Windows - - Windows tab content - tab set 2 - -.. tabs:: - - .. group-tab:: Linux - - Linux tab content - tab set 3 - - .. group-tab:: Mac OSX - - Mac OSX tab content - tab set 3 - - .. group-tab:: Windows - - Windows tab content - tab set 3 - -*********************************** -Considerations for alternate builds -*********************************** - -It is important to make allowances for builds of StarlingX documentation in -contexts that may not support tabs, such as by other parties or for print -output. To support such environments, the use of tabs must be conditionalized -and the related content repeated for non tab scenarios. The following sample -illustrates the standard way to achieve this: - -.. code-block:: - - .. only:: starlingx and html - - .. tabs:: - - .. group-tab:: Bare Metal - - .. begin-install-prereqs-bm - - .. include:: /shared/_includes/installation-prereqs.rest - :start-after: begin-install-prereqs - :end-before: end-install-prereqs - - .. end-install-prereqs-bm - - .. group-tab:: Virtual - - .. begin-install-prereqs-virt - - Several pre-requisites must be completed prior to starting the |prod| - installation. - - Before attempting to install |prod|, ensure that you have the the - |prod| host installer ISO image file. - - Get the latest |prod| ISO from the `StarlingX mirror - `__. - Alternately, you can get an older release ISO from `here `__. - - .. end-install-prereqs-virt - - - .. only:: partner and (html or latex) - - ********** - Bare Metal - ********** - - .. include:: /deploy_install_guides/release/bare_metal/aio_duplex_install_kubernetes.rst - :start-after: begin-install-prereqs-bm - :end-before: end-install-prereqs-bm - - ******* - Virtual - ******* - - .. include:: /deploy_install_guides/release/bare_metal/aio_duplex_install_kubernetes.rst - :start-after: begin-install-prereqs-virt - :end-before: end-install-prereqs-virt - -In this example, the tabbed content is conditionalized to only appear in -StarlingX HTML output (``.. only:: starlingx and html``). - -The ``.. begin-install-prereqs-bm``, ``.. end-install-prereqs-bm``, ``.. -begin-install-prereqs-virt`` and ``.. end-install-prereqs-virt`` comments allow -the contents of the ``Bare Netal`` and ``Virtual`` tabs to be included -conditionally in other builds that do not support tabs. In this example the -content is conditionalized in the ``.. only:: partner and (html or latex)`` -block. - -.. end-using-tabbed-content - ------------------------- -Automated quality checks ------------------------- - -.. begin-automated-quality-checks - -Several automated checks are available to help improve and maintain the quality -of your documentation. - -Some of these checks are run every time you perform a build and are intended to -catch errors before they are submitted for review. Others are invoked -independently of regular builds and are intended to identify problems prior to -a release. - -***************** -Formatting checks -***************** - -.. begin-post-build-checks - -You can build the HTML documentation locally using the ``tox -e docs`` command. -After every successful build, several quality checks are performed against the -build HTML output. - -.. parsed-literal:: - - Checking for "grey bar" formatting errors in output ... - Found 2 HTML file(s) with greybar formatting issues: - ./dist_cloud/kubernetes/reinstalling-a-subcloud-with-redfish-platform-management-service.html - ./dist_cloud/kubernetes/installing-a-subcloud-without-redfish-platform-management-service.html - Using a browser, locate vertical grey bars in the left margin of the above file(s), then correct the issue(s) in the corresponding rST file(s). - Checking for ".. include::" errors in output ... - Checking for unexpanded substitution errors in output ... - Found 1 HTML file(s) that may have unexpanded substitution(s): - - ./node_management/kubernetes/hardware_acceleration_devices/enabling-mount-bryce-hw-accelerator-for-hosted-vram-containerized-workloads.html:| 1d02 | |html-pipe|\ SATA\ |html-pipe| controller | Intel Corporation | - - Correct the issue(s) in the corresponding rST file(s). - -This sample shows three problems. - -.. list-table:: Post-check issues and remedies - :header-rows: 1 - :stub-columns: 1 - :widths: auto - - * - Test - - Explanation - - Remedy - * - Grey bars - - Scans the output for evidence of |RST| vertical grey bars inserted into the - output next to formatting errors and reports which files they were found - in.​ - - #. Open the file :file:`doc/build/html/index.html` in a browser and - navigate to the page reported in the output. - - #. Locate the grey bars. - - .. tip:: - Grey bars can be hard to find in some locations, such as notes, - where they are obscured by a background fill. Look for other - evidence of a problem such as an oversized font, text that - appears to be randomly bolded, or senseless line breaks. - - #. Open the corresponding :file:`.rst` file and find the location - matching the grey bars in the output. - #. Correct the issue. - - .. hint:: - Grey bars are often caused by indentation errors. - * - Include errors - - Scans the output for malformed ``.. include::`` statements that result - in |RST| code and unintended content being exposed and reports which - files they were found in.​ - - As above, find the problem in the appropriate - :file:`.rst` file by examining the :file:`.html` file reported. Look for - code fragments associated with ``.. include::`` directives such as - :start\ |html-comment|-after: and :end\ |html-comment|-before: - that have been exposed in the final output. - - Correct the issues by making the code comply with the documentation at: - - https://docutils.sourceforge.io/docs/ref/rst/directives.html#include - * - Substitution errors - - Scans the output for potential unexpanded substitutions such as - |html-pipe|\ prod\ |html-pipe| and reports which files they were found in, along with the - offending lines of HTML. - - .. note:: - This check cannot distinguish between a substitution and an ascii - output table where cells are not properly padded. In either case, the - problem needs to be fixed. - - - As above, find the problem in the appropriate :file:`.rst` file by - examining the :file:`.html` file reported. Look for |html-pipe|\ \ |html-pipe| code - exposed in the output. In the corresponding :file:`.rst`, find and - correct the issue. - - .. hint:: - Substitutions are not allowed in code blocks, :ref:, :doc:, - or within |RST| markup such as ``**``, ``*```, `````, and so on. - - Substitutions cannot be used in ASCII "picture" style tables. If you - need a substitution in a table, use the ``.. list-table::`` format - instead. - -.. end-post-build-checks - -*********** -Link checks -*********** - -Link checks are not performed as part of regular documentation builds. They are -intended to be run periodically and prior to a release. - -You can invoke the Sphinx link checker with the following command: - -.. code-block:: bash - - $ tox -e linkcheck - -Sphinx will perform a temporary build and then attempt to follow all external -links from the output files. Results are reported on the console and -logged for future use. - -.. note:: - - You may need to disconnect any corporate firewall or VPN to allow the link - checker to reach external sites. - -**Console output** - -The following two lines illustrate output for a valid and a bad link on lines 1 -and 2 respectively. In each case the name of the file being checked, the line -number the link was found on, and the link itself are reported. In the case of -a broken link, the server error code is also shown, in this case a 404 *file -not found* error. This indicates that the page may have moved or been deleted. - -.. code-block:: none - :linenos: - - (developer_resources/build_docker_image: line 120) ok https://mirror.starlingx.windriver.com/mirror/starlingx/master/centos/latest_docker_image_build/outputs/wheels/stx-centos-stable-wheels.tar - (developer_resources/build_docker_image: line 122) broken https://mirror.starlingx.windriver.com/mirror/starlingx/master/centos/latest_docker_image_build/outputs/wheels/stx-centos-dev-wheels.tar - 404 Client Error: Not Found for url: https://mirror.starlingx.windriver.com/mirror/starlingx/master/centos/latest_docker_image_build/outputs/wheels/stx-centos-dev-wheels.tar - -**Logs** - -Non "OK" results such as *file not found* and *permanent redirect* are -logged under :file:`doc/build/linkcheck` in two files: - -* :file:`doc/build/linkcheck/output.txt` provides a results log in plain-text - format. - -* :file:`doc/build/linkcheck/output.json` provides the same information in - ``JSON`` format. - -Investigate all issues and update the links as needed. In the case of permanent -redirects, replace the existing URL with that of the redirect target. - -************ -Spell checks -************ - -Spell checks are not performed as part of regular documentation builds. They -are intended to be run periodically and prior to a release. - -You can invoke the Sphinx link checker with the following command: - -.. code-block:: bash - - $ tox -e spellcheck - -Sphinx will perform a temporary build and then check the output against a US -English dictionary. Results are reported on the console and logged for future -use. - -**Console output** - -Console output shows the path and name of the file an error was found in, the -line number, the misspelled term and the full line to provide context. - -.. code-block:: none - - doc/source/storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:41: Spell check: aditional: used as aditional disk volumes for VMs booted from images. - - -**Logs** - -Spell check logs are stored under :file:`doc/build/spelling` in -:file:`*.spelling` files located and named for their :file:`rst` counterparts. - -For example, errors found in the file: - -:file:`doc/source/storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst` - -are logged in the file: - -:file:`doc/build/spelling/storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.spelling` - -Log files itemize one issue per line. For example: - -.. code-block:: none - - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:41: (aditional) used as aditional disk volumes for VMs booted from images - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:68: (num) For more information on how placement group numbers, (pg_num) can be set - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:72: (num) group numbers (pg_num) required based on pg_calc algorithm, estimates on - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:116: (num) To list all the pools with their pg_num values, use the following command, - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:119: (num) To get only the pg_num / pgp_num value, use the following command, - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:119: (num) To get only the pg_num / pgp_num value, use the following command, - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:142: (num) Increasing pg_num of a pool has to be done in increments of 64/ - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:142: (num) pg_num number, retry and wait for the cluster to be - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:149: (num) pg_num of that pool, using the following commands: - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:162: (num) pgp_num should be equal to pg_num. - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:162: (num) pgp_num should be equal to pg_num. - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:203: (num) pg_num, pgp_num, crush_rule. - storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:203: (num) pg_num, pgp_num, crush_rule - -Note that the spell check in this example matched on the substring ``num`` -several times in contexts such as ``pgp_num``. Cases such as this may call for -additional spell check customization. - -Adding words -************ - -|org| documentation makes use of many technical terms that are not known to the -default dictionary. - -You can add these to the file -:file:`doc/source/spelling_wordlist.txt`. - -This file contains one term per line. - -.. note:: - - * Care should be taken when adding terms to a custom dictionary to avoid - errors not being reported. For example, "fs" may be correct in a code - block but a typo in some other context. As a general rule, it is better - to have the spell checker over-report than under-report. - - * It is important that :file:`spelling_wordlist.txt` be kept in - alphabetical order. - - * :file:`spelling_wordlist.txt` is under :program:`git` management and - changes must be submitted for review and merge via a :program:`gerrit` - review. - -.. end-automated-quality-checks - ---------------- -RST conventions ---------------- - -StarlingX documentation follows many (but not all!) of the RST conventions -described in the `OpenStack documentation RST conventions guide -`_. If RST markup -is not listed in this section's quick reference, refer to the OpenStack guide. - -For detailed information about RST and Sphinx extensions, refer to the following -documents: - -* `Sphinx documentation `_ -* `reStructuredText primer `_ - --------------------------- -Command prompt conventions --------------------------- - -Command examples in |prod| are preceded by a shell prompt. These prompts -provide readers with important hints about the context in which the command is -to be used. It is important that the following prompts be used consistently -throughout the |prod| documentation. - -``$`` (dollar sign) - Used to indicate that a command should be run in a Linux terminal as a - regular user. - -``#`` (pound or hash sign) - Used to indicate that a command should be run in a Linux terminal as a - root user. - -``~(keystone_admin)]$`` - Used to indicate that the command must be run within the sourced environment - of a system controller, i.e. after running - - ``$ source /etc/platform/openrc`` - -------------- -Content reuse -------------- - -.. _using-includes: - -Content can be reused in multiple places using the Sphinx ``.. include::`` -directive. - -For example: - -.. code-block:: - - .. include:: /_includes/my_reusable_content.rest - -"Include" files must not end in ``.rst``. The StarlingX convention is to use -``.rest``. - -You can store multiple fragments of content in a single include file and use -them in various places. To do this, use ``rst`` comments to delineate where -each begins and ends: - -.. code-block:: - - .. begin-fragement-1 - - This content will be inserted using ``.. include::`` example 1, below. - - .. end-fragment-1 - - .. begin-fragement-2 - - This content will be inserted using ``.. include::`` example 2, below. - - .. end-fragment-2 - -To use one or the other in an ``rst`` topic, use the *start after* -and *end before* parameters as shown below: - -.. rubric:: **Example 1** - -.. parsed-literal:: - - ======== - My Topic - ======== - - Integer sed tortor nisi. Vivamus feugiat, urna in posuere gravida, ligula - nunc hendrerit magna, nec tristique ex tortor non lorem. - - ... - - .. include:: /_includes/my_reusable_content.rest - :start\ |html-comment|-after: begin-fragement-1 - :end\ |html-comment|-before: end-fragement-1 - -.. rubric:: **Example 2** - -.. parsed-literal:: - - ============== - My Other Topic - ============== - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. - - ... - - .. include:: /_includes/my_reusable_content.rest - :start\ |html-comment|-after: begin-fragement-2 - :end\ |html-comment|-before: end-fragement-2 - -********************** -Content reuse in steps -********************** - -.. begin-content--in-steps - -Inserting reusable or conditional steps in a numbered list context causes the -list to restart. For example: - -An include file, ``mysteps.rest``, containing: - -.. code-block:: rst - - .. begin-step - - #. Blue - - .. end-step - -used in an ``rst`` file as follows: - -.. parsed-literal:: - - #. Orange - - #. Red - - .. include:: mysteps.rest - :start\ |html-comment|-after: begin-step - :end\ |html-comment|-before: end-step - - #. Green - -Results in: - -1. Orange - -2. Red - -3. Blue - -4. Green - -To avoid this, use substitute .. pre\ |html-comment|-include:: for ``.. include::`` - -.. parsed-literal:: - - #. Orange - - #. Red - - .. pre\ |html-comment|-include:: mysteps.rest - :start\ |html-comment|-after: begin-step - :end\ |html-comment|-before: end-step - - #. Green - -This will result in the expected numbering sequence: - -1. Orange - -2. Red - -3. Blue - -4. Green - -.. note:: - - * Only the start\ |html-comment|-after and end\ |html-comment|-before - parameters work with .. pre\ |html-comment|-include::. - - * Indentation within the ``rest`` file being referenced must match the - calling context. - - * If the list is not indented, the additional step(s) to be inserted should - not be indented. - - * If the list is indented (a sublist or in a nested block context), the - same indentation must be applied to the additional steps. - -.. end-content--in-steps - --------------------------- -Content conditionalization --------------------------- - -**************************** -Conditionalize across builds -**************************** - -.. begin-conditionalize-content-across-builds - -If you need to conditionalize some content to be used in a specific build -context, such as StarlingX or a 3rd party build that reuses StarlingX content, -you can use the ``.. only::`` directive. - -For example: - -.. code-block:: - - .. only:: starlingx - - Integer sed tortor nisi. Vivamus feugiat, urna in posuere gravida, ligula - nunc hendrerit magna, nec tristique ex tortor non lorem. - -Three build contexts are available: - -``starlingx`` - Content will be included in the standard StarlingX documentation build. - -``partner`` - Content will be excluded from the StarlingX documentation build. To reuse - this content in a 3rd party build, ensure that the ``partner`` tag is based - to the builder. - -``openstack`` - Content will be included in an OpenStack documentation context. This content - is included in the StarlingX documentation build. - -.. end-conditionalize-content-across-builds - -*************************** -Conditionalize across pages -*************************** - -.. begin-conditionalize-content-across-pages - -If you want to reuse a block of content in multiple ``rst`` files from the same -build using ``.. include::`` directives, but need to exclude specific strings -from one of those locations, you can use the ``hideable`` role and substitution. - -You can hide both strings and blocks (paragraphs etc.). - -Hiding strings -************** - -To hide a string, use the ``hideable`` role. For example: - -.. code-block:: - - .. start-prepare-servers-common - - Prior to starting the |prod| installation, ensure that the |bare-metal| - servers are in the following state: - - ... - - - BIOS configured with Intel Virtualization (VTD, VTX) - - - Disabled for controller-only servers and storage servers. - - - Enabled for :hideable:`controller+worker (All-in-one) servers and` worker servers. - - - The servers are powered off. - - .. end-prepare-servers-common - -In the ``rst`` file where you want to include the text marked up with the -``:hideable:`` role, simply insert the content using the :ref:`include -` directive: - -.. parsed-literal:: - - .. _aio_duplex_install_kubernetes_r7: - - ================================================ - Install Kubernetes Platform on All-in-one Duplex - ================================================ - - ... - - -------------------------------- - Prepare Servers for Installation - -------------------------------- - - .. include:: /shared/_includes/prepare-servers-for-installation-91baad307173.rest - :start\ |html-comment|-after: start-prepare-servers-common - :end\ |html-comment|-before: end-prepare-servers-common - - ... - -The bullet: - -``- Enabled for :hideable:`controller+worker (All-in-one) servers and` worker servers.`` - -will render as: - -- Enabled for controller+worker (All-in-one) servers and worker servers. - - -In the ``rst`` file where you want to suppress the text marked up with the -``:hideable:`` role, do the same, but add the ``|hideable|`` substitution at the -top of the file: - -.. parsed-literal:: - - \|hideable\| - - .. _aio_duplex_install_kubernetes_r7: - - ================================================ - Install Kubernetes Platform on All-in-one Duplex - ================================================ - - ... - - -------------------------------- - Prepare Servers for Installation - -------------------------------- - - .. include:: /shared/_includes/prepare-servers-for-installation-91baad307173.rest - :start\ |html-comment|-after: start-prepare-servers-common - :end\ |html-comment|-before: end-prepare-servers-common - - ... - -The bullet: - -``- Enabled for :hideable:`controller+worker (All-in-one) servers and` worker servers.`` - -will render as: - -- Enabled for worker servers. - -Hiding blocks -************* - -To hide a block, wrap it in a ``container`` directive with the argument -``hideable`` - -For example, create an include file ``install-status.rest`` with the -following contents: - -.. code-block:: - - The **deploy status** field has the following values: - - .. container:: hideable - - ``Pre-Install`` - This status indicates that the ISO for the subcloud is being updated by - the Central Cloud with the boot menu parameters, and kickstart - configuration as specified in the ``install-values.yaml`` file. - - ``Installing`` - This status indicates that the subcloud's ISO is being installed from - the Central Cloud to the subcloud using the Redfish Virtual Media - service on the subcloud's |BMC|. - - .. container:: - - ``Bootstrapping`` - This status indicates that the Ansible bootstrap of |prod-long| - software on the subcloud's controller-0 is in progress. - -and load it in two different contexts: - -.. code-block:: - :caption: a.rst - - .. include:: install-status.rest - -.. code-block:: - :caption: b.rst - - |hideable| - - .. include:: install-status.rest - -The output from ``a.rst`` will include all three definitions. The output from -``b.rst`` will include only the ``bootstrap`` definition. - -.. end-conditionalize-content-across-pages - -------------------------- -Removing empty table rows -------------------------- - -.. begin-hide-empty-rows - -.. _hide-empty-rows: - -A table may occasionally contain rows with conditionalized content that applies -only in one context, resulting in empty rows in the output from other contexts. - -You can suppress the output of empty rows by adding ``|hide-empty-rows|`` to -the files in which you want this behavior. All empty rows will be hidden in the -files where you make this addition. - -.. note:: - - If you are also using empty rows as separators between sections in longer - tables, then this behavior may not be what you want. - -.. end-hide-empty-rows - ----------------------- -Removing table columns ----------------------- - -.. begin-hide-table-columns - -A table may contain columns that you want to appear in one publishing context -but not another. - -You can supress the output of one or more columns from a publishing context by -adding metadata to the reStructuredText file containing the table. - -If the conditionalization is unidirectional (applies to only one build or is -the same everywhere used), you can add the metadata directly to the :file:`rst` -file. - -.. rubric:: |eg| - -.. code-block:: none - - .. meta:: - :remove-column-from-html-table: Memory Requirements,Node - :remove-column-emptied-row: 1 - :docs-build-context: starlingx - -where: - -``remove-column-from-html-table`` - is a manditory metadata field and must contain one or more column names - separated by commas. - - - Do not add spaces after commas. - - Column names are case and space sensitive. They must match the name - used in the table header row exactly. - -``remove-column-emptied-row`` - is an optional metadata field. If set, empty rows will also be removed - after column removal. This is usful to clean up rows that only contained - content in the removed column, and are thus left empty. - - Set the value to ``1`` to enable this option. Rows will not be removed if - you set any other value or if ``remove-column-emptied-row`` does not exist. - - .. note:: - - This feature is different from removing empty table rows using - ``|hide-empty-rows|`` as described in :ref:`Removing empty table rows - `. In that case the removal is global to a file. In this - case it is per modified table. - -``docs-build-context`` - specifies the documentation build(s) for which you want to remove columns - from a reStructuredText file. For example, to remove the columns ``Memory - Requirements`` and ``Node`` from a file in the StarlingX build, set the - value to ``starlingx``. Multiple contexts must be separated by commas, - without spaces. - - .. warning:: - - If you embed metadata directly into a reStructuredText file and do not - set ``docs-build-context``, then columns will be removed in all build - contexts. This is probably not what you want. - - .. include:: /_includes/build-contexts-c86d03c16918.rest - -You can also achieve bi or multidirectional conditionalization, such as -removing the column ``Memory Requirements`` from StarlingX builds, but removing -the column ``Node`` from the same table in some other build while leaving both -intact in a third. - -To do this, instead of embedding metadata directly in the file, use an -*include* file with different metadata in each build context. - -.. rubric:: |eg| - -#. In the context where you want to remove ``Memory Requirements``, create an - *include* file named :file:`remove-mem-requirements-and-node-cols.rest` with - the following content: - - .. code-block:: none - - .. meta:: - :remove-column-from-html-table: Memory Requirements - :remove-column-emptied-row: 1 - - .. note:: - - Do not use the ``docs-build-context`` option if using *include* files. - -#. In the context where ``Node`` be removed, create an *include* file named - :file:`remove-mem-requirements-and-node-cols.rest` with the following - content: - - .. code-block:: none - - .. meta:: - :remove-column-from-html-table: Node - :remove-column-emptied-row: 1 - -#. In the context where neither column will be removed, create an empty file - named :file:`remove-mem-requirements-and-node-cols.rest`. - -#. Include this file at the beginning of the reStructuredText containing the - table: - - .. code-block:: none - - .. include:: remove-mem-requirements-and-node-cols.rest - -The metadata will be added via the *include* file when processing the file in -each publishing context, resulting in the column ``Memory Requirements`` being -removed from one build and ``Node`` from the second. Neither column will be -removed from the third. - -**Limitations:** - -* This feature operates globally across all tables in input files where the - specified column names are found. Use caution to prevent a column you want to - remove from one table being removed from other tables in the file. - -* The ``remove-column-emptied-row`` option removes all empty rows from - processed tables. If you are using empty rows as separators between - sections in longer tables, then this behavior may not be what you want. - -* To use the ``docs-build-context``, an environment variable named - ``DOCS_BUILD_CONTEXT`` must be set and readable by the build toolchain. The - value of this variable must be passed to ``docs-build-context`` for a - reStructuredText file to be processed in the build. - -* This feature will not work with tables that do not have header rows. Columns - to be removed must be named. - -* This feature relies on the HTML ```` syntax. It will not work with - tables that are constructed using other elements such as ``
``. - reStructuredText tables are rendered using HTML ``
`` elements. - -.. end-hide-table-columns - -------------------- -RST quick reference -------------------- - -.. contents:: - :local: - :depth: 1 - -******** -Acronyms -******** - -Define acronym at first instance on page. After definition, use acronym only. - -**Input:** - -:: - - :abbr:`CPU (Central Processing Unit)` - -**Output:** - -:abbr:`CPU (Central Processing Unit)` - -************ -Code samples -************ - -Format code snippets as standalone literal blocks. - -**Input:** - -:: - - :: - - ping 8.8.8.8 - -**Output:** - -:: - - ping 8.8.8.8 - -******** -Commands -******** - -Format commands using the Sphinx ``command`` role. - -**Input:** - -:: - - :command:`system help` - -**Output:** - -Use the :command:`system help` command for the full list of options. - -**************** -Cross-references -**************** - -Cross-reference to arbitrary locations in a document using the ``ref`` role and -a named target. Named targets must precede a section heading. For more -information on references, see `Internal Hyperlink Targets -`_. - -When using external references, be sure to prefix the URL with either -``http://`` or ``https://``. For example: - -.. code-block:: - - `Internal Hyperlink Targets - `_. - -.. begin-xrefs-sample-note - -.. note:: - - When providing an example of a URL format, treat the example as code by - either placing it in a ``.. code-block::`` or in double backticks, for - example: - - .. code-block:: - - ``https:///`` - -.. end-xrefs-sample-note - -**Input:** - -:: - - .. _my_named_target: - - ********** - My section - ********** - - This is the section we want to reference. - - ... - - This is the reference to :ref:`my_named_target`. - -**Output:** - -.. _my_named_target: - -********** -My section -********** - -This is the section we want to reference. - -... - -This is the reference to :ref:`my_named_target`. - -****************** -Information blocks -****************** - -Emphasize information using notices (an *admonition* in Sphinx). Different types -of notices exist to emphasize degrees of information importance. - -**Input:** - -:: - - .. note:: - - Use a ``note`` for a generic message. - - .. seealso:: - - Use ``seealso`` for extra but helpful information. - - .. important:: - - Use ``important`` for details that can be easily missed, but should not be - ignored by a user and are valuable before proceeding. - - .. warning:: - - Use ``warning`` to call out information the user must understand - to avoid negative consequences. - -**Output:** - -.. note:: - - Use a ``note`` for a generic message. - -.. seealso:: - - Use ``seealso`` for extra but helpful information. - -.. important:: - - Use ``important`` for details that can be easily missed, but should not be - ignored by a user and are valuable before proceeding. - -.. warning:: - - Use ``warning`` to call out information the user must understand - to avoid negative consequences. - - -*************** -Inline elements -*************** - -Format most inline elements such as filenames and paths, code fragments, -parameters, or options with double back ticks. - -**Input:** -:: - - ``/path/to/file.name`` - ``--option`` - -**Output:** - -Open the ``/path/to/file.name`` file. - -Optionally pass the ``--option`` with the command. - -Refer to the `OpenStack Inline elements guide -`_ -for markup for other inline elements. - -***** -Lists -***** - -Use a bulleted list for a sequence of items whose order does not matter, such as -a list of features. - -**Input:** - -:: - - * Banana - * Apple - * Orange - -**Output:** - -* Banana -* Apple -* Orange - -Use an enumerated list for a sequence of items whose order matters, such as in -an ordered sequence of installation steps. - -**Input:** - -:: - - #. Wash apple. - #. Peel apple. - #. Eat apple. - -**Output:** - -#. Wash apple. -#. Peel apple. -#. Eat apple. - -Use a definition list for an unordered list where each item has a short -definition, such as term/definition pairs. - -**Input:** - -:: - - Command A - Description of command A. - - Command B - Description of command B. - -**Output:** - -Command A - Description of command A. - -Command B - Description of command B. - -**************** -Section headings -**************** - -Use up to three levels of headings in one file using the following characters: - -* Heading 1 (Page Title in Title Case) - underline and overline with equal signs; - - * Heading 2 (Major page sections in Sentence case) - underline and overline with dashes; - - * Heading 3 (subsections in Sentence case) - underline and overline with asterisks. - -Example RST: - -.. code-block:: rest - - ============== - Document Title - ============== - - Introduce the topic using 1-2 concise sentences. It should tell the user what - info can be found on this page. - - .. contents:: // Use a local TOC to aid user navigation in the page - :local: - :depth: 1 - - --------------- - Section heading - --------------- - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. - - ****************** - Subsection heading - ****************** - - Integer sed tortor nisi. Vivamus feugiat, urna in posuere gravida, ligula - nunc hendrerit magna, nec tristique ex tortor non lorem. - ------------------- -Release activities ------------------- - -Several activities must be completed in preparation for each release. - -********************* -Release notes updates -********************* - -Various sections in the |prod| release notes must be updated on the ``master`` -branch before the release branch for the upcoming release (for example -``r/stx.9.0``) is created. - -The Release notes can be found in the directory -:file:`doc/source/releasenotes`. - -********************** -Version number updates -********************** - -Product and related software version numbers must be updated throughout the -source :file:`rst` files. - -* Some of these changes must me made manually by searching for and replacing - the appropriate values. - -* More common version values are implemented as Sphinx substitutions: simple, - reusable placeholders. - - * For the current version of |prod|, edit the value of ``this-ver`` in the - file :file:`doc/source/_this.txt`. - - .. code-block:: - - .. |this-ver| replace:: r9.0 - - * For other values, consult the file - :file:`doc/source/_vendor/vendor_strings.txt`. - -******************** -Version menu updates -******************** - -A menu is available on each page of |prod| documentation to allow easy -switching between documentation versions. This menu must be updated on -``master`` and each release branch. - -To do so: - -#. On a working branch, open the file :file:`doc/source/conf.py`. - -#. Locate the configuration assignment ``starlingxdocs_plus_other_versions``. - - This assignment takes a *key,value* pair for each branch other than the - branch you are configuring. - - * Each key is the name of the branch that will appear in the menu. - * Each value is the name of the branch. - - For example, if you are editing :file:`conf.py` on the branch ``r/stx.7.0``, - then this assignment would container a key pair for each of - - ``r/stx.6.0``, ``r/stx.8.0``, ```` ..., and ``master``. - - These pairs are separated by commas and must be listed from oldest to most - recent, always ending with the ``master`` branch. The *key* for the - ``master`` branch is ``Latest``. - - For example, for release 9.0, the ``r/stx.9.0`` version of this file would - have this assignment: - - .. code-block:: - - starlingxdocs_plus_other_versions = [("Version 6.0","r/stx.6.0"),("Version 7.0","r/stx.7.0"),("Version 8.0","r/stx.8.0"),("Version 9.0","r/stx.9.0")] - - .. note:: - - During a documentation build, Sphinx prepends a forward slash to each - *value* in ``starlingxdocs_plus_other_versions`` to construct the correct - URLs, such as ``https://docs.starlingx.io/r/stx.8.0/``. Since the - ``master`` documentation is at the base URL ``docs.startlingx.io``, this - means that the value must be an empty string, as show above. - -********************** -Adding the promote job -********************** - -A ``promote`` job must be created for merged reviews on a new release branch to -be published to docs.starlingx.io. - -.. rubric:: |prereq| - -You must have the OpenStack ``project-config`` repo available. - -.. rubric:: |proc| - -#. In the ``project-config`` repo, open the file - :file:`zuul.d/starlingx-jobs.yaml`. - -#. Locate the ``promote-stx-tox-docs-site`` job. - -#. Add the new branch to the list of branches that will be published. - - For example: - - .. code-block:: yaml - :emphasize-lines: 21 - - - job: - name: promote-stx-tox-docs-site - parent: opendev-promote-docs-base - description: | - Promote content from openstack-tox-docs job for - starlingx/doc repository only. - - Publish the results of a sphinx build to - /afs/.openstack.org/project/starlingx.io/www - - final: true - vars: - download_artifact_job: openstack-tox-docs - # add older release branches as desired - branches: - - master - - r/stx.5.0 - - r/stx.6.0 - - r/stx.7.0 - - r/stx.8.0 - - r/stx.9.0 - -#. Save the file and commit a gerrit review. - -See https://review.opendev.org/c/openstack/project-config/+/873266 for a +.. include:: /_vendor/rl-strings.txt + +.. _doc_contribute_guide: + +=============================== +Documentation Contributor Guide +=============================== + +This section describes the guidelines for contributing to the StarlingX +documentation. + +.. contents:: + :local: + :depth: 1 + +---------- +Quickstart +---------- + +The StarlingX documentation uses reStructuredText (RST) markup syntax with +Sphinx extensions. It uses the same contribution setup and workflow as the +OpenStack documentation. + +* `OpenStack Documentation Contributor Guide `_. + +.. note:: + + The supported version of tox is currently pinned at 2.9.1. If possible, + using this version is recommended for local builds. + +********************** +Setup for contribution +********************** + +Follow the OpenStack instructions for `setting up for contribution +`_. + +************* +Make a change +************* + +#. Make changes following the OpenStack instructions for: + + #. `Starting a change `_ + #. `Committing a change `_. + + .. note:: + + StarlingX requires the use of a **Signed-off-by** header. Use the + :command:`-s` option with :command:`git commit`. + + +#. When writing documentation, follow `Writing style`_ and `RST conventions`_. + +#. Build the documentation locally to verify your changes before committing. + Follow the OpenStack instructions for + `Building documentation `_. + +#. If needed, follow up with edits to your patch following the OpenStack + instructions for `Responding to requests `_. + +.. build-singledoc-begin + +It can sometimes be useful to search the output globally for a string that may +not be reliably returned by the built-in search functionality. For example, you +may need to find and update all instances of a version number or container name. + +You can generate HTML output to a single page and use your browser's search +functionality to search globally. + +To build all documentation as a single page, run the following command from +your local clone of the documentation repository: + +.. code-block:: bash + + $ tox -e singledoc + +The output will be available in **/``doc/build/singlepage`` + +.. note:: + + The quality checks done at the end of the build scan the most recent output + from running :command:`tox -e docs` and do not reflect any errors or + corrections in ``singledoc`` output. + +.. build-singledoc-end + +-------------------------- +Find tasks and help needed +-------------------------- + +If you are looking for work to complete: + +* Refer to the `StarlingX documentation StoryBoard + `_ for topics that + need content. Many topics have stub pages in the documentation with a link to + the associated story. + +* Find open `documentation bugs on Launchpad + `_. + + +If you make a contribution that has an the associated story, task, or bug in the +comment, link to the related story or bug as described in the +:ref:`Code Submission Guidelines `. + +----------------- +Docs organization +----------------- + +Documentation for StarlingX is organized into the following sections: + +:ref:`Introduction ` + Overview of the StarlingX project. + +:ref:`Deployment Configurations ` + Supported deployment configuration options. + +:ref:`Planning ` + Requirements planning guidance. + +:ref:`Installation ` + Release-specific installation and deployment guides. + +:ref:`Security ` + Detailed discussion of security configuration. + +:ref:`System Configuration ` + Detailed discussion of various post-installation configuration changes. + +:ref:`Data Networks ` + Discussion of |prod| data network configuration and management. + +:ref:`Node Management ` + Discussion of |prod| node configuration and management. + +:ref:`Backup and Restore ` + Discussion of |prod| backup and restore procedures. + +:ref:`Updates and Upgrades ` + Discussion of |prod| update and upgrade procedures. + +:ref:`KubeVirt ` + Overview of |VM| support using KubeVirt. + +:ref:`Admin Tasks ` + Overview of common administrator tasks. + +:ref:`User Tasks ` + Overview of common user tasks. + +:ref:`Guest Integration ` + Overview of various guest integrations. + +:ref:`Distributed Cloud ` + Discussion of |prod| |prod-dc| for edge computing. + +:ref:`Sample Application Deployment ` + +:doc:`/archive/configuration/index` + Configuration references for post-installation StarlingX system configuration. + +:doc:`/operations/index` + System administration and maintenance guides. + +:doc:`/api-ref/index` + REST API references for the StarlingX project. For additional information + about where REST API documentation is located, see `API documentation`_. + +:doc:`/cli_ref/index` + Reference for the StarlingX project command line interface (CLI). + +:doc:`/developer_resources/index` + Resources for developers using or building StarlingX. + +:doc:`/releasenotes/index` + Release notes for all StarlingX releases. + +:doc:`/contributor/index` + Overview and guidelines for contributing to StarlingX documentation. + +***************** +API documentation +***************** + +The structure and location of the REST API documentation deserves extra +explanation. + +Most REST API content is generated from the StarlingX project associated with +the API. For example, the documentation for the StarlingX metal REST API is +generated from the `metal repository `_. + +API references for StarlingX extensions are part of the docs repository, located +in the ``api-ref`` project: + +* StarlingX extensions to the OpenStack Block Storage API +* StarlingX extensions to the OpenStack Compute API +* StarlingX extensions to the OpenStack Image API +* StarlingX extensions to the OpenStack Networking API + +The ``api-ref`` project also contains index pages used by Sphinx to +generate the final content tree. Note that the REST API landing page used to +render content in the generated website is found in the ``doc`` project. + +For additional information on the API documentation, refer to +:doc:`api_contribute_guide`. + +****************** +Spec documentation +****************** + +Spec documentation is found in the +`Starlingx specs project `_. + +The ``specs/2019.03`` directory contains the documentation files for approved +and implemented specs. + +------------------ +Document structure +------------------ + +.. begin-document-structure + +.. _index-rules: + +*********** +Index rules +*********** + +Each document consists of one main Sphinx index file, with two optional ones +for each of Kubernetes and OpenStack content, if applicable. + +The index file contains one or more *toctrees*, which define the manifest and +structure of topics to be included in the document. The index file must be at +the root of the document's folder structure. If your document contains a mix of +Kubernetes and OpenStack topics, create a subdirectory for each with an index +file for those topics and link it to the top-level index. + +For example: + +.. code-block:: bash + + $ mkdir -p doc/source/newbook + $ cd doc/source/newbook + $ mkdir kubernetes + $ mkdir opemstack + $ tox -e newfile # follow instructions for creating a new index stub + $ cd kubernetes + $ tox -e newfile # create an index stub for kubernetes content + $ cd ../openstack + $ tox -e newfile # create an index stub for OpenStack content + +See :ref:`create-rst-files` for details on using :command:`tox -e newfile` + +In the book's main index under :file:`doc/source/newbook`, create entries to +the two subindexes: + +.. code-block:: none + + ========== + Kubernetes + ========== + + .. toctree:: + + kubernetes/index-768a6e9aaeff + + ========= + OpenStack + ========= + + .. toctree:: + + openstack/index-1b466179efc3 + +Add your Kubernetes and OpenStack content to the +:file:`kubernetes/index-768a6e9aaeff.rst` and +:file:`openstack/index-1b466179efc3.rst` files respectively. (Note that the +random strings ``768a6e9aaeff`` and ``1b466179efc3`` were added by +:command:`tox -e newfile` and will differ in your usage.) + +.. important:: + + Additional indexes, either at the root of the document or in subfolders, are + not allowed. + + The following images provide examples of correct and incorrect layouts. + + .. figure:: figures/index-structure-ok-2.png + + **Correct Kubernetes/OpenStack layout** + + + .. figure:: figures/index-structure-wrong.png + + **Incorrect Kubernetes/OpenStack layout** + + + Use section headings in the index file to define document structure. For + example: + + .. code-block:: + + .. _contribute: + + ================== + Contributor Guides + ================== + + Welcome to the StarlingX community! We are glad you are here. + + If you are new to the project, take a moment to review the + `StarlingX wiki `_. + + --------------------------- + Contribute to documentation + --------------------------- + + .. toctree:: + :maxdepth: 1 + + doc_contribute_guide + api_contribute_guide + release_note_contribute_guide + blog_contribute_guide + website_contribute_guide + + + + ------------------ + Contribute to code + ------------------ + + StarlingX follows the `OpenStack developer contribution guidelines + `_. Additional + StarlingX-specific resources are listed below. + + .. toctree:: + :maxdepth: 1 + + development_process + /developer_resources/code-submission-guide + /developer_resources/debug_issues + + -------------------- + Additional resources + -------------------- + + * `StarlingX wiki `_ + * :doc:`/developer_resources/index` + +.. end-document-structure + +**************** +Folder structure +**************** + +For any new document, create a new directory under :file:`source`. Create a +subdirectory called :file:`figures` to hold images. + +* for short, simple documents, you can place index and topic files directly in + this new document directory. + +* for more complex documents with multiple chapters, create one subdirectory + for each chapter, for example, :file:`source//developer_resources`. + +* for documents that distinguish between Kubernetes and OpenStack, create one + subdirectory for each. Any chapter directory should be created under these. + For example: :file:`source//kubernetes/developer_resources`. + + See the section on :ref:`index-rules` for more information. + + +------------- +Writing style +------------- + +.. begin-writing-style + +StarlingX documentation follows many (but not all!) of the writing style +guidelines described in the `OpenStack documentation writing style guide +`_. +Differences between the StarlingX and OpenStack practices are highlighted +below. + +* Use Title Case for page titles. For example: + + :: + + =============================== + Documentation Contributor Guide + =============================== + +* Start section titles with an action verb. Do not use a gerund (word that ends + with -ing). For example: + + :: + + ------------------ + Configure endpoint + ------------------ + +.. end-writing-style + +.. _create-rst-files: + +---------------- +Create rST Files +---------------- + +.. begin-create-rst-files + +Use the :command:`tox -e newfile` command to create new |RST| files. + +.. rubric:: |context| + +All |RST| files created in StarlingX documentation repositories must have the +following characteristics: + +* They must have unique file names. +* They must have |RST| labels at the beginning of the files that match the file + names. + +.. important:: + These rules apply to *index* files as well as those containing user + documentation. + +A utility is available for use from within each documentation repository you +have installed to generate uniquely named files for you. + +.. rubric:: |prereq| + +You must have :program:`uuidgen` installed on your system. This program is +included by default on most modern Linux distributions. If it is not installed, +consult your distribution's documentation for instructions. + +.. rubric:: |proc| + +#. Change to the directory where you wish to create a new topic. + + Typically, this will be below the :file:`doc/source` directory of the + repository. + +#. Run the following :command:`tox` command. + + .. code-block:: bash + + tox -e newfile + +#. When prompted, enter a title for the new topic. + + .. code-block:: none + :emphasize-lines: 3 + + You are about to create a new reStructuredText file in + + /home/jdoe/starlingx/docs/doc/source/intro + + or a content fragment file in doc/source/_includes + + If this is not what you want, press CTL-C to quit and change to the directory + you want to create the file in. + + Enter a title for the new topic. The file name and topic label used for + linking will be based on this value. + + + Topic title: + + #. Review the directory (an example is highlighted above) that the utility + will create the new file in. + + .. note:: + This does not apply if you choose to create a content fragment using + the :kbd:`f` option when prompted. In that case, the file will be + saved to :file:`doc/source/_includes` regardless of your current + working directory. + + #. If this is not correct, press :kbd:`CTL-C` to quit, change to the correct + directory, and run the command again; otherwise, type the topic title and + press :kbd:`ENTER`. + +#. When prompted, select the type of |RST| stub file you want to create. + + .. code-block:: none + + Thanks. Now choose a topic type. Enter one of the following characters: + + t) A task topic. Will contain the outline of a procedure. + i) An index. + r) A reference topic. Will contain a minimal list-table definition. + g) A minimal generic topic. + f) A content fragment included in an rST file. Will be saved to doc/source/_includes. + Topic type: + + Each option creates a stub file with different templated content useful for + getting started. Press the corresponding key. + +.. rubric:: |result| + +The new |RST| file is created. + + +The title used in the new |RST| file matches what you typed exactly. However, +some changes have been made to the file name and topic label. + +For example, if you entered ``Architectural Considerations!`` as a title, +listing the directory will show a file similar to the following: + +.. code-block:: bash + + $ ls + +.. code-block:: none + + architectural-considerations--d9dd4c105700.rst + +The following changes were made. + +* All alphabetical characters were converted to lower case. +* *Not shown* The characters ``+``, ``-``, ``@``, and ``&`` are replaced with + ``plus``, ``minus``, ``at``, and ``and`` respectively. +* All spaces and other special characters, such as the ``!`` were replaced by + dashes. +* A final dash and 12 digit random string were appended to the file name. +* The extension :file:`.rst` was added for all options except :kbd:`f`, in + which case the extension :file:`.rest` was added. +* If you chose to create an ``index`` file by selecting :kbd:`i` when prompted, + :file:`index-` was prepended to the file name. + +Examining the file reveals that the label matches the file name, while the +title is preserved as typed. No label was added if you selected :kbd:`f`. + +.. code-block:: bash + + cat architectural-considerations--d9dd4c105700.rst + +.. code-block:: none + :emphasize-lines: 1,4 + + .. _architectural-considerations--d9dd4c105700: + + ============================= + Architectural Considerations! + ============================= + + .. content here + +When you reference this file in ``toctree`` and ``ref`` directives, use +the file name/label string like this: ``architectural-considerations--d9dd4c105700`` + +.. end-create-rst-files + +-------------------- +Using tabbed content +-------------------- + +Content on the master branch can take advantage of the ``sphinx-tabs`` +extension to organize content into tabs. + + +.. begin-using-tabbed-content + + +Tabs are useful for presenting alternate sets of content in a way that does not +require that the reader interact with sets that are not of interest. This is +particularly useful in procedures where some steps vary across two or more +variable factors. Rather than maintain two or more separate procedures, tabs +can be used to show one of the alternate sets of content. For example, the +|prod| installation procedures make heavy use of tabs to allow the reader to +switch between virtual and bare-metal versions of the procedures. + +.. only:: starlingx + + See :ref:`aio_simplex_install_kubernetes_r7` for an example. + +**Basic tabs** + +Basic tabs are stand-alone. They have no relationship to other tabbed content +on a page. + +.. code-block:: rst + + .. tabs:: + + .. tab:: Apples + + Apples are green, or sometimes red. + + .. tab:: Pears + + Pears are green. + + .. tab:: Oranges + + Oranges are orange. + +.. tabs:: + + .. tab:: Apples + + Apples are green, or sometimes red. + + .. tab:: Pears + + Pears are green. + + .. tab:: Oranges + + Oranges are orange. + +**Nested tabs** + +Tab sets can be defined within other tab sets. While this can be useful for +organizing logical hierarchies of information, care should be taken not to make +readers 'dig' for relevant content, making it unnecessarily difficult to find. + +.. tip:: + + Remember that the organizational goal of tabs is hide irrelevant information + while *making all relevant information visible*. + +.. code-block:: rst + + .. tabs:: + + .. tab:: Stars + + .. tabs:: + + .. tab:: The Sun + + The closest star to us. + + .. tab:: Proxima Centauri + + The second closest star to us. + + .. tab:: Polaris + + The North Star. + + .. tab:: Moons + + .. tabs:: + + .. tab:: The Moon + + Orbits the Earth + + .. tab:: Titan + + Orbits Jupiter + +.. tabs:: + + .. tab:: Stars + + .. tabs:: + + .. tab:: The Sun + + The closest star to us. + + .. tab:: Proxima Centauri + + The second closest star to us. + + .. tab:: Polaris + + The North Star. + + .. tab:: Moons + + .. tabs:: + + .. tab:: The Moon + + Orbits the Earth + + .. tab:: Titan + + Orbits Jupiter + +**Group tabs** + +Tab sets can be grouped so that switching to a tab with a certain name in one +set causes all other tab sets on the page to switch to the same tab. This can +be very useful when the same alternatives recur many times on the same page. +The reader only needs to select the tab that is relevant to them once to have +the entire page switch to the appropriate content. + +Do this by using the ``.. group-tab::`` directive in place of the ``.. tab::`` +directive and by being sure to label all tabs consistently across tab sets. + +In the example below, a reader can switch all tab sets to :guilabel:`Linux`, +:guilabel:`Mac OSX`, or :guilabel:`Windows` by making the selection once, in +any of the tab sets. + +.. code-block:: rst + + .. tabs:: + + .. group-tab:: Linux + + Linux tab content - tab set 1 + + .. group-tab:: Mac OSX + + Mac OSX tab content - tab set 1 + + .. group-tab:: Windows + + Windows tab content - tab set 1 + + .. tabs:: + + .. group-tab:: Linux + + Linux tab content - tab set 2 + + .. group-tab:: Mac OSX + + Mac OSX tab content - tab set 2 + + .. group-tab:: Windows + + Windows tab content - tab set 2 + + .. tabs:: + + .. group-tab:: Linux + + Linux tab content - tab set 3 + + .. group-tab:: Mac OSX + + Mac OSX tab content - tab set 3 + + .. group-tab:: Windows + + Windows tab content - tab set 3 + +Try it out for yourself here: + +.. tabs:: + + .. group-tab:: Linux + + Linux tab content - tab set 1 + + .. group-tab:: Mac OSX + + Mac OSX tab content - tab set 1 + + .. group-tab:: Windows + + Windows tab content - tab set 1 + +.. tabs:: + + .. group-tab:: Linux + + Linux tab content - tab set 2 + + .. group-tab:: Mac OSX + + Mac OSX tab content - tab set 2 + + .. group-tab:: Windows + + Windows tab content - tab set 2 + +.. tabs:: + + .. group-tab:: Linux + + Linux tab content - tab set 3 + + .. group-tab:: Mac OSX + + Mac OSX tab content - tab set 3 + + .. group-tab:: Windows + + Windows tab content - tab set 3 + +*********************************** +Considerations for alternate builds +*********************************** + +It is important to make allowances for builds of StarlingX documentation in +contexts that may not support tabs, such as by other parties or for print +output. To support such environments, the use of tabs must be conditionalized +and the related content repeated for non tab scenarios. The following sample +illustrates the standard way to achieve this: + +.. code-block:: + + .. only:: starlingx and html + + .. tabs:: + + .. group-tab:: Bare Metal + + .. begin-install-prereqs-bm + + .. include:: /shared/_includes/installation-prereqs.rest + :start-after: begin-install-prereqs + :end-before: end-install-prereqs + + .. end-install-prereqs-bm + + .. group-tab:: Virtual + + .. begin-install-prereqs-virt + + Several pre-requisites must be completed prior to starting the |prod| + installation. + + Before attempting to install |prod|, ensure that you have the the + |prod| host installer ISO image file. + + Get the latest |prod| ISO from the `StarlingX mirror + `__. + Alternately, you can get an older release ISO from `here `__. + + .. end-install-prereqs-virt + + + .. only:: partner and (html or latex) + + ********** + Bare Metal + ********** + + .. include:: /deploy_install_guides/release/bare_metal/aio_duplex_install_kubernetes.rst + :start-after: begin-install-prereqs-bm + :end-before: end-install-prereqs-bm + + ******* + Virtual + ******* + + .. include:: /deploy_install_guides/release/bare_metal/aio_duplex_install_kubernetes.rst + :start-after: begin-install-prereqs-virt + :end-before: end-install-prereqs-virt + +In this example, the tabbed content is conditionalized to only appear in +StarlingX HTML output (``.. only:: starlingx and html``). + +The ``.. begin-install-prereqs-bm``, ``.. end-install-prereqs-bm``, ``.. +begin-install-prereqs-virt`` and ``.. end-install-prereqs-virt`` comments allow +the contents of the ``Bare Netal`` and ``Virtual`` tabs to be included +conditionally in other builds that do not support tabs. In this example the +content is conditionalized in the ``.. only:: partner and (html or latex)`` +block. + +.. end-using-tabbed-content + +------------------------ +Automated quality checks +------------------------ + +.. begin-automated-quality-checks + +Several automated checks are available to help improve and maintain the quality +of your documentation. + +Some of these checks are run every time you perform a build and are intended to +catch errors before they are submitted for review. Others are invoked +independently of regular builds and are intended to identify problems prior to +a release. + +***************** +Formatting checks +***************** + +.. begin-post-build-checks + +You can build the HTML documentation locally using the ``tox -e docs`` command. +After every successful build, several quality checks are performed against the +build HTML output. + +.. parsed-literal:: + + Checking for "grey bar" formatting errors in output ... + Found 2 HTML file(s) with greybar formatting issues: + ./dist_cloud/kubernetes/reinstalling-a-subcloud-with-redfish-platform-management-service.html + ./dist_cloud/kubernetes/installing-a-subcloud-without-redfish-platform-management-service.html + Using a browser, locate vertical grey bars in the left margin of the above file(s), then correct the issue(s) in the corresponding rST file(s). + Checking for ".. include::" errors in output ... + Checking for unexpanded substitution errors in output ... + Found 1 HTML file(s) that may have unexpanded substitution(s): + + ./node_management/kubernetes/hardware_acceleration_devices/enabling-mount-bryce-hw-accelerator-for-hosted-vram-containerized-workloads.html:| 1d02 | |html-pipe|\ SATA\ |html-pipe| controller | Intel Corporation | + + Correct the issue(s) in the corresponding rST file(s). + +This sample shows three problems. + +.. list-table:: Post-check issues and remedies + :header-rows: 1 + :stub-columns: 1 + :widths: auto + + * - Test + - Explanation + - Remedy + * - Grey bars + - Scans the output for evidence of |RST| vertical grey bars inserted into the + output next to formatting errors and reports which files they were found + in.​ + - #. Open the file :file:`doc/build/html/index.html` in a browser and + navigate to the page reported in the output. + + #. Locate the grey bars. + + .. tip:: + Grey bars can be hard to find in some locations, such as notes, + where they are obscured by a background fill. Look for other + evidence of a problem such as an oversized font, text that + appears to be randomly bolded, or senseless line breaks. + + #. Open the corresponding :file:`.rst` file and find the location + matching the grey bars in the output. + #. Correct the issue. + + .. hint:: + Grey bars are often caused by indentation errors. + * - Include errors + - Scans the output for malformed ``.. include::`` statements that result + in |RST| code and unintended content being exposed and reports which + files they were found in.​ + - As above, find the problem in the appropriate + :file:`.rst` file by examining the :file:`.html` file reported. Look for + code fragments associated with ``.. include::`` directives such as + :start\ |html-comment|-after: and :end\ |html-comment|-before: + that have been exposed in the final output. + + Correct the issues by making the code comply with the documentation at: + + https://docutils.sourceforge.io/docs/ref/rst/directives.html#include + * - Substitution errors + - Scans the output for potential unexpanded substitutions such as + |html-pipe|\ prod\ |html-pipe| and reports which files they were found in, along with the + offending lines of HTML. + + .. note:: + This check cannot distinguish between a substitution and an ascii + output table where cells are not properly padded. In either case, the + problem needs to be fixed. + + - As above, find the problem in the appropriate :file:`.rst` file by + examining the :file:`.html` file reported. Look for |html-pipe|\ \ |html-pipe| code + exposed in the output. In the corresponding :file:`.rst`, find and + correct the issue. + + .. hint:: + Substitutions are not allowed in code blocks, :ref:, :doc:, + or within |RST| markup such as ``**``, ``*```, `````, and so on. + + Substitutions cannot be used in ASCII "picture" style tables. If you + need a substitution in a table, use the ``.. list-table::`` format + instead. + +.. end-post-build-checks + +*********** +Link checks +*********** + +Link checks are not performed as part of regular documentation builds. They are +intended to be run periodically and prior to a release. + +You can invoke the Sphinx link checker with the following command: + +.. code-block:: bash + + $ tox -e linkcheck + +Sphinx will perform a temporary build and then attempt to follow all external +links from the output files. Results are reported on the console and +logged for future use. + +.. note:: + + You may need to disconnect any corporate firewall or VPN to allow the link + checker to reach external sites. + +**Console output** + +The following two lines illustrate output for a valid and a bad link on lines 1 +and 2 respectively. In each case the name of the file being checked, the line +number the link was found on, and the link itself are reported. In the case of +a broken link, the server error code is also shown, in this case a 404 *file +not found* error. This indicates that the page may have moved or been deleted. + +.. code-block:: none + :linenos: + + (developer_resources/build_docker_image: line 120) ok https://mirror.starlingx.windriver.com/mirror/starlingx/master/centos/latest_docker_image_build/outputs/wheels/stx-centos-stable-wheels.tar + (developer_resources/build_docker_image: line 122) broken https://mirror.starlingx.windriver.com/mirror/starlingx/master/centos/latest_docker_image_build/outputs/wheels/stx-centos-dev-wheels.tar - 404 Client Error: Not Found for url: https://mirror.starlingx.windriver.com/mirror/starlingx/master/centos/latest_docker_image_build/outputs/wheels/stx-centos-dev-wheels.tar + +**Logs** + +Non "OK" results such as *file not found* and *permanent redirect* are +logged under :file:`doc/build/linkcheck` in two files: + +* :file:`doc/build/linkcheck/output.txt` provides a results log in plain-text + format. + +* :file:`doc/build/linkcheck/output.json` provides the same information in + ``JSON`` format. + +Investigate all issues and update the links as needed. In the case of permanent +redirects, replace the existing URL with that of the redirect target. + +************ +Spell checks +************ + +Spell checks are not performed as part of regular documentation builds. They +are intended to be run periodically and prior to a release. + +You can invoke the Sphinx link checker with the following command: + +.. code-block:: bash + + $ tox -e spellcheck + +Sphinx will perform a temporary build and then check the output against a US +English dictionary. Results are reported on the console and logged for future +use. + +**Console output** + +Console output shows the path and name of the file an error was found in, the +line number, the misspelled term and the full line to provide context. + +.. code-block:: none + + doc/source/storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:41: Spell check: aditional: used as aditional disk volumes for VMs booted from images. + + +**Logs** + +Spell check logs are stored under :file:`doc/build/spelling` in +:file:`*.spelling` files located and named for their :file:`rst` counterparts. + +For example, errors found in the file: + +:file:`doc/source/storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst` + +are logged in the file: + +:file:`doc/build/spelling/storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.spelling` + +Log files itemize one issue per line. For example: + +.. code-block:: none + + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:41: (aditional) used as aditional disk volumes for VMs booted from images + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:68: (num) For more information on how placement group numbers, (pg_num) can be set + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:72: (num) group numbers (pg_num) required based on pg_calc algorithm, estimates on + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:116: (num) To list all the pools with their pg_num values, use the following command, + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:119: (num) To get only the pg_num / pgp_num value, use the following command, + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:119: (num) To get only the pg_num / pgp_num value, use the following command, + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:142: (num) Increasing pg_num of a pool has to be done in increments of 64/ + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:142: (num) pg_num number, retry and wait for the cluster to be + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:149: (num) pg_num of that pool, using the following commands: + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:162: (num) pgp_num should be equal to pg_num. + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:162: (num) pgp_num should be equal to pg_num. + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:203: (num) pg_num, pgp_num, crush_rule. + storage/openstack/config-and-management-ceph-placement-group-number-dimensioning-for-storage-cluster.rst:203: (num) pg_num, pgp_num, crush_rule + +Note that the spell check in this example matched on the substring ``num`` +several times in contexts such as ``pgp_num``. Cases such as this may call for +additional spell check customization. + +Adding words +************ + +|org| documentation makes use of many technical terms that are not known to the +default dictionary. + +You can add these to the file +:file:`doc/source/spelling_wordlist.txt`. + +This file contains one term per line. + +.. note:: + + * Care should be taken when adding terms to a custom dictionary to avoid + errors not being reported. For example, "fs" may be correct in a code + block but a typo in some other context. As a general rule, it is better + to have the spell checker over-report than under-report. + + * It is important that :file:`spelling_wordlist.txt` be kept in + alphabetical order. + + * :file:`spelling_wordlist.txt` is under :program:`git` management and + changes must be submitted for review and merge via a :program:`gerrit` + review. + +.. end-automated-quality-checks + +--------------- +RST conventions +--------------- + +StarlingX documentation follows many (but not all!) of the RST conventions +described in the `OpenStack documentation RST conventions guide +`_. If RST markup +is not listed in this section's quick reference, refer to the OpenStack guide. + +For detailed information about RST and Sphinx extensions, refer to the following +documents: + +* `Sphinx documentation `_ +* `reStructuredText primer `_ + +-------------------------- +Command prompt conventions +-------------------------- + +Command examples in |prod| are preceded by a shell prompt. These prompts +provide readers with important hints about the context in which the command is +to be used. It is important that the following prompts be used consistently +throughout the |prod| documentation. + +``$`` (dollar sign) + Used to indicate that a command should be run in a Linux terminal as a + regular user. + +``#`` (pound or hash sign) + Used to indicate that a command should be run in a Linux terminal as a + root user. + +``~(keystone_admin)]$`` + Used to indicate that the command must be run within the sourced environment + of a system controller, i.e. after running + + ``$ source /etc/platform/openrc`` + +------------- +Content reuse +------------- + +.. _using-includes: + +Content can be reused in multiple places using the Sphinx ``.. include::`` +directive. + +For example: + +.. code-block:: + + .. include:: /_includes/my_reusable_content.rest + +"Include" files must not end in ``.rst``. The StarlingX convention is to use +``.rest``. + +You can store multiple fragments of content in a single include file and use +them in various places. To do this, use ``rst`` comments to delineate where +each begins and ends: + +.. code-block:: + + .. begin-fragement-1 + + This content will be inserted using ``.. include::`` example 1, below. + + .. end-fragment-1 + + .. begin-fragement-2 + + This content will be inserted using ``.. include::`` example 2, below. + + .. end-fragment-2 + +To use one or the other in an ``rst`` topic, use the *start after* +and *end before* parameters as shown below: + +.. rubric:: **Example 1** + +.. parsed-literal:: + + ======== + My Topic + ======== + + Integer sed tortor nisi. Vivamus feugiat, urna in posuere gravida, ligula + nunc hendrerit magna, nec tristique ex tortor non lorem. + + ... + + .. include:: /_includes/my_reusable_content.rest + :start\ |html-comment|-after: begin-fragement-1 + :end\ |html-comment|-before: end-fragement-1 + +.. rubric:: **Example 2** + +.. parsed-literal:: + + ============== + My Other Topic + ============== + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + + ... + + .. include:: /_includes/my_reusable_content.rest + :start\ |html-comment|-after: begin-fragement-2 + :end\ |html-comment|-before: end-fragement-2 + +********************** +Content reuse in steps +********************** + +.. begin-content--in-steps + +Inserting reusable or conditional steps in a numbered list context causes the +list to restart. For example: + +An include file, ``mysteps.rest``, containing: + +.. code-block:: rst + + .. begin-step + + #. Blue + + .. end-step + +used in an ``rst`` file as follows: + +.. parsed-literal:: + + #. Orange + + #. Red + + .. include:: mysteps.rest + :start\ |html-comment|-after: begin-step + :end\ |html-comment|-before: end-step + + #. Green + +Results in: + +1. Orange + +2. Red + +3. Blue + +4. Green + +To avoid this, use substitute .. pre\ |html-comment|-include:: for ``.. include::`` + +.. parsed-literal:: + + #. Orange + + #. Red + + .. pre\ |html-comment|-include:: mysteps.rest + :start\ |html-comment|-after: begin-step + :end\ |html-comment|-before: end-step + + #. Green + +This will result in the expected numbering sequence: + +1. Orange + +2. Red + +3. Blue + +4. Green + +.. note:: + + * Only the start\ |html-comment|-after and end\ |html-comment|-before + parameters work with .. pre\ |html-comment|-include::. + + * Indentation within the ``rest`` file being referenced must match the + calling context. + + * If the list is not indented, the additional step(s) to be inserted should + not be indented. + + * If the list is indented (a sublist or in a nested block context), the + same indentation must be applied to the additional steps. + +.. end-content--in-steps + +-------------------------- +Content conditionalization +-------------------------- + +**************************** +Conditionalize across builds +**************************** + +.. begin-conditionalize-content-across-builds + +If you need to conditionalize some content to be used in a specific build +context, such as StarlingX or a 3rd party build that reuses StarlingX content, +you can use the ``.. only::`` directive. + +For example: + +.. code-block:: + + .. only:: starlingx + + Integer sed tortor nisi. Vivamus feugiat, urna in posuere gravida, ligula + nunc hendrerit magna, nec tristique ex tortor non lorem. + +Three build contexts are available: + +``starlingx`` + Content will be included in the standard StarlingX documentation build. + +``partner`` + Content will be excluded from the StarlingX documentation build. To reuse + this content in a 3rd party build, ensure that the ``partner`` tag is based + to the builder. + +``openstack`` + Content will be included in an OpenStack documentation context. This content + is included in the StarlingX documentation build. + +.. end-conditionalize-content-across-builds + +*************************** +Conditionalize across pages +*************************** + +.. begin-conditionalize-content-across-pages + +If you want to reuse a block of content in multiple ``rst`` files from the same +build using ``.. include::`` directives, but need to exclude specific strings +from one of those locations, you can use the ``hideable`` role and substitution. + +You can hide both strings and blocks (paragraphs etc.). + +Hiding strings +************** + +To hide a string, use the ``hideable`` role. For example: + +.. code-block:: + + .. start-prepare-servers-common + + Prior to starting the |prod| installation, ensure that the |bare-metal| + servers are in the following state: + + ... + + - BIOS configured with Intel Virtualization (VTD, VTX) + + - Disabled for controller-only servers and storage servers. + + - Enabled for :hideable:`controller+worker (All-in-one) servers and` worker servers. + + - The servers are powered off. + + .. end-prepare-servers-common + +In the ``rst`` file where you want to include the text marked up with the +``:hideable:`` role, simply insert the content using the :ref:`include +` directive: + +.. parsed-literal:: + + .. _aio_duplex_install_kubernetes_r7: + + ================================================ + Install Kubernetes Platform on All-in-one Duplex + ================================================ + + ... + + -------------------------------- + Prepare Servers for Installation + -------------------------------- + + .. include:: /shared/_includes/prepare-servers-for-installation-91baad307173.rest + :start\ |html-comment|-after: start-prepare-servers-common + :end\ |html-comment|-before: end-prepare-servers-common + + ... + +The bullet: + +``- Enabled for :hideable:`controller+worker (All-in-one) servers and` worker servers.`` + +will render as: + +- Enabled for controller+worker (All-in-one) servers and worker servers. + + +In the ``rst`` file where you want to suppress the text marked up with the +``:hideable:`` role, do the same, but add the ``|hideable|`` substitution at the +top of the file: + +.. parsed-literal:: + + \|hideable\| + + .. _aio_duplex_install_kubernetes_r7: + + ================================================ + Install Kubernetes Platform on All-in-one Duplex + ================================================ + + ... + + -------------------------------- + Prepare Servers for Installation + -------------------------------- + + .. include:: /shared/_includes/prepare-servers-for-installation-91baad307173.rest + :start\ |html-comment|-after: start-prepare-servers-common + :end\ |html-comment|-before: end-prepare-servers-common + + ... + +The bullet: + +``- Enabled for :hideable:`controller+worker (All-in-one) servers and` worker servers.`` + +will render as: + +- Enabled for worker servers. + +Hiding blocks +************* + +To hide a block, wrap it in a ``container`` directive with the argument +``hideable`` + +For example, create an include file ``install-status.rest`` with the +following contents: + +.. code-block:: + + The **deploy status** field has the following values: + + .. container:: hideable + + ``Pre-Install`` + This status indicates that the ISO for the subcloud is being updated by + the Central Cloud with the boot menu parameters, and kickstart + configuration as specified in the ``install-values.yaml`` file. + + ``Installing`` + This status indicates that the subcloud's ISO is being installed from + the Central Cloud to the subcloud using the Redfish Virtual Media + service on the subcloud's |BMC|. + + .. container:: + + ``Bootstrapping`` + This status indicates that the Ansible bootstrap of |prod-long| + software on the subcloud's controller-0 is in progress. + +and load it in two different contexts: + +.. code-block:: + :caption: a.rst + + .. include:: install-status.rest + +.. code-block:: + :caption: b.rst + + |hideable| + + .. include:: install-status.rest + +The output from ``a.rst`` will include all three definitions. The output from +``b.rst`` will include only the ``bootstrap`` definition. + +.. end-conditionalize-content-across-pages + +------------------------- +Removing empty table rows +------------------------- + +.. begin-hide-empty-rows + +.. _hide-empty-rows: + +A table may occasionally contain rows with conditionalized content that applies +only in one context, resulting in empty rows in the output from other contexts. + +You can suppress the output of empty rows by adding ``|hide-empty-rows|`` to +the files in which you want this behavior. All empty rows will be hidden in the +files where you make this addition. + +.. note:: + + If you are also using empty rows as separators between sections in longer + tables, then this behavior may not be what you want. + +.. end-hide-empty-rows + +---------------------- +Removing table columns +---------------------- + +.. begin-hide-table-columns + +A table may contain columns that you want to appear in one publishing context +but not another. + +You can supress the output of one or more columns from a publishing context by +adding metadata to the reStructuredText file containing the table. + +If the conditionalization is unidirectional (applies to only one build or is +the same everywhere used), you can add the metadata directly to the :file:`rst` +file. + +.. rubric:: |eg| + +.. code-block:: none + + .. meta:: + :remove-column-from-html-table: Memory Requirements,Node + :remove-column-emptied-row: 1 + :docs-build-context: starlingx + +where: + +``remove-column-from-html-table`` + is a manditory metadata field and must contain one or more column names + separated by commas. + + - Do not add spaces after commas. + - Column names are case and space sensitive. They must match the name + used in the table header row exactly. + +``remove-column-emptied-row`` + is an optional metadata field. If set, empty rows will also be removed + after column removal. This is usful to clean up rows that only contained + content in the removed column, and are thus left empty. + + Set the value to ``1`` to enable this option. Rows will not be removed if + you set any other value or if ``remove-column-emptied-row`` does not exist. + + .. note:: + + This feature is different from removing empty table rows using + ``|hide-empty-rows|`` as described in :ref:`Removing empty table rows + `. In that case the removal is global to a file. In this + case it is per modified table. + +``docs-build-context`` + specifies the documentation build(s) for which you want to remove columns + from a reStructuredText file. For example, to remove the columns ``Memory + Requirements`` and ``Node`` from a file in the StarlingX build, set the + value to ``starlingx``. Multiple contexts must be separated by commas, + without spaces. + + .. warning:: + + If you embed metadata directly into a reStructuredText file and do not + set ``docs-build-context``, then columns will be removed in all build + contexts. This is probably not what you want. + + .. include:: /_includes/build-contexts-c86d03c16918.rest + +You can also achieve bi or multidirectional conditionalization, such as +removing the column ``Memory Requirements`` from StarlingX builds, but removing +the column ``Node`` from the same table in some other build while leaving both +intact in a third. + +To do this, instead of embedding metadata directly in the file, use an +*include* file with different metadata in each build context. + +.. rubric:: |eg| + +#. In the context where you want to remove ``Memory Requirements``, create an + *include* file named :file:`remove-mem-requirements-and-node-cols.rest` with + the following content: + + .. code-block:: none + + .. meta:: + :remove-column-from-html-table: Memory Requirements + :remove-column-emptied-row: 1 + + .. note:: + + Do not use the ``docs-build-context`` option if using *include* files. + +#. In the context where ``Node`` be removed, create an *include* file named + :file:`remove-mem-requirements-and-node-cols.rest` with the following + content: + + .. code-block:: none + + .. meta:: + :remove-column-from-html-table: Node + :remove-column-emptied-row: 1 + +#. In the context where neither column will be removed, create an empty file + named :file:`remove-mem-requirements-and-node-cols.rest`. + +#. Include this file at the beginning of the reStructuredText containing the + table: + + .. code-block:: none + + .. include:: remove-mem-requirements-and-node-cols.rest + +The metadata will be added via the *include* file when processing the file in +each publishing context, resulting in the column ``Memory Requirements`` being +removed from one build and ``Node`` from the second. Neither column will be +removed from the third. + +**Limitations:** + +* This feature operates globally across all tables in input files where the + specified column names are found. Use caution to prevent a column you want to + remove from one table being removed from other tables in the file. + +* The ``remove-column-emptied-row`` option removes all empty rows from + processed tables. If you are using empty rows as separators between + sections in longer tables, then this behavior may not be what you want. + +* To use the ``docs-build-context``, an environment variable named + ``DOCS_BUILD_CONTEXT`` must be set and readable by the build toolchain. The + value of this variable must be passed to ``docs-build-context`` for a + reStructuredText file to be processed in the build. + +* This feature will not work with tables that do not have header rows. Columns + to be removed must be named. + +* This feature relies on the HTML ``
`` syntax. It will not work with + tables that are constructed using other elements such as ``
``. + reStructuredText tables are rendered using HTML ``
`` elements. + +.. end-hide-table-columns + +------------------- +RST quick reference +------------------- + +.. contents:: + :local: + :depth: 1 + +******** +Acronyms +******** + +Define acronym at first instance on page. After definition, use acronym only. + +**Input:** + +:: + + :abbr:`CPU (Central Processing Unit)` + +**Output:** + +:abbr:`CPU (Central Processing Unit)` + +************ +Code samples +************ + +Format code snippets as standalone literal blocks. + +**Input:** + +:: + + :: + + ping 8.8.8.8 + +**Output:** + +:: + + ping 8.8.8.8 + +******** +Commands +******** + +Format commands using the Sphinx ``command`` role. + +**Input:** + +:: + + :command:`system help` + +**Output:** + +Use the :command:`system help` command for the full list of options. + +**************** +Cross-references +**************** + +Cross-reference to arbitrary locations in a document using the ``ref`` role and +a named target. Named targets must precede a section heading. For more +information on references, see `Internal Hyperlink Targets +`_. + +When using external references, be sure to prefix the URL with either +``http://`` or ``https://``. For example: + +.. code-block:: + + `Internal Hyperlink Targets + `_. + +.. begin-xrefs-sample-note + +.. note:: + + When providing an example of a URL format, treat the example as code by + either placing it in a ``.. code-block::`` or in double backticks, for + example: + + .. code-block:: + + ``https:///`` + +.. end-xrefs-sample-note + +**Input:** + +:: + + .. _my_named_target: + + ********** + My section + ********** + + This is the section we want to reference. + + ... + + This is the reference to :ref:`my_named_target`. + +**Output:** + +.. _my_named_target: + +********** +My section +********** + +This is the section we want to reference. + +... + +This is the reference to :ref:`my_named_target`. + +****************** +Information blocks +****************** + +Emphasize information using notices (an *admonition* in Sphinx). Different types +of notices exist to emphasize degrees of information importance. + +**Input:** + +:: + + .. note:: + + Use a ``note`` for a generic message. + + .. seealso:: + + Use ``seealso`` for extra but helpful information. + + .. important:: + + Use ``important`` for details that can be easily missed, but should not be + ignored by a user and are valuable before proceeding. + + .. warning:: + + Use ``warning`` to call out information the user must understand + to avoid negative consequences. + +**Output:** + +.. note:: + + Use a ``note`` for a generic message. + +.. seealso:: + + Use ``seealso`` for extra but helpful information. + +.. important:: + + Use ``important`` for details that can be easily missed, but should not be + ignored by a user and are valuable before proceeding. + +.. warning:: + + Use ``warning`` to call out information the user must understand + to avoid negative consequences. + + +*************** +Inline elements +*************** + +Format most inline elements such as filenames and paths, code fragments, +parameters, or options with double back ticks. + +**Input:** +:: + + ``/path/to/file.name`` + ``--option`` + +**Output:** + +Open the ``/path/to/file.name`` file. + +Optionally pass the ``--option`` with the command. + +Refer to the `OpenStack Inline elements guide +`_ +for markup for other inline elements. + +***** +Lists +***** + +Use a bulleted list for a sequence of items whose order does not matter, such as +a list of features. + +**Input:** + +:: + + * Banana + * Apple + * Orange + +**Output:** + +* Banana +* Apple +* Orange + +Use an enumerated list for a sequence of items whose order matters, such as in +an ordered sequence of installation steps. + +**Input:** + +:: + + #. Wash apple. + #. Peel apple. + #. Eat apple. + +**Output:** + +#. Wash apple. +#. Peel apple. +#. Eat apple. + +Use a definition list for an unordered list where each item has a short +definition, such as term/definition pairs. + +**Input:** + +:: + + Command A + Description of command A. + + Command B + Description of command B. + +**Output:** + +Command A + Description of command A. + +Command B + Description of command B. + +**************** +Section headings +**************** + +Use up to three levels of headings in one file using the following characters: + +* Heading 1 (Page Title in Title Case) - underline and overline with equal signs; + + * Heading 2 (Major page sections in Sentence case) - underline and overline with dashes; + + * Heading 3 (subsections in Sentence case) - underline and overline with asterisks. + +Example RST: + +.. code-block:: rest + + ============== + Document Title + ============== + + Introduce the topic using 1-2 concise sentences. It should tell the user what + info can be found on this page. + + .. contents:: // Use a local TOC to aid user navigation in the page + :local: + :depth: 1 + + --------------- + Section heading + --------------- + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + + ****************** + Subsection heading + ****************** + + Integer sed tortor nisi. Vivamus feugiat, urna in posuere gravida, ligula + nunc hendrerit magna, nec tristique ex tortor non lorem. + +------------------ +Release activities +------------------ + +Several activities must be completed in preparation for each release. + +********************* +Release notes updates +********************* + +Various sections in the |prod| release notes must be updated on the ``master`` +branch before the release branch for the upcoming release (for example +``r/stx.9.0``) is created. + +The Release notes can be found in the directory +:file:`doc/source/releasenotes`. + +********************** +Version number updates +********************** + +Product and related software version numbers must be updated throughout the +source :file:`rst` files. + +* Some of these changes must me made manually by searching for and replacing + the appropriate values. + +* More common version values are implemented as Sphinx substitutions: simple, + reusable placeholders. + + * For the current version of |prod|, edit the value of ``this-ver`` in the + file :file:`doc/source/_this.txt`. + + .. code-block:: + + .. |this-ver| replace:: r9.0 + + * For other values, consult the file + :file:`doc/source/_vendor/vendor_strings.txt`. + +******************** +Version menu updates +******************** + +A menu is available on each page of |prod| documentation to allow easy +switching between documentation versions. This menu must be updated on +``master`` and each release branch. + +To do so: + +#. On a working branch, open the file :file:`doc/source/conf.py`. + +#. Locate the configuration assignment ``starlingxdocs_plus_other_versions``. + + This assignment takes a *key,value* pair for each branch other than the + branch you are configuring. + + * Each key is the name of the branch that will appear in the menu. + * Each value is the name of the branch. + + For example, if you are editing :file:`conf.py` on the branch ``r/stx.7.0``, + then this assignment would container a key pair for each of + + ``r/stx.6.0``, ``r/stx.8.0``, ```` ..., and ``master``. + + These pairs are separated by commas and must be listed from oldest to most + recent, always ending with the ``master`` branch. The *key* for the + ``master`` branch is ``Latest``. + + For example, for release 9.0, the ``r/stx.9.0`` version of this file would + have this assignment: + + .. code-block:: + + starlingxdocs_plus_other_versions = [("Version 6.0","r/stx.6.0"),("Version 7.0","r/stx.7.0"),("Version 8.0","r/stx.8.0"),("Version 9.0","r/stx.9.0")] + + .. note:: + + During a documentation build, Sphinx prepends a forward slash to each + *value* in ``starlingxdocs_plus_other_versions`` to construct the correct + URLs, such as ``https://docs.starlingx.io/r/stx.8.0/``. Since the + ``master`` documentation is at the base URL ``docs.startlingx.io``, this + means that the value must be an empty string, as show above. + +********************** +Adding the promote job +********************** + +A ``promote`` job must be created for merged reviews on a new release branch to +be published to docs.starlingx.io. + +.. rubric:: |prereq| + +You must have the OpenStack ``project-config`` repo available. + +.. rubric:: |proc| + +#. In the ``project-config`` repo, open the file + :file:`zuul.d/starlingx-jobs.yaml`. + +#. Locate the ``promote-stx-tox-docs-site`` job. + +#. Add the new branch to the list of branches that will be published. + + For example: + + .. code-block:: yaml + :emphasize-lines: 21 + + - job: + name: promote-stx-tox-docs-site + parent: opendev-promote-docs-base + description: | + Promote content from openstack-tox-docs job for + starlingx/doc repository only. + + Publish the results of a sphinx build to + /afs/.openstack.org/project/starlingx.io/www + + final: true + vars: + download_artifact_job: openstack-tox-docs + # add older release branches as desired + branches: + - master + - r/stx.5.0 + - r/stx.6.0 + - r/stx.7.0 + - r/stx.8.0 + - r/stx.9.0 + +#. Save the file and commit a gerrit review. + +See https://review.opendev.org/c/openstack/project-config/+/873266 for a sample promote job update with reviewers. \ No newline at end of file diff --git a/remove-grid-columns.py b/remove-grid-columns.py new file mode 100644 index 000000000..8ee0d4eca --- /dev/null +++ b/remove-grid-columns.py @@ -0,0 +1,476 @@ +#!/usr/bin/env python3 +""" +Script to remove columns from reStructuredText grid tables based on column names. +Only processes grid tables that are declared using the .. table:: directive. +Column names to remove are specified using field lists in the RST file itself. + +Usage: + python remove_rst_columns.py input.rst -o output.rst + python remove_rst_columns.py input.rst --output output.rst + +If no output file is specified, the result is printed to stdout. + +The RST file should contain field list entries specifying columns to remove: + :remove-column-from-html-table: Column1, Column2, Column3 + +Note: Only grid tables declared with the .. table:: directive will be modified. +Standalone grid tables without the directive will be left unchanged. +""" + +import argparse +import sys +import re +import os +from typing import List, Tuple, Optional + + +def parse_grid_table(lines: List[str], start_idx: int) -> Tuple[List[List[List[str]]], List[int], int]: + """ + Parse a reStructuredText grid table starting at the given line index. + + Returns: + - table_data: List of rows, where each row is a list of cells, + and each cell is a list of lines (to preserve multi-line content) + - col_widths: List of column widths + - end_idx: Index of the line after the table + """ + # Find the table boundaries + table_lines = [] + i = start_idx + + # Skip to first border line + while i < len(lines) and not lines[i].strip().startswith('+'): + i += 1 + + if i >= len(lines): + return [], [], start_idx + + # Collect all table lines + while i < len(lines) and (lines[i].strip().startswith('+') or lines[i].strip().startswith('|')): + table_lines.append(lines[i]) + i += 1 + + if not table_lines: + return [], [], start_idx + + # Parse column positions from the first border line + border_line = table_lines[0] + col_positions = [] + for match in re.finditer(r'\+', border_line): + col_positions.append(match.start()) + + if len(col_positions) < 2: + return [], [], i + + # Calculate column widths + col_widths = [] + for j in range(len(col_positions) - 1): + col_widths.append(col_positions[j + 1] - col_positions[j] - 1) + + # Parse table data + table_data = [] + current_row = None + + for line in table_lines: + if line.strip().startswith('+'): + # Border line - if we have a current row, add it to table_data + if current_row is not None: + table_data.append(current_row) + current_row = None + elif line.strip().startswith('|'): + # Data line + if current_row is None: + current_row = [[] for _ in range(len(col_positions) - 1)] + + # Extract cell contents + for j in range(len(col_positions) - 1): + start_pos = col_positions[j] + 1 + end_pos = col_positions[j + 1] + cell_content = line[start_pos:end_pos].rstrip() # Only strip right whitespace + + # Add this line to the cell (preserving empty lines and indentation) + current_row[j].append(cell_content) + + # Add the last row if it exists + if current_row is not None: + table_data.append(current_row) + + return table_data, col_widths, i + + +def find_column_removal_directives(lines: List[str]) -> List[str]: + """ + Find field list entries that specify columns to remove. + Looks for entries like: :remove-column-from-html-table: Column1, Column2 + + Returns a list of column names to remove. + """ + columns_to_remove = [] + + for line in lines: + stripped_line = line.strip() + + # Look for the field list entry + if stripped_line.startswith(':remove-column-from-html-table:'): + # Extract the column names after the colon + field_content = stripped_line[len(':remove-column-from-html-table:'):].strip() + + if field_content: + # Split by comma and clean up each column name + column_names = [name.strip() for name in field_content.split(',')] + columns_to_remove.extend([name for name in column_names if name]) + + return columns_to_remove + + +def check_docs_build_context(lines: List[str]) -> None: + """ + Check if the docs-build-context directive matches the DOCS_BUILD_CONTEXT environment variable. + Exit the script if they don't match. + """ + docs_context = None + + for line in lines: + stripped_line = line.strip() + if stripped_line.startswith(':docs-build-context:'): + field_content = stripped_line[len(':docs-build-context:'):].strip() + if field_content: + docs_context = field_content + break + + if docs_context is not None: + env_context = os.environ.get('DOCS_BUILD_CONTEXT') + if env_context != docs_context: + print(f"Docs-build-context '{docs_context}' does not match DOCS_BUILD_CONTEXT environment variable '{env_context}'. Skipping.", file=sys.stderr) + sys.exit(0) + print(f"docs-build-context '{docs_context}' matches environment variable", file=sys.stderr) + + +def should_remove_emptied_rows(lines: List[str]) -> bool: + """ + Check if the remove-column-emptied-row directive is set to 1. + """ + for line in lines: + stripped_line = line.strip() + if stripped_line.startswith(':remove-column-emptied-row:'): + field_content = stripped_line[len(':remove-column-emptied-row:'):].strip() + return field_content == '1' + return False + + +def find_first_table_position(lines: List[str]) -> int: + """ + Find the position of the first table in the document. + Returns the line number of the first table, or len(lines) if no table found. + """ + for i, line in enumerate(lines): + if line.strip().startswith('+') and '-' in line: + # Check if this is actually a table by looking for the directive + is_table, _, _, _ = find_table_directive(lines, i) + if is_table: + return i + return len(lines) + + +def find_column_indices(headers: List[List[str]], columns_to_remove: List[str]) -> List[int]: + """Find the indices of columns to remove based on header names.""" + indices = [] + + # Convert headers (which are lists of lines) to single strings for comparison + header_strings = [] + for header_cell in headers: + # Join all lines in the cell and strip whitespace + header_text = '\n'.join(header_cell).strip() + header_strings.append(header_text) + + for col_name in columns_to_remove: + # Try exact match first + if col_name in header_strings: + indices.append(header_strings.index(col_name)) + else: + # Try case-insensitive match + for i, header in enumerate(header_strings): + if header.lower() == col_name.lower(): + indices.append(i) + break + else: + print(f"Warning: Column '{col_name}' not found in table headers", file=sys.stderr) + + return sorted(set(indices), reverse=True) # Remove duplicates and sort in reverse order + + +def remove_columns_and_empty_rows(table_data: List[List[List[str]]], col_indices: List[int], remove_empty_rows: bool = False) -> List[List[List[str]]]: + """Remove specified columns from table data and optionally remove rows that become empty.""" + new_table = [] + for row in table_data: + new_row = row.copy() + for idx in col_indices: + if idx < len(new_row): + new_row.pop(idx) + + # If remove_empty_rows is True, check if the row is now empty (all cells are empty or whitespace) + if remove_empty_rows: + row_is_empty = True + for cell in new_row: + cell_content = '\n'.join(cell).strip() + if cell_content: + row_is_empty = False + break + if row_is_empty: + continue # Skip this row as it's now empty + + new_table.append(new_row) + return new_table + + +def calculate_column_widths(table_data: List[List[List[str]]]) -> List[int]: + """Calculate the minimum width needed for each column, considering multi-line content.""" + if not table_data: + return [] + + num_cols = len(table_data[0]) + col_widths = [0] * num_cols + + for row in table_data: + for i, cell in enumerate(row): + if i < len(col_widths): + # Find the maximum line width in this cell + max_line_width = 0 + for line in cell: + max_line_width = max(max_line_width, len(line.rstrip())) + col_widths[i] = max(col_widths[i], max_line_width) + + return col_widths + + +def generate_border_line(col_widths: List[int], indent: str = '') -> str: + """Generate a border line for the table with proper indentation.""" + parts = ['+'] + for width in col_widths: + parts.append('-' * width + '+') + return indent + ''.join(parts) + + +def generate_data_lines(row: List[List[str]], col_widths: List[int], indent: str = '') -> List[str]: + """Generate data lines for a table row, handling multi-line cells with proper indentation.""" + # Find the maximum number of lines in any cell of this row + max_lines = max(len(cell) for cell in row) if row else 0 + + data_lines = [] + + for line_idx in range(max_lines): + parts = ['|'] + for col_idx, cell in enumerate(row): + if col_idx < len(col_widths): + # Get the content for this line of the cell, or empty string if no more lines + if line_idx < len(cell): + cell_content = cell[line_idx].rstrip() + else: + cell_content = '' + + # Pad the cell content to the column width + padded_cell = cell_content.ljust(col_widths[col_idx]) + parts.append(padded_cell + '|') + + data_lines.append(indent + ''.join(parts)) + + return data_lines + + +def rebuild_table(table_data: List[List[List[str]]], indent: str = '') -> List[str]: + """Rebuild the grid table as a list of lines with proper indentation and preserved formatting.""" + if not table_data: + return [] + + col_widths = calculate_column_widths(table_data) + border_line = generate_border_line(col_widths, indent) + + lines = [border_line] + + for i, row in enumerate(table_data): + data_lines = generate_data_lines(row, col_widths, indent) + lines.extend(data_lines) + lines.append(border_line) + + return lines + + +def find_table_directive(lines: List[str], start_idx: int) -> Tuple[bool, int, Optional[str], str]: + """ + Check if there's a .. table:: directive before the given grid table. + The directive must be the first non-empty line when looking backwards from the table. + + Returns: + - is_table_directive: True if this grid table is declared with .. table:: + - directive_start: Index where the directive starts + - table_title: Optional title from the directive + - table_indent: The indentation string used for the table + """ + # Get the indentation of the table itself + table_line = lines[start_idx] + table_indent = '' + for char in table_line: + if char in ' \t': + table_indent += char + else: + break + + # Look backwards from the grid table start to find the first non-empty line + i = start_idx - 1 + + # Skip empty lines immediately before the table + while i >= 0 and lines[i].strip() == '': + i -= 1 + + if i < 0: + return False, -1, None, '' + + # The first non-empty line must be the .. table:: directive + line = lines[i] + stripped_line = line.strip() + + if stripped_line.startswith('.. table::') or \ + stripped_line.startswith(':header-rows') or \ + stripped_line.startswith(':widths'): + # Found the directive as the first non-empty line + table_title = None + if len(stripped_line) > 10: # More than just ".. table::" + table_title = stripped_line[10:].strip() + return True, i, table_title, table_indent + + # First non-empty line is not .. table:: directive + return False, -1, None, '' + + +def process_rst_file(content: str, columns_to_remove: List[str], remove_empty_rows: bool = False) -> str: + """Process the entire RST content and remove specified columns from grid tables declared with .. table:: directive.""" + lines = content.split('\n') + result_lines = [] + i = 0 + + while i < len(lines): + line = lines[i] + + # Check if this line might be the start of a grid table + if line.strip().startswith('+') and '-' in line: + # Check if this grid table is declared with .. table:: directive + is_directive_table, directive_start, table_title, table_indent = find_table_directive(lines, i) + + if is_directive_table: + # Try to parse as a grid table + table_data, original_col_widths, end_idx = parse_grid_table(lines, i) + + if table_data and len(table_data) > 0: + # Assume first row contains headers + headers = table_data[0] + col_indices = find_column_indices(headers, columns_to_remove) + + # Add any lines we haven't processed yet up to the current position + while len(result_lines) < i: + result_lines.append(lines[len(result_lines)]) + + if col_indices: + # Remove specified columns and rebuild table with preserved indentation + new_table_data = remove_columns_and_empty_rows(table_data, col_indices, remove_empty_rows) + new_table_lines = rebuild_table(new_table_data, table_indent) + result_lines.extend(new_table_lines) + + title_info = f" ('{table_title}')" if table_title else "" + removed_cols_info = ['\n'.join(headers[idx]).strip() for idx in sorted(col_indices)] + empty_rows_info = " and empty rows" if remove_empty_rows else "" + print(f"Processed table{title_info}: removed columns {removed_cols_info}{empty_rows_info}", file=sys.stderr) + else: + # No columns to remove, keep original table + result_lines.extend(lines[i:end_idx]) + + i = end_idx + else: + # Not a valid grid table, keep the line + result_lines.append(line) + i += 1 + else: + # Grid table not declared with .. table:: directive, keep it unchanged + result_lines.append(line) + i += 1 + else: + # Regular line, keep it + result_lines.append(line) + i += 1 + + return '\n'.join(result_lines) + + +def main(): + parser = argparse.ArgumentParser( + description='Remove columns from reStructuredText grid tables declared with .. table:: directive', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + %(prog)s input.rst -o output.rst + %(prog)s input.rst --output output.rst + cat input.rst | %(prog)s - > output.rst + +The RST file should contain field list entries specifying columns to remove: + :remove-column-from-html-table: Column1, Column2, Column3 + +Note: Only processes grid tables declared with the .. table:: directive. +Standalone grid tables will be left unchanged. + """ + ) + + parser.add_argument('input', + help='Input RST file (use "-" for stdin)') + parser.add_argument('-o', '--output', + help='Output file (default: stdout)') + + args = parser.parse_args() + + # Read input + if args.input == '-': + content = sys.stdin.read() + else: + try: + with open(args.input, 'r', encoding='utf-8') as f: + content = f.read() + except IOError as e: + print(f"Error reading input file: {e}", file=sys.stderr) + sys.exit(1) + + # Find columns to remove from the content itself + lines = content.split('\n') + + # Check docs-build-context against environment variable + check_docs_build_context(lines) + + # Find columns to remove and whether to remove emptied rows + columns_to_remove = find_column_removal_directives(lines) + remove_empty_rows = should_remove_emptied_rows(lines) + + if not columns_to_remove: + print("No column removal directives found in the file.", file=sys.stderr) + print("Looking for: :remove-column-from-html-table: Column1, Column2", file=sys.stderr) + + if remove_empty_rows: + print("Will remove rows that become empty after column removal.", file=sys.stderr) + + # Process content + try: + result = process_rst_file(content, columns_to_remove, remove_empty_rows) + except Exception as e: + print(f"Error processing file: {e}", file=sys.stderr) + sys.exit(1) + + # Write output + if args.output: + try: + with open(args.output, 'w', encoding='utf-8') as f: + f.write(result) + except IOError as e: + print(f"Error writing output file: {e}", file=sys.stderr) + sys.exit(1) + else: + print(result, end='') + + +if __name__ == '__main__': + main() diff --git a/remove-list-columns.py b/remove-list-columns.py new file mode 100644 index 000000000..6b4964807 --- /dev/null +++ b/remove-list-columns.py @@ -0,0 +1,153 @@ +import os +import re +import sys + +def parse_meta_directives(lines): + directives = {} + for line in lines: + if ":remove-column-from-html-table:" in line: + directives["remove_column"] = line.split(":", 2)[2].strip() + if ":remove-column-emptied-row:" in line: + directives["remove_emptied_row"] = line.split(":", 2)[2].strip() == "1" + return directives + +def extract_table_blocks(lines): + blocks = [] + current = [] + inside = False + for line in lines: + if line.strip().startswith(".. list-table::"): + inside = True + current = [line] + elif inside and line.startswith(" ") or line.strip() == "": + current.append(line) + elif inside: + blocks.append(current) + inside = False + if inside: + blocks.append(current) + return blocks + +def split_table_row(row_lines): + """Splits a table row (beginning with '*') into a list of cells.""" + cells = [] + current_cell = [] + for line in row_lines: + if re.match(r'^\s*\*\s+-', line): # First cell in row + parts = re.split(r'\s*\*\s+-\s*', line, maxsplit=1) + current_cell = [parts[1]] + elif re.match(r'^\s*-\s+', line): # New cell + cells.append(current_cell) + current_cell = [line.strip()[2:]] + else: + current_cell.append(line.strip()) + cells.append(current_cell) + return cells + +def join_cells(cells, base_indent=" "): + """Reconstructs a list-table row from cell lists.""" + line = f"{base_indent}* - " + cells[0][0] + lines = [line] + for line in cells[0][1:]: + lines.append(base_indent + " " + line) + for cell in cells[1:]: + lines.append(base_indent + " - " + cell[0]) + for l in cell[1:]: + lines.append(base_indent + " " + l) + return lines + +def process_table(table_lines, col_to_remove, remove_empty_row=False): + processed = [] + table_rows = [] + header_index = -1 + header_row = [] + buffer = [] + + for line in table_lines: + if re.match(r'\s*\*\s+-', line): + if buffer: + table_rows.append(buffer) + buffer = [line] + elif buffer != [] and (line.strip() == "" or re.match(r'^\s*(-|[^*].*)$', line)): + buffer.append(line) + else: + if buffer: + table_rows.append(buffer) + buffer = [] + processed.append(line) + + if buffer: + table_rows.append(buffer) + + # Parse header row + for i, row in enumerate(table_rows): + if i == 0: + cells = split_table_row(row) + flat_cells = [' '.join(c).strip() for c in cells] + if col_to_remove not in flat_cells: + return table_lines # Don't modify + header_index = flat_cells.index(col_to_remove) + header_row = cells + break + + if header_index == -1: + return table_lines # Don't modify + + # Remove the column from each row + new_rows = [] + for row in table_rows: + cells = split_table_row(row) + if header_index >= len(cells): + continue + if remove_empty_row and all(not ''.join(cell).strip() for cell in cells[:header_index] + cells[header_index+1:]): + continue + del cells[header_index] + new_rows.append(join_cells(cells)) + + return processed + [""] + [line for row in new_rows for line in row] + +def process_file(path): + with open(path, 'r', encoding='utf-8') as f: + lines = f.readlines() + + directives = parse_meta_directives(lines) + if "remove_column" not in directives: + return + + table_blocks = extract_table_blocks(lines) + output_lines = [] + i = 0 + while i < len(lines): + line = lines[i] + if line.strip().startswith(".. list-table::"): + # Find the table block and replace + for block in table_blocks: + if lines[i:i+len(block)] == block: + processed = process_table( + block, + directives["remove_column"], + directives.get("remove_emptied_row", False) + ) + output_lines.extend(processed) + i += len(block) + break + else: + output_lines.append(line) + i += 1 + + with open(path, 'w', encoding='utf-8') as f: + f.writelines(l + ("\n" if not l.endswith("\n") else "") for l in output_lines) + +def scan_dir(directory): + for root, _, files in os.walk(directory): + for name in files: + if name.endswith(".rst"): + process_file(os.path.join(root, name)) + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("Usage: python remove-columns.py ") + sys.exit(1) + process_file(sys.argv[1]) + # scan_dir(sys.argv[1]) + diff --git a/remove_empty-grid_rows.py b/remove_empty-grid_rows.py new file mode 100644 index 000000000..bff31b64f --- /dev/null +++ b/remove_empty-grid_rows.py @@ -0,0 +1,68 @@ +import sys +import re + +def is_grid_table_line(line): + return re.match(r'^\+[-=+]+$', line.strip()) is not None + +def is_grid_row_empty(row): + # A grid row is considered empty if the cells contain only whitespace or are just column dividers + content = re.sub(r'[+|]', '', row) + return content.strip() == '' + + +def remove_empty_grid_rows(lines): + result = [] + i = 0 + while i < len(lines): + line = lines[i] + + if is_grid_table_line(line): + result.append(line) + + # Check if there's a data line and a closing border after this + if i + 2 < len(lines): + data_line = lines[i + 1] + next_border = lines[i + 2] + + if is_grid_table_line(next_border): + if is_grid_row_empty(data_line): + # Skip this row (data + border) + i += 3 + continue + else: + # Keep data row and closing border + result.append(data_line) + result.append(next_border) + i += 3 + continue + else: + # Not a properly structured row — just advance + i += 1 + else: + # Not enough lines ahead — just advance + i += 1 + else: + result.append(line) + i += 1 + + return result + + +def remove_empty_table_rows(filepath): + with open(filepath, 'r', encoding='utf-8') as f: + lines = f.readlines() + + lines = remove_empty_grid_rows(lines) + + with open(filepath, 'w', encoding='utf-8') as f: + f.writelines(lines) + +if __name__ == '__main__': + if len(sys.argv) != 2: + print("Usage: python remove_empty-grid_rows.py path/to/file.rst") + sys.exit(1) + + filepath = sys.argv[1] + remove_empty_table_rows(filepath) + print(f"Processed: {filepath}") + diff --git a/remove_empty-list_rows.py b/remove_empty-list_rows.py new file mode 100644 index 000000000..36efca693 --- /dev/null +++ b/remove_empty-list_rows.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python3 +""" +Script to remove empty rows from reStructuredText grid tables and list tables. +Supports both grid tables (with +---+ borders) and simple list tables. +""" + +import re +import argparse +import sys +from pathlib import Path + + +def is_list_row_empty(row_lines): + """ + Check if a list table row contains only empty cells. + + Args: + row_lines (list): Lines that make up the row + + Returns: + bool: True if row contains only empty cells, False otherwise + """ + # Join all lines and remove list markers + content = ' '.join(row_lines) + # Remove the first list marker + content = re.sub(r'^\s*\*\s*-\s*', '', content) + # Remove additional cell separators + content = re.sub(r'\s*-\s*', ' ', content) + # Check if anything meaningful remains + return not content.strip() + + +def clean_list_table(table_text): + """ + Remove empty rows from a reStructuredText list table. + + Args: + table_text (str): The complete list table text + + Returns: + str: Cleaned table text with empty rows removed + """ + lines = table_text.split('\n') + cleaned_lines = [] + + current_row_lines = [] + in_row = False + + for i, line in enumerate(lines): + # Check if this line starts a new row (begins with *) + if re.match(r'^\s*\*\s*-', line): + # Process previous row if it exists + if current_row_lines: + if not is_list_row_empty(current_row_lines): + cleaned_lines.extend(current_row_lines) + current_row_lines = [] + + # Start new row + current_row_lines = [line] + in_row = True + elif in_row and re.match(r'^\s+-', line): + # This is a continuation of the current row (additional columns) + current_row_lines.append(line) + elif in_row and line.strip() == '': + # Empty line might end the row, but could also be within row + # Look ahead to see if next line continues the row + if i + 1 < len(lines) and re.match(r'^\s*-', lines[i + 1]): + current_row_lines.append(line) # Part of current row + else: + # End of row + if not is_list_row_empty(current_row_lines): + cleaned_lines.extend(current_row_lines) + current_row_lines = [] + cleaned_lines.append(line) + in_row = False + elif in_row and re.match(r'^\s+\S', line): + # Multi-line cell content + current_row_lines.append(line) + else: + # Not in a row, or row ended + if current_row_lines: + if not is_list_row_empty(current_row_lines): + cleaned_lines.extend(current_row_lines) + current_row_lines = [] + cleaned_lines.append(line) + in_row = False + + # Handle the last row + if current_row_lines and not is_list_row_empty(current_row_lines): + cleaned_lines.extend(current_row_lines) + + return '\n'.join(cleaned_lines) + + +def process_content(content): + """ + Process the entire content, finding and cleaning all tables. + + Args: + content (str): Full document content + + Returns: + str: Content with cleaned tables + """ + lines = content.split('\n') + result_lines = [] + i = 0 + + while i < len(lines): + line = lines[i] + + # Check for list table start + if re.match(r'^\s*\.\.\s+(list-table::|table::)', line): + # Found list table directive, collect the entire table + table_lines = [line] + i += 1 + + # Collect all indented lines that belong to this directive + while i < len(lines): + current_line = lines[i] + if (current_line.strip() == '' or + current_line.startswith(' ') or + current_line.startswith('\t')): + table_lines.append(current_line) + i += 1 + elif re.match(r'^\s*\*\s*-', current_line): + # This is a list table row + table_lines.append(current_line) + i += 1 + else: + break + + # Clean the list table + table_text = '\n'.join(table_lines) + cleaned_table = clean_list_table(table_text) + result_lines.extend(cleaned_table.split('\n')) + + else: + result_lines.append(line) + i += 1 + + return '\n'.join(result_lines) + + +def main(): + parser = argparse.ArgumentParser( + description='Remove empty rows from reStructuredText tables' + ) + parser.add_argument( + 'input_file', + help='Input .rst file path' + ) + parser.add_argument( + '-o', '--output', + help='Output file path (default: overwrite input file)' + ) + parser.add_argument( + '--dry-run', + action='store_true', + help='Show what would be changed without modifying files' + ) + + args = parser.parse_args() + + # Read input file + try: + input_path = Path(args.input_file) + with open(input_path, 'r', encoding='utf-8') as f: + content = f.read() + except FileNotFoundError: + print(f"Error: File '{args.input_file}' not found", file=sys.stderr) + sys.exit(1) + except Exception as e: + print(f"Error reading file: {e}", file=sys.stderr) + sys.exit(1) + + # Clean the content + cleaned_content = process_content(content) + + # Handle output + if args.dry_run: + print("=== DRY RUN MODE ===") + if cleaned_content != content: + print("Changes would be made:") + print("=" * 50) + print(cleaned_content) + print("=" * 50) + else: + print("No changes needed.") + else: + output_path = Path(args.output) if args.output else input_path + + try: + with open(output_path, 'w', encoding='utf-8') as f: + f.write(cleaned_content) + print(f"Successfully cleaned tables in '{output_path}'") + except Exception as e: + print(f"Error writing file: {e}", file=sys.stderr) + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/tox.ini b/tox.ini index 175d9960b..83b67bb8a 100644 --- a/tox.ini +++ b/tox.ini @@ -11,6 +11,8 @@ setenv = VIRTUAL_ENV={envdir} OS_TEST_TIMEOUT=60 LC_ALL=C DOCS_BUILD_CONTEXT=starlingx +drop_table_cols = {env:DROP_TABLE_COLS:bash -c 'for f in $(grep -rl -e :remove-column-from-html-table: doc/source/*); do python3 remove-list-columns.py "$f" -o "$f"; python3 remove-grid-columns.py "$f" -o "$f"; done'} +drop_table_rows = {env:DROP_TABLE_ROWS:bash -c 'for f in $(grep -rl -e :remove-empty-table-rows: doc/source/*); do python3 remove_empty-list_rows.py "$f" -o "$f"; python3 remove_empty-grid_rows.py "$f" -o "$f"; done'} deps = -r{toxinidir}/test-requirements.txt [testenv:prebuild-docs] @@ -27,6 +29,8 @@ commands = bash ./fetch-ports-files.sh python py_2_xlsx.py tmp/platform_firewall.py tmp/constants.py tmp/FW_PORTS.xlsx python xlst_2_csv.py tmp/FW_PORTS.xlsx doc/source/shared/FW_PORTS.csv --columns Source Port Protocol Network Desc HTTPS Note _stx --sort_orders Port=asc --filters _stx=y + {[testenv]drop_table_cols} + {[testenv]drop_table_rows} [testenv:postbuild-docs] commands = @@ -34,8 +38,8 @@ commands = git restore doc/source/dist_cloud/kubernetes/* bash hw-updates.sh # bash hide-empty-rows.sh doc/build/html - bash -c 'python hide-empty-rows.py $(grep -rl --include="*.html" "post-build-hide-empty-table-rows" doc/build/html/*)' - bash -c 'python hide-table-columns.py $(grep -rl --include=*.html --exclude=doc_contribute_guide.html remove-column-from-html-table doc/build/html/*)' + # bash -c 'python hide-empty-rows.py $(grep -rl --include="*.html" "post-build-hide-empty-table-rows" doc/build/html/*)' + # bash -c 'python hide-table-columns.py $(grep -rl --include=*.html --exclude=doc_contribute_guide.html remove-column-from-html-table doc/build/html/*)' bash htmlChecks.sh doc/build/html [testenv:docs]