From 5c95af24c26bbedfef632a28b281073517d18f4e Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Wed, 1 Oct 2025 16:43:35 -1000 Subject: [PATCH 1/2] Add RuboCop linting and newline enforcement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set up automated linting and code quality tools: 1. Added RuboCop with extensions: - rubocop-rake for rake task linting - rubocop-rspec for RSpec linting - Created .rubocop.yml with sensible defaults 2. Created rake tasks for linting (rakelib/lint.rake): - rake lint - Run all linters - rake lint:fix - Auto-fix issues - rake check_newlines - Verify files end with newlines - rake fix_newlines - Fix missing newlines 3. Added pre-commit hook installer (bin/install-hooks): - Checks for missing newlines - Runs RuboCop on staged Ruby files - Prevents commits with linting issues 4. Added GitHub Actions workflow (.github/workflows/lint.yml): - Runs on all PRs and pushes to master - Enforces linting in CI - Checks for missing newlines 5. Updated CI workflow: - Added :ci task to run specs, lint, and newline checks - Ensures all checks pass before merge To install pre-commit hook: ./bin/install-hooks 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/workflows/lint.yml | 26 +++++++++++++ .rubocop.yml | 76 ++++++++++++++++++++++++++++++++++++++ Rakefile | 3 ++ bin/install-hooks | 50 +++++++++++++++++++++++++ cypress-on-rails.gemspec | 3 ++ rakelib/lint.rake | 63 +++++++++++++++++++++++++++++++ 6 files changed, 221 insertions(+) create mode 100644 .github/workflows/lint.yml create mode 100644 .rubocop.yml create mode 100755 bin/install-hooks create mode 100644 rakelib/lint.rake diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..4df4b114 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,26 @@ +name: Lint + +on: + push: + branches: [master, main] + pull_request: + branches: [master, main] + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.2' + bundler-cache: true + + - name: Run RuboCop + run: bundle exec rubocop + + - name: Check for files missing newlines + run: bundle exec rake check_newlines diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000..8ddb9706 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,76 @@ +require: + - rubocop-rake + - rubocop-rspec + +AllCops: + TargetRubyVersion: 2.6 + NewCops: enable + Exclude: + - 'vendor/**/*' + - 'spec/fixtures/**/*' + - 'tmp/**/*' + - 'pkg/**/*' + - 'node_modules/**/*' + - 'specs_e2e/**/*' + - 'e2e/**/*' + +# Ensure all files end with a newline +Layout/TrailingEmptyLines: + Enabled: true + EnforcedStyle: final_newline + +# Ensure no trailing whitespace +Layout/TrailingWhitespace: + Enabled: true + +# Line length - be reasonable but not too strict +Layout/LineLength: + Max: 120 + Exclude: + - 'spec/**/*' + - 'lib/generators/**/*' + +# Allow longer blocks in specs and rake tasks +Metrics/BlockLength: + Exclude: + - 'spec/**/*' + - '**/*.rake' + - 'Rakefile' + - '*.gemspec' + +# Allow longer methods in rake tasks +Metrics/MethodLength: + Exclude: + - '**/*.rake' + - 'Rakefile' + +# String literals +Style/StringLiterals: + Enabled: true + EnforcedStyle: single_quotes + ConsistentQuotesInMultiline: true + +# Frozen string literal pragma +Style/FrozenStringLiteralComment: + Enabled: true + EnforcedStyle: always + Exclude: + - 'spec/**/*' + +# Documentation +Style/Documentation: + Enabled: false + +# Allow compact module/class definitions +Style/ClassAndModuleChildren: + Enabled: false + +# RSpec specific +RSpec/ExampleLength: + Max: 20 + +RSpec/MultipleExpectations: + Max: 5 + +RSpec/NestedGroups: + Max: 4 diff --git a/Rakefile b/Rakefile index d19b8a05..d3301ce1 100644 --- a/Rakefile +++ b/Rakefile @@ -5,4 +5,7 @@ RSpec::Core::RakeTask.new(:spec) do |t| t.pattern = 'spec/cypress_on_rails/*_spec.rb' end +desc 'Run all CI checks (specs, linting, newlines)' +task ci: %i[spec lint check_newlines] + task default: %w[spec build] diff --git a/bin/install-hooks b/bin/install-hooks new file mode 100755 index 00000000..dcf6998c --- /dev/null +++ b/bin/install-hooks @@ -0,0 +1,50 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'fileutils' + +hooks_dir = File.expand_path('../.git/hooks', __dir__) +pre_commit_hook = File.join(hooks_dir, 'pre-commit') + +# Create pre-commit hook content +hook_content = <<~HOOK + #!/bin/sh + # Pre-commit hook to run linters and check for newlines + + # Check for files missing newlines + echo "Checking for files missing newlines..." + bundle exec rake check_newlines + if [ $? -ne 0 ]; then + echo "❌ Some files are missing final newlines. Run 'bundle exec rake fix_newlines' to fix." + exit 1 + fi + + # Run RuboCop on staged Ruby files + echo "Running RuboCop on staged files..." + files=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\\.(rb|rake)$') + if [ -n "$files" ]; then + bundle exec rubocop $files + if [ $? -ne 0 ]; then + echo "❌ RuboCop failed. Fix issues or run 'bundle exec rake lint:fix'" + exit 1 + fi + fi + + echo "✅ All checks passed!" +HOOK + +# Create hooks directory if it doesn't exist +FileUtils.mkdir_p(hooks_dir) + +# Write the pre-commit hook +File.write(pre_commit_hook, hook_content) + +# Make it executable +File.chmod(0o755, pre_commit_hook) + +puts '✅ Pre-commit hook installed successfully!' +puts 'The hook will:' +puts ' - Check that all files end with a newline' +puts ' - Run RuboCop on staged Ruby files' +puts '' +puts 'To skip the hook temporarily, use: git commit --no-verify' diff --git a/cypress-on-rails.gemspec b/cypress-on-rails.gemspec index a53b4c42..715ec1ab 100644 --- a/cypress-on-rails.gemspec +++ b/cypress-on-rails.gemspec @@ -22,6 +22,9 @@ Gem::Specification.new do |s| s.add_development_dependency 'factory_bot', '!= 6.4.5' s.add_development_dependency 'vcr' s.add_development_dependency 'gem-release' + s.add_development_dependency 'rubocop' + s.add_development_dependency 'rubocop-rake' + s.add_development_dependency 'rubocop-rspec' s.metadata = { "bug_tracker_uri" => "https://github.com/shakacode/cypress-on-rails/issues", "changelog_uri" => "https://github.com/shakacode/cypress-on-rails/blob/master/CHANGELOG.md", diff --git a/rakelib/lint.rake b/rakelib/lint.rake new file mode 100644 index 00000000..a5a66eb3 --- /dev/null +++ b/rakelib/lint.rake @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +desc 'Run RuboCop' +task :rubocop do + sh 'bundle exec rubocop' +end + +desc 'Run RuboCop with auto-correct' +task 'rubocop:auto_correct' do + sh 'bundle exec rubocop -A' +end + +desc 'Run all linters' +task lint: :rubocop + +desc 'Auto-fix all linting issues' +task 'lint:fix' => 'rubocop:auto_correct' + +desc 'Ensure all files end with newline' +task :check_newlines do + files_without_newline = [] + + Dir.glob('**/*.{rb,rake,yml,yaml,md,gemspec,ru,erb,js,json}').each do |file| + next if file.include?('vendor/') || file.include?('node_modules/') || file.include?('.git/') + next if file.include?('pkg/') || file.include?('tmp/') || file.include?('coverage/') + next unless File.file?(file) + + content = File.read(file) + files_without_newline << file unless content.empty? || content.end_with?("\n") + end + + if files_without_newline.any? + puts 'Files missing final newline:' + files_without_newline.each { |f| puts " #{f}" } + exit 1 + else + puts '✓ All files end with newline' + end +end + +desc 'Fix files missing final newline' +task :fix_newlines do + fixed_files = [] + + Dir.glob('**/*.{rb,rake,yml,yaml,md,gemspec,ru,erb,js,json}').each do |file| + next if file.include?('vendor/') || file.include?('node_modules/') || file.include?('.git/') + next if file.include?('pkg/') || file.include?('tmp/') || file.include?('coverage/') + next unless File.file?(file) + + content = File.read(file) + unless content.empty? || content.end_with?("\n") + File.write(file, content + "\n") + fixed_files << file + end + end + + if fixed_files.any? + puts "Fixed #{fixed_files.length} files:" + fixed_files.each { |f| puts " #{f}" } + else + puts '✓ All files already end with newline' + end +end From c354937bdcb98fa1e3d12ab14a94c0f12d0b81ab Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Wed, 1 Oct 2025 18:37:41 -1000 Subject: [PATCH 2/2] Fix Ruby version consistency and pin RuboCop versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Set minimum Ruby version to 3.0 across all configurations - Updated .rubocop.yml TargetRubyVersion from 2.6 to 3.0 - Updated GitHub Actions workflow to use Ruby 3.0 - Added required_ruby_version >= 3.0.0 to gemspec - Pinned RuboCop versions for consistency: - rubocop ~> 1.81 - rubocop-rake ~> 0.7 - rubocop-rspec ~> 3.7 - Updated to use new plugin syntax instead of require This ensures consistency between CI, local development, and RuboCop configuration. Ruby 3.0 is a reasonable minimum for modern projects. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/workflows/lint.yml | 2 +- .rubocop.yml | 4 ++-- cypress-on-rails.gemspec | 9 ++++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4df4b114..4423c584 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: '3.2' + ruby-version: '3.0' bundler-cache: true - name: Run RuboCop diff --git a/.rubocop.yml b/.rubocop.yml index 8ddb9706..a36087ca 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,9 +1,9 @@ -require: +plugins: - rubocop-rake - rubocop-rspec AllCops: - TargetRubyVersion: 2.6 + TargetRubyVersion: 3.0 NewCops: enable Exclude: - 'vendor/**/*' diff --git a/cypress-on-rails.gemspec b/cypress-on-rails.gemspec index 715ec1ab..a8aaf2e0 100644 --- a/cypress-on-rails.gemspec +++ b/cypress-on-rails.gemspec @@ -22,9 +22,12 @@ Gem::Specification.new do |s| s.add_development_dependency 'factory_bot', '!= 6.4.5' s.add_development_dependency 'vcr' s.add_development_dependency 'gem-release' - s.add_development_dependency 'rubocop' - s.add_development_dependency 'rubocop-rake' - s.add_development_dependency 'rubocop-rspec' + s.add_development_dependency 'rubocop', '~> 1.81' + s.add_development_dependency 'rubocop-rake', '~> 0.7' + s.add_development_dependency 'rubocop-rspec', '~> 3.7' + + s.required_ruby_version = '>= 3.0.0' + s.metadata = { "bug_tracker_uri" => "https://github.com/shakacode/cypress-on-rails/issues", "changelog_uri" => "https://github.com/shakacode/cypress-on-rails/blob/master/CHANGELOG.md",