165 lines
5.3 KiB
Python
Executable File
165 lines
5.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# Copyright (C) 2021-2022 Intel Corporation
|
|
# Copyright (C) CVAT.ai Corporation
|
|
#
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
from urllib.parse import urljoin
|
|
|
|
import git
|
|
import toml
|
|
from packaging import version
|
|
|
|
# Number of most recent tags to build documentation for
|
|
MAX_VERSIONS_TO_BUILD = 6
|
|
|
|
# Base URL for the documentation site
|
|
BASE_URL = os.getenv("BASE_URL", "/")
|
|
|
|
# Hugo binary for documentation builds
|
|
hugo110 = "hugo-0.110" # used for all documentation builds
|
|
|
|
|
|
def prepare_tags(repo: git.Repo):
|
|
# Group tags by minor version (major.minor) and keep only the latest patch for each
|
|
minor_versions = {}
|
|
for tag in repo.tags:
|
|
tag_version = version.parse(tag.name)
|
|
if not tag_version.is_prerelease:
|
|
minor_key = (tag_version.major, tag_version.minor)
|
|
if minor_key not in minor_versions or tag_version > version.parse(
|
|
minor_versions[minor_key].name
|
|
):
|
|
minor_versions[minor_key] = tag
|
|
|
|
# Sort minor versions by version in descending order (newest first)
|
|
sorted_tags = sorted(minor_versions.values(), key=lambda t: version.parse(t.name), reverse=True)
|
|
|
|
# Return only the configured number of most recent minor versions
|
|
return sorted_tags[:MAX_VERSIONS_TO_BUILD]
|
|
|
|
|
|
def generate_versioning_config(filename, versions, url_prefix=""):
|
|
def write_version_item(file_object, version, url):
|
|
file_object.write("[[params.versions]]\n")
|
|
file_object.write('version = "{}"\n'.format(version))
|
|
file_object.write('url = "{}"\n\n'.format(url))
|
|
|
|
with open(filename, "w") as f:
|
|
write_version_item(f, "Latest version", "{}/".format(url_prefix))
|
|
for v in versions:
|
|
write_version_item(f, v, "{}/{}".format(url_prefix, v))
|
|
|
|
|
|
def git_checkout(ref: str, temp_repo: git.Repo, temp_dir: Path):
|
|
# We need to checkout with submodules, recursively
|
|
|
|
subdirs = [
|
|
"site/content",
|
|
"site/assets",
|
|
"site/layouts/partials",
|
|
"site/layouts/shortcodes",
|
|
"site/themes",
|
|
]
|
|
|
|
temp_repo.git.checkout(ref, recurse_submodules=True, force=True)
|
|
temp_repo.git.submodule("update", "--init", "--recursive")
|
|
tmp_repo_root = Path(temp_repo.working_tree_dir)
|
|
|
|
for subdir in subdirs:
|
|
dst_dir = temp_dir / subdir
|
|
shutil.rmtree(dst_dir)
|
|
shutil.copytree(tmp_repo_root / subdir, dst_dir, symlinks=True)
|
|
|
|
|
|
def change_version_menu_toml(filename, version):
|
|
data = toml.load(filename)
|
|
data["params"]["version_menu"] = version
|
|
|
|
with open(filename, "w") as f:
|
|
toml.dump(data, f)
|
|
|
|
|
|
def generate_docs(repo: git.Repo, output_dir: os.PathLike, tags):
|
|
repo_root = Path(repo.working_tree_dir)
|
|
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
content_loc = Path(temp_dir, "site")
|
|
shutil.copytree(repo_root / "site", content_loc, symlinks=True)
|
|
|
|
def run_npm_install():
|
|
subprocess.run(["npm", "install"], cwd=content_loc) # nosec
|
|
|
|
def run_hugo(
|
|
*,
|
|
executable: Optional[str] = "hugo",
|
|
rel_dest_dir: str = ".",
|
|
):
|
|
# Construct the full destination path
|
|
full_destination = Path(output_dir) / rel_dest_dir
|
|
|
|
subprocess.run( # nosec
|
|
[
|
|
executable,
|
|
"--destination",
|
|
str(full_destination),
|
|
"--baseURL",
|
|
urljoin(BASE_URL, rel_dest_dir),
|
|
"--config",
|
|
"config.toml,versioning.toml",
|
|
],
|
|
cwd=content_loc,
|
|
check=True,
|
|
)
|
|
|
|
versioning_toml_path = content_loc / "versioning.toml"
|
|
|
|
# Process the develop version
|
|
generate_versioning_config(versioning_toml_path, (t.name for t in tags))
|
|
change_version_menu_toml(versioning_toml_path, "develop")
|
|
run_hugo(executable=hugo110)
|
|
|
|
# Create a temp repo for checkouts
|
|
temp_repo_path = Path(temp_dir) / "tmp_repo"
|
|
shutil.copytree(repo_root, temp_repo_path, symlinks=True)
|
|
temp_repo = git.Repo(temp_repo_path)
|
|
temp_repo.git.reset(hard=True, recurse_submodules=True)
|
|
|
|
# Process older versions
|
|
generate_versioning_config(versioning_toml_path, (t.name for t in tags), "/..")
|
|
for tag in tags:
|
|
git_checkout(tag.name, temp_repo, Path(temp_dir))
|
|
change_version_menu_toml(versioning_toml_path, tag.name)
|
|
run_npm_install()
|
|
|
|
# Use hugo110 for all recent versions (since we only build the last MAX_VERSIONS_TO_BUILD tags)
|
|
run_hugo(
|
|
executable=hugo110,
|
|
rel_dest_dir=tag.name,
|
|
)
|
|
|
|
|
|
def validate_env():
|
|
try:
|
|
subprocess.run([hugo110, "version"], capture_output=True) # nosec
|
|
except (subprocess.CalledProcessError, FileNotFoundError) as ex:
|
|
raise Exception(f"Failed to run '{hugo110}', please make sure it exists.") from ex
|
|
|
|
|
|
if __name__ == "__main__":
|
|
repo_root = Path(__file__).resolve().parents[1]
|
|
output_dir = repo_root / "public"
|
|
|
|
validate_env()
|
|
|
|
with git.Repo(repo_root) as repo:
|
|
tags = prepare_tags(repo)
|
|
generate_docs(repo, output_dir, tags)
|