rails-quality-assurance 1.0.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 +7 -0
- data/CHANGELOG.md +27 -0
- data/LICENSE.txt +21 -0
- data/README.md +125 -0
- data/config/biome.json +50 -0
- data/config/reek.yml +33 -0
- data/lib/generators/rails_quality_assurance/ci/ci_generator.rb +21 -0
- data/lib/generators/rails_quality_assurance/ci/templates/bin_ci.erb +8 -0
- data/lib/generators/rails_quality_assurance/ci/templates/config_ci.rb.erb +20 -0
- data/lib/rails_quality_assurance/all.rb +10 -0
- data/lib/rails_quality_assurance/ci.rb +70 -0
- data/lib/rails_quality_assurance/ci_runner.rb +14 -0
- data/lib/rails_quality_assurance/playwright/helper.rb +96 -0
- data/lib/rails_quality_assurance/playwright.rb +4 -0
- data/lib/rails_quality_assurance/railtie.rb +11 -0
- data/lib/rails_quality_assurance/rspec/helper.rb +31 -0
- data/lib/rails_quality_assurance/rspec.rb +4 -0
- data/lib/rails_quality_assurance/simplecov/helper.rb +52 -0
- data/lib/rails_quality_assurance/simplecov.rb +4 -0
- data/lib/rails_quality_assurance/test_helper.rb +3 -0
- data/lib/rails_quality_assurance/version.rb +5 -0
- data/lib/rails_quality_assurance.rb +30 -0
- data/lib/tasks/quality_assurance.rake +87 -0
- data/rubocop.yml +143 -0
- metadata +390 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 4fbc6fbabe01efd826fc05c8a532acc86d0a27b3daa02011637636c8a2cc82b4
|
|
4
|
+
data.tar.gz: 8b5b8f23af17448d99ed7eff051e39d2df7167c5250ad3a1c7ed84faaf167167
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: caa5a305daad24a7341a93fd599f07e3fcc1a29b7f1f48a49278601e6a7dda3ab8cfece9eb19ad24c932b23f731a51f8c9d1c7e8807aedf6b83a11e9c45bff34
|
|
7
|
+
data.tar.gz: 6eeaf4ad31f53038d9cb23b3d2ec1746fbbc24f01bdce1b315869236f523cba13c4f6d54cb82e67a7d9a4cc7f50a701deb968cc47681aea384a933f911d8dc2d
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2026-09-14
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial release of the Rails Quality Assurance kit.
|
|
13
|
+
- Shared RuboCop configuration for plugins: `rubocop-performance`, `rubocop-rspec`,
|
|
14
|
+
`rubocop-rspec_rails`, `rubocop-capybara`, `rubocop-factory_bot`,
|
|
15
|
+
`rubocop-rubycw`, `rubocop-migration`, `rubocop-rails`.
|
|
16
|
+
- `inherit_mode.merge: [Exclude]` so consuming projects add their own
|
|
17
|
+
exclusions without dropping the shared ones.
|
|
18
|
+
- Reek base configuration with Rails-appropriate defaults.
|
|
19
|
+
- Biome and Stylelint configurations for frontend linting.
|
|
20
|
+
- Single-require test setup via `rails_quality_assurance/all`: SimpleCov
|
|
21
|
+
100% line & branch coverage with LCOV output, RSpec core defaults, and
|
|
22
|
+
Playwright/Capybara system test driver with parallel worker port
|
|
23
|
+
allocation and failure HTML dumps.
|
|
24
|
+
- Rake tasks for quality checks (`qa:lint`, `qa:frontend`, `spec:parallel`).
|
|
25
|
+
- `rails_quality_assurance:ci` generator installing `bin/ci` and
|
|
26
|
+
`config/ci.rb` for host-level CI execution.
|
|
27
|
+
- Release workflow using RubyGems trusted publishing (OIDC).
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mauricio Zaffari
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Rails Quality Assurance
|
|
2
|
+
|
|
3
|
+
Opinionated quality assurance kit for Ruby on Rails applications.
|
|
4
|
+
|
|
5
|
+
`rails-quality-assurance` provides an out-of-the-box, comprehensive quality control setup designed to work with zero-configuration defaults. It integrates the standard quality control suite used across Develoz Rails applications.
|
|
6
|
+
|
|
7
|
+
## What's Included
|
|
8
|
+
|
|
9
|
+
### 1. Style & Linting
|
|
10
|
+
|
|
11
|
+
- **RuboCop**: Pre-configured `rubocop.yml` targeting Ruby 4.0 with all standard plugins loaded (`rubocop-rails`, `rubocop-rspec`, `rubocop-rspec_rails`, `rubocop-performance`, `rubocop-capybara`, `rubocop-factory_bot`, `rubocop-rubycw`, `rubocop-migration`).
|
|
12
|
+
- **Reek**: Code smell detection with sensible Rails defaults (`config/reek.yml`).
|
|
13
|
+
- **Flay**: Structural code duplication analysis.
|
|
14
|
+
- **Biome**: Pre-configured `config/biome.json` for fast JavaScript/TypeScript/JSON linting and formatting.
|
|
15
|
+
- **Stylelint**: Pre-configured `config/.stylelintrc.json` with Tailwind CSS support.
|
|
16
|
+
|
|
17
|
+
### 2. Security
|
|
18
|
+
|
|
19
|
+
- **Brakeman**: Static analysis security vulnerability scanner.
|
|
20
|
+
- **Bundler Audit**: Vulnerability scanner for gem dependencies.
|
|
21
|
+
|
|
22
|
+
### 3. Testing & Coverage
|
|
23
|
+
|
|
24
|
+
- **RSpec**: Shared helpers and configuration.
|
|
25
|
+
- **Playwright + Capybara**: Remote Chromium headless driver support with auto port assignment for parallel workers and HTML error state dumps on failure (`require 'rails_quality_assurance/playwright'`).
|
|
26
|
+
- **Parallel Tests**: `rake spec:parallel` task with automated system test isolation.
|
|
27
|
+
- **SimpleCov**: 100% line and branch coverage threshold enforcement, LCOV reporting, and parallel process reporting (`require 'rails_quality_assurance/simplecov'`).
|
|
28
|
+
|
|
29
|
+
### 4. Continuous Integration Harness
|
|
30
|
+
|
|
31
|
+
- **`RailsQualityAssurance::CI`**: Built-in pipeline runner modeled after Rails CI harnesses.
|
|
32
|
+
- **CLI / Executable**: Run with `bundle exec rails-qa` or define your pipeline in `config/ci.rb`.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
Add to your `Gemfile`:
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
group :development, :test do
|
|
42
|
+
gem 'rails-quality-assurance', require: false
|
|
43
|
+
end
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Then run:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
bundle install
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Zero-Config Usage
|
|
55
|
+
|
|
56
|
+
### 1. RuboCop
|
|
57
|
+
|
|
58
|
+
In your `.rubocop.yml`:
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
inherit_gem:
|
|
62
|
+
rails-quality-assurance: rubocop.yml
|
|
63
|
+
|
|
64
|
+
# Only your application-specific overrides are needed here
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 2. Single Require for Testing & Coverage (spec/spec_helper.rb)
|
|
68
|
+
|
|
69
|
+
Add a single line at the very top of `spec/spec_helper.rb`:
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
require 'rails_quality_assurance/all'
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
That single require sets up:
|
|
76
|
+
|
|
77
|
+
1. **SimpleCov**: Starts immediately before application code loads, enforcing 100% line & branch coverage thresholds, parallel process aggregation, and LCOV output.
|
|
78
|
+
2. **RSpec**: Configures mock verification of partial doubles, expectations, and metadata inheritance.
|
|
79
|
+
3. **Playwright + Capybara System Tests**: Registers the `:remote_playwright` headless driver, defaults system specs to `:rack_test`, escalates to Playwright for `js: true`, dynamically allocates ports for `parallel_tests` workers, and dumps HTML failure snapshots into `tmp/capybara`.
|
|
80
|
+
|
|
81
|
+
*(If you prefer to load them individually, `require 'rails_quality_assurance/simplecov'` and `require 'rails_quality_assurance/playwright'` remain available.)*
|
|
82
|
+
|
|
83
|
+
### 3. Continuous Integration: `bin/ci`
|
|
84
|
+
|
|
85
|
+
Run the generator to install `bin/ci` and `config/ci.rb`:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
bin/rails generate rails_quality_assurance:ci
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
This generates `bin/ci` (executable) and `config/ci.rb` following Develoz standards (matching Pitwall and Develoz B2B).
|
|
92
|
+
|
|
93
|
+
Run CI anytime on the host:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
bin/ci
|
|
97
|
+
```
|
|
98
|
+
Or in Docker-based setups:
|
|
99
|
+
```bash
|
|
100
|
+
bin/run bin/ci
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 4. Rake Tasks (Optional)
|
|
104
|
+
|
|
105
|
+
The gem also provides tasks if you prefer `rake`:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
bin/rails qa:lint # Runs RuboCop, Reek, Flay, Brakeman, bundler-audit
|
|
109
|
+
bin/rails qa:frontend # Runs Biome and Stylelint
|
|
110
|
+
bin/rails spec:parallel # Runs RSpec in parallel with system specs isolated
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Development
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
bundle install
|
|
119
|
+
bundle exec rspec
|
|
120
|
+
bundle exec rubocop
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
Released under the [MIT License](https://opensource.org/license/mit/).
|
data/config/biome.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.4.2/schema.json",
|
|
3
|
+
"assist": {
|
|
4
|
+
"actions": {
|
|
5
|
+
"source": {
|
|
6
|
+
"organizeImports": "on"
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"linter": {
|
|
11
|
+
"enabled": true,
|
|
12
|
+
"rules": {
|
|
13
|
+
"recommended": true,
|
|
14
|
+
"correctness": {
|
|
15
|
+
"noUnusedImports": "warn",
|
|
16
|
+
"noUnusedVariables": "warn"
|
|
17
|
+
},
|
|
18
|
+
"suspicious": {
|
|
19
|
+
"useIterableCallbackReturn": "off",
|
|
20
|
+
"noAssignInExpressions": "off",
|
|
21
|
+
"noDocumentCookie": "off"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"formatter": {
|
|
26
|
+
"enabled": true,
|
|
27
|
+
"indentStyle": "space",
|
|
28
|
+
"indentWidth": 2,
|
|
29
|
+
"lineWidth": 120
|
|
30
|
+
},
|
|
31
|
+
"javascript": {
|
|
32
|
+
"formatter": {
|
|
33
|
+
"quoteStyle": "double",
|
|
34
|
+
"semicolons": "asNeeded"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"json": {
|
|
38
|
+
"formatter": {
|
|
39
|
+
"indentWidth": 2
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"files": {
|
|
43
|
+
"includes": [
|
|
44
|
+
"app/javascript/**/*.js",
|
|
45
|
+
"app/javascript/**/*.ts",
|
|
46
|
+
"app/javascript/**/*.jsx",
|
|
47
|
+
"app/javascript/**/*.tsx"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
}
|
data/config/reek.yml
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Base Reek smell detectors for Rails applications
|
|
3
|
+
exclude_paths:
|
|
4
|
+
- app/assets
|
|
5
|
+
- config
|
|
6
|
+
- db
|
|
7
|
+
- lib/tasks
|
|
8
|
+
- vendor
|
|
9
|
+
- spec
|
|
10
|
+
- node_modules
|
|
11
|
+
|
|
12
|
+
detectors:
|
|
13
|
+
IrresponsibleModule:
|
|
14
|
+
enabled: false
|
|
15
|
+
UtilityFunction:
|
|
16
|
+
enabled: false
|
|
17
|
+
ControlParameter:
|
|
18
|
+
enabled: false
|
|
19
|
+
BooleanParameter:
|
|
20
|
+
enabled: false
|
|
21
|
+
FeatureEnvy:
|
|
22
|
+
enabled: false
|
|
23
|
+
TooManyStatements:
|
|
24
|
+
max_statements: 15
|
|
25
|
+
TooManyMethods:
|
|
26
|
+
max_methods: 25
|
|
27
|
+
UncommunicativeVariableName:
|
|
28
|
+
accept:
|
|
29
|
+
- e
|
|
30
|
+
- id
|
|
31
|
+
- f
|
|
32
|
+
- i
|
|
33
|
+
- n
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
require 'rails/generators/base'
|
|
5
|
+
|
|
6
|
+
module RailsQualityAssurance
|
|
7
|
+
module Generators
|
|
8
|
+
# Generates bin/ci and config/ci.rb for host-level CI execution
|
|
9
|
+
class CiGenerator < Rails::Generators::Base
|
|
10
|
+
source_root File.expand_path('templates', __dir__)
|
|
11
|
+
|
|
12
|
+
desc 'Installs bin/ci and config/ci.rb for Rails Continuous Integration'
|
|
13
|
+
|
|
14
|
+
def copy_ci_files
|
|
15
|
+
template 'bin_ci.erb', 'bin/ci'
|
|
16
|
+
chmod 'bin/ci', 0o755
|
|
17
|
+
template 'config_ci.rb.erb', 'config/ci.rb'
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Run using bin/ci
|
|
4
|
+
CI.run do
|
|
5
|
+
step 'Setup', 'bin/setup --skip-server'
|
|
6
|
+
|
|
7
|
+
step 'Style: Ruby', 'bin/rubocop'
|
|
8
|
+
step 'Style: Reek', 'bundle exec rake qa:reek'
|
|
9
|
+
step 'Style: Flay', 'bundle exec rake qa:flay'
|
|
10
|
+
|
|
11
|
+
step 'Security: Gem audit', 'bundle exec rake qa:audit'
|
|
12
|
+
step 'Security: Brakeman', 'bin/brakeman --quiet --no-pager --exit-on-warn --exit-on-error'
|
|
13
|
+
|
|
14
|
+
step 'Frontend: Biome', 'npm run biome' if File.exist?('biome.json')
|
|
15
|
+
step 'Frontend: Stylelint', 'npm run stylelint' if File.exist?('.stylelintrc.json')
|
|
16
|
+
|
|
17
|
+
step 'Tests: RSpec (parallel)', 'bin/rails spec:parallel'
|
|
18
|
+
|
|
19
|
+
# Coverage gate: enforced by SimpleCov in spec/spec_helper.rb (100% line + branch)
|
|
20
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# 1. Start SimpleCov immediately before any app code is loaded
|
|
4
|
+
require 'rails_quality_assurance/simplecov'
|
|
5
|
+
|
|
6
|
+
# 2. Configure RSpec core settings if RSpec is present
|
|
7
|
+
require 'rails_quality_assurance/rspec'
|
|
8
|
+
|
|
9
|
+
# 3. Configure Capybara + Playwright system test driver
|
|
10
|
+
require 'rails_quality_assurance/playwright'
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'English'
|
|
4
|
+
|
|
5
|
+
module RailsQualityAssurance
|
|
6
|
+
# Continuous Integration test and lint execution harness
|
|
7
|
+
class CI
|
|
8
|
+
# Represents a single verification step in the pipeline
|
|
9
|
+
class Step
|
|
10
|
+
attr_reader :name, :command
|
|
11
|
+
|
|
12
|
+
def initialize(name, command)
|
|
13
|
+
@name = name
|
|
14
|
+
@command = command
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def run
|
|
18
|
+
banner("Running: #{name}")
|
|
19
|
+
|
|
20
|
+
system(command)
|
|
21
|
+
exit_code = $CHILD_STATUS&.exitstatus || 1
|
|
22
|
+
|
|
23
|
+
if exit_code.zero?
|
|
24
|
+
puts "✓ #{name} passed"
|
|
25
|
+
else
|
|
26
|
+
puts "✗ #{name} failed (exit code: #{exit_code})"
|
|
27
|
+
Kernel.exit(exit_code)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.run(&)
|
|
33
|
+
runner = new
|
|
34
|
+
runner.instance_eval(&) if block_given?
|
|
35
|
+
runner.execute
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def initialize
|
|
39
|
+
@steps = []
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def step(name, command = nil, &block)
|
|
43
|
+
@steps << [name, command || block]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def execute
|
|
47
|
+
banner('Rails Quality Assurance Pipeline')
|
|
48
|
+
|
|
49
|
+
@steps.each do |name, action|
|
|
50
|
+
if action.is_a?(Proc)
|
|
51
|
+
banner("Running: #{name}")
|
|
52
|
+
action.call
|
|
53
|
+
else
|
|
54
|
+
Step.new(name, action).run
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
banner('✓ All Quality Assurance checks passed')
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def banner(text)
|
|
64
|
+
separator = '=' * 60
|
|
65
|
+
puts "\n#{separator}"
|
|
66
|
+
puts text
|
|
67
|
+
puts separator
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_quality_assurance/ci'
|
|
4
|
+
|
|
5
|
+
# Emulate ActiveSupport::ContinuousIntegration interface if needed
|
|
6
|
+
unless defined?(ActiveSupport::ContinuousIntegration)
|
|
7
|
+
module ActiveSupport
|
|
8
|
+
module ContinuousIntegration
|
|
9
|
+
def self.run(&)
|
|
10
|
+
RailsQualityAssurance::CI.run(&)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsQualityAssurance
|
|
4
|
+
module PlaywrightHelper
|
|
5
|
+
def self.configure!
|
|
6
|
+
require 'capybara'
|
|
7
|
+
require 'capybara-playwright-driver'
|
|
8
|
+
|
|
9
|
+
playwright_url = ENV.fetch('PLAYWRIGHT_URL', nil)
|
|
10
|
+
capybara_port = ENV.fetch('CAPYBARA_SERVER_PORT', 3001)
|
|
11
|
+
|
|
12
|
+
register_capybara_driver(playwright_url)
|
|
13
|
+
configure_rspec(playwright_url, capybara_port) if defined?(RSpec)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.register_capybara_driver(playwright_url)
|
|
17
|
+
Capybara.register_driver :remote_playwright do |app|
|
|
18
|
+
options = {
|
|
19
|
+
browser_type: :chromium,
|
|
20
|
+
headless: true,
|
|
21
|
+
args: ['--disable-dev-shm-usage'],
|
|
22
|
+
viewport: { width: 1400, height: 1400 },
|
|
23
|
+
screen: { width: 1400, height: 1400 }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if playwright_url.present?
|
|
27
|
+
options[:browser_server_endpoint_url] = playwright_url
|
|
28
|
+
elsif local_playwright_cli
|
|
29
|
+
options[:playwright_cli_executable_path] = local_playwright_cli.to_s
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
Capybara::Playwright::Driver.new(app, **options)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.local_playwright_cli
|
|
37
|
+
return nil unless defined?(Rails)
|
|
38
|
+
|
|
39
|
+
cli_path = Rails.root.join('node_modules/.bin/playwright-core')
|
|
40
|
+
cli_path.executable? ? cli_path : nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.configure_rspec(playwright_url, capybara_port)
|
|
44
|
+
RSpec.configure do |config|
|
|
45
|
+
setup_system_hooks(config, playwright_url, capybara_port)
|
|
46
|
+
setup_failure_dump(config)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.setup_system_hooks(config, playwright_url, capybara_port)
|
|
51
|
+
config.before(type: :system) do
|
|
52
|
+
Capybara.default_max_wait_time = 10
|
|
53
|
+
driven_by :rack_test
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
config.before(type: :system, js: true) do
|
|
57
|
+
PlaywrightHelper.apply_js_system_driver(playwright_url, capybara_port)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.apply_js_system_driver(playwright_url, capybara_port)
|
|
62
|
+
if playwright_url.present?
|
|
63
|
+
Capybara.server_host = '0.0.0.0'
|
|
64
|
+
base_port = capybara_port.to_i
|
|
65
|
+
test_env_number = (ENV.fetch('TEST_ENV_NUMBER', nil) || '0').to_i
|
|
66
|
+
Capybara.server_port = base_port + test_env_number
|
|
67
|
+
|
|
68
|
+
hostname = Socket.gethostname
|
|
69
|
+
Capybara.app_host = "http://#{hostname}:#{Capybara.server_port}"
|
|
70
|
+
else
|
|
71
|
+
Capybara.server_port = nil
|
|
72
|
+
Capybara.app_host = nil
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
Capybara.current_driver = :remote_playwright
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.setup_failure_dump(config)
|
|
79
|
+
config.after(type: :system) do |example|
|
|
80
|
+
next unless example.exception
|
|
81
|
+
next unless defined?(Rails)
|
|
82
|
+
|
|
83
|
+
session = Capybara.current_session
|
|
84
|
+
next unless session.current_url.to_s.start_with?('http')
|
|
85
|
+
|
|
86
|
+
save_dir = Rails.root.join('tmp/capybara')
|
|
87
|
+
FileUtils.mkdir_p(save_dir)
|
|
88
|
+
slug = example.full_description.parameterize.first(120)
|
|
89
|
+
path = save_dir.join("failure-#{slug}-#{Process.pid}.html")
|
|
90
|
+
File.write(path, session.html)
|
|
91
|
+
rescue StandardError
|
|
92
|
+
# Never fail the suite on diagnostic errors
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_quality_assurance/simplecov/helper'
|
|
4
|
+
require 'rails_quality_assurance/playwright/helper'
|
|
5
|
+
|
|
6
|
+
module RailsQualityAssurance
|
|
7
|
+
module RSpecHelper
|
|
8
|
+
def self.configure!
|
|
9
|
+
return unless defined?(RSpec)
|
|
10
|
+
|
|
11
|
+
RSpec.configure do |config|
|
|
12
|
+
configure_expectations(config)
|
|
13
|
+
configure_mocks(config)
|
|
14
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
|
15
|
+
config.order = :random
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.configure_expectations(config)
|
|
20
|
+
config.expect_with :rspec do |expectations|
|
|
21
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.configure_mocks(config)
|
|
26
|
+
config.mock_with :rspec do |mocks|
|
|
27
|
+
mocks.verify_partial_doubles = true
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsQualityAssurance
|
|
4
|
+
module SimpleCovHelper
|
|
5
|
+
def self.configure!
|
|
6
|
+
return if ENV['NO_COVERAGE']
|
|
7
|
+
return if filtered_run? && !ENV['COVERAGE']
|
|
8
|
+
|
|
9
|
+
require 'simplecov'
|
|
10
|
+
require 'simplecov-lcov'
|
|
11
|
+
|
|
12
|
+
configure_lcov_formatter
|
|
13
|
+
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
|
|
14
|
+
SimpleCov::Formatter::HTMLFormatter,
|
|
15
|
+
SimpleCov::Formatter::LcovFormatter
|
|
16
|
+
])
|
|
17
|
+
start_coverage
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.filtered_run?
|
|
21
|
+
return false unless defined?(RSpec)
|
|
22
|
+
|
|
23
|
+
rspec_config = RSpec.configuration
|
|
24
|
+
rspec_config.files_to_run.one? ||
|
|
25
|
+
rspec_config.only_failures? ||
|
|
26
|
+
(rspec_config.inclusion_filter.rules&.size&.> 0)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.configure_lcov_formatter
|
|
30
|
+
SimpleCov::Formatter::LcovFormatter.config do |formatter|
|
|
31
|
+
formatter.report_with_single_file = true
|
|
32
|
+
formatter.single_report_path = 'public/coverage/lcov.info'
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.start_coverage
|
|
37
|
+
SimpleCov.start 'rails' do
|
|
38
|
+
ENV['SIMPLECOV_INLINE_ASSETS'] = 'true'
|
|
39
|
+
coverage_dir 'public/coverage'
|
|
40
|
+
enable_coverage :branch
|
|
41
|
+
|
|
42
|
+
command_name "rspec#{ENV.fetch('TEST_ENV_NUMBER', nil)}"
|
|
43
|
+
|
|
44
|
+
add_filter '/spec/'
|
|
45
|
+
add_filter '/config/'
|
|
46
|
+
add_filter '/vendor/'
|
|
47
|
+
|
|
48
|
+
SimpleCov.minimum_coverage line: 100, branch: 100
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_quality_assurance/version'
|
|
4
|
+
require 'rails_quality_assurance/ci'
|
|
5
|
+
|
|
6
|
+
module RailsQualityAssurance
|
|
7
|
+
class Error < StandardError; end
|
|
8
|
+
|
|
9
|
+
def self.root
|
|
10
|
+
File.expand_path('..', __dir__)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.rubocop_config_path
|
|
14
|
+
File.join(root, 'rubocop.yml')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.reek_config_path
|
|
18
|
+
File.join(root, 'config/reek.yml')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.biome_config_path
|
|
22
|
+
File.join(root, 'config/biome.json')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.stylelint_config_path
|
|
26
|
+
File.join(root, 'config/.stylelintrc.json')
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
require 'rails_quality_assurance/railtie' if defined?(Rails::Railtie)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_quality_assurance'
|
|
4
|
+
|
|
5
|
+
namespace :qa do
|
|
6
|
+
desc 'Run all quality assurance checks (RuboCop, Reek, Flay, Brakeman, bundler-audit)'
|
|
7
|
+
task lint: %w[qa:rubocop qa:reek qa:flay qa:brakeman qa:audit]
|
|
8
|
+
|
|
9
|
+
desc 'Run RuboCop'
|
|
10
|
+
task rubocop: :environment do
|
|
11
|
+
sh 'bundle exec rubocop'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
desc 'Run Reek code smell detection'
|
|
15
|
+
task reek: :environment do
|
|
16
|
+
config = File.exist?('.reek.yml') ? '' : "-c #{RailsQualityAssurance.reek_config_path}"
|
|
17
|
+
sh "bundle exec reek #{config} app lib"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
desc 'Run Flay structural code duplication analysis'
|
|
21
|
+
task flay: :environment do
|
|
22
|
+
mass = ENV.fetch('FLAY_MASS', '300')
|
|
23
|
+
output = `bundle exec flay --mass #{mass} app lib`
|
|
24
|
+
puts output
|
|
25
|
+
abort 'Flay detected structural duplication' unless output.include?('Total score (lower is better) = 0')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
desc 'Run Brakeman static security analysis'
|
|
29
|
+
task brakeman: :environment do
|
|
30
|
+
sh 'bundle exec brakeman --quiet --no-pager --exit-on-warn --exit-on-error'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
desc 'Run Bundler Audit for vulnerable gems'
|
|
34
|
+
task audit: :environment do
|
|
35
|
+
sh 'bundle exec bundle audit check --update'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
namespace :lint do
|
|
39
|
+
desc 'Run BiomeJS on JS/TS/JSON'
|
|
40
|
+
task biome: :environment do
|
|
41
|
+
config = File.exist?('biome.json') ? '' : "--config-path #{RailsQualityAssurance.biome_config_path}"
|
|
42
|
+
sh "npx @biomejs/biome check #{config}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
desc 'Run Stylelint on CSS'
|
|
46
|
+
task stylelint: :environment do
|
|
47
|
+
config = File.exist?('.stylelintrc.json') ? '' : "--config #{RailsQualityAssurance.stylelint_config_path}"
|
|
48
|
+
sh "npx stylelint #{config} \"**/*.css\""
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
desc 'Run frontend linters (Biome + Stylelint)'
|
|
53
|
+
task frontend: %w[qa:lint:biome qa:lint:stylelint]
|
|
54
|
+
|
|
55
|
+
desc 'Run all CI checks'
|
|
56
|
+
task ci: %w[qa:lint qa:frontend spec:parallel]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
namespace :lint do
|
|
60
|
+
desc 'Alias for qa:lint'
|
|
61
|
+
task all: 'qa:lint'
|
|
62
|
+
|
|
63
|
+
desc 'Run BiomeJS linter'
|
|
64
|
+
task biome: 'qa:lint:biome'
|
|
65
|
+
|
|
66
|
+
desc 'Run Stylelint on CSS'
|
|
67
|
+
task stylelint: 'qa:lint:stylelint'
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
task lint: 'qa:lint'
|
|
71
|
+
|
|
72
|
+
namespace :spec do
|
|
73
|
+
desc 'Run specs in parallel with system specs isolated'
|
|
74
|
+
task parallel: :environment do
|
|
75
|
+
ENV['PARALLEL_TEST_FIRST_IS_1'] ||= 'true'
|
|
76
|
+
parallel_tasks = ENV.fetch('PARALLEL_TEST_PROCESSORS', 3).to_s
|
|
77
|
+
isolate_tasks = ENV.fetch('ISOLATE_SPEC_TASKS', 1).to_s
|
|
78
|
+
test_options = ENV.fetch('PARALLEL_SPEC_OPTIONS', nil)
|
|
79
|
+
raise ArgumentError, 'PARALLEL_TEST_PROCESSORS must be a positive integer' if parallel_tasks.to_i <= 0
|
|
80
|
+
|
|
81
|
+
options = "--isolate --single spec/system/ --isolate-n #{isolate_tasks}"
|
|
82
|
+
options << " --test-options=\"#{test_options}\"" if test_options
|
|
83
|
+
Rake::Task['parallel:create'].invoke(parallel_tasks)
|
|
84
|
+
Rake::Task['parallel:load_schema'].invoke(parallel_tasks)
|
|
85
|
+
Rake::Task['parallel:spec'].invoke(parallel_tasks, nil, nil, options)
|
|
86
|
+
end
|
|
87
|
+
end
|
data/rubocop.yml
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Develoz Ruby styling.
|
|
2
|
+
#
|
|
3
|
+
# Shared baseline for all Develoz projects. Application-specific tweaks
|
|
4
|
+
# (file excludes, loosened metrics) belong in the project's own
|
|
5
|
+
# .rubocop.yml, which inherits this file.
|
|
6
|
+
#
|
|
7
|
+
# Never remove this line.
|
|
8
|
+
# This merges default exclusions which makes running rubocop much faster.
|
|
9
|
+
inherit_mode:
|
|
10
|
+
merge:
|
|
11
|
+
- Exclude
|
|
12
|
+
|
|
13
|
+
plugins:
|
|
14
|
+
- rubocop-performance
|
|
15
|
+
- rubocop-rspec
|
|
16
|
+
- rubocop-rspec_rails
|
|
17
|
+
- rubocop-capybara
|
|
18
|
+
- rubocop-factory_bot
|
|
19
|
+
- rubocop-rubycw
|
|
20
|
+
- rubocop-migration
|
|
21
|
+
- rubocop-rails
|
|
22
|
+
|
|
23
|
+
AllCops:
|
|
24
|
+
TargetRubyVersion: 4.0
|
|
25
|
+
NewCops: enable
|
|
26
|
+
Exclude:
|
|
27
|
+
- "bin/*"
|
|
28
|
+
- "db/schema.rb"
|
|
29
|
+
- "db/migrate/**/*.rb"
|
|
30
|
+
- "vendor/**/*"
|
|
31
|
+
- "config/locales/**/*.yml"
|
|
32
|
+
|
|
33
|
+
FactoryBot/ExcessiveCreateList:
|
|
34
|
+
MaxAmount: 15
|
|
35
|
+
|
|
36
|
+
Layout/LineLength:
|
|
37
|
+
Max: 120
|
|
38
|
+
AllowedPatterns:
|
|
39
|
+
- !ruby/regexp /^ *# /
|
|
40
|
+
|
|
41
|
+
Migration/AddIndexColumnsCount:
|
|
42
|
+
Enabled: true
|
|
43
|
+
MaxColumnsCount: 4
|
|
44
|
+
|
|
45
|
+
Migration/AddIndexConcurrently:
|
|
46
|
+
Enabled: true
|
|
47
|
+
|
|
48
|
+
Migration/AddIndexDuplicate:
|
|
49
|
+
Enabled: true
|
|
50
|
+
|
|
51
|
+
Migration/Jsonb:
|
|
52
|
+
Enabled: true
|
|
53
|
+
|
|
54
|
+
Naming/VariableNumber:
|
|
55
|
+
Enabled: false
|
|
56
|
+
|
|
57
|
+
Rails/SkipsModelValidations:
|
|
58
|
+
Enabled: false
|
|
59
|
+
|
|
60
|
+
Style/Documentation:
|
|
61
|
+
Enabled: false
|
|
62
|
+
|
|
63
|
+
Style/SafeNavigationChainLength:
|
|
64
|
+
Enabled: false
|
|
65
|
+
|
|
66
|
+
Style/HashSyntax:
|
|
67
|
+
EnforcedShorthandSyntax: always
|
|
68
|
+
|
|
69
|
+
Metrics/AbcSize:
|
|
70
|
+
Max: 35
|
|
71
|
+
|
|
72
|
+
Metrics/ClassLength:
|
|
73
|
+
Max: 150
|
|
74
|
+
|
|
75
|
+
Metrics/MethodLength:
|
|
76
|
+
Max: 30
|
|
77
|
+
|
|
78
|
+
Metrics/BlockLength:
|
|
79
|
+
Exclude:
|
|
80
|
+
- "config/**/*"
|
|
81
|
+
- "lib/tasks/**/*"
|
|
82
|
+
|
|
83
|
+
Metrics/CyclomaticComplexity:
|
|
84
|
+
Max: 10
|
|
85
|
+
|
|
86
|
+
Metrics/PerceivedComplexity:
|
|
87
|
+
Max: 10
|
|
88
|
+
|
|
89
|
+
# RSpec system tests naturally have multiple expectations
|
|
90
|
+
RSpec/MultipleExpectations:
|
|
91
|
+
Max: 5
|
|
92
|
+
Exclude:
|
|
93
|
+
- "spec/system/**/*"
|
|
94
|
+
- "spec/views/**/*"
|
|
95
|
+
- "spec/helpers/**/*"
|
|
96
|
+
|
|
97
|
+
# RSpec system tests can be longer
|
|
98
|
+
RSpec/ExampleLength:
|
|
99
|
+
Max: 15
|
|
100
|
+
Exclude:
|
|
101
|
+
- "spec/system/**/*"
|
|
102
|
+
- "spec/views/**/*"
|
|
103
|
+
- "spec/helpers/**/*"
|
|
104
|
+
|
|
105
|
+
# We might want to check texts in tests
|
|
106
|
+
Rails/I18nLocaleTexts:
|
|
107
|
+
Exclude:
|
|
108
|
+
- "spec/**/*"
|
|
109
|
+
|
|
110
|
+
# Allow more memoized helpers in specs for comprehensive testing
|
|
111
|
+
RSpec/MultipleMemoizedHelpers:
|
|
112
|
+
Max: 10
|
|
113
|
+
|
|
114
|
+
# Allow I18n.locale assignment in test setup blocks
|
|
115
|
+
Rails/I18nLocaleAssignment:
|
|
116
|
+
Exclude:
|
|
117
|
+
- "spec/**/*"
|
|
118
|
+
|
|
119
|
+
# Allow allow_any_instance_of
|
|
120
|
+
RSpec/AnyInstance:
|
|
121
|
+
Enabled: false
|
|
122
|
+
|
|
123
|
+
# Allow expect_any_instance_of
|
|
124
|
+
RSpec/StubbedMock:
|
|
125
|
+
Enabled: false
|
|
126
|
+
|
|
127
|
+
# Allow message chains
|
|
128
|
+
RSpec/MessageChain:
|
|
129
|
+
Enabled: false
|
|
130
|
+
|
|
131
|
+
RSpec/NestedGroups:
|
|
132
|
+
Max: 6
|
|
133
|
+
|
|
134
|
+
# Allow let! setup in specs where roles/associations are needed
|
|
135
|
+
RSpec/LetSetup:
|
|
136
|
+
Exclude:
|
|
137
|
+
- "spec/system/**/*"
|
|
138
|
+
- "spec/requests/**/*"
|
|
139
|
+
- "spec/controllers/**/*"
|
|
140
|
+
|
|
141
|
+
# Capybara negation matcher warnings are false positives for have_no_*
|
|
142
|
+
Capybara/NegationMatcherAfterVisit:
|
|
143
|
+
Enabled: false
|
metadata
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rails-quality-assurance
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Mauricio Zaffari
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rubocop
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 1.85.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 1.85.0
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rubocop-capybara
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 2.22.0
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 2.22.0
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rubocop-factory_bot
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 2.28.0
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 2.28.0
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rubocop-migration
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: 0.7.1
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: 0.7.1
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: rubocop-performance
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: 1.26.0
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: 1.26.0
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: rubocop-rails
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: 2.34.0
|
|
89
|
+
type: :runtime
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: 2.34.0
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: rubocop-rspec
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: 3.9.0
|
|
103
|
+
type: :runtime
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: 3.9.0
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: rubocop-rspec_rails
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: 2.32.0
|
|
117
|
+
type: :runtime
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: 2.32.0
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: rubocop-rubycw
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - "~>"
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: 0.2.0
|
|
131
|
+
type: :runtime
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - "~>"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: 0.2.0
|
|
138
|
+
- !ruby/object:Gem::Dependency
|
|
139
|
+
name: brakeman
|
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
|
141
|
+
requirements:
|
|
142
|
+
- - ">="
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: '7.0'
|
|
145
|
+
type: :runtime
|
|
146
|
+
prerelease: false
|
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - ">="
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '7.0'
|
|
152
|
+
- !ruby/object:Gem::Dependency
|
|
153
|
+
name: bundler-audit
|
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
|
155
|
+
requirements:
|
|
156
|
+
- - ">="
|
|
157
|
+
- !ruby/object:Gem::Version
|
|
158
|
+
version: '0.9'
|
|
159
|
+
type: :runtime
|
|
160
|
+
prerelease: false
|
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - ">="
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '0.9'
|
|
166
|
+
- !ruby/object:Gem::Dependency
|
|
167
|
+
name: flay
|
|
168
|
+
requirement: !ruby/object:Gem::Requirement
|
|
169
|
+
requirements:
|
|
170
|
+
- - ">="
|
|
171
|
+
- !ruby/object:Gem::Version
|
|
172
|
+
version: '2.14'
|
|
173
|
+
type: :runtime
|
|
174
|
+
prerelease: false
|
|
175
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
176
|
+
requirements:
|
|
177
|
+
- - ">="
|
|
178
|
+
- !ruby/object:Gem::Version
|
|
179
|
+
version: '2.14'
|
|
180
|
+
- !ruby/object:Gem::Dependency
|
|
181
|
+
name: reek
|
|
182
|
+
requirement: !ruby/object:Gem::Requirement
|
|
183
|
+
requirements:
|
|
184
|
+
- - ">="
|
|
185
|
+
- !ruby/object:Gem::Version
|
|
186
|
+
version: '6.3'
|
|
187
|
+
type: :runtime
|
|
188
|
+
prerelease: false
|
|
189
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
190
|
+
requirements:
|
|
191
|
+
- - ">="
|
|
192
|
+
- !ruby/object:Gem::Version
|
|
193
|
+
version: '6.3'
|
|
194
|
+
- !ruby/object:Gem::Dependency
|
|
195
|
+
name: parallel_tests
|
|
196
|
+
requirement: !ruby/object:Gem::Requirement
|
|
197
|
+
requirements:
|
|
198
|
+
- - ">="
|
|
199
|
+
- !ruby/object:Gem::Version
|
|
200
|
+
version: '5.0'
|
|
201
|
+
type: :runtime
|
|
202
|
+
prerelease: false
|
|
203
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
204
|
+
requirements:
|
|
205
|
+
- - ">="
|
|
206
|
+
- !ruby/object:Gem::Version
|
|
207
|
+
version: '5.0'
|
|
208
|
+
- !ruby/object:Gem::Dependency
|
|
209
|
+
name: rspec-rails
|
|
210
|
+
requirement: !ruby/object:Gem::Requirement
|
|
211
|
+
requirements:
|
|
212
|
+
- - ">="
|
|
213
|
+
- !ruby/object:Gem::Version
|
|
214
|
+
version: '7.0'
|
|
215
|
+
type: :runtime
|
|
216
|
+
prerelease: false
|
|
217
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
218
|
+
requirements:
|
|
219
|
+
- - ">="
|
|
220
|
+
- !ruby/object:Gem::Version
|
|
221
|
+
version: '7.0'
|
|
222
|
+
- !ruby/object:Gem::Dependency
|
|
223
|
+
name: simplecov
|
|
224
|
+
requirement: !ruby/object:Gem::Requirement
|
|
225
|
+
requirements:
|
|
226
|
+
- - ">="
|
|
227
|
+
- !ruby/object:Gem::Version
|
|
228
|
+
version: '0.22'
|
|
229
|
+
type: :runtime
|
|
230
|
+
prerelease: false
|
|
231
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
232
|
+
requirements:
|
|
233
|
+
- - ">="
|
|
234
|
+
- !ruby/object:Gem::Version
|
|
235
|
+
version: '0.22'
|
|
236
|
+
- !ruby/object:Gem::Dependency
|
|
237
|
+
name: simplecov-lcov
|
|
238
|
+
requirement: !ruby/object:Gem::Requirement
|
|
239
|
+
requirements:
|
|
240
|
+
- - ">="
|
|
241
|
+
- !ruby/object:Gem::Version
|
|
242
|
+
version: '0.8'
|
|
243
|
+
type: :runtime
|
|
244
|
+
prerelease: false
|
|
245
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
246
|
+
requirements:
|
|
247
|
+
- - ">="
|
|
248
|
+
- !ruby/object:Gem::Version
|
|
249
|
+
version: '0.8'
|
|
250
|
+
- !ruby/object:Gem::Dependency
|
|
251
|
+
name: capybara
|
|
252
|
+
requirement: !ruby/object:Gem::Requirement
|
|
253
|
+
requirements:
|
|
254
|
+
- - ">="
|
|
255
|
+
- !ruby/object:Gem::Version
|
|
256
|
+
version: '3.40'
|
|
257
|
+
type: :runtime
|
|
258
|
+
prerelease: false
|
|
259
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
260
|
+
requirements:
|
|
261
|
+
- - ">="
|
|
262
|
+
- !ruby/object:Gem::Version
|
|
263
|
+
version: '3.40'
|
|
264
|
+
- !ruby/object:Gem::Dependency
|
|
265
|
+
name: capybara-playwright-driver
|
|
266
|
+
requirement: !ruby/object:Gem::Requirement
|
|
267
|
+
requirements:
|
|
268
|
+
- - ">="
|
|
269
|
+
- !ruby/object:Gem::Version
|
|
270
|
+
version: 0.5.0
|
|
271
|
+
type: :runtime
|
|
272
|
+
prerelease: false
|
|
273
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
274
|
+
requirements:
|
|
275
|
+
- - ">="
|
|
276
|
+
- !ruby/object:Gem::Version
|
|
277
|
+
version: 0.5.0
|
|
278
|
+
- !ruby/object:Gem::Dependency
|
|
279
|
+
name: playwright-ruby-client
|
|
280
|
+
requirement: !ruby/object:Gem::Requirement
|
|
281
|
+
requirements:
|
|
282
|
+
- - ">="
|
|
283
|
+
- !ruby/object:Gem::Version
|
|
284
|
+
version: 1.50.0
|
|
285
|
+
type: :runtime
|
|
286
|
+
prerelease: false
|
|
287
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
288
|
+
requirements:
|
|
289
|
+
- - ">="
|
|
290
|
+
- !ruby/object:Gem::Version
|
|
291
|
+
version: 1.50.0
|
|
292
|
+
- !ruby/object:Gem::Dependency
|
|
293
|
+
name: railties
|
|
294
|
+
requirement: !ruby/object:Gem::Requirement
|
|
295
|
+
requirements:
|
|
296
|
+
- - ">="
|
|
297
|
+
- !ruby/object:Gem::Version
|
|
298
|
+
version: '7.0'
|
|
299
|
+
type: :runtime
|
|
300
|
+
prerelease: false
|
|
301
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
302
|
+
requirements:
|
|
303
|
+
- - ">="
|
|
304
|
+
- !ruby/object:Gem::Version
|
|
305
|
+
version: '7.0'
|
|
306
|
+
- !ruby/object:Gem::Dependency
|
|
307
|
+
name: rake
|
|
308
|
+
requirement: !ruby/object:Gem::Requirement
|
|
309
|
+
requirements:
|
|
310
|
+
- - "~>"
|
|
311
|
+
- !ruby/object:Gem::Version
|
|
312
|
+
version: '13.0'
|
|
313
|
+
type: :development
|
|
314
|
+
prerelease: false
|
|
315
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
316
|
+
requirements:
|
|
317
|
+
- - "~>"
|
|
318
|
+
- !ruby/object:Gem::Version
|
|
319
|
+
version: '13.0'
|
|
320
|
+
- !ruby/object:Gem::Dependency
|
|
321
|
+
name: rspec
|
|
322
|
+
requirement: !ruby/object:Gem::Requirement
|
|
323
|
+
requirements:
|
|
324
|
+
- - "~>"
|
|
325
|
+
- !ruby/object:Gem::Version
|
|
326
|
+
version: '3.13'
|
|
327
|
+
type: :development
|
|
328
|
+
prerelease: false
|
|
329
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
330
|
+
requirements:
|
|
331
|
+
- - "~>"
|
|
332
|
+
- !ruby/object:Gem::Version
|
|
333
|
+
version: '3.13'
|
|
334
|
+
description: 'Unified QA kit for Rails apps: testing, linters, security audits, parallel
|
|
335
|
+
execution, and CI.'
|
|
336
|
+
email:
|
|
337
|
+
- mauricio@develoz.com
|
|
338
|
+
executables: []
|
|
339
|
+
extensions: []
|
|
340
|
+
extra_rdoc_files: []
|
|
341
|
+
files:
|
|
342
|
+
- CHANGELOG.md
|
|
343
|
+
- LICENSE.txt
|
|
344
|
+
- README.md
|
|
345
|
+
- config/biome.json
|
|
346
|
+
- config/reek.yml
|
|
347
|
+
- lib/generators/rails_quality_assurance/ci/ci_generator.rb
|
|
348
|
+
- lib/generators/rails_quality_assurance/ci/templates/bin_ci.erb
|
|
349
|
+
- lib/generators/rails_quality_assurance/ci/templates/config_ci.rb.erb
|
|
350
|
+
- lib/rails_quality_assurance.rb
|
|
351
|
+
- lib/rails_quality_assurance/all.rb
|
|
352
|
+
- lib/rails_quality_assurance/ci.rb
|
|
353
|
+
- lib/rails_quality_assurance/ci_runner.rb
|
|
354
|
+
- lib/rails_quality_assurance/playwright.rb
|
|
355
|
+
- lib/rails_quality_assurance/playwright/helper.rb
|
|
356
|
+
- lib/rails_quality_assurance/railtie.rb
|
|
357
|
+
- lib/rails_quality_assurance/rspec.rb
|
|
358
|
+
- lib/rails_quality_assurance/rspec/helper.rb
|
|
359
|
+
- lib/rails_quality_assurance/simplecov.rb
|
|
360
|
+
- lib/rails_quality_assurance/simplecov/helper.rb
|
|
361
|
+
- lib/rails_quality_assurance/test_helper.rb
|
|
362
|
+
- lib/rails_quality_assurance/version.rb
|
|
363
|
+
- lib/tasks/quality_assurance.rake
|
|
364
|
+
- rubocop.yml
|
|
365
|
+
homepage: https://github.com/develoz-com/rails-quality-assurance
|
|
366
|
+
licenses:
|
|
367
|
+
- MIT
|
|
368
|
+
metadata:
|
|
369
|
+
homepage_uri: https://github.com/develoz-com/rails-quality-assurance
|
|
370
|
+
source_code_uri: https://github.com/develoz-com/rails-quality-assurance
|
|
371
|
+
changelog_uri: https://github.com/develoz-com/rails-quality-assurance/blob/main/CHANGELOG.md
|
|
372
|
+
rubygems_mfa_required: 'true'
|
|
373
|
+
rdoc_options: []
|
|
374
|
+
require_paths:
|
|
375
|
+
- lib
|
|
376
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
377
|
+
requirements:
|
|
378
|
+
- - ">="
|
|
379
|
+
- !ruby/object:Gem::Version
|
|
380
|
+
version: '4.0'
|
|
381
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
382
|
+
requirements:
|
|
383
|
+
- - ">="
|
|
384
|
+
- !ruby/object:Gem::Version
|
|
385
|
+
version: '0'
|
|
386
|
+
requirements: []
|
|
387
|
+
rubygems_version: 4.0.16
|
|
388
|
+
specification_version: 4
|
|
389
|
+
summary: Opinionated quality assurance kit for Rails applications.
|
|
390
|
+
test_files: []
|