From 390dd699a84d85511736399ccf9dfa118e1f4bf2 Mon Sep 17 00:00:00 2001 From: Sam Bostock Date: Fri, 18 Aug 2023 17:14:29 -0400 Subject: [PATCH 1/3] Format YAML files --- .github/workflows/ci.yml | 44 ++++++++++++++++++++-------------------- .rubocop.yml | 4 ++-- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 75f277c6..03f252be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: redis: image: redis ports: - - 6379:6379 + - 6379:6379 strategy: matrix: ruby: ["2.7", "3.0", "3.1", "3.2"] @@ -22,7 +22,7 @@ jobs: - ruby: "3.2" gemfile: rails_6_0 - ruby: "3.2" - gemfile: rails_6_1 + gemfile: rails_6_1 include: - ruby: head @@ -30,23 +30,23 @@ jobs: env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile steps: - - name: Check out code - uses: actions/checkout@v3 - - name: Set up Ruby ${{ matrix.ruby }} - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ matrix.ruby }} - bundler-cache: true - - name: Start MySQL and create DB - run: | - sudo systemctl start mysql.service - mysql -uroot -h localhost -proot -e "CREATE DATABASE job_iteration_test;" - - name: Rubocop - run: bundle exec rubocop - - name: Ruby tests - run: bundle exec rake test - env: - REDIS_HOST: localhost - REDIS_PORT: ${{ job.services.redis.ports[6379] }} - - name: Documentation correctly written - run: bundle exec yardoc --no-output --no-save --no-stats --fail-on-warning + - name: Check out code + uses: actions/checkout@v3 + - name: Set up Ruby ${{ matrix.ruby }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - name: Start MySQL and create DB + run: | + sudo systemctl start mysql.service + mysql -uroot -h localhost -proot -e "CREATE DATABASE job_iteration_test;" + - name: Rubocop + run: bundle exec rubocop + - name: Ruby tests + run: bundle exec rake test + env: + REDIS_HOST: localhost + REDIS_PORT: ${{ job.services.redis.ports[6379] }} + - name: Documentation correctly written + run: bundle exec yardoc --no-output --no-save --no-stats --fail-on-warning diff --git a/.rubocop.yml b/.rubocop.yml index 2a6551ab..d1c3a915 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,7 +4,7 @@ inherit_gem: AllCops: TargetRubyVersion: 2.7.6 Exclude: - - 'vendor/bundle/**/*' + - "vendor/bundle/**/*" Lint/SuppressedException: Exclude: - lib/job-iteration.rb @@ -16,5 +16,5 @@ Naming/FileName: - lib/job-iteration.rb Style/MethodCallWithArgsParentheses: Exclude: - - 'gemfiles/*' + - "gemfiles/*" - Gemfile From 135caff736633fbd2422759d69d54079e8caf11a Mon Sep 17 00:00:00 2001 From: Sam Bostock Date: Fri, 18 Aug 2023 17:18:56 -0400 Subject: [PATCH 2/3] Use less granular `TargetRubyVersion` --- .rubocop.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rubocop.yml b/.rubocop.yml index d1c3a915..e398184f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -2,7 +2,7 @@ inherit_gem: rubocop-shopify: rubocop.yml AllCops: - TargetRubyVersion: 2.7.6 + TargetRubyVersion: 2.7 Exclude: - "vendor/bundle/**/*" Lint/SuppressedException: From b5bdb4c5fdf76524ae24bb854435c9481ea383bc Mon Sep 17 00:00:00 2001 From: Sam Bostock Date: Fri, 18 Aug 2023 17:17:16 -0400 Subject: [PATCH 3/3] Extract linting into separate CI job Because we can simply set `TargetRubyVersion` to the version whose syntax we want to support, we can run the Rubocop in a single job, rather than repeating it across all jobs (and matrix combinations). A side benefit is that this separates test failures from linting failures, whereas previously tests would be skipped if the linter failed. --- .github/workflows/ci.yml | 16 +++++++- test/rubocop_config_test.rb | 79 +++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 test/rubocop_config_test.rb diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03f252be..4dc1743a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,12 +41,24 @@ jobs: run: | sudo systemctl start mysql.service mysql -uroot -h localhost -proot -e "CREATE DATABASE job_iteration_test;" - - name: Rubocop - run: bundle exec rubocop - name: Ruby tests run: bundle exec rake test env: REDIS_HOST: localhost REDIS_PORT: ${{ job.services.redis.ports[6379] }} + + lint: + runs-on: ubuntu-latest + name: Lint + steps: + - name: Check out code + uses: actions/checkout@v3 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.2" + bundler-cache: true + - name: Rubocop + run: bundle exec rubocop - name: Documentation correctly written run: bundle exec yardoc --no-output --no-save --no-stats --fail-on-warning diff --git a/test/rubocop_config_test.rb b/test/rubocop_config_test.rb new file mode 100644 index 00000000..299b5535 --- /dev/null +++ b/test/rubocop_config_test.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +require "test_helper" +require "yaml" + +module JobIteration + class RubocopConfigTest < ActiveSupport::TestCase + test "TargetRubyVersion in .rubocop.yml matches oldest Ruby in CI matrix" do + assert_equal( + oldest_ruby_in_matrix, + target_ruby_version, + "TargetRubyVersion in .rubocop.yml does not match oldest Ruby in CI matrix", + ) + end + + test "Linting runs on the newest Ruby in CI matrix" do + assert_equal( + newest_ruby_in_matrix, + ruby_version_for_linting, + "Linting does not run on the newest Ruby in CI matrix", + ) + end + + test "TargetRubyVersion in .rubocop.yml matches required Ruby version in gemspec" do + assert_equal( + required_ruby_version, + target_ruby_version, + "TargetRubyVersion in .rubocop.yml does not match required Ruby version in gemspec", + ) + end + + private + + def oldest_ruby_in_matrix + ruby_versions_in_matrix.min + end + + def newest_ruby_in_matrix + ruby_versions_in_matrix.max + end + + def ruby_versions_in_matrix + YAML + .load_file(".github/workflows/ci.yml") + .dig("jobs", "build", "strategy", "matrix", "ruby") + .tap { |ruby_versions| refute_nil(ruby_versions, "Ruby versions not found in CI matrix") } + .map { |ruby_version| Gem::Version.new(ruby_version) } + end + + def ruby_version_for_linting + YAML + .load_file(".github/workflows/ci.yml") + .dig("jobs", "lint", "steps") + .tap { |steps| refute_nil(steps, "Steps not found in linting CI config") } + .find { |step| step.fetch("uses", "") =~ %r{^ruby/setup-ruby} } + .tap { |step| refute_nil(step, "Ruby setup step not found in linting CI config") } + .then { |step| step.dig("with", "ruby-version") } + .tap { |ruby_version| refute_nil(ruby_version, "Ruby version not found in linting CI config") } + .then { |ruby_version| Gem::Version.new(ruby_version) } + end + + def target_ruby_version + YAML + .load_file(".rubocop.yml") + .dig("AllCops", "TargetRubyVersion") + .tap { |ruby_version| refute_nil(ruby_version, "TargetRubyVersion not found in .rubocop.yml") } + .then { |ruby_version| Gem::Version.new(ruby_version) } + end + + def required_ruby_version + Gem + .loaded_specs + .fetch("job-iteration") + .required_ruby_version + .to_s[/(?<=>= )\d+\.\d+/] + .then { |ruby_version| Gem::Version.new(ruby_version) } + end + end +end