Merge ~jugmac00/lpci:fix-run-clean into lpci:main

Proposed by Jürgen Gmach
Status: Merged
Merged at revision: 96275f5072e76f857f692ae5ae62931bad293248
Proposed branch: ~jugmac00/lpci:fix-run-clean
Merge into: lpci:main
Diff against target: 248 lines (+101/-105)
2 files modified
lpcraft/commands/run.py (+54/-57)
lpcraft/commands/tests/test_run.py (+47/-48)
Reviewer Review Type Date Requested Status
Guruprasad Approve
Review via email: mp+428857@code.launchpad.net

Commit message

Fix `lpcraft run --clean`

To post a comment you must log in.
Revision history for this message
Guruprasad (lgp171188) :
Revision history for this message
Guruprasad (lgp171188) :
review: Approve
Revision history for this message
Jürgen Gmach (jugmac00) wrote :

Thanks for the review!

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 8012ad4..3c31054 100644
3--- a/lpcraft/commands/run.py
4+++ b/lpcraft/commands/run.py
5@@ -634,69 +634,66 @@ class RunCommand(BaseCommand):
6
7 provider = get_provider()
8 provider.ensure_provider_is_available()
9- launched_instances = []
10
11 secrets = {}
12 if args.secrets_file:
13 with open(args.secrets_file) as f:
14 content = f.read()
15 secrets = yaml.safe_load(content)
16-
17- try:
18- for stage in config.pipeline:
19- stage_failed = False
20- for job_name in stage:
21- try:
22- jobs = config.jobs.get(job_name, [])
23- if not jobs:
24- raise CommandError(
25- f"No job definition for {job_name!r}"
26- )
27- for job_index, job in enumerate(jobs):
28- launched_instances.append(
29- _get_job_instance_name(provider, job)
30- )
31- # we prefer package repositories via CLI more
32- # so they need to come first
33- # also see sources.list(5)
34- package_repositories = args.package_repositories
35- for group in job.package_repositories:
36- for repository in group.sources_list_lines():
37- package_repositories.append(repository)
38- _run_job(
39- config,
40- job_name,
41- job_index,
42- provider,
43- args.output_directory,
44- replace_package_repositories=(
45- args.apt_replace_repositories
46- + args.replace_package_repositories
47- ),
48- package_repositories=package_repositories,
49- env_from_cli=args.set_env,
50- plugin_settings=args.plugin_setting,
51- secrets=secrets,
52- )
53- except CommandError as e:
54- if len(stage) == 1:
55- # Single-job stage, so just reraise this
56- # in order to get simpler error messages.
57- raise
58- else:
59- emit.error(e)
60- stage_failed = True
61- if stage_failed:
62- raise CommandError(
63- f"Some jobs in {stage} failed; stopping.", retcode=1
64- )
65- finally:
66- if args.clean:
67- cwd = Path.cwd()
68- provider.clean_project_environments(
69- project_name=cwd.name,
70- project_path=cwd,
71- instances=launched_instances,
72+ for stage in config.pipeline:
73+ stage_failed = False
74+ for job_name in stage:
75+ try:
76+ jobs = config.jobs.get(job_name, [])
77+ if not jobs:
78+ raise CommandError(
79+ f"No job definition for {job_name!r}"
80+ )
81+ for job_index, job in enumerate(jobs):
82+ # we prefer package repositories via CLI more
83+ # so they need to come first
84+ # also see sources.list(5)
85+ package_repositories = args.package_repositories
86+ for group in job.package_repositories:
87+ for repository in group.sources_list_lines():
88+ package_repositories.append(repository)
89+ _run_job(
90+ config,
91+ job_name,
92+ job_index,
93+ provider,
94+ args.output_directory,
95+ replace_package_repositories=(
96+ args.apt_replace_repositories
97+ + args.replace_package_repositories
98+ ),
99+ package_repositories=package_repositories,
100+ env_from_cli=args.set_env,
101+ plugin_settings=args.plugin_setting,
102+ secrets=secrets,
103+ )
104+
105+ except CommandError as e:
106+ if len(stage) == 1:
107+ # Single-job stage, so just reraise this
108+ # in order to get simpler error messages.
109+ raise
110+ else:
111+ emit.error(e)
112+ stage_failed = True
113+ finally:
114+ if args.clean:
115+ cwd = Path.cwd()
116+ provider.clean_project_environments(
117+ project_name=cwd.name,
118+ project_path=cwd,
119+ instances=[
120+ _get_job_instance_name(provider, job),
121+ ],
122+ )
123+ if stage_failed:
124+ raise CommandError(
125+ f"Some jobs in {stage} failed; stopping.", retcode=1
126 )
127 return 0
128
129diff --git a/lpcraft/commands/tests/test_run.py b/lpcraft/commands/tests/test_run.py
130index e06a28e..93c5fcd 100644
131--- a/lpcraft/commands/tests/test_run.py
132+++ b/lpcraft/commands/tests/test_run.py
133@@ -2113,46 +2113,20 @@ class TestRun(RunBaseTestCase):
134 expected_instance_names = self.get_instance_names(
135 provider, ("focal", "bionic")
136 )
137- mock_clean_project_environments.assert_called_with(
138- project_name=self.tmp_project_path.name,
139- project_path=self.tmp_project_path,
140- instances=expected_instance_names,
141- )
142-
143- @patch("lpcraft.commands.run.get_provider")
144- @patch("lpcraft.commands.run.get_host_architecture", return_value="amd64")
145- @patch("lpcraft.providers._lxd.LXDProvider.clean_project_environments")
146- def test_clean_flag_cleans_up_even_when_there_are_errors(
147- self,
148- mock_clean_project_environments,
149- mock_get_host_architecture,
150- mock_get_provider,
151- ):
152- mock_get_provider.return_value = makeLXDProvider()
153- # There are no jobs defined. So there will be an error.
154- config = dedent(
155- """
156- pipeline:
157- - test
158-
159- jobs: {}
160- """
161- )
162- Path(".launchpad.yaml").write_text(config)
163-
164- result = self.run_command("run", "--clean")
165-
166- self.assertThat(
167- result,
168- MatchesStructure.byEquality(
169- exit_code=1,
170- errors=[CommandError("No job definition for 'test'")],
171- ),
172- )
173- mock_clean_project_environments.assert_called_with(
174- project_name=self.tmp_project_path.name,
175- project_path=self.tmp_project_path,
176- instances=[],
177+ self.assertEqual(
178+ mock_clean_project_environments.call_args_list,
179+ [
180+ call(
181+ project_name=self.tmp_project_path.name,
182+ project_path=self.tmp_project_path,
183+ instances=[expected_instance_names[0]],
184+ ),
185+ call(
186+ project_name=self.tmp_project_path.name,
187+ project_path=self.tmp_project_path,
188+ instances=[expected_instance_names[1]],
189+ ),
190+ ],
191 )
192
193 @patch("lpcraft.commands.run._run_job")
194@@ -2216,10 +2190,25 @@ class TestRun(RunBaseTestCase):
195 expected_instance_names = self.get_instance_names(
196 provider, ("focal", "bionic", "jammy")
197 )
198- mock_clean_project_environments.assert_called_with(
199- project_name=self.tmp_project_path.name,
200- project_path=self.tmp_project_path,
201- instances=expected_instance_names,
202+ self.assertEqual(
203+ mock_clean_project_environments.call_args_list,
204+ [
205+ call(
206+ project_name=self.tmp_project_path.name,
207+ project_path=self.tmp_project_path,
208+ instances=[expected_instance_names[0]],
209+ ),
210+ call(
211+ project_name=self.tmp_project_path.name,
212+ project_path=self.tmp_project_path,
213+ instances=[expected_instance_names[1]],
214+ ),
215+ call(
216+ project_name=self.tmp_project_path.name,
217+ project_path=self.tmp_project_path,
218+ instances=[expected_instance_names[2]],
219+ ),
220+ ],
221 )
222
223 @patch("lpcraft.commands.run._run_job")
224@@ -2269,10 +2258,20 @@ class TestRun(RunBaseTestCase):
225 provider,
226 ("focal", "bionic"),
227 )
228- mock_clean_project_environments.assert_called_with(
229- project_name=self.tmp_project_path.name,
230- project_path=self.tmp_project_path,
231- instances=expected_instance_names,
232+ self.assertEqual(
233+ mock_clean_project_environments.call_args_list,
234+ [
235+ call(
236+ project_name=self.tmp_project_path.name,
237+ project_path=self.tmp_project_path,
238+ instances=[expected_instance_names[0]],
239+ ),
240+ call(
241+ project_name=self.tmp_project_path.name,
242+ project_path=self.tmp_project_path,
243+ instances=[expected_instance_names[1]],
244+ ),
245+ ],
246 )
247
248 @patch("lpcraft.commands.run.get_provider")

Subscribers

People subscribed via source and target branches