A framework for building GitHub Apps, in Rust
⚠️ Under Development - This framework is currently in active development and may have bugs and issues.
A framework for building GitHub Apps in Rust, inspired by Probot. Octofer provides a clean, type-safe way to build GitHub Apps with minimal boilerplate and automatic webhook handling.
Octofer simplifies GitHub App development by:
- Handling webhook events - Automatically receives and routes GitHub webhook events
- Managing authentication - Handles GitHub App authentication and installation tokens
- Providing type safety - Full Rust type safety for GitHub API interactions
- Offering simple APIs - Clean, intuitive event handler registration
🛠️ Looking for a full production-ready example? Check out frezze! A bot that you can use to schedule "freeze" periods for your repo, blocking all PR merges for specific periods of time!
GitHub webhook events supported by Octofer (depends on octocrab):
on_issue()- Issue events (opened, closed, edited, etc.)on_issue_comment()- Issue comment events (created, edited, deleted)on_pull_request()- Pull request events (opened, closed, merged, etc.)on_pull_request_review()- Pull request review eventson_pull_request_review_comment()- Pull request review comment eventson_pull_request_review_thread()- Pull request review thread events
on_push()- Push eventson_create()- Branch/tag createdon_delete()- Branch/tag deletedon_fork()- Repository forkedon_commit_comment()- Comment on commiton_gollum()- Wiki page updateon_public()- Repository made publicon_repository()- Repository eventson_repository_dispatch()- Repository dispatchon_repository_import()- Repository importon_branch_protection_rule()- Branch protection rule events
on_workflow_run()- Workflow run eventson_workflow_job()- Workflow job eventson_workflow_dispatch()- Workflow dispatch eventson_status()- Commit status events
on_check_run()- Check run eventson_check_suite()- Check suite eventson_code_scanning_alert()- Code scanning alertson_secret_scanning_alert()- Secret scanning alertson_secret_scanning_alert_location()- Secret scanning alert locationon_dependabot_alert()- Dependabot alertson_repository_vulnerability_alert()- Repository vulnerability alertson_security_advisory()- Security advisory eventson_repository_advisory()- Repository advisory eventson_security_and_analysis()- Security and analysis events
on_deployment()- Deployment eventson_deployment_status()- Deployment status eventson_deploy_key()- Deploy key eventson_deployment_protection_rule()- Deployment protection rule events
on_discussion()- Discussion eventson_discussion_comment()- Discussion comment events
on_project()- Project (classic) eventson_project_card()- Project card eventson_project_column()- Project column eventson_projects_v2()- Projects v2 eventson_projects_v2_item()- Projects v2 item events
on_team()- Team eventson_team_add()- Team add eventson_member()- Member eventson_membership()- Membership eventson_organization()- Organization eventson_org_block()- Org block events
on_release()- Release eventson_package()- Package eventson_registry_package()- Registry package events
on_installation()- Installation eventson_installation_repositories()- Installation repositories eventson_installation_target()- Installation target eventson_github_app_authorization()- GitHub App authorization eventson_personal_access_token_request()- Personal access token request events
on_label()- Label eventson_milestone()- Milestone eventson_watch()- Watch (star) eventson_star()- Star eventson_ping()- Ping eventson_meta()- Meta eventson_page_build()- Page build eventson_schedule()- Schedule eventson_sponsorship()- Sponsorship eventson_marketplace_purchase()- Marketplace purchase eventson_merge_group()- Merge group events
Check the examples directory or the example below:
use std::sync::Arc;
use octofer::{Octofer, Config};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = Config::from_env().unwrap_or_default();
config.init_logging();
let mut app = Octofer::new(config).await.unwrap_or_else(|_| {
Octofer::new_default()
});
// Handle issue comments
app.on_issue_comment(
|context, _| async move {
println!("Issue comment event received!");
println!("Event type: {}", context.kind());
if let Some(client) = &context.github_client {
// Use GitHub API client here
println!("GitHub client available for API calls");
}
Ok(())
},
Arc::new(()),
).await;
app.start().await?;
Ok(())
}Octofer uses a centralized configuration system that loads from environment variables:
# Required for GitHub App authentication
export GITHUB_APP_ID=your_app_id
export GITHUB_PRIVATE_KEY_PATH=path/to/private-key.pem
# OR
export GITHUB_PRIVATE_KEY_BASE64=base64_encoded_key
# Webhook
export GITHUB_WEBHOOK_SECRET=your_webhook_secret
# Server configuration (optional)
export OCTOFER_HOST=127.0.0.1 # Default: 127.0.0.1
export OCTOFER_PORT=8000 # Default: 8000
# Logging configuration (optional)
export OCTOFER_LOG_LEVEL=info # Default: info (trace, debug, info, warn, error)
export OCTOFER_LOG_FORMAT=compact # Default: compact (compact, pretty, json)
export OCTOFER_LOG_WITH_TARGET=false # Default: false (show target module)
export OCTOFER_LOG_WITH_FILE=false # Default: false (show file and line info)
export OCTOFER_LOG_WITH_THREAD_IDS=false # Default: false (show thread IDs)You can also create configuration programmatically:
use octofer::Config;
let config = Config::new(
123456, // app_id
Some("path/to/private-key.pem".to_string()), // private_key_path
None, // private_key_base64
"your-webhook-secret".to_string(), // webhook_secret
std::net::Ipv4Addr::LOCALHOST, // host
8000, // port
)?;
// Initialize logging with the configuration
config.init_logging();Build all components:
cargo buildRun tests:
cargo testFormat code:
cargo fmtRun linting:
cargo clippy -- -D warnings- Centralized Configuration: All configuration managed through a single
Configstruct - Environment Variable Support: Automatic loading from environment variables
- GitHub Client Access: Direct access to authenticated GitHub clients from event handlers
- Modular Architecture: Clean separation of concerns across modules
- Type Safety: Full Rust type safety for GitHub API interactions
- Automatic Token Management: GitHub App installation token caching and refresh
- Middleware Support: HMAC verification and event processing middleware
Event handlers receive a Context object that provides access to:
- Event data:
context.payload()- The full GitHub webhook payload - Event:
context.event()- The full GitHub webhook event - Event type:
context.kind()- The type of event (e.g., "issues", "issue_comment") - Installation ID:
context.installation_id()- GitHub App installation ID - GitHub client:
context.github()- Authenticated GitHub API client - Installation client:
context.installation_client()- Installation-specific authenticated client
The repository includes several examples:
basic.rs- Simple GitHub App with event handlers.github_client.rs- Direct GitHub API client usage
MIT