From 15321e9fe9269bb1e71204eeb07fb959d5a67430 Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Sat, 26 Feb 2022 13:35:34 +0100 Subject: [PATCH] feat: auto-discover tags and add annotation identifier (#250) --- ansibledoctor/config.py | 4 +-- ansibledoctor/doc_parser.py | 10 +++---- ansibledoctor/templates/hugo-book/_tag.j2 | 13 +++++++++ ansibledoctor/templates/hugo-book/_toc.j2 | 6 +++++ ansibledoctor/templates/hugo-book/index.md.j2 | 3 +++ ansibledoctor/templates/readme/README.md.j2 | 3 +++ ansibledoctor/templates/readme/_tag.j2 | 12 +++++++++ ansibledoctor/templates/readme/_toc.j2 | 6 +++++ ansibledoctor/utils.py | 14 ++++++++++ docs/content/usage/getting-started.md | 27 +++++++++++++++++++ example/README.md | 11 ++++++++ example/demo-role/tasks/main.yml | 14 +++++++++- 12 files changed, 115 insertions(+), 8 deletions(-) create mode 100644 ansibledoctor/templates/hugo-book/_tag.j2 create mode 100644 ansibledoctor/templates/readme/_tag.j2 diff --git a/ansibledoctor/config.py b/ansibledoctor/config.py index c93edbf..248d408 100644 --- a/ansibledoctor/config.py +++ b/ansibledoctor/config.py @@ -133,8 +133,8 @@ class Config(): "tag": { "name": "tag", "automatic": True, - "subtypes": [], - "allow_multiple": True + "subtypes": ["value", "description"], + "allow_multiple": False }, } diff --git a/ansibledoctor/doc_parser.py b/ansibledoctor/doc_parser.py index 18a4bd3..27ed38e 100644 --- a/ansibledoctor/doc_parser.py +++ b/ansibledoctor/doc_parser.py @@ -14,6 +14,7 @@ from ansibledoctor.contstants import YAML_EXTENSIONS from ansibledoctor.file_registry import Registry from ansibledoctor.utils import SingleLog from ansibledoctor.utils import UnsafeTag +from ansibledoctor.utils import flatten class Parser: @@ -28,6 +29,7 @@ class Parser: self._files_registry = Registry() self._parse_meta_file() self._parse_var_files() + self._parse_task_tags() self._populate_doc_data() def _yaml_remove_comments(self, d): @@ -107,7 +109,9 @@ class Parser: raw = ruamel.yaml.YAML(typ="rt").load(yaml_file) self._yaml_remove_comments(raw) - data = defaultdict(dict, raw) + tags = list(set(flatten(nested_lookup("tags", raw)))) + for tag in tags: + self._data["tag"][tag] = {"value": tag} except ( ruamel.yaml.composer.ComposerError, ruamel.yaml.scanner.ScannerError ) as e: @@ -116,10 +120,6 @@ class Parser: "Unable to read yaml file {}\n{}".format(rfile, message) ) - tags_found = nested_lookup("tags", data) - for tag in tags_found: - self._data["tags"][tag] = {} - def _populate_doc_data(self): """Generate the documentation data object.""" tags = defaultdict(dict) diff --git a/ansibledoctor/templates/hugo-book/_tag.j2 b/ansibledoctor/templates/hugo-book/_tag.j2 new file mode 100644 index 0000000..a42f1c0 --- /dev/null +++ b/ansibledoctor/templates/hugo-book/_tag.j2 @@ -0,0 +1,13 @@ +{% set tag = role.tag | default({}) %} +{% if tag %} +## Discovered Tags +{% for key, item in tag | dictsort %} + +{{ key }} +{% if item.description is defined and item.description | save_join(" ") | striptags %} +: {{ item.description | save_join(" ") | striptags }} +{% else %} +:   +{% endif %} +{% endfor %} +{% endif %} diff --git a/ansibledoctor/templates/hugo-book/_toc.j2 b/ansibledoctor/templates/hugo-book/_toc.j2 index b85bae4..7e0a931 100644 --- a/ansibledoctor/templates/hugo-book/_toc.j2 +++ b/ansibledoctor/templates/hugo-book/_toc.j2 @@ -5,6 +5,12 @@ - [{{ key }}](#{{ key }}) {% endfor %} {% endif %} +{% if tag %} +- [Discovered Tags](#discovered-tags) +{% endif %} +{% if todo %} +- [Open Tasks](#open-tasks) +{% endif %} - [Dependencies](#dependencies) --- diff --git a/ansibledoctor/templates/hugo-book/index.md.j2 b/ansibledoctor/templates/hugo-book/index.md.j2 index 806fbc7..5340872 100644 --- a/ansibledoctor/templates/hugo-book/index.md.j2 +++ b/ansibledoctor/templates/hugo-book/index.md.j2 @@ -16,6 +16,9 @@ type: docs {# Vars #} {% include '_vars.j2' %} +{# Todo #} +{% include '_tag.j2' %} + {# Todo #} {% include '_todo.j2' %} diff --git a/ansibledoctor/templates/readme/README.md.j2 b/ansibledoctor/templates/readme/README.md.j2 index b4e66c2..0fecd44 100644 --- a/ansibledoctor/templates/readme/README.md.j2 +++ b/ansibledoctor/templates/readme/README.md.j2 @@ -13,6 +13,9 @@ {# Vars #} {% include '_vars.j2' %} +{# Todo #} +{% include '_tag.j2' %} + {# Todo #} {% include '_todo.j2' %} diff --git a/ansibledoctor/templates/readme/_tag.j2 b/ansibledoctor/templates/readme/_tag.j2 new file mode 100644 index 0000000..681c97c --- /dev/null +++ b/ansibledoctor/templates/readme/_tag.j2 @@ -0,0 +1,12 @@ +{% set tag = role.tag | default({}) %} +{% if tag %} +## Discovered Tags +{% for key, item in tag | dictsort %} +{% set is_desc = item.description is defined and item.description | save_join(" ") | striptags %} + +**_{{ key }}_**{{ "\\" if is_desc else "" }} +{% if is_desc %} + {{ item.description | save_join(" ") | striptags }} +{% endif %} +{% endfor %} +{% endif %} diff --git a/ansibledoctor/templates/readme/_toc.j2 b/ansibledoctor/templates/readme/_toc.j2 index e564d6b..fc47a29 100644 --- a/ansibledoctor/templates/readme/_toc.j2 +++ b/ansibledoctor/templates/readme/_toc.j2 @@ -7,6 +7,12 @@ - [{{ key }}](#{{ key }}) {% endfor %} {% endif %} +{% if tag %} +- [Discovered Tags](#discovered-tags) +{% endif %} +{% if todo %} +- [Open Tasks](#open-tasks) +{% endif %} - [Dependencies](#dependencies) - [License](#license) - [Author](#author) diff --git a/ansibledoctor/utils.py b/ansibledoctor/utils.py index ab47320..75d0002 100644 --- a/ansibledoctor/utils.py +++ b/ansibledoctor/utils.py @@ -9,6 +9,11 @@ from distutils.util import strtobool import colorama from pythonjsonlogger import jsonlogger +try: + from typing import Iterable +except ImportError: + from collections import Iterable + import ansibledoctor.exception CONSOLE_FORMAT = "{}{}[%(levelname)s]{} %(message)s" @@ -19,6 +24,15 @@ def to_bool(string): return bool(strtobool(str(string))) +def flatten(items): + for x in items: + if isinstance(x, Iterable) and not isinstance(x, (str, bytes)): + for sub_x in flatten(x): + yield sub_x + else: + yield x + + def _should_do_markup(): py_colors = os.environ.get("PY_COLORS", None) if py_colors is not None: diff --git a/docs/content/usage/getting-started.md b/docs/content/usage/getting-started.md index 319aff1..6e75513 100644 --- a/docs/content/usage/getting-started.md +++ b/docs/content/usage/getting-started.md @@ -62,6 +62,33 @@ option2 docker_registry_password: "secret" ``` +### `@tag` + +Used tags within the Ansible task files will be auto-discovered. This identifier can be used to define tags manually or add extended information to discovered tags. + +option1 +: the name of the tag to which additional information should be added + +option2 +: supports `["value", "description"]` as information scopes + +**Example:** + +```YAML +- name: Demo task with a tag list + debug: + msg: "Demo message" + tags: + - role-tag1 + - role-tag2 + +# @tag single-tag:description: Example description of tag `single-tag` +- name: Demo task with a single tag + debug: + msg: "Demo message" + tags: single-tag +``` + ### `@todo` Identifier to open tasks that need to be addressed. The general structure for this identifier is `# @identifier option1: `. diff --git a/example/README.md b/example/README.md index a28b675..8c07b28 100644 --- a/example/README.md +++ b/example/README.md @@ -15,6 +15,8 @@ Role to demonstrate ansible-doctor. It is also possible to overwrite the default - [demo_role_single](#demo_role_single) - [demo_role_undefined_var](#demo_role_undefined_var) - [demo_role_unset](#demo_role_unset) +- [Discovered Tags](#discovered-tags) +- [Open Tasks](#open-tasks) - [Dependencies](#dependencies) - [License](#license) - [Author](#author) @@ -129,6 +131,15 @@ demo_role_unset: demo_role_unset: some_value ``` +## Discovered Tags + +**_role-tag1_** + +**_role-tag2_** + +**_single-tag_**\ + Example description of tag `single-tag` + ## Open Tasks - Unscoped general todo. diff --git a/example/demo-role/tasks/main.yml b/example/demo-role/tasks/main.yml index c558725..d6c032e 100644 --- a/example/demo-role/tasks/main.yml +++ b/example/demo-role/tasks/main.yml @@ -6,5 +6,17 @@ # @end # @todo improvement: Some things that need to be improved. - # @todo default: Unscoped general todo. + +- name: Demo task with a tag list + debug: + msg: "Demo message" + tags: + - role-tag1 + - role-tag2 + +# @tag single-tag:description: Example description of tag `single-tag` +- name: Demo task with a single tag + debug: + msg: "Demo message" + tags: single-tag