# Project export: mechanic

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2025
- Tagline: Streamline optimization in fast-moving projects.
- Devpost: https://devpost.com/software/mechanic
- GitHub: https://github.com/vznh/th25
- Team: 1 GitHub contributor(s) — Jason Son (24 commits)

## Devpost submission (written by the team)

### Overview

💡 Inspired by friends & personal work experiences. Friends would complain at their work that code was unoptimized, leading to shit piling on top of shit. Personal experience would be that startup culture prefer bootstrapping over optimization (for good reason & proof-of-concept). Why waste your time doing code review and nitpicking at all the files? 🔨 Layman’s terms, we’re a mechanic that constantly maintains your car to see if there are any problems of any sort that needs attention. Technically, mechanic constantly reviews over your commits within PR's to suggest optimizations, apply code changes, and merge suggestions with fleshed documentation. Kind of like if you had an optimization engineer on 24/7. Using it is really easy -- install it in your repo, and it'll run every time you commit within a PR. It'll also make informative comments, where you can branch the suggestions that it makes and merge with documentation if you like it (and test it...) 🚧 I built it using Rust, Axum, Groq, and GraphQL. We used Perplexity, Warp, Zed, Arc and Raycast as our development tools. 🏆 Executing this project was extremely informative (&frustrating) to me as an engineer — it definitely showed me the advantages and disadvantages of Rust as a web server and its' conjunction with GitHub apps. I'm proud overall to make an app that my internal will use, and my friends will try. 🔗 GitHub YouTube

## README (from the GitHub repository)

No README available.

## Detected evidence (automated analysis)

Indexed codebase: 11 recognized source files, 23 KB.
- Rust (language) — detected in the code

## Codebase structure (from repository index)

### Files (17 of 17)

```
.DS_Store
.gitignore
Cargo.lock
Cargo.toml
part.rs
rustfmt.toml
src/.DS_Store
src/handlers/mod.rs
src/handlers/webhook.rs
src/helpers/event.rs
src/helpers/jwt.rs
src/helpers/mod.rs
src/helpers/octo.rs
src/lib.rs
src/main.rs
src/services/groq.rs
src/services/mod.rs
```

### Dependencies

- Cargo.toml: axum@0.8.1, axum-server@0.7.1, base64@0.22.1, chrono@0.4.39, jsonwebtoken@9.3.1, octocrab@0.43.0, once_cell@1.20.3, reqwest@0.12.12, serde@1.0.217, serde_json@1.0.138, tokio@1.43.0

### Recent commits (newest first)

- final commit
- WE FUCKING COMMENTED
- Octocrab was init & ready for routing
- Screenshot of something thats working i think lol pre-push state
- Merge branch 'master' of https://github.com/vznh/th25
- bane of existnence
- chore(dep)
- Merge pull request #2 from vznh/pr1
- Screenshot of current handler
- Initial github app commit
- Merge pull request #1 from vznh/pr1
- Webhook can now differentiate if it's a pull req or not; if is, do something else not
- Pushed api key to git LOLOOL and formatted imps
- Moved one directory up
- Files were formatted
- Added formatting file
- Added groq handler
- Debloated by abstracting modules
- Web server can now parse for necessary details and return as is
- Merged old

## Key source files (fetched from GitHub, selected and truncated for size)

### Cargo.toml

```
[package]
name = "treehacks25"
version = "0.1.0"
edition = "2024"

[dependencies]
axum = "0.8.1"
reqwest = { version = "0.12.12", features = ["json", "blocking"] }
serde_json = "1.0.138"
tokio = { version = "1.43.0", features = ["rt-multi-thread", "fs"] }
axum-server = "0.7.1"
jsonwebtoken = "9.3.1"
serde = "1.0.217"
chrono = "0.4.39"
base64 = "0.22.1"
once_cell = "1.20.3"
octocrab = "0.43.0"

```

### src/main.rs

```rust
// main.rs
use axum::{Router, routing::post};
use std::net::SocketAddr;
use treehacks25::handlers::webhook::github_wh_test_handler;

// Build and serve the Axum app.
pub async fn serve() {
  let app = Router::new()
    // New route to trigger our GitHub event sending.
    // .route("/send-event", post(send_github_event_handler))
    // Your original webhook test route.
    .route("/github-wh-test", post(github_wh_test_handler));

  let addr = SocketAddr::from(([127, 0, 0, 1], 3000));

  println!("Successfully listening on {}. You can now make requests.", addr);
  axum_server::bind(addr).serve(app.into_make_service()).await.unwrap();
}

#[tokio::main]
async fn main() {
  serve().await;
}

```

