Skip to content

Commit 7e42019

Browse files
Revert "Add root config file support for analysis tuning and improve SoMEF failure handling"
1 parent 04ca67c commit 7e42019

10 files changed

Lines changed: 29 additions & 491 deletions

File tree

README.md

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -170,54 +170,6 @@ By default, the JSON-LD files generated by RsMetaCheck will only contain informa
170170
poetry run rsmetacheck --input https://github.com/tidyverse/tidyverse --verbose
171171
```
172172

173-
#### Configure Analysis with a Root Config File
174-
175-
You can configure RsMetaCheck with a TOML file at the repository root named `.rsmetacheck.toml` (auto-detected), or pass a custom path with `--config`.
176-
177-
Supported options:
178-
179-
- `ignore`: warnings/pitfalls to ignore (e.g. `P001`, `W002`)
180-
- `exclude_files`: metadata sources to ignore (glob, filename, or substring match)
181-
- `parameters`: per-check parameters for configurable checks
182-
- `profiles`: alternate configurations such as `unstable` or `prerelease`
183-
184-
Example:
185-
186-
```toml
187-
ignore = ["W002"]
188-
exclude_files = ["**/generated/**", "tmp_metadata.json"]
189-
190-
[parameters.P001]
191-
ahead_significant_diff = 2
192-
193-
[parameters.W002]
194-
stale_after_days = 3
195-
196-
[profiles.unstable]
197-
ignore = ["W002", "P017"]
198-
199-
[profiles.unstable.parameters.P001]
200-
ahead_significant_diff = 10
201-
202-
[profiles.prerelease]
203-
ignore = []
204-
205-
[profiles.prerelease.parameters.P001]
206-
ahead_significant_diff = 1
207-
```
208-
209-
Use a specific profile:
210-
211-
```bash
212-
poetry run rsmetacheck --input https://github.com/example/repo --config-profile unstable
213-
```
214-
215-
Use a custom config path:
216-
217-
```bash
218-
poetry run rsmetacheck --input https://github.com/example/repo --config ./ci/rsmetacheck.toml
219-
```
220-
221173
### Output
222174

223175
The tool will:

docs/usage.md

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -35,36 +35,6 @@ Run the analysis:
3535
poetry run rsmetacheck --input repositories.json
3636
```
3737

38-
### Configure Analysis Rules
39-
40-
RsMetaCheck can load a root-level `.rsmetacheck.toml` file to customize analysis behavior.
41-
42-
```toml
43-
ignore = ["W002"]
44-
exclude_files = ["tmp_metadata.json"]
45-
46-
[parameters.P001]
47-
ahead_significant_diff = 10
48-
49-
[profiles.prerelease]
50-
ignore = []
51-
52-
[profiles.unstable]
53-
ignore = ["W002", "P017"]
54-
```
55-
56-
Use a profile:
57-
58-
```bash
59-
poetry run rsmetacheck --input https://github.com/example/repo --config-profile unstable
60-
```
61-
62-
Use an explicit config path:
63-
64-
```bash
65-
poetry run rsmetacheck --input https://github.com/example/repo --config ./ci/rsmetacheck.toml
66-
```
67-
6838
## GitHub Action
6939

7040
You can integrate RSMetaCheck into your GitHub workflows:

src/rsmetacheck/cli.py

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import os
33
from pathlib import Path
44

5-
from rsmetacheck.config import load_analysis_config
65
from rsmetacheck.run_analyzer import run_analysis
76
from rsmetacheck.run_somef import (
87
ensure_somef_configured,
@@ -70,28 +69,9 @@ def cli():
7069
action="store_true",
7170
help="Include both detected AND undetected pitfalls in the output JSON-LD.",
7271
)
73-
parser.add_argument(
74-
"--config",
75-
default=None,
76-
help="Path to RsMetaCheck TOML config file (default: auto-detect .rsmetacheck.toml at repository root).",
77-
)
78-
parser.add_argument(
79-
"--config-profile",
80-
default=None,
81-
help="Name of config profile to apply (e.g., unstable, prerelease).",
82-
)
8372

8473
args = parser.parse_args()
8574

86-
try:
87-
analysis_config = load_analysis_config(
88-
config_path=args.config,
89-
profile=args.config_profile,
90-
)
91-
except (FileNotFoundError, ValueError, OSError, Exception) as exc:
92-
print(f"Error loading config: {exc}")
93-
return
94-
9575
if args.skip_somef:
9676
print(
9777
f"Skipping SoMEF execution. Analyzing {len(args.input)} existing SoMEF output files..."
@@ -115,7 +95,6 @@ def cli():
11595
args.analysis_output,
11696
verbose=args.verbose,
11797
notes_output=args.notes_output,
118-
analysis_config=analysis_config,
11998
)
12099

