swarm: the notification router tells a PR's author when CI on it fails or is cancelled
This commit is contained in:
parent
d4e58f8741
commit
c8eaa93268
3 changed files with 490 additions and 60 deletions
|
|
@ -1892,6 +1892,14 @@ fn hook_registration(kind: DeliveryKind) -> (&'static [&'static str], HookScope<
|
|||
],
|
||||
HookScope::Instance,
|
||||
),
|
||||
// Instance-wide too: the outcome of a CI run, which the router tells a
|
||||
// PR's author about. A hook of its own, because Forgejo's hook edit
|
||||
// never sets `workflow_run_*` events: a hook can only get them when it
|
||||
// is created.
|
||||
DeliveryKind::WorkflowRun => (
|
||||
&["workflow_run_failure", "workflow_run_cancelled"],
|
||||
HookScope::Instance,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2244,10 +2252,15 @@ mod tests {
|
|||
"pull_request_review_comment",
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
events(DeliveryKind::WorkflowRun),
|
||||
["workflow_run_failure", "workflow_run_cancelled"]
|
||||
);
|
||||
// The events a stored flow's source may name are the ones the hooks
|
||||
// deliver to the router.
|
||||
let mut routed = events(DeliveryKind::Issues);
|
||||
routed.extend(events(DeliveryKind::PullRequest));
|
||||
routed.extend(events(DeliveryKind::WorkflowRun));
|
||||
routed.sort_unstable();
|
||||
let mut sources = swarm_wire::notify_flows::SOURCE_EVENTS
|
||||
.iter()
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ mod tests {
|
|||
let Json(view) = get_flows(State(state.clone())).await.expect("get");
|
||||
assert_eq!(view.revision, 0);
|
||||
assert!(view.disabled_builtins.is_empty() && view.flows.is_empty());
|
||||
assert_eq!(view.builtins.len(), 4);
|
||||
assert_eq!(view.builtins.len(), notify_flows::builtins().len());
|
||||
assert!(view.builtins.iter().any(|f| f.id == "head-classifier"));
|
||||
let json = serde_json::to_value(&view).expect("serializes");
|
||||
assert_eq!(json["schema"]["limits"]["max_nodes"], 64);
|
||||
|
|
@ -331,7 +331,11 @@ mod tests {
|
|||
.expect("read")
|
||||
.expect("stored");
|
||||
let doc = Document::decode(&bytes).expect("the router reads it");
|
||||
assert_eq!(doc.active().0.len(), 4, "3 built-ins and the custom flow");
|
||||
assert_eq!(
|
||||
doc.active().0.len(),
|
||||
notify_flows::builtins().len(),
|
||||
"the built-ins less the switched-off one, and the custom flow"
|
||||
);
|
||||
|
||||
// A refused save changes nothing: an orphan node, and a built-in that does not exist.
|
||||
let mut orphan = custom("orphan");
|
||||
|
|
|
|||
|
|
@ -420,6 +420,13 @@ pub(super) enum DeliveryKind {
|
|||
/// the instance, kept the same way.
|
||||
#[strum(serialize = "pull-request")]
|
||||
PullRequest,
|
||||
/// Every finished CI run that failed or was cancelled, on every repo in
|
||||
/// the instance, kept the same way. Its own hook: Forgejo's hook edit
|
||||
/// ignores the `workflow_run_*` events, so they can only be set when a
|
||||
/// hook is created, and a `pull-request` hook registered earlier could not
|
||||
/// gain them.
|
||||
#[strum(serialize = "workflow-run")]
|
||||
WorkflowRun,
|
||||
}
|
||||
|
||||
/// The route prefix a registered `target_url` must point at.
|
||||
|
|
@ -435,13 +442,14 @@ impl DeliveryKind {
|
|||
/// Every kind, for the registration sweep. An array rather than a
|
||||
/// hand-written list at the call site, so adding a kind cannot leave one
|
||||
/// hook unregistered.
|
||||
pub(super) const ALL: [Self; 6] = [
|
||||
pub(super) const ALL: [Self; 7] = [
|
||||
Self::Knowledge,
|
||||
Self::ConfigPr,
|
||||
Self::VcsActivity,
|
||||
Self::ReviewRequest,
|
||||
Self::Issues,
|
||||
Self::PullRequest,
|
||||
Self::WorkflowRun,
|
||||
];
|
||||
|
||||
/// The `target_url` to register with Forgejo for this kind, given the
|
||||
|
|
@ -549,8 +557,8 @@ pub(super) fn verify(
|
|||
/// comment for why both this and a periodic poll write the same cache), and a
|
||||
/// merge queues a deploy of the merged commit on the agent's hive. A
|
||||
/// `ReviewRequest` delivery naming the review classifier's account starts a
|
||||
/// review run in the background. An `Issues` or `PullRequest` delivery is
|
||||
/// kept in the forge events stream for the notification router
|
||||
/// review run in the background. An `Issues`, `PullRequest` or `WorkflowRun`
|
||||
/// delivery is kept in the forge events stream for the notification router
|
||||
/// (`crate::forge_events`).
|
||||
///
|
||||
/// Returns 200 on an accepted delivery so Forgejo does not retry. A refused
|
||||
|
|
@ -564,7 +572,8 @@ pub(super) fn verify(
|
|||
params(
|
||||
("kind" = String, Path, description = "which swarm-wide hook this delivery arrived on: \
|
||||
`knowledge`, `config-pr`, `vcs-activity`, \
|
||||
`review-request`, `issues` or `pull-request`")
|
||||
`review-request`, `issues`, `pull-request` or \
|
||||
`workflow-run`")
|
||||
),
|
||||
request_body(
|
||||
content = String,
|
||||
|
|
@ -637,7 +646,7 @@ pub(super) async fn post_webhook_forge(
|
|||
}
|
||||
}
|
||||
DeliveryKind::ReviewRequest => crate::review_classifier::review::on_delivery(&state, &body),
|
||||
DeliveryKind::Issues | DeliveryKind::PullRequest => {
|
||||
DeliveryKind::Issues | DeliveryKind::PullRequest | DeliveryKind::WorkflowRun => {
|
||||
if let Err(not_kept) = crate::forge_events::publish(&state, &headers, body).await {
|
||||
tracing::warn!(kind = <&str>::from(kind), reason = ?not_kept, "webhook: forge event not kept");
|
||||
return (StatusCode::SERVICE_UNAVAILABLE, "forge event not kept").into_response();
|
||||
|
|
|
|||
Loading…
Reference in a new issue