Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🤖 Set build config via Sphinx ext #2360

Open
wants to merge 1 commit into
base: devel
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions docs/docsite/_ext/build_context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
"""Sphinx extension for setting up the build settings."""

import subprocess
from dataclasses import dataclass
from functools import cache
from pathlib import Path
from tomllib import loads as parse_toml_string
from typing import Literal

from sphinx.application import Sphinx
from sphinx.util import logging


logger = logging.getLogger(__name__)


DOCSITE_ROOT_DIR = Path(__file__).parents[1].resolve()
DOCSITE_EOL_CONFIG_PATH = DOCSITE_ROOT_DIR / 'end_of_life.toml'


@dataclass(frozen=True)
class Distribution:
end_of_life: list[str]
supported: list[str]

@classmethod
def from_dict(cls, raw_dist: dict[str, list[str]]) -> 'Distribution':
return cls(
**{
kind.replace('-', '_'): versions
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dataclass has to have snake_case attrs so this is doing that conversion. It effectively maps end-of-life in the TOML config to end_of_life.

for kind, versions in raw_dist.items()
},
)


EOLConfigType = dict[str, Distribution]


@cache
def _read_eol_data() -> EOLConfigType:
raw_config_dict = parse_toml_string(DOCSITE_EOL_CONFIG_PATH.read_text())

return {
dist_name: Distribution.from_dict(dist_data)
for dist_name, dist_data in raw_config_dict['distribution'].items()
}


@cache
def _is_eol_build(git_branch: str, kind: str) -> bool:
return git_branch in _read_eol_data()[kind].end_of_life


@cache
def _get_current_git_branch():
git_branch_cmd = 'git', 'rev-parse', '--abbrev-ref', 'HEAD'

try:
return subprocess.check_output(git_branch_cmd, text=True).strip()
except subprocess.CalledProcessError as proc_err:
raise LookupError(
f'Failed to locate current Git branch: {proc_err !s}',
) from proc_err


def _set_global_j2_context(app, config):
if 'is_eol' in config.html_context:
raise ValueError(
'`is_eol` found in `html_context` unexpectedly. '
'It should not be set in `conf.py`.',
) from None

dist_name = (
'ansible-core' if app.tags.has('core')
else 'ansible' if app.tags.has('ansible')
else None
)

if dist_name is None:
return

try:
git_branch = _get_current_git_branch()
except LookupError as lookup_err:
logger.info(str(lookup_err))
return

config.html_context['is_eol'] = _is_eol_build(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oraNod this is what sets that value into the variable defined in conf.py. It basically replaces the old hardcoded value.

git_branch=git_branch, kind=dist_name,
)


def setup(app: Sphinx) -> dict[str, bool | str]:
"""Initialize the extension.

:param app: A Sphinx application object.
:returns: Extension metadata as a dict.
"""

# NOTE: `config-inited` is used because it runs once as opposed to
# NOTE: `html-page-context` that runs per each page. The data we
# NOTE: compute is immutable throughout the build so there's no need
# NOTE: to have a callback that would be executed hundreds of times.
app.connect('config-inited', _set_global_j2_context)

return {
'parallel_read_safe': True,
'parallel_write_safe': True,
'version': app.config.release,
}
25 changes: 25 additions & 0 deletions docs/docsite/end_of_life.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[distribution.ansible]
end-of-life = [
'stable-2.15',
'stable-2.14',
'stable-2.13',
]
supported = [
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oraNod did you plan to use this list somehow? I just copied it, but it's not actually used anywhere.

'devel',
'stable-2.18',
'stable-2.17',
'stable-2.16',
]

[distribution.ansible-core]
end-of-life = [
'stable-2.15',
'stable-2.14',
'stable-2.13',
]
supported = [
'devel',
'stable-2.18',
'stable-2.17',
'stable-2.16',
]
Comment on lines +14 to +25
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oraNod things here are the same as in the other mapping. Did you expect them to differ at some point? What's the semantic meaning you were going for?

15 changes: 14 additions & 1 deletion docs/docsite/rst/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@

import sys
import os
from pathlib import Path


DOCS_ROOT_DIR = Path(__file__).parent.resolve()


# Make in-tree extension importable in non-tox setups/envs, like RTD.
# Refs:
# https://github.com/readthedocs/readthedocs.org/issues/6311
# https://github.com/readthedocs/readthedocs.org/issues/7182
sys.path.insert(0, str(DOCS_ROOT_DIR.parent / '_ext'))

# If your extensions are in another directory, add it here. If the directory
# is relative to the documentation root, use os.path.abspath to make it
Expand Down Expand Up @@ -65,6 +76,9 @@
'notfound.extension',
'sphinx_antsibull_ext', # provides CSS for the plugin/module docs generated by antsibull
'sphinx_copybutton',

# In-tree extensions:
'build_context', # computes build settings for env context
]

# Later on, add 'sphinx.ext.viewcode' to the list if you want to have
Expand Down Expand Up @@ -227,7 +241,6 @@
html_context = {
'display_github': 'True',
'show_sphinx': False,
'is_eol': False,
'github_user': 'ansible',
'github_repo': 'ansible-documentation',
'github_version': 'devel',
Expand Down
Loading