121100
else:
@@ -131,51 +110,37 @@ def cli():
131110
"Codemeta generation is ENABLED. Codemeta files will be created for each repository."
132111
)
133112

134-
any_somef_success = False
135-
136113
for input_item in args.input:
137114
if input_item.startswith("http://") or input_item.startswith("https://"):
138115
print(f"Processing repository URL: {input_item}")
139-
success = run_somef_single(
116+
run_somef_single(
140117
input_item,
141118
somef_output_dir,
142119
threshold,
143120
branch=args.branch,
144121
generate_codemeta=generate_codemeta,
145122
)
146-
any_somef_success = any_somef_success or bool(success)
147123
elif os.path.exists(input_item):
148124
print(f"Processing repositories from file: {input_item}")
149-
success = run_somef_batch(
125+
run_somef_batch(
150126
input_item,
151127
somef_output_dir,
152128
threshold,
153129
branch=args.branch,
154130
generate_codemeta=generate_codemeta,
155131
)
156-
any_somef_success = any_somef_success or bool(success)
157132
else:
158133
print(
159134
f"Warning: Skipping invalid input (not a URL or existing file): {input_item}"
160135
)
161136

162-
if not any_somef_success:
163-
print(
164-
"Error: SoMEF did not produce any outputs. Analysis is aborted."
165-
)
166-
print(
167-
"Fix SoMEF/authentication issues and rerun, or run with --skip-somef on existing SoMEF JSON files."
168-
)
169-
return
170-
171137
print(f"\nRunning analysis on outputs in {somef_output_dir}...")
172138
run_analysis(
173139
somef_output_dir,
174140
args.pitfalls_output,
175141
args.analysis_output,
176142
verbose=args.verbose,
177143
notes_output=args.notes_output,
178-
analysis_config=analysis_config,
179144
)
180145

181146

src/rsmetacheck/detect_pitfalls_main.py

Lines changed: 4 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import json
2-
import copy
3-
import fnmatch
4-
import inspect
52
from pathlib import Path
63
from typing import Iterable, Union
74
from rsmetacheck.run_somef import CODEMETA_DEFAULT_NAME
8-
from rsmetacheck.config import AnalysisConfig
95
from rsmetacheck.utils.pitfall_utils import extract_programming_languages
106
from rsmetacheck.utils.json_ld_utils import create_pitfall_jsonld, save_individual_pitfall_jsonld
117
from rsmetacheck.utils.somef_compat import normalize_somef_data
@@ -44,89 +40,7 @@
4440
from rsmetacheck.scripts.warnings.w010 import detect_git_remote_shorthand_pitfall
4541

4642

47-
def _source_matches_exclude_patterns(source_value: str, exclude_patterns: list[str]) -> bool:
48-
source = str(source_value)
49-
basename = Path(source).name
50-
51-
for pattern in exclude_patterns:
52-
if fnmatch.fnmatch(source, pattern):
53-
return True
54-
if fnmatch.fnmatch(basename, pattern):
55-
return True
56-
if pattern in source:
57-
return True
58-
59-
return False
60-
61-
62-
def _filter_somef_data_by_excluded_files(data, exclude_patterns: list[str]):
63-
if isinstance(data, dict):
64-
filtered_dict = {}
65-
66-
for key, value in data.items():
67-
if key == "source":
68-
if isinstance(value, list):
69-
kept_sources = [
70-
src for src in value if not _source_matches_exclude_patterns(src, exclude_patterns)
71-
]
72-
if not kept_sources:
73-
return None
74-
filtered_dict[key] = kept_sources
75-
else:
76-
if _source_matches_exclude_patterns(value, exclude_patterns):
77-
return None
78-
filtered_dict[key] = value
79-
continue
80-
81-
filtered_value = _filter_somef_data_by_excluded_files(value, exclude_patterns)
82-
if filtered_value is not None:
83-
filtered_dict[key] = filtered_value
84-
85-
return filtered_dict
86-
87-
if isinstance(data, list):
88-
filtered_list = []
89-
for item in data:
90-
filtered_item = _filter_somef_data_by_excluded_files(item, exclude_patterns)
91-
if filtered_item is not None:
92-
filtered_list.append(filtered_item)
93-
return filtered_list
94-
95-
return data
96-
97-
98-
def _run_detector_with_parameters(detector_func, somef_data, file_name: str, parameters: dict):
99-
if not parameters:
100-
return detector_func(somef_data, file_name)
101-
102-
signature = inspect.signature(detector_func)
103-
accepts_kwargs = any(
104-
param.kind == inspect.Parameter.VAR_KEYWORD
105-
for param in signature.parameters.values()
106-
)
107-
108-
if accepts_kwargs:
109-
return detector_func(somef_data, file_name, **parameters)
110-
111-
accepted_parameter_names = set(signature.parameters.keys()) - {"somef_data", "file_name"}
112-
filtered_parameters = {
113-
key: value for key, value in parameters.items() if key in accepted_parameter_names
114-
}
115-
116-
if filtered_parameters:
117-
return detector_func(somef_data, file_name, **filtered_parameters)
118-
119-
return detector_func(somef_data, file_name)
120-
121-
122-
def detect_all_pitfalls(
123-
json_files: Iterable[Path],
124-
pitfalls_output_dir: Union[str, Path],
125-
output_file: Union[str, Path],
126-
verbose: bool = False,
127-
notes_output: Union[str, Path] = None,
128-
analysis_config: AnalysisConfig = None,
129-
):
43+
def detect_all_pitfalls(json_files: Iterable[Path], pitfalls_output_dir: Union[str, Path], output_file: Union[str, Path], verbose: bool = False, notes_output: Union[str, Path] = None):
13044
"""
13145
Detect all software repository pitfalls in SoMEF output files using modular detectors.
13246
Now also generates individual JSON-LD files for each repository.
@@ -135,21 +49,12 @@ def detect_all_pitfalls(
13549
pitfalls_output_dir = Path(pitfalls_output_dir)
13650
pitfalls_output_dir.mkdir(exist_ok=True, parents=True)
13751
json_files = list(json_files)
138-
config = analysis_config or AnalysisConfig.empty()
13952

14053
if not json_files:
14154
print("No JSON files found for analysis.")
14255
return
14356

14457
print(f"Analyzing {len(json_files)} SoMEF JSON files...")
145-
if config.source_path:
146-
print(f"Using config file: {config.source_path}")
147-
if config.profile:
148-
print(f"Using config profile: {config.profile}")
149-
if config.ignored_checks:
150-
print(f"Ignoring checks: {', '.join(sorted(config.ignored_checks))}")
151-
if config.exclude_files:
152-
print(f"Excluded source patterns: {config.exclude_files}")
15358

15459
results = {
15560
"summary": {
@@ -416,13 +321,6 @@ def detect_all_pitfalls(
416321
somef_data = json.load(f)
417322

418323
somef_data = normalize_somef_data(somef_data)
419-
if config.exclude_files:
420-
somef_data = _filter_somef_data_by_excluded_files(
421-
copy.deepcopy(somef_data),
422-
config.exclude_files,
423-
)
424-
if somef_data is None:
425-
somef_data = {}
426324

427325
languages = extract_programming_languages(somef_data)
428326

@@ -432,16 +330,8 @@ def detect_all_pitfalls(
432330
repo_pitfall_results = []
433331

434332
for idx, (detector_func, pitfall_code) in enumerate(pitfall_detectors):
435-
if config.is_ignored(pitfall_code):
436-
continue
437-
438333
try:
439-
detector_results = _run_detector_with_parameters(
440-
detector_func,
441-
somef_data,
442-
json_file.name,
443-
config.get_parameters(pitfall_code),
444-
)
334+
detector_results = detector_func(somef_data, json_file.name)
445335
if not isinstance(detector_results, list):
446336
detector_results = [detector_results]
447337

@@ -610,15 +500,7 @@ def detect_all_pitfalls(
610500
print(f"Error writing output file: {e}")
611501

612502

613-
def main(
614-
input_dir=None,
615-
somef_json_paths=None,
616-
pitfalls_dir=None,
617-
analysis_output=None,
618-
verbose=False,
619-
notes_output=None,
620-
analysis_config: AnalysisConfig = None,
621-
):
503+
def main(input_dir=None, somef_json_paths=None, pitfalls_dir=None, analysis_output=None, verbose=False, notes_output=None):
622504
"""
623505
Main function to run all pitfall detections.
624506
@@ -659,14 +541,7 @@ def main(
659541
print("No JSON files found for analysis.")
660542
return
661543

662-
detect_all_pitfalls(
663-
json_files,
664-
pitfalls_directory,
665-
output_file,
666-
verbose,
667-
notes_output,
668-
analysis_config=analysis_config,
669-
)
544+
detect_all_pitfalls(json_files, pitfalls_directory, output_file, verbose, notes_output)
670545

671546
if __name__ == "__main__":
672547
main()

0 commit comments

Comments
 (0)