Skip to content

Commit

Permalink
Merge pull request #438 from cjp256/output-cwd
Browse files Browse the repository at this point in the history
commands/build: output charms to cwd when using provider (CRAFT-359)
  • Loading branch information
Chris Patterson authored and facundobatista committed Jul 8, 2021
1 parent bd9d6cc commit e9527f2
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 5 deletions.
13 changes: 11 additions & 2 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,16 @@ jobs:
- name: Run smoke tests
run: |
mkdir -p charm-smoke-test
cd charm-smoke-test
pushd charm-smoke-test
charmcraft -v init --author testuser
sg lxd -c "charmcraft -v build"
sg lxd -c "charmcraft -v pack"
test -f *.charm
sg lxd -c "charmcraft -v clean"
popd
mkdir -p another-directory
pushd another-directory
sg lxd -c "charmcraft -v pack --project-dir ../charm-smoke-test"
test -f *.charm
sg lxd -c "charmcraft -v clean --project-dir ../charm-smoke-test"
popd
29 changes: 27 additions & 2 deletions charmcraft/commands/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
import zipfile
from typing import List, Optional


from charmcraft.bases import check_if_base_matches_host
from charmcraft.cmdbase import BaseCommand, CommandError
from charmcraft.config import Base, BasesConfiguration, Config
from charmcraft.deprecations import notify_deprecation
from charmcraft.env import (
get_managed_environment_home_path,
get_managed_environment_project_path,
is_charmcraft_running_in_managed_mode,
)
Expand Down Expand Up @@ -254,6 +254,20 @@ def pack_charm_in_instance(
charm_name = format_charm_file_name(
self.metadata.name, self.config.bases[bases_index]
)

# If building in project directory, use the project path as the working
# directory. The output charms will be placed in the correct directory
# without needing retrieval. If outputing to a directory other than the
# charm project directory, we need to output the charm outside the
# project directory and can retrieve it when complete.
cwd = pathlib.Path.cwd()
if cwd == self.charmdir:
instance_output_dir = get_managed_environment_project_path()
pull_charm = False
else:
instance_output_dir = get_managed_environment_home_path()
pull_charm = True

cmd = ["charmcraft", "pack", "--bases-index", str(bases_index)]

if message_handler.mode == message_handler.VERBOSE:
Expand All @@ -273,14 +287,25 @@ def pack_charm_in_instance(
instance.execute_run(
cmd,
check=True,
cwd=get_managed_environment_project_path().as_posix(),
cwd=instance_output_dir.as_posix(),
)
except subprocess.CalledProcessError as error:
capture_logs_from_instance(instance)
raise CommandError(
f"Failed to build charm for bases index '{bases_index}'."
) from error

if pull_charm:
try:
instance.pull_file(
source=instance_output_dir / charm_name,
destination=cwd / charm_name,
)
except FileNotFoundError as error:
raise CommandError(
"Unexpected error retrieving charm from instance."
) from error

return charm_name

def _load_juju_ignore(self):
Expand Down
7 changes: 6 additions & 1 deletion charmcraft/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,19 @@
from charmcraft.cmdbase import CommandError


def get_managed_environment_home_path():
"""Path for home when running in managed environment."""
return pathlib.Path("/root")


def get_managed_environment_log_path():
"""Path for charmcraft log when running in managed environment."""
return pathlib.Path("/tmp/charmcraft.log")


def get_managed_environment_project_path():
"""Path for project when running in managed environment."""
return pathlib.Path("/root/project")
return get_managed_environment_home_path() / "project"


def is_charmcraft_running_from_snap():
Expand Down
127 changes: 127 additions & 0 deletions tests/commands/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,133 @@ def test_build_multiple_with_charmcraft_yaml(basic_project, monkeypatch, caplog)
assert "Building for 'bases[2]' as host matches 'build-on[0]'." in records


def test_build_project_is_cwd(
basic_project,
caplog,
mock_capture_logs_from_instance,
mock_ensure_provider_is_available,
monkeypatch,
):
"""Test cases for base-index parameter."""
mode = message_handler.NORMAL
monkeypatch.setattr(message_handler, "mode", mode)
host_base = get_host_as_base()
host_arch = host_base.architectures[0]
charmcraft_file = basic_project / "charmcraft.yaml"
charmcraft_file.write_text(
dedent(
f"""\
type: charm
bases:
- name: ubuntu
channel: "18.04"
architectures: {host_base.architectures!r}
"""
)
)
config = load(basic_project)
builder = Builder(
{
"from": basic_project,
"entrypoint": basic_project / "src" / "charm.py",
"requirement": [],
},
config,
)

monkeypatch.chdir(basic_project)
with patch("charmcraft.commands.build.launched_environment") as mock_launch:
zipnames = builder.run([0])

assert zipnames == [
f"name-from-metadata_ubuntu-18.04-{host_arch}.charm",
]
assert mock_launch.mock_calls == [
call(
charm_name="name-from-metadata",
project_path=basic_project,
base=Base(name="ubuntu", channel="18.04", architectures=[host_arch]),
bases_index=0,
build_on_index=0,
),
call().__enter__(),
call()
.__enter__()
.execute_run(
["charmcraft", "pack", "--bases-index", "0"],
check=True,
cwd="/root/project",
),
call().__exit__(None, None, None),
]


def test_build_project_is_not_cwd(
basic_project,
caplog,
mock_capture_logs_from_instance,
mock_ensure_provider_is_available,
monkeypatch,
):
"""Test cases for base-index parameter."""
mode = message_handler.NORMAL
monkeypatch.setattr(message_handler, "mode", mode)
host_base = get_host_as_base()
host_arch = host_base.architectures[0]
charmcraft_file = basic_project / "charmcraft.yaml"
charmcraft_file.write_text(
dedent(
f"""\
type: charm
bases:
- name: ubuntu
channel: "18.04"
architectures: {host_base.architectures!r}
"""
)
)
config = load(basic_project)
builder = Builder(
{
"from": basic_project,
"entrypoint": basic_project / "src" / "charm.py",
"requirement": [],
},
config,
)

with patch("charmcraft.commands.build.launched_environment") as mock_launch:
zipnames = builder.run([0])

assert zipnames == [
f"name-from-metadata_ubuntu-18.04-{host_arch}.charm",
]
assert mock_launch.mock_calls == [
call(
charm_name="name-from-metadata",
project_path=basic_project,
base=Base(name="ubuntu", channel="18.04", architectures=[host_arch]),
bases_index=0,
build_on_index=0,
),
call().__enter__(),
call()
.__enter__()
.execute_run(
["charmcraft", "pack", "--bases-index", "0"],
check=True,
cwd="/root",
),
call()
.__enter__()
.pull_file(
source=pathlib.Path("/root") / zipnames[0],
destination=pathlib.Path.cwd() / zipnames[0],
),
call().__exit__(None, None, None),
]


@pytest.mark.parametrize(
"mode,cmd_flags",
[
Expand Down
6 changes: 6 additions & 0 deletions tests/test_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
from charmcraft.cmdbase import CommandError


def test_get_managed_environment_home_path():
dirpath = env.get_managed_environment_home_path()

assert dirpath == pathlib.Path("/root")


def test_get_managed_environment_log_path():
dirpath = env.get_managed_environment_log_path()

Expand Down

0 comments on commit e9527f2

Please sign in to comment.