Skip to content

Commit ed41bcc

Browse files
committed
feat: adds wrangler version check
1 parent 8801d72 commit ed41bcc

File tree

3 files changed

+93
-2
lines changed

3 files changed

+93
-2
lines changed

src/pywrangler/cli.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ def get_command(self, ctx, cmd_name):
5757
if cmd_name in ["dev", "publish", "deploy", "versions"]:
5858
ctx.invoke(sync_command, force=False, directly_requested=False)
5959

60+
if cmd_name == "dev":
61+
from pywrangler.sync import check_wrangler_version
62+
63+
check_wrangler_version()
64+
6065
_proxy_to_wrangler(cmd_name, remaining_args)
6166
sys.exit(0)
6267

src/pywrangler/sync.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22
import os
3+
import re
34
import shutil
45
import tempfile
56
from contextlib import contextmanager
@@ -229,6 +230,7 @@ def create_workers_venv():
229230

230231

231232
MIN_UV_VERSION = (0, 8, 10)
233+
MIN_WRANGLER_VERSION = (4, 42, 1)
232234

233235

234236
def check_uv_version():
@@ -243,6 +245,48 @@ def check_uv_version():
243245
raise click.exceptions.Exit(code=1)
244246

245247

248+
def check_wrangler_version():
249+
"""
250+
Check that the installed wrangler version is at least 4.42.1.
251+
252+
Raises:
253+
click.exceptions.Exit: If wrangler is not installed or version is too old.
254+
"""
255+
result = run_command(
256+
["npx", "--yes", "wrangler", "--version"], capture_output=True, check=False
257+
)
258+
if result.returncode != 0:
259+
logger.error("Failed to get wrangler version. Is wrangler installed?")
260+
logger.error("Install wrangler with: npm install wrangler@latest")
261+
raise click.exceptions.Exit(code=1)
262+
263+
# Parse version from output like "wrangler 4.42.1" or " ⛅️ wrangler 4.42.1"
264+
version_line = result.stdout.strip()
265+
# Extract version number using regex
266+
version_match = re.search(r"wrangler\s+(\d+)\.(\d+)\.(\d+)", version_line)
267+
268+
if not version_match:
269+
logger.error(f"Could not parse wrangler version from: {version_line}")
270+
logger.error("Install wrangler with: npm install wrangler@latest")
271+
raise click.exceptions.Exit(code=1)
272+
273+
major, minor, patch = map(int, version_match.groups())
274+
current_version = (major, minor, patch)
275+
276+
if current_version < MIN_WRANGLER_VERSION:
277+
min_version_str = ".".join(str(x) for x in MIN_WRANGLER_VERSION)
278+
current_version_str = ".".join(str(x) for x in current_version)
279+
logger.error(
280+
f"wrangler version at least {min_version_str} required, have {current_version_str}."
281+
)
282+
logger.error("Update wrangler with: npm install wrangler@latest")
283+
raise click.exceptions.Exit(code=1)
284+
285+
logger.debug(
286+
f"wrangler version {'.'.join(str(x) for x in current_version)} is sufficient"
287+
)
288+
289+
246290
def create_pyodide_venv():
247291
if PYODIDE_VENV_PATH.is_dir():
248292
logger.debug(

tests/test_cli.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import shutil
44
import subprocess
55
from pathlib import Path
6-
from unittest.mock import patch
6+
from unittest.mock import patch, Mock
77
from textwrap import dedent
88

99
import pytest
@@ -406,10 +406,13 @@ def test_proxy_to_wrangler_unknown_command(mock_proxy_to_wrangler):
406406
)
407407

408408

409+
@patch("pywrangler.sync.check_wrangler_version")
409410
@patch("pywrangler.cli._proxy_to_wrangler")
410411
@patch("pywrangler.cli.sync_command")
411412
@patch("sys.argv", ["pywrangler", "dev", "--local"])
412-
def test_proxy_auto_sync_commands(mock_sync_command, mock_proxy_to_wrangler):
413+
def test_proxy_auto_sync_commands(
414+
mock_sync_command, mock_proxy_to_wrangler, mock_check_wrangler_version
415+
):
413416
"""Test that dev, publish, and deploy commands automatically run sync first."""
414417
runner = CliRunner()
415418

@@ -530,3 +533,42 @@ def test_sync_recreates_venv_on_python_version_mismatch(clean_test_dir):
530533
assert "3.13" in version_result.stdout, (
531534
f"Python version is not 3.13: {version_result.stdout}"
532535
)
536+
537+
538+
# Wrangler version check tests
539+
@patch("pywrangler.sync.run_command")
540+
def test_check_wrangler_version_sufficient(mock_run_command):
541+
"""Test that check_wrangler_version passes with sufficient version."""
542+
from pywrangler.sync import check_wrangler_version
543+
544+
# Mock successful wrangler version output
545+
mock_result = Mock()
546+
mock_result.returncode = 0
547+
mock_result.stdout = "wrangler 4.42.1"
548+
mock_run_command.return_value = mock_result
549+
550+
# Should not raise an exception
551+
check_wrangler_version()
552+
553+
# Verify the command was called correctly
554+
mock_run_command.assert_called_once_with(
555+
["npx", "--yes", "wrangler", "--version"], capture_output=True, check=False
556+
)
557+
558+
559+
@patch("pywrangler.sync.run_command")
560+
def test_check_wrangler_version_insufficient(mock_run_command):
561+
"""Test that check_wrangler_version fails with insufficient version."""
562+
from pywrangler.sync import check_wrangler_version
563+
564+
# Mock wrangler version output with old version
565+
mock_result = Mock()
566+
mock_result.returncode = 0
567+
mock_result.stdout = "⛅️ wrangler 4.40.0"
568+
mock_run_command.return_value = mock_result
569+
570+
# Should raise SystemExit
571+
import click
572+
573+
with pytest.raises(click.exceptions.Exit):
574+
check_wrangler_version()

0 commit comments

Comments
 (0)