From 2716e96e2590f38f63345aed5642519dc64a9ca3 Mon Sep 17 00:00:00 2001 From: Federico Capoano Date: Fri, 30 Jan 2026 20:49:23 -0300 Subject: [PATCH] [feature] Added SKIP_FETCH argument --- Makefile | 7 +++++-- README.rst | 35 ++++++++++++++++++++++++++--------- build.py | 31 ++++++++++++++++++++----------- 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index bfb69ec1..5221056c 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,9 @@ help: @echo " build to build the documentation in all formats (PDF, HTML and ePUB)" @echo " build_html to build the documentation in HTML format only" @echo " release_notes to generate the release notes for a specific version (default: 25.10). Use 'make changelog VERSION=XX' to specify." + @echo "" + @echo "Build arguments:" + @echo " SKIP_FETCH=1 skip GitHub fetch/clone operations (for quick iteration)" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @@ -71,10 +74,10 @@ build: mv _build/versions_map.json versions_map.json &> /dev/null || true @echo "Building version map" - ./build.py --formats version_map $(if $(VERSION),--version $(VERSION)) $(if $(MODULES),--modules $(MODULES)) + ./build.py --formats version_map $(if $(VERSION),--version $(VERSION)) $(if $(MODULES),--modules $(MODULES)) $(if $(SKIP_FETCH),--skip-fetch) @echo "Building documentation" - ./build.py $(if $(FORMATS),--formats $(FORMATS)) $(if $(VERSION),--version $(VERSION)) $(if $(MODULES),--modules $(MODULES)) + ./build.py $(if $(FORMATS),--formats $(FORMATS)) $(if $(VERSION),--version $(VERSION)) $(if $(MODULES),--modules $(MODULES)) $(if $(SKIP_FETCH),--skip-fetch) # Store the version map in the _build/ directory mv versions_map.json _build/ diff --git a/README.rst b/README.rst index a1263d65..d051c125 100644 --- a/README.rst +++ b/README.rst @@ -31,25 +31,18 @@ Requirements: Python >= 3.9. # This command will generate the documentation in all formats - HTML, PDF and ePUB make build - # The ``formats`` argument is a comma separated list of formats to build, # e.g. ``formats=html,pdf,epub``. The default is to build all available # formats, which currently are ``html``, ``pdf`` and ``epub``. make build formats=pdf,html - # This command is a shortcut for generating only HTML documentation during # development, since building PDF and ePUB takes time. It also supports # the VERSION argument. make build_html - # Build only the dev version in HTML format make build VERSION=dev FORMATS=html - -.. - note: - - Please refer the "`build options" <#build-options>`_section of this - configuration for a complete reference of the available options. + # Quickly rebuild, useful during iteration + make build VERSION=dev FORMATS=html SKIP_FETCH=1 5. Open the generated HTML files in your browser. @@ -170,6 +163,30 @@ instead of HTTPS. For example: SSH=1 make build +Skipping repository fetch for quick iteration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When actively editing documentation, you may want to skip the +fetch/clone/update operations to speed up the build process. This is +especially useful when you have already cloned the repositories and want +to quickly rebuild the documentation after making local changes. + +To skip all repository operations, use the ``SKIP_FETCH`` argument: + +.. code-block:: shell + + make build SKIP_FETCH=1 + +Or for HTML-only builds: + +.. code-block:: shell + + make build_html SKIP_FETCH=1 + +**Note**: Using ``SKIP_FETCH`` requires that the repositories have already been + cloned in a previous build. If the repositories don't exist, the build + will fail. + Spell check ~~~~~~~~~~~ diff --git a/build.py b/build.py index d4458edc..095149c9 100755 --- a/build.py +++ b/build.py @@ -267,11 +267,14 @@ def git_is_on_branch(repo_path): def clone_or_update_repo( - name, branch, dir_name, owner="openwisp", dest=None, version_name=None + name, branch, dir_name, skip_fetch=False, owner="openwisp", dest=None, version_name=None ): """ Clone or update a repository based on the module name and branch provided. If the repository already exists, update it. Otherwise, clone the repository. + The resulting directory is then symlinked internally. + If skip_fetch=True is passed, git fetching/cloning + is skipped and only symlink is performed. """ repository = f"{owner}/{name}" # Support for building with local changes @@ -327,9 +330,9 @@ def clone_or_update_repo( repo_url = f"git@github.com:{repository}.git" else: repo_url = f"https://github.com/{repository}.git" + # update if dir exists, otherwise clone clone_path = os.path.abspath(os.path.join("modules", dir_name)) - - if os.path.exists(clone_path): + if os.path.exists(clone_path) and not skip_fetch: print(f"Repository '{name}' already exists. Updating...") subprocess.run( # Update remote-tracking ref (avoid fetching into checked-out branch) @@ -366,7 +369,7 @@ def clone_or_update_repo( subprocess.run( ["git", "pull", "origin", branch], cwd=clone_path, check=True ) - else: + elif not skip_fetch: print(f"Cloning repository '{name}'...") subprocess.run( [ @@ -382,6 +385,10 @@ def clone_or_update_repo( ], check=True, ) + elif skip_fetch and not os.path.exists(clone_path): + raise FileNotFoundError( + f"Repository \"{name}\" not found at {clone_path}; run without SKIP_FETCH=1 first." + ) # Create a symlink to either the 'docs' directory inside the cloned repository # or to the entire repository if no 'docs' directory exists. # This makes the documentation sources available to the Sphinx build process. @@ -414,11 +421,15 @@ def main(): help="comma separated modules to build" "in the format of :::", ) + parser.add_argument( + "--skip-fetch", + action="store_true", + default=False, + help="skip fetching/cloning repositories (useful for quick iteration while editing docs)", + ) args = parser.parse_args() - with open("config.yml") as f: config = yaml.safe_load(f) - build_versions = get_build_versions(config["versions"], args.version) stable_version = get_stable_version(build_versions) docs_root = "" @@ -428,11 +439,10 @@ def main(): docs_root = "/docs" html_base_url = "https://openwisp.io" build_dir = f"{build_dir}{docs_root}" - + # loop over versions and build each one by one for version in build_versions: version_name = version["name"] module_dirs = [] - # Modules which are configured to be included in all the builds default_modules = ( config["modules"] if not version.get("overwrite_modules") else [] @@ -446,7 +456,6 @@ def main(): version_modules=version_modules, overridden_modules=overridden_modules, ) - # If a module does not define a branch, # it will fallback to the version_branch. version_branch = version.get("module_branch", version["name"]) @@ -454,12 +463,14 @@ def main(): clone_or_update_repo( name="openwisp-docs", branch=docs_branch, + skip_fetch=args.skip_fetch, dir_name="openwisp-docs", version_name=version_name, ) for module in modules: clone_or_update_repo( branch=module.pop("branch", version_branch), + skip_fetch=args.skip_fetch, **module, ) module_dirs.append(module["dir_name"]) @@ -484,13 +495,11 @@ def main(): # Remove all temporary directories for dir in module_dirs: remove_symlink(dir) - # Generate the index.html file which redirects to the stable version. env = Environment(loader=FileSystemLoader("_static")) template = env.get_template("index.jinja2") with open(f"{build_dir}/index.html", "w") as f: f.write(template.render(stable_version=stable_version, docs_root=docs_root)) - # Create a symbolic link for the stable version subprocess.run( [