lmrc-gitlab 0.3.16

GitLab API client library for the LMRC Stack - comprehensive Rust library for programmatic control of GitLab via its API
Documentation
//! Demonstrates the different API patterns available in the library.
//!
//! This example shows:
//! 1. Resource-specific operations (via client methods)
//! 2. Project-level operations (creating resources)
//! 3. Direct API access (for operations not yet wrapped)
//!
//! To run this example:
//! ```bash
//! export GITLAB_TOKEN="your-token"
//! export GITLAB_PROJECT="your-project"
//! cargo run --example api_patterns
//! ```

use lmrc_gitlab::{GitLabClient, Result};

#[tokio::main]
async fn main() -> Result<()> {
    let gitlab_url =
        std::env::var("GITLAB_URL").unwrap_or_else(|_| "https://gitlab.com".to_string());
    let gitlab_token =
        std::env::var("GITLAB_TOKEN").expect("GITLAB_TOKEN environment variable must be set");
    let project =
        std::env::var("GITLAB_PROJECT").unwrap_or_else(|_| "gitlab-org/gitlab".to_string());

    println!("=== GitLab Client API Patterns ===\n");

    // Create the client
    let client = GitLabClient::new(&gitlab_url, &gitlab_token)?;

    // =================================================================
    // Pattern 1: Resource-specific operations (via client methods)
    // =================================================================
    println!("## Pattern 1: Resource-Specific Operations\n");

    // Single resource operations
    println!("### Single Resource Operations");
    let pipelines = client.pipelines(&project).limit(1).list().await?;

    if let Some(pipeline_basic) = pipelines.first() {
        let pipeline_id = pipeline_basic.id;

        // Get pipeline details
        let pipeline = client.pipeline(&project, pipeline_id).get().await?;
        println!("✓ Got pipeline #{}: {}", pipeline.id, pipeline.status);

        // Get jobs in the pipeline
        let jobs = client
            .jobs(&project)
            .pipeline(pipeline_id)
            .limit(3)
            .list()
            .await?;
        println!("✓ Found {} jobs in pipeline #{}", jobs.len(), pipeline_id);

        if let Some(job) = jobs.first() {
            let job_id = job.id;

            // Get job details
            let job_details = client.job(&project, job_id).get().await?;
            println!("✓ Got job #{}: {}", job_details.id, job_details.name);

            // Get job logs (might be empty if job hasn't run)
            match client.job(&project, job_id).logs().await {
                Ok(logs) => {
                    let preview = if logs.len() > 100 {
                        &logs[..100]
                    } else {
                        &logs
                    };
                    println!("✓ Got job logs ({}bytes): {}...", logs.len(), preview);
                }
                Err(e) => println!("⚠ Could not get job logs: {}", e),
            }
        }
    }

    // List operations with filters
    println!("\n### List Operations with Filters");

    // Filter pipelines by status
    let failed = client
        .pipelines(&project)
        .status(lmrc_gitlab::models::PipelineStatus::Failed)
        .limit(2)
        .list()
        .await?;
    println!("✓ Found {} failed pipelines", failed.len());

    // Filter by branch
    let main_pipelines = client
        .pipelines(&project)
        .ref_name("main")
        .limit(2)
        .list()
        .await?;
    println!(
        "✓ Found {} pipelines on 'main' branch",
        main_pipelines.len()
    );

    // Combine filters
    let recent_main_failures = client
        .pipelines(&project)
        .status(lmrc_gitlab::models::PipelineStatus::Failed)
        .ref_name("main")
        .limit(1)
        .list()
        .await?;
    println!(
        "✓ Found {} recent failures on 'main'",
        recent_main_failures.len()
    );

    // =================================================================
    // Pattern 2: Project-level operations
    // =================================================================
    println!("\n## Pattern 2: Project-Level Operations\n");

    println!("### Creating/Triggering Resources");

    // Example: Trigger a new pipeline (commented out to avoid creating actual pipelines)
    println!("Example code (not executed):");
    println!("```rust");
    println!("// Trigger a new pipeline");
    println!("let pipeline = client.project(&project)");
    println!("    .create_pipeline()");
    println!("    .ref_name(\"main\")");
    println!("    .trigger()");
    println!("    .await?;");
    println!();
    println!("// Trigger with variables");
    println!("let mut vars = HashMap::new();");
    println!("vars.insert(\"DEPLOY_ENV\".to_string(), \"staging\".to_string());");
    println!();
    println!("let pipeline = client.project(&project)");
    println!("    .create_pipeline()");
    println!("    .ref_name(\"main\")");
    println!("    .variables(vars)");
    println!("    .trigger()");
    println!("    .await?;");
    println!();
    println!("// Or use the fluent API");
    println!("let pipeline = client.project(&project)");
    println!("    .create_pipeline()");
    println!("    .ref_name(\"main\")");
    println!("    .variable(\"ENVIRONMENT\", \"production\")");
    println!("    .variable(\"DEBUG\", \"false\")");
    println!("    .trigger()");
    println!("    .await?;");
    println!("```");

    // =================================================================
    // Pattern 3: Direct API access
    // =================================================================
    println!("\n## Pattern 3: Direct API Access\n");

    println!("For operations not yet wrapped by the library,");
    println!("you can access the underlying gitlab crate client:");
    println!();
    println!("```rust");
    println!("use gitlab::api::Query;");
    println!();
    println!("// Access the raw client");
    println!("let raw_client = client.client();");
    println!();
    println!("// Use any gitlab crate endpoint");
    println!("// Example: Get current user");
    println!("// let endpoint = CurrentUser::builder().build()?;");
    println!("// let user = endpoint.query(raw_client)?;");
    println!("```");

    // =================================================================
    // Common Patterns
    // =================================================================
    println!("\n## Common Patterns\n");

    println!("### Error Handling");
    println!("```rust");
    println!("match client.pipeline(&project, 999999).get().await {{");
    println!("    Ok(pipeline) => println!(\"Found: {{:?}}\", pipeline),");
    println!("    Err(gitlab_manager::GitLabError::NotFound {{ resource, id }}) => {{");
    println!("        println!(\"{{}} with id {{}} not found\", resource, id);");
    println!("    }}");
    println!("    Err(e) => println!(\"Other error: {{}}\", e),");
    println!("}}");
    println!("```");

    println!("\n### Checking Status");
    if let Some(pipeline) = pipelines.first() {
        let status = pipeline.status;
        println!("Pipeline status checks:");
        println!("  - Is finished? {}", status.is_finished());
        println!("  - Is active? {}", status.is_active());
        println!("  - Is successful? {}", status.is_successful());
        println!("  - Is failed? {}", status.is_failed());
    }

    println!("\n### Working with Jobs");
    if let Some(pipeline) = pipelines.first() {
        let jobs = client.jobs(&project).pipeline(pipeline.id).list().await?;

        if let Some(job) = jobs.first() {
            let status = job.status;
            println!("Job status checks:");
            println!("  - Is finished? {}", status.is_finished());
            println!("  - Is active? {}", status.is_active());
            println!("  - Is successful? {}", status.is_successful());
            println!("  - Is failed? {}", status.is_failed());
        }
    }

    println!("\n✅ API patterns demonstration completed!");

    Ok(())
}