From f2d2c913ae24a4e3f6a2e6adf57cb2ba0bbd33b3 Mon Sep 17 00:00:00 2001 From: Felipe Freitag Vargas Date: Mon, 11 Oct 2021 10:38:52 -0300 Subject: [PATCH] Config gh ci (#63) * Config GH actions * Fix rubocop config * Try to fix simplecov * Try to fix simplecov * Add undercover and rubycritic * Add missing dependency * Update simplecov * Add rspec experiment * Report rspec failures * Install cmake on CircleCI * Install cmake before bundler * Fix rubocop * Remove CC reporter * Update versions * Try another config * Clean up --- .circleci/config.yml | 15 +- .github/workflows/ci.yml | 135 ++++++++++++++++++ .rubocop.yml | 7 +- Gemfile.lock | 134 +++++++++++++---- croods.gemspec | 14 +- lib/croods/resource/authorization.rb | 4 +- lib/croods/resource/filters.rb | 4 +- .../resource/json_schema/links/collection.rb | 4 +- lib/croods/service.rb | 4 +- spec/spec_helper.rb | 26 ++-- spec/support/auth.rb | 2 + todos/.ruby-version | 2 +- todos/config/environments/production.rb | 2 +- todos/config/puma.rb | 8 +- 14 files changed, 281 insertions(+), 80 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.circleci/config.yml b/.circleci/config.yml index 0bb6f65..8400553 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -33,10 +33,10 @@ jobs: - run: name: install dependencies command: | + sudo apt update + sudo apt install postgresql-client cmake gem install bundler -v '2.1.4' bundle install --jobs=4 --retry=3 --path vendor/bundle - sudo apt update - sudo apt install postgresql-client sudo npm install -g mjml@4.3.1 - save_cache: paths: @@ -51,24 +51,17 @@ jobs: # Database setup - run: todos/bin/setup - # Setup coverage report - - run: - name: Setup Code Climate test-reporter - command: | - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter - chmod +x ./cc-test-reporter # run tests! - run: name: Run tests command: | mkdir /tmp/test-results - ./cc-test-reporter before-build bundle exec rspec --format progress \ --format RspecJunitFormatter \ --out /tmp/test-results/rspec.xml \ --format progress - ./cc-test-reporter after-build --coverage-input-type simplecov --exit-code $? - # collect reports + + # collect reports - store_test_results: path: /tmp/test-results - store_artifacts: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..df1c981 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,135 @@ +name: CI + +on: + workflow_dispatch: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + test: + name: Run unit tests + env: + POSTGRES_USER: 'postgres' + POSTGRES_HOST: 'localhost' + RAILS_ENV: test + + runs-on: ubuntu-latest + + services: + redis: + image: redis + ports: ['6379:6379'] + options: --entrypoint redis-server + postgres: + image: postgres + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: 'postgres' + POSTGRES_DB: postgres + POSTGRES_HOST_AUTH_METHOD: 'trust' + ports: + - 5432:5432 + # needed because the postgres container does not provide a healthcheck + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + + - name: Install dependencies + run: | + sudo apt update + sudo apt install postgresql-client cmake + sudo npm install -g mjml@4.6.3 + + - name: Database setup + run: | + todos/bin/setup + + - run: mkdir tmp/ + + - name: Run rspec + run: bundle exec rspec -f j -o tmp/rspec_results.json + + - name: RSpec Report + uses: SonicGarden/rspec-report-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + json-path: tmp/rspec_results.json + if: always() + + - name: Generate Undercover report + run: | + bundle exec undercover -c origin/master > tmp/undercover.txt || \ + echo "Running undercover and ignoring exit status ..." + bundle exec undercover-checkstyle --compare origin/master > tmp/undercover-checkstyle.xml || \ + echo "Running undercover-checkstyle and ignoring exit status ..." + + - name: Archive coverage results + uses: actions/upload-artifact@v2 + with: + name: coverage + path: coverage + retention-days: 10 + + - name: Archive undercover results + uses: actions/upload-artifact@v2 + with: + name: undercover + path: tmp/undercover.txt + retention-days: 10 + + - name: Archive undercover-checkstyle results + uses: actions/upload-artifact@v2 + with: + name: undercover-checkstyle + path: tmp/undercover-checkstyle.xml + retention-days: 10 + + run-linter: + name: Run linter + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - name: Check out code + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - uses: ruby/setup-ruby@v1 + + - name: rubocop + uses: reviewdog/action-rubocop@v2 + with: + rubocop_version: gemfile + rubocop_extensions: rubocop-rails:gemfile rubocop-rspec:gemfile + github_token: ${{ secrets.github_token }} + + report-diff-coverage: + name: Report diff coverage + needs: test + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: actions/download-artifact@v2 + with: + name: undercover-checkstyle + + - uses: reviewdog/action-setup@v1 + + - name: Comment on PR + env: + REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + cat undercover-checkstyle.xml | \ + reviewdog -reporter=github-check -name="Diff coverage" -f=checkstyle diff --git a/.rubocop.yml b/.rubocop.yml index 71d9a09..89a2d93 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,7 @@ require: rubocop-rspec AllCops: + NewCops: disable DisplayCopNames: true Include: - '**/*.rb' @@ -18,8 +19,6 @@ AllCops: - 'todos/bin/*' - 'todos/node_modules/**/*' - 'spec/rails_helper.rb' -Rails: - Enabled: true Documentation: Enabled: false Metrics/BlockLength: @@ -38,3 +37,7 @@ Style/HashTransformKeys: Enabled: true Style/HashTransformValues: Enabled: true +RSpec/MultipleMemoizedHelpers: + Enabled: false +RSpec/FilePath: + Enabled: false diff --git a/Gemfile.lock b/Gemfile.lock index a5e4d9d..fe77134 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - croods (0.3.4) + croods (0.3.5) api-pagination (= 4.8.2) committee (= 3.3.0) devise_token_auth (= 1.1.3) @@ -57,19 +57,29 @@ GEM i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) + addressable (2.8.0) + public_suffix (>= 2.0.2, < 5.0) api-pagination (4.8.2) arel (9.0.0) - ast (2.4.1) + ast (2.4.2) awesome_print (1.8.0) + axiom-types (0.1.1) + descendants_tracker (~> 0.0.4) + ice_nine (~> 0.11.0) + thread_safe (~> 0.3, >= 0.3.1) bcrypt (3.1.16) builder (3.2.4) byebug (11.1.3) + coercible (1.0.0) + descendants_tracker (~> 0.0.1) committee (3.3.0) json_schema (~> 0.14, >= 0.14.3) openapi_parser (>= 0.6.1) rack (>= 1.5) concurrent-ruby (1.1.8) crass (1.0.6) + descendants_tracker (0.0.4) + thread_safe (~> 0.3, >= 0.3.1) devise (4.8.0) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -81,20 +91,32 @@ GEM devise (> 3.5.2, < 5) rails (>= 4.2.0, < 6.1) diff-lcs (1.3) - docile (1.3.2) + docile (1.4.0) dotenv (2.7.6) dotenv-rails (2.7.6) dotenv (= 2.7.6) railties (>= 3.2) + equalizer (0.0.11) erubi (1.10.0) + erubis (2.7.0) + flay (2.12.1) + erubis (~> 2.7.0) + path_expander (~> 1.0) + ruby_parser (~> 3.0) + sexp_processor (~> 4.0) + flog (4.6.4) + path_expander (~> 1.0) + ruby_parser (~> 3.1, > 3.1.0) + sexp_processor (~> 4.8) gem-release (2.1.1) - globalid (0.4.2) - activesupport (>= 4.2.0) + globalid (0.5.2) + activesupport (>= 5.0) i18n (1.8.10) concurrent-ruby (~> 1.0) + ice_nine (0.11.2) + imagen (0.1.8) + parser (>= 2.5, != 2.5.1.1) its-it (1.3.0) - jaro_winkler (1.5.4) - json (2.3.0) json_schema (0.21.0) kaminari (1.2.1) activesupport (>= 4.1.0) @@ -109,31 +131,36 @@ GEM kaminari-core (= 1.2.1) kaminari-core (1.2.1) key_struct (0.4.2) + kwalify (0.7.2) + launchy (2.5.0) + addressable (~> 2.7) loofah (2.9.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) - marcel (1.0.1) + marcel (1.0.2) method_source (1.0.0) - mini_mime (1.1.0) + mini_mime (1.1.1) mini_portile2 (2.5.1) minitest (5.14.4) modware (0.1.3) key_struct (~> 0.4) - nio4r (2.5.7) + nio4r (2.5.8) nokogiri (1.11.4) mini_portile2 (~> 2.5.0) racc (~> 1.4) - openapi_parser (0.13.0) + openapi_parser (0.14.1) orm_adapter (0.5.0) - parallel (1.19.1) - parser (2.7.1.3) - ast (~> 2.4.0) + parallel (1.21.0) + parser (3.0.2.0) + ast (~> 2.4.1) + path_expander (1.1.0) pg (1.2.3) pg_search (2.3.4) activerecord (>= 5.2) activesupport (>= 5.2) + public_suffix (4.0.6) pundit (2.1.0) activesupport (>= 3.0.0) racc (1.5.2) @@ -168,6 +195,11 @@ GEM thor (>= 0.19.0, < 2.0) rainbow (3.0.0) rake (13.0.3) + reek (6.0.6) + kwalify (~> 0.7.0) + parser (~> 3.0.0) + rainbow (>= 2.0, < 4.0) + regexp_parser (2.1.1) responders (3.0.1) actionpack (>= 5.0) railties (>= 5.0) @@ -191,17 +223,38 @@ GEM rspec-support (3.9.3) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.80.1) - jaro_winkler (~> 1.5.1) + rubocop (1.21.0) parallel (~> 1.10) - parser (>= 2.7.0.1) + parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) rexml + rubocop-ast (>= 1.9.1, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 1.7) - rubocop-rspec (1.38.1) - rubocop (>= 0.68.1) - ruby-progressbar (1.10.1) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.11.0) + parser (>= 3.0.1.1) + rubocop-rails (2.12.2) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.7.0, < 2.0) + rubocop-rspec (2.5.0) + rubocop (~> 1.19) + ruby-progressbar (1.11.0) + ruby_parser (3.17.0) + sexp_processor (~> 4.15, >= 4.15.1) + rubycritic (4.6.1) + flay (~> 2.8) + flog (~> 4.4) + launchy (>= 2.0.0) + parser (>= 2.6.0) + rainbow (~> 3.0) + reek (~> 6.0, < 7.0) + ruby_parser (~> 3.8) + simplecov (>= 0.17.0) + tty-which (~> 0.4.0) + virtus (~> 1.0) + rugged (1.1.1) schema_associations (1.2.7) schema_plus_foreign_keys (~> 0.1) schema_auto_foreign_keys (0.1.3) @@ -237,13 +290,16 @@ GEM activerecord (~> 5.0) schema_plus_columns valuable + sexp_processor (4.15.3) shoulda-matchers (4.3.0) activesupport (>= 4.2.0) - simplecov (0.17.1) + simplecov (0.21.2) docile (~> 1.1) - json (>= 1.8, < 3) - simplecov-html (~> 0.10.0) - simplecov-html (0.10.2) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov-lcov (0.8.0) + simplecov_json_formatter (0.1.3) sprockets (4.0.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -254,13 +310,26 @@ GEM thor (1.1.0) thread_safe (0.3.6) timecop (0.9.1) + tty-which (0.4.2) tzinfo (1.2.9) thread_safe (~> 0.1) - unicode-display_width (1.6.1) + undercover (0.4.3) + imagen (>= 0.1.8) + rainbow (>= 2.1, < 4.0) + rugged (>= 0.27, < 1.2) + undercover-checkstyle (0.3.0) + rexml + undercover (>= 0.3.4) + unicode-display_width (2.1.0) valuable (0.9.14) + virtus (1.0.5) + axiom-types (~> 0.1) + coercible (~> 1.0) + descendants_tracker (~> 0.0, >= 0.0.3) + equalizer (~> 0.0, >= 0.0.9) warden (1.2.9) rack (>= 2.0.9) - websocket-driver (0.7.3) + websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) @@ -277,11 +346,16 @@ DEPENDENCIES rack-cors (= 1.1.1) rspec-rails (~> 4.0.1) rspec_junit_formatter (~> 0.4.1) - rubocop (= 0.80.1) - rubocop-rspec (= 1.38.1) + rubocop (~> 1.21.0) + rubocop-rails + rubocop-rspec (~> 2.5.0) + rubycritic shoulda-matchers - simplecov (~> 0.17.0) + simplecov (~> 0.21.0) + simplecov-lcov timecop (= 0.9.1) + undercover + undercover-checkstyle BUNDLED WITH 2.1.4 diff --git a/croods.gemspec b/croods.gemspec index 0f3ee2a..0f8011d 100644 --- a/croods.gemspec +++ b/croods.gemspec @@ -16,6 +16,7 @@ Gem::Specification.new do |spec| spec.summary = 'A framework for creating CRUDs in Rails APIs' spec.description = 'A framework for creating CRUDs in Rails APIs' spec.license = 'MIT' + spec.required_ruby_version = '>= 2.6.5' spec.files = Dir[ '{app,config,db,lib}/**/*', 'MIT-LICENSE', 'Rakefile', 'README.md' @@ -35,11 +36,16 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'gem-release' spec.add_development_dependency 'pg' spec.add_development_dependency 'rack-cors', '1.1.1' - spec.add_development_dependency 'rspec-rails', '~> 4.0.1' spec.add_development_dependency 'rspec_junit_formatter', '~> 0.4.1' - spec.add_development_dependency 'rubocop', '0.80.1' - spec.add_development_dependency 'rubocop-rspec', '1.38.1' - spec.add_development_dependency 'simplecov', '~> 0.17.0' + spec.add_development_dependency 'rspec-rails', '~> 4.0.1' + spec.add_development_dependency 'rubocop', '~> 1.21.0' + spec.add_development_dependency 'rubocop-rails' + spec.add_development_dependency 'rubocop-rspec', '~> 2.5.0' + spec.add_development_dependency 'rubycritic' + spec.add_development_dependency 'simplecov', '~> 0.21.0' + spec.add_development_dependency 'simplecov-lcov' spec.add_development_dependency 'timecop', '0.9.1' + spec.add_development_dependency 'undercover' + spec.add_development_dependency 'undercover-checkstyle' end # rubocop:enable Metrics/BlockLength diff --git a/lib/croods/resource/authorization.rb b/lib/croods/resource/authorization.rb index c0bed51..a11b3d2 100644 --- a/lib/croods/resource/authorization.rb +++ b/lib/croods/resource/authorization.rb @@ -6,7 +6,7 @@ module Authorization def authorize(*roles, on: nil) return if roles.empty? - on = [on] if on&.is_a?(Symbol) + on = [on] if on.is_a?(Symbol) authorization_roles << { roles: roles, on: on } end @@ -31,7 +31,7 @@ def apply_authorization_roles! def public_actions(*names) return unless names - names = [names] if names&.is_a?(Symbol) + names = [names] if names.is_a?(Symbol) extend_controller do skip_before_action :authenticate_user!, only: names diff --git a/lib/croods/resource/filters.rb b/lib/croods/resource/filters.rb index 234cea8..b693988 100644 --- a/lib/croods/resource/filters.rb +++ b/lib/croods/resource/filters.rb @@ -15,9 +15,7 @@ def filters def apply_filters(scope, params) filters.each do |attribute| - unless model.has_attribute?(attribute.name) - attribute.name = "#{attribute.name}_id" - end + attribute.name = "#{attribute.name}_id" unless model.has_attribute?(attribute.name) value = params[attribute.name] next unless value diff --git a/lib/croods/resource/json_schema/links/collection.rb b/lib/croods/resource/json_schema/links/collection.rb index 4470517..1c401aa 100644 --- a/lib/croods/resource/json_schema/links/collection.rb +++ b/lib/croods/resource/json_schema/links/collection.rb @@ -23,9 +23,7 @@ def filters(resource) filters = {} resource.filters.each do |attribute| - unless resource.model.has_attribute?(attribute.name) - attribute.name = "#{attribute.name}_id" - end + attribute.name = "#{attribute.name}_id" unless resource.model.has_attribute?(attribute.name) filters[attribute.name] = definition(attribute) end diff --git a/lib/croods/service.rb b/lib/croods/service.rb index 8679f01..89e8c71 100644 --- a/lib/croods/service.rb +++ b/lib/croods/service.rb @@ -16,9 +16,7 @@ def self.execute(member_or_collection, params, current_user) end def initialize(member_or_collection, params, current_user) - if self.class.about - public_send("#{self.class.about}=", member_or_collection) - end + public_send("#{self.class.about}=", member_or_collection) if self.class.about self.member_or_collection = member_or_collection self.params = params diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 23341b2..d55f58d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,27 +1,21 @@ # frozen_string_literal: true require 'simplecov' +require 'simplecov-lcov' + +SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true +SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter SimpleCov.start 'rails' do add_filter ['.gems', 'lib/generators/'] + add_filter(%r{^/spec/}) + + # Report branch coverage to trigger branch-level undercover warnings + enable_coverage(:branch) end -# This file was generated by the `rails generate rspec:install` command. -# Conventionally, all -# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. -# The generated `.rspec` file contains `--require spec_helper` which will cause -# this file to always be loaded, without a need to explicitly require it in any -# files. -# -# Given that it is always loaded, you are encouraged to keep this file as -# light-weight as possible. Requiring heavyweight dependencies from this file -# will add to the boot time of your test suite on EVERY test run, even for an -# individual file that may not need all of that loaded. Instead, consider making -# a separate helper file that requires the additional dependencies and performs -# the additional setup, and require it from the spec files that actually need -# it. -# -# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +require 'undercover' + RSpec.configure do |config| # rspec-expectations config goes here. You can use an alternate # assertion/expectation library such as wrong or the stdlib/minitest diff --git a/spec/support/auth.rb b/spec/support/auth.rb index 8e83bca..ccde93e 100644 --- a/spec/support/auth.rb +++ b/spec/support/auth.rb @@ -7,6 +7,7 @@ ) end + # rubocop:disable RSpec/LetSetup let!(:current_user) do current_organization.users.create!( email: 'current.user@email.com', @@ -16,6 +17,7 @@ supervisor: true ) end + # rubocop:enable RSpec/LetSetup end RSpec.configure do |config| diff --git a/todos/.ruby-version b/todos/.ruby-version index 24ba9a3..57cf282 100644 --- a/todos/.ruby-version +++ b/todos/.ruby-version @@ -1 +1 @@ -2.7.0 +2.6.5 diff --git a/todos/config/environments/production.rb b/todos/config/environments/production.rb index a03c006..98eff16 100644 --- a/todos/config/environments/production.rb +++ b/todos/config/environments/production.rb @@ -68,7 +68,7 @@ # .new(Syslog::Logger.new 'app-name') if ENV['RAILS_LOG_TO_STDOUT'].present? - logger = ActiveSupport::Logger.new(STDOUT) + logger = ActiveSupport::Logger.new($stdout) logger.formatter = config.log_formatter config.logger = ActiveSupport::TaggedLogging.new(logger) end diff --git a/todos/config/puma.rb b/todos/config/puma.rb index 9900408..4cae04a 100644 --- a/todos/config/puma.rb +++ b/todos/config/puma.rb @@ -6,21 +6,21 @@ # the maximum value specified for Puma. Default is set to 5 threads for minimum # and maximum; this matches the default thread size of Active Record. # -max_threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 } +max_threads_count = ENV.fetch('RAILS_MAX_THREADS', 5) min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count } threads min_threads_count, max_threads_count # Specifies the `port` that Puma will listen on to receive requests; # default is 3000. # -port ENV.fetch('PORT') { 3000 } +port ENV.fetch('PORT', 3000) # Specifies the `environment` that Puma will run in. # -environment ENV.fetch('RAILS_ENV') { 'development' } +environment ENV.fetch('RAILS_ENV', 'development') # Specifies the `pidfile` that Puma will use. -pidfile ENV.fetch('PIDFILE') { 'tmp/pids/server.pid' } +pidfile ENV.fetch('PIDFILE', 'tmp/pids/server.pid') # Specifies the number of `workers` to boot in clustered mode. # Workers are forked web server processes. If using threads and workers together