canic-host 0.70.6

Host-side build, install, deployment, and fleet-template library for Canic workspaces
Documentation
use super::operations::InstallPhaseOperation;
use crate::deployment_truth::{
    ArtifactTransportV1, ObservationStatusV1, StagingReceiptV1, VerifiedPostconditionV1,
    staging_receipt_evidence,
};
use crate::release_set::{RootReleaseSetManifest, stage_root_release_set};
use std::path::Path;

pub(super) struct StageReleaseSetOperation<'a> {
    icp_root: &'a Path,
    network: &'a str,
    root_canister_id: &'a str,
    manifest_path: &'a Path,
    manifest: RootReleaseSetManifest,
}

impl<'a> StageReleaseSetOperation<'a> {
    pub(super) const fn new(
        icp_root: &'a Path,
        network: &'a str,
        root_canister_id: &'a str,
        manifest_path: &'a Path,
        manifest: RootReleaseSetManifest,
    ) -> Self {
        Self {
            icp_root,
            network,
            root_canister_id,
            manifest_path,
            manifest,
        }
    }
}

impl InstallPhaseOperation for StageReleaseSetOperation<'_> {
    fn phase(&self) -> &'static str {
        "stage_release_set"
    }

    fn attempted_action(&self) -> &'static str {
        "stage root release set"
    }

    fn evidence(&self) -> Vec<String> {
        current_install_staging_evidence(self.root_canister_id, self.manifest_path, &self.manifest)
    }

    fn execute(&self) -> Result<(), Box<dyn std::error::Error>> {
        stage_root_release_set(
            self.icp_root,
            self.network,
            self.root_canister_id,
            &self.manifest,
        )
    }
}

pub(super) fn current_install_staging_evidence(
    root_canister_id: &str,
    manifest_path: &Path,
    manifest: &RootReleaseSetManifest,
) -> Vec<String> {
    let mut evidence = vec![
        format!("root_canister:{root_canister_id}"),
        format!("manifest_path:{}", manifest_path.display()),
        format!("release_version:{}", manifest.release_version),
    ];
    let staging_receipts = current_install_staging_receipts(root_canister_id, manifest);
    evidence.extend(staging_receipt_evidence(&staging_receipts));
    evidence
}

fn current_install_staging_receipts(
    root_canister_id: &str,
    manifest: &RootReleaseSetManifest,
) -> Vec<StagingReceiptV1> {
    manifest
        .entries
        .iter()
        .map(|entry| StagingReceiptV1 {
            schema_version: crate::deployment_truth::DEPLOYMENT_TRUTH_SCHEMA_VERSION,
            role: entry.role.clone(),
            artifact_identity: format!(
                "{}:{}:{}",
                entry.template_id, manifest.release_version, entry.payload_sha256_hex
            ),
            transport: ArtifactTransportV1::WasmStore,
            wasm_store_locator: Some(format!("root:{root_canister_id}:bootstrap")),
            prepared_chunk_hashes: entry.chunk_sha256_hex.clone(),
            published_chunk_count: entry.chunk_sha256_hex.len(),
            verified_postcondition: VerifiedPostconditionV1 {
                status: ObservationStatusV1::Observed,
                evidence: vec![
                    format!("payload_sha256:{}", entry.payload_sha256_hex),
                    format!("payload_size_bytes:{}", entry.payload_size_bytes),
                    format!("chunk_size_bytes:{}", entry.chunk_size_bytes),
                    format!("chunk_count:{}", entry.chunk_sha256_hex.len()),
                ],
            },
        })
        .collect()
}