Skip to content

Commit

Permalink
Implement fetching dependencies for yarn regular workflow
Browse files Browse the repository at this point in the history
* with new custom YarnCommandError
* covered with unit tests

JIRA: STONEBLD-1788

Signed-off-by: Michal Šoltis <[email protected]>
  • Loading branch information
slimreaper35 authored and chmeliik committed Oct 13, 2023
1 parent 80aecd8 commit a9e41e2
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 10 deletions.
14 changes: 14 additions & 0 deletions cachi2/core/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,17 @@ class GoModError(Cachi2Error):
The output of the failing go command should provide more details, please check the logs.
"""
).strip()


class YarnCommandError(Cachi2Error):
"""The 'yarn' command used while processing a Yarn project returned an error."""

default_solution = textwrap.dedent(
"""
The cause of the failure could be:
- something is broken in Cachi2
- something is wrong with your yarn project
- communication with an external service failed (please try again)
The output of the failing yarn command should provide more details, please check the logs.
"""
).strip()
12 changes: 7 additions & 5 deletions cachi2/core/package_managers/yarn/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
create_component_from_package,
resolve_packages,
)
from cachi2.core.package_managers.yarn.utils import run_yarn_cmd
from cachi2.core.rooted_path import RootedPath

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -73,7 +74,7 @@ def _check_yarn_cache(source_dir: RootedPath) -> None:
"""Check the contents of the yarn cache using 'yarn install'.
:param source_dir: the directory in which the yarn command will be called.
:raises SubprocessCallError: if the 'yarn install' command fails.
:raises YarnCommandError: if the 'yarn install' command fails.
"""
# the yarn commands can be called by using the core.utils.run_cmd function
pass
Expand All @@ -84,11 +85,12 @@ def _fetch_dependencies(source_dir: RootedPath, output_dir: RootedPath) -> None:
:param source_dir: the directory in which the yarn command will be called.
:param output_dir: the directory where the yarn dependencies will be downloaded to.
:raises SubprocessCallError: if the 'yarn install' command fails.
:raises YarnCommandError: if the 'yarn install' command fails.
"""
# the output_dir is where the globalFolder must be set to
# the yarn commands can be called by using the core.utils.run_cmd function
pass
cachi2_output = output_dir.join_within_root("deps", "yarn")

args = ["install", "--mode", "skip-build"]
run_yarn_cmd(args, source_dir, {"YARN_GLOBAL_FOLDER": str(cachi2_output)})


def _undo_changes(project: Project) -> None:
Expand Down
2 changes: 1 addition & 1 deletion cachi2/core/package_managers/yarn/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def resolve_packages(source_dir: RootedPath) -> list[Package]:
processed.
:raises PackageRejected: if the validation fails.
:raises SubprocessCallError: if the 'yarn info' command fails.
:raises YarnCommandError: if the 'yarn info' command fails.
"""
under_development = True
if under_development:
Expand Down
11 changes: 8 additions & 3 deletions cachi2/core/package_managers/yarn/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import subprocess # nosec

from cachi2.core.errors import YarnCommandError
from cachi2.core.rooted_path import RootedPath
from cachi2.core.utils import run_cmd

Expand All @@ -9,7 +12,9 @@ def run_yarn_cmd(cmd: list[str], source_dir: RootedPath, env: dict[str, str]) ->
:param source_dir: the directory in the repository containing the yarn source files.
:param env: environment variables to be set during the command's execution.
:raises SubprocessCallError: if the command fails.
:raises YarnCommandError: if the command fails.
"""
run_cmd(cmd=["yarn", *cmd], params={"cwd": source_dir, "env": env})
return NotImplemented
try:
return run_cmd(cmd=["yarn", *cmd], params={"cwd": source_dir, "env": env})
except subprocess.CalledProcessError:
raise YarnCommandError(f"Yarn command failed: {' '.join(cmd)}")
2 changes: 1 addition & 1 deletion cachi2/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def run_cmd(cmd: Any, params: dict) -> str:
:param dict params: keyword parameters for command execution
:returns: the command output
:rtype: str
:raises SubprocessCallError: if the command fails
:raises CalledProcessError: if the command fails
"""
params.setdefault("capture_output", True)
params.setdefault("universal_newlines", True)
Expand Down
26 changes: 26 additions & 0 deletions tests/unit/package_managers/yarn/test_main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from unittest import mock

import pytest

from cachi2.core.errors import YarnCommandError
from cachi2.core.package_managers.yarn.main import _fetch_dependencies
from cachi2.core.rooted_path import RootedPath


@mock.patch("cachi2.core.package_managers.yarn.main.run_yarn_cmd")
def test_fetch_dependencies(mock_yarn_cmd: mock.Mock, rooted_tmp_path: RootedPath) -> None:
source_dir = rooted_tmp_path
output_dir = rooted_tmp_path.join_within_root("cachi2-output")

mock_yarn_cmd.side_effect = YarnCommandError("berryscary")

with pytest.raises(YarnCommandError) as exc_info:
_fetch_dependencies(source_dir, output_dir)

mock_yarn_cmd.assert_called_once_with(
["install", "--mode", "skip-build"],
source_dir,
{"YARN_GLOBAL_FOLDER": str(output_dir.join_within_root("deps", "yarn"))},
)

assert str(exc_info.value) == "berryscary"
15 changes: 15 additions & 0 deletions tests/unit/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@ def test_gomod_error_friendly_msg() -> None:
assert err.friendly_msg() == expect_msg


def test_yarn_command_error_friendly_msg() -> None:
err = errors.YarnCommandError("Some yarn command failed")
expect_msg = dedent(
"""
Some yarn command failed
The cause of the failure could be:
- something is broken in Cachi2
- something is wrong with your yarn project
- communication with an external service failed (please try again)
The output of the failing yarn command should provide more details, please check the logs.
"""
).strip()
assert err.friendly_msg() == expect_msg


def test_fetch_error_friendly_msg() -> None:
err = errors.FetchError("Failed to fetch something")
expect_msg = dedent(
Expand Down

0 comments on commit a9e41e2

Please sign in to comment.