Crate octofer

Crate octofer 

Source
Expand description

§Octofer - GitHub Apps Framework for Rust

Octofer is a framework for building GitHub Apps in Rust, inspired by Probot. It provides a clean, type-safe way to build GitHub Apps with minimal boilerplate and automatic webhook handling.

§Key Features

  • 🔐 Automatic Authentication - JWT token generation and installation token management
  • 📡 Webhook Handling - Built-in HTTP server with HMAC verification
  • 🎯 Event Routing - Type-safe event handlers for GitHub webhook events
  • 🌐 GitHub API Integration - Authenticated GitHub API client with caching
  • ⚙️ Configuration Management - Environment variable based configuration
  • 📊 Observability - Built-in logging and request tracing

§Supported Events

Octofer supports all major GitHub webhook events:

  • Issues & PRs: on_issue(), on_issue_comment(), on_pull_request(), on_pull_request_review(), on_pull_request_review_comment(), on_pull_request_review_thread()
  • Repository: on_push(), on_create(), on_delete(), on_fork(), on_repository(), etc.
  • Workflows: on_workflow_run(), on_workflow_job(), on_workflow_dispatch(), on_status()
  • Security: on_code_scanning_alert(), on_secret_scanning_alert(), on_dependabot_alert(), etc.
  • Deployments: on_deployment(), on_deployment_status(), on_deploy_key()
  • Projects: on_project(), on_projects_v2(), on_projects_v2_item()
  • Teams: on_team(), on_member(), on_organization()
  • And many more - See events module for complete list

§Quick Start

§1. Basic Example

use octofer::{Octofer, Config};
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Load configuration from environment variables
    let config = Config::from_env().unwrap_or_default();
    config.init_logging();
     
    // Create the application
    let mut app = Octofer::new(config).await.unwrap_or_else(|_| {
        Octofer::new_default()
    });

    // Register event handlers
    app.on_issue(|context, _| async move {
        println!("Issue event: {}", context.kind());
        Ok(())
    }, Arc::new(())).await;
     
    // Start the webhook server
    app.start().await?;
    Ok(())
}
use octofer::{Octofer, Config, Context};
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Load configuration and initialize logging
    let config = Config::from_env()?;
    config.init_logging();
     
    let mut app = Octofer::new(config).await?;

    // Handle issue comments
    app.on_issue_comment(
        |context: Context, _| async move {
            let payload = context.payload();
             
            if let Some(comment) = payload.get("comment") {
                if let Some(body) = comment.get("body") {
                    println!("Comment: {}", body);
                     
                    // Use GitHub API client
                    if let Some(client) = context.github() {
                        let installations = client.get_installations().await?;
                        println!("Found {} installations", installations.len());
                    }
                }
            }
             
            Ok(())
        },
        Arc::new(()),
    ).await;

    // Handle pull requests
    app.on_pull_request(
        |context: Context, _| async move {
            let payload = context.payload();
             
            if payload.get("action").and_then(|a| a.as_str()) == Some("opened") {
                println!("New PR opened!");
                 
                // Use installation client for repository operations
                if let Some(installation_client) = context.installation_client().await? {
                    let user = installation_client.current().user().await?;
                    println!("Acting as: {}", user.login);
                }
            }
             
            Ok(())
        },
        Arc::new(()),
    ).await;

    println!("Starting GitHub App on {}:{}",
        app.config().server.host,
        app.config().server.port
    );
     
    app.start().await?;
    Ok(())
}

§Configuration

Set the following environment variables:

# Required
export GITHUB_APP_ID=your_app_id
export GITHUB_PRIVATE_KEY_PATH=path/to/private-key.pem
export GITHUB_WEBHOOK_SECRET=your_webhook_secret

# Optional
export OCTOFER_HOST=0.0.0.0      # Default: 127.0.0.1
export OCTOFER_PORT=3000         # Default: 8000
export OCTOFER_LOG_LEVEL=debug   # Default: info

See Config for complete configuration options.

§Architecture

Octofer consists of several key modules:

  • config - Configuration management and environment variable loading
  • core - Core types including Context and event handler traits
  • github - GitHub API client with authentication and token management
  • events - Event handler registration methods
  • webhook - HTTP server for receiving webhook events

§Error Handling

All event handlers should return anyhow::Result<()>. If a handler returns an error, it will be logged and the webhook request will return a 500 status code, causing GitHub to retry the delivery.

§Thread Safety

Octofer is fully thread-safe. Event handlers can be called concurrently, and the GitHub client handles token caching and refresh automatically across threads.

Re-exports§

pub use config::Config;
pub use core::Context;
pub use octocrab;

Modules§

config
Configuration module for Octofer
core
Core types and traits for Octofer
events
Event handler registration for GitHub webhook events
github
GitHub API client and authentication module
webhook
Webhook server module for handling GitHub webhook events

Structs§

Octofer
Main Octofer application

Traits§

SerdeToString
Trait for converting types to strings via serde serialization