Skip to content

Commit 982111d

Browse files
nichmorruben-arts
andauthored
feat: store intermediate_recipe.yaml in debugdir (#410)
Co-authored-by: Ruben Arts <ruben.arts@hotmail.com>
1 parent 3017bbe commit 982111d

File tree

5 files changed

+207
-6
lines changed

5 files changed

+207
-6
lines changed

crates/pixi-build-backend/src/generated_recipe.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pub trait GenerateRecipe {
8989
}
9090

9191
pub trait BackendConfig: DeserializeOwned + Clone {
92-
/// At least debug dir should be provided by the backend config
92+
/// Debug dir provided by the backend config
9393
fn debug_dir(&self) -> Option<&Path>;
9494

9595
/// Merge this configuration with a target-specific configuration.

crates/pixi-build-backend/src/intermediate_backend.rs

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ use crate::{
6565
utils::TemporaryRenderedRecipe,
6666
};
6767

68+
use fs_err::tokio as tokio_fs;
69+
6870
#[derive(Debug, Default, Deserialize)]
6971
#[serde(rename_all = "kebab-case")]
7072
pub struct IntermediateBackendConfig {
@@ -415,6 +417,27 @@ where
415417
},
416418
);
417419

420+
let directories = output_directory(
421+
if number_of_outputs == 1 {
422+
OneOrMultipleOutputs::Single(discovered_output.name.clone())
423+
} else {
424+
OneOrMultipleOutputs::OneOfMany(discovered_output.name.clone())
425+
},
426+
params.work_directory.clone(),
427+
&named_source.path,
428+
);
429+
// Save intermediate recipe in the debug dir
430+
let debug_path = directories.work_dir.join("recipe.yaml");
431+
tokio_fs::create_dir_all(&directories.work_dir)
432+
.await
433+
.into_diagnostic()?;
434+
tokio_fs::write(
435+
&debug_path,
436+
generated_recipe.recipe.to_yaml_pretty().into_diagnostic()?,
437+
)
438+
.await
439+
.into_diagnostic()?;
440+
418441
let mut output = Output {
419442
recipe,
420443
build_configuration: BuildConfiguration {
@@ -764,6 +787,28 @@ where
764787
},
765788
);
766789

790+
let directories = output_directory(
791+
if number_of_outputs == 1 {
792+
OneOrMultipleOutputs::Single(discovered_output.name.clone())
793+
} else {
794+
OneOrMultipleOutputs::OneOfMany(discovered_output.name.clone())
795+
},
796+
params.work_directory.clone(),
797+
&named_source.path,
798+
);
799+
800+
// Save intermediate recipe in the debug dir
801+
let debug_path = directories.work_dir.join("recipe.yaml");
802+
tokio_fs::create_dir_all(&directories.work_dir)
803+
.await
804+
.into_diagnostic()?;
805+
tokio_fs::write(
806+
&debug_path,
807+
generated_recipe.recipe.to_yaml_pretty().into_diagnostic()?,
808+
)
809+
.await
810+
.into_diagnostic()?;
811+
767812
let mut output = Output {
768813
recipe,
769814
build_configuration: BuildConfiguration {
@@ -912,7 +957,7 @@ where
912957
variant_config.variants.append(&mut param_variants);
913958

914959
// Construct the intermediate recipe
915-
let recipe = self.generate_recipe.generate_recipe(
960+
let generated_recipe = self.generate_recipe.generate_recipe(
916961
&self.project_model,
917962
&config,
918963
self.source_dir.clone(),
@@ -928,7 +973,13 @@ where
928973
let recipe_path = self.source_dir.join(&self.manifest_rel_path);
929974
let named_source = Source {
930975
name: self.manifest_rel_path.display().to_string(),
931-
code: Arc::from(recipe.recipe.to_yaml_pretty().into_diagnostic()?.as_str()),
976+
code: Arc::from(
977+
generated_recipe
978+
.recipe
979+
.to_yaml_pretty()
980+
.into_diagnostic()?
981+
.as_str(),
982+
),
932983
path: recipe_path.clone(),
933984
};
934985

@@ -962,6 +1013,8 @@ where
9621013

9631014
let mut subpackages = HashMap::new();
9641015
let mut outputs = Vec::new();
1016+
1017+
let num_of_outputs = discovered_outputs.len();
9651018
for discovered_output in discovered_outputs {
9661019
let variant = discovered_output.used_vars;
9671020
let hash = HashInfo::from_variant(&variant, &discovered_output.noarch_type);
@@ -993,6 +1046,28 @@ where
9931046

9941047
let build_number = recipe.build().number;
9951048

1049+
let directories = output_directory(
1050+
if num_of_outputs == 1 {
1051+
OneOrMultipleOutputs::Single(discovered_output.name.clone())
1052+
} else {
1053+
OneOrMultipleOutputs::OneOfMany(discovered_output.name.clone())
1054+
},
1055+
params.work_directory.clone(),
1056+
&named_source.path,
1057+
);
1058+
1059+
// Save intermediate recipe in the debug dir
1060+
let debug_path = directories.work_dir.join("recipe.yaml");
1061+
tokio_fs::create_dir_all(&directories.work_dir)
1062+
.await
1063+
.into_diagnostic()?;
1064+
tokio_fs::write(
1065+
&debug_path,
1066+
generated_recipe.recipe.to_yaml_pretty().into_diagnostic()?,
1067+
)
1068+
.await
1069+
.into_diagnostic()?;
1070+
9961071
subpackages.insert(
9971072
recipe.package().name().clone(),
9981073
PackageIdentifier {
@@ -1103,7 +1178,7 @@ where
11031178

11041179
Ok(CondaOutputsResult {
11051180
outputs,
1106-
input_globs: recipe.metadata_input_globs,
1181+
input_globs: generated_recipe.metadata_input_globs,
11071182
})
11081183
}
11091184

@@ -1194,6 +1269,18 @@ where
11941269
recipe_path,
11951270
);
11961271

1272+
// Save intermediate recipe in the debug dir
1273+
let debug_path = directories.work_dir.join("recipe.yaml");
1274+
tokio_fs::create_dir_all(&directories.work_dir)
1275+
.await
1276+
.into_diagnostic()?;
1277+
tokio_fs::write(
1278+
&debug_path,
1279+
recipe.recipe.to_yaml_pretty().into_diagnostic()?,
1280+
)
1281+
.await
1282+
.into_diagnostic()?;
1283+
11971284
let tool_config = Configuration::builder()
11981285
.with_opt_cache_dir(self.cache_dir.clone())
11991286
.with_logging_output_handler(self.logging_output_handler.clone())
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "minimal-package",
3+
"version": "1.0.0",
4+
"description": null,
5+
"authors": null,
6+
"license": null,
7+
"license_file": null,
8+
"readme": null,
9+
"homepage": null,
10+
"repository": null,
11+
"documentation": null,
12+
"targets": {
13+
"default_target": {
14+
"host_dependencies": {},
15+
"build_dependencies": {},
16+
"run_dependencies": {
17+
"python": {
18+
"binary": {
19+
"version": ">=3.8"
20+
}
21+
}
22+
}
23+
}
24+
}
25+
}

crates/pixi-build-backend/tests/integration/protocol.rs

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ use imp::TestGenerateRecipe;
55
use pixi_build_backend::{intermediate_backend::IntermediateBackend, protocol::Protocol};
66
use pixi_build_types::{
77
ChannelConfiguration, PlatformAndVirtualPackages,
8-
procedures::{conda_build_v0::CondaBuildParams, conda_metadata::CondaMetadataParams},
8+
procedures::{
9+
conda_build_v0::CondaBuildParams,
10+
conda_build_v1::{CondaBuildV1Output, CondaBuildV1Params},
11+
conda_metadata::CondaMetadataParams,
12+
},
913
};
1014
use rattler_build::console_utils::LoggingOutputHandler;
11-
use rattler_conda_types::Platform;
15+
use rattler_conda_types::{ChannelUrl, Platform};
1216
use serde_json::json;
1317
use tempfile::TempDir;
1418
use url::Url;
@@ -201,3 +205,78 @@ async fn test_conda_build() {
201205
".packages[0].subdir" => "[redacted]",
202206
});
203207
}
208+
209+
#[tokio::test]
210+
async fn test_conda_build_v1() {
211+
let tmp_dir = TempDir::new().unwrap();
212+
let tmp_dir_path = tmp_dir.path().to_path_buf();
213+
214+
let pixi_manifest = tmp_dir_path.join("pixi.toml");
215+
let build_dir = tmp_dir_path.join("build");
216+
217+
// Load a model from JSON
218+
let original_model = load_project_model_from_json("minimal_project_model_for_build.json");
219+
220+
// Serialize it back to JSON
221+
let project_model_v1 = convert_test_model_to_project_model_v1(original_model);
222+
223+
// save the pixi.toml file to a temporary location
224+
fs_err::write(&pixi_manifest, toml::to_string(&project_model_v1).unwrap()).unwrap();
225+
226+
let channel_url = Url::parse("https://prefix.dev/conda-forge").unwrap();
227+
228+
let channel_url = ChannelUrl::from(channel_url);
229+
230+
let build_params = CondaBuildV1Params {
231+
channels: vec![channel_url],
232+
233+
build_prefix: None,
234+
host_prefix: None,
235+
run_constraints: None,
236+
run_dependencies: None,
237+
run_exports: None,
238+
output: CondaBuildV1Output {
239+
name: "minimal-package".parse().unwrap(),
240+
version: None,
241+
build: None,
242+
subdir: Platform::current(),
243+
variant: Default::default(),
244+
},
245+
work_directory: build_dir.clone(),
246+
output_directory: None,
247+
editable: None,
248+
};
249+
250+
let some_config = json!({
251+
"debug-dir": "some_debug_dir",
252+
});
253+
254+
let target_config = Default::default();
255+
256+
let intermediate_backend: IntermediateBackend<TestGenerateRecipe> = IntermediateBackend::new(
257+
pixi_manifest.clone(),
258+
Some(tmp_dir_path.clone()),
259+
project_model_v1,
260+
Arc::default(),
261+
some_config,
262+
target_config,
263+
LoggingOutputHandler::default(),
264+
None,
265+
)
266+
.unwrap();
267+
268+
let conda_build_result = intermediate_backend
269+
.conda_build_v1(build_params)
270+
.await
271+
.unwrap();
272+
273+
insta::assert_yaml_snapshot!(conda_build_result, {
274+
".output_file" => "[redacted]",
275+
".build" => "[redacted]",
276+
".subdir" => "[redacted]",
277+
});
278+
279+
// we also want to assert that we put intermediate_recipe.yaml in the debug dir
280+
281+
assert!(build_dir.join("work").join("recipe.yaml").exists());
282+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
source: crates/pixi-build-backend/tests/integration/protocol.rs
3+
expression: conda_build_result
4+
---
5+
output_file: "[redacted]"
6+
input_globs: []
7+
name: minimal-package
8+
version: 1.0.0
9+
build: "[redacted]"
10+
subdir: "[redacted]"

0 commit comments

Comments
 (0)