Skip to content

Also show warnings when PRs are updated #1901

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

Merged
merged 1 commit into from
Apr 7, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 74 additions & 5 deletions src/handlers/check_commits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,35 @@ use anyhow::bail;
use super::Context;
use crate::{
config::Config,
github::{Event, IssuesAction},
db::issue_data::IssueData,
github::{Event, IssuesAction, IssuesEvent, ReportedContentClassifiers},
};

mod modified_submodule;
mod non_default_branch;

/// Key for the state in the database
const CHECK_COMMITS_WARNINGS_KEY: &str = "check-commits-warnings";

/// State stored in the database
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
struct CheckCommitsWarningsState {
/// List of the last warnings in the most recent comment.
last_warnings: Vec<String>,
/// ID of the most recent warning comment.
last_warned_comment: Option<String>,
}

pub(super) async fn handle(ctx: &Context, event: &Event, config: &Config) -> anyhow::Result<()> {
let Event::Issue(event) = event else {
return Ok(());
};

if !matches!(event.action, IssuesAction::Opened) || !event.issue.is_pr() {
if !matches!(
event.action,
IssuesAction::Opened | IssuesAction::Synchronize
) || !event.issue.is_pr()
{
return Ok(());
}

Expand All @@ -27,6 +44,7 @@ pub(super) async fn handle(ctx: &Context, event: &Event, config: &Config) -> any

let mut warnings = Vec::new();

// Compute the warnings
if let Some(assign_config) = &config.assign {
// For legacy reasons the non-default-branch and modifies-submodule warnings
// are behind the `[assign]` config.
Expand All @@ -40,14 +58,65 @@ pub(super) async fn handle(ctx: &Context, event: &Event, config: &Config) -> any
warnings.extend(modified_submodule::modifies_submodule(diff));
}

if !warnings.is_empty() {
handle_warnings(ctx, event, warnings).await
}

// Add, hide or hide&add a comment with the warnings.
async fn handle_warnings(
ctx: &Context,
event: &IssuesEvent,
warnings: Vec<String>,
) -> anyhow::Result<()> {
// Get the state of the warnings for this PR in the database.
let mut db = ctx.db.get().await;
let mut state: IssueData<'_, CheckCommitsWarningsState> =
IssueData::load(&mut db, &event.issue, CHECK_COMMITS_WARNINGS_KEY).await?;

// We only post a new comment when we haven't posted one with the same warnings before.
if !warnings.is_empty() && state.data.last_warnings != warnings {
// New set of warnings, let's post them.

// Hide a previous warnings comment if there was one before printing the new ones.
if let Some(last_warned_comment_id) = state.data.last_warned_comment {
event
.issue
.hide_comment(
&ctx.github,
&last_warned_comment_id,
ReportedContentClassifiers::Resolved,
)
.await?;
}

// Format the warnings for user consumption on Github
let warnings: Vec<_> = warnings
.iter()
.map(|warning| format!("* {warning}"))
.collect();
let warning = format!(":warning: **Warning** :warning:\n\n{}", warnings.join("\n"));
event.issue.post_comment(&ctx.github, &warning).await?;
};
let comment = event.issue.post_comment(&ctx.github, &warning).await?;

// Save new state in the database
state.data.last_warnings = warnings;
state.data.last_warned_comment = Some(comment.node_id);
state.save().await?;
} else if warnings.is_empty() {
// No warnings to be shown, let's resolve a previous warnings comment, if there was one.
if let Some(last_warned_comment_id) = state.data.last_warned_comment {
event
.issue
.hide_comment(
&ctx.github,
&last_warned_comment_id,
ReportedContentClassifiers::Resolved,
)
.await?;

state.data.last_warnings = Vec::new();
state.data.last_warned_comment = None;
state.save().await?;
}
}

Ok(())
}
Loading