use std::fs;
use std::path::Path;
pub fn generate_dockerfile(tl_file: &str) -> String {
let filename = Path::new(tl_file)
.file_name()
.unwrap_or_default()
.to_string_lossy();
format!(
r#"# Generated by ThinkingLanguage
FROM rust:1.83-slim AS builder
RUN apt-get update && apt-get install -y pkg-config libssl-dev && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . .
RUN cargo install --path crates/tl-cli
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates libssl3 && rm -rf /var/lib/apt/lists/*
COPY --from=builder /usr/local/cargo/bin/tl /usr/local/bin/tl
COPY {filename} /app/{filename}
WORKDIR /app
ENTRYPOINT ["tl", "run", "{filename}"]
"#
)
}
pub fn generate_k8s_manifest(tl_file: &str) -> String {
let filename = Path::new(tl_file)
.file_name()
.unwrap_or_default()
.to_string_lossy();
let app_name = Path::new(tl_file)
.file_stem()
.unwrap_or_default()
.to_string_lossy()
.replace('_', "-");
format!(
r#"# Generated by ThinkingLanguage
apiVersion: apps/v1
kind: Deployment
metadata:
name: {app_name}
labels:
app: {app_name}
spec:
replicas: 1
selector:
matchLabels:
app: {app_name}
template:
metadata:
labels:
app: {app_name}
spec:
containers:
- name: {app_name}
image: {app_name}:latest
command: ["tl", "run", "{filename}"]
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: {app_name}
spec:
selector:
app: {app_name}
ports:
- port: 8080
targetPort: 8080
"#
)
}
pub fn write_deploy(tl_file: &str, target: &str, output_dir: &str) -> Result<(), String> {
let out = Path::new(output_dir);
fs::create_dir_all(out).map_err(|e| format!("Failed to create output dir: {e}"))?;
match target {
"docker" => {
let content = generate_dockerfile(tl_file);
let path = out.join("Dockerfile");
fs::write(&path, &content).map_err(|e| format!("Failed to write Dockerfile: {e}"))?;
println!("Generated {}", path.display());
}
"k8s" => {
let content = generate_k8s_manifest(tl_file);
let path = out.join("deployment.yaml");
fs::write(&path, &content)
.map_err(|e| format!("Failed to write deployment.yaml: {e}"))?;
println!("Generated {}", path.display());
}
other => {
return Err(format!(
"Unknown deploy target: '{other}'. Use 'docker' or 'k8s'."
));
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generate_dockerfile() {
let df = generate_dockerfile("pipeline.tl");
assert!(df.contains("FROM rust:"));
assert!(df.contains("pipeline.tl"));
assert!(df.contains("ENTRYPOINT"));
assert!(df.contains("tl"));
}
#[test]
fn test_generate_k8s_manifest() {
let manifest = generate_k8s_manifest("my_pipeline.tl");
assert!(manifest.contains("apiVersion: apps/v1"));
assert!(manifest.contains("kind: Deployment"));
assert!(manifest.contains("my-pipeline"));
assert!(manifest.contains("my_pipeline.tl"));
assert!(manifest.contains("kind: Service"));
}
#[test]
fn test_generate_dockerfile_nested_path() {
let df = generate_dockerfile("examples/stream_01.tl");
assert!(df.contains("stream_01.tl"));
}
}