From 4c29fc9f02bdfb4e689b1bb27035dc4a7dda0ca8 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Thu, 20 Mar 2025 14:13:03 +0100 Subject: [PATCH] Implemented more auto docs --- .gitignore | 3 +- 08_DEVELOPE.md | 1 - 08_DEVELOPE.rst | 4 +++ docs/.gitignore | 4 ++- docs/Makefile | 32 +++++++++++++-------- docs/conf.py | 11 +++++-- docs/generated/.gitkeep | 0 docs/generators/ansible_roles.py | 42 +++++++++++++++++++++++++++ docs/generators/yaml_index.py | 49 ++++++++++++++++++++++++++++++++ docs/requirements.txt | 4 ++- index.rst | 2 +- roles/docker-jenkins/README.md | 1 + roles/docker-xmpp/README.md | 2 ++ roles/nginx-https/README.md | 1 + 14 files changed, 135 insertions(+), 21 deletions(-) delete mode 100644 08_DEVELOPE.md create mode 100644 08_DEVELOPE.rst create mode 100644 docs/generated/.gitkeep create mode 100644 docs/generators/ansible_roles.py create mode 100644 docs/generators/yaml_index.py diff --git a/.gitignore b/.gitignore index 2862954e..3f8e7cdc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ site.retry *__pycache__ venv -*.log -modules/* \ No newline at end of file +*.log \ No newline at end of file diff --git a/08_DEVELOPE.md b/08_DEVELOPE.md deleted file mode 100644 index 6f8d214d..00000000 --- a/08_DEVELOPE.md +++ /dev/null @@ -1 +0,0 @@ -# Developer Guide \ No newline at end of file diff --git a/08_DEVELOPE.rst b/08_DEVELOPE.rst new file mode 100644 index 00000000..0dc39d0c --- /dev/null +++ b/08_DEVELOPE.rst @@ -0,0 +1,4 @@ +Developer Guide +=============== + +:doc: docs/generated/yaml_index.rst \ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore index ce2f9493..f84829b2 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,2 +1,4 @@ assets/img/* -generated/* \ No newline at end of file +build/* +generated/* +!generated/.gitkeep \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile index 960bd7e8..dab95cd3 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -5,10 +5,10 @@ SPHINXOPTS ?= -c . SPHINXBUILD ?= sphinx-build SPHINX_SOURCE_DIR ?= ../ -SPHINX_BUILD_DIR ?= ./generated -SPHINX_APIDOC_BUILD_DIR = $(SPHINX_SOURCE_DIR)modules +SPHINX_BUILD_DIR ?= ./build +SPHINX_GENERATED_DIR = ./generated -.PHONY: help install copy-images apidoc remove-apidoc html Makefile +.PHONY: help install copy-images apidoc remove-generated html Makefile # Copy images before running any Sphinx command (except for help) copy-images: @@ -16,23 +16,31 @@ copy-images: cp -vr ../assets/img/* ./assets/img/ # Generate reStructuredText files from Python modules using sphinx-apidoc -apidoc: +generate-apidoc: @echo "Running sphinx-apidoc..." - sphinx-apidoc -f -o $(SPHINX_APIDOC_BUILD_DIR) $(SPHINX_SOURCE_DIR) + sphinx-apidoc -f -o $(SPHINX_GENERATED_DIR)/modules $(SPHINX_SOURCE_DIR) -remove-apidoc: - @echo "Removing sphinx-apidoc files..." - - rm -rv $(SPHINX_APIDOC_BUILD_DIR) +remove-generated: + @echo "Removing generated files..." + - find $(SPHINX_GENERATED_DIR)/ -type f ! -name '.gitkeep' -delete + +generate-yaml-index: + @echo "Generating YAML index..." + python generators/yaml_index.py --source-dir $(SPHINX_SOURCE_DIR) --output-file $(SPHINX_GENERATED_DIR)/yaml_index.rst + +generate-ansible-roles: + @echo "Generating Ansible roles documentation..." + python generators/ansible_roles.py --roles-dir $(SPHINX_SOURCE_DIR)/roles --output-dir $(SPHINX_GENERATED_DIR)/roles # "help" target does not copy images help: @$(SPHINXBUILD) -M help "$(SPHINX_SOURCE_DIR)" "$(SPHINX_BUILD_DIR)" $(SPHINXOPTS) $(O) -# HTML target depends on apidoc so that sphinx-apidoc runs first -html: copy-images - @$(SPHINXBUILD) -M html "$(SPHINX_SOURCE_DIR)" "$(SPHINX_BUILD_DIR)" $(SPHINXOPTS) $(O) +html: copy-images generate-apidoc generate-yaml-index generate-ansible-roles + @$(SPHINXBUILD) -M html "$(SPHINX_SOURCE_DIR)" "$(SPHINX_BUILD_DIR)" $(SPHINXOPTS) -clean: remove-apidoc + +clean: remove-generated @$(SPHINXBUILD) -M html "$(SPHINX_SOURCE_DIR)" "$(SPHINX_BUILD_DIR)" $(SPHINXOPTS) $(O) # Catch-all target: route all unknown targets to Sphinx using the new diff --git a/docs/conf.py b/docs/conf.py index 8d810b99..e01c2dc0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -25,7 +25,11 @@ lexers['j2'] = DjangoLexer() # -- General configuration --------------------------------------------------- templates_path = ['templates'] -exclude_patterns = ['docs', 'venv', 'venv/**'] +exclude_patterns = [ + 'docs/build', + 'venv', + 'venv/**' + ] # -- Options for HTML output ------------------------------------------------- html_theme = 'sphinxawesome_theme' @@ -50,6 +54,8 @@ html_theme_options = { source_suffix = { '.rst': 'restructuredtext', '.md': 'markdown', + '.yml': 'restructuredtext', + '.yaml': 'restructuredtext', } sys.path.insert(0, os.path.abspath('./extensions')) @@ -62,8 +68,7 @@ extensions = [ 'extensions.roles_overview', 'extensions.markdown_include', 'sphinx.ext.autodoc', - 'sphinx.ext.napoleon', # Optional, wenn Sie Google- oder NumPy-Dokstrings verwenden - + 'sphinx.ext.napoleon', ] autosummary_generate = True diff --git a/docs/generated/.gitkeep b/docs/generated/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/generators/ansible_roles.py b/docs/generators/ansible_roles.py new file mode 100644 index 00000000..e7b50bf0 --- /dev/null +++ b/docs/generators/ansible_roles.py @@ -0,0 +1,42 @@ +import os +import yaml +import argparse + +def generate_ansible_roles_doc(roles_dir, output_dir): + """Generates reStructuredText documentation for Ansible roles.""" + if not os.path.exists(output_dir): + os.makedirs(output_dir) + + for role in os.listdir(roles_dir): + role_path = os.path.join(roles_dir, role) + meta_file = os.path.join(role_path, "meta/main.yml") + readme_file = os.path.join(role_path, "README.md") + + if os.path.exists(meta_file): + with open(meta_file, "r", encoding="utf-8") as f: + meta_data = yaml.safe_load(f) + + role_doc = os.path.join(output_dir, f"{role}.rst") + with open(role_doc, "w", encoding="utf-8") as f: + f.write(f"{role.capitalize()} Role\n") + f.write("=" * (len(role) + 7) + "\n\n") + f.write(f"**Description:** {meta_data.get('description', 'No description available')}\n\n") + + f.write("### Variables\n") + for key, value in meta_data.get('galaxy_info', {}).items(): + f.write(f"- **{key}**: {value}\n") + + if os.path.exists(readme_file): + f.write("\n### README\n") + with open(readme_file, "r", encoding="utf-8") as readme: + f.write("\n" + readme.read()) + + print(f"Ansible roles documentation has been generated in {output_dir}") + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Generate documentation for Ansible roles.") + parser.add_argument("--roles-dir", required=True, help="Directory containing Ansible roles.") + parser.add_argument("--output-dir", required=True, help="Directory where documentation will be saved.") + + args = parser.parse_args() + generate_ansible_roles_doc(args.roles_dir, args.output_dir) diff --git a/docs/generators/yaml_index.py b/docs/generators/yaml_index.py new file mode 100644 index 00000000..24b75249 --- /dev/null +++ b/docs/generators/yaml_index.py @@ -0,0 +1,49 @@ +import os +import argparse +import pathspec + +def load_gitignore_patterns(source_dir): + """Loads .gitignore patterns from the given source directory and returns a PathSpec object.""" + gitignore_path = os.path.join(source_dir, ".gitignore") + if not os.path.exists(gitignore_path): + return pathspec.PathSpec.from_lines("gitwildmatch", []) + + with open(gitignore_path, "r", encoding="utf-8") as f: + patterns = f.readlines() + + return pathspec.PathSpec.from_lines("gitwildmatch", patterns) + +def generate_yaml_index(source_dir, output_file): + """Generates an index file listing all YAML files in the specified directory while respecting .gitignore rules.""" + + yaml_files = [] + spec = load_gitignore_patterns(source_dir) # Load .gitignore rules + + # Walk through the source directory and collect YAML files + for root, _, files in os.walk(source_dir): + for file in files: + file_path = os.path.relpath(os.path.join(root, file), start=source_dir) + + if file.endswith(('.yml', '.yaml')) and not spec.match_file(file_path): + yaml_files.append(os.path.join(root, file)) + + # Create the output directory if it doesn't exist + os.makedirs(os.path.dirname(output_file), exist_ok=True) + + # Write the YAML index to the output file + with open(output_file, "w", encoding="utf-8") as f: + f.write("YAML Files\n===========\n\n") + f.write("This document lists all `.yaml` and `.yml` files found in the specified directory, excluding ignored files.\n\n") + + for file in sorted(yaml_files): + f.write(f".. literalinclude:: {file}\n :language: yaml\n :linenos:\n\n") + + print(f"YAML index has been generated at {output_file}") + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Generate an index for YAML files while respecting .gitignore.") + parser.add_argument("--source-dir", required=True, help="Directory containing YAML files.") + parser.add_argument("--output-file", required=True, help="Path to the output .rst file.") + + args = parser.parse_args() + generate_yaml_index(args.source_dir, args.output_file) diff --git a/docs/requirements.txt b/docs/requirements.txt index 6945d242..29a4c88d 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,4 +2,6 @@ myst-parser sphinx sphinxawesome-theme docutils -sphinxcontrib-jinja \ No newline at end of file +sphinx-jinja +sphinxcontrib-yaml +pathspec diff --git a/index.rst b/index.rst index 616c03b8..d080d163 100644 --- a/index.rst +++ b/index.rst @@ -1,4 +1,4 @@ About =============================== -.. markdown-include:: README.md \ No newline at end of file +.. markdown-include:: ../README.md \ No newline at end of file diff --git a/roles/docker-jenkins/README.md b/roles/docker-jenkins/README.md index 92e8f32c..f351d9f2 100644 --- a/roles/docker-jenkins/README.md +++ b/roles/docker-jenkins/README.md @@ -1 +1,2 @@ +# Jenkins This role is deprecated. Needs to be reimplemented. \ No newline at end of file diff --git a/roles/docker-xmpp/README.md b/roles/docker-xmpp/README.md index dfbdb794..ebfbcbec 100644 --- a/roles/docker-xmpp/README.md +++ b/roles/docker-xmpp/README.md @@ -1,3 +1,5 @@ +# XMPP +This role needs to be implemented - https://hub.docker.com/r/ejabberd/ecs/ - https://docs.ejabberd.im/CONTAINER/ - https://github.com/processone/docker-ejabberd diff --git a/roles/nginx-https/README.md b/roles/nginx-https/README.md index 257a9158..2bb720f0 100644 --- a/roles/nginx-https/README.md +++ b/roles/nginx-https/README.md @@ -1 +1,2 @@ +# Nginx Https Server This role loads the components to create an nginx server with https \ No newline at end of file