lex-detect 0.1.7 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/CLAUDE.md +2 -2
- data/lib/legion/extensions/detect/formatters/json.rb +23 -0
- data/lib/legion/extensions/detect/formatters/markdown_pr.rb +61 -0
- data/lib/legion/extensions/detect/formatters/sarif.rb +82 -0
- data/lib/legion/extensions/detect/formatters.rb +23 -0
- data/lib/legion/extensions/detect/version.rb +1 -1
- data/lib/legion/extensions/detect.rb +6 -0
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8e8430d894d1792494f0781c7f13c28de7da13817c40fa3a9f80cfc4c89bc9ad
|
|
4
|
+
data.tar.gz: 2bff9f69460165c22a025dc97912639202cca9200366e91dafbc84dc9d37bb8f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b087321a87beeff9cd42417286a39477edd5608ca8190bc67877b6e55b57f6bd4f971c05b802eadf47b68967acbb40c0e74b96c25a1d970d1431adffc3f43d2a
|
|
7
|
+
data.tar.gz: 6f9c61761fad7069ad09110f21d23227a664a606fcc5b50737d0d05c462ce9240b60e6f91a7d3b1684845b76c92f1500e2951a512725c33880eafacbc8ac3274
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.1] - 2026-03-22
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `Formatters::Json` passthrough formatter returning detections unchanged (or as pretty-printed JSON via `.to_json`)
|
|
7
|
+
- `Formatters` module entry point with `Formatters.format(detections, format:)` dispatcher for `:sarif`, `:markdown`, and `:json`
|
|
8
|
+
- `format_results` now delegates to `Formatters.format` instead of dispatching inline
|
|
9
|
+
- 5 new specs for `Formatters::Json` covering passthrough identity, field preservation, JSON serialization, and empty input
|
|
10
|
+
|
|
11
|
+
## [0.2.0] - 2026-03-22
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- SARIF 2.1.0 formatter (`Formatters::Sarif`) for GitHub Code Scanning integration
|
|
15
|
+
- Markdown PR comment formatter (`Formatters::MarkdownPr`) for GitHub PR annotations
|
|
16
|
+
- `format_results(format:, detections:)` public API method supporting `:sarif`, `:markdown`, and `:json` output formats
|
|
17
|
+
|
|
3
18
|
## [0.1.7] - 2026-03-22
|
|
4
19
|
|
|
5
20
|
### Fixed
|
data/CLAUDE.md
CHANGED
|
@@ -10,7 +10,7 @@ Legion Extension that scans the local environment and recommends which `lex-*` e
|
|
|
10
10
|
|
|
11
11
|
**GitHub**: https://github.com/LegionIO/lex-detect
|
|
12
12
|
**License**: MIT
|
|
13
|
-
**Version**: 0.
|
|
13
|
+
**Version**: 0.2.0
|
|
14
14
|
|
|
15
15
|
## Architecture
|
|
16
16
|
|
|
@@ -57,7 +57,7 @@ Legion::Extensions::Detect.catalog # raw CATALOG constant
|
|
|
57
57
|
|
|
58
58
|
## Testing
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
54 specs across 9 spec files.
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
63
|
bundle install
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Detect
|
|
8
|
+
module Formatters
|
|
9
|
+
module Json
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def format(detections)
|
|
13
|
+
detections
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_json(detections)
|
|
17
|
+
::JSON.pretty_generate(format(detections))
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Detect
|
|
6
|
+
module Formatters
|
|
7
|
+
module MarkdownPr
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
def format(detections)
|
|
11
|
+
missing = collect_missing(detections)
|
|
12
|
+
installed = collect_installed(detections)
|
|
13
|
+
|
|
14
|
+
lines = ["## Legion Detect Findings\n"]
|
|
15
|
+
|
|
16
|
+
if missing.any?
|
|
17
|
+
lines << "### Missing Extensions (#{missing.size})\n"
|
|
18
|
+
missing.each do |m|
|
|
19
|
+
lines << "- **#{m[:name]}**: `#{m[:extension]}` not installed"
|
|
20
|
+
lines << " Detected by: #{m[:signals].join(', ')}"
|
|
21
|
+
lines << " Install: `gem install #{m[:extension]}`\n"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
if installed.any?
|
|
26
|
+
lines << "### Installed (#{installed.size})\n"
|
|
27
|
+
installed.each do |i|
|
|
28
|
+
lines << "- #{i[:name]}: `#{i[:extension]}` :white_check_mark:"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
lines << "No extensions detected.\n" if missing.empty? && installed.empty?
|
|
33
|
+
|
|
34
|
+
lines << "\n---\n*Generated by legion-detect v#{VERSION}*"
|
|
35
|
+
lines.join("\n")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def collect_missing(detections)
|
|
39
|
+
detections.flat_map do |d|
|
|
40
|
+
d[:extensions].filter_map do |ext|
|
|
41
|
+
next if d[:installed][ext]
|
|
42
|
+
|
|
43
|
+
{ name: d[:name], extension: ext, signals: d[:matched_signals] }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def collect_installed(detections)
|
|
49
|
+
detections.flat_map do |d|
|
|
50
|
+
d[:extensions].filter_map do |ext|
|
|
51
|
+
next unless d[:installed][ext]
|
|
52
|
+
|
|
53
|
+
{ name: d[:name], extension: ext }
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Detect
|
|
8
|
+
module Formatters
|
|
9
|
+
module Sarif
|
|
10
|
+
SCHEMA = 'https://json.schemastore.org/sarif-2.1.0.json'
|
|
11
|
+
SARIF_VERSION = '2.1.0'
|
|
12
|
+
|
|
13
|
+
SEVERITY_MAP = {
|
|
14
|
+
missing: 'warning',
|
|
15
|
+
installed: 'note'
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
module_function
|
|
19
|
+
|
|
20
|
+
def format(detections)
|
|
21
|
+
rules = build_rules(detections)
|
|
22
|
+
results = build_results(detections)
|
|
23
|
+
|
|
24
|
+
{
|
|
25
|
+
'$schema' => SCHEMA,
|
|
26
|
+
'version' => SARIF_VERSION,
|
|
27
|
+
'runs' => [{
|
|
28
|
+
'tool' => {
|
|
29
|
+
'driver' => {
|
|
30
|
+
'name' => 'legion-detect',
|
|
31
|
+
'version' => VERSION,
|
|
32
|
+
'informationUri' => 'https://github.com/LegionIO/lex-detect',
|
|
33
|
+
'rules' => rules
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
'results' => results
|
|
37
|
+
}]
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def to_json(detections)
|
|
42
|
+
::JSON.pretty_generate(format(detections))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def build_rules(detections)
|
|
46
|
+
rules = detections.flat_map do |detection|
|
|
47
|
+
detection[:extensions].map do |ext|
|
|
48
|
+
{
|
|
49
|
+
'id' => "detect/#{ext}",
|
|
50
|
+
'name' => detection[:name],
|
|
51
|
+
'shortDescription' => { 'text' => "#{detection[:name]} detected — #{ext} recommended" },
|
|
52
|
+
'defaultConfiguration' => { 'level' => 'warning' }
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
rules.uniq { |r| r['id'] }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def build_results(detections)
|
|
60
|
+
detections.flat_map do |detection|
|
|
61
|
+
detection[:extensions].filter_map do |ext|
|
|
62
|
+
next if detection[:installed][ext]
|
|
63
|
+
|
|
64
|
+
{
|
|
65
|
+
'ruleId' => "detect/#{ext}",
|
|
66
|
+
'level' => 'warning',
|
|
67
|
+
'message' => {
|
|
68
|
+
'text' => "#{detection[:name]} detected (#{detection[:matched_signals].join(', ')}) but #{ext} is not installed"
|
|
69
|
+
},
|
|
70
|
+
'properties' => {
|
|
71
|
+
'matched_signals' => detection[:matched_signals],
|
|
72
|
+
'detection_name' => detection[:name]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/detect/formatters/json'
|
|
4
|
+
require 'legion/extensions/detect/formatters/sarif'
|
|
5
|
+
require 'legion/extensions/detect/formatters/markdown_pr'
|
|
6
|
+
|
|
7
|
+
module Legion
|
|
8
|
+
module Extensions
|
|
9
|
+
module Detect
|
|
10
|
+
module Formatters
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
def format(detections, format: :json)
|
|
14
|
+
case format.to_sym
|
|
15
|
+
when :sarif then Sarif.to_json(detections)
|
|
16
|
+
when :markdown then MarkdownPr.format(detections)
|
|
17
|
+
else Json.format(detections)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -4,6 +4,7 @@ require 'legion/extensions/detect/version'
|
|
|
4
4
|
require 'legion/extensions/detect/catalog'
|
|
5
5
|
require 'legion/extensions/detect/scanner'
|
|
6
6
|
require 'legion/extensions/detect/installer'
|
|
7
|
+
require 'legion/extensions/detect/formatters'
|
|
7
8
|
require_relative 'detect/runners/task_observer'
|
|
8
9
|
require_relative 'detect/runners/cancel_task'
|
|
9
10
|
|
|
@@ -41,6 +42,11 @@ module Legion
|
|
|
41
42
|
def catalog
|
|
42
43
|
CATALOG
|
|
43
44
|
end
|
|
45
|
+
|
|
46
|
+
def format_results(format: :json, detections: nil)
|
|
47
|
+
results = detections || scan
|
|
48
|
+
Formatters.format(results, format: format)
|
|
49
|
+
end
|
|
44
50
|
end
|
|
45
51
|
|
|
46
52
|
require_relative 'detect/actors/full_scan' if defined?(Legion::Extensions::Actors::Once)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lex-detect
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -31,6 +31,10 @@ files:
|
|
|
31
31
|
- lib/legion/extensions/detect/actors/full_scan.rb
|
|
32
32
|
- lib/legion/extensions/detect/actors/observer_tick.rb
|
|
33
33
|
- lib/legion/extensions/detect/catalog.rb
|
|
34
|
+
- lib/legion/extensions/detect/formatters.rb
|
|
35
|
+
- lib/legion/extensions/detect/formatters/json.rb
|
|
36
|
+
- lib/legion/extensions/detect/formatters/markdown_pr.rb
|
|
37
|
+
- lib/legion/extensions/detect/formatters/sarif.rb
|
|
34
38
|
- lib/legion/extensions/detect/installer.rb
|
|
35
39
|
- lib/legion/extensions/detect/local_migrations/20260319000001_create_detect_results.rb
|
|
36
40
|
- lib/legion/extensions/detect/local_migrations/20260320000001_create_observer_events.rb
|