Login
4 branches 0 tags
Ben (Desktop/Arch) Code cleanup ada8ea6 11 days ago 251 Commits
rubhub / crates / ci / src / lib.rs
//! RubHub CI
//!
//! A modular CI system for RubHub with support for local Podman execution
//! and remote runners.

pub mod executor;
pub mod models;
pub mod runner_client;
pub mod storage;

use std::path::Path;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;

use anyhow::Result;
use tokio::sync::mpsc;

use executor::ExecutorConfig;
use rubhub_state::{RunnerClientConfig, RunnerRegistry};

// Re-export key types for convenience
pub use executor::local::validate_podman;
pub use executor::remote::{spawn_heartbeat_checker, spawn_server_heartbeat_sender};
pub use models::{
    CiJob, CiJobRequest, CiJobResult, CiJobResultResponse, CiJobStatus, CiRunStatusResponse,
    CiStepResult, CiStepResultResponse, CiWorkflow, WorkflowJob, WorkflowStep, format_relative_time,
};
pub use runner_client::spawn_runner_client;
pub use storage::{list_jobs, load_job, load_job_log, load_run_with_all_logs};

/// Configuration for starting the CI system
pub struct CiConfig {
    /// Root directory for CI job data
    pub ci_root: Arc<Path>,
    /// Root directory for git repositories
    pub git_root: Arc<Path>,
    /// Whether local podman CI is available
    pub local_podman_available: Arc<AtomicBool>,
    /// Registry of connected remote runners
    pub runner_registry: Arc<RunnerRegistry>,
}

/// Handle for submitting CI jobs
#[derive(Clone)]
pub struct CiHandle {
    tx: mpsc::Sender<CiJobRequest>,
}

impl CiHandle {
    /// Submit a job request to the CI system
    pub async fn submit(&self, request: CiJobRequest) -> Result<()> {
        self.tx
            .send(request)
            .await
            .map_err(|e| anyhow::anyhow!("Failed to submit CI job: {}", e))
    }

    /// Get a reference to the underlying sender (for downcasting in the main crate)
    pub fn sender(&self) -> &mpsc::Sender<CiJobRequest> {
        &self.tx
    }
}

/// Start the CI system and return a handle for submitting jobs
///
/// This spawns the CI worker that processes jobs from the queue.
pub fn start(config: CiConfig) -> CiHandle {
    let (tx, rx) = mpsc::channel(256);

    let executor_config = ExecutorConfig {
        ci_root: config.ci_root,
        git_root: config.git_root,
        local_podman_available: config.local_podman_available,
        runner_registry: config.runner_registry,
    };

    executor::spawn_worker(executor_config, rx);

    CiHandle { tx }
}

/// Start the runner client that connects to a master instance
pub fn start_runner_client(config: RunnerClientConfig) {
    spawn_runner_client(config);
}

/// Start the heartbeat checker and sender for remote runners
pub fn start_runner_management(runner_registry: Arc<RunnerRegistry>, ci_root: Arc<Path>) {
    spawn_heartbeat_checker(runner_registry.clone(), ci_root);
    spawn_server_heartbeat_sender(runner_registry);
}