diff --git a/Cargo.lock b/Cargo.lock index 0dbae51f..4f7b1ba9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1494,9 +1494,9 @@ dependencies = [ [[package]] name = "octocrab" -version = "0.45.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9142159757f166a7b20e3dcd410a5af008a63747c73e836a01fa4f7af84d2c4" +checksum = "a1620cb765b304c2828fe3cc1c6510cad7354cbeb519561f415fd3b07aae0ef5" dependencies = [ "arc-swap", "async-trait", diff --git a/src/templates.rs b/src/templates.rs index 9e2c1be8..478d5752 100644 --- a/src/templates.rs +++ b/src/templates.rs @@ -1,8 +1,23 @@ -use crate::database::{MergeableState::*, PullRequestModel, QueueStatus::*, TreeState}; +use crate::database::{MergeableState::*, PullRequestModel, QueueStatus, TreeState}; use askama::Template; use axum::response::{Html, IntoResponse, Response}; use http::StatusCode; +/// Build status to display on the queue page. +pub fn status_text(pr: &PullRequestModel) -> String { + if let Some(try_build) = &pr.try_build { + try_build.status.to_string() + } else { + match pr.queue_status() { + QueueStatus::Approved(_) => "approved".to_string(), + QueueStatus::ReadyForMerge(_, _) => "ready for merge".to_string(), + QueueStatus::Pending(_, _) => "pending".to_string(), + QueueStatus::Stalled(_, _) => "stalled".to_string(), + QueueStatus::NotApproved => String::new(), + } + } +} + pub struct HtmlTemplate(pub T); impl IntoResponse for HtmlTemplate diff --git a/src/utils/sort_queue.rs b/src/utils/sort_queue.rs index 164be611..e40985ac 100644 --- a/src/utils/sort_queue.rs +++ b/src/utils/sort_queue.rs @@ -1,63 +1,40 @@ use crate::bors::RollupMode; -use crate::database::{BuildStatus, MergeableState, PullRequestModel}; +use crate::database::{MergeableState, PullRequestModel, QueueStatus}; /// Sorts pull requests according to merge queue priority rules. -/// Ordered by pending builds > success builds > approval > mergeability > priority value > rollup > age. +/// Ordered by: ready for merge > pending builds > approved > stalled > not approved > mergeability +/// > priority > rollup > age. pub fn sort_queue_prs(mut prs: Vec) -> Vec { prs.sort_by(|a, b| { - // 1. Pending builds come first (to block merge queue) - get_queue_blocking_priority(a) - .cmp(&get_queue_blocking_priority(b)) - // 2. Compare approval status (approved PRs should come first) - .then_with(|| a.is_approved().cmp(&b.is_approved()).reverse()) - // 3. Compare build status within approval groups - .then_with(|| get_status_priority(a).cmp(&get_status_priority(b))) - // 4. Compare mergeability state (0 = mergeable, 1 = conflicts/unknown) + // 1. Compare queue status (ready for merge > pending > approved > stalled > not approved) + get_queue_status_priority(&a.queue_status()) + .cmp(&get_queue_status_priority(&b.queue_status())) + // 2. Compare mergeability state (0 = mergeable, 1 = conflicts/unknown) .then_with(|| get_mergeable_priority(a).cmp(&get_mergeable_priority(b))) - // 5. Compare priority numbers (higher priority should come first) + // 3. Compare priority numbers (higher priority should come first) .then_with(|| { a.priority .unwrap_or(0) .cmp(&b.priority.unwrap_or(0)) .reverse() }) - // 6. Compare rollup mode (-1 = never/iffy, 0 = maybe, 1 = always) + // 4. Compare rollup mode (always > maybe > iffy > never) .then_with(|| { get_rollup_priority(a.rollup.as_ref()).cmp(&get_rollup_priority(b.rollup.as_ref())) }) - // 7. Compare PR numbers (older first) + // 5. Compare PR numbers (older first) .then_with(|| a.number.cmp(&b.number)) }); prs } -fn get_queue_blocking_priority(pr: &PullRequestModel) -> u32 { - match &pr.auto_build { - Some(build) => match build.status { - // Pending builds must come first to block the merge queue - BuildStatus::Pending => 0, - // All other statuses come after - _ => 1, - }, - None => 1, // No build - can potentially start new build - } -} - -fn get_status_priority(pr: &PullRequestModel) -> u32 { - match &pr.auto_build { - Some(build) => match build.status { - BuildStatus::Success => 0, - BuildStatus::Pending => 1, - BuildStatus::Failure => 3, - BuildStatus::Cancelled | BuildStatus::Timeouted => 2, - }, - None => { - if pr.is_approved() { - 1 // Approved but no build - should be prioritized - } else { - 2 // No status - } - } +fn get_queue_status_priority(status: &QueueStatus) -> u32 { + match status { + QueueStatus::ReadyForMerge(_, _) => 0, + QueueStatus::Pending(_, _) => 1, + QueueStatus::Approved(_) => 2, + QueueStatus::Stalled(_, _) => 3, + QueueStatus::NotApproved => 4, } } diff --git a/templates/queue.html b/templates/queue.html index cef5d70d..a6dc753f 100644 --- a/templates/queue.html +++ b/templates/queue.html @@ -3,12 +3,29 @@ {% block title %}Bors queue - {{ repo_name }} {% if tree_state.is_closed() %} [TREECLOSED] {% endif %}{% endblock %} {% block head %} + + {% endblock %} @@ -32,72 +49,144 @@

{{ stats.failed_count }} failed, {{ stats.rolled_up_count }} rolled up

- - - - - - - - - - - - - - - {% for pr in prs %} - - - - - - - - - - - - {% endfor %} - -
#StatusMergeableTitleAuthorAssigneesApproved byPriorityRollup
- {{ pr.number.0 }} - - {% if let Some(try_build) = pr.try_build %} - {{ try_build.status }} (try) - {% else %} - {% match pr.queue_status() %} - {% when Approved(_) %} - approved - {% when ReadyForMerge(_, _) %} - ready for merge - {% when Pending(_, _) %} - pending - {% when Stalled(_, _) %} - stalled - {% when NotApproved %} - {% endmatch %} - {% endif %} - - {% match pr.mergeable_state %} - {% when Mergeable %} - yes - {% when HasConflicts %} - no - {% when Unknown %} - {% endmatch %} - {{ pr.title }}{{ pr.author }}{{ pr.assignees|join(", ") }} - {% if let Some(approver) = pr.approver() %} - {{ approver }} - {% endif %} - {{ pr.priority.unwrap_or(0) }} - {% if let Some(rollup) = pr.rollup %} - {{ rollup }} - {% endif %} -
+
+ + +
+ +
+ + + + + + + + + + + + + + + + + {% for pr in prs %} + + + + + + + + + + + + {% endfor %} + +
#StatusMergeableTitleAuthorAssigneesApproved byPriorityRollup
+ {{ pr.number.0 }} + + {% if let Some(try_build) = pr.try_build %} + {{ crate::templates::status_text(pr) }} (try) + {% else %} + {{ crate::templates::status_text(pr) }} + {% endif %} + + {% match pr.mergeable_state %} + {% when Mergeable %} + yes + {% when HasConflicts %} + no + {% when Unknown %} + {% endmatch %} + {{ pr.title }}{{ pr.author }}{{ pr.assignees|join(", ") }} + {% if let Some(approver) = pr.approver() %} + {{ approver }} + {% endif %} + {{ pr.priority.unwrap_or(0) }} + {% if let Some(rollup) = pr.rollup %} + {{ rollup }} + {% endif %} +
+
+ + + + + + {% endblock %}