swagcov 0.6.0 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba29f88b400a4b44a37ee42725f70a5a97aa8ec9186de531ea13de33e8fec205
4
- data.tar.gz: 6651caaa48d8fa61bd90f1598cfd3d78b8d6612ca6f14f76360ef8d85a256828
3
+ metadata.gz: 1df02b05f23038aacedc8a990a47012d27f90f64f7185c689507face26acd8c4
4
+ data.tar.gz: 8d2e127ed1b1de208ef87fe6a8920fe505fbdceade1f430300b26e2bb6441d19
5
5
  SHA512:
6
- metadata.gz: 86b8e97506c580b7981090803aa41a609d1c1396613a57da1faf7c66864c40ac0337675fa009a5c48311ceff89bf8e6f1eb683d098a0153525a71d95cdb9c124
7
- data.tar.gz: e62b2919cb26ff819d28abf200fce58d23b7f509b47200114ce6f69bc23d086fb2399b21be6e0363a6a15102f845d6ad5dc003e5fb36f175ab1c87947b21a68a
6
+ metadata.gz: 4faad26270ff8aceddad224fdb26b6fcd8c86eb0d1c2a75c8bff082aa829187a5d571b7aff037b4a8c5bc907c26c446d55a5807420b111f18abc5c7b475a445c
7
+ data.tar.gz: a8bbfa8964e97929d4e190353729e399e9f0bf59d78acef28084699e902be2689bf8e7bf2a2ea3289f10114040c10112204c0954da319da4c38971c6ea7f0c5e
data/CHANGELOG.md CHANGED
@@ -2,6 +2,30 @@
2
2
  ## main (unreleased)
3
3
  -
4
4
 
