diff --git a/changelogs/fragments/49-collection-supported-ansible-core.yml b/changelogs/fragments/49-collection-supported-ansible-core.yml
new file mode 100644
index 00000000..ba5ba352
--- /dev/null
+++ b/changelogs/fragments/49-collection-supported-ansible-core.yml
@@ -0,0 +1,3 @@
+minor_changes:
+ - "Antsibull-docs now depends on `packaging `__ (https://github.com/ansible-community/antsibull-docs/pull/49)."
+ - "The collection index pages now contain the supported versions of ansible-core of the collection in case collection's ``meta/runtime.yml`` specifies ``requires_ansible`` (https://github.com/ansible-community/antsibull-docs/issues/48, https://github.com/ansible-community/antsibull-docs/pull/49)."
diff --git a/pyproject.toml b/pyproject.toml
index 808c4c61..1c6010a9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -39,6 +39,7 @@ antsibull-core = ">= 1.2.0, < 2.0.0"
asyncio-pool = "*"
docutils = "*"
jinja2 = "*"
+packaging = "*"
rstcheck = ">= 3.0.0, < 7.0.0"
sphinx = "*"
diff --git a/src/antsibull_docs/data/docsite/plugins_by_collection.rst.j2 b/src/antsibull_docs/data/docsite/plugins_by_collection.rst.j2
index bb566dd2..09d86741 100644
--- a/src/antsibull_docs/data/docsite/plugins_by_collection.rst.j2
+++ b/src/antsibull_docs/data/docsite/plugins_by_collection.rst.j2
@@ -27,7 +27,7 @@ Collection version @{ collection_version }@
:local:
:depth: 1
-{% if collection_description or collection_authors or collection_links %}
+{% if collection_description or collection_authors or collection_links or requires_ansible %}
Description
-----------
@@ -43,6 +43,14 @@ Description
{% endfor %}
{% endif %}
+{% if requires_ansible %}
+**Supported ansible-core versions:**
+
+{% for part in requires_ansible %}
+* @{ part | rst_escape }@
+{% endfor %}
+{% endif %}
+
{% if collection_links %}
.. raw:: html
diff --git a/src/antsibull_docs/docs_parsing/__init__.py b/src/antsibull_docs/docs_parsing/__init__.py
index 6a1e3a47..b99f4ac2 100644
--- a/src/antsibull_docs/docs_parsing/__init__.py
+++ b/src/antsibull_docs/docs_parsing/__init__.py
@@ -69,10 +69,15 @@ def _get_environment(collection_dir: t.Optional[str]) -> t.Dict[str, str]:
class AnsibleCollectionMetadata:
path: str
version: t.Optional[str]
+ requires_ansible: t.Optional[str]
- def __init__(self, path: str, version: t.Optional[str]):
+ def __init__(self,
+ path: str,
+ version: t.Optional[str] = None,
+ requires_ansible: t.Optional[str] = None):
self.path = path
self.version = version
+ self.requires_ansible = requires_ansible
def __repr__(self):
return f'AnsibleCollectionMetadata({repr(self.path)}, {repr(self.version)})'
diff --git a/src/antsibull_docs/docs_parsing/ansible_doc.py b/src/antsibull_docs/docs_parsing/ansible_doc.py
index 00636a4f..c4ab64b3 100644
--- a/src/antsibull_docs/docs_parsing/ansible_doc.py
+++ b/src/antsibull_docs/docs_parsing/ansible_doc.py
@@ -230,7 +230,8 @@ def get_collection_metadata(venv: t.Union['VenvRunner', 'FakeVenvRunner'],
raw_result = ansible_collection_list_cmd.stdout.decode('utf-8', errors='surrogateescape')
collection_list = parse_ansible_galaxy_collection_list(raw_result, collection_names)
for namespace, name, path, version in collection_list:
- collection_metadata[f'{namespace}.{name}'] = AnsibleCollectionMetadata(
+ collection_name = f'{namespace}.{name}'
+ collection_metadata[collection_name] = AnsibleCollectionMetadata(
path=path, version=version)
return collection_metadata
diff --git a/src/antsibull_docs/docs_parsing/routing.py b/src/antsibull_docs/docs_parsing/routing.py
index a392a95e..deabeae4 100644
--- a/src/antsibull_docs/docs_parsing/routing.py
+++ b/src/antsibull_docs/docs_parsing/routing.py
@@ -189,7 +189,14 @@ def remove_flatmapping_artifacts(plugin_routing: t.Dict[str, t.Dict[str, t.Dict[
plugin_routing_type.pop(plugin_name, None)
-def calculate_meta_runtime(collection_name, collection_metadata):
+def load_meta_runtime(collection_name: str,
+ collection_metadata: AnsibleCollectionMetadata) -> t.Mapping[str, t.Any]:
+ '''
+ Load meta/runtime.yml for collections, and ansible_builtin_runtime.yml for ansible-core.
+
+ Also extracts additional metadata stored in meta/runtime.yml, like requires_ansible,
+ and stores it in collection_metadata
+ '''
if collection_name == 'ansible.builtin':
meta_runtime_path = os.path.join(
collection_metadata.path, 'config', 'ansible_builtin_runtime.yml')
@@ -201,6 +208,11 @@ def calculate_meta_runtime(collection_name, collection_metadata):
else:
meta_runtime = {}
+ if collection_name != 'ansible.builtin':
+ requires_ansible = meta_runtime.get('requires_ansible')
+ if isinstance(requires_ansible, str):
+ collection_metadata.requires_ansible = requires_ansible
+
return meta_runtime
@@ -210,7 +222,7 @@ async def load_collection_routing(collection_name: str,
"""
Load plugin routing for a collection.
"""
- meta_runtime = calculate_meta_runtime(collection_name, collection_metadata)
+ meta_runtime = load_meta_runtime(collection_name, collection_metadata)
plugin_routing_out: t.Dict[str, t.Dict[str, t.Dict[str, t.Any]]] = {}
plugin_routing_in = meta_runtime.get('plugin_routing') or {}
for plugin_type in DOCUMENTABLE_PLUGINS:
diff --git a/src/antsibull_docs/write_docs.py b/src/antsibull_docs/write_docs.py
index 5d36ace3..1bf1175a 100644
--- a/src/antsibull_docs/write_docs.py
+++ b/src/antsibull_docs/write_docs.py
@@ -13,6 +13,7 @@
import asyncio_pool # type: ignore[import]
from jinja2 import Template
+from packaging.specifiers import SpecifierSet
from antsibull_core import app_context
from antsibull_core.logging import log
@@ -602,6 +603,29 @@ async def write_plugin_type_index(plugin_type: str,
await write_file(dest_filename, index_contents)
+def _parse_required_ansible(requires_ansible: str) -> t.List[str]:
+ result = []
+ for specifier in reversed(sorted(
+ SpecifierSet(requires_ansible),
+ key=lambda specifier: (specifier.operator, specifier.version)
+ )):
+ if specifier.operator == '>=':
+ result.append(f'{specifier.version} or newer')
+ elif specifier.operator == '>':
+ result.append(f'newer than {specifier.version}')
+ elif specifier.operator == '<=':
+ result.append(f'{specifier.version} or older')
+ elif specifier.operator == '<':
+ result.append(f'older than {specifier.version}')
+ elif specifier.operator == '!=':
+ result.append(f'version {specifier.version} is specifically not supported')
+ elif specifier.operator == '==':
+ result.append(f'version {specifier.version} is specifically supported')
+ else:
+ result.append(f'{specifier.operator} {specifier.version}')
+ return result
+
+
async def write_plugin_lists(collection_name: str,
plugin_maps: t.Mapping[str, t.Mapping[str, str]],
template: Template,
@@ -627,12 +651,28 @@ async def write_plugin_lists(collection_name: str,
:kwarg for_official_docsite: Default False. Set to True to use wording specific for the
official docsite on docs.ansible.com.
"""
+ flog = mlog.fields(func='write_plugin_lists')
+ flog.debug('Enter')
+
+ requires_ansible = []
+ if collection_name != 'ansible.builtin' and collection_meta.requires_ansible:
+ try:
+ requires_ansible = _parse_required_ansible(collection_meta.requires_ansible)
+ except Exception as exc: # pylint:disable=broad-except
+ flog.fields(
+ collection_name=collection_name,
+ exception=exc,
+ ).error(
+ 'Cannot parse required_ansible specifier set for {collection_name}',
+ collection_name=collection_name,
+ )
index_contents = _render_template(
template,
dest_dir,
collection_name=collection_name,
plugin_maps=plugin_maps,
collection_version=collection_meta.version,
+ requires_ansible=requires_ansible,
link_data=link_data,
breadcrumbs=breadcrumbs,
extra_docs_sections=extra_docs_data[0],
@@ -650,6 +690,8 @@ async def write_plugin_lists(collection_name: str,
await write_file(index_file, index_contents)
+ flog.debug('Leave')
+
async def output_collection_index(collection_to_plugin_info: CollectionInfoT,
collection_namespaces: t.Mapping[str, t.List[str]],
diff --git a/tests/functional/baseline-default/collections/ns/col1/index.rst b/tests/functional/baseline-default/collections/ns/col1/index.rst
index f8d0d6dd..72a3e08b 100644
--- a/tests/functional/baseline-default/collections/ns/col1/index.rst
+++ b/tests/functional/baseline-default/collections/ns/col1/index.rst
@@ -25,6 +25,7 @@ A short description.
+
.. toctree::
:maxdepth: 1
diff --git a/tests/functional/baseline-default/collections/ns/col2/index.rst b/tests/functional/baseline-default/collections/ns/col2/index.rst
index b395e8ad..2259e71b 100644
--- a/tests/functional/baseline-default/collections/ns/col2/index.rst
+++ b/tests/functional/baseline-default/collections/ns/col2/index.rst
@@ -20,6 +20,10 @@ Description
* Ansible (https://github.com/ansible)
+**Supported ansible-core versions:**
+
+* newer than 2.11.0
+
diff --git a/tests/functional/baseline-default/collections/ns2/col/index.rst b/tests/functional/baseline-default/collections/ns2/col/index.rst
index 05a43cc3..4fa9cf5c 100644
--- a/tests/functional/baseline-default/collections/ns2/col/index.rst
+++ b/tests/functional/baseline-default/collections/ns2/col/index.rst
@@ -24,6 +24,12 @@ With multiple paragraphs.
* Ansible (https://github.com/ansible)
+**Supported ansible-core versions:**
+
+* 2.11.0 or newer
+* older than 2.99.0
+* version 2.12.2 is specifically not supported
+
.. raw:: html
diff --git a/tests/functional/baseline-no-breadcrumbs/collections/ns/col1/index.rst b/tests/functional/baseline-no-breadcrumbs/collections/ns/col1/index.rst
index 8b50b03a..f1af8db9 100644
--- a/tests/functional/baseline-no-breadcrumbs/collections/ns/col1/index.rst
+++ b/tests/functional/baseline-no-breadcrumbs/collections/ns/col1/index.rst
@@ -26,6 +26,7 @@ A short description.
+
.. toctree::
:maxdepth: 1
diff --git a/tests/functional/baseline-no-breadcrumbs/collections/ns/col2/index.rst b/tests/functional/baseline-no-breadcrumbs/collections/ns/col2/index.rst
index f8f414da..c2133f88 100644
--- a/tests/functional/baseline-no-breadcrumbs/collections/ns/col2/index.rst
+++ b/tests/functional/baseline-no-breadcrumbs/collections/ns/col2/index.rst
@@ -21,6 +21,10 @@ Description
* Ansible (https://github.com/ansible)
+**Supported ansible-core versions:**
+
+* newer than 2.11.0
+
diff --git a/tests/functional/baseline-no-breadcrumbs/collections/ns2/col/index.rst b/tests/functional/baseline-no-breadcrumbs/collections/ns2/col/index.rst
index ee52fc24..58f0a13f 100644
--- a/tests/functional/baseline-no-breadcrumbs/collections/ns2/col/index.rst
+++ b/tests/functional/baseline-no-breadcrumbs/collections/ns2/col/index.rst
@@ -25,6 +25,12 @@ With multiple paragraphs.
* Ansible (https://github.com/ansible)
+**Supported ansible-core versions:**
+
+* 2.11.0 or newer
+* older than 2.99.0
+* version 2.12.2 is specifically not supported
+
.. raw:: html
diff --git a/tests/functional/baseline-no-indexes/collections/ns/col1/index.rst b/tests/functional/baseline-no-indexes/collections/ns/col1/index.rst
index f8d0d6dd..72a3e08b 100644
--- a/tests/functional/baseline-no-indexes/collections/ns/col1/index.rst
+++ b/tests/functional/baseline-no-indexes/collections/ns/col1/index.rst
@@ -25,6 +25,7 @@ A short description.
+
.. toctree::
:maxdepth: 1
diff --git a/tests/functional/baseline-no-indexes/collections/ns/col2/index.rst b/tests/functional/baseline-no-indexes/collections/ns/col2/index.rst
index b395e8ad..2259e71b 100644
--- a/tests/functional/baseline-no-indexes/collections/ns/col2/index.rst
+++ b/tests/functional/baseline-no-indexes/collections/ns/col2/index.rst
@@ -20,6 +20,10 @@ Description
* Ansible (https://github.com/ansible)
+**Supported ansible-core versions:**
+
+* newer than 2.11.0
+
diff --git a/tests/functional/baseline-no-indexes/collections/ns2/col/index.rst b/tests/functional/baseline-no-indexes/collections/ns2/col/index.rst
index 05a43cc3..4fa9cf5c 100644
--- a/tests/functional/baseline-no-indexes/collections/ns2/col/index.rst
+++ b/tests/functional/baseline-no-indexes/collections/ns2/col/index.rst
@@ -24,6 +24,12 @@ With multiple paragraphs.
* Ansible (https://github.com/ansible)
+**Supported ansible-core versions:**
+
+* 2.11.0 or newer
+* older than 2.99.0
+* version 2.12.2 is specifically not supported
+
.. raw:: html
diff --git a/tests/functional/baseline-squash-hierarchy/index.rst b/tests/functional/baseline-squash-hierarchy/index.rst
index 05a43cc3..4fa9cf5c 100644
--- a/tests/functional/baseline-squash-hierarchy/index.rst
+++ b/tests/functional/baseline-squash-hierarchy/index.rst
@@ -24,6 +24,12 @@ With multiple paragraphs.
* Ansible (https://github.com/ansible)
+**Supported ansible-core versions:**
+
+* 2.11.0 or newer
+* older than 2.99.0
+* version 2.12.2 is specifically not supported
+
.. raw:: html
diff --git a/tests/functional/baseline-use-html-blobs/collections/ns2/col/index.rst b/tests/functional/baseline-use-html-blobs/collections/ns2/col/index.rst
index 05a43cc3..4fa9cf5c 100644
--- a/tests/functional/baseline-use-html-blobs/collections/ns2/col/index.rst
+++ b/tests/functional/baseline-use-html-blobs/collections/ns2/col/index.rst
@@ -24,6 +24,12 @@ With multiple paragraphs.
* Ansible (https://github.com/ansible)
+**Supported ansible-core versions:**
+
+* 2.11.0 or newer
+* older than 2.99.0
+* version 2.12.2 is specifically not supported
+
.. raw:: html