Skip to content

Commit af1f4ac

Browse files
committed
Add support for subpackages (like pulp_file)
1 parent 19e935b commit af1f4ac

File tree

6 files changed

+121
-59
lines changed

6 files changed

+121
-59
lines changed

README.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ Python Package to help aggregating Pulp's multirepo ecosystem into a unified doc
1212

1313
This packages is:
1414

15-
- A `mkdocs-macros-plugin` [pluget](https://mkdocs-macros-plugin.readthedocs.io/en/latest/pluglets/). [relevant-code]()
16-
- A repository for common doc website asset. [relevant-code](https://github.com/pedro-psb/pulp-docs/tree/main/src/pulp_docs/docs)
15+
- A `mkdocs-macros-plugin` [pluget](https://mkdocs-macros-plugin.readthedocs.io/en/latest/pluglets/).
16+
- A repository for common doc website asset.
1717
- A centralized entrypoint for installing doc-related packages/tooling. (via its own requirements)
18-
- A CLI for doc-related tasks, like serving and building. [relevant-code](https://github.com/pedro-psb/pulp-docs/blob/main/src/pulp_docs/cli.py)
18+
- A CLI for doc-related tasks, like serving and building.
1919

2020
The idea is that each repository should install `pulp-docs` and imediatelly be able run the unified website server.
2121
Also, this should be used for the production build.
@@ -24,7 +24,7 @@ Also, this should be used for the production build.
2424

2525
Through a `mkdocs-macro-plugin` hook (called in early stages of mkdocs processing), we inject the following steps:
2626

27-
1. Read `repolist.yml` packaged with `pulp-docs` to know which repos/urls to use
27+
1. Read [`repolist.yml`](https://github.com/pedro-psb/pulp-docs/blob/main/src/pulp_docs/data/repolist.yml) packaged with `pulp-docs` to know which repos/urls to use
2828
1. Download/Move all source code required to dir under `tempfile.gettempdir()`
2929
- Uses `../{repo}` if available OR
3030
- Uses existing cached `{tmpdir}/{repo}` if available OR
@@ -39,13 +39,13 @@ And thats it, the magic is done.
3939
Recommended way for daily usage:
4040

4141
```bash
42-
$ pipx install git+https://github.com/pedro-psb/pulp-docs --include-deps
43-
$ pulp-docs serve
42+
pipx install git+https://github.com/pedro-psb/pulp-docs --include-deps
43+
pulp-docs serve
4444
```
4545

4646
For development, use your prefered method!
4747

48-
## How to share inter-repo "unofficial" work
48+
## How to override `repolist.yml`
4949

5050
If you want to share work you are doing in muliple forks, you can share a custom `repolist.yml` which points to your forks.
5151

src/pulp_docs/constants.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
ADMIN_NAME = "admin"
22
USER_NAME = "user"
3+
RESTAPI_URL_TEMPLATE = "https://docs.pulpproject.org/{}/restapi.html"
34

45
DISPLAY_NAMES = {
56
"guides": "How-to Guides",

src/pulp_docs/data/repolist.yml

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
meta:
2+
version: 1
23
rest_api_template: https://docs.pulpproject.org/{}/restapi.html
34

45
repos:
@@ -24,10 +25,6 @@ repos:
2425
owner: pulp
2526
title: Ansible
2627
branch: main
27-
- name: pulp-certguard
28-
owner: pulp
29-
title: Certguard
30-
branch: main
3128
- name: pulp_container
3229
owner: pulp
3330
title: Container
@@ -44,10 +41,13 @@ repos:
4441
owner: pulp
4542
title: RPM
4643
branch: main
47-
# - name: pulp_file
48-
# nested_under: pulp/pulpcore/pulp_file
49-
# title: File
50-
# branch: main
44+
# subpackages
45+
- name: pulp_certguard
46+
title: Certguard
47+
subpackage_of: pulpcore
48+
- name: pulp_file
49+
title: File
50+
subpackage_of: pulpcore
5151
other:
5252
- name: pulp-oci-images
5353
owner: pulp

src/pulp_docs/mkdocs_macros.py

+44-36
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@
2424
import rich
2525

2626
from pulp_docs.cli import Config
27+
from pulp_docs.constants import RESTAPI_URL_TEMPLATE
2728
from pulp_docs.navigation import get_navigation
28-
from pulp_docs.repository import Repos
29+
from pulp_docs.repository import Repo, Repos, SubPackage
2930

3031
# the name of the docs in the source repositories
3132
SRC_DOCS_DIRNAME = "staging_docs"
@@ -91,47 +92,23 @@ def prepare_repositories(TMPDIR: Path, repos: Repos, config: Config):
9192

9293
for repo in repos.all:
9394
start = time.perf_counter()
94-
# if repo.name == "pulp-docs":
95-
# breakpoint()
96-
# 1. Download repo (copy locally or fetch from GH)
97-
this_src_dir = repo_sources / repo.name
98-
repo.download(dest_dir=this_src_dir, clear_cache=config.clear_cache)
99-
100-
# 2. Isolate docs dir from codebase (makes mkdocs happy)
95+
# handle subpcakges nested under repositories
10196
this_docs_dir = repo_docs / repo.name
102-
log.info(
103-
"Moving doc files:\nfrom '{}'\nto '{}'".format(this_src_dir, this_docs_dir)
104-
)
97+
if not isinstance(repo, SubPackage):
98+
this_src_dir = repo_sources / repo.name
99+
repo.download(dest_dir=this_src_dir, clear_cache=config.clear_cache)
100+
else:
101+
this_src_dir = repo_sources / repo.subpackage_of / repo.name
105102

106-
try:
107-
shutil.copytree(this_src_dir / SRC_DOCS_DIRNAME, this_docs_dir / "docs")
108-
except FileNotFoundError:
109-
Path(this_docs_dir / "docs").mkdir(parents=True)
110-
repo.status.has_staging_docs = False
111-
try:
112-
shutil.copy(this_src_dir / "CHANGELOG.md", this_docs_dir / "CHANGELOG.md")
113-
except FileNotFoundError:
114-
repo.status.has_changelog = False
115-
116-
try:
117-
shutil.copy(this_src_dir / "README.md", this_docs_dir / "README.md")
118-
except FileNotFoundError:
119-
repo.status.has_readme = False
120-
121-
# 3. Generate REST Api pages (workaround)
103+
# install and post-process
104+
_install_doc_files(this_src_dir, this_docs_dir, repo)
122105
if repo.type == "content":
123-
log.info("Generating REST_API page")
124-
rest_api_page = this_docs_dir / "docs" / "rest_api.md"
125-
rest_api_page.touch()
126-
md_title = f"# {repo.title} REST Api"
127-
md_body = f"[{repo.rest_api_link}]({repo.rest_api_link})"
128-
rest_api_page.write_text(f"{md_title}\n\n{md_body}")
106+
_generate_rest_api_page(this_docs_dir, repo.name, repo.title)
129107

130108
end = time.perf_counter()
131-
duration = end - start
132-
log.info(f"{repo.name} completed in {duration:.2} sec")
109+
log.info(f"{repo.name} completed in {end - start:.2} sec")
133110

134-
# Copy template-files (from this plugin) to tmpdir
111+
# Copy core-files (shipped with pulp-docs) to tmpdir
135112
shutil.copy(
136113
repo_sources / repos.core_repo.name / SRC_DOCS_DIRNAME / "index.md",
137114
repo_docs / "index.md",
@@ -145,6 +122,37 @@ def prepare_repositories(TMPDIR: Path, repos: Repos, config: Config):
145122
return (repo_docs, repo_sources)
146123

147124

125+
def _install_doc_files(src_dir: Path, docs_dir: Path, repo: Repo):
126+
"""Copy only doc-related files from src_dir to doc_dir"""
127+
log.info(f"Moving doc files:\nfrom '{src_dir}'\nto '{docs_dir}'")
128+
129+
try:
130+
shutil.copytree(src_dir / SRC_DOCS_DIRNAME, docs_dir / "docs")
131+
except FileNotFoundError:
132+
Path(docs_dir / "docs").mkdir(parents=True)
133+
repo.status.has_staging_docs = False
134+
try:
135+
shutil.copy(src_dir / "CHANGELOG.md", docs_dir / "CHANGELOG.md")
136+
except FileNotFoundError:
137+
repo.status.has_changelog = False
138+
139+
try:
140+
shutil.copy(src_dir / "README.md", docs_dir / "README.md")
141+
except FileNotFoundError:
142+
repo.status.has_readme = False
143+
144+
145+
def _generate_rest_api_page(docs_dir: Path, repo_name: str, repo_title: str):
146+
"""Create page that contain a link to the rest api, based on the project url template"""
147+
log.info("Generating REST_API page")
148+
rest_api_page = docs_dir / "docs" / "rest_api.md"
149+
rest_api_page.touch()
150+
restapi_url = RESTAPI_URL_TEMPLATE.format(repo_name)
151+
md_title = f"# {repo_title} REST Api"
152+
md_body = f"[{restapi_url}]({restapi_url})"
153+
rest_api_page.write_text(f"{md_title}\n\n{md_body}")
154+
155+
148156
def print_user_repo(repos: Repos, config: Config):
149157
"""Emit report about local checkout being used or warn if none."""
150158
print("*" * 79)

src/pulp_docs/repository.py

+60-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import tarfile
1313
import tempfile
1414
import typing as t
15+
from collections import ChainMap, defaultdict
1516
from dataclasses import dataclass, field
1617
from io import BytesIO
1718
from pathlib import Path
@@ -25,7 +26,6 @@
2526

2627
FIXTURE_WORKDIR = Path("tests/fixtures").absolute()
2728
DOWNLOAD_CACHE_DIR = Path(tempfile.gettempdir()) / "repo_downloads"
28-
RESTAPI_TEMPLATE = "https://docs.pulpproject.org/{}/restapi.html"
2929

3030

3131
# @dataclass # raising errors in py311/312
@@ -61,6 +61,7 @@ class Repo:
6161
branch: str = "main"
6262
branch_in_use: t.Optional[str] = None
6363
local_basepath: t.Optional[Path] = None
64+
subpackages: t.Optional[t.List] = None
6465
status: RepoStatus = field(default_factory=lambda: RepoStatus())
6566
type: t.Optional[str] = None
6667

@@ -190,6 +191,20 @@ def download_from_gh_latest(dest_dir: Path, owner: str, name: str):
190191
return latest_release_tar_url
191192

192193

194+
@dataclass
195+
class SubPackage:
196+
"""A package that lives under another Repo."""
197+
198+
name: str
199+
title: str
200+
subpackage_of: str
201+
type: t.Optional[str] = None
202+
status: RepoStatus = field(default_factory=lambda: RepoStatus())
203+
local_basepath = None
204+
branch_in_use = ""
205+
branch = ""
206+
207+
193208
@dataclass
194209
class Repos:
195210
"""A collection of Repos"""
@@ -216,7 +231,25 @@ def get(self, repo_name: str) -> t.Optional[Repo]:
216231

217232
@property
218233
def all(self):
219-
return [self.core_repo] + self.content_repos + self.other_repos
234+
"""The set of repositories and subpackages"""
235+
repos = [self.core_repo] + self.content_repos + self.other_repos
236+
subpackages = []
237+
for repo in repos:
238+
if repo.subpackages:
239+
subpackages.extend(repo.subpackages)
240+
return repos + subpackages
241+
242+
def get_repos(self, type="all"):
243+
"""Get a set of repositories and subpackages by type."""
244+
if type == "all":
245+
return self.all
246+
247+
repos_and_pkgs = []
248+
for repo in self.all:
249+
if getattr(repo, "subpackages", None):
250+
repos_and_pkgs.extend(repo.subpackages)
251+
252+
return [repo for repo in repos_and_pkgs if repo.type == type]
220253

221254
@classmethod
222255
def from_yaml(cls, path: str):
@@ -242,14 +275,34 @@ def from_yaml(cls, path: str):
242275
raise ValueError("File does not exist:", file)
243276
log.info(f"repofile={str(file.absolute())}")
244277

278+
# Create Repo objects from yaml data
279+
repos: t.Dict[str, t.List] = {}
280+
nested_packages: t.Dict[str, t.List[SubPackage]] = {}
245281
with open(file, "r") as f:
246282
data = yaml.load(f, Loader=yaml.SafeLoader)
247-
repos = data["repos"]
248-
core_repo = Repo(**repos["core"][0], type="core")
249-
content_repos = [Repo(**repo, type="content") for repo in repos["content"]]
250-
other_repos = [Repo(**repo, type="other") for repo in repos["other"]]
283+
for repo_type in ("core", "content", "other"):
284+
repos[repo_type] = []
285+
for repo in data["repos"][repo_type]:
286+
# Collect nested packages
287+
if parent_package := repo.get("subpackage_of", None):
288+
nested_packages.setdefault(parent_package, []).append(
289+
SubPackage(**repo, type=repo_type)
290+
)
291+
continue
292+
# Create regular packages
293+
repos[repo_type].append(Repo(**repo, type=repo_type))
294+
295+
# Update Repo objects that contain subpackages
296+
for parent_repo_name, subpackages_list in nested_packages.items():
297+
flat_repos = repos["core"] + repos["content"] + repos["other"]
298+
for repo in flat_repos:
299+
if repo.name == parent_repo_name:
300+
repo.subpackages = subpackages_list
301+
251302
return Repos(
252-
core_repo=core_repo, content_repos=content_repos, other_repos=other_repos
303+
core_repo=repos["core"][0],
304+
content_repos=repos["content"],
305+
other_repos=repos["other"],
253306
)
254307

255308
@classmethod

src/pulp_docs/utils/aggregation.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def repo_grouping(
9494
selected_repos = self.repos.all
9595
else:
9696
for repo_name in repo_types:
97-
selected_repos.extend(getattr(self.repos, f"{repo_name}_repos"))
97+
selected_repos.extend(self.repos.get_repos(type=type))
9898

9999
# Dont expand content-types
100100
if not _expand_content_types:

0 commit comments

Comments
 (0)