Merge ~jugmac00/lpci:declare-snap-dependencies-for-jobs into lpci:main

Proposed by Jürgen Gmach
Status: Merged
Merged at revision: a4152145f111677e26acf0c099585b2dd6f3f4e6
Proposed branch: ~jugmac00/lpci:declare-snap-dependencies-for-jobs
Merge into: lpci:main
Diff against target: 193 lines (+136/-3)
4 files modified
lpcraft/commands/run.py (+13/-3)
lpcraft/commands/tests/test_run.py (+87/-0)
lpcraft/config.py (+1/-0)
lpcraft/tests/test_config.py (+35/-0)
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+412478@code.launchpad.net

Commit message

Declare snap dependencies for jobs

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) :
review: Needs Fixing
Revision history for this message
Jürgen Gmach (jugmac00) wrote :

Applied suggested fixes - please re-re-view.

Revision history for this message
Colin Watson (cjwatson) wrote :

I expect that we'll have to extend this to support channels other than stable at some point, but this will do fine for now.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lpcraft/commands/run.py b/lpcraft/commands/run.py
2index eb03be0..8e94a5d 100644
3--- a/lpcraft/commands/run.py
4+++ b/lpcraft/commands/run.py
5@@ -11,6 +11,7 @@ from typing import List, Set
6
7 from craft_cli import emit
8 from craft_providers import Executor
9+from craft_providers.actions.snap_installer import install_from_store
10 from dotenv import dotenv_values
11
12 from lpcraft import env
13@@ -180,7 +181,6 @@ def run(args: Namespace) -> int:
14 f"does not set 'run'"
15 )
16
17- cmd = ["bash", "--noprofile", "--norc", "-ec", job.run]
18 remote_cwd = env.get_managed_environment_project_path()
19
20 emit.progress(
21@@ -192,10 +192,20 @@ def run(args: Namespace) -> int:
22 series=job.series,
23 architecture=host_architecture,
24 ) as instance:
25+ if job.snaps:
26+ for snap in job.snaps:
27+ emit.progress(f"Running `snap install {snap}`")
28+ install_from_store(
29+ executor=instance,
30+ snap_name=snap,
31+ channel="stable",
32+ classic=True,
33+ )
34+ run_cmd = ["bash", "--noprofile", "--norc", "-ec", job.run]
35 emit.progress("Running the job")
36- with emit.open_stream(f"Running {cmd}") as stream:
37+ with emit.open_stream(f"Running {run_cmd}") as stream:
38 proc = instance.execute_run(
39- cmd,
40+ run_cmd,
41 cwd=remote_cwd,
42 env=job.environment,
43 stdout=stream,
44diff --git a/lpcraft/commands/tests/test_run.py b/lpcraft/commands/tests/test_run.py
45index cf47f49..25ea37b 100644
46--- a/lpcraft/commands/tests/test_run.py
47+++ b/lpcraft/commands/tests/test_run.py
48@@ -872,3 +872,90 @@ class TestRun(CommandBaseTestCase):
49 self.assertEqual(1, result.exit_code)
50 [error] = result.errors
51 self.assertIn("/target", str(error))
52+
53+ @patch("lpcraft.commands.run.get_provider")
54+ @patch("lpcraft.commands.run.get_host_architecture", return_value="amd64")
55+ def test_install_snaps(
56+ self, mock_get_host_architecture, mock_get_provider
57+ ):
58+ launcher = Mock(spec=launch)
59+ provider = self.makeLXDProvider(lxd_launcher=launcher)
60+ mock_get_provider.return_value = provider
61+ execute_run = launcher.return_value.execute_run
62+ execute_run.return_value = subprocess.CompletedProcess([], 0)
63+ config = dedent(
64+ """
65+ pipeline:
66+ - test
67+
68+ jobs:
69+ test:
70+ series: focal
71+ architectures: amd64
72+ run: tox
73+ snaps: [chromium, firefox]
74+ """
75+ )
76+ Path(".launchpad.yaml").write_text(config)
77+
78+ result = self.run_command("run")
79+
80+ self.assertEqual(0, result.exit_code)
81+ self.assertEqual(
82+ [
83+ call(
84+ [
85+ "snap",
86+ "download",
87+ "chromium",
88+ "--channel=stable",
89+ "--basename=chromium",
90+ "--target-directory=/tmp",
91+ ],
92+ check=True,
93+ capture_output=True,
94+ ),
95+ call(
96+ [
97+ "snap",
98+ "install",
99+ "/tmp/chromium.snap",
100+ "--classic",
101+ "--dangerous",
102+ ],
103+ check=True,
104+ capture_output=True,
105+ ),
106+ call(
107+ [
108+ "snap",
109+ "download",
110+ "firefox",
111+ "--channel=stable",
112+ "--basename=firefox",
113+ "--target-directory=/tmp",
114+ ],
115+ check=True,
116+ capture_output=True,
117+ ),
118+ call(
119+ [
120+ "snap",
121+ "install",
122+ "/tmp/firefox.snap",
123+ "--classic",
124+ "--dangerous",
125+ ],
126+ check=True,
127+ capture_output=True,
128+ ),
129+ call(
130+ ["bash", "--noprofile", "--norc", "-ec", "tox"],
131+ cwd=Path("/root/project"),
132+ env=None,
133+ stdout=27,
134+ stderr=27,
135+ ),
136+ ],
137+ execute_run.call_args_list,
138+ )
139diff --git a/lpcraft/config.py b/lpcraft/config.py
140index 97c582b..fc49f85 100644
141--- a/lpcraft/config.py
142+++ b/lpcraft/config.py
143@@ -53,6 +53,7 @@ class Job(ModelConfigDefaults):
144 run: Optional[StrictStr]
145 environment: Optional[Dict[str, Optional[str]]]
146 output: Optional[Output]
147+ snaps: Optional[List[StrictStr]]
148
149 @pydantic.validator("architectures", pre=True)
150 def validate_architectures(
151diff --git a/lpcraft/tests/test_config.py b/lpcraft/tests/test_config.py
152index 67a9e0e..0efd32d 100644
153--- a/lpcraft/tests/test_config.py
154+++ b/lpcraft/tests/test_config.py
155@@ -212,3 +212,38 @@ class TestConfig(TestCase):
156 Config.load,
157 path,
158 )
159+
160+ def test_load_snaps(self):
161+ path = self.create_config(
162+ dedent(
163+ """
164+ pipeline:
165+ - test
166+
167+ jobs:
168+ test:
169+ series: focal
170+ architectures: amd64
171+ snaps: [chromium, firefox]
172+ """
173+ )
174+ )
175+ config = Config.load(path)
176+ self.assertEqual(["chromium", "firefox"], config.jobs["test"][0].snaps)
177+
178+ def test_load_config_without_snaps(self):
179+ path = self.create_config(
180+ dedent(
181+ """
182+ pipeline:
183+ - test
184+
185+ jobs:
186+ test:
187+ series: focal
188+ architectures: amd64
189+ """
190+ )
191+ )
192+ config = Config.load(path)
193+ self.assertEqual(None, config.jobs["test"][0].snaps)

Subscribers

People subscribed via source and target branches