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:
parent
6e297455b9
commit
fb23798d78
8 changed files with 75 additions and 35 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
*.log
|
||||
/Cargo.lock
|
||||
/config.json
|
||||
/db/
|
||||
|
|
20
Cargo.toml
20
Cargo.toml
|
@ -1,23 +1,27 @@
|
|||
[package]
|
||||
name = "git-webhook-client"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
authors = ["Mo Bitar <mo8it@proton.me>"]
|
||||
edition = "2021"
|
||||
readme = "README.adoc"
|
||||
license-file = "LICENSE"
|
||||
repository = "https://codeberg.org/Mo8it/git-webhook-client"
|
||||
license-file = "LICENSE.txt"
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.22"
|
||||
diesel = { version = "2.0.2", features = [
|
||||
anyhow = "1.0"
|
||||
chrono = "0.4"
|
||||
diesel = { version = "2.0", features = [
|
||||
"r2d2",
|
||||
"sqlite",
|
||||
"returning_clauses_for_sqlite_3_35",
|
||||
"without-deprecated",
|
||||
] }
|
||||
hex = "0.4.3"
|
||||
hmac = "0.12.1"
|
||||
hex = "0.4"
|
||||
hmac = "0.12"
|
||||
log = "0.4"
|
||||
rocket = "0.5.0-rc.2"
|
||||
rocket_dyn_templates = { version = "0.1.0-rc.2", features = ["tera"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0.87"
|
||||
sha2 = "0.10.6"
|
||||
serde_json = "1.0"
|
||||
sha2 = "0.10"
|
||||
simplelog = "0.12"
|
||||
|
|
|
@ -22,7 +22,7 @@ Currently, only Gitea is supported. If you want support for Gitlab or Github, th
|
|||
|
||||
=== 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.
|
||||
. `base_url`: The base_url of the webhook client.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use serde::Deserialize;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Hook {
|
||||
|
@ -15,19 +15,18 @@ pub struct Hook {
|
|||
pub struct Config {
|
||||
pub secret: String,
|
||||
pub base_url: String,
|
||||
pub log_file: String,
|
||||
pub hooks: Vec<Hook>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new() -> Self {
|
||||
let config_path = Path::new("config.json");
|
||||
let config_file = File::open(config_path).unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"Can not open the config file at the path {}!",
|
||||
config_path
|
||||
.to_str()
|
||||
.expect("Can not convert the config file path into a string")
|
||||
)
|
||||
let config_file_var = "GWC_CONFIG_FILE";
|
||||
let config_path = env::var(config_file_var)
|
||||
.unwrap_or_else(|_| panic!("Environment variable {config_file_var} missing!"));
|
||||
|
||||
let config_file = File::open(&config_path).unwrap_or_else(|e| {
|
||||
panic!("Can not open the config file at the path {config_path}: {e}")
|
||||
});
|
||||
let config_reader = BufReader::new(config_file);
|
||||
let config: Self =
|
||||
|
|
27
src/db.rs
27
src/db.rs
|
@ -1,6 +1,8 @@
|
|||
use anyhow::{Context, Result};
|
||||
use chrono::Local;
|
||||
use diesel::prelude::*;
|
||||
use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
|
||||
use log::error;
|
||||
use std::env;
|
||||
|
||||
use crate::config::Hook;
|
||||
|
@ -10,8 +12,10 @@ use crate::schema::hooklog;
|
|||
pub type DBPool = Pool<ConnectionManager<SqliteConnection>>;
|
||||
|
||||
pub fn establish_connection_pool() -> DBPool {
|
||||
let database_url =
|
||||
env::var("DATABASE_URL").expect("Environment variable DATABASE_URL missing!");
|
||||
let database_url_var = "DATABASE_URL";
|
||||
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);
|
||||
|
||||
Pool::builder()
|
||||
|
@ -19,14 +23,11 @@ pub fn establish_connection_pool() -> DBPool {
|
|||
.expect("Could not build database connection pool!")
|
||||
}
|
||||
|
||||
fn get_conn(
|
||||
pool: &DBPool,
|
||||
) -> Result<PooledConnection<ConnectionManager<SqliteConnection>>, String> {
|
||||
pool.get()
|
||||
.map_err(|_| "Could not get database pool!".to_string())
|
||||
fn get_conn(pool: &DBPool) -> Result<PooledConnection<ConnectionManager<SqliteConnection>>> {
|
||||
pool.get().context("Could not get database pool!")
|
||||
}
|
||||
|
||||
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 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)
|
||||
.values(&new_hook_log)
|
||||
.get_result::<HookLog>(conn)
|
||||
.map_err(|e| e.to_string())
|
||||
.context("Could not insert hook log!")
|
||||
}
|
||||
|
||||
pub fn fill_hook_log(
|
||||
|
@ -54,7 +55,7 @@ pub fn fill_hook_log(
|
|||
let conn = &mut match get_conn(pool) {
|
||||
Ok(pool) => pool,
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
@ -73,12 +74,12 @@ pub fn fill_hook_log(
|
|||
{
|
||||
Ok(_) => (),
|
||||
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!
|
||||
|
||||
let conn = &mut get_conn(pool)?;
|
||||
|
@ -92,5 +93,5 @@ pub fn get_hook_log(pool: &DBPool, id: i32) -> Result<HookLog, String> {
|
|||
.first(conn)
|
||||
};
|
||||
|
||||
hl.map_err(|e| e.to_string())
|
||||
hl.context("Could not get hook log!")
|
||||
}
|
||||
|
|
29
src/logging.rs
Normal file
29
src/logging.rs
Normal 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!");
|
||||
}
|
10
src/main.rs
10
src/main.rs
|
@ -1,19 +1,27 @@
|
|||
mod config;
|
||||
mod db;
|
||||
mod guards;
|
||||
mod logging;
|
||||
mod models;
|
||||
mod routes;
|
||||
mod schema;
|
||||
mod states;
|
||||
|
||||
use log::info;
|
||||
use rocket_dyn_templates::Template;
|
||||
|
||||
#[rocket::launch]
|
||||
fn rocket() -> _ {
|
||||
let config = config::Config::new();
|
||||
|
||||
logging::init_logger(&config);
|
||||
|
||||
info!("Starting client");
|
||||
|
||||
rocket::build()
|
||||
.mount("/", rocket::routes![routes::index])
|
||||
.mount("/api", rocket::routes![routes::trigger])
|
||||
.manage(states::DB::new())
|
||||
.manage(states::Config::new())
|
||||
.manage(states::Config::new(config))
|
||||
.attach(Template::fairing())
|
||||
}
|
||||
|
|
|
@ -20,9 +20,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new() -> Self {
|
||||
let config = config::Config::new();
|
||||
|
||||
pub fn new(config: config::Config) -> Self {
|
||||
Self {
|
||||
secret: config.secret.as_bytes().to_owned(),
|
||||
base_url: config.base_url,
|
||||
|
|
Loading…
Reference in a new issue