Skip to content

Commit

Permalink
fix: reprime for try
Browse files Browse the repository at this point in the history
This solves the case where prime was run before try, where a
subsequent run of try would mask the contents of the existing prime
directory with a newly mounted one from the host. In legacy we had the
concept of `clean --unprime` to solve this.

Signed-off-by: Sergio Schvezov <sergio.schvezov@canonical.com>
  • Loading branch information
sergiusens committed Sep 4, 2023
1 parent 1501166 commit 526fad1
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 6 deletions.
3 changes: 3 additions & 0 deletions snapcraft/parts/lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,9 @@ def _run_lifecycle_and_pack(
step_name,
shell=getattr(parsed_args, "shell", False),
shell_after=getattr(parsed_args, "shell_after", False),
# Repriming needs to happen to take into account any changes to
# the actual target directory.
rerun_step=command_name == "try",
)

# Extract metadata and generate snap.yaml
Expand Down
14 changes: 14 additions & 0 deletions snapcraft/parts/parts.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,14 @@ def run(
*,
shell: bool = False,
shell_after: bool = False,
rerun_step: bool = False,
) -> None:
"""Run the parts lifecycle.
:param target_step: The final step to execute.
:param shell: Enter a shell instead of running step_name.
:param shell: Enter a shell after running step_name.
:param rerun_step: Force running step_name.
:raises PartsLifecycleError: On error during lifecycle.
:raises RuntimeError: On unexpected error.
Expand All @@ -171,6 +175,16 @@ def run(

with self._lcm.action_executor() as aex:
for action in actions:
# Workaround until canonical/craft-parts#540 is fixed
if action.step == target_step and rerun_step:
action = craft_parts.Action(
part_name=action.part_name,
step=action.step,
action_type=ActionType.RERUN,
reason="forced rerun",
project_vars=action.project_vars,
properties=action.properties,
)
message = _action_message(action)
emit.progress(f"Executing parts lifecycle: {message}")
with emit.open_stream("Executing action") as stream:
Expand Down
5 changes: 4 additions & 1 deletion tests/spread/core22/try/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ execute: |
chmod a+w prime
unset SNAPCRAFT_BUILD_ENVIRONMENT
# Prime first to regression test snapcore/snapcraft#4219
snapcraft prime --use-lxd
# Followed by the actual try
snapcraft try --use-lxd
find prime/meta/snap.yaml
find prime/usr/bin/hello
snap try prime
hello-try | MATCH "Hello, world"
snap remove hello-try
snap remove hello-try
50 changes: 45 additions & 5 deletions tests/unit/parts/test_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,13 +299,45 @@ def test_lifecycle_run_command_step(
parsed_args=parsed_args,
)

call_args = {"shell": False, "shell_after": False}
call_args = {"shell": False, "shell_after": False, "rerun_step": False}
if debug_shell:
call_args[debug_shell] = True

assert run_mock.mock_calls == [call(step, **call_args)]


def test_lifecycle_run_try_command(snapcraft_yaml, project_vars, new_dir, mocker):
project = Project.unmarshal(snapcraft_yaml(base="core22"))
run_mock = mocker.patch("snapcraft.parts.PartsLifecycle.run")
mocker.patch("snapcraft.meta.snap_yaml.write")
mocker.patch("snapcraft.pack.pack_snap")

parsed_args = argparse.Namespace(
debug=False,
destructive_mode=True,
enable_manifest=False,
shell=False,
shell_after=False,
use_lxd=False,
ua_token=None,
parts=[],
)

parts_lifecycle._run_command(
"try",
project=project,
parse_info={},
assets_dir=Path(),
start_time=datetime.now(),
parallel_build_count=8,
parsed_args=parsed_args,
)

assert run_mock.mock_calls == [
call("prime", shell=False, shell_after=False, rerun_step=True)
]


@pytest.mark.parametrize("cmd", ["pack", "snap"])
def test_lifecycle_run_command_pack(cmd, snapcraft_yaml, project_vars, new_dir, mocker):
project = Project.unmarshal(snapcraft_yaml(base="core22"))
Expand Down Expand Up @@ -333,7 +365,9 @@ def test_lifecycle_run_command_pack(cmd, snapcraft_yaml, project_vars, new_dir,
),
)

assert run_mock.mock_calls == [call("prime", shell=False, shell_after=False)]
assert run_mock.mock_calls == [
call("prime", shell=False, shell_after=False, rerun_step=False)
]
assert pack_mock.mock_calls[:1] == [
call(
new_dir / "prime",
Expand Down Expand Up @@ -382,7 +416,9 @@ def test_lifecycle_pack_destructive_mode(
)

assert run_in_provider_mock.mock_calls == []
assert run_mock.mock_calls == [call("prime", shell=False, shell_after=False)]
assert run_mock.mock_calls == [
call("prime", shell=False, shell_after=False, rerun_step=False)
]
assert pack_mock.mock_calls[:1] == [
call(
new_dir / "home/prime",
Expand Down Expand Up @@ -432,7 +468,9 @@ def test_lifecycle_pack_managed(cmd, snapcraft_yaml, project_vars, new_dir, mock
)

assert run_in_provider_mock.mock_calls == []
assert run_mock.mock_calls == [call("prime", shell=False, shell_after=False)]
assert run_mock.mock_calls == [
call("prime", shell=False, shell_after=False, rerun_step=False)
]
assert pack_mock.mock_calls[:1] == [
call(
new_dir / "home/prime",
Expand Down Expand Up @@ -525,7 +563,9 @@ def test_lifecycle_pack_metadata_error(cmd, snapcraft_yaml, new_dir, mocker):
assert str(raised.value) == (
"error setting grade: unexpected value; permitted: 'stable', 'devel'"
)
assert run_mock.mock_calls == [call("prime", shell=False, shell_after=False)]
assert run_mock.mock_calls == [
call("prime", shell=False, shell_after=False, rerun_step=False)
]
assert pack_mock.mock_calls == []


Expand Down

0 comments on commit 526fad1

Please sign in to comment.