Documentation Aggregation Technical Reference
Source code documentation for the documentation aggregation system.
Source Code Structure
src/
├── aggregate.py # CLI entry point
├── migration_tracker.py # Standalone utility
└── aggregation/ # Core package
├── __init__.py
├── config.py # Config I/O
├── constants.py # Shared constants (Mermaid theme, GitHub URL templates)
├── fetcher.py # Git + local fetch
├── flavor_matrix.py # Flavor matrix docs from flavors.yaml
├── github_api.py # GitHub HTTP client (releases fetch, auth)
├── glrd.py # GLRD subprocess wrapper (active versions, metadata)
├── models.py # Data classes
├── release_notes.py # Per-release note pages from GH data
├── releases.py # Release tables from GLRD (filtered by GH tags)
├── sphinx_builder.py # Sphinx-to-Markdown builder for sphinx-structured repos
├── structure.py # Directory transforms
└── transformer.py # Content transformsModule Reference
aggregation/models.py
Data classes for type safety:
RepoConfig— Repository configuration data classAggregateResult— Fetch result with commit hash
aggregation/config.py
Configuration file handling:
load_config()— Parse repos-config.jsonsave_config()— Write updated config (commit locks)
aggregation/constants.py
Shared constants for release-doc generation. Contains no functions; exposes only module-level constants:
GANTT_THEME— Mermaid Gantt chart theme variables using the Garden Linux color palette.GITHUB_BASE_URL,RELEASES_TAG_URL,COMMITS_URL— GitHub URL templates for thegardenlinux/gardenlinuxrepository.LIFECYCLE_LINKS— Anchor-link map for release lifecycle documentation sections.
aggregation/fetcher.py
Repository fetching:
DocsFetcher — Main fetcher class
Methods:
__init__(project_root, update_locks=False)— Initialize with optional commit lock updatingfetch()— Fetch repository and return result with commit hash_fetch_remote()— Git sparse checkout from remote repository_fetch_local()— Filesystem copy from local repository_copy_docs()— Static method to copy docs directory_copy_root_files()— Static method to copy root-level files (e.g., CONTRIBUTING.md)
aggregation/transformer.py
Content transformation:
rewrite_links()— Fix markdown links for cross-repository referencesquote_yaml_value()— YAML safety for front-matter valuesensure_frontmatter()— Add or fix front-matter in markdown filesparse_frontmatter()— Extract metadata from markdown front-matterfix_broken_project_links()— Validate and fix links to project mirrors
aggregation/github_api.py
GitHub HTTP client for release data:
GitHubAPIError— Exception raised on any GitHub API failure (network, non-2xx, rate-limit, or empty first page).get_json(url)— Fetch a single GitHub API URL and return the parsed JSON response. UsesGITHUB_TOKENwhen set. Hard-fails on non-2xx status.list_repo_releases(owner, repo, per_page=100)— Paginate through all releases for a repository and return the full list. Paginates until GitHub returns an empty page (uncapped). Hard-fails on any error or an empty first page.
This module is the single source of truth for GitHub HTTP calls in the aggregation package. Future callers should use it rather than adding new ad-hoc HTTP requests.
aggregation/glrd.py
GLRD subprocess wrapper:
run_glrd_json(args)— Runglrdwith JSON output and return the parsed data. ReturnsNoneon any failure (binary not found, non-zero exit, JSON decode error).get_active_minor_versions()— Return the set of active minor-release version strings from GLRD (e.g.{"1877.14", "2150.1.0"}).
aggregation/sphinx_builder.py
Sphinx-to-Markdown builder for repos configured with "structure": "sphinx" in repos-config.json:
build_sphinx_markdown(repo_dir, docs_path, output_dir, target_map=None)— Runpython -m sphinx -M markdownon a fetched repository and copy the resulting Markdown intooutput_dirso the standard Transform/Structure stages can consume it. Injects VitePress frontmatter, carries over hand-written Markdown files that have agithub_target_pathfrontmatter field, and strips Sphinx HTML anchors that break VitePress compatibility. ReturnsTrueon success,Falseon any failure. Requiressphinx,sphinx-markdown-builder, and any project-specific Sphinx extensions installed in the same Python environment as the aggregator.
aggregation/releases.py
Release-table generation from GLRD data:
generate_release_docs(docs_dir, existing_gh_tags)— Read GLRD release data and write per-release documentation pages. Only writes pages for releases whose normalized version string appears inexisting_gh_tags.generate_release_table(releases_data, active_versions, existing_gh_tags)— Build the release-status table. GLRD-listed rows that carry aminorversion component are only emitted when their normalized version string appears inexisting_gh_tags. Major-only rows are always emitted. Skipped rows are logged tostderr.
aggregation/release_notes.py
Per-release note page generation:
generate_release_notes_docs(docs_dir, releases)— Write one Markdown page per release from the pre-fetchedreleaseslist. Accepts the release list returned bygithub_api.list_repo_releases()and makes no network calls itself.
aggregation/flavor_matrix.py
Flavor matrix documentation generator:
get_flavor_list(gardenlinux_repo_dir)— Parseflavors.yamlin the fetched Garden Linux repository and return a per-architecture dict of flavor combinations. ReturnsNoneon failure.generate_flavor_matrix_docs(docs_dir, gardenlinux_repo_dir)— Generate the flavor matrix Markdown page by combiningget_flavor_list()output with feature metadata from the Garden LinuxFeaturesParser. Appends the generated table to the existing aggregatedreference/flavor-matrix.mdfile. ReturnsTrueon success,Falseon any failure.
aggregation/structure.py
Directory operations:
copy_targeted_docs(source_dir, docs_dir, repo_name, media_dirs=None, root_files=None)— Copy files withgithub_target_pathfront-matter to specified locations- Handles nested media dirs (e.g.,
tutorials/assets/) by copying to same relative path - Handles root-level media dirs (e.g.,
_static/) by copying to common ancestor of targeted files - Supports scanning root_files for targeted placement
- Handles nested media dirs (e.g.,
verify_internal_links(source_dir, docs_dir, repo_name)— Verify that all internal relative links in shipped Markdown files resolve to files that were also shipped. Returns the number of broken links found (0 = success). Hard-fails aggregation when any shipped file links to a source-repo file that was not itself shipped.process_markdown_file()— Transform single markdown file (links, front-matter)process_all_markdown()— Batch process all markdown files in directory
aggregate.py
CLI orchestration — Combines all modules into the complete aggregation workflow.
Usage Example
Basic programmatic usage:
from aggregation import load_config, DocsFetcher, process_all_markdown
# Load configuration
repos = load_config("repos-config.json")
# Initialize fetcher
fetcher = DocsFetcher(project_root)
# Fetch documentation
result = fetcher.fetch(repo, output_dir)
# Transform markdown files
process_all_markdown(target_dir, repo_name)Key Concepts
Targeted Documentation
Files with github_target_path in their front-matter are automatically placed at that exact path:
---
github_target_path: "docs/tutorials/example.md"
---The copy_targeted_docs() function scans all markdown files and copies those with this front-matter to their specified locations.
Link Rewriting
The rewrite_links() function transforms markdown links to work in the aggregated site:
- Relative links within the same repo are maintained
- Cross-repository links are rewritten to point to the correct locations
- Links to project mirrors are validated
Media Handling
Media directories specified in media_directories configuration are:
- Discovered recursively in the source repository
- Copied alongside their associated documentation
- Placed according to whether they're nested (same relative path) or root-level (common ancestor)
Commit Locking
When update_locks=True is passed to DocsFetcher.__init__(), the system:
- Fetches from the
ref(branch/tag) - Records the resolved commit hash
- Updates
repos-config.jsonwith the lock
This ensures reproducible builds.
Development
Running Tests
See Testing Reference for details on the test suite.
Adding New Transformation
To add a new transformation:
- Add function to
transformer.py - Call it from
process_markdown_file()orprocess_all_markdown() - Add tests in
tests/unit/test_transformer.py
Adding New Structure Type
To add a new structure mapping type:
- Add the corresponding logic to
structure.py - Add corresponding structure key handling
- Update configuration documentation
Architecture Decisions
Key architectural decisions are documented in the source repository:
- Sparse git checkout for efficiency
- Front-matter-based targeting for flexibility
- Separate fetch/transform/structure stages for modularity