|
| 1 | + |
| 2 | +# Modularity Sphinx Extension |
| 3 | + |
| 4 | +A Sphinx extension that enables conditional documentation rendering based on feature flags. |
| 5 | + |
| 6 | +## Overview |
| 7 | + |
| 8 | +The extension consists of two main components: |
| 9 | + |
| 10 | +1. `feature_flags.bzl`: A Bazel translation layer that converts commands into tags |
| 11 | +2. `modularity`: A Sphinx extension that filters documentation based on feature flags |
| 12 | + |
| 13 | +It currently functions as a blacklist. |
| 14 | +**The extension is setup so it only disables requirements where *all* tags are contained within the filtered ones.** |
| 15 | + |
| 16 | +## Usage |
| 17 | + |
| 18 | +### Command Line |
| 19 | + |
| 20 | +Disable features when building documentation: |
| 21 | + |
| 22 | +```bash |
| 23 | +docs build //docs:docs --//docs:feature1=true |
| 24 | +``` |
| 25 | + |
| 26 | +## Configuration |
| 27 | + |
| 28 | +### Feature Flags (feature_flags.bzl) |
| 29 | + |
| 30 | +The `feature_flags.bzl` file takes care of the following things: |
| 31 | + |
| 32 | +- Feature-to-tag translation |
| 33 | +- Feature name to flag mappings |
| 34 | +- Default values for flags |
| 35 | +- Temporary file generation for flag storage |
| 36 | + |
| 37 | +Example configuration: |
| 38 | + |
| 39 | +Mapping of features to tags is defined as follows: |
| 40 | + |
| 41 | +```bzl |
| 42 | +FEATURE_TAG_MAPPING = { |
| 43 | + "feature1": ["some-ip", "tag2"], # --//docs:feature1=true -> will expand to 'some-ip', 'tag2' |
| 44 | + "second-feature": ["test-feat", "tag6"], |
| 45 | +} |
| 46 | +``` |
| 47 | + |
| 48 | +The default values are defined like such: |
| 49 | +```bzl |
| 50 | +def define_feature_flags(name): |
| 51 | + bool_flag( |
| 52 | + name = "feature1", |
| 53 | + build_setting_default = False, |
| 54 | + ) |
| 55 | + bool_flag( |
| 56 | + name = "second-feature", |
| 57 | + build_setting_default = False, |
| 58 | + ) |
| 59 | + |
| 60 | + feature_flag_translator( |
| 61 | + name = name, |
| 62 | + flags = {":feature1": "True", ":second-feature": "True"}, |
| 63 | + ) |
| 64 | +``` |
| 65 | +As can be seen here, each flag needs to be registered as well as have a default value defined. |
| 66 | +After adding new flags it's possible to call them via the `--//docs:<flag-name>=<value>` command |
| 67 | + |
| 68 | +The `feature_flag.bzl` file will after parsing the flags and translating them write a temporary file with all to be disabled tags. |
| 69 | + |
| 70 | +### Extension (modularity) |
| 71 | + |
| 72 | +The extension processes the temporary flag file and disables documentation sections tagged with disabled features. |
| 73 | + |
| 74 | +#### Use in requirements |
| 75 | + |
| 76 | +All requirements which tags are **all** contained within the tags that we look for, will be disabled. |
| 77 | +Here an eaxmple to illustrate the point. |
| 78 | +We will disable the `test-feat` tag via feature flags. If we take the following example rst: |
| 79 | +```rst |
| 80 | +.. tool_req:: Test_TOOL |
| 81 | + :id: TEST_TOOL_REQ |
| 82 | + :tags: feature1, test-feat |
| 83 | + :satisfies: TEST_STKH_REQ_1, TEST_STKH_REQ_20 |
| 84 | + |
| 85 | + We will see that this should still be rendered but 'TEST_STKH_REQ_1' will be missing from the 'satisfies' option |
| 86 | +
|
| 87 | +.. stkh_req:: Test_REQ disable |
| 88 | + :id: TEST_STKH_REQ_1 |
| 89 | + :tags: test-feat |
| 90 | + |
| 91 | + This is a requirement that we would want to disable via the feature flag |
| 92 | +
|
| 93 | +.. stkh_req:: Test_REQ do not disable |
| 94 | + :id: TEST_STKH_REQ_20 |
| 95 | + :tags: feature1 |
| 96 | +
|
| 97 | + This requirement will not be disabled. |
| 98 | +``` |
| 99 | +We can then build it with our feature flag enabled via `bazel build //docs:docs --//docs:second-feature=true` |
| 100 | +This will expand via our translation layer `feature_flag.bzl` into the tags `test-feat` and `tag5`. |
| 101 | + |
| 102 | +**The extension is setup so it only disables requirements where *all* tags are contained within the filtered ones.** |
| 103 | +In the rst above `TEST_TOOL_REQ` has the `test-feat` tag but it also has the `feature1` tag, therefore it wont be disabled. |
| 104 | +In contrast, TEST_STKH_REQ_20 has only the `test-feat` tag, therefore it will be disabled and removed from any links as well. |
| 105 | + |
| 106 | +If we now look at the rendered HTML: |
| 107 | + |
| 108 | + |
| 109 | +We can confirm that the `TEST_STKH_REQ_1` requirement is gone and so is the reference to it from `TEST_TOOL_REQ`. |
| 110 | + |
| 111 | + |
| 112 | +*However, keep in mind that in the source code the actual underlying RST has not changed, it's just the HTML.* |
| 113 | +This means that one can still see all the requirements there and also if searching for it will still find the document where it is mentioned. |
| 114 | + |
| 115 | + |
| 116 | +### How the extension achieves this? |
| 117 | + |
| 118 | +The extension uses a sphinx-needs buildin option called `hide`. If a need has the `hide=True` it will not be shown in the final HTML. |
| 119 | +It also gatheres a list of all 'hidden' requirements as it then in a second iteration removes these from any of the possible links. |
| 120 | + |
0 commit comments