5
+ ## 0.7.0 (2025-04-18)
6
+ ### Enhancement
7
+ - Add support for Ruby 3.5 ([#98](https://github.com/smridge/swagcov/pull/98))
8
+ - Add rake task for auto-generation of `.swagcov_todo.yml` file ([#93](https://github.com/smridge/swagcov/pull/93), [#96](https://github.com/smridge/swagcov/pull/96))
9
+ ```shell
10
+ bundle exec rake swagcov:generate_todo
11
+ ```
12
+
13
+ ### Refactor
14
+ - Add `Swagcov.project_root` method ([#86](https://github.com/smridge/swagcov/pull/86))
15
+ - Separate coverage collection and output ([#83](https://github.com/smridge/swagcov/pull/83))
16
+ - Replace ActiveSupport string method with ruby string method ([#85](https://github.com/smridge/swagcov/pull/85))
17
+ - Replace `Swagcov::Coverage.new.report` with `Swagcov::Command::ReportCoverage.new.run` ([#89](https://github.com/smridge/swagcov/pull/89))
18
+ - Rename `Swagcov::Install` to `Swagcov::Command::GenerateDotfile` ([#88](https://github.com/smridge/swagcov/pull/88))
19
+ - Refactor `GenerateDotfile` to be consistent with `GenerateTodoFile` ([#97](https://github.com/smridge/swagcov/pull/97))
20
+
21
+ ### Fix
22
+ - Add exit code to install task + update messaging ([#87](https://github.com/smridge/swagcov/pull/87))
23
+ - Ignored path verb matching when duplicate path keys are present ([#92](https://github.com/smridge/swagcov/pull/92))
24
+ - Fix exit code error handling ([#95](https://github.com/smridge/swagcov/pull/95))
25
+
26
+ ### Development
27
+ - Add irb console for local development ([#94](https://github.com/smridge/swagcov/pull/94))
28
+
5
29
  ## 0.6.0 (2025-04-09)
6
30
  ### Fix
7
31
  - Grammatical number for endpoint(s) count output ([#78](https://github.com/smridge/swagcov/pull/78))
@@ -15,23 +39,23 @@
15
39
  - Improve path matching processing for `ignore` and `only` routes ([#65](https://github.com/smridge/swagcov/pull/65))
16
40
 
17
41
  ### Code Coverage
18
- - Add test coverage reporting ([#68](https://github.com/smridge/swagcov/pull/68), [#69](https://github.com/smridge/swagcov/pull/69))
42
+ - Add test coverage reporting ([#68](https://github.com/smridge/swagcov/pull/68), [#69](https://github.com/smridge/swagcov/pull/69))
19
43
 
20
44
  ## 0.5.0 (2025-03-26)
21
45
  ### Enhancement
22
- - Add rake task for configuration installation ([#59](https://github.com/smridge/swagcov/pull/59))
23
- ```shell
24
- bundle exec rake swagcov:install
25
- ```
26
- - Extend `ignore` routes configuration to exclude only specific actions ([#60](https://github.com/smridge/swagcov/pull/60))
27
- ```yml
28
- routes:
29
- paths:
30
- ignore:
31
- - /v2/users # existing configuration that ignores all associated actions (verbs)
32
- - /v2/users/:id: # new option to extend to specific actions
33
- - GET
34
- ```
46
+ - Add rake task for configuration installation ([#59](https://github.com/smridge/swagcov/pull/59))
47
+ ```shell
48
+ bundle exec rake swagcov:install
49
+ ```
50
+ - Extend `ignore` routes configuration to exclude only specific actions ([#60](https://github.com/smridge/swagcov/pull/60))
51
+ ```yml
52
+ routes:
53
+ paths:
54
+ ignore:
55
+ - /v2/users # existing configuration that ignores all associated actions (verbs)
56
+ - /v2/users/:id: # new option to extend to specific actions
57
+ - GET
58
+ ```
35
59
 
36
60
  ## 0.4.1 (2025-03-18)
37
61
  ### Fix
@@ -45,48 +69,49 @@
45
69
 
46
70
  ## 0.3.0 (2022-02-21)
47
71
  ### Enhancement
48
- - Raise specific `Swagcov::BadConfigurationError` for malinformed yaml files ([#23](https://github.com/smridge/swagcov/pull/23))
72
+ - Raise specific `Swagcov::BadConfigurationError` for malformed yaml files ([#23](https://github.com/smridge/swagcov/pull/23))
49
73
 
50
74
  ### Security
51
- - Require Multi-Factor Authentication for RubyGems privileged operations ([#16](https://github.com/smridge/swagcov/pull/16))
75
+ - Require Multi-Factor Authentication for RubyGems privileged operations ([#16](https://github.com/smridge/swagcov/pull/16))
52
76
 
53
77
  ### Code Coverage
54
- - Add Sandbox Application and specs for Rails 5.1 ([#20](https://github.com/smridge/swagcov/pull/20))
55
- - Add specs for Rails 5.2 ([#7](https://github.com/smridge/swagcov/pull/7)), ([#14](https://github.com/smridge/swagcov/pull/14))
56
- - Add Sandbox Application and specs for Rails 6.0 ([#17](https://github.com/smridge/swagcov/pull/17))
57
- - Add Sandbox Application and specs for Rails 6.1 ([#22](https://github.com/smridge/swagcov/pull/22))
58
- - Add GitHub Actions to run specs ([#18](https://github.com/smridge/swagcov/pull/18))
59
- - Add GitHub CodeQL ([#13](https://github.com/smridge/swagcov/pull/13))
78
+ - Add Sandbox Application and specs for Rails 5.1 ([#20](https://github.com/smridge/swagcov/pull/20))
79
+ - Add specs for Rails 5.2 ([#7](https://github.com/smridge/swagcov/pull/7)), ([#14](https://github.com/smridge/swagcov/pull/14))
80
+ - Add Sandbox Application and specs for Rails 6.0 ([#17](https://github.com/smridge/swagcov/pull/17))
81
+ - Add Sandbox Application and specs for Rails 6.1 ([#22](https://github.com/smridge/swagcov/pull/22))
82
+ - Add GitHub Actions to run specs ([#18](https://github.com/smridge/swagcov/pull/18))
83
+ - Add GitHub CodeQL ([#13](https://github.com/smridge/swagcov/pull/13))
60
84
 
61
85
  ### Refactor
62
- - Move `SystemExit` to rake task for easier testing ([#24](https://github.com/smridge/swagcov/pull/24))
63
- - Reduce complexity when matching routes ([#15](https://github.com/smridge/swagcov/pull/15))
86
+ - Move `SystemExit` to rake task for easier testing ([#24](https://github.com/smridge/swagcov/pull/24))
87
+ - Reduce complexity when matching routes ([#15](https://github.com/smridge/swagcov/pull/15))
64
88
 
65
89
  ## 0.2.5 (2021-09-14)
66
90
  ### Fix
67
- - Matching routes against swagger paths. Previously, partial paths could result in a match ([#12](https://github.com/smridge/swagcov/pull/12))
91
+ - Matching routes against swagger paths. Previously, partial paths could result in a match ([#12](https://github.com/smridge/swagcov/pull/12))
68
92
 
69
93
  ## 0.2.4 (2021-04-30)
70
94
  ### Fix
71
- - If a route path does not start with "^" match the entire path ([#5](https://github.com/smridge/swagcov/pull/5))
95
+ - If a route path does not start with "^" match the entire path ([#5](https://github.com/smridge/swagcov/pull/5))
96
+
72
97
  ### Enhancement
73
- - Raise specific `Swagcov::BadConfigurationError` error if bad or missing configuration ([#5](https://github.com/smridge/swagcov/pull/5))
98
+ - Raise specific `Swagcov::BadConfigurationError` error if bad or missing configuration ([#5](https://github.com/smridge/swagcov/pull/5))
74
99
 
75
100
  ## 0.2.3 (2021-04-23)
76
101
  ### Fix
77
- - Exclude ActiveStorage and ActionMailer routes ([#3](https://github.com/smridge/swagcov/pull/3))
102
+ - Exclude ActiveStorage and ActionMailer routes ([#3](https://github.com/smridge/swagcov/pull/3))
78
103
 
79
104
  ## 0.2.2 (2021-04-22)
80
105
  ### Fix
81
- - Exclude Rails Internal Routes and Mounted Applications ([#2](https://github.com/smridge/swagcov/pull/2))
106
+ - Exclude Rails Internal Routes and Mounted Applications ([#2](https://github.com/smridge/swagcov/pull/2))
82
107
 
83
108
  ## 0.2.1 (2021-04-21)
84
109
  ### Fix
85
- - Exceptions caused by missing dependency for strings. ([#1](https://github.com/smridge/swagcov/pull/1))
110
+ - Exceptions caused by missing dependency for strings. ([#1](https://github.com/smridge/swagcov/pull/1))
86
111
 
87
112
  ## 0.2.0 (2021-04-20)
88
113
  ### Enhancement
89
- - Add Exit status to easily build a pass/fail into build pipeline
114
+ - Add Exit status to easily build a pass/fail into build pipeline
90
115
 
91
116
  ## 0.1.0 (2021-02-24)
92
117
  - Create Rake Task for checking documentation coverage (rails only)
data/README.md CHANGED
@@ -15,6 +15,12 @@ See OpenAPI documentation coverage report for Rails Routes.
15
15
  - See overview of different endpoints covered, missing and what you choose to ignore.
16
16
  - Add pass/fail to your build pipeline when missing Documentation Coverage.
17
17
 
18
+ | `rake task` | `rails console` | Description |
19
+ | :--- | :--- | :--- |
20
+ | `rake swagcov` | `Swagcov::Command::ReportCoverage.new.run` | Check documentation coverage |
21
+ | `rake swagcov:install` | `Swagcov::Command::GenerateDotfile.new.run` | Install required `.swagcov.yml` config file |
22
+ | `rake swagcov:generate_todo` | `Swagcov::Command::GenerateTodoFile.new.run` | Generate `.swagcov_todo.yml` |
23
+
18
24
  ## Ruby and Rails Version Support
19
25
  Versioning support from a test coverage perspective, see [tests.yml](/.github/workflows/tests.yml) for detail
20
26
  | `ruby -v` | `rails 4.2` | `rails 5.0` | `rails 5.1` | `rails 5.2` | `rails 6.0` | `rails 6.1` | `rails 7.0` | `rails 7.1` | `rails 7.2` | `rails 8.0` |
@@ -27,6 +33,7 @@ Versioning support from a test coverage perspective, see [tests.yml](/.github/wo
27
33
  | `3.2` | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
28
34
  | `3.3` | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
29
35
  | `3.4` | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
36
+ | `3.5` | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
30
37
 
31
38
  ## Installation
32
39
  Add this line to your application's Gemfile:
@@ -88,7 +95,8 @@ Execute:
88
95
  bundle exec rake swagcov
89
96
  ```
90
97
 
91
- ### Example configurations and output from running `bundle exec rake swagcov` from the root of your Rails Application:
98
+ ## Examples
99
+ Configurations and output from running `bundle exec rake swagcov` from the root of your Rails Application
92
100
  - All Routes (minimal configuration):
93
101
  ```yml
94
102
  docs:
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Swagcov
4
+ module Command
5
+ class GenerateDotfile
6
+ attr_reader :dotfile
7
+
8
+ def initialize basename: ::Swagcov::Dotfile::DEFAULT_CONFIG_FILE_NAME
9
+ @dotfile = ::Swagcov.project_root.join(basename)
10
+ end
11
+
12
+ def run
13
+ if ::File.exist?(@dotfile)
14
+ $stdout.puts "#{@dotfile.basename} already exists at #{@dotfile.dirname}"
15
+ return ::Swagcov::STATUS_ERROR
16
+ end
17
+
18
+ ::File.write(
19
+ dotfile,
20
+ <<~YAML
21
+ ## Required field:
22
+ # List your OpenAPI documentation files
23
+ docs:
24
+ paths:
25
+ - swagger.yaml
26
+
27
+ ## Optional fields:
28
+ # routes:
29
+ # paths:
30
+ # only:
31
+ # - ^/v2 # only track v2 endpoints
32
+ # ignore:
33
+ # - /v2/users # do not track certain endpoints
34
+ # - /v2/users/:id: # ignore only certain actions (verbs)
35
+ # - GET
36
+ YAML
37
+ )
38
+
39
+ $stdout.puts "created #{@dotfile.basename} at #{@dotfile.dirname}"
40
+
41
+ ::Swagcov::STATUS_SUCCESS
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Swagcov
4
+ module Command
5
+ class GenerateTodoFile
6
+ def initialize basename: ::Swagcov::Dotfile::TODO_CONFIG_FILE_NAME,
7
+ data: ::Swagcov::Coverage.new(dotfile: ::Swagcov::Dotfile.new(skip_todo: true)).collect[:uncovered]
8
+ @dotfile = ::Swagcov.project_root.join(basename)
9
+ @data = data
10
+ end
11
+
12
+ def run
13
+ ::File.write(
14
+ @dotfile,
15
+ <<~YAML
16
+ # This configuration was auto generated
17
+ # The intent is to remove these route configurations as documentation is added
18
+ #{routes_yaml}
19
+ YAML
20
+ )
21
+
22
+ $stdout.puts "created #{@dotfile.basename} at #{@dotfile.dirname}"
23
+
24
+ ::Swagcov::STATUS_SUCCESS
25
+ end
26
+
27
+ private
28
+
29
+ def routes_yaml
30
+ return if routes.empty?
31
+
32
+ {
33
+ "routes" => {
34
+ "paths" => {
35
+ "ignore" => routes
36
+ }
37
+ }
38
+ }.to_yaml.strip
39
+ end
40
+
41
+ def routes
42
+ hash = {}
43
+
44
+ @data.each do |route|
45
+ hash[route[:path]] ? hash[route[:path]] << route[:verb] : hash[route[:path]] = [route[:verb]]
46
+ end
47
+
48
+ @routes ||= hash.map { |key, value| { key => value } }
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Swagcov
4
+ module Command
5
+ class ReportCoverage
6
+ def initialize data: nil
7
+ @data = data
8
+ end
9
+
10
+ def run
11
+ data = @data || ::Swagcov::Coverage.new.collect
12
+
13
+ ::Swagcov::Formatter::Console.new(data: data).run
14
+ rescue ::Swagcov::Errors::BadConfiguration => e
15
+ warn "#{e.class}: #{e.message}"
16
+ ::Swagcov::STATUS_ERROR
17
+ end
18
+ end
19
+ end
20
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Swagcov
4
4
  class Coverage
5
- attr_reader :data
5
+ attr_reader :dotfile
6
6
 
7
7
  def initialize dotfile: ::Swagcov::Dotfile.new, routes: ::Rails.application.routes.routes
8
8
  @dotfile = dotfile
@@ -18,22 +18,7 @@ module Swagcov
18
18
  }
19
19
  end
20
20
 
21
- def report
22
- collect_coverage
23
- routes_output(@data[:covered], "green")
24
- routes_output(@data[:ignored], "yellow")
25
- routes_output(@data[:uncovered], "red")
26
-
27
- final_output
28
-
29
- @data[:uncovered_count]
30
- end
31
-
32
- private
33
-
34
- attr_reader :dotfile
35
-
36
- def collect_coverage
21
+ def collect
37
22
  openapi_files = ::Swagcov::OpenapiFiles.new(filepaths: dotfile.docs_config)
38
23
  rails_version = ::Rails::VERSION::STRING
39
24
 
@@ -58,8 +43,12 @@ module Swagcov
58
43
  update_data(:uncovered, verb, path, "none")
59
44
  end
60
45
  end
46
+
47
+ @data
61
48
  end
62
49
 
50
+ private
51
+
63
52
  def third_party_route? route, path, rails_version
64
53
  # https://github.com/rails/rails/blob/48f3c3e201b57a4832314b2c957a3b303e89bfea/actionpack/lib/action_dispatch/routing/inspector.rb#L105-L107
65
54
  # Skips route paths like ["/rails/info/properties", "/rails/info", "/rails/mailers"]
@@ -86,59 +75,5 @@ module Swagcov
86
75
  @data[:"#{key}_count"] += 1
87
76
  @data[key] << { verb: verb, path: path, status: status }
88
77
  end
89
-
90
- def routes_output routes, status_color
91
- routes.each do |route|
92
- $stdout.puts(
93
- format(
94
- "%<verb>10s %<path>-#{min_width(:path) + 1}s %<status>s",
95
- { verb: route[:verb], path: route[:path], status: route[:status].send(status_color) }
96
- )
97
- )
98
- end
99
- end
100
-
101
- def min_width key
102
- strings =
103
- @data[:covered].map { |hash| hash[key] } +
104
- @data[:ignored].map { |hash| hash[key] } +
105
- @data[:uncovered].map { |hash| hash[key] }
106
-
107
- strings.max_by(&:length).size
108
- end
109
-
110
- def final_output
111
- $stdout.puts
112
- $stdout.puts(
113
- format(
114
- "OpenAPI documentation coverage %<percentage>.2f%% (%<covered>d/%<total>d)",
115
- {
116
- percentage: 100.0 * @data[:covered_count] / @data[:total_count],
117
- covered: @data[:covered_count],
118
- total: @data[:total_count]
119
- }
120
- )
121
- )
122
-
123
- count_output
124
- end
125
-
126
- def count_output
127
- {
128
- ignored: "yellow",
129
- total: "blue",
130
- covered: "green",
131
- uncovered: "red"
132
- }.each do |key, color|
133
- count = @data[:"#{key}_count"]
134
-
135
- $stdout.puts(
136
- format(
137
- "%<status>s #{key} #{count == 1 ? 'endpoint' : 'endpoints'}",
138
- { status: count.to_s.send(color) }
139
- )
140
- )
141
- end
142
- end
143
78
  end
144
79
  end
@@ -3,12 +3,14 @@
3
3
  module Swagcov
4
4
  class Dotfile
5
5
  DEFAULT_CONFIG_FILE_NAME = ".swagcov.yml"
6
+ TODO_CONFIG_FILE_NAME = ".swagcov_todo.yml"
6
7
 
7
- def initialize pathname: ::Rails.root.join(DEFAULT_CONFIG_FILE_NAME)
8
- @dotfile = load_yaml(pathname)
8
+ def initialize basename: DEFAULT_CONFIG_FILE_NAME, todo_basename: TODO_CONFIG_FILE_NAME, skip_todo: false
9
+ @dotfile = load_yaml(basename, required: true)
9
10
 
10
11
  raise ::Swagcov::Errors::BadConfiguration, "Invalid config file (#{DEFAULT_CONFIG_FILE_NAME})" unless valid?
11
12
 
13
+ @todo_file = load_yaml(todo_basename) unless skip_todo
12
14
  @ignored_regex = path_config_regex(ignored_config)
13
15
  @only_regex = path_config_regex(only_config)
14
16
  end
@@ -18,11 +20,12 @@ module Swagcov
18
20
 
19
21
  ignore_all_path_actions = @ignored_regex.match?(path)
20
22
 
21
- ignored_verbs = @ignored_config.find { |config| config[path] }
23
+ ignored_verbs =
24
+ @ignored_config.select { |config| config[path]&.is_a?(::Array) }.map(&:values).flatten.map(&:downcase)
22
25
 
23
- return ignore_all_path_actions unless ignored_verbs.is_a?(::Hash)
26
+ return ignore_all_path_actions if ignored_verbs.empty?
24
27
 
25
- ignored_verbs.values.flatten.map(&:downcase).any?(verb.downcase)
28
+ ignored_verbs.any?(verb.downcase)
26
29
  end
27
30
 
28
31
  def only_path_mismatch? path
@@ -34,7 +37,11 @@ module Swagcov
34
37
  end
35
38
 
36
39
  def ignored_config
37
- @ignored_config ||= dotfile.dig("routes", "paths", "ignore")
40
+ dotfile_routes = dotfile.dig("routes", "paths", "ignore").to_a
41
+ todo_routes = todo_file ? todo_file.dig("routes", "paths", "ignore").to_a : []
42
+ routes = dotfile_routes + todo_routes
43
+
44
+ @ignored_config ||= routes.empty? ? nil : routes
38
45
  end
39
46
 
40
47
  def only_config
@@ -43,16 +50,18 @@ module Swagcov
43
50
 
44
51
  private
45
52
 
46
- attr_reader :dotfile
53
+ attr_reader :dotfile, :todo_file
54
+
55
+ def load_yaml basename, required: false
56
+ pathname = ::Swagcov.project_root.join(basename)
57
+
58
+ raise ::Swagcov::Errors::BadConfiguration, "Missing config file (#{basename})" if !pathname.exist? && required
47
59
 
48
- def load_yaml pathname
49
- unless pathname.exist?
50
- raise ::Swagcov::Errors::BadConfiguration, "Missing config file (#{DEFAULT_CONFIG_FILE_NAME})"
51
- end
60
+ return unless pathname.exist?
52
61
 
53
62
  ::YAML.load_file(pathname)
54
- rescue Psych::SyntaxError
55
- raise ::Swagcov::Errors::BadConfiguration, "Malinformed config file (#{DEFAULT_CONFIG_FILE_NAME})"
63
+ rescue ::Psych::SyntaxError
64
+ raise ::Swagcov::Errors::BadConfiguration, "Malformed config file (#{basename})"
56
65
  end
57
66
 
58
67
  def path_config_regex path_config
@@ -63,7 +72,7 @@ module Swagcov
63
72
  if path.is_a?(::Hash)
64
73
  "^#{path.keys.first}$"
65
74
  else
66
- path.first == "^" ? path : "^#{path}$"
75
+ path.chr == "^" ? path : "^#{path}$"
67
76
  end
68
77
  end
69
78
 
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Swagcov
4
+ module Formatter
5
+ class Console
6
+ attr_reader :data
7
+
8
+ def initialize data: ::Swagcov::Coverage.new.collect
9
+ @data = data
10
+ end
11
+
12
+ def run
13
+ routes_output(data[:covered], "green")
14
+ routes_output(data[:ignored], "yellow")
15
+ routes_output(data[:uncovered], "red")
16
+ final_output
17
+
18
+ data[:uncovered_count].zero? ? ::Swagcov::STATUS_SUCCESS : ::Swagcov::STATUS_OFFENSES
19
+ end
20
+
21
+ private
22
+
23
+ def routes_output routes, status_color
24
+ routes.each do |route|
25
+ $stdout.puts(
26
+ format(
27
+ "%<verb>10s %<path>-#{min_width(:path) + 1}s %<status>s",
28
+ { verb: route[:verb], path: route[:path], status: route[:status].send(status_color) }
29
+ )
30
+ )
31
+ end
32
+ end
33
+
34
+ def min_width key
35
+ strings =
36
+ data[:covered].map { |hash| hash[key] } +
37
+ data[:ignored].map { |hash| hash[key] } +
38
+ data[:uncovered].map { |hash| hash[key] }
39
+
40
+ strings.max_by(&:length).size
41
+ end
42
+
43
+ def final_output
44
+ $stdout.puts
45
+ $stdout.puts(
46
+ format(
47
+ "OpenAPI documentation coverage %<percentage>.2f%% (%<covered>d/%<total>d)",
48
+ {
49
+ percentage: 100.0 * data[:covered_count] / data[:total_count],
50
+ covered: data[:covered_count],
51
+ total: data[:total_count]
52
+ }
53
+ )
54
+ )
55
+
56
+ count_output
57
+ end
58
+
59
+ def count_output
60
+ {
61
+ ignored: "yellow",
62
+ total: "blue",
63
+ covered: "green",
64
+ uncovered: "red"
65
+ }.each do |key, color|
66
+ count = data[:"#{key}_count"]
67
+
68
+ $stdout.puts(
69
+ format(
70
+ "%<status>s #{key} #{count == 1 ? 'endpoint' : 'endpoints'}",
71
+ { status: count.to_s.send(color) }
72
+ )
73
+ )
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -28,7 +28,7 @@ module Swagcov
28
28
  def load_yaml filepath
29
29
  ::YAML.load_file(filepath)["paths"]
30
30
  rescue ::Psych::SyntaxError
31
- raise ::Swagcov::Errors::BadConfiguration, "Malinformed openapi file (#{filepath})"
31
+ raise ::Swagcov::Errors::BadConfiguration, "Malformed openapi file (#{filepath})"
32
32
  end
33
33
  end
34
34
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Swagcov
4
4
  module Version
5
- STRING = "0.6.0"
5
+ STRING = "0.7.0"
6
6
  end
7
7
  end
data/lib/swagcov.rb CHANGED
@@ -1,16 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rails"
4
- require "active_support/core_ext"
5
4
 
5
+ require "swagcov/command/generate_dotfile"
6
+ require "swagcov/command/generate_todo_file"
7
+ require "swagcov/command/report_coverage"
6
8
  require "swagcov/core_ext/string"
9
+ require "swagcov/formatter/console"
7
10
  require "swagcov/coverage"
8
11
  require "swagcov/dotfile"
9
12
  require "swagcov/errors"
10
- require "swagcov/install"
11
13
  require "swagcov/openapi_files"
12
14
  require "swagcov/railtie"
13
15
  require "swagcov/version"
14
16
 
15
17
  module Swagcov
18
+ module_function
19
+
20
+ STATUS_SUCCESS = 0
21
+ STATUS_OFFENSES = 1
22
+ STATUS_ERROR = 2
23
+
24
+ def project_root
25
+ ::Rails.root || ::Pathname.new(::FileUtils.pwd)
26
+ end
16
27
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :swagcov do
4
+ desc "generate todo config file"
5
+ task generate_todo: :environment do
6
+ exit Swagcov::Command::GenerateTodoFile.new.run
7
+ end
8
+ end
@@ -3,6 +3,6 @@
3
3
  namespace :swagcov do
4
4
  desc "create config file"
5
5
  task install: :environment do
6
- Swagcov::Install.new.generate_dotfile
6
+ exit Swagcov::Command::GenerateDotfile.new.run
7
7
  end
8
8
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  desc "check documentation coverage for endpoints"
4
4
  task swagcov: :environment do
5
- exit Swagcov::Coverage.new.report
5
+ exit Swagcov::Command::ReportCoverage.new.run
6
6
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swagcov
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sarah Ridge
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-04-09 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -34,15 +34,19 @@ files:
34
34
  - README.md
35
35
  - Rakefile
36
36
  - lib/swagcov.rb
37
+ - lib/swagcov/command/generate_dotfile.rb
38
+ - lib/swagcov/command/generate_todo_file.rb
39
+ - lib/swagcov/command/report_coverage.rb
37
40
  - lib/swagcov/core_ext/string.rb
38
41
  - lib/swagcov/coverage.rb
39
42
  - lib/swagcov/dotfile.rb
40
43
  - lib/swagcov/errors.rb
41
- - lib/swagcov/install.rb
44
+ - lib/swagcov/formatter/console.rb
42
45
  - lib/swagcov/openapi_files.rb
43
46
  - lib/swagcov/railtie.rb
44
47
  - lib/swagcov/version.rb
45
48
  - lib/tasks/swagcov.rake
49
+ - lib/tasks/swagcov/generate_todo.rake
46
50
  - lib/tasks/swagcov/install.rake
47
51
  homepage: https://github.com/smridge/swagcov
48
52
  licenses:
@@ -67,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
71
  - !ruby/object:Gem::Version
68
72
  version: '0'
69
73
  requirements: []
70
- rubygems_version: 3.6.6
74
+ rubygems_version: 3.6.8
71
75
  specification_version: 4
72
76
  summary: OpenAPI documentation coverage for Rails Routes
73
77
  test_files: []
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Swagcov
4
- class Install
5
- attr_reader :dotfile
6
-
7
- def initialize pathname: ::Rails.root.join(::Swagcov::Dotfile::DEFAULT_CONFIG_FILE_NAME).to_s
8
- @dotfile = pathname
9
- end
10
-
11
- def generate_dotfile
12
- if ::File.exist?(dotfile)
13
- $stdout.puts "#{dotfile} already exists"
14
- return
15
- end
16
-
17
- ::File.write(
18
- dotfile,
19
- <<~YAML
20
- ## Required field:
21
- # List your OpenAPI documentation files
22
- docs:
23
- paths:
24
- - swagger.yaml
25
-
26
- ## Optional fields:
27
- # routes:
28
- # paths:
29
- # only:
30
- # - ^/v2 # only track v2 endpoints
31
- # ignore:
32
- # - /v2/users # do not track certain endpoints
33
- # - /v2/users/:id: # ignore only certain actions (verbs)
34
- # - GET
35
- YAML
36
- )
37
-
38
- $stdout.puts "created #{::Swagcov::Dotfile::DEFAULT_CONFIG_FILE_NAME}"
39
- end
40
- end
41
- end