hyperi_rustlib/deployment/mod.rs
1// Project: hyperi-rustlib
2// File: src/deployment/mod.rs
3// Purpose: Deployment contract validation and generation for Helm charts and Dockerfiles
4// Language: Rust
5//
6// License: BUSL-1.1
7// Copyright: (c) 2026 HYPERI PTY LIMITED
8
9//! Deployment contract validation and generation for Kubernetes/Helm/Docker.
10//!
11//! Apps provide ~20% customisation via [`DeploymentContract`]; this module
12//! generates ~80% boilerplate (Dockerfile, Helm chart, Compose fragment) and
13//! validates existing artifacts against the contract.
14//!
15//! # Architecture
16//!
17//! ```text
18//! App Config::default() → DeploymentContract → generate_chart("chart/")
19//! → generate_dockerfile()
20//! → generate_compose_fragment()
21//! → validate_helm_values("chart/")
22//! → validate_dockerfile("Dockerfile")
23//! ```
24//!
25//! The config cascade (figment) is the SSoT for app defaults. The contract
26//! captures the deployment-facing subset. Generation creates artifacts from
27//! scratch; validation asserts that existing artifacts match.
28//!
29//! # Example
30//!
31//! ```rust,no_run
32//! use hyperi_rustlib::deployment::{
33//! DeploymentContract, HealthContract, ImageProfile, KedaContract, NativeDepsContract,
34//! generate_dockerfile, generate_chart, generate_compose_fragment,
35//! };
36//!
37//! let contract = DeploymentContract {
38//! app_name: "dfe-loader".into(),
39//! binary_name: "dfe-loader".into(),
40//! description: "High-performance data loader".into(),
41//! metrics_port: 9090,
42//! health: HealthContract::default(),
43//! env_prefix: "DFE_LOADER".into(),
44//! metric_prefix: "loader".into(),
45//! config_mount_path: "/etc/dfe/loader.yaml".into(),
46//! image_registry: "ghcr.io/hyperi-io".into(),
47//! extra_ports: vec![],
48//! entrypoint_args: vec!["--config".into(), "/etc/dfe/loader.yaml".into()],
49//! secrets: vec![],
50//! default_config: None,
51//! depends_on: vec!["kafka".into(), "clickhouse".into()],
52//! keda: Some(KedaContract::default()),
53//! base_image: "ubuntu:24.04".into(),
54//! native_deps: NativeDepsContract::for_rustlib_features(
55//! &["transport-kafka", "spool", "tiered-sink"],
56//! "ubuntu:24.04",
57//! ),
58//! image_profile: ImageProfile::Production,
59//! oci_labels: Default::default(),
60//! schema_version: 1,
61//! };
62//!
63//! // Generate production Dockerfile (without identity annotations -- Phase 1
64//! // backwards-compat. New callers should pass `Some(&identity)`; see
65//! // `ContractIdentity::new` and `ContractIdentity::detect`.)
66//! let dockerfile = generate_dockerfile(&contract, None);
67//!
68//! // Generate development Dockerfile (same binary, adds debug tools)
69//! let dev_dockerfile = generate_dockerfile(&contract.with_dev_profile(), None);
70//!
71//! // Generate Helm chart directory
72//! // generate_chart(&contract, "chart/").unwrap();
73//!
74//! // Generate Docker Compose service fragment
75//! let compose = generate_compose_fragment(&contract);
76//! ```
77
78pub mod app_project;
79mod contract;
80pub mod contract_identity;
81mod error;
82pub mod generate;
83mod keda;
84mod native_deps;
85mod registry;
86#[cfg(feature = "deployment-smoke")]
87pub mod smoke;
88#[cfg(feature = "deployment-test-support")]
89pub mod test_support;
90mod validate;
91pub mod waves;
92
93pub use app_project::{AppProjectContract, AppProjectDestination, generate_argocd_app_project};
94pub use contract::{
95 DeploymentContract, HealthContract, ImageProfile, OciLabels, PortContract, SecretEnvContract,
96 SecretGroupContract,
97};
98pub use contract_identity::{ContractIdentity, IdentityError, KEY_PREFIX, VERSION};
99pub use error::{ContractMismatch, DeploymentError};
100pub use generate::{
101 ArgocdConfig, generate_argocd_application, generate_chart, generate_compose_fragment,
102 generate_container_manifest, generate_dockerfile, generate_runtime_stage,
103};
104pub use keda::{KedaConfig, KedaContract};
105pub use native_deps::{AptRepoContract, NativeDepsContract};
106pub use registry::{
107 DEFAULT_BASE_IMAGE, DEFAULT_IMAGE_REGISTRY, argocd_repo_url_from_cascade,
108 base_image_from_cascade, image_registry_from_cascade,
109};
110pub use validate::{validate_dockerfile, validate_helm_values};
111pub use waves::{WAVE_APPS, WAVE_CRDS, WAVE_OPERATORS, WAVE_POST, WAVE_TOPICS};