Skip to content

Commit

Permalink
az_cli_universal_dependency: Enhance error messaging (#934)
Browse files Browse the repository at this point in the history
1. If the `azure-devops` extension is not installed, provide a URL
   with installation instructions. This link can directly be clicked
   in many shell environments.
2. If an error occurs running the Azure CLI then show the error
   message to the user. This often has helpful instructions for what
   needs to be done to resolve the error. Example shown below.

Before:

```
    raise Exception("{0} failed with Return Code: {1}".format(cmd, returncode_str))
	Exception: az artifacts universal download --organization https://dev.azure.com/Organization/
	  --feed FEED --name NAME --version 0.0.1 --path "PATH" failed with Return Code: 0x00000001
```

After:

```
    raise Exception(
      Exception:
        Command "az artifacts universal download --organization https://dev.azure.com/Organization/
	      --feed FEED --name NAME --version 0.0.1 --path "PATH"" failed with 1.

      ERROR: Failed to update Universal Packages tooling.
        Before you can run Azure DevOps commands, you need to run the login command(az login if using
		AAD/MSA identity else az devops login if using PAT token) to setup credentials.
		Please see https://aka.ms/azure-devops-cli-auth for more information.
```

Signed-off-by: Michael Kubacki <[email protected]>
  • Loading branch information
makubacki authored Feb 14, 2025
1 parent 9793738 commit dc10b16
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ def VerifyToolDependencies(cls: "AzureCliUniversalDependency") -> None:

# 2 - Check for azure-devops extension
if "azure-devops" not in found.keys():
logging.critical("Missing required Azure-cli extension azure-devops")
logging.critical(
"Missing required Azure-cli extension azure-devops.\n"
"Installation instructions: https://learn.microsoft.com/azure/devops/cli"
)
raise EnvironmentError("Missing required Azure-cli extension azure-devops")

cls.VersionLogged = True
Expand Down Expand Up @@ -141,7 +144,11 @@ def _attempt_universal_install(self, install_dir: str) -> None:
e[self.AZURE_CLI_DEVOPS_ENV_VAR] = self._pat

results = StringIO()
RunCmd(cmd[0], " ".join(cmd[1:]), outstream=results, environ=e, raise_exception_on_nonzero=True)
ret = RunCmd(cmd[0], " ".join(cmd[1:]), outstream=results, environ=e)
if ret != 0:
results.seek(0)
raise Exception(f"\nCommand \"{' '.join(cmd)}\" failed with {ret}.\n\n" f"{results.getvalue()}")

# az tool returns json data that includes the downloaded version
# lets check it to double confirm
result_data = json.loads(results.getvalue())
Expand Down
17 changes: 17 additions & 0 deletions tests.unit/test_az_cli_universal_dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from edk2toolext.environment import version_aggregator
from edk2toolext.environment.extdeptypes.az_cli_universal_dependency import AzureCliUniversalDependency
from edk2toollib.utility_functions import RemoveTree
from unittest.mock import MagicMock, patch

test_dir = None

Expand Down Expand Up @@ -224,6 +225,22 @@ def test_download_good_universal_dependency_folders_file_filter(self):
# make sure we clean up after ourselves
ext_dep.clean()

# bad case
# note: similar to `test_download_bad_universal_dependency()` but more
# generally tests the non-zero return from `RunCmd()` behavior
# without depending on a PAT or other assumptions about the feed.
@patch("edk2toolext.environment.extdeptypes.az_cli_universal_dependency.RunCmd", return_value=1)
def test_cmd_run_non_zero(self, mock_run_cmd: MagicMock):
version = "0.0.1"
ext_dep_file_path = os.path.join(test_dir, "unit_test_ext_dep.json")
with open(ext_dep_file_path, "w+") as ext_dep_file:
ext_dep_file.write(single_file_json_template % version)

ext_dep_descriptor = EDF.ExternDepDescriptor(ext_dep_file_path).descriptor_contents
ext_dep = AzureCliUniversalDependency(ext_dep_descriptor)
with self.assertRaises(Exception):
ext_dep.fetch()

# bad case
@unittest.skipIf(
"PAT_FOR_UNIVERSAL_ORG_TIANOCORE" not in os.environ.keys(),
Expand Down

0 comments on commit dc10b16

Please sign in to comment.