route_guard 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c095ab5dfc78ae856774803b38cd9d4cceb6073d623908014e73f2d48752d2db
4
+ data.tar.gz: edcb632d5f8b621477d8d3f8b612b3c581877308db4807e3e57e8ad835f4bf78
5
+ SHA512:
6
+ metadata.gz: 2dbdfaf0cb426abccbe8e9258742ae121923e635e1f1b6041ebed0d6085fc86409c888e05686c947ccdb757c871ea547a9675a193d0171cfe1c85b9d94ccc6e0
7
+ data.tar.gz: dd07ec99fb9ad444cc5851db746f36eb73f66017ae9c276dafca239e78f90d7df6b19717bfaf0a8c22b5b27171d4e4daa5b346263ed44eef8b796fc8fcf4d554
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ # Test results and coverage
2
+ /coverage/
3
+ /.rspec_status
4
+ /test.log
5
+ /tmp/
6
+
7
+ # Bundler
8
+ /.bundle/
9
+ /vendor/bundle/
10
+
11
+ # Gem builds
12
+ /pkg/
13
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,173 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ route_guard (0.1.0)
5
+ actionpack (>= 6.1)
6
+ railties (>= 6.1)
7
+ rainbow (~> 3.1)
8
+ thor (~> 1.2)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ actionpack (8.1.3.1)
14
+ actionview (= 8.1.3.1)
15
+ activesupport (= 8.1.3.1)
16
+ nokogiri (>= 1.8.5)
17
+ rack (>= 2.2.4)
18
+ rack-session (>= 1.0.1)
19
+ rack-test (>= 0.6.3)
20
+ rails-dom-testing (~> 2.2)
21
+ rails-html-sanitizer (~> 1.6)
22
+ useragent (~> 0.16)
23
+ actionview (8.1.3.1)
24
+ activesupport (= 8.1.3.1)
25
+ builder (~> 3.1)
26
+ erubi (~> 1.11)
27
+ rails-dom-testing (~> 2.2)
28
+ rails-html-sanitizer (~> 1.6)
29
+ activesupport (8.1.3.1)
30
+ base64
31
+ bigdecimal
32
+ concurrent-ruby (~> 1.0, >= 1.3.1)
33
+ connection_pool (>= 2.2.5)
34
+ drb
35
+ i18n (>= 1.6, < 2)
36
+ json
37
+ logger (>= 1.4.2)
38
+ minitest (>= 5.1)
39
+ securerandom (>= 0.3)
40
+ tzinfo (~> 2.0, >= 2.0.5)
41
+ uri (>= 0.13.1)
42
+ base64 (0.3.0)
43
+ bigdecimal (4.1.2)
44
+ builder (3.3.0)
45
+ concurrent-ruby (1.3.8)
46
+ connection_pool (3.0.2)
47
+ crass (1.0.7)
48
+ diff-lcs (1.6.2)
49
+ docile (1.4.1)
50
+ drb (2.2.3)
51
+ erb (6.0.6)
52
+ erubi (1.13.1)
53
+ i18n (1.15.2)
54
+ concurrent-ruby (~> 1.0)
55
+ io-console (0.8.2)
56
+ irb (1.18.0)
57
+ pp (>= 0.6.0)
58
+ prism (>= 1.3.0)
59
+ rdoc (>= 4.0.0)
60
+ reline (>= 0.4.2)
61
+ json (2.21.2)
62
+ logger (1.7.0)
63
+ loofah (2.25.2)
64
+ crass (~> 1.0.2)
65
+ nokogiri (>= 1.12.0)
66
+ minitest (6.0.6)
67
+ drb (~> 2.0)
68
+ prism (~> 1.5)
69
+ nokogiri (1.19.4-aarch64-linux-gnu)
70
+ racc (~> 1.4)
71
+ nokogiri (1.19.4-aarch64-linux-musl)
72
+ racc (~> 1.4)
73
+ nokogiri (1.19.4-arm-linux-gnu)
74
+ racc (~> 1.4)
75
+ nokogiri (1.19.4-arm-linux-musl)
76
+ racc (~> 1.4)
77
+ nokogiri (1.19.4-arm64-darwin)
78
+ racc (~> 1.4)
79
+ nokogiri (1.19.4-x86_64-darwin)
80
+ racc (~> 1.4)
81
+ nokogiri (1.19.4-x86_64-linux-gnu)
82
+ racc (~> 1.4)
83
+ nokogiri (1.19.4-x86_64-linux-musl)
84
+ racc (~> 1.4)
85
+ pp (0.6.4)
86
+ prettyprint
87
+ prettyprint (0.2.0)
88
+ prism (1.9.0)
89
+ racc (1.8.1)
90
+ rack (3.2.6)
91
+ rack-session (2.1.2)
92
+ base64 (>= 0.1.0)
93
+ rack (>= 3.0.0)
94
+ rack-test (2.2.0)
95
+ rack (>= 1.3)
96
+ rackup (2.3.1)
97
+ rack (>= 3)
98
+ rails-dom-testing (2.3.0)
99
+ activesupport (>= 5.0.0)
100
+ minitest
101
+ nokogiri (>= 1.6)
102
+ rails-html-sanitizer (1.7.1)
103
+ loofah (~> 2.25, >= 2.25.2)
104
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
105
+ railties (8.1.3.1)
106
+ actionpack (= 8.1.3.1)
107
+ activesupport (= 8.1.3.1)
108
+ irb (~> 1.13)
109
+ rackup (>= 1.0.0)
110
+ rake (>= 12.2)
111
+ thor (~> 1.0, >= 1.2.2)
112
+ tsort (>= 0.2)
113
+ zeitwerk (~> 2.6)
114
+ rainbow (3.1.1)
115
+ rake (13.4.2)
116
+ rbs (4.1.2)
117
+ logger
118
+ prism (>= 1.6.0)
119
+ tsort
120
+ rdoc (8.0.0)
121
+ erb
122
+ prism (>= 1.6.0)
123
+ rbs (>= 4.0.0)
124
+ tsort
125
+ reline (0.6.3)
126
+ io-console (~> 0.5)
127
+ rspec (3.13.2)
128
+ rspec-core (~> 3.13.0)
129
+ rspec-expectations (~> 3.13.0)
130
+ rspec-mocks (~> 3.13.0)
131
+ rspec-core (3.13.6)
132
+ rspec-support (~> 3.13.0)
133
+ rspec-expectations (3.13.5)
134
+ diff-lcs (>= 1.2.0, < 2.0)
135
+ rspec-support (~> 3.13.0)
136
+ rspec-mocks (3.13.8)
137
+ diff-lcs (>= 1.2.0, < 2.0)
138
+ rspec-support (~> 3.13.0)
139
+ rspec-support (3.13.7)
140
+ securerandom (0.4.1)
141
+ simplecov (0.22.0)
142
+ docile (~> 1.1)
143
+ simplecov-html (~> 0.11)
144
+ simplecov_json_formatter (~> 0.1)
145
+ simplecov-html (0.13.2)
146
+ simplecov_json_formatter (0.1.4)
147
+ thor (1.5.0)
148
+ tsort (0.2.0)
149
+ tzinfo (2.0.6)
150
+ concurrent-ruby (~> 1.0)
151
+ uri (1.1.1)
152
+ useragent (0.16.11)
153
+ zeitwerk (2.8.3)
154
+
155
+ PLATFORMS
156
+ aarch64-linux-gnu
157
+ aarch64-linux-musl
158
+ arm-linux-gnu
159
+ arm-linux-musl
160
+ arm64-darwin
161
+ x86_64-darwin
162
+ x86_64-linux-gnu
163
+ x86_64-linux-musl
164
+
165
+ DEPENDENCIES
166
+ bundler (~> 2.4)
167
+ rake (~> 13.0)
168
+ route_guard!
169
+ rspec (~> 3.12)
170
+ simplecov (~> 0.22)
171
+
172
+ BUNDLED WITH
173
+ 2.5.3
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # RouteGuard
2
+
3
+ RouteGuard is a production-ready static analysis tool for Rails routing. It inspects your Rails routes to catch issues Rails itself doesn't report—like shadowing, duplicates, unreachable catch-alls, and duplicate resource blocks.
4
+
5
+ ## Core Features
6
+
7
+ * **Duplicate Route Detection**: Detects routes sharing the same HTTP verb and path pattern.
8
+ * **Route Shadowing**: Flags routes that can never be matched because an earlier route matches first (e.g. `/users/:id` shadowing `/users/new`).
9
+ * **Unreachable Routes**: Detects routes defined after catch-all wildcard routes (e.g. `match "*path"`).
10
+ * **Duplicate Named Helpers**: Identifies duplicate helper names (e.g., duplicate `auth_path` helpers pointing to different paths).
11
+ * **Duplicate Resources**: Warns when identical resources are declared multiple times in the same namespace scope.
12
+ * **Route Statistics**: Computes REST resources count, nested scopes, and wildcards.
13
+ * **Health Score**: Measures a 0-100 maintainability score based on issues and path nesting levels.
14
+
15
+ ---
16
+
17
+ ## Quick Start
18
+
19
+ ### Installation
20
+
21
+ Add this gem to your group `:development, :test` block:
22
+
23
+ ```ruby
24
+ group :development, :test do
25
+ gem "route_guard", path: "path/to/route_guard"
26
+ end
27
+ ```
28
+
29
+ Run `bundle install`.
30
+
31
+ ### Run RouteGuard
32
+
33
+ Run check from the terminal:
34
+
35
+ ```bash
36
+ bundle exec route_guard check
37
+ ```
38
+
39
+ Or execute via Rake tasks:
40
+
41
+ ```bash
42
+ bundle exec rails route_guard
43
+ bundle exec rails routes:doctor
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Documentation
49
+
50
+ For detailed configurations, options, and workflows, please see:
51
+
52
+ * [Usage & Integration Guide](docs/usage.md)
53
+ * [Publishing Guide](docs/publishing.md)
54
+
55
+ ## License
56
+
57
+ MIT License.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |t|
7
+ t.rspec_opts = "--format documentation"
8
+ end
9
+
10
+ task default: :spec
data/bin/route_guard ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../lib/route_guard"
5
+
6
+ begin
7
+ RouteGuard::CLI.start(ARGV)
8
+ rescue SystemExit => e
9
+ # Propagate CLI exits
10
+ exit(e.status)
11
+ rescue => e
12
+ warn "Error: #{e.message}"
13
+ exit(1)
14
+ end
@@ -0,0 +1,76 @@
1
+ # RouteGuard: Gem Publishing Guide
2
+
3
+ This guide details how to build, package, and publish the **RouteGuard** gem to the RubyGems community.
4
+
5
+ ---
6
+
7
+ ## 1. Preparing for Release
8
+
9
+ Before building and publishing, ensure that:
10
+
11
+ 1. All tests pass:
12
+ ```bash
13
+ bundle exec rspec
14
+ ```
15
+ 2. Your version in `lib/route_guard/version.rb` is bumped according to Semantic Versioning (SemVer) rules:
16
+ ```ruby
17
+ module RouteGuard
18
+ VERSION = "0.1.0" # Major.Minor.Patch
19
+ end
20
+ ```
21
+ 3. The metadata in `route_guard.gemspec` (homepage, authors, email, etc.) is correct.
22
+
23
+ ---
24
+
25
+ ## 2. Building the Gem
26
+
27
+ To package the gem code into a distributable `.gem` file, run the `gem build` command from the root of the project:
28
+
29
+ ```bash
30
+ gem build route_guard.gemspec
31
+ ```
32
+
33
+ This generates a file named `route_guard-0.1.0.gem` (matching your current version) in the root folder.
34
+
35
+ ---
36
+
37
+ ## 3. Authentication with RubyGems
38
+
39
+ To publish a gem, you need an account on [RubyGems.org](https://rubygems.org/).
40
+
41
+ Once registered, sign in via your terminal using:
42
+
43
+ ```bash
44
+ gem signin
45
+ ```
46
+
47
+ Enter your RubyGems email and password when prompted. This securely stores your API key locally in `~/.gem/credentials`.
48
+
49
+ ---
50
+
51
+ ## 4. Publishing to RubyGems
52
+
53
+ Publish the built gem package using the `gem push` command:
54
+
55
+ ```bash
56
+ gem push route_guard-0.1.0.gem
57
+ ```
58
+
59
+ Once pushed, your gem will be immediately indexable, and developers around the world can install it via:
60
+
61
+ ```bash
62
+ gem install route_guard
63
+ ```
64
+
65
+ ---
66
+
67
+ ## 5. Version Control Best Practices
68
+
69
+ After publishing a release:
70
+
71
+ 1. **Tag the release** in git:
72
+ ```bash
73
+ git tag -a v0.1.0 -m "Release version 0.1.0"
74
+ git push origin v0.1.0
75
+ ```
76
+ 2. **Document changes** in a `CHANGELOG.md` file so developers know what changed.
data/docs/usage.md ADDED
@@ -0,0 +1,81 @@
1
+ # RouteGuard: Usage Guide
2
+
3
+ This guide explains how to install, integrate, and run **RouteGuard** in your Rails application.
4
+
5
+ ---
6
+
7
+ ## 1. Installation
8
+
9
+ Add `route_guard` to your application's `Gemfile`. Since RouteGuard has zero runtime overhead in production, it is highly recommended to group it under `:development` and `:test`:
10
+
11
+ ```ruby
12
+ group :development, :test do
13
+ gem "route_guard", path: "path/to/route_guard" # During local development
14
+ # Or once published:
15
+ # gem "route_guard"
16
+ end
17
+ ```
18
+
19
+ Then execute:
20
+
21
+ ```bash
22
+ bundle install
23
+ ```
24
+
25
+ ---
26
+
27
+ ## 2. Command Line Interface (CLI)
28
+
29
+ You can run RouteGuard directly from your terminal. Since it automatically boot-loads your Rails environment, make sure to execute it from your Rails application root directory:
30
+
31
+ ```bash
32
+ bundle exec route_guard
33
+ ```
34
+
35
+ ### Commands
36
+
37
+ * `check` (default): Run full inspection rules on routes.
38
+ * `stats`: Generate key route complexity metrics and statistics.
39
+ * `doctor`: Run in strict mode (fails on warnings/errors). Perfect for CI pipelines.
40
+ * `json`: Generate a machine-readable JSON report.
41
+ * `html`: Generate a premium interactive HTML report dashboard.
42
+
43
+ ### CLI Options
44
+
45
+ | Option | Type | Description |
46
+ | :--- | :--- | :--- |
47
+ | `--strict` | Boolean | Treat all warnings as errors. |
48
+ | `--format` | String | Output format (`terminal`, `json`, `html`, `ci`). |
49
+ | `--only` | Array | Only run specific inspections (e.g. `duplicate_routes`). |
50
+ | `--except` | Array | Exclude specific inspections from running. |
51
+ | `--fail-on-warning`| Boolean | Exit with status code `1` if warnings are found. |
52
+ | `--output` | String | Path to write the JSON/HTML output. |
53
+ | `--verbose` | Boolean | Display detailed debug information. |
54
+
55
+ #### Examples
56
+
57
+ **Generate a self-contained HTML dashboard report:**
58
+ ```bash
59
+ bundle exec route_guard html --output=coverage/route_guard_report.html
60
+ ```
61
+
62
+ **Run only duplicate route checking:**
63
+ ```bash
64
+ bundle exec route_guard check --only duplicate_routes
65
+ ```
66
+
67
+ **Strict checking in CI, failing on warnings:**
68
+ ```bash
69
+ bundle exec route_guard check --fail-on-warning
70
+ ```
71
+
72
+ ---
73
+
74
+ ## 3. Rails / Rake Integration
75
+
76
+ RouteGuard automatically registers Rake tasks when loaded in your Rails application.
77
+
78
+ ### Available Tasks
79
+
80
+ * **`bundle exec rails route_guard`** (or `bundle exec rails routes:lint`): Analyzes your routes and prints findings to your terminal.
81
+ * **`bundle exec rails routes:doctor`**: Runs strict verification. Exits with non-zero code if any issue (warning or error) is detected. Ideal for Git pre-commit hooks or CI steps.
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "models/report"
4
+ require_relative "rules/duplicate_routes"
5
+ require_relative "rules/shadowed_routes"
6
+ require_relative "rules/unreachable_routes"
7
+ require_relative "rules/duplicate_helpers"
8
+ require_relative "rules/duplicate_resources"
9
+ require_relative "rules/statistics"
10
+ require_relative "rules/complexity"
11
+ require_relative "rules/unused_routes"
12
+
13
+ module RouteGuard
14
+ class Analyzer
15
+ RULE_MAPPING = {
16
+ duplicate_routes: Rules::DuplicateRoutes,
17
+ shadowed_routes: Rules::ShadowedRoutes,
18
+ unreachable_routes: Rules::UnreachableRoutes,
19
+ duplicate_helpers: Rules::DuplicateHelpers,
20
+ duplicate_resources: Rules::DuplicateResources,
21
+ statistics: Rules::Statistics,
22
+ complexity: Rules::Complexity,
23
+ unused_routes: Rules::UnusedRoutes
24
+ }.freeze
25
+
26
+ def self.analyze(routes, enabled_rules, options = {})
27
+ report = Models::Report.new(routes)
28
+ start_time = Time.now
29
+
30
+ # 1. Run Statistics first (if enabled)
31
+ if enabled_rules.include?(:statistics)
32
+ stat_rule = Rules::Statistics.new(options)
33
+ stat_rule.analyze(routes, report)
34
+ end
35
+
36
+ # 2. Run other lint rules
37
+ issues = []
38
+ lint_rules = %i[duplicate_routes shadowed_routes unreachable_routes duplicate_helpers duplicate_resources unused_routes]
39
+ (lint_rules & enabled_rules).each do |rule_sym|
40
+ rule_class = RULE_MAPPING[rule_sym]
41
+ next unless rule_class
42
+
43
+ rule = rule_class.new(options)
44
+ rule_issues = rule.analyze(routes, report)
45
+ issues.concat(rule_issues) if rule_issues.is_a?(Array)
46
+ end
47
+
48
+ # Expose intermediate issues on report for Complexity to analyze
49
+ report.issues = issues
50
+
51
+ # Update stats with issue metrics
52
+ if report.stats && report.stats.any?
53
+ report.stats[:duplicate_paths] = issues.count { |i| i.rule_name == :duplicate_routes }
54
+ report.stats[:shadowed_routes] = issues.count { |i| i.rule_name == :shadowed_routes }
55
+ end
56
+
57
+ # 3. Run Complexity last (if enabled)
58
+ if enabled_rules.include?(:complexity)
59
+ comp_rule = Rules::Complexity.new(options)
60
+ comp_issues = comp_rule.analyze(routes, report)
61
+ issues.concat(comp_issues) if comp_issues.is_a?(Array)
62
+ end
63
+
64
+ report.issues = issues
65
+ report.duration = Time.now - start_time
66
+ report
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+ require_relative "../route_guard"
5
+
6
+ module RouteGuard
7
+ class CLI < Thor
8
+ class_option :strict, type: :boolean, default: false, desc: "Treat warnings as errors"
9
+ class_option :format, type: :string, default: "terminal", desc: "Output format: terminal, json, html, ci"
10
+ class_option :only, type: :array, default: [], desc: "Run only specified rules"
11
+ class_option :except, type: :array, default: [], desc: "Exclude specified rules"
12
+ class_option :fail_on_warning, type: :boolean, default: false, desc: "Fail if warnings are found"
13
+ class_option :verbose, type: :boolean, default: false, desc: "Print verbose output"
14
+ class_option :output, type: :string, desc: "Output file path"
15
+
16
+ desc "check", "Analyze Rails routes for issues"
17
+ def check
18
+ config = build_config
19
+ inspector = Inspector.new(config)
20
+ report = inspector.run
21
+
22
+ fmt = (options[:format] || "terminal").to_sym
23
+ io = if options[:output]
24
+ File.open(options[:output], "w")
25
+ else
26
+ $stdout
27
+ end
28
+
29
+ inspector.format(report, fmt, io)
30
+ io.close if options[:output]
31
+
32
+ exit_status(report, config)
33
+ end
34
+
35
+ default_task :check
36
+
37
+ desc "stats", "Calculate routing statistics and metrics"
38
+ def stats
39
+ config = build_config
40
+ config.rules = [:statistics]
41
+ inspector = Inspector.new(config)
42
+ report = inspector.run
43
+
44
+ fmt = (options[:format] || "terminal").to_sym
45
+ if fmt == :json
46
+ inspector.format(report, :json)
47
+ else
48
+ inspector.format(report, :terminal)
49
+ end
50
+ end
51
+
52
+ desc "doctor", "Thoroughly inspect and report on route health"
53
+ def doctor
54
+ config = build_config
55
+ config.strict = true
56
+ config.fail_on_warning = true
57
+ inspector = Inspector.new(config)
58
+ report = inspector.run
59
+ inspector.format(report, :terminal)
60
+ exit_status(report, config)
61
+ end
62
+
63
+ desc "json", "Output results in JSON format"
64
+ def json
65
+ config = build_config
66
+ config.formatters = [:json]
67
+ inspector = Inspector.new(config)
68
+ report = inspector.run
69
+ inspector.format(report, :json)
70
+ exit_status(report, config)
71
+ end
72
+
73
+ desc "html", "Generate a beautiful HTML report"
74
+ def html
75
+ config = build_config
76
+ config.formatters = [:html]
77
+ inspector = Inspector.new(config)
78
+ report = inspector.run
79
+
80
+ output_file = options[:output] || "route_guard_report.html"
81
+ File.open(output_file, "w") do |f|
82
+ inspector.format(report, :html, f)
83
+ end
84
+ puts "HTML report generated at #{output_file}"
85
+ exit_status(report, config)
86
+ end
87
+
88
+ # Disable Thor's exit-on-failure behavior by default to control exit statuses
89
+ def self.exit_on_failure?
90
+ true
91
+ end
92
+
93
+ private
94
+
95
+ def build_config
96
+ config = Configuration.new
97
+ config.strict = options[:strict]
98
+ config.fail_on_warning = options[:fail_on_warning]
99
+ config.only = options[:only] || []
100
+ config.except = options[:except] || []
101
+ config.verbose = options[:verbose]
102
+
103
+ fmt = (options[:format] || "terminal").to_sym
104
+ config.formatters = [fmt]
105
+ config
106
+ end
107
+
108
+ def exit_status(report, config = nil)
109
+ strict = config ? config.strict : options[:strict]
110
+ fail_on_warning = config ? config.fail_on_warning : options[:fail_on_warning]
111
+
112
+ if report.errors.any?
113
+ exit(1)
114
+ elsif fail_on_warning && report.warnings.any?
115
+ exit(1)
116
+ elsif strict && report.warnings.any?
117
+ exit(1)
118
+ else
119
+ exit(0)
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RouteGuard
4
+ class Configuration
5
+ attr_accessor :rules, :formatters, :strict, :fail_on_warning, :only, :except, :verbose
6
+
7
+ ALL_RULES = %i[
8
+ duplicate_routes
9
+ shadowed_routes
10
+ unreachable_routes
11
+ duplicate_helpers
12
+ duplicate_resources
13
+ unused_routes
14
+ statistics
15
+ complexity
16
+ ].freeze
17
+
18
+ def initialize
19
+ @rules = ALL_RULES.dup
20
+ @formatters = [:terminal]
21
+ @strict = false
22
+ @fail_on_warning = false
23
+ @only = []
24
+ @except = []
25
+ @verbose = false
26
+ end
27
+
28
+ def enabled_rules
29
+ active_rules = if only.any?
30
+ rules & only.map(&:to_sym)
31
+ else
32
+ rules
33
+ end
34
+
35
+ active_rules - except.map(&:to_sym)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RouteGuard
4
+ module Formatter
5
+ class Ci
6
+ def format(report, io = $stdout)
7
+ report.issues.each do |issue|
8
+ severity = issue.severity == :error ? "error" : "warning"
9
+
10
+ if issue.file && issue.line
11
+ rel_file = issue.file.sub(/\A#{Regexp.escape(Dir.pwd)}\//, "")
12
+ io.puts "::#{severity} file=#{rel_file},line=#{issue.line}::[RouteGuard] #{issue.message}"
13
+ else
14
+ io.puts "::#{severity}::[RouteGuard] #{issue.message}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end