Skip to content

Commit 6e455a4

Browse files
committed
ci: pedantic checks
1 parent 34eaab0 commit 6e455a4

File tree

10 files changed

+64
-61
lines changed

10 files changed

+64
-61
lines changed

.github/workflows/ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ jobs:
2929
uses: actions/checkout@v4
3030
- uses: dtolnay/rust-toolchain@stable
3131
- uses: Swatinem/rust-cache@v2
32-
- name: cargo check
32+
- name: Checks
3333
run: |
34-
cargo clippy -- -D warnings
34+
cargo clippy -- -D warnings -D clippy::pedantic

crates/config/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(clippy::missing_panics_doc)]
2+
13
use std::collections::HashSet;
24
use std::path::PathBuf;
35

@@ -77,6 +79,7 @@ impl Config {
7779
}
7880
}
7981

82+
#[must_use]
8083
pub fn parse_config(path: &PathBuf) -> Config {
8184
if path.is_dir() {
8285
let mut config = Config::default();
@@ -103,6 +106,7 @@ pub fn parse_config(path: &PathBuf) -> Config {
103106
}
104107
}
105108

109+
#[must_use]
106110
pub fn get_config() -> (PathBuf, Config) {
107111
let args = Command::new("grhooks")
108112
.version(env!("CARGO_PKG_VERSION"))

crates/core/src/cmd.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
use std::path::PathBuf;
2-
use std::sync::Arc;
32

43
use grhooks_config::WebhookConfig;
54
use srtemplate::SrTemplate;
65

7-
pub async fn execute_command<'a>(
6+
pub async fn execute_command(
87
config: &WebhookConfig,
98
event_type: &str,
109
value: &serde_json::Value,
1110
) -> std::io::Result<String> {
12-
let ctx = Arc::new(SrTemplate::with_delimiter("${{", "}}"));
11+
let ctx = SrTemplate::with_delimiter("${{", "}}");
1312
ctx.add_variable("event.type", event_type);
14-
crate::process_value(ctx.clone(), "event", value);
13+
crate::process_value(&ctx, "event", value);
1514

1615
let (shell, args) = if let Some(shell) = config.shell.as_ref() {
1716
let mut args = shell.clone();
@@ -22,9 +21,9 @@ pub async fn execute_command<'a>(
2221
};
2322

2423
let output = if let Some(script_path) = &config.script {
25-
execute_script(ctx.as_ref(), script_path, &shell, &args).await?
24+
execute_script(&ctx, script_path, &shell, &args).await?
2625
} else if let Some(command) = config.command.as_deref() {
27-
execute_direct_command(ctx.as_ref(), command, &shell, &args).await?
26+
execute_direct_command(&ctx, command, &shell, &args).await?
2827
} else {
2928
return Err(std::io::Error::new(
3029
std::io::ErrorKind::Other,
@@ -35,8 +34,8 @@ pub async fn execute_command<'a>(
3534
Ok(output)
3635
}
3736

38-
async fn execute_direct_command<'a>(
39-
ctx: &SrTemplate<'a>,
37+
async fn execute_direct_command(
38+
ctx: &SrTemplate<'_>,
4039
command: &str,
4140
shell: &str,
4241
shell_args: &[String],
@@ -55,11 +54,11 @@ async fn execute_direct_command<'a>(
5554
.output()
5655
.await?;
5756

58-
handle_command_output(output, &rendered_cmd)
57+
handle_command_output(&output, &rendered_cmd)
5958
}
6059

61-
async fn execute_script<'a>(
62-
ctx: &SrTemplate<'a>,
60+
async fn execute_script(
61+
ctx: &SrTemplate<'_>,
6362
script_path: &PathBuf,
6463
shell: &str,
6564
shell_args: &[String],
@@ -93,10 +92,10 @@ async fn execute_script<'a>(
9392
.output()
9493
.await?;
9594

96-
handle_command_output(output, &format!("script: {temp_script:?}"))
95+
handle_command_output(&output, &format!("script: {temp_script:?}"))
9796
}
9897

99-
fn handle_command_output(output: std::process::Output, context: &str) -> std::io::Result<String> {
98+
fn handle_command_output(output: &std::process::Output, context: &str) -> std::io::Result<String> {
10099
if !output.status.success() {
101100
let err_msg = format!(
102101
"Command failed ({} - {}):\nSTDERR: {}\nSTDOUT: {}",

crates/core/src/lib.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::sync::Arc;
1+
#![allow(clippy::missing_errors_doc)]
22

33
use serde_json::Value;
44
use srtemplate::SrTemplate;
@@ -15,32 +15,32 @@ pub fn render_secret(secret: &str, event_type: &str) -> String {
1515
secret
1616
}
1717

18-
pub fn process_value<'a>(ctx: Arc<SrTemplate<'a>>, prefix: &'a str, value: &'a Value) {
18+
pub fn process_value<'a>(ctx: &SrTemplate<'a>, prefix: &'a str, value: &'a Value) {
1919
match value {
2020
Value::Null => {
2121
tracing::trace!("Processing value: {prefix} = {value}");
22-
ctx.add_variable(prefix, &"null")
22+
ctx.add_variable(prefix, "null");
2323
}
2424
Value::Bool(b) => {
2525
tracing::trace!("Processing value: {prefix} = {value}");
26-
ctx.add_variable(prefix, b)
26+
ctx.add_variable(prefix, b);
2727
}
2828
Value::Number(n) => {
2929
tracing::trace!("Processing value: {prefix} = {value}");
30-
ctx.add_variable(prefix, n)
30+
ctx.add_variable(prefix, n);
3131
}
3232
Value::String(s) => {
3333
tracing::trace!("Processing value: {prefix} = {value}");
34-
ctx.add_variable(prefix, s)
34+
ctx.add_variable(prefix, s);
3535
}
3636
Value::Array(arr) => {
3737
tracing::trace!("Processing value: {prefix} = Array {{}}");
3838
for (i, item) in arr.iter().enumerate() {
39-
let key = format!("{}[{}]", prefix, i);
39+
let key = format!("{prefix}[{i}]");
4040
let key = unsafe {
4141
core::mem::transmute::<&str, &'a str>(Box::leak(key.into_boxed_str()))
4242
};
43-
process_value(ctx.clone(), key, item);
43+
process_value(ctx, key, item);
4444
}
4545
}
4646
Value::Object(obj) => {
@@ -49,12 +49,12 @@ pub fn process_value<'a>(ctx: Arc<SrTemplate<'a>>, prefix: &'a str, value: &'a V
4949
let key = if prefix.is_empty() {
5050
k.to_string()
5151
} else {
52-
format!("{}.{}", prefix, k)
52+
format!("{prefix}.{k}")
5353
};
5454
let key = unsafe {
5555
core::mem::transmute::<&str, &'a str>(Box::leak(key.into_boxed_str()))
5656
};
57-
process_value(ctx.clone(), &key, v);
57+
process_value(ctx, key, v);
5858
}
5959
}
6060
}

crates/origin/src/errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub enum Error {
1313
impl Debug for Error {
1414
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1515
match self {
16-
Error::MissingHeader(header) => write!(f, "Missing required header: {}", header),
16+
Error::MissingHeader(header) => write!(f, "Missing required header: {header}"),
1717
Error::InvalidSignature => write!(f, "Invalid signature"),
1818
Error::InvalidUserAgent => write!(f, "Invalid user agent"),
1919
Error::UnsupportedEvent => write!(f, "Unsupported event type"),
@@ -26,7 +26,7 @@ impl IntoResponse for Error {
2626
match self {
2727
Error::MissingHeader(header) => (
2828
StatusCode::BAD_REQUEST,
29-
format!("Missing required header: {}", header),
29+
format!("Missing required header: {header}"),
3030
)
3131
.into_response(),
3232
Error::InvalidSignature => {

crates/origin/src/github.rs

+19-22
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl WebhookOrigin for GitHubValidator {
3838
headers
3939
.get("X-GitHub-Event")
4040
.and_then(|v| v.to_str().ok())
41-
.map(|s| s.to_string())
41+
.map(ToString::to_string)
4242
.ok_or(Error::MissingHeader("X-GitHub-Event"))
4343
}
4444

@@ -48,30 +48,27 @@ impl WebhookOrigin for GitHubValidator {
4848
secret: &str,
4949
body: &[u8],
5050
) -> Result<(), Error> {
51-
let (expected_signature, signature) = match headers
51+
let (expected_signature, signature) = if let Some(signature) = headers
5252
.get("X-Hub-Signature-256")
5353
.and_then(|v| v.to_str().ok())
5454
{
55-
Some(signature) => {
56-
let signature = signature.trim_start_matches("sha256=");
57-
let mut mac = Hmac::<Sha256>::new_from_slice(secret.as_bytes())
58-
.map_err(|_| Error::InvalidSignature)?;
59-
mac.update(body);
60-
let expected_signature = hex::encode(mac.finalize().into_bytes());
61-
(expected_signature, signature)
62-
}
63-
None => {
64-
let signature = headers
65-
.get("X-Hub-Signature")
66-
.and_then(|v| v.to_str().ok())
67-
.ok_or(Error::MissingHeader("X-Hub-Signature"))?;
68-
let signature = signature.trim_start_matches("sha1=");
69-
let mut mac = Hmac::<Sha1>::new_from_slice(secret.as_bytes())
70-
.map_err(|_| Error::InvalidSignature)?;
71-
mac.update(body);
72-
let expected_signature = hex::encode(mac.finalize().into_bytes());
73-
(expected_signature, signature)
74-
}
55+
let signature = signature.trim_start_matches("sha256=");
56+
let mut mac = Hmac::<Sha256>::new_from_slice(secret.as_bytes())
57+
.map_err(|_| Error::InvalidSignature)?;
58+
mac.update(body);
59+
let expected_signature = hex::encode(mac.finalize().into_bytes());
60+
(expected_signature, signature)
61+
} else {
62+
let signature = headers
63+
.get("X-Hub-Signature")
64+
.and_then(|v| v.to_str().ok())
65+
.ok_or(Error::MissingHeader("X-Hub-Signature"))?;
66+
let signature = signature.trim_start_matches("sha1=");
67+
let mut mac = Hmac::<Sha1>::new_from_slice(secret.as_bytes())
68+
.map_err(|_| Error::InvalidSignature)?;
69+
mac.update(body);
70+
let expected_signature = hex::encode(mac.finalize().into_bytes());
71+
(expected_signature, signature)
7572
};
7673

7774
if !constant_time_eq::constant_time_eq(signature.as_bytes(), expected_signature.as_bytes())

crates/origin/src/gitlab.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl WebhookOrigin for GitLabValidator {
3030
headers
3131
.get("X-Gitlab-Event")
3232
.and_then(|v| v.to_str().ok())
33-
.map(|s| s.to_string())
33+
.map(ToString::to_string)
3434
.ok_or(Error::MissingHeader("X-Gitlab-Event"))
3535
}
3636

crates/origin/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(clippy::missing_errors_doc)]
2+
13
use axum::http::HeaderMap;
24
use serde::Deserialize;
35

src/handlers.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,21 @@ pub async fn webhook_handler(
2525
let Some(event_type) = header.get("X-GitHub-Event").and_then(|v| v.to_str().ok()) else {
2626
return (
2727
StatusCode::BAD_REQUEST,
28-
format!("Missing X-GitHub-Event header"),
28+
"Missing X-GitHub-Event header".to_string(),
2929
);
3030
};
3131

32-
if !webhook.events.is_empty() && !webhook.events.contains(&"*".to_string()) {
33-
if !webhook.events.contains(&event_type.to_string()) {
34-
return (
35-
StatusCode::BAD_REQUEST,
36-
format!("Event '{event_type}' not allowed"),
37-
);
38-
}
32+
if !webhook.events.is_empty()
33+
&& !webhook.events.contains("*")
34+
&& !webhook.events.contains(event_type)
35+
{
36+
return (
37+
StatusCode::BAD_REQUEST,
38+
format!("Event '{event_type}' not allowed"),
39+
);
3940
}
4041

41-
match grhooks_core::execute_command(&webhook, event_type, &value).await {
42+
match grhooks_core::execute_command(webhook, event_type, &value).await {
4243
Ok(output) => (StatusCode::OK, output),
4344
Err(e) => {
4445
tracing::error!("Error executing command: {e}");

src/main.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ async fn main() {
4646

4747
println!("listening on {}", listener.local_addr().unwrap());
4848

49-
axum::serve(listener, app).await.unwrap()
49+
axum::serve(listener, app).await.unwrap();
5050
}
5151

5252
fn listen_config_changes(state: GlobalConfig) -> impl EventHandler {
@@ -60,7 +60,7 @@ fn listen_config_changes(state: GlobalConfig) -> impl EventHandler {
6060
config.webhooks = Vec::new(); // restore webhooks
6161
event.paths.iter().for_each(|path| {
6262
tracing::info!("Config file changed: {path:?}");
63-
config.merge(grhooks_config::parse_config(&path))
63+
config.merge(grhooks_config::parse_config(path));
6464
});
6565
config.print_paths();
6666
}

0 commit comments

Comments
 (0)