Skip to content

Commit adf7cdb

Browse files
committed
Add new simplified triagebot.toml validation for PR
1 parent 5648e1f commit adf7cdb

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

src/handlers/check_commits.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mod modified_submodule;
1919
mod no_mentions;
2020
mod no_merges;
2121
mod non_default_branch;
22+
mod validate_config;
2223

2324
/// Key for the state in the database
2425
const CHECK_COMMITS_KEY: &str = "check-commits-warnings";
@@ -44,7 +45,10 @@ pub(super) async fn handle(ctx: &Context, event: &Event, config: &Config) -> any
4445

4546
if !matches!(
4647
event.action,
47-
IssuesAction::Opened | IssuesAction::Synchronize | IssuesAction::ReadyForReview
48+
IssuesAction::Opened
49+
| IssuesAction::Reopened
50+
| IssuesAction::Synchronize
51+
| IssuesAction::ReadyForReview
4852
) || !event.issue.is_pr()
4953
{
5054
return Ok(());
@@ -112,6 +116,13 @@ pub(super) async fn handle(ctx: &Context, event: &Event, config: &Config) -> any
112116
}
113117
}
114118

119+
// Check if the `triagebot.toml` config is valid
120+
errors.extend(
121+
validate_config::validate_config(ctx, &event, diff)
122+
.await
123+
.context("validating the the triagebot config")?,
124+
);
125+
115126
handle_new_state(ctx, event, errors, warnings, labels).await
116127
}
117128

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//! For pull requests that have changed the triagebot.toml, validate that the
2+
//! changes are a valid configuration file.
3+
4+
use crate::{
5+
config::CONFIG_FILE_NAME,
6+
github::FileDiff,
7+
handlers::{Context, IssuesEvent},
8+
};
9+
use anyhow::{Context as _, bail};
10+
11+
pub(super) async fn validate_config(
12+
ctx: &Context,
13+
event: &IssuesEvent,
14+
diff: &[FileDiff],
15+
) -> anyhow::Result<Option<String>> {
16+
if !diff.iter().any(|diff| diff.filename == CONFIG_FILE_NAME) {
17+
return Ok(None);
18+
}
19+
20+
let Some(pr_source) = &event.issue.head else {
21+
bail!("expected head commit");
22+
};
23+
let Some(repo) = &pr_source.repo else {
24+
bail!("repo is not available");
25+
};
26+
27+
let triagebot_content = ctx
28+
.github
29+
.raw_file(&repo.full_name, &pr_source.sha, CONFIG_FILE_NAME)
30+
.await
31+
.context("{CONFIG_FILE_NAME} modified, but failed to get content")?;
32+
33+
let triagebot_content = triagebot_content.unwrap_or_default();
34+
let triagebot_content = String::from_utf8_lossy(&*triagebot_content);
35+
36+
let Err(e) = toml::from_str::<crate::handlers::Config>(&triagebot_content) else {
37+
return Ok(None);
38+
};
39+
40+
let position = match e.span() {
41+
// toml sometimes gives bad spans, see https://github.com/toml-rs/toml/issues/589
42+
Some(span) if span != (0..0) => {
43+
let (line, col) = translate_position(&triagebot_content, span.start);
44+
let url = format!(
45+
"https://github.com/{}/blob/{}/{CONFIG_FILE_NAME}#L{line}",
46+
repo.full_name, pr_source.sha
47+
);
48+
format!(" at position [{line}:{col}]({url})",)
49+
}
50+
Some(_) | None => String::new(),
51+
};
52+
53+
Ok(Some(format!(
54+
"Invalid `triagebot.toml`{position}:\n\
55+
`````\n\
56+
{e}\n\
57+
`````",
58+
)))
59+
}
60+
61+
/// Helper to translate a toml span to a `(line_no, col_no)` (1-based).
62+
fn translate_position(input: &str, index: usize) -> (usize, usize) {
63+
if input.is_empty() {
64+
return (0, index);
65+
}
66+
67+
let safe_index = index.min(input.len() - 1);
68+
let column_offset = index - safe_index;
69+
70+
let nl = input[0..safe_index]
71+
.as_bytes()
72+
.iter()
73+
.rev()
74+
.enumerate()
75+
.find(|(_, b)| **b == b'\n')
76+
.map(|(nl, _)| safe_index - nl - 1);
77+
let line_start = match nl {
78+
Some(nl) => nl + 1,
79+
None => 0,
80+
};
81+
let line = input[0..line_start]
82+
.as_bytes()
83+
.iter()
84+
.filter(|c| **c == b'\n')
85+
.count();
86+
let column = input[line_start..=safe_index].chars().count() - 1;
87+
let column = column + column_offset;
88+
89+
(line + 1, column + 1)
90+
}

0 commit comments

Comments
 (0)