diff --git a/readthedocs/doc_builder/director.py b/readthedocs/doc_builder/director.py index 02a9b806757..830eb083367 100644 --- a/readthedocs/doc_builder/director.py +++ b/readthedocs/doc_builder/director.py @@ -442,7 +442,7 @@ def check_old_output_directory(self): def run_build_commands(self): """Runs each build command in the build environment.""" - reshim_commands = ( + python_reshim_commands = ( {"pip", "install"}, {"conda", "create"}, {"conda", "install"}, @@ -450,6 +450,8 @@ def run_build_commands(self): {"mamba", "install"}, {"poetry", "install"}, ) + rust_reshim_commands = ({"cargo", "install"},) + cwd = self.data.project.checkout_path(self.data.version.slug) environment = self.build_environment for command in self.data.config.build.commands: @@ -458,11 +460,11 @@ def run_build_commands(self): # Execute ``asdf reshim python`` if the user is installing a # package since the package may contain an executable # See https://github.com/readthedocs/readthedocs.org/pull/9150#discussion_r882849790 - for reshim_command in reshim_commands: + for python_reshim_command in python_reshim_commands: # Convert tuple/list into set to check reshim command is a # subset of the command itself. This is to find ``pip install`` # but also ``pip -v install`` and ``python -m pip install`` - if reshim_command.issubset(command.split()): + if python_reshim_command.issubset(command.split()): environment.run( *["asdf", "reshim", "python"], escape_command=False, @@ -470,6 +472,16 @@ def run_build_commands(self): record=False, ) + # Do same for Rust + for rust_reshim_command in rust_reshim_commands: + if rust_reshim_command.issubset(command.split()): + environment.run( + *["asdf", "reshim", "rust"], + escape_command=False, + cwd=cwd, + record=False, + ) + html_output_path = os.path.join(cwd, BUILD_COMMANDS_OUTPUT_PATH_HTML) if not os.path.exists(html_output_path): raise BuildUserError(BuildUserError.BUILD_COMMANDS_WITHOUT_OUTPUT) diff --git a/readthedocs/projects/tests/test_build_tasks.py b/readthedocs/projects/tests/test_build_tasks.py index 5fa64b6673b..7732a2fcac8 100644 --- a/readthedocs/projects/tests/test_build_tasks.py +++ b/readthedocs/projects/tests/test_build_tasks.py @@ -1468,6 +1468,56 @@ def test_build_commands(self, load_yaml_config): ] ) + @mock.patch("readthedocs.doc_builder.director.load_yaml_config") + def test_reshim_rust(self, load_yaml_config): + config = BuildConfigV2( + { + "version": 2, + "build": { + "os": "ubuntu-22.04", + "tools": { + "rust": "latest", + }, + "commands": [ + "cargo install mdbook", + "mdbook build", + ], + }, + }, + source_file="readthedocs.yml", + ) + config.validate() + load_yaml_config.return_value = config + + self._trigger_update_docs_task() + + rust_version = settings.RTD_DOCKER_BUILD_SETTINGS["tools"]["rust"]["latest"] + self.mocker.mocks["environment.run"].assert_has_calls( + [ + mock.call("asdf", "install", "rust", rust_version), + mock.call("asdf", "global", "rust", rust_version), + mock.call("asdf", "reshim", "rust", record=False), + mock.call( + "cargo install mdbook", + escape_command=False, + cwd=mock.ANY, + ), + mock.call( + "asdf", + "reshim", + "rust", + escape_command=False, + record=False, + cwd=mock.ANY, + ), + mock.call( + "mdbook build", + escape_command=False, + cwd=mock.ANY, + ), + ] + ) + @mock.patch("readthedocs.doc_builder.director.load_yaml_config") def test_requirements_from_config_file_installed(self, load_yaml_config): load_yaml_config.return_value = get_build_config(