Skip to content

Commit 9ffa6ce

Browse files
committed
Split recipe processing in a separate function
1 parent b45b369 commit 9ffa6ce

File tree

1 file changed

+133
-65
lines changed

1 file changed

+133
-65
lines changed

conda_build/_rattler_build/compat.py

Lines changed: 133 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
from pathlib import Path
66

77
from conda.base.context import context
8+
from rattler_build.build_result import BuildResult
89
from rattler_build.progress import RichProgressCallback
910
from rattler_build.render import RenderConfig
1011
from rattler_build.stage0 import Stage0Recipe
1112
from rattler_build.tool_config import PlatformConfig, ToolConfiguration
1213
from rattler_build.variant_config import VariantConfig
1314

1415
from ..config import CondaPkgFormat, Config
16+
from ..exceptions import CondaBuildUserError
1517

1618
CONFIG_FILES = {"conda_build_config.yaml", "variants.yaml"}
1719

@@ -87,28 +89,126 @@ def check_arguments_rattler(
8789
)
8890

8991

92+
def process_recipes(
93+
recipes: list[str],
94+
variant_config: VariantConfig,
95+
render_config: RenderConfig,
96+
tool_config: ToolConfiguration,
97+
command: str,
98+
output_dir: str,
99+
channels: list[str],
100+
show_logs: bool,
101+
no_build_id: bool,
102+
package_format: str,
103+
no_include_recipe: bool,
104+
debug: bool,
105+
) -> list[BuildResult]:
106+
import yaml
107+
108+
results: list = []
109+
succeeded: list[str] = []
110+
failed: dict[str, str] = {}
111+
112+
for recipe_path in recipes:
113+
recipe_path_str = str(recipe_path)
114+
try:
115+
# load the recipe file
116+
try:
117+
recipe = Stage0Recipe.from_file(Path(recipe_path))
118+
except Exception as e:
119+
raise CondaBuildUserError(
120+
f"Failed to process recipe {recipe_path}: {str(e)}"
121+
)
122+
123+
# render the recipe
124+
try:
125+
rendered = recipe.render(variant_config, render_config)
126+
except Exception as e:
127+
raise CondaBuildUserError(
128+
f"Failed to render recipe {recipe_path}: {str(e)}"
129+
)
130+
131+
if command == "render":
132+
data = rendered[0].recipe.to_dict()
133+
print(yaml.safe_dump(data, indent=2, sort_keys=False))
134+
succeeded.append(recipe_path_str)
135+
continue
136+
137+
# build all rendered variants
138+
for i, variant in enumerate(rendered, 1):
139+
print(
140+
f"\n🔨 Building variant {i}/{len(rendered)} "
141+
f"for recipe {recipe_path}"
142+
)
143+
144+
try:
145+
with RichProgressCallback(show_logs=show_logs) as progress_callback:
146+
result = variant.run_build(
147+
tool_config=tool_config,
148+
output_dir=output_dir,
149+
channels=channels,
150+
progress_callback=progress_callback,
151+
no_build_id=no_build_id,
152+
package_format=package_format,
153+
no_include_recipe=no_include_recipe,
154+
debug=debug,
155+
)
156+
results.append(result)
157+
except Exception as e:
158+
print(f"❌ Build failed for recipe {recipe_path}: {str(e)}")
159+
raise
160+
161+
# if all variants built without raising, mark recipe as succeeded
162+
succeeded.append(recipe_path_str)
163+
164+
except Exception as e:
165+
# catch any failure for this recipe and continue with the next
166+
failed[recipe_path_str] = str(e)
167+
print(f"Skipping remaining work for recipe {recipe_path}.")
168+
169+
# summary
170+
print("\n=== Build summary ===")
171+
if succeeded:
172+
print("Succeeded:")
173+
for path in succeeded:
174+
print(f" - {path}")
175+
else:
176+
print("Succeeded: none")
177+
178+
if failed:
179+
print("\nFailed:")
180+
for path, error in failed.items():
181+
print(f" - {path}: {error}")
182+
else:
183+
print("\nFailed: none")
184+
185+
return results
186+
187+
90188
def run_rattler(command: str, parsed_args: argparse.Namespace, config: Config) -> int:
91189
"""Run rattler-build for v1 recipes"""
92190
if command not in ("build", "render", "debug"):
93191
raise ValueError(f"Unrecognized subcommand: {command}")
94192

