Skip to content

Commit 833f25c

Browse files
samcoferclaude
andauthored
fix(workbench): provision rsconnect via venv in publish-to-connect test (#524)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent ae7a56f commit 833f25c

1 file changed

Lines changed: 71 additions & 13 deletions

File tree

src/vip_tests/workbench/test_publish_to_connect.py

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from __future__ import annotations
1414

1515
import re
16+
import uuid
1617
import warnings
1718
from pathlib import Path
1819

@@ -30,7 +31,7 @@
3031
wait_for_session_active,
3132
workbench_login,
3233
)
33-
from vip_tests.workbench.exec import terminal_run
34+
from vip_tests.workbench.exec import ExecError, terminal_run
3435
from vip_tests.workbench.pages import Homepage, NewSessionDialog, VSCodeSession
3536

3637
pytestmark = pytest.mark.order(60)
@@ -40,6 +41,10 @@
4041
# Timeout for rsconnect deploy, which bundles, uploads, and deploys.
4142
_DEPLOY_TIMEOUT_MS = 180_000
4243

44+
# Timeout for the short venv-management commands (create, pip install, cleanup).
45+
_VENV_SETUP_TIMEOUT_MS = 120_000
46+
_VENV_QUICK_TIMEOUT_MS = 30_000
47+
4348

4449
@scenario(
4550
"test_publish_to_connect.feature",
@@ -182,25 +187,78 @@ def deploy_python_shiny_via_terminal(
182187
connect_client,
183188
_connect_created_guids: list,
184189
):
185-
"""Run ``rsconnect deploy shiny`` in the VS Code terminal and register the GUID."""
190+
"""Run ``rsconnect deploy shiny`` in the VS Code terminal and register the GUID.
191+
192+
``rsconnect-python`` is not assumed to be on PATH. We create a throwaway
193+
venv from whatever ``python3`` the session provides, install
194+
``rsconnect-python`` into it, deploy with that venv's ``rsconnect``, and
195+
tear the venv down afterwards. A missing ``python3`` fails the preflight.
196+
"""
186197
# Open the integrated terminal.
187198
page.keyboard.press("Control+`")
188199
terminal_input = page.locator(VSCodeSession.TERMINAL_INPUT)
189200
expect(terminal_input).to_be_visible(timeout=TIMEOUT_SESSION_START)
190201

202+
# Preflight: a Python interpreter must be on PATH to build the venv.
203+
# Prefer ``python3`` but accept ``python`` so sessions without the
204+
# ``python3`` symlink still qualify.
205+
try:
206+
python_bin = terminal_run(
207+
page,
208+
"command -v python3 || command -v python",
209+
timeout=_VENV_QUICK_TIMEOUT_MS,
210+
readback_lang="python",
211+
).strip()
212+
except ExecError as exc:
213+
raise AssertionError(
214+
"Neither python3 nor python is on PATH in the Workbench session; "
215+
"cannot create a venv to install rsconnect-python for deployment."
216+
) from exc
217+
191218
title = f"vip_test_shiny_{unique_session_name(_FILENAME)}"
219+
venv_dir = f"/tmp/vip_rsconnect_venv_{uuid.uuid4().hex}"
220+
rsconnect_bin = f"{venv_dir}/bin/rsconnect"
192221

193-
output = terminal_run(
194-
page,
195-
(
196-
f"rsconnect deploy shiny {python_shiny_bundle_path} "
197-
f"--server {connect_url} "
198-
f"--api-key {vip_config.connect.api_key} "
199-
f"--title {title}"
200-
),
201-
timeout=_DEPLOY_TIMEOUT_MS,
202-
readback_lang="python",
203-
)
222+
try:
223+
# Create the venv and install rsconnect-python into it.
224+
terminal_run(
225+
page,
226+
f"{python_bin} -m venv {venv_dir}",
227+
timeout=_VENV_SETUP_TIMEOUT_MS,
228+
readback_lang="python",
229+
)
230+
terminal_run(
231+
page,
232+
f"{venv_dir}/bin/pip install --quiet --upgrade rsconnect-python",
233+
timeout=_VENV_SETUP_TIMEOUT_MS,
234+
readback_lang="python",
235+
)
236+
237+
output = terminal_run(
238+
page,
239+
(
240+
f"{rsconnect_bin} deploy shiny {python_shiny_bundle_path} "
241+
f"--server {connect_url} "
242+
f"--api-key {vip_config.connect.api_key} "
243+
f"--title {title}"
244+
),
245+
timeout=_DEPLOY_TIMEOUT_MS,
246+
readback_lang="python",
247+
)
248+
finally:
249+
# Tear down the throwaway venv regardless of deploy outcome.
250+
try:
251+
terminal_run(
252+
page,
253+
f"rm -rf {venv_dir}",
254+
timeout=_VENV_QUICK_TIMEOUT_MS,
255+
readback_lang="python",
256+
)
257+
except ExecError:
258+
warnings.warn(
259+
f"Failed to remove temporary venv at {venv_dir}; manual cleanup may be required.",
260+
stacklevel=2,
261+
)
204262

205263
# Primary: stable API title lookup (version-independent).
206264
content = connect_client._find_content_by_name(title)

0 commit comments

Comments
 (0)