Add payload_manifest_kind and payload_manifest_mount_name accessors to StagedLinuxRustPayloadRole
Intent: Give the Rust orchestrator model first-class methods that return the canonical manifest identity strings for each payload role, enabling callers to pass these values to the Nix build environment rather than relying on downstream inference.
Affected files: crates/pikaci/src/model.rs
Evidence
@@ -220,6 +220,20 @@ impl StagedLinuxRustPayloadRole {
+ pub fn payload_manifest_kind(self) -> &'static str {
+ match self {
+ Self::WorkspaceDeps => "staged_linux_workspace_deps_v1",
+ Self::WorkspaceBuild => "staged_linux_workspace_build_v1",
+ }
+ }
+
+ pub fn payload_manifest_mount_name(self) -> &'static str {
+ match self {
+ Self::WorkspaceDeps => "workspace_deps_root",
+ Self::WorkspaceBuild => "workspace_build_root",
+ }
+ }
Two new pub fn methods are added to StagedLinuxRustPayloadRole at crates/pikaci/src/model.rs:223-234.
payload_manifest_kind returns the schema-level kind string (staged_linux_workspace_deps_v1 or staged_linux_workspace_build_v1).
payload_manifest_mount_name returns the mount name used in the manifest's mounts array (workspace_deps_root or workspace_build_root).
Both methods take self by copy (the enum is Copy) and return &'static str, keeping them zero-cost. These strings are the single source of truth that the Nix derivations will now consume instead of re-deriving them.
Add unit tests for the new accessor methods
Intent: Lock in the expected string values for both enum variants so that any accidental rename or mismatch between the Rust model and the Nix layer is caught at `cargo test` time.
Affected files: crates/pikaci/src/model.rs
Evidence
@@ -1085,6 +1099,14 @@ mod tests {
+ assert_eq!(
+ roles[0].payload_manifest_kind(),
+ "staged_linux_workspace_deps_v1"
+ );
+ assert_eq!(
+ roles[0].payload_manifest_mount_name(),
+ "workspace_deps_root"
+ );
@@ -1095,6 +1117,14 @@ mod tests {
+ assert_eq!(
+ roles[1].payload_manifest_kind(),
+ "staged_linux_workspace_build_v1"
+ );
+ assert_eq!(
+ roles[1].payload_manifest_mount_name(),
+ "workspace_build_root"
+ );
The existing test that exercises StagedLinuxRustPayloadRole ordering and path methods is extended with four new assert_eq! calls (two per variant). These appear at crates/pikaci/src/model.rs:1102-1108 and crates/pikaci/src/model.rs:1120-1126.
The assertions verify:
| Variant | payload_manifest_kind() | payload_manifest_mount_name() |
WorkspaceDeps (roles[0]) | staged_linux_workspace_deps_v1 | workspace_deps_root |
WorkspaceBuild (roles[1]) | staged_linux_workspace_build_v1 | workspace_build_root |
Declare manifest identity as environment variables in Nix derivations
Intent: Move the source of truth for each derivation's payload kind, mount name, and guest path from runtime heuristics into explicit Nix-level attributes, so the values are visible in the build graph and reviewable without reading the Python script.
Affected files: nix/ci/linux-rust.nix
Evidence
@@ -1759,6 +1753,9 @@ rec {
+ PIKACI_PAYLOAD_MANIFEST_KIND = "staged_linux_workspace_deps_v1";
+ PIKACI_PAYLOAD_MANIFEST_MOUNT_NAME = "workspace_deps_root";
+ PIKACI_PAYLOAD_MANIFEST_GUEST_PATH = "/staged/linux-rust/workspace-deps";
@@ -1771,6 +1768,9 @@ rec {
+ PIKACI_PAYLOAD_MANIFEST_KIND = "staged_linux_workspace_build_v1";
+ PIKACI_PAYLOAD_MANIFEST_MOUNT_NAME = "workspace_build_root";
+ PIKACI_PAYLOAD_MANIFEST_GUEST_PATH = "/staged/linux-rust/workspace-build";
Three new attributes are added to each of the two crane-based derivations in nix/ci/linux-rust.nix:
WorkspaceDeps derivation (~line 1755):
PIKACI_PAYLOAD_MANIFEST_KIND = "staged_linux_workspace_deps_v1";
PIKACI_PAYLOAD_MANIFEST_MOUNT_NAME = "workspace_deps_root";
PIKACI_PAYLOAD_MANIFEST_GUEST_PATH = "/staged/linux-rust/workspace-deps";
WorkspaceBuild derivation (~line 1770):
PIKACI_PAYLOAD_MANIFEST_KIND = "staged_linux_workspace_build_v1";
PIKACI_PAYLOAD_MANIFEST_MOUNT_NAME = "workspace_build_root";
PIKACI_PAYLOAD_MANIFEST_GUEST_PATH = "/staged/linux-rust/workspace-build";
Because these are set as top-level derivation attributes, Nix automatically exports them as environment variables during the build, making them available to the postInstall phase that runs the manifest-generation script.
Consume declared identity in the manifest-generation Python script
Intent: Replace the filesystem-probing heuristic with simple environment-variable reads, making the script purely data-driven and removing the conditional mount-construction logic.
Affected files: nix/ci/linux-rust.nix
Evidence
@@ -109,13 +109,18 @@ let
+ export PIKACI_PAYLOAD_MANIFEST_KIND
+ export PIKACI_PAYLOAD_MANIFEST_MOUNT_NAME
+ export PIKACI_PAYLOAD_MANIFEST_GUEST_PATH
@@ -131,25 +136,14 @@ if os.environ.get("PIKACI_PAYLOAD_MANIFEST_HAS_LIB") == "1":
-kind = "staged_linux_workspace_build_v1" if (out / "bin").is_dir() else "staged_linux_workspace_deps_v1"
+kind = os.environ["PIKACI_PAYLOAD_MANIFEST_KIND"]
+mount_name = os.environ["PIKACI_PAYLOAD_MANIFEST_MOUNT_NAME"]
+guest_path = os.environ["PIKACI_PAYLOAD_MANIFEST_GUEST_PATH"]
@@ -131,25 +136,14 @@
-if kind == "staged_linux_workspace_deps_v1":
- mounts.append(
- {
- "name": "workspace_deps_root",
- ...
- }
- )
-elif kind == "staged_linux_workspace_build_v1":
- mounts.append(
- {
- "name": "workspace_build_root",
- ...
- }
- )
+mounts = [
+ {
+ "name": mount_name,
+ "relative_path": ".",
+ "guest_path": guest_path,
+ "read_only": True,
+ }
+]
The inline Python script undergoes two simplifications:
-
Kind detection — The old heuristic "staged_linux_workspace_build_v1" if (out / "bin").is_dir() else "staged_linux_workspace_deps_v1" is replaced by a direct os.environ["PIKACI_PAYLOAD_MANIFEST_KIND"] read. This eliminates a fragile assumption that the presence of a bin/ directory determines the payload role.
-
Mount construction — The if/elif branches that hard-coded different name and guest_path values per kind are collapsed into a single, unconditional mount entry that reads mount_name and guest_path from the environment. This removes ~15 lines of branching logic and makes the script agnostic to which payload role it is building.
Three export statements are added to the surrounding bash wrapper to ensure the variables propagate into the Python subprocess's environment. The net effect is a reduction of about 11 lines in the Nix file while making the manifest generation deterministic from declared inputs rather than inferred filesystem state.