Skip to content

Commit cc1b8f9

Browse files
authored
fix (cli): implementing env vars (#702)
## Description <!-- Provide a brief description of the changes in this PR --> implementing docker build reading env vars ## Related Issues <!-- Link to any related issues using #issue_number --> Closes # ## Checklist when merging to main <!-- Mark items with "x" when completed --> - [ ] No compiler warnings (if applicable) - [ ] Code is formatted with `rustfmt` - [ ] No useless or dead code (if applicable) - [ ] Code is easy to understand - [ ] Doc comments are used for all functions, enums, structs, and fields (where appropriate) - [ ] All tests pass - [ ] Performance has not regressed (assuming change was not to fix a bug) - [ ] Version number has been updated in `helix-cli/Cargo.toml` and `helixdb/Cargo.toml` ## Additional Notes <!-- Add any additional information that would be helpful for reviewers -->
2 parents 7f7abff + 2841ace commit cc1b8f9

File tree

1 file changed

+27
-144
lines changed

1 file changed

+27
-144
lines changed

helix-cli/src/docker.rs

Lines changed: 27 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
use crate::config::{BuildMode, InstanceInfo};
22
use crate::project::ProjectContext;
3-
use crate::utils::{print_confirm, print_status, print_warning};
3+
use crate::utils::print_status;
44
use eyre::{Result, eyre};
55
use std::process::{Command, Output};
6-
use std::thread;
7-
use std::time::Duration;
86

97
pub struct DockerManager<'a> {
108
project: &'a ProjectContext,
@@ -46,8 +44,12 @@ impl<'a> DockerManager<'a> {
4644
}
4745

4846
/// Get environment variables for an instance
47+
/// Loads from .env file and shell environment
4948
pub(crate) fn environment_variables(&self, instance_name: &str) -> Vec<String> {
50-
vec![
49+
// Load .env file (silently ignore if it doesn't exist)
50+
let _ = dotenvy::dotenv();
51+
52+
let mut env_vars = vec![
5153
{
5254
let port = self
5355
.project
@@ -64,7 +66,17 @@ impl<'a> DockerManager<'a> {
6466
let project_name = &self.project.config.project.name;
6567
format!("HELIX_PROJECT={project_name}")
6668
},
67-
]
69+
];
70+
71+
// Add API keys from environment (which includes .env after dotenv() call)
72+
if let Ok(openai_key) = std::env::var("OPENAI_API_KEY") {
73+
env_vars.push(format!("OPENAI_API_KEY={openai_key}"));
74+
}
75+
if let Ok(gemini_key) = std::env::var("GEMINI_API_KEY") {
76+
env_vars.push(format!("GEMINI_API_KEY={gemini_key}"));
77+
}
78+
79+
env_vars
6880
}
6981

7082
/// Get the container name for an instance
@@ -107,112 +119,6 @@ impl<'a> DockerManager<'a> {
107119
Ok(output)
108120
}
109121

110-
/// Detect the current operating system platform
111-
fn detect_platform() -> &'static str {
112-
#[cfg(target_os = "macos")]
113-
return "macos";
114-
115-
#[cfg(target_os = "linux")]
116-
return "linux";
117-
118-
#[cfg(target_os = "windows")]
119-
return "windows";
120-
121-
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
122-
return "unknown";
123-
}
124-
125-
/// Start the Docker daemon based on the platform
126-
fn start_docker_daemon() -> Result<()> {
127-
let platform = Self::detect_platform();
128-
129-
match platform {
130-
"macos" => {
131-
print_status("DOCKER", "Starting Docker Desktop for macOS...");
132-
Command::new("open")
133-
.args(["-a", "Docker"])
134-
.output()
135-
.map_err(|e| eyre!("Failed to start Docker Desktop: {}", e))?;
136-
}
137-
"linux" => {
138-
print_status("DOCKER", "Attempting to start Docker daemon on Linux...");
139-
// Try systemctl first, then service command as fallback
140-
let systemctl_result = Command::new("systemctl").args(["start", "docker"]).output();
141-
142-
match systemctl_result {
143-
Ok(output) if output.status.success() => {
144-
// systemctl succeeded
145-
}
146-
_ => {
147-
// Try service command as fallback
148-
let service_result = Command::new("service")
149-
.args(["docker", "start"])
150-
.output()
151-
.map_err(|e| eyre!("Failed to start Docker daemon: {}", e))?;
152-
153-
if !service_result.status.success() {
154-
let stderr = String::from_utf8_lossy(&service_result.stderr);
155-
return Err(eyre!("Failed to start Docker daemon: {}", stderr));
156-
}
157-
}
158-
}
159-
}
160-
"windows" => {
161-
print_status("DOCKER", "Starting Docker Desktop for Windows...");
162-
// Try Docker Desktop CLI (4.37+) first
163-
let cli_result = Command::new("docker")
164-
.args(["desktop", "start"])
165-
.output();
166-
167-
match cli_result {
168-
Ok(output) if output.status.success() => {
169-
// Modern Docker Desktop CLI worked
170-
}
171-
_ => {
172-
// Fallback to direct executable path for older versions
173-
// Note: Empty string "" is required as window title parameter
174-
Command::new("cmd")
175-
.args(["/c", "start", "", "\"C:\\Program Files\\Docker\\Docker\\Docker Desktop.exe\""])
176-
.output()
177-
.map_err(|e| eyre!("Failed to start Docker Desktop: {}", e))?;
178-
}
179-
}
180-
}
181-
_ => {
182-
return Err(eyre!("Unsupported platform for auto-starting Docker"));
183-
}
184-
}
185-
186-
Ok(())
187-
}
188-
189-
/// Wait for Docker daemon to be ready
190-
fn wait_for_docker(timeout_secs: u64) -> Result<()> {
191-
print_status("DOCKER", "Waiting for Docker daemon to start...");
192-
193-
let start = std::time::Instant::now();
194-
let timeout = Duration::from_secs(timeout_secs);
195-
196-
while start.elapsed() < timeout {
197-
// Check if Docker daemon is responding
198-
let output = Command::new("docker").args(["info"]).output();
199-
200-
if let Ok(output) = output
201-
&& output.status.success()
202-
{
203-
print_status("DOCKER", "Docker daemon is now running");
204-
return Ok(());
205-
}
206-
207-
// Wait a bit before retrying
208-
thread::sleep(Duration::from_millis(500));
209-
}
210-
211-
Err(eyre!(
212-
"Timeout waiting for Docker daemon to start. Please start Docker manually and try again."
213-
))
214-
}
215-
216122
/// Check if Docker is installed and running
217123
pub fn check_docker_available() -> Result<()> {
218124
let output = Command::new("docker")
@@ -231,33 +137,7 @@ impl<'a> DockerManager<'a> {
231137
.map_err(|_| eyre!("Failed to check Docker daemon status"))?;
232138

233139
if !output.status.success() {
234-
// Docker daemon is not running - prompt user
235-
let should_start =
236-
print_confirm("Docker daemon is not running. Would you like to start Docker?")
237-
.unwrap_or(false);
238-
239-
if should_start {
240-
// Try to start Docker
241-
Self::start_docker_daemon()?;
242-
243-
// Wait for Docker to be ready
244-
Self::wait_for_docker(15)?;
245-
246-
// Verify Docker is now running
247-
let verify_output = Command::new("docker")
248-
.args(["info"])
249-
.output()
250-
.map_err(|_| eyre!("Failed to verify Docker daemon status"))?;
251-
252-
if !verify_output.status.success() {
253-
return Err(eyre!(
254-
"Docker daemon failed to start. Please start Docker manually and try again."
255-
));
256-
}
257-
} else {
258-
print_warning("Docker daemon must be running to execute this command.");
259-
return Err(eyre!("Docker daemon is not running. Please start Docker."));
260-
}
140+
return Err(eyre!("Docker daemon is not running. Please start Docker."));
261141
}
262142

263143
Ok(())
@@ -354,6 +234,14 @@ CMD ["helix-container"]
354234
let container_name = self.container_name(instance_name);
355235
let network_name = self.network_name(instance_name);
356236

237+
// Get all environment variables dynamically
238+
let env_vars = self.environment_variables(instance_name);
239+
let env_section = env_vars
240+
.iter()
241+
.map(|var| format!(" - {var}"))
242+
.collect::<Vec<_>>()
243+
.join("\n");
244+
357245
let compose = format!(
358246
r#"# Generated docker-compose.yml for Helix instance: {instance_name}
359247
services:
@@ -369,10 +257,7 @@ services:
369257
volumes:
370258
- ../.volumes/{instance_name}:/data
371259
environment:
372-
- HELIX_PORT={port}
373-
- HELIX_DATA_DIR={data_dir}
374-
- HELIX_INSTANCE={instance_name}
375-
- HELIX_PROJECT={project_name}
260+
{env_section}
376261
restart: unless-stopped
377262
networks:
378263
- {network_name}
@@ -384,8 +269,6 @@ networks:
384269
platform = instance_config
385270
.docker_build_target()
386271
.map_or("".to_string(), |p| format!("platforms:\n - {p}")),
387-
project_name = self.project.config.project.name,
388-
data_dir = HELIX_DATA_DIR,
389272
);
390273

391274
Ok(compose)

0 commit comments

Comments
 (0)