use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;
use super::config::DeploymentTarget;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentState {
pub target: DeploymentTarget,
pub deployed_at: chrono::DateTime<chrono::Utc>,
pub service_label: String,
pub project_name: String,
}
impl DeploymentState {
pub fn load(project_root: &std::path::Path) -> Result<Self> {
let path = Self::state_file_path(project_root);
if !path.exists() {
anyhow::bail!("No deployment state found. Has the project been deployed?");
}
let content = fs::read_to_string(&path)
.with_context(|| format!("Failed to read deployment state from {}", path.display()))?;
toml::from_str(&content).context("Failed to parse deployment state")
}
pub fn save(&self, project_root: &std::path::Path) -> Result<()> {
let path = Self::state_file_path(project_root);
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).context("Failed to create .audb directory")?;
}
let content = toml::to_string_pretty(self).context("Failed to serialize state")?;
fs::write(&path, content)
.with_context(|| format!("Failed to write deployment state to {}", path.display()))?;
Ok(())
}
fn state_file_path(project_root: &std::path::Path) -> PathBuf {
project_root.join(".audb").join("deploy.toml")
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn test_state_file_path() {
let project_root = PathBuf::from("/tmp/test-project");
let path = DeploymentState::state_file_path(&project_root);
assert!(path.ends_with(".audb/deploy.toml"));
}
}