- Fixed PSO budget calculation bug in ml/src/hyperopt/optimizer.rs - Root cause: Division by n_particles in sequential execution - Now correctly calculates max_iters = remaining_trials (no division) - Result: 50 trials complete instead of 23 (100% vs 46%) - Added comprehensive DQN hyperopt results analysis - 39/50 trials analyzed across 2 RunPod deployments - Best hyperparameters identified: LR 4.89e-5 (ultra-low) - Created DQN_HYPEROPT_RESULTS_SUMMARY.md with expert validation - GitLab CI/CD pipeline operational (48 lines fixed) - Fixed YAML syntax errors (unquoted colons) - All 7 jobs validated and working - Warning cleanup complete (136 → 0 warnings) - Removed 143 lines dead code - Fixed visibility, unused imports, Debug traits - Archived Wave D reports to docs/archive/ - 8 early stopping reports moved - Root directory cleaned up 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
130 lines
3.9 KiB
Rust
130 lines
3.9 KiB
Rust
use crate::error::{FoxhuntError, Result};
|
|
use crate::utils;
|
|
use indicatif::{ProgressBar, ProgressStyle};
|
|
use std::io::{BufRead, BufReader};
|
|
use std::process::{Command, Stdio};
|
|
use std::time::Duration;
|
|
|
|
/// Push a Docker image to a registry
|
|
pub(crate) fn push_image(tag: &str) -> Result<()> {
|
|
// Verify image exists locally
|
|
if !super::image_exists(tag)? {
|
|
return Err(FoxhuntError::Docker(format!(
|
|
"Image '{}' does not exist locally. Build it first.",
|
|
tag
|
|
)));
|
|
}
|
|
|
|
utils::info(&format!("Pushing Docker image: {}", tag));
|
|
|
|
// Create progress bar
|
|
let pb = ProgressBar::new_spinner();
|
|
pb.set_style(
|
|
ProgressStyle::default_spinner()
|
|
.template("{spinner:.blue} {msg}")
|
|
.unwrap()
|
|
.tick_strings(&["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]),
|
|
);
|
|
pb.enable_steady_tick(Duration::from_millis(100));
|
|
pb.set_message("Pushing to registry...");
|
|
|
|
// Build docker push command
|
|
let mut cmd = Command::new("docker");
|
|
cmd.arg("push");
|
|
cmd.arg(tag);
|
|
|
|
// Configure to capture output
|
|
cmd.stdout(Stdio::piped());
|
|
cmd.stderr(Stdio::piped());
|
|
|
|
// Spawn the process
|
|
let mut child = cmd
|
|
.spawn()
|
|
.map_err(|e| FoxhuntError::Docker(format!("Failed to spawn docker push: {}", e)))?;
|
|
|
|
// Stream stdout to show progress
|
|
if let Some(stdout) = child.stdout.take() {
|
|
let reader = BufReader::new(stdout);
|
|
for line in reader.lines() {
|
|
if let Ok(line) = line {
|
|
// Update progress bar with push progress
|
|
if line.contains("Pushing") || line.contains("Pushed") || line.contains("Waiting") {
|
|
pb.set_message(line.clone());
|
|
}
|
|
tracing::debug!("docker push: {}", line);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Wait for completion
|
|
let status = child
|
|
.wait()
|
|
.map_err(|e| FoxhuntError::Docker(format!("Failed to wait for docker push: {}", e)))?;
|
|
|
|
pb.finish_and_clear();
|
|
|
|
if !status.success() {
|
|
// Try to get stderr for error details
|
|
let stderr = if let Some(stderr) = child.stderr {
|
|
let reader = BufReader::new(stderr);
|
|
let mut error_msg = String::new();
|
|
for line in reader.lines().flatten() {
|
|
error_msg.push_str(&line);
|
|
error_msg.push('\n');
|
|
}
|
|
error_msg
|
|
} else {
|
|
"Unknown error".to_string()
|
|
};
|
|
|
|
// Check for authentication errors
|
|
if stderr.contains("authentication") || stderr.contains("unauthorized") {
|
|
return Err(FoxhuntError::Docker(format!(
|
|
"Docker registry authentication failed. Please run 'docker login' first.\n{}",
|
|
stderr
|
|
)));
|
|
}
|
|
|
|
return Err(FoxhuntError::Docker(format!(
|
|
"Docker push failed with exit code {:?}:\n{}",
|
|
status.code(),
|
|
stderr
|
|
)));
|
|
}
|
|
|
|
utils::success(&format!("Successfully pushed: {}", tag));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Check if user is logged in to Docker registry
|
|
#[allow(dead_code)]
|
|
pub(crate) fn check_registry_auth(registry: &str) -> Result<bool> {
|
|
// Try to get credentials from Docker config
|
|
let output = Command::new("docker")
|
|
.args(["login", "--help"])
|
|
.output()
|
|
.map_err(|e| FoxhuntError::Docker(format!("Failed to check Docker login status: {}", e)))?;
|
|
|
|
if !output.status.success() {
|
|
return Ok(false);
|
|
}
|
|
|
|
// For simplicity, we assume if docker login command exists, auth is possible
|
|
// A more robust check would parse ~/.docker/config.json
|
|
tracing::debug!("Registry auth check for: {}", registry);
|
|
Ok(true)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_check_registry_auth() {
|
|
// This will succeed or fail depending on Docker installation
|
|
let result = check_registry_auth("docker.io");
|
|
assert!(result.is_ok());
|
|
}
|
|
}
|