### src/lib.rs

```rust
pub mod handlers;
pub mod helpers;
pub mod services;

```

### src/services/mod.rs

```rust
pub mod groq;

```

### src/handlers/mod.rs

```rust
pub mod webhook;

```

### src/helpers/mod.rs

```rust
pub mod event;
pub mod jwt;
pub mod octo;

```

### src/handlers/webhook.rs

```rust
// webhook.rs
use crate::helpers::event::process_event_and_get_token;
use axum::{Json, response::IntoResponse};
use serde_json::Value;

pub async fn github_wh_test_handler(
  headers: axum::http::HeaderMap,
  Json(payload): Json<Value>,
) -> impl IntoResponse {
  match process_event_and_get_token(&headers, &payload).await {
    Ok(token) => {
      println!("Successfully obtained installation token: {}", token);
      token // Return the token as the response
    }
    Err(e) => {
      println!("Error processing event: {}", e);
      format!("Error: {}", e)
    }
  }
}

```

### src/helpers/jwt.rs

```rust
// jwt.rs
use chrono::{Duration, Utc};
use jsonwebtoken::{Algorithm, EncodingKey, Header, encode};
use reqwest::Client;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::error::Error;
use std::fs;

#[derive(Debug, Serialize, Deserialize)]
struct Claims {
  iat: usize,
  exp: usize,
  iss: String,
}

pub fn create_jwt() -> Result<String, Box<dyn Error>> {
  println!("beginning to create jwt");
  // Hardcoded GitHub App ID and PEM file path
  let app_id = 1146309; // Replace with your actual GitHub App ID
  let pem_path = "certs/fuckyou.pem";
  // print this and check if it exists
  // Update to your PEM file's location

  // Attempt to read the private key file
  let key_contents = fs::read_to_string(pem_path)
    .map_err(|e| format!("Failed to read PEM file from '{}': {}", pem_path, e))?;

  let now = Utc::now();
  let iat = (now.timestamp() - 60) as usize;
  let exp = (now + Duration::minutes(10)).timestamp() as usize; // JWT valid for 10 minutes

  let claims = Claims { iat, exp, iss: app_id.to_string() };

  // Create the header using RS256
  let header = Header::new(Algorithm::RS256);

  // Attempt to create the encoding key from the PEM contents
  let encoding_key = EncodingKey::from_rsa_pem(key_contents.as_bytes())
    .map_err(|e| format!("Failed to create encoding key: {}", e))?;

  // Encode the token
  let token =
    encode(&header, &claims, &encoding_key).map_err(|e| format!("Failed to encode JWT: {}", e))?;

  Ok(token)
}

pub async fn exchange_jwt_for_installation_token(
  jwt: &str,
  installation_id: u64,
) -> Result<String, Box<dyn Error>> {
  // Construct the URL to request the installation token.
  let url = format!("https://api.github.com/app/installations/{}/access_tokens", installation_id);

  // Create a reqwest client.
  let client = Client::new();

  // Perform the POST request with the required headers.
  let response = client
    .post(&url)
    .header("Authorization", format!("Bearer {}", jwt))
    .header("Accept", "application/vnd.github+json")
    .header("User-Agent", "3mechanic") // GitHub API requires a User-Agent header.
    .send()
    .await?
    .error_for_status()?;

  // Parse the JSON response.
  let json: Value = response.json().await?;

  // Attempt to extract the installation token.
  if let Some(token) = json.get("token").and_then(|v| v.as_str()) {
    println!("Installation token obtained: xq{}", token);
    Ok(token.to_string())
  } else {
    Err(format!("Failed to obtain installation token. Response: {:?}", json).into())
  }
}

```

### src/helpers/octo.rs

