Files
foxhunt/foxhunt-deploy/src/docker/push.rs
jgrusewski 3853988af7 feat(hyperopt): Complete DQN hyperopt analysis and PSO optimizer fix
- 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>
2025-11-02 21:49:07 +01:00

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());
}
}