From 7fa6ac5d55eed28e02615e62afef3d7cc364efec Mon Sep 17 00:00:00 2001 From: Emily Ragan Date: Wed, 30 Sep 2026 13:48:39 -0600 Subject: [PATCH] fix(plugins): skip python dependency install on modified_diff dry run Co-Authored-By: Claude --- openc3/lib/openc3/models/plugin_model.rb | 5 ++++- openc3/spec/models/plugin_model_spec.rb | 19 +++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/openc3/lib/openc3/models/plugin_model.rb b/openc3/lib/openc3/models/plugin_model.rb index c5b1fce410..747b7c0122 100644 --- a/openc3/lib/openc3/models/plugin_model.rb +++ b/openc3/lib/openc3/models/plugin_model.rb @@ -278,7 +278,10 @@ def self.install_phase2(plugin_hash, scope:, gem_file_path: nil, validate_only: if File.exist?(pyproject_path) || File.exist?(requirements_path) pypi_url = resolve_pypi_url(scope: scope) - unless validate_only + # Skipped for any dry run: diff_only runs inline in an HTTP request, so + # a slow or unreachable PyPI would time it out, and it must not mutate + # the plugin venv. + unless dry_run pypi_args = build_pypi_args(pypi_url) # Install Python dependencies into an isolated per-plugin venv when UV diff --git a/openc3/spec/models/plugin_model_spec.rb b/openc3/spec/models/plugin_model_spec.rb index 8c621b94fd..bdb88e0da9 100644 --- a/openc3/spec/models/plugin_model_spec.rb +++ b/openc3/spec/models/plugin_model_spec.rb @@ -634,7 +634,7 @@ module OpenC3 # which Python dependency file it ships and what OPENC3_USE_UV is set # to, so the shared doubles live here and each example is left with the # behavior it actually asserts. - def stub_plugin_gem(dep_file: 'pyproject.toml', dep_body: '[project]', use_uv: nil) + def stub_plugin_gem(dep_file: 'pyproject.toml', dep_body: '[project]', use_uv: nil, gem_install: true) expect(GemModel).to receive(:get).and_return("my_plugin.gem") gem = double("gem") expect(gem).to receive(:extract_files) do |path| @@ -643,7 +643,11 @@ def stub_plugin_gem(dep_file: 'pyproject.toml', dep_body: '[project]', use_uv: n end expect(Gem::Package).to receive(:new).and_return(gem) allow(gem).to receive(:spec).and_return(spec_double) - expect(GemModel).to receive(:install).and_return(nil) + if gem_install + expect(GemModel).to receive(:install).and_return(nil) + else + expect(GemModel).to_not receive(:install) + end allow(ENV).to receive(:[]).and_call_original allow(ENV).to receive(:[]).with('OPENC3_USE_UV').and_return(use_uv) @@ -740,6 +744,17 @@ def install_plugin expect(install_plugin['needs_dependencies']).to eql true end + + it "does not install python packages when diff_only" do + stub_plugin_gem(gem_install: false) + stub_uv_on_path(true) + + expect(Open3).to_not receive(:capture2e) + + result = PluginModel.install_phase2({"name" => "name", "variables" => {}, "plugin_txt_lines" => plugin_txt_lines}, + scope: "DEFAULT", diff_only: true) + expect(result).to eql([]) + end end end