From 28ed6aa52cd9e484fa7dd93ce3613d0450a54945 Mon Sep 17 00:00:00 2001 From: Sergei Kharchikov Date: Mon, 23 Feb 2026 14:40:53 +0000 Subject: [PATCH] feat: support multiple --env-file in ComposeConfig ComposeConfig previously only accepted a single env file (Option).This changes it to Vec to match Docker Compose v2.17+ support for multiple --env-file flags, and aligns with how RunCommand and ExecCommand already handle env files --- src/command.rs | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/src/command.rs b/src/command.rs index de8de3f..34730d5 100644 --- a/src/command.rs +++ b/src/command.rs @@ -210,8 +210,8 @@ pub struct ComposeConfig { pub project_directory: Option, /// Profiles to enable (--profile) pub profiles: Vec, - /// Environment file (--env-file) - pub env_file: Option, + /// Environment files (--env-file), can be specified multiple times + pub env_files: Vec, /// Run in compatibility mode pub compatibility: bool, /// Execute in dry run mode @@ -307,10 +307,10 @@ impl ComposeConfig { self } - /// Set environment file + /// Add an environment file (can be called multiple times) #[must_use] pub fn env_file(mut self, path: impl Into) -> Self { - self.env_file = Some(path.into()); + self.env_files.push(path.into()); self } @@ -378,8 +378,8 @@ impl ComposeConfig { args.push(profile.clone()); } - // Add environment file - if let Some(ref env_file) = self.env_file { + // Add environment files + for env_file in &self.env_files { args.push("--env-file".to_string()); args.push(env_file.to_string_lossy().to_string()); } @@ -1079,6 +1079,39 @@ mod tests { assert!(empty_output.stderr_is_empty()); } + #[test] + fn test_compose_config_single_env_file() { + let config = ComposeConfig::new().env_file("/path/to/.env"); + let args = config.build_global_args(); + + let env_file_count = args.iter().filter(|a| a.as_str() == "--env-file").count(); + assert_eq!(env_file_count, 1); + assert!(args.contains(&"/path/to/.env".to_string())); + } + + #[test] + fn test_compose_config_multiple_env_files() { + let config = ComposeConfig::new() + .env_file("/path/to/.env") + .env_file("/path/to/.env.local") + .env_file("/path/to/.env.production"); + let args = config.build_global_args(); + + let env_file_count = args.iter().filter(|a| a.as_str() == "--env-file").count(); + assert_eq!(env_file_count, 3); + assert!(args.contains(&"/path/to/.env".to_string())); + assert!(args.contains(&"/path/to/.env.local".to_string())); + assert!(args.contains(&"/path/to/.env.production".to_string())); + } + + #[test] + fn test_compose_config_no_env_file() { + let config = ComposeConfig::new(); + let args = config.build_global_args(); + + assert!(!args.contains(&"--env-file".to_string())); + } + /// Regression test for issue #233: Verify that compose commands don't produce /// "docker docker compose" when executed. The args returned by `ComposeCommand` /// should start with "compose" (not "docker"), and the `execute_command` logic