Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/how-to/customize-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ runtime-name = "demo"
installer = "homebrew"
```

During automatic bootstrap, that stamp writes Constructor-compatible
`.installer.info` JSON into the managed prefix. Its `name`, `version`, and
`platform` fields identify the stamped distribution, while `type` contains the
configured `installer` value. This metadata identifies the distribution and
installer. It is not a launcher ownership record.

## Choose Runtime Packages

The selected source environment is the complete runtime package set.
Expand Down
6 changes: 6 additions & 0 deletions docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,12 @@ For the naming model behind `runtime-name`, `artifact-name`, `install-name`, and
Release workflows can override this with `cs build --installer INSTALLER` or
the GitHub Action `installer` input.

When configured, automatic bootstrap writes Constructor-compatible
`<prefix>/.installer.info` JSON with the exact fields `name`, `version`,
`platform`, and `type`. The configured `installer` value becomes `type`.
This metadata records how the prefix was distributed. Update and uninstall
code must not use it as a launcher ownership record.

`condarc-file`
: Optional path to a YAML condarc file. Relative paths are resolved from
the selected project manifest. The builder requires a YAML mapping and stamps
Expand Down
68 changes: 68 additions & 0 deletions src/constructor_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ use rattler_conda_types::{Platform, RepoDataRecord};

use crate::{install, policy};

#[derive(serde::Serialize)]
struct InstallerInfo<'a> {
name: &'a str,
version: &'a str,
platform: String,
#[serde(rename = "type")]
installer_type: &'a str,
}

pub(crate) fn write_prefix_metadata(
prefix: &Path,
lock_content: &str,
Expand Down Expand Up @@ -63,6 +72,44 @@ fn write_prefix_metadata_from_records(
})?;
eprintln!(" Wrote {}", policy::path_for_display(&explicit_path));

write_configured_installer_info(prefix, platform)?;

Ok(())
}

fn write_configured_installer_info(prefix: &Path, platform: Platform) -> miette::Result<()> {
let Some(installer_type) = policy::installer() else {
return Ok(());
};
write_installer_info(
prefix,
policy::runtime_name(),
policy::runtime_version(),
platform,
installer_type,
)
}

fn write_installer_info(
prefix: &Path,
name: &str,
version: &str,
platform: Platform,
installer_type: &str,
) -> miette::Result<()> {
let path = prefix.join(".installer.info");
let contents = serde_json::to_string(&InstallerInfo {
name,
version,
platform: platform.to_string(),
installer_type,
})
.into_diagnostic()
.context("failed to render Constructor installer metadata")?;
std::fs::write(&path, contents)
.into_diagnostic()
.with_context(|| format!("failed to write {}", policy::path_for_display(&path)))?;
eprintln!(" Wrote {}", policy::path_for_display(&path));
Ok(())
}

Expand Down Expand Up @@ -324,6 +371,27 @@ https://conda.anaconda.org/conda-forge/noarch/conda-spawn-1.0-0.conda#sha256:{SH
)),
"{explicit}"
);
assert!(!tmp.path().join(".installer.info").exists());
}

#[test]
fn test_write_installer_info_matches_constructor_json() {
let tmp = TempDir::new().unwrap();

write_installer_info(
tmp.path(),
"Demo Distribution",
"1.2.3",
Platform::Linux64,
"homebrew",
)
.unwrap();

let contents = std::fs::read_to_string(tmp.path().join(".installer.info")).unwrap();
assert_eq!(
contents,
r#"{"name":"Demo Distribution","version":"1.2.3","platform":"linux-64","type":"homebrew"}"#
);
}

#[test]
Expand Down
4 changes: 4 additions & 0 deletions src/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ pub(crate) fn delegate_executable() -> &'static str {
&runtime_data::current().header.delegate_executable
}

pub(crate) fn installer() -> Option<&'static str> {
runtime_data::current().header.installer.as_deref()
}

pub(crate) fn display_name() -> &'static str {
runtime_name()
}
Expand Down
Loading