95193
# Initialize configuration defaults
96-
test_strategy = None
97-
skip_existing = None
98-
noarch_build_platform = None
99-
channel_priority = None
100-
output_dir = config.croot
101-
no_include_recipe = False
102-
no_build_id = False
103-
package_format = None
104-
debug = False
105-
channels = []
106-
extra_context = {}
107-
show_logs = not parsed_args.quiet
108-
target_platform = config.variant.get("host_platform", config.subdir)
109-
build_platform = config.variant.get("build_platform", config.subdir)
110-
host_platform = config.variant.get("target_platform", config.subdir)
111-
noarch_build_platform = config.variant.get("noarch_build_platform", config.subdir)
194+
test_strategy: str | None = None
195+
skip_existing: bool | None = None
196+
noarch_build_platform: str | None = None
197+
channel_priority: str | None = None
198+
output_dir: str = config.croot
199+
no_include_recipe: bool = False
200+
no_build_id: bool = False
201+
package_format: str | None = None
202+
debug: bool = False
203+
channels: list[str] = []
204+
extra_context: dict[str] = {}
205+
show_logs: bool = getattr(parsed_args, "quiet", False) is False
206+
target_platform: str = config.variant.get("host_platform", config.subdir)
207+
build_platform: str = config.variant.get("build_platform", config.subdir)
208+
host_platform: str = config.variant.get("target_platform", config.subdir)
209+
noarch_build_platform: str = config.variant.get(
210+
"noarch_build_platform", config.subdir
211+
)
112212

113213
# TODO: investigate why is config.channel_urls
114214
# does not pick up condarc settings, need to use context.channels
@@ -169,7 +269,7 @@ def run_rattler(command: str, parsed_args: argparse.Namespace, config: Config) -
169269
# TODO: output_name does not exist in python bindings
170270
# if parsed_args.output_id:
171271
# cmd.extend(["--output-name", parsed_args.output_id])
172-
elif command == "build":
272+
if command == "build":
173273
if parsed_args.extra_meta:
174274
extra_context.update(parsed_args.extra_meta)
175275
if parsed_args.output_folder:
@@ -204,7 +304,7 @@ def run_rattler(command: str, parsed_args: argparse.Namespace, config: Config) -
204304
for variant in config_files:
205305
variant_config = VariantConfig.from_file(variant)
206306

207-
# coon tool / platform / render configuration
307+
# common tool / platform / render configuration
208308
tool_config = ToolConfiguration(
209309
test_strategy=test_strategy,
210310
skip_existing=skip_existing,
@@ -223,51 +323,19 @@ def run_rattler(command: str, parsed_args: argparse.Namespace, config: Config) -
223323
extra_context=extra_context,
224324
)
225325

226-
# iterate over all recipes
227-
for recipe_path in recipes:
228-
recipe = Stage0Recipe.from_file(Path(recipe_path))
229-
230-
variant_config = None
231-
for variant_file in config_files:
232-
variant_config = VariantConfig.from_file(variant_file)
233-
234-
# render the recipe
235-
rendered = recipe.render(variant_config, render_config)
236-
237-
if command == "render":
238-
import json
239-
240-
data = rendered[0].recipe.to_dict()
241-
print(json.dumps(data, indent=2, sort_keys=True))
242-
continue
243-
244-
# build all rendered variants
245-
for i, variant in enumerate(rendered, 1):
246-
print(
247-
f"\n🔨 Building variant {i}/{len(rendered)} "
248-
f"for recipe {recipe_path}"
249-
)
326+
results = process_recipes(
327+
recipes=recipes,
328+
variant_config=variant_config,
329+
render_config=render_config,
330+
tool_config=tool_config,
331+
command=command,
332+
output_dir=output_dir,
333+
channels=channels,
334+
show_logs=show_logs,
335+
no_build_id=no_build_id,
336+
package_format=package_format,
337+
no_include_recipe=no_include_recipe,
338+
debug=debug,
339+
)
250340

251-
with RichProgressCallback(show_logs=show_logs) as progress_callback:
252-
result = variant.run_build(
253-
tool_config=tool_config,
254-
output_dir=output_dir,
255-
channels=channels,
256-
progress_callback=progress_callback,
257-
recipe_path=recipe_path,
258-
no_build_id=no_build_id,
259-
package_format=package_format,
260-
no_include_recipe=no_include_recipe,
261-
debug=debug,
262-
)
263-
results.append(result)
264-
265-
print("\n" + "=" * 60)
266-
print("Build Result:")
267-
print("=" * 60)
268-
print(f" Package: {result.name} {result.version}")
269-
print(f" Build string: {result.build_string}")
270-
print(f" Platform: {result.platform}")
271-
print(f" Build time: {result.build_time:.2f}s")
272-
273-
return 0
341+
return results

0 commit comments

Comments
 (0)