1
0
Fork 0
mirror of https://codeberg.org/Mo8it/git-webhook-client synced 2024-11-21 11:06:32 +00:00

Use anyhow and simplelog

This commit is contained in:
Mo 2022-10-23 17:11:49 +02:00
parent 6e297455b9
commit fb23798d78
8 changed files with 75 additions and 35 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
*.log
/Cargo.lock /Cargo.lock
/config.json /config.json
/db/ /db/

View file

@ -1,23 +1,27 @@
[package] [package]
name = "git-webhook-client" name = "git-webhook-client"
version = "0.1.0" version = "0.2.0"
authors = ["Mo Bitar <mo8it@proton.me>"] authors = ["Mo Bitar <mo8it@proton.me>"]
edition = "2021" edition = "2021"
readme = "README.adoc" readme = "README.adoc"
license-file = "LICENSE" repository = "https://codeberg.org/Mo8it/git-webhook-client"
license-file = "LICENSE.txt"
[dependencies] [dependencies]
chrono = "0.4.22" anyhow = "1.0"
diesel = { version = "2.0.2", features = [ chrono = "0.4"
diesel = { version = "2.0", features = [
"r2d2", "r2d2",
"sqlite", "sqlite",
"returning_clauses_for_sqlite_3_35", "returning_clauses_for_sqlite_3_35",
"without-deprecated", "without-deprecated",
] } ] }
hex = "0.4.3" hex = "0.4"
hmac = "0.12.1" hmac = "0.12"
log = "0.4"
rocket = "0.5.0-rc.2" rocket = "0.5.0-rc.2"
rocket_dyn_templates = { version = "0.1.0-rc.2", features = ["tera"] } rocket_dyn_templates = { version = "0.1.0-rc.2", features = ["tera"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.87" serde_json = "1.0"
sha2 = "0.10.6" sha2 = "0.10"
simplelog = "0.12"

View file

@ -22,7 +22,7 @@ Currently, only Gitea is supported. If you want support for Gitlab or Github, th
=== Configuration === Configuration
The program looks for the configuration file `config.json` that contains the following: The program looks for the configuration file configured with the environment variable `GWC_CONFIG_FILE` that contains the following:
. `secret`: The secret of the webhook. . `secret`: The secret of the webhook.
. `base_url`: The base_url of the webhook client. . `base_url`: The base_url of the webhook client.

View file

@ -1,7 +1,7 @@
use serde::Deserialize; use serde::Deserialize;
use std::env;
use std::fs::File; use std::fs::File;
use std::io::BufReader; use std::io::BufReader;
use std::path::Path;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct Hook { pub struct Hook {
@ -15,19 +15,18 @@ pub struct Hook {
pub struct Config { pub struct Config {
pub secret: String, pub secret: String,
pub base_url: String, pub base_url: String,
pub log_file: String,
pub hooks: Vec<Hook>, pub hooks: Vec<Hook>,
} }
impl Config { impl Config {
pub fn new() -> Self { pub fn new() -> Self {
let config_path = Path::new("config.json"); let config_file_var = "GWC_CONFIG_FILE";
let config_file = File::open(config_path).unwrap_or_else(|_| { let config_path = env::var(config_file_var)
panic!( .unwrap_or_else(|_| panic!("Environment variable {config_file_var} missing!"));
"Can not open the config file at the path {}!",
config_path let config_file = File::open(&config_path).unwrap_or_else(|e| {
.to_str() panic!("Can not open the config file at the path {config_path}: {e}")
.expect("Can not convert the config file path into a string")
)
}); });
let config_reader = BufReader::new(config_file); let config_reader = BufReader::new(config_file);
let config: Self = let config: Self =

View file

@ -1,6 +1,8 @@
use anyhow::{Context, Result};
use chrono::Local; use chrono::Local;
use diesel::prelude::*; use diesel::prelude::*;
use diesel::r2d2::{ConnectionManager, Pool, PooledConnection}; use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
use log::error;
use std::env; use std::env;
use crate::config::Hook; use crate::config::Hook;
@ -10,8 +12,10 @@ use crate::schema::hooklog;
pub type DBPool = Pool<ConnectionManager<SqliteConnection>>; pub type DBPool = Pool<ConnectionManager<SqliteConnection>>;
pub fn establish_connection_pool() -> DBPool { pub fn establish_connection_pool() -> DBPool {
let database_url = let database_url_var = "DATABASE_URL";
env::var("DATABASE_URL").expect("Environment variable DATABASE_URL missing!"); let database_url = env::var(database_url_var)
.unwrap_or_else(|_| panic!("Environment variable {database_url_var} missing!"));
let manager = ConnectionManager::<SqliteConnection>::new(&database_url); let manager = ConnectionManager::<SqliteConnection>::new(&database_url);
Pool::builder() Pool::builder()
@ -19,14 +23,11 @@ pub fn establish_connection_pool() -> DBPool {
.expect("Could not build database connection pool!") .expect("Could not build database connection pool!")
} }
fn get_conn( fn get_conn(pool: &DBPool) -> Result<PooledConnection<ConnectionManager<SqliteConnection>>> {
pool: &DBPool, pool.get().context("Could not get database pool!")
) -> Result<PooledConnection<ConnectionManager<SqliteConnection>>, String> {
pool.get()
.map_err(|_| "Could not get database pool!".to_string())
} }
pub fn add_hook_log(pool: &DBPool, hook: &Hook) -> Result<HookLog, String> { pub fn add_hook_log(pool: &DBPool, hook: &Hook) -> Result<HookLog> {
let conn = &mut get_conn(pool)?; let conn = &mut get_conn(pool)?;
let command_with_args = hook.command.to_owned() + " " + &hook.args.join(" "); let command_with_args = hook.command.to_owned() + " " + &hook.args.join(" ");
@ -41,7 +42,7 @@ pub fn add_hook_log(pool: &DBPool, hook: &Hook) -> Result<HookLog, String> {
diesel::insert_into(hooklog::table) diesel::insert_into(hooklog::table)
.values(&new_hook_log) .values(&new_hook_log)
.get_result::<HookLog>(conn) .get_result::<HookLog>(conn)
.map_err(|e| e.to_string()) .context("Could not insert hook log!")
} }
pub fn fill_hook_log( pub fn fill_hook_log(
@ -54,7 +55,7 @@ pub fn fill_hook_log(
let conn = &mut match get_conn(pool) { let conn = &mut match get_conn(pool) {
Ok(pool) => pool, Ok(pool) => pool,
Err(e) => { Err(e) => {
println!("Error while trying to fill hook log: {e}"); error!("Could not get a database pool connection to fill hook log with id {hook_log_id}: {e}");
return; return;
} }
}; };
@ -73,12 +74,12 @@ pub fn fill_hook_log(
{ {
Ok(_) => (), Ok(_) => (),
Err(e) => { Err(e) => {
println!("Could not update hook log: {e}"); error!("Could not update hook log with id {hook_log_id}: {e}");
} }
}; };
} }
pub fn get_hook_log(pool: &DBPool, id: i32) -> Result<HookLog, String> { pub fn get_hook_log(pool: &DBPool, id: i32) -> Result<HookLog> {
// id=0 not allowed! // id=0 not allowed!
let conn = &mut get_conn(pool)?; let conn = &mut get_conn(pool)?;
@ -92,5 +93,5 @@ pub fn get_hook_log(pool: &DBPool, id: i32) -> Result<HookLog, String> {
.first(conn) .first(conn)
}; };
hl.map_err(|e| e.to_string()) hl.context("Could not get hook log!")
} }

29
src/logging.rs Normal file
View file

@ -0,0 +1,29 @@
use simplelog::{ColorChoice, LevelFilter, TermLogger, TerminalMode, WriteLogger};
use std::fs::OpenOptions;
use crate::config;
pub fn init_logger(config: &config::Config) {
let logger = if cfg!(debug_assertions) {
TermLogger::init(
LevelFilter::Debug,
simplelog::Config::default(),
TerminalMode::Mixed,
ColorChoice::Auto,
)
} else {
WriteLogger::init(
LevelFilter::Info,
simplelog::Config::default(),
OpenOptions::new()
.create(true)
.append(true)
.open(&config.log_file)
.unwrap_or_else(|e| {
panic!("Could not open the log file {}: {e}", &config.log_file)
}),
)
};
logger.expect("Could not initialize the logger!");
}

View file

@ -1,19 +1,27 @@
mod config; mod config;
mod db; mod db;
mod guards; mod guards;
mod logging;
mod models; mod models;
mod routes; mod routes;
mod schema; mod schema;
mod states; mod states;
use log::info;
use rocket_dyn_templates::Template; use rocket_dyn_templates::Template;
#[rocket::launch] #[rocket::launch]
fn rocket() -> _ { fn rocket() -> _ {
let config = config::Config::new();
logging::init_logger(&config);
info!("Starting client");
rocket::build() rocket::build()
.mount("/", rocket::routes![routes::index]) .mount("/", rocket::routes![routes::index])
.mount("/api", rocket::routes![routes::trigger]) .mount("/api", rocket::routes![routes::trigger])
.manage(states::DB::new()) .manage(states::DB::new())
.manage(states::Config::new()) .manage(states::Config::new(config))
.attach(Template::fairing()) .attach(Template::fairing())
} }

View file

@ -20,9 +20,7 @@ pub struct Config {
} }
impl Config { impl Config {
pub fn new() -> Self { pub fn new(config: config::Config) -> Self {
let config = config::Config::new();
Self { Self {
secret: config.secret.as_bytes().to_owned(), secret: config.secret.as_bytes().to_owned(),
base_url: config.base_url, base_url: config.base_url,