diff --git a/src/azure-cli/azure/cli/command_modules/resource/_bicep.py b/src/azure-cli/azure/cli/command_modules/resource/_bicep.py index 351e561a951..d5579eb4947 100644 --- a/src/azure-cli/azure/cli/command_modules/resource/_bicep.py +++ b/src/azure-cli/azure/cli/command_modules/resource/_bicep.py @@ -93,9 +93,9 @@ def run_bicep_command(cli_ctx, args, auto_install=True): # Users may continue using the current installed version. installed_version = _get_bicep_installed_version(installation_path) latest_release_tag = get_bicep_latest_release_tag() if cache_expired else latest_release_tag - latest_version = _extract_semver(latest_release_tag) + latest_version = _extract_version(latest_release_tag) - if installed_version and latest_version and semver.compare(installed_version, latest_version) < 0: + if installed_version and latest_version and installed_version < latest_version: _logger.warning( 'A new Bicep release is available: %s. Upgrade now by running "az bicep upgrade".', latest_release_tag, @@ -116,8 +116,8 @@ def ensure_bicep_installation(cli_ctx, release_tag=None, target_platform=None, s return installed_version = _get_bicep_installed_version(installation_path) - target_version = _extract_semver(release_tag) - if installed_version and target_version and semver.compare(installed_version, target_version) == 0: + target_version = _extract_version(release_tag) + if installed_version and target_version and installed_version == target_version: return installation_dir = os.path.dirname(installation_path) @@ -192,7 +192,7 @@ def get_bicep_latest_release_tag(): response = requests.get("https://aka.ms/BicepLatestRelease", verify=_requests_verify) response.raise_for_status() return response.json()["tag_name"] - except IOError as err: + except requests.RequestException as err: raise ClientRequestError(f"Error while attempting to retrieve the latest Bicep version: {err}.") @@ -200,14 +200,8 @@ def bicep_version_greater_than_or_equal_to(version): system = platform.system() installation_path = _get_bicep_installation_path(system) installed_version = _get_bicep_installed_version(installation_path) - return semver.compare(installed_version, version) >= 0 - - -def supports_bicep_publish(): - system = platform.system() - installation_path = _get_bicep_installation_path(system) - installed_version = _get_bicep_installed_version(installation_path) - return semver.compare(installed_version, "0.4.1008") >= 0 + parsed_version = semver.VersionInfo.parse(version) + return installed_version >= parsed_version def _bicep_installed_in_ci(): @@ -260,18 +254,18 @@ def _load_bicep_version_check_result_from_cache(): return None, True -def _refresh_bicep_version_check_cache(lastest_release_tag): +def _refresh_bicep_version_check_cache(latest_release_tag): with open(_bicep_version_check_file_path, "w+") as version_check_file: version_check_data = { "lastCheckTime": datetime.now().strftime(_bicep_version_check_time_format), - "latestReleaseTag": lastest_release_tag, + "latestReleaseTag": latest_release_tag, } json.dump(version_check_data, version_check_file) def _get_bicep_installed_version(bicep_executable_path): installed_version_output = _run_command(bicep_executable_path, ["--version"]) - return _extract_semver(installed_version_output) + return _extract_version(installed_version_output) def _get_bicep_download_url(system, release_tag, target_platform=None): @@ -302,9 +296,9 @@ def _get_bicep_installation_path(system): raise ValidationError(f'The platform "{system}" is not supported.') -def _extract_semver(text): +def _extract_version(text): semver_match = re.search(_semver_pattern, text) - return semver_match.group(0) if semver_match else None + return semver.VersionInfo.parse(semver_match.group(0)) if semver_match else None def _run_command(bicep_installation_path, args): diff --git a/src/azure-cli/azure/cli/command_modules/resource/custom.py b/src/azure-cli/azure/cli/command_modules/resource/custom.py index ed84f6cbacd..e1c482b98ec 100644 --- a/src/azure-cli/azure/cli/command_modules/resource/custom.py +++ b/src/azure-cli/azure/cli/command_modules/resource/custom.py @@ -1448,8 +1448,6 @@ def _validate_resource_inputs(resource_group_name, resource_provider_namespace, raise CLIError('--namespace is required') -# region Custom Commands - def list_resource_groups(cmd, tag=None): # pylint: disable=no-self-use """ List resource groups, optionally filtered by a tag. :param str tag:tag to filter by in 'key[=value]' format diff --git a/src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource_bicep.py b/src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource_bicep.py index 52eaa051f28..69aa0570387 100644 --- a/src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource_bicep.py +++ b/src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource_bicep.py @@ -6,6 +6,7 @@ import os import contextlib import unittest +import semver from unittest import mock from knack.util import CLIError @@ -19,20 +20,21 @@ from azure.cli.core.azclierror import InvalidTemplateError from azure.cli.core.mock import DummyCli -cli_ctx = DummyCli() - class TestBicep(unittest.TestCase): + def setUp(self): + self.cli_ctx = DummyCli(random_config_dir=True) + @mock.patch("os.path.isfile") def test_run_bicep_command_raise_error_if_not_installed_and_not_auto_install(self, isfile_stub): isfile_stub.return_value = False with contextlib.suppress(FileNotFoundError): - remove_bicep_installation(cli_ctx) + remove_bicep_installation(self.cli_ctx) - cli_ctx.config.set_value("bicep", "use_binary_from_path", "false") + self.cli_ctx.config.set_value("bicep", "use_binary_from_path", "false") with self.assertRaisesRegex(CLIError, 'Bicep CLI not found. Install it now by running "az bicep install".'): - run_bicep_command(cli_ctx, ["--version"], auto_install=False) + run_bicep_command(self.cli_ctx, ["--version"], auto_install=False) @mock.patch("os.chmod") @mock.patch("os.stat") @@ -59,22 +61,22 @@ def test_use_bicep_cli_from_path_false_after_install(self, isfile_stub, dirname_ response.read.return_value = b"test" urlopen_stub.return_value = response - ensure_bicep_installation(cli_ctx, release_tag="v0.14.85", stdout=False) + ensure_bicep_installation(self.cli_ctx, release_tag="v0.14.85", stdout=False) - self.assertTrue(cli_ctx.config.get("bicep", "use_binary_from_path") == "false") + self.assertTrue(self.cli_ctx.config.get("bicep", "use_binary_from_path") == "false") @mock.patch("shutil.which") def test_run_bicep_command_raise_error_if_bicep_cli_not_found_when_use_binary_from_path_is_true(self, which_stub): which_stub.return_value = None - cli_ctx.config.set_value("bicep", "use_binary_from_path", "true") + self.cli_ctx.config.set_value("bicep", "use_binary_from_path", "true") with self.assertRaisesRegex( CLIError, 'Could not find the "bicep" executable on PATH. To install Bicep via Azure CLI, set the "bicep.use_binary_from_path" configuration to False and run "az bicep install".', ): - run_bicep_command(cli_ctx, ["--version"], auto_install=False) + run_bicep_command(self.cli_ctx, ["--version"], auto_install=False) - cli_ctx.config.set_value("bicep", "use_binary_from_path", "false") + self.cli_ctx.config.set_value("bicep", "use_binary_from_path", "false") @mock.patch.dict(os.environ, {"GITHUB_ACTIONS": "true"}, clear=True) @mock.patch("azure.cli.command_modules.resource._bicep._logger.debug") @@ -83,9 +85,9 @@ def test_run_bicep_command_raise_error_if_bicep_cli_not_found_when_use_binary_fr def test_run_bicep_command_use_bicep_cli_from_path_in_ci(self, which_stub, run_command_stub, debug_mock): which_stub.return_value = True run_command_stub.return_value = "Bicep CLI version 0.13.1 (e3ac80d678)" - cli_ctx.config.set_value("bicep", "use_binary_from_path", "if_found_in_ci") + self.cli_ctx.config.set_value("bicep", "use_binary_from_path", "if_found_in_ci") - run_bicep_command(cli_ctx, ["--version"], auto_install=False) + run_bicep_command(self.cli_ctx, ["--version"], auto_install=False) debug_mock.assert_called_with( "Using Bicep CLI from PATH. %s", @@ -108,12 +110,12 @@ def test_run_bicep_command_check_version( warning_mock, ): isfile_stub.return_value = True - _get_bicep_installed_version_stub.return_value = "1.0.0" + _get_bicep_installed_version_stub.return_value = semver.VersionInfo.parse("1.0.0") get_bicep_latest_release_tag_stub.return_value = "v2.0.0" - cli_ctx.config.set_value("bicep", "check_version", "True") - cli_ctx.config.set_value("bicep", "use_binary_from_path", "false") - run_bicep_command(cli_ctx, ["--version"]) + self.cli_ctx.config.set_value("bicep", "check_version", "True") + self.cli_ctx.config.set_value("bicep", "use_binary_from_path", "false") + run_bicep_command(self.cli_ctx, ["--version"]) warning_mock.assert_called_once_with( 'A new Bicep release is available: %s. Upgrade now by running "az bicep upgrade".', @@ -139,10 +141,10 @@ def test_run_bicep_command_check_version_cache_read_write( self._remove_bicep_version_check_file() isfile_stub.return_value = True - _get_bicep_installed_version_stub.return_value = "1.0.0" + _get_bicep_installed_version_stub.return_value = semver.VersionInfo.parse("1.0.0") get_bicep_latest_release_tag_stub.return_value = "v2.0.0" - run_bicep_command(cli_ctx, ["--version"]) + run_bicep_command(self.cli_ctx, ["--version"]) self.assertTrue(os.path.isfile(_bicep_version_check_file_path)) finally: @@ -154,10 +156,10 @@ def test_run_bicep_command_check_version_cache_read_write( def test_ensure_bicep_installation_skip_download_if_installed_version_matches_release_tag( self, dirname_mock, _get_bicep_installed_version_stub, isfile_stub ): - _get_bicep_installed_version_stub.return_value = "0.1.0" + _get_bicep_installed_version_stub.return_value = semver.VersionInfo.parse("0.1.0") isfile_stub.return_value = True - ensure_bicep_installation(cli_ctx, release_tag="v0.1.0") + ensure_bicep_installation(self.cli_ctx, release_tag="v0.1.0") dirname_mock.assert_not_called()