-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial setup for adding GitHub on-prem support. #65
Changes from all commits
8865bf9
9de5d3a
91bf6e1
e4b32af
3cd0c19
fab2065
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod setup; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod setup; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// setup_gh.rs | ||
|
||
use crate::github::auth::fetch_access_token; // Import shared utilities | ||
use reqwest::Client; | ||
use serde::{Deserialize, Serialize}; | ||
use tokio::task; | ||
|
||
#[derive(Debug, Deserialize, Serialize, Clone)] | ||
struct SetupInfoGithub { | ||
provider: String, | ||
owner: String, | ||
repos: Vec<String>, | ||
} | ||
|
||
#[derive(Debug, Deserialize, Serialize, Clone)] | ||
struct PublishRequestGithub { | ||
installationId: String, | ||
info: Vec<SetupInfoGithub>, | ||
} | ||
|
||
pub async fn handle_install_github(installation_code: &str) { | ||
// TODO: Implement the logic to handle GitHub installation | ||
|
||
// For example: | ||
// 1. Get access token from GitHub using the installation code | ||
let auth_info = fetch_access_token(installation_code).await; | ||
println!("[handle_install_github] auth_info = {:?}", &auth_info); | ||
// 2. Fetch user repositories and other necessary data | ||
// 3. Process webhooks or other setup tasks | ||
// 4. Send setup info or any other post-processing | ||
} | ||
|
||
async fn get_github_repositories(access_token: &str) -> Vec<String> { | ||
// TODO: Implement the logic to fetch user repositories from GitHub | ||
Vec::new() | ||
} | ||
|
||
async fn process_webhooks_github(repo_name: String, access_token: String) { | ||
// TODO: Implement the logic to process GitHub webhooks | ||
} | ||
|
||
async fn send_setup_info_github(setup_info: &Vec<SetupInfoGithub>) { | ||
// TODO: Implement the logic to send setup info for GitHub | ||
} | ||
|
||
// Add other necessary functions and utilities specific to GitHub setup |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
pub mod setup; | ||
pub mod review; | ||
mod coverage; | ||
mod coverage; | ||
|
||
pub mod bitbucket; | ||
pub mod github; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
use jsonwebtoken::{encode, Header, EncodingKey, Algorithm}; | ||
use serde::{Deserialize, Serialize}; | ||
use serde_json::Value; | ||
use std::env; | ||
use chrono::{Utc, Duration}; | ||
use std::fs; | ||
use crate::{utils::reqwest_client::get_client, utils::auth::AuthInfo}; | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
struct AccessTokenResponse { | ||
token: String, | ||
// Add other fields if necessary | ||
} | ||
|
||
#[derive(Debug, Serialize)] | ||
struct Claims { | ||
iat: i64, | ||
exp: i64, | ||
iss: String, | ||
} | ||
|
||
fn generate_jwt(github_app_id: &str) -> Option<String> { | ||
let pem_file_path = "/app/repoprofiler_private.pem"; | ||
let pem_data_res = fs::read(pem_file_path); | ||
|
||
if pem_data_res.is_err() { | ||
let pem_data_err = pem_data_res.expect_err("No error in reading pem file"); | ||
println!("Error reading pem file: {:?}", pem_data_err); | ||
return None; | ||
} | ||
let pem_data = pem_data_res.expect("Error reading pem file"); | ||
|
||
let my_claims = Claims { | ||
iat: Utc::now().timestamp(), | ||
exp: (Utc::now() + Duration::minutes(5)).timestamp(), | ||
iss: github_app_id.to_string(), | ||
}; | ||
|
||
let encoding_key = EncodingKey::from_rsa_pem(&pem_data); | ||
if encoding_key.is_err() { | ||
println!("Error creating encoding key"); | ||
return None; | ||
} | ||
|
||
let token_res = encode(&Header::new(Algorithm::RS256), &my_claims, &encoding_key.unwrap()); | ||
if token_res.is_err() { | ||
let token_err = token_res.expect_err("No error in fetching token"); | ||
println!("Error encoding JWT: {:?}", token_err); | ||
return None; | ||
}; | ||
let token = token_res.expect("Error encoding JWT"); | ||
Some(token) | ||
} | ||
Comment on lines
+22
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fn generate_jwt(github_app_id: &str) -> Result<String, Box<dyn std::error::Error>> {
let pem_file_path = "/app/repoprofiler_private.pem";
let pem_data = fs::read(pem_file_path)?;
let my_claims = Claims {
iat: Utc::now().timestamp(),
exp: (Utc::now() + Duration::minutes(5)).timestamp(),
iss: github_app_id.to_string(),
};
let encoding_key = EncodingKey::from_rsa_pem(&pem_data)?;
let token = encode(&Header::new(Algorithm::RS256), &my_claims, &encoding_key)?;
Ok(token)
} |
||
|
||
pub async fn fetch_access_token(installation_id: &str) -> Option<Value> { | ||
let github_app_id = env::var("GITHUB_APP_ID"); | ||
let github_app_id_str = github_app_id.expect("GITHUB_APP_ID must be set"); | ||
let jwt_token = generate_jwt(&github_app_id_str).expect("Error generating JWT"); | ||
|
||
let client = get_client(); | ||
let response = client.post(&format!("https://api.github.com/app/installations/{}/access_tokens", installation_id)) | ||
.header("Accept", "application/vnd.github+json") | ||
.header("Authorization", format!("Bearer {}", jwt_token)) | ||
.header("User-Agent", "Vibinex code review Test App") | ||
.send() | ||
.await; | ||
if response.is_err() { | ||
let e = response.expect_err("No error in response"); | ||
eprintln!("error in calling github api : {:?}", e); | ||
return None; | ||
} | ||
let response_access_token = response.expect("Uncaught error in reponse"); | ||
if !response_access_token.status().is_success() { | ||
println!( | ||
"Failed to exchange code for access token. Status code: {}, Response content: {:?}", | ||
response_access_token.status(), | ||
response_access_token.text().await | ||
); | ||
return None; | ||
} | ||
let parse_res = response_access_token.json().await ; | ||
if parse_res.is_err() { | ||
let e = parse_res.expect_err("No error in parse_res for AuthInfo"); | ||
eprintln!("error deserializing AuthInfo: {:?}", e); | ||
return None; | ||
} | ||
let response_json: Value = parse_res.expect("Uncaught error in parse_res for AuthInfo"); | ||
return Some(response_json); | ||
} | ||
Comment on lines
+55
to
+89
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The pub async fn fetch_access_token(installation_id: &str) -> Result<Value, Box<dyn std::error::Error>> {
let github_app_id = env::var("GITHUB_APP_ID")?;
let jwt_token = generate_jwt(&github_app_id)?;
let client = get_client();
let response = client.post(&format!("https://api.github.com/app/installations/{}/access_tokens", installation_id))
.header("Accept", "application/vnd.github+json")
.header("Authorization", format!("Bearer {}", jwt_token))
.header("User-Agent", "Vibinex code review Test App")
.send()
.await?;
if !response.status().is_success() {
return Err(format!(
"Failed to exchange code for access token. Status code: {}, Response content: {:?}",
response.status(),
response.text().await
).into());
}
let response_json: Value = response.json().await?;
return Ok(response_json);
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod auth; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ mod pubsub; | |
mod db; | ||
mod core; | ||
mod bitbucket; | ||
mod github; | ||
mod utils; | ||
|
||
#[tokio::main] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
use std::sync::Arc; | ||
use once_cell::sync::Lazy; | ||
use reqwest::Client; | ||
|
||
static CLIENT: Lazy<Arc<Client>> = Lazy::new(|| { | ||
Arc::new(Client::new()) | ||
}); | ||
|
||
pub fn get_client() -> Arc<Client> { | ||
Arc::clone(&CLIENT) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function
send_setup_info
is missing error handling for the case when the environment variables "INSTALL_ID" and "SERVER_URL" are not set. This could lead to a panic at runtime. Consider usingenv::var().ok()
instead ofenv::var().expect()
, and handle theNone
case appropriately.The rest of the code looks fine, but it's hard to review without the full context. It would be helpful to see how these functions are used in the larger application.