From 9a98a7ad6d47d9faf52914fb9c0c875466c8eb35 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Thu, 28 Nov 2024 14:50:42 +0100 Subject: [PATCH] Build: don't run default steps if no `sphinx` or `mkdocs` This PR modifies the build to not run default commands when the user doesn't specify `sphinx` or `mkdocs` configs in the YAML file. This allows to use the following YAML file to build with Docusaurus, for example: ```yaml version: 2 build: os: ubuntu-24.04 tools: nodejs: "22" jobs: install: - cd docs/ && npm install build: html: - cd docs/ && npm run build post_build: - mkdir --parents $READTHEDOCS_OUTPUT/html/ - cp --recursive docs/build/* $READTHEDOCS_OUTPUT/html/ ``` This is the structure I've been wanting to have to allow any type of doctool to work in our platform following the `build.jobs` pattern. The code deployed in production doesn't allow this because it runs automatically `create_environment`, `install_core_dependencies` and `install_requirements` even if the project is not using Python --which is incorrect. It fails with the generic error: " Unknown problem. There was a problem with Read the Docs while building your documentation" - https://app.readthedocs.org/projects/test-builds/builds/26425680/ - https://read-the-docs.sentry.io/issues/4458662274/ This PR detects if the user is defining `sphinx` or `mkdocs` and if it's not, it doesn't run those jobs and leave the user to handle the build workflow completely. * Related https://github.com/readthedocs/readthedocs.org/issues/11216 * Related https://github.com/readthedocs/readthedocs.org/issues/11551 --- readthedocs/config/config.py | 9 ++++++++- readthedocs/doc_builder/director.py | 25 ++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/readthedocs/config/config.py b/readthedocs/config/config.py index 53690534716..3ce3062bf50 100644 --- a/readthedocs/config/config.py +++ b/readthedocs/config/config.py @@ -828,7 +828,14 @@ def doctype(self): if self.mkdocs: return "mkdocs" - return self.sphinx.builder + + # NOTE: we need to use "source config" here because `_config` is + # auto-populated with Sphinx if no `sphinx` and no `mkdocs` keys are + # declared. + if self.source_config.get("sphinx"): + return self.sphinx.builder + + return GENERIC @property def submodules(self): diff --git a/readthedocs/doc_builder/director.py b/readthedocs/doc_builder/director.py index 02a9b806757..859e97021dc 100644 --- a/readthedocs/doc_builder/director.py +++ b/readthedocs/doc_builder/director.py @@ -107,6 +107,8 @@ def setup_vcs(self): # self.run_build_job("pre_checkout") self.checkout() + self.run_default_commands = self.is_type_mkdocs() or self.is_type_sphinx() + self.run_build_job("post_checkout") commit = self.data.build_commit or self.vcs_repository.commit @@ -309,7 +311,9 @@ def create_environment(self): if self.data.config.build.jobs.create_environment is not None: self.run_build_job("create_environment") return - self.language_environment.setup_base() + + if self.run_default_commands or self.data.config.source_config.get("python"): + self.language_environment.setup_base() # Install def install(self): @@ -317,15 +321,18 @@ def install(self): self.run_build_job("install") return - self.language_environment.install_core_requirements() - self.language_environment.install_requirements() + if self.run_default_commands or self.data.config.source_config.get("python"): + self.language_environment.install_core_requirements() + self.language_environment.install_requirements() # Build def build_html(self): if self.data.config.build.jobs.build.html is not None: self.run_build_job("build.html") return - return self.build_docs_class(self.data.config.doctype) + + if self.run_default_commands: + return self.build_docs_class(self.data.config.doctype) def build_pdf(self): if "pdf" not in self.data.config.formats or self.data.version.type == EXTERNAL: @@ -336,7 +343,7 @@ def build_pdf(self): return # Mkdocs has no pdf generation currently. - if self.is_type_sphinx(): + if self.is_type_sphinx() and self.run_default_commands: return self.build_docs_class("sphinx_pdf") return False @@ -353,7 +360,7 @@ def build_htmlzip(self): return # We don't generate a zip for mkdocs currently. - if self.is_type_sphinx(): + if self.is_type_sphinx() and self.run_default_commands: return self.build_docs_class("sphinx_singlehtmllocalmedia") return False @@ -366,7 +373,7 @@ def build_epub(self): return # Mkdocs has no epub generation currently. - if self.is_type_sphinx(): + if self.is_type_sphinx() and self.run_default_commands: return self.build_docs_class("sphinx_epub") return False @@ -744,6 +751,10 @@ def is_type_sphinx(self): """Is documentation type Sphinx.""" return "sphinx" in self.data.config.doctype + def is_type_mkdocs(self): + """Is documentation type MkDocs.""" + return "mkdocs" in self.data.config.doctype + def store_readthedocs_build_yaml(self): # load YAML from user yaml_path = os.path.join(