Lines
85.71 %
Functions
50 %
Branches
100 %
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[cfg(test)]
mod test;
/// Name of check-runs created by the bot
pub const CHECK_RUN_NAME: &str = "cerberus-mergeguard";
/// Status for unfinished check-runs from the bot
/// Using 'queued', because while 'pending' is valid according to docs, the actual API does not allow it.
pub const CHECK_RUN_INITIAL_STATUS: &str = "queued";
/// Status for completed check-runs from the bot
pub const CHECK_RUN_COMPLETED_STATUS: &str = "completed";
/// Conclusion for completed check-runs from the bot
pub const CHECK_RUN_CONCLUSION: &str = "success";
/// Title for unfinished check-runs from the bot
pub const CHECK_RUN_INITIAL_TITLE: &str = "Waiting for other checks to complete";
/// Title for completed check-runs from the bot
pub const CHECK_RUN_COMPLETED_TITLE: &str = "All status checks have passed";
/// Summary for check-runs from the bot
pub const CHECK_RUN_SUMMARY: &str = "Will block merging until all other checks have completed";
/// Partial fields of a pull_request event webhook payload.
#[derive(Debug, Serialize, Deserialize)]
pub struct PullRequestEvent {
pub action: String,
pub installation: Option<Installation>,
pub number: u64,
pub pull_request: PullRequest,
pub repository: Repo,
}
/// Partial fields of a check_run event webhook payload.
pub struct CheckRunEvent {
pub check_run: CheckRun,
/// Partial fields of an issue_comment event webhook payload.
pub struct IssueCommentEvent {
pub issue: Issue,
pub comment: Comment,
/// Partial fields of a pull_request object.
pub struct PullRequest {
pub title: String,
pub head: BranchRef,
/// Partial fields of a branch reference object.
pub struct BranchRef {
pub label: String,
#[serde(rename = "ref")]
pub ref_field: String,
pub sha: String,
pub repo: Repo,
/// Partial fields of a repository object.
pub struct Repo {
pub id: u64,
pub name: String,
pub full_name: String,
/// Partial fields of a check_run object.
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
pub struct CheckRun {
#[serde(skip_serializing_if = "is_zero")]
pub head_sha: String,
pub status: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub conclusion: Option<String>,
pub started_at: Option<String>,
pub completed_at: Option<String>,
pub output: Option<CheckRunOutput>,
pub app: Option<App>,
fn is_zero(value: &u64) -> bool {
*value == 0
impl CheckRun {
/// Create a new check-run for the given commit.
pub fn new(commit: &str) -> Self {
CheckRun {
name: CHECK_RUN_NAME.to_string(),
head_sha: commit.to_string(),
status: CHECK_RUN_INITIAL_STATUS.to_string(),
output: Some(CheckRunOutput {
title: Some(CHECK_RUN_INITIAL_TITLE.to_string()),
summary: Some(CHECK_RUN_SUMMARY.to_string()),
}),
..Default::default()
/// Update the status based on the count of uncompleted check-runs.
/// Returns if the content of the check-run has changed.
pub fn update_status(&mut self, count: u32) -> bool {
let status: String;
let conclusion: Option<String>;
let output_title: Option<String>;
if count == 0 {
status = CHECK_RUN_COMPLETED_STATUS.to_string();
conclusion = Some(CHECK_RUN_CONCLUSION.to_string());
output_title = Some(CHECK_RUN_COMPLETED_TITLE.to_string());
} else {
status = CHECK_RUN_INITIAL_STATUS.to_string();
conclusion = None;
output_title = Some(format!("Waiting for {count} other checks to complete"));
let mut changed = false;
if self.status != status {
changed = true;
self.status = status;
if self.conclusion != conclusion {
self.conclusion = conclusion;
match &mut self.output {
Some(output) => {
if output.title != output_title {
output.title = output_title;
None => {
self.output = Some(CheckRunOutput {
title: output_title,
});
changed
/// Partial fields of a check_run output object.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CheckRunOutput {
pub title: Option<String>,
pub summary: Option<String>,
/// Partial fields of a GitHub App object.
pub struct App {
pub client_id: String,
pub slug: String,
/// Partial fields of an installation object.
pub struct Installation {
/// Partial fields of a comment object.
pub struct Comment {
pub body: String,
/// Partial fields of an issue object.
pub struct Issue {
/// Response to check-run requests from the GitHub API.
pub struct CheckRunsResponse {
pub total_count: u64,
pub check_runs: Vec<CheckRun>,
/// Response to installation token requests from the GitHub API.
pub struct TokenResponse {
pub token: String,
pub expires_at: DateTime<Utc>,
/// Response to get pull request from the GitHub API.
pub struct PullRequestResponse {