Skip to content

Commit

Permalink
Allow collections to render changelog as part of their docsite (#267)
Browse files Browse the repository at this point in the history
* Add dependency on antsibull-changelog.

* Refactor.

* Allow collections to add their changelog.

* Convert changelog config to a dict.

* Add documentation.

* Add tests.

* Add error handling.

* Remove some unnecessary newlines.

* Apply suggestions from code review.

Co-authored-by: Don Naro <[email protected]>

---------

Co-authored-by: Don Naro <[email protected]>
  • Loading branch information
felixfontein and oraNod authored Apr 6, 2024
1 parent ded050c commit a8f0773
Show file tree
Hide file tree
Showing 51 changed files with 1,187 additions and 78 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/antsibull-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ jobs:
- "stable-2"
antsibull_docs_parser_ref:
- main
antsibull_changelog_ref:
- main
include:
- options: '--use-current --use-html-blobs --no-breadcrumbs community.crypto community.docker --extra-conf antsibull_ext_color_scheme=none'
python: '3.9'
Expand All @@ -62,6 +64,13 @@ jobs:
path: antsibull-docs-parser
ref: ${{ matrix.antsibull_docs_parser_ref }}

- name: Check out dependent project antsibull-changelog
uses: actions/checkout@v4
with:
repository: ansible-community/antsibull-changelog
path: antsibull-changelog
ref: ${{ matrix.antsibull_changelog_ref }}

- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v5
with:
Expand Down Expand Up @@ -166,6 +175,12 @@ jobs:
repository: ansible-community/antsibull-docs-parser
path: antsibull-docs-parser

- name: Check out dependent project antsibull-changelog
uses: actions/checkout@v4
with:
repository: ansible-community/antsibull-changelog
path: antsibull-changelog

- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
Expand Down Expand Up @@ -224,6 +239,12 @@ jobs:
repository: ansible-community/antsibull-docs-parser
path: antsibull-docs-parser

- name: Check out dependent project antsibull-changelog
uses: actions/checkout@v4
with:
repository: ansible-community/antsibull-changelog
path: antsibull-changelog

- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/nox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ jobs:
with:
repository: ansible-community/antsibull-docs-parser
path: antsibull-docs-parser
- name: Check out dependent project antsibull-changelog
uses: actions/checkout@v4
with:
repository: ansible-community/antsibull-changelog
path: antsibull-changelog
- name: Install extra packages
if: "matrix.packages != ''"
run: |
Expand Down
2 changes: 2 additions & 0 deletions changelogs/fragments/267-changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- "It is now possible to render the collection changelog as part of the collection docsite by using the ``changelog`` option in ``docs/docsite/config.yml`` (https://github.com/ansible-community/antsibull-docs/issues/31, https://github.com/ansible-community/antsibull-docs/pull/267)."
23 changes: 23 additions & 0 deletions docs/collection-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,29 @@ The `sphinx-init` subcommand has quite a few configuration options:
* `--intersphinx` can be used to add intersphinx config entries to allow to use RST references to more external documentation. Refer to the [intersphinx documentation](https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html) for more information.
* `--project`, `--copyright`, `--title`, `--html-short-title`, `--extra-conf`, `--extra-html-context`, and `--extra-html-theme-options` can be used to add specific configuration entries to the Sphinx configuration `conf.py`.

## Configuring the docsite

Generally, configuration is done with a `docs/docsite/config.yml` YAML file. The format and options are as follows:
```yaml
---
# Whether the collection uses flatmapping to flatten subdirectories in
# `plugins/*/`.
flatmap: false

# List of environment variables that are defined by `.. envvar::` directives
# in the extra docsite RST files.
envvar_directives: []

# Changelog configuration (added in antsibull-docs 2.10.0)
changelog:
# Whether to write the changelog (taken from changelogs/changelog.yaml, see the
# antsibull-changelog documentation for more information) and link to it from the
# collection's index page.
write_changelog: false
```
Most collections should use `envvar_directives` and `changelog` only. The `flatmap` option applies to older versions of community.general and community.network and should be used for legacy collections only, not for new ones.

## Adding extra documentation

It is possible to add extra documentation in RST format to the docsite. This can for example be used to provide scenario guides. On the [community.crypto docsite](https://ansible-collections.github.io/community.crypto/branch/main/), there are for example some how-tos in the "Scenario Guides" section.
Expand Down
2 changes: 1 addition & 1 deletion noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def other_antsibull(
if mode is None:
mode = DEFAULT_MODE
to_install: list[str | Path] = []
args = ("antsibull-core", "antsibull-docs-parser")
args = ("antsibull-changelog", "antsibull-core", "antsibull-docs-parser")
for project in args:
path = Path("../", project)
path_exists = path.is_dir()
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ classifiers = [
requires-python = ">=3.9"
dependencies = [
"ansible-pygments",
"antsibull-changelog >= 0.24.0",
"antsibull-core >= 2.1.0, < 4.0.0",
"antsibull-docs-parser >= 1.0.0, < 2.0.0",
"asyncio-pool",
Expand Down Expand Up @@ -72,7 +73,6 @@ antsibull-docs = "antsibull_docs.cli.antsibull_docs:main"

[project.optional-dependencies]
codeqa = [
"antsibull-changelog",
"flake8 >= 3.8.0",
"pylint >= 2.17.2",
"reuse",
Expand Down
15 changes: 14 additions & 1 deletion src/antsibull_docs/cli/doc_commands/_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
DEFAULT_COLLECTION_URL_TRANSFORM,
)
from ...utils.collection_name_transformer import CollectionNameTransformer
from ...write_docs.changelog import output_changelogs
from ...write_docs.collections import output_extra_docs, output_indexes
from ...write_docs.hierarchy import (
output_collection_index,
Expand Down Expand Up @@ -144,7 +145,8 @@ def generate_docs_for_all_collections( # noqa: C901
with ``collection_names``.
:kwarg create_indexes: Whether to create the collection, namespace, and plugin indexes. By
default, they are created.
:kwarg create_collection_indexes: Whether to create the per-collection plugin index.
:kwarg create_collection_indexes: Whether to create the per-collection plugin index and other
global docs.
:kwarg add_extra_docs: Whether to add extra docs.
:kwarg add_redirect_stubs: Whether to create redirect stub files.
:kwarg squash_hierarchy: If set to ``True``, no directory hierarchy will be used.
Expand Down Expand Up @@ -344,6 +346,17 @@ def generate_docs_for_all_collections( # noqa: C901
)
flog.notice("Finished writing indexes")

asyncio.run(
output_changelogs(
collection_to_plugin_info,
dest_dir,
collection_metadata=collection_metadata,
squash_hierarchy=squash_hierarchy,
output_format=output_format,
)
)
flog.notice("Finished writing indexes")

if add_redirect_stubs:
asyncio.run(
output_all_plugin_stub_rst(
Expand Down
2 changes: 1 addition & 1 deletion src/antsibull_docs/cli/doc_commands/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def generate_plugin_docs(
)
except CalledProcessError as exc:
err_msg = []
formatted_exception = traceback.format_exception(None, exc, exc.__traceback__)
formatted_exception = traceback.format_exception(exc)
err_msg.append(
f"Exception while parsing documentation for {plugin_type} plugin:"
f" {plugin_name}. Will not document this plugin."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ Communication
.. toctree::
:maxdepth: 1

{% if has_changelog %}
Changelog
---------

.. toctree::
:maxdepth: 1

changelog

{% endif %}
{% for section in extra_docs_sections %}
@{section.title}@
@{ '-' * (section.title | column_width) }@
Expand All @@ -120,7 +130,6 @@ Communication
{% endif %}

{% endfor %}

Plugin Index
------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ Communication
{% endfor %}
{% endif %}

{% if has_changelog %}
Changelog
---------

`@{ collection_name.title() }@ Release Notes <changelog.rst>`_

{% endif %}
{% for section in extra_docs_sections %}
@{section.title}@
@{ '-' * (section.title | column_width) }@
Expand All @@ -95,7 +102,6 @@ Communication
{% endif %}

{% endfor %}

Plugin Index
------------

Expand Down
28 changes: 22 additions & 6 deletions src/antsibull_docs/jinja2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,46 @@

from enum import Enum

from antsibull_changelog.config import TextFormat


class OutputFormat(Enum):
def __init__(
self, output_format: str, template_extension: str, output_extension: str
self,
output_format: str,
template_extension: str,
output_extension: str,
changelog_format: TextFormat,
):
self._output_format = output_format
self._template_extension = template_extension
self._output_extension = output_extension
self._changelog_format = changelog_format

ANSIBLE_DOCSITE = ("ansible-docsite", ".rst.j2", ".rst")
SIMPLIFIED_RST = ("simplified-rst", ".rst.j2", ".rst")
ANSIBLE_DOCSITE = (
"ansible-docsite",
".rst.j2",
".rst",
TextFormat.RESTRUCTURED_TEXT,
)
SIMPLIFIED_RST = ("simplified-rst", ".rst.j2", ".rst", TextFormat.RESTRUCTURED_TEXT)

@property
def output_format(self):
def output_format(self) -> str:
return self._output_format

@property
def template_extension(self):
def template_extension(self) -> str:
return self._template_extension

@property
def output_extension(self):
def output_extension(self) -> str:
return self._output_extension

@property
def changelog_format(self) -> TextFormat:
return self._changelog_format

@classmethod
def parse(cls, output_format: str) -> OutputFormat:
for elt in cls:
Expand Down
8 changes: 8 additions & 0 deletions src/antsibull_docs/schemas/collection_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
from antsibull_docs._pydantic_compat import v1 as p


class ChangelogConfig(p.BaseModel):
# Whether to write the changelog
write_changelog: bool = False


class CollectionConfig(p.BaseModel):
# Whether the collection uses flatmapping to flatten subdirectories in
# `plugins/*/`.
Expand All @@ -20,3 +25,6 @@ class CollectionConfig(p.BaseModel):
# List of environment variables that are defined by `.. envvar::` directives
# in the extra docsite RST files.
envvar_directives: list[str] = []

# Changelog configuration (added in version 2.10.0)
changelog: ChangelogConfig = ChangelogConfig()
34 changes: 34 additions & 0 deletions src/antsibull_docs/write_docs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from __future__ import annotations

import os
from collections.abc import Mapping, Sequence

from antsibull_core.logging import log
Expand Down Expand Up @@ -36,3 +37,36 @@ def _render_template(_template: Template, _name: str, **kwargs) -> str:
)
except Exception as exc:
raise RuntimeError(f"Error while rendering {_name}") from exc


def _get_collection_dir(
dest_dir: str,
namespace: str,
collection: str,
/,
squash_hierarchy: bool = False,
create_if_not_exists: bool = False,
):
"""
Compose collection directory.
:arg dest_dir: Destination directory for the plugin data. For instance,
:file:`ansible-checkout/docs/docsite/rst/`. The directory structure underneath this
directory will be created if needed.
:arg namespace: The collection's namespace.
:arg collection: The collection's name.
:kwarg squash_hierarchy: If set to ``True``, no directory hierarchy will be used.
Undefined behavior if documentation for multiple collections are
created.
:kwarg create_if_not_exists: If set to ``True``, the directory will be created if it does
not exist. The ``dest_dir`` is assumed to exist.
"""
if squash_hierarchy:
return dest_dir

collection_dir = os.path.join(dest_dir, "collections", namespace, collection)
if create_if_not_exists:
# This is dangerous but the code that takes dest_dir from the user checks
# permissions on it to make it as safe as possible.
os.makedirs(collection_dir, mode=0o755, exist_ok=True)
return collection_dir
Loading

0 comments on commit a8f0773

Please sign in to comment.