Skip to content

g1t/crates/rules/src/outcome.rs

91 lines2,891 bytesCodeBlame

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Merge rulesets: branch and tag rules, agent-first, enforced on push and merge1//! How one ruleset judged one change, and how several stack.
2
3use g1t_contracts::rules::{Applicable, BypassMode, Enforcement, Level, Verdict, Violation};
4
5use crate::content::Problem;
6
7/// One ruleset's judgement of one change to one ref.
8#[derive(Clone, Debug, PartialEq)]
9pub struct Judged {
10 pub id: String,
11 pub name: String,
12 pub level: Level,
13 pub enforcement: Enforcement,
14 pub bypass: Option<BypassMode>,
15 /// The full ref.
16 pub git_ref: String,
17 pub violations: Vec<Violation>,
18 /// Whether the change is a pull request merging (a bypass "for pull
19 /// requests" holds) rather than a push.
20 pub merging: bool,
21}
22
23impl Judged {
24 pub(crate) fn of(ruleset: &Applicable, git_ref: &str, merging: bool) -> Judged {
25 Judged {
26 id: ruleset.id.clone(),
27 name: ruleset.name.clone(),
28 level: ruleset.level,
29 enforcement: ruleset.enforcement,
30 bypass: ruleset.bypass,
31 git_ref: git_ref.to_owned(),
32 violations: Vec::new(),
33 merging,
34 }
35 }
36
37 pub(crate) fn add(&mut self, rule: &str, problem: Problem) {
38 self.violations.push(Violation {
39 rule: rule.to_owned(),
40 ruleset_id: self.id.clone(),
41 ruleset_name: self.name.clone(),
42 enforcement: self.enforcement,
43 message: problem.message,
44 remedy: problem.remedy,
45 });
46 }
47
48 /// Whether the actor's bypass holds for this change.
49 pub fn bypassed(&self) -> bool {
50 match self.bypass {
51 Some(BypassMode::Always) => true,
52 Some(BypassMode::PullRequests) => self.merging,
53 None => false,
54 }
55 }
56
57 pub fn verdict(&self) -> Verdict {
58 if self.violations.is_empty() {
59 Verdict::Pass
60 } else if self.bypassed() {
61 Verdict::Bypass
62 } else {
63 Verdict::Fail
64 }
65 }
66
67 /// Whether it refuses the change: an active ruleset that failed.
68 pub fn blocks(&self) -> bool {
69 self.enforcement == Enforcement::Active && self.verdict() == Verdict::Fail
70 }
71
72 /// Whether it would refuse it, were it active.
73 pub fn would_block(&self) -> bool {
74 self.enforcement == Enforcement::Evaluate && self.verdict() == Verdict::Fail
75 }
76}
77
78/// The violations that refuse the change, across rulesets.
79pub fn blocking(judged: &[Judged]) -> Vec<&Violation> {
80 judged.iter().filter(|one| one.blocks()).flat_map(|one| one.violations.iter()).collect()
81}
82
83/// The violations rulesets in `evaluate` would have refused it for.
84pub fn would_block(judged: &[Judged]) -> Vec<&Violation> {
85 judged.iter().filter(|one| one.would_block()).flat_map(|one| one.violations.iter()).collect()
86}
87
88/// Whether anything refuses the change.
89pub fn refused(judged: &[Judged]) -> bool {
90 judged.iter().any(Judged::blocks)
91}

This file's history is long; its oldest lines are credited to the oldest commit read.