```rust
use octocrab::Octocrab;
use octocrab::models::pulls::PullRequest;
use octocrab::params::{State, repos::Reference};
use std::error::Error;

/// Initialize Octocrab with a GitHub installation token.
pub fn init_octocrab(installation_token: String) -> Octocrab {
  Octocrab::builder()
    .personal_token(installation_token)
    .build()
    .expect("Failed to initialize Octocrab")
}

/// List open pull requests in a repository.
pub async fn test_list_pull_requests(octo: &Octocrab, owner: &str, repo: &str) {
  match octo.pulls(owner, repo).list().state(State::Open).per_page(5).send().await {
    Ok(prs) => {
      let pr_list: Vec<PullRequest> = prs.items;
      println!("Open pull requests in {}/{}: {:#?}", owner, repo, pr_list);
    }
    Err(err) => {
      println!("Failed to list pull requests: {:?}", err);
    }
  }
}

//// Find the latest PR and create a unique "mechanic-[issue]" branch from its latest commit.
pub async fn create_mechanic_branch(octo: &Octocrab, owner: &str, repo: &str) {
  // Step 1: Find the latest PR
  match octo.pulls(owner, repo).list().state(State::Open).per_page(1).send().await {
    Ok(prs) => {
      if let Some(pr) = prs.items.first() {
        let pr_number = pr.number;
        println!("Found latest PR: #{}", pr_number);

        // Step 2: Get the latest commit SHA of the PR
        let latest_commit = pr.head.sha.clone();

        println!("Latest PR commit SHA: {}", latest_commit);

        // Step 3: Generate base branch name
        let base_branch = format!("mechanic-{}", pr_number);
        let mut new_branch = base_branch.clone();
        let mut counter = 1;

        // Step 4: Check if the branch exists and increment if necessary
        while octo.repos(owner, repo).get_ref(&Reference::Branch(new_branch.clone())).await.is_ok()
        {
          new_branch = format!("{}-{}", base_branch, counter);
          counter += 1;
        }

        // Step 5: Create a new branch from the latest commit
        match octo
          .repos(owner, repo)
          .create_ref(&Reference::Branch(new_branch.clone()), &latest_commit)
          .await
        {
          Ok(_) => println!("Created new branch: {}", new_branch),
          Err(err) => println!("Failed to create new branch: {:?}", err),
        }
      } else {
        println!("No open PRs found.");
      }
    }
    Err(err) => {
      println!("Failed to fetch PRs: {:?}", err);
    }
  }
}

pub async fn reply_to_latest_pr(octo: &Octocrab, owner: &str, repo: &str) {
  match octo.pulls(owner, repo).list().state(octocrab::params::State::Open).per_page(1).send().await
  {
    Ok(prs) => {
      if let Some(pr) = prs.items.first() {
        let pr_number = pr.number;
        println!("Found latest PR: #{}", pr_number);
        match octo
          .issues(owner, repo)
          .create_comment(pr_number, "Mechanic doesn't have any suggestions to do. Great work!")
          .await
        {
          Ok(comment) => println!("Comment posted: {}", comment.html_url.to_string()),
          Err(err) => println!("Failed to comment on PR #{}: {:?}", pr_number, err),
        }
      } else {
        println!("No open PRs found.");
      }
    }
    Err(err) => {
      println!("Failed to fetch PRs: {:?}", err);
    }
  }
}


pub async fn post_markdown_as_comment(
  octo: &Octocrab,
  owner: &str,
  repo: &str,
  pr_number: u64,
  markdown: &str,
) -> Result<(), Box<dyn Error>> {
  let comment = octo
      .issues(owner, repo)
      .create_comment(pr_number, markdown)
      .await?;
  println!("Comment posted: {}", comment.html_url);
  Ok(())
}
```

### src/helpers/event.rs

