diff --git a/readthedocs/doc_builder/director.py b/readthedocs/doc_builder/director.py index 77a5ade28ee..dc7646db99d 100644 --- a/readthedocs/doc_builder/director.py +++ b/readthedocs/doc_builder/director.py @@ -97,6 +97,15 @@ def setup_vcs(self): if commit: self.data.build["commit"] = commit + def create_build_environment(self): + self.build_environment = self.data.environment_class( + project=self.data.project, + version=self.data.version, + config=self.data.config, + build=self.data.build, + environment=self.get_build_env_vars(), + ) + def setup_environment(self): """ Create the environment and install required dependencies. @@ -105,59 +114,50 @@ def setup_environment(self): 2. create language (e.g. Python) environment 3. install dependencies into the environment """ - self.build_environment = self.data.environment_class( - project=self.data.project, + # Environment used for building code, usually with Docker + language_environment_cls = Virtualenv + if any( + [ + self.data.config.conda is not None, + self.data.config.python_interpreter in ("conda", "mamba"), + ] + ): + language_environment_cls = Conda + + self.language_environment = language_environment_cls( version=self.data.version, + build_env=self.build_environment, config=self.data.config, - build=self.data.build, - environment=self.get_build_env_vars(), ) - # Environment used for building code, usually with Docker - with self.build_environment: - language_environment_cls = Virtualenv - if any( - [ - self.data.config.conda is not None, - self.data.config.python_interpreter in ("conda", "mamba"), - ] - ): - language_environment_cls = Conda - - self.language_environment = language_environment_cls( - version=self.data.version, - build_env=self.build_environment, - config=self.data.config, - ) - - # TODO: check if `before_build` and `after_build` are still useful - # (maybe in commercial?) - # - # I didn't find they are used anywhere, we should probably remove them - before_build.send( - sender=self.data.version, - environment=self.build_environment, - ) + # TODO: check if `before_build` and `after_build` are still useful + # (maybe in commercial?) + # + # I didn't find they are used anywhere, we should probably remove them + before_build.send( + sender=self.data.version, + environment=self.build_environment, + ) - self.pre_system_dependencies() - self.system_dependencies() - self.post_system_dependencies() + self.pre_system_dependencies() + self.system_dependencies() + self.post_system_dependencies() - # Install all ``build.tools`` specified by the user - if self.data.config.using_build_tools: - self.language_environment.install_build_tools() + # Install all ``build.tools`` specified by the user + if self.data.config.using_build_tools: + self.language_environment.install_build_tools() - self.pre_create_environment() - self.create_environment() - self.post_create_environment() + self.pre_create_environment() + self.create_environment() + self.post_create_environment() - self.pre_install() - self.install() - self.post_install() + self.pre_install() + self.install() + self.post_install() - # TODO: remove this and document how to do it on `build.jobs.post_install` - if self.data.project.has_feature(Feature.LIST_PACKAGES_INSTALLED_ENV): - self.language_environment.list_packages_installed() + # TODO: remove this and document how to do it on `build.jobs.post_install` + if self.data.project.has_feature(Feature.LIST_PACKAGES_INSTALLED_ENV): + self.language_environment.list_packages_installed() def build(self): """ @@ -168,17 +168,16 @@ def build(self): 3. build PDF 4. build ePub """ - with self.build_environment: - self.data.outcomes = defaultdict(lambda: False) - self.data.outcomes["html"] = self.build_html() - self.data.outcomes["search"] = self.is_type_sphinx() - self.data.outcomes["localmedia"] = self.build_htmlzip() - self.data.outcomes["pdf"] = self.build_pdf() - self.data.outcomes["epub"] = self.build_epub() - - after_build.send( - sender=self.data.version, - ) + self.data.outcomes = defaultdict(lambda: False) + self.data.outcomes["html"] = self.build_html() + self.data.outcomes["search"] = self.is_type_sphinx() + self.data.outcomes["localmedia"] = self.build_htmlzip() + self.data.outcomes["pdf"] = self.build_pdf() + self.data.outcomes["epub"] = self.build_epub() + + after_build.send( + sender=self.data.version, + ) # VCS checkout def pre_checkout(self): diff --git a/readthedocs/projects/tasks/builds.py b/readthedocs/projects/tasks/builds.py index 573d162a732..c750a4175b8 100644 --- a/readthedocs/projects/tasks/builds.py +++ b/readthedocs/projects/tasks/builds.py @@ -548,13 +548,19 @@ def execute(self): # objects in the database self.sync_versions(self.data.build_director.vcs_repository) - # Installing - self.update_build(state=BUILD_STATE_INSTALLING) - self.data.build_director.setup_environment() - - # Building - self.update_build(state=BUILD_STATE_BUILDING) - self.data.build_director.build() + # TODO: remove the ``create_build_environment`` hack. Ideally, this should be + # handled inside the ``BuildDirector`` but we can't use ``with + # self.build_environment`` twice because it kills the container on + # ``__exit__`` + self.data.build_director.create_build_environment() + with self.data.build_director.build_environment: + # Installing + self.update_build(state=BUILD_STATE_INSTALLING) + self.data.build_director.setup_environment() + + # Building + self.update_build(state=BUILD_STATE_BUILDING) + self.data.build_director.build() @staticmethod def get_project(project_pk):