Skip to content

Commit 406ff0a

Browse files
authored
Deprecate override in favour of triage (#2005)
qltysh/cloud#5925
1 parent 6ac4ae4 commit 406ff0a

File tree

16 files changed

+301
-94
lines changed

16 files changed

+301
-94
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

qlty-check/src/planner.rs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@ use crate::planner::config_files::PluginConfigFile;
1010
use crate::Settings;
1111
use anyhow::{bail, Error, Result};
1212
use check_filters::CheckFilters;
13+
use console::style;
1314
use document_url_generator::DocumentUrlGenerator;
1415
use itertools::Itertools;
1516
use qlty_analysis::cache::{Cache, FilesystemCache, NullCache};
1617
use qlty_analysis::git::{compute_upstream, DiffLineFilter};
1718
use qlty_analysis::workspace_entries::TargetMode;
1819
use qlty_config::config::issue_transformer::IssueTransformer;
19-
use qlty_config::config::{DriverType, PluginDef};
20+
use qlty_config::config::{DriverType, Match, PluginDef, Set, Triage};
2021
use qlty_config::{QltyConfig, Workspace};
2122
use qlty_types::analysis::v1::ExecutionVerb;
23+
use qlty_types::{category_from_str, level_from_str};
2224
use rayon::prelude::*;
2325
use std::collections::HashMap;
2426
use std::time::Instant;
@@ -271,12 +273,48 @@ impl Planner {
271273
self.transformers
272274
.push(Box::new(IssueMuter::new(self.staging_area.clone())));
273275

274-
// keep overrides last
275-
for issue_override in &self.config.overrides {
276-
self.transformers.push(Box::new(issue_override.clone()));
276+
// keep triage last
277+
let triages = self.build_triages();
278+
for issue_triage in &triages {
279+
self.transformers.push(Box::new(issue_triage.clone()));
277280
}
278281
}
279282

283+
fn build_triages(&self) -> Vec<Triage> {
284+
let mut triages = self.config.triage.clone();
285+
286+
if !self.config.overrides.is_empty() {
287+
eprintln!(
288+
"{} The `{}` field in qlty.toml is deprecated. Please use `{}` instead.",
289+
style("WARNING:").bold().yellow(),
290+
style("override").bold(),
291+
style("triage").bold()
292+
);
293+
294+
for issue_override in &self.config.overrides {
295+
triages.push(Triage {
296+
set: Set {
297+
level: issue_override.level.as_ref().map(|l| level_from_str(l)),
298+
category: issue_override
299+
.category
300+
.as_ref()
301+
.map(|c| category_from_str(c)),
302+
mode: issue_override.mode,
303+
..Default::default()
304+
},
305+
r#match: Match {
306+
plugins: issue_override.plugins.clone(),
307+
rules: issue_override.rules.clone(),
308+
file_patterns: issue_override.file_patterns.clone(),
309+
..Default::default()
310+
},
311+
});
312+
}
313+
}
314+
315+
triages
316+
}
317+
280318
fn build_plan(&mut self) -> Result<Plan> {
281319
let target_mode = self
282320
.target_mode

qlty-cli/tests/cmd/check/override.in/.qlty/qlty.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,7 @@ batch = true
1212
[[plugin]]
1313
name = "exists"
1414
version = "1.0.0"
15+
16+
[[override]]
17+
plugin = "exists"
1518
mode = "monitor"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
WARNING: The `override` field in qlty.toml is deprecated. Please use `triage` instead.
12
✖ 1 issue
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.qlty/results
2+
.qlty/logs
3+
.qlty/out
4+
.qlty/sources
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
config_version = "0"
2+
3+
[plugins.definitions.triaged]
4+
file_types = ["shell"]
5+
6+
[plugins.definitions.triaged.drivers.lint]
7+
script = "false"
8+
success_codes = [0]
9+
output = "pass_fail"
10+
batch = true
11+
12+
[[plugin]]
13+
name = "triaged"
14+
version = "1.0.0"
15+
16+
[plugins.definitions.untriaged]
17+
file_types = ["shell"]
18+
19+
[plugins.definitions.untriaged.drivers.lint]
20+
script = "false"
21+
success_codes = [0]
22+
output = "pass_fail"
23+
batch = true
24+
25+
[[plugin]]
26+
name = "untriaged"
27+
version = "1.0.0"
28+
29+
[[triage]]
30+
match.plugins = ["triaged"]
31+
set.mode = "comment"
32+
set.level = "low"
33+
set.category = "structure"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
echo "$foo"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#/usr/bin/env bash
2+
rm -fr ~/.cache/qlty/tools/ruby ~/.cache/qlty/tools/rubocop
3+
4+
export RUNTIME="ruby"
5+
export RUNTIME_VERSION="3.2.2"
6+
7+
runtime_directory="/Users/bhelmkamp/.cache/qlty/tools/$RUNTIME/$RUNTIME_VERSION"
8+
mkdir -p $runtime_directory
9+
cd $runtime_directory || exit
10+
11+
download_filename="v20230330.tar.gz"
12+
download_url="https://github.com/rbenv/ruby-build/archive/refs/tags/$download_filename"
13+
wget "$download_url"
14+
tar --strip-components=1 -xpvzf $download_filename
15+
rm $download_filename
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
✖ 2 issues
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[
2+
{
3+
"tool": "untriaged",
4+
"ruleKey": "fail",
5+
"message": "untriaged failed",
6+
"level": "LEVEL_HIGH",
7+
"category": "CATEGORY_LINT",
8+
"mode": "MODE_BLOCK"
9+
},
10+
{
11+
"tool": "triaged",
12+
"ruleKey": "fail",
13+
"message": "triaged failed",
14+
"level": "LEVEL_LOW",
15+
"category": "CATEGORY_STRUCTURE",
16+
"mode": "MODE_COMMENT"
17+
}
18+
]

qlty-cli/tests/cmd/check/triage.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bin.name = "qlty"
2+
args = ["check", "--all", "--no-cache", "--json"]
3+
status.code = 1

qlty-config/src/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod plugin;
1111
mod release;
1212
pub mod smells;
1313
mod source;
14+
pub mod triage;
1415

1516
pub use self::ignore::{Ignore, ALL_WILDCARD};
1617
pub use self::overrides::Override;
@@ -29,6 +30,7 @@ pub use plugin::{
2930
};
3031
pub use release::ReleaseDef;
3132
pub use source::SourceDef;
33+
pub use triage::{Match, Set, Triage};
3234

3335
use crate::config::plugin::EnabledRuntimes;
3436
pub use crate::config::plugin::PluginsConfig;
@@ -56,6 +58,10 @@ pub struct QltyConfig {
5658
#[serde(rename = "override")] // Since `override` is a reserved keyword
5759
pub overrides: Vec<Override>,
5860

61+
#[serde(default)]
62+
#[serde(rename = "triage")]
63+
pub triage: Vec<Triage>,
64+
5965
#[serde(default)]
6066
pub file_types: HashMap<String, FileType>,
6167

qlty-config/src/config/overrides.rs

Lines changed: 2 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
use super::ignore::is_rule_issue_match;
21
use super::IssueMode;
3-
use crate::config::issue_transformer::IssueTransformer;
4-
use globset::{Glob, GlobSet, GlobSetBuilder};
5-
use qlty_types::category_from_str;
6-
use qlty_types::{analysis::v1::Issue, level_from_str};
72
use schemars::JsonSchema;
83
use serde::{Deserialize, Serialize};
9-
use std::sync::RwLock;
104

11-
#[derive(Debug, Serialize, Deserialize, Default, JsonSchema)]
5+
// DEPRECATED -- Use Triage instead
6+
#[derive(Debug, Serialize, Deserialize, Default, Clone, JsonSchema)]
127
pub struct Override {
138
#[serde(default)]
149
pub level: Option<String>,
@@ -27,87 +22,4 @@ pub struct Override {
2722

2823
#[serde(default)]
2924
pub mode: Option<IssueMode>,
30-
31-
#[serde(skip)]
32-
glob_set: RwLock<Option<GlobSet>>,
33-
}
34-
35-
impl Clone for Override {
36-
fn clone(&self) -> Self {
37-
Self {
38-
level: self.level.clone(),
39-
category: self.category.clone(),
40-
plugins: self.plugins.clone(),
41-
rules: self.rules.clone(),
42-
file_patterns: self.file_patterns.clone(),
43-
mode: self.mode,
44-
glob_set: RwLock::new(None),
45-
}
46-
}
47-
}
48-
49-
impl IssueTransformer for Override {
50-
fn initialize(&self) {
51-
let mut globset_builder = GlobSetBuilder::new();
52-
53-
for glob in &self.file_patterns {
54-
globset_builder.add(Glob::new(glob).unwrap());
55-
}
56-
57-
let mut glob_set = self.glob_set.write().unwrap();
58-
*glob_set = Some(globset_builder.build().unwrap());
59-
}
60-
61-
fn transform(&self, issue: Issue) -> Option<Issue> {
62-
if self.applies_to_issue(&issue) {
63-
let mut new_issue = issue.clone();
64-
65-
if let Some(level) = &self.level {
66-
new_issue.level = level_from_str(level).into();
67-
}
68-
69-
if let Some(category) = &self.category {
70-
new_issue.category = category_from_str(category).into();
71-
}
72-
73-
if let Some(mode) = &self.mode {
74-
new_issue.mode = *mode as i32;
75-
}
76-
77-
Some(new_issue)
78-
} else {
79-
Some(issue)
80-
}
81-
}
82-
83-
fn clone_box(&self) -> Box<dyn IssueTransformer> {
84-
Box::new(self.clone())
85-
}
86-
}
87-
88-
impl Override {
89-
fn applies_to_issue(&self, issue: &Issue) -> bool {
90-
self.plugin_applies_to_issue(issue)
91-
&& is_rule_issue_match(&self.rules, issue)
92-
&& self.glob_applies_to_issue(issue)
93-
}
94-
95-
fn plugin_applies_to_issue(&self, issue: &Issue) -> bool {
96-
self.plugins.is_empty() || self.plugins.contains(&issue.tool.to_string())
97-
}
98-
99-
fn glob_applies_to_issue(&self, issue: &Issue) -> bool {
100-
if self.file_patterns.is_empty() {
101-
return true;
102-
}
103-
104-
let glob_set = self.glob_set.read().unwrap();
105-
106-
if let Some(path) = issue.path() {
107-
glob_set.as_ref().unwrap().is_match(path)
108-
} else {
109-
// TODO: Issues without a path are not filterable
110-
false
111-
}
112-
}
11325
}

0 commit comments

Comments
 (0)