```rust
use crate::helpers::octo::{init_octocrab, reply_to_latest_pr, post_markdown_as_comment};
use crate::services::groq::{
  extract_new_functions, json_to_xml, save_xml_to_file, send_request_to_groq,
}; // Import Groq functions
use axum::http::HeaderMap;
use serde_json::Value;
use std::error::Error;

#[derive(Debug)]
pub struct GitHubEvent {
  pub owner: String,
  pub repo: String,
  pub pull_number: u64,
  pub installation_id: u64,
  pub commit_sha: String,
}

pub fn get_installation_id(payload: &Value) -> Option<u64> {
  payload
    .get("installation")
    .and_then(|installation| installation.get("id"))
    .and_then(|id| id.as_u64())
}

/// Process the webhook payload and headers to extract the GitHub event details and trigger Groq processing.
pub async fn process_github_payload(headers: &HeaderMap, payload: &Value) -> GitHubEvent {
  let mut owner = String::new();
  let mut repo = String::new();
  let mut pull_number = 0;
  let mut installation_id = 0;
  let mut commit_sha = String::new();

  if let Some(event) = headers.get("X-GitHub-Event").and_then(|v| v.to_str().ok()) {
    if event == "pull_request" {
      if let Some(action) = payload.get("action").and_then(|v| v.as_str()) {
        if action == "synchronize" {
          owner = payload["repository"]["owner"]["login"].as_str().unwrap_or("").to_string();
          repo = payload["repository"]["name"].as_str().unwrap_or("").to_string();
          pull_number = payload["pull_request"]["number"].as_u64().unwrap_or(0);
          commit_sha = payload["after"].as_str().unwrap_or("").to_string();
          if let Some(id) = get_installation_id(payload) {
            installation_id = id;
          } else {
            println!("Installation ID missing in webhook payload");
          }
          println!(
            "Received pull_request.synchronize event for PR #{} in {}/{} with commit SHA {}.",
            pull_number, owner, repo, commit_sha
          );
        }
      }
    } else {
      // Handle other events (e.g., push event)
      owner = payload["repository"]["owner"]["login"].as_str().unwrap_or("").to_string();
      commit_sha = payload["after"].as_str().unwrap_or("").to_string();
      repo = payload["repository"]["name"].as_str().unwrap_or("").to_string();
      println!("Webhook received successfully!");
      if let Some(id) = get_installation_id(payload) {
        installation_id = id;
      } else {
        println!("Installation ID missing in webhook payload");
      }
    }
  } else {
    println!("X-GitHub-Event header missing.");
  }

  println!(
    "Values were successfully obtained. O: {}; R: {}; PR: #{}; IID: {}; SHA: {}",
    owner, repo, pull_number, installation_id, commit_sha
  );

  GitHubEvent { owner, repo, pull_number, installation_id, commit_sha }
}

/// Process the event and swap the installation ID for an installation token.
/// This function creates a JWT and then exchanges it for an installation token.
/// It returns the token as a String.
pub async fn process_event_and_get_token(
  headers: &HeaderMap,
  payload: &Value,
) -> Result<String, Box<dyn Error>> {
  let event = process_github_payload(headers, payload).await;

  if event.installation_id == 0 {
    return Err("No installation ID found in payload".into());
  }

  // Create the JWT using your helper function
  let jwt = crate::helpers::jwt::create_jwt()?;

  // Exchange the JWT for an installation token using your helper function
  let token =
    crate::helpers::jwt::exchange_jwt_for_installation_token(&jwt, event.installation_id).await?;

  // Initialize Octocrab with the installation token.
  let octo = init_octocrab(token.to_string());

  // ✅ **Run the Groq Pipeline for This Commit**
  if !event.commit_sha.is_empty() {
    println!("Extracting new functions from commit: {}", event.commit_sha);

    let _ = extract_new_functions(&event.owner, &event.repo, &event.commit_sha, &octo).await;
    let xml_output = json_to_xml().await;
    save_xml_to_file(&xml_output);

    println!("Sending extracted functions to Groq AI...");
    let groq_response = send_request_to_groq().await;

    match groq_response {
        Ok(response) => {
            println!("Groq AI Analysis Result:\n{}", response);
            // Here, assume your response is a markdown payload.
            if let Err(e) = post_markdown_as_comment(&octo, &event.owner, &event.repo, event.pull_number, &response).await {
                eprintln!("Failed to post markdown comment: {:?}", e);
            }
        }
        Err(e) => eprintln!("❌ Groq AI Request Failed: {:?}", e),
    }
} else {
    println!("⚠️ No commit SHA found, skipping Groq processing.");
}


  // Verify authentication by fetching the current user.
  match octo.current().user().await {
    Ok(user) => {
      println!("Authentication verified! Authenticated as: {:?}", user);
    }
    Err(err) => {
      println!("Failed to verify authentication: {:?}", err);
    }
  }

  // Now automate replying to the latest PR commit with any comment. If it's a change, then reply with a message. Else, reply with mechanic has no comment.
  // test_list_pull_requests(&octo, &event.owner, &event.repo).await;
  // reply_to_latest_pr(&octo, &event.owner, &event.repo).await;

  Ok(token)
}

```

[1 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]