diff --git a/.dockerignore b/.dockerignore index b512c09d..454ee670 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +1,2 @@ -node_modules \ No newline at end of file +node_modules +./docker \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 881e30e2..a39574e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,33 +33,28 @@ jobs: --health-timeout 5s --health-retries 5 steps: - - uses: actions/checkout@v2 - - name: Set up Ruby (uses .ruby-version) - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true # runs 'bundle install' and caches installed gems automatically - - name: Install postgres client - run: sudo apt-get install libpq-dev - - name: Cache chromedriver - uses: actions/cache@v2 - with: - path: "/usr/local/share/chromedriver" - key: chromedriver-${{ runner.os }}-${{ hashFiles('/usr/local/share/chromedriver') }} - - name: Cache clode climate reporter - uses: actions/cache@v2 - with: - path: "cc-test-reporter" - key: cc-${{ runner.os }}-${{ hashFiles('./cc-test-reporter') }} - - name: script/cibuild - run: | - script/cibuild - env: - DB_PASSWORD: ${{ env.POSTGRES_PASSWORD }} - DB_NAME: ${{ env.POSTGRES_DB }} - DB_USER: ${{ env.POSTGRES_USER }} - REDIS_URL: redis://localhost:6379/0 - DATA_TEST_S3_BUCKET: ${{ secrets.DATA_TEST_S3_BUCKET }} - DATA_TEST_S3_REGION: ${{ secrets.DATA_TEST_S3_REGION }} - FETCHER_S3_ACCESS: ${{ secrets.FETCHER_S3_ACCESS }} - FETCHER_S3_KEY: ${{ secrets.FETCHER_S3_KEY }} - CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} + - uses: actions/checkout@v2 + - name: Set up Ruby (uses .ruby-version) + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + - name: Install postgres client + run: sudo apt-get install libpq-dev + - name: Cache clode climate reporter + uses: actions/cache@v2 + with: + path: "cc-test-reporter" + key: cc-${{ runner.os }}-${{ hashFiles('./cc-test-reporter') }} + - name: script/cibuild + run: | + script/cibuild + env: + DB_PASSWORD: ${{ env.POSTGRES_PASSWORD }} + DB_NAME: ${{ env.POSTGRES_DB }} + DB_USER: ${{ env.POSTGRES_USER }} + REDIS_URL: redis://localhost:6379/0 + DATA_TEST_S3_BUCKET: ${{ secrets.DATA_TEST_S3_BUCKET }} + DATA_TEST_S3_REGION: ${{ secrets.DATA_TEST_S3_REGION }} + FETCHER_S3_ACCESS: ${{ secrets.FETCHER_S3_ACCESS }} + FETCHER_S3_KEY: ${{ secrets.FETCHER_S3_KEY }} + CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} diff --git a/.gitignore b/.gitignore index 64ef54eb..7d248786 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,7 @@ dump.rdb coverage spec/artefacts/* config/data_test.json -.env* +./.env* # I, pj, still vendor my ruby gems in the directory of the # application, this stops me from committing them here. diff --git a/.ruby-version b/.ruby-version index ecd7ee50..944880fa 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.5.8 +3.2.0 diff --git a/Dockerfile.build b/Dockerfile.build index 4cef3c7d..7b92bc48 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,4 +1,4 @@ -FROM ruby:2.5.8-alpine AS build-env +FROM ruby:3.2.0-alpine AS build-env ARG RAILS_ROOT=/app ARG BUILD_PACKAGES="build-base curl-dev git" @@ -19,23 +19,23 @@ RUN apk update \ COPY Gemfile* ./ # install rubygem COPY Gemfile Gemfile.lock $RAILS_ROOT/ -RUN gem update --system 3.2.3 && gem install bundler -i 2.2.3 && bundle config set --local without 'development test' && bundle config set --local path 'vendor/bundle' +RUN gem update --system 3.4.1 && gem install bundler -i 2.4.4 && bundle config set --local without 'development test' && bundle config set --local path 'vendor/bundle' RUN bundle install \ - && rm -rf vendor/bundle/ruby/2.5.0/cache/*.gem \ - && find vendor/bundle/ruby/2.5.0/gems/ -name "*.c" -delete \ - && find vendor/bundle/ruby/2.5.0/gems/ -name "*.o" -delete + && rm -rf vendor/bundle/ruby/3.2.0/cache/*.gem \ + && find vendor/bundle/ruby/3.2.0/gems/ -name "*.c" -delete \ + && find vendor/bundle/ruby/3.2.0/gems/ -name "*.o" -delete COPY . . RUN DATABASE_URL=nulldb:://null SECRET_KEY_BASE=1 RAILS_ENV=production bundle exec rake assets:precompile --trace # Remove folders not needed in resulting image -RUN rm -rf node_modules tmp/cache app/assets vendor/assets spec +RUN rm -rf node_modules tmp/cache vendor/assets spec -FROM ruby:2.5.8-alpine +FROM ruby:3.2.0-alpine ARG RAILS_ROOT=/app ARG PACKAGES="tzdata postgresql-client nodejs bash curl-dev" ENV RAILS_ENV=production ENV BUNDLE_APP_CONFIG="$RAILS_ROOT/.bundle" -RUN gem update --system 3.2.3 && gem install bundler -i 2.2.3 +RUN gem update --system 3.4.1 && gem install bundler -i 2.4.4 WORKDIR $RAILS_ROOT # install packages RUN apk update \ diff --git a/Gemfile b/Gemfile index 9aaaa365..6e53a774 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -ruby "2.5.8" +ruby "3.2.0" git_source(:github) do |repo_name| repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") @@ -11,30 +11,30 @@ end ## Infrastructure +gem "activerecord-nulldb-adapter" gem "dhis2", github: "BLSQ/dhis2", branch: "legacy-v2" -gem "paper_trail", "~> 10.1.0" -gem "paper_trail-association_tracking", "~> 1.0.0" -gem "pg", "~> 0.18" +gem "paper_trail", "~> 13.0.0" +gem "paper_trail-association_tracking", "~> 2.2.1" +gem "pg", "~> 1.4.5" gem "puma", "~> 4.3" gem "rack", ">= 2.0.6" -gem "rails", "~> 5.2", "< 5.3" -gem "activerecord-nulldb-adapter" -gem "rails_admin", "~> 1.4.2" +gem "rails", "~> 7.0.4.1" +gem "rails_admin", "~> 3.1.1" gem "sidekiq", "< 6" gem "sidekiq-throttled", "~> 0.9.0" ## Tooling -gem "bootsnap", "~> 1.3.2" +gem "bootsnap", "~> 1.15.0" gem "figaro" -gem "lograge", "~> 0.10.0" +gem "lograge", "~> 0.12.0" gem "sentry-raven", "~> 2.7.4" # Feature flipper is the act of enabling/disabling features in your app... # [flipper](https://github.com/jnunemaker/flipper) -gem "flipper", "~> 0.16.1" -gem "flipper-active_record", "~> 0.16.1" -gem "flipper-ui", "~> 0.16.1" +gem "flipper", "~> 0.26.0" +gem "flipper-active_record", "~> 0.26.0" +gem "flipper-ui", "~> 0.26.0" ## Frontend and asset related @@ -45,17 +45,16 @@ gem "coffee-rails", "~> 4.2" gem "jquery-rails", "~> 4.3.3" gem "jquery-ui-rails", "~> 5.0.5" gem "rails-jquery-autocomplete" -gem "sassc-rails", "~> 2.0.0" +gem "sassc-rails", "~> 2.1.2" gem "simple_form" -gem "sprockets", "~> 3.7.2" +gem "sprockets", "~> 4.2.0" gem "turbolinks", "~> 5" gem "uglifier", ">= 1.3.0" - ## Authentication # Flexible authentication solution for Rails with Warden # [devise](https://github.com/plataformatec/devise) -gem "devise", "~> 4.7.1" +gem "devise", "~> 4.8.1" # Log in as another user in Rails # [pretender](https://github.com/ankane/pretender) @@ -86,7 +85,7 @@ else # We're using both of them against the latest master. We should set # them to versions when they become more stable gem "hesabu", github: "BLSQ/hesabu" - gem "orbf-rules_engine", github: "BLSQ/orbf-rules_engine", branch: "master" + gem "orbf-rules_engine", github: "BLSQ/orbf-rules_engine", branch: "ruby-3.2.0-test" # TODO: back to master end # Like a modern code version of the mythical beast with 100 serpent hea... # [typhoeus](https://github.com/typhoeus/typhoeus) @@ -96,28 +95,26 @@ group :development, :test do gem "byebug", platform: :mri # Use pry instead of irb: http://pryrepl.org - gem "pry", "~> 0.12.2" + gem "pry", "~> 0.14.2" gem "pry-rails", "~> 0.3.9" gem "database_cleaner" - gem "factory_bot_rails", "~> 4.11.1" + gem "factory_bot_rails", "~> 6.2.0" gem "faker" gem "immigrant" gem "rails-controller-testing" gem "rest-client-logger", github: "uswitch/rest-client-logger" gem "rspec-its" - gem "rspec-rails", "~> 3.0" + gem "rspec-rails", "~> 6.0.1" gem "ruby-prof" gem "shoulda-matchers", require: false - gem "capybara" gem "json-diff", "~> 0.4.1" gem "rubyzip", "~> 1.3.0" - gem "selenium-webdriver" end group :development do - gem "annotate", "~> 2.7.4" + gem "annotate", "~> 3.2.0" gem "flamegraph" gem "listen", "~> 3.0.5" gem "memory_profiler" @@ -127,7 +124,7 @@ group :development do gem "pronto-simplecov", require: false gem "rack-mini-profiler" gem "rubocop", require: false - gem 'rubocop-rails', require: false + gem "rubocop-rails", require: false gem "spring" gem "spring-watcher-listen", "~> 2.0.0" gem "stackprof" @@ -140,9 +137,5 @@ group :test do gem "webmock" end -group :production do - gem "heroku-deflater" -end - # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem "tzinfo-data", platforms: %i[mingw mswin x64_mingw jruby] diff --git a/Gemfile.lock b/Gemfile.lock index cfa99cae..ea507608 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -14,13 +14,13 @@ GIT GIT remote: https://github.com/BLSQ/orbf-rules_engine.git - revision: 89c59c18608029348a0d2643e1d32c162656fe5d - branch: master + revision: c4676c756e1c411483dbd19285c825fe276e216e + branch: ruby-3.2.0-test specs: orbf-rules_engine (0.1.0) activesupport colorize - dentaku (= 3.1.0) + dentaku (= 3.5.1) descriptive_statistics dhis2 (= 2.3.8) hesabu @@ -36,96 +36,114 @@ GIT GEM remote: https://rubygems.org/ specs: - actioncable (5.2.6.2) - actionpack (= 5.2.6.2) + actioncable (7.0.4.1) + actionpack (= 7.0.4.1) + activesupport (= 7.0.4.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.6.2) - actionpack (= 5.2.6.2) - actionview (= 5.2.6.2) - activejob (= 5.2.6.2) + actionmailbox (7.0.4.1) + actionpack (= 7.0.4.1) + activejob (= 7.0.4.1) + activerecord (= 7.0.4.1) + activestorage (= 7.0.4.1) + activesupport (= 7.0.4.1) + mail (>= 2.7.1) + net-imap + net-pop + net-smtp + actionmailer (7.0.4.1) + actionpack (= 7.0.4.1) + actionview (= 7.0.4.1) + activejob (= 7.0.4.1) + activesupport (= 7.0.4.1) mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp rails-dom-testing (~> 2.0) - actionpack (5.2.6.2) - actionview (= 5.2.6.2) - activesupport (= 5.2.6.2) - rack (~> 2.0, >= 2.0.8) + actionpack (7.0.4.1) + actionview (= 7.0.4.1) + activesupport (= 7.0.4.1) + rack (~> 2.0, >= 2.2.0) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.6.2) - activesupport (= 5.2.6.2) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (7.0.4.1) + actionpack (= 7.0.4.1) + activerecord (= 7.0.4.1) + activestorage (= 7.0.4.1) + activesupport (= 7.0.4.1) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (7.0.4.1) + activesupport (= 7.0.4.1) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.6.2) - activesupport (= 5.2.6.2) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (7.0.4.1) + activesupport (= 7.0.4.1) globalid (>= 0.3.6) - activemodel (5.2.6.2) - activesupport (= 5.2.6.2) - activerecord (5.2.6.2) - activemodel (= 5.2.6.2) - activesupport (= 5.2.6.2) - arel (>= 9.0) - activerecord-nulldb-adapter (0.7.0) - activerecord (>= 5.2.0, < 6.3) - activestorage (5.2.6.2) - actionpack (= 5.2.6.2) - activerecord (= 5.2.6.2) - marcel (~> 1.0.0) - activesupport (5.2.6.2) + activemodel (7.0.4.1) + activesupport (= 7.0.4.1) + activemodel-serializers-xml (1.0.2) + activemodel (> 5.x) + activesupport (> 5.x) + builder (~> 3.1) + activerecord (7.0.4.1) + activemodel (= 7.0.4.1) + activesupport (= 7.0.4.1) + activerecord-nulldb-adapter (0.8.0) + activerecord (>= 5.2.0, < 7.1) + activestorage (7.0.4.1) + actionpack (= 7.0.4.1) + activejob (= 7.0.4.1) + activerecord (= 7.0.4.1) + activesupport (= 7.0.4.1) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (7.0.4.1) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) - annotate (2.7.4) - activerecord (>= 3.2, < 6.0) - rake (>= 10.4, < 13.0) - arel (9.0.0) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) + annotate (3.2.0) + activerecord (>= 3.2, < 8.0) + rake (>= 10.4, < 14.0) ast (2.4.2) - autoprefixer-rails (9.4.9) - execjs - aws-eventstream (1.1.0) - aws-partitions (1.329.0) - aws-sdk-core (3.99.2) + autoprefixer-rails (10.4.7.0) + execjs (~> 2) + aws-eventstream (1.2.0) + aws-partitions (1.693.0) + aws-sdk-core (3.168.4) aws-eventstream (~> 1, >= 1.0.2) - aws-partitions (~> 1, >= 1.239.0) - aws-sigv4 (~> 1.1) - jmespath (~> 1.0) - aws-sdk-kms (1.34.1) - aws-sdk-core (~> 3, >= 3.99.0) + aws-partitions (~> 1, >= 1.651.0) + aws-sigv4 (~> 1.5) + jmespath (~> 1, >= 1.6.1) + aws-sdk-kms (1.61.0) + aws-sdk-core (~> 3, >= 3.165.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.68.1) - aws-sdk-core (~> 3, >= 3.99.0) + aws-sdk-s3 (1.117.2) + aws-sdk-core (~> 3, >= 3.165.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.1) - aws-sigv4 (1.1.4) - aws-eventstream (~> 1.0, >= 1.0.2) - bcrypt (3.1.13) - bindex (0.5.0) - bootsnap (1.3.2) - msgpack (~> 1.0) - bootstrap-datepicker-rails (1.8.0.1) + aws-sigv4 (~> 1.4) + aws-sigv4 (1.5.2) + aws-eventstream (~> 1, >= 1.0.2) + bcrypt (3.1.18) + bindex (0.8.1) + bootsnap (1.15.0) + msgpack (~> 1.2) + bootstrap-datepicker-rails (1.9.0.1) railties (>= 3.0) bootstrap-sass (3.4.1) autoprefixer-rails (>= 5.2.1) sassc (>= 2.0.0) builder (3.2.4) - byebug (10.0.2) - capybara (3.33.0) - addressable - mini_mime (>= 0.1.3) - nokogiri (~> 1.8) - rack (>= 1.6.0) - rack-test (>= 0.6.3) - regexp_parser (~> 1.5) - xpath (~> 3.2) - childprocess (3.0.0) - cocoon (1.2.12) - coderay (1.1.2) + byebug (11.1.3) + cocoon (1.2.15) + coderay (1.1.3) coffee-rails (4.2.2) coffee-script (>= 2.2.0) railties (>= 4.0.0) @@ -134,88 +152,89 @@ GEM execjs coffee-script-source (1.12.2) colorize (0.8.1) - concurrent-ruby (1.1.10) - connection_pool (2.2.5) - crack (0.4.3) - safe_yaml (~> 1.0.0) + concurrent-ruby (1.2.0) + connection_pool (2.3.0) + crack (0.4.5) + rexml crass (1.0.6) - database_cleaner (1.7.0) - deep_cloneable (2.3.2) - activerecord (>= 3.1.0, < 6) - dentaku (3.1.0) + database_cleaner (2.0.1) + database_cleaner-active_record (~> 2.0.0) + database_cleaner-active_record (2.0.1) + activerecord (>= 5.a) + database_cleaner-core (~> 2.0.0) + database_cleaner-core (2.0.1) + date (3.3.3) + deep_cloneable (3.2.0) + activerecord (>= 3.1.0, < 8) + dentaku (3.5.1) + concurrent-ruby descriptive_statistics (2.5.1) - devise (4.7.1) + devise (4.8.1) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) - diff-lcs (1.3) + diff-lcs (1.5.0) differ (0.1.2) - docile (1.1.5) + docile (1.4.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - erubi (1.10.0) - erubis (2.7.0) - ethon (0.12.0) - ffi (>= 1.3.0) - execjs (2.7.0) - factory_bot (4.11.1) - activesupport (>= 3.0.0) - factory_bot_rails (4.11.1) - factory_bot (~> 4.11.1) - railties (>= 3.0.0) - faker (1.9.1) - i18n (>= 0.7) - faraday (0.17.4) + erubi (1.12.0) + ethon (0.16.0) + ffi (>= 1.15.0) + execjs (2.8.1) + factory_bot (6.2.1) + activesupport (>= 5.0.0) + factory_bot_rails (6.2.0) + factory_bot (~> 6.2.0) + railties (>= 5.0.0) + faker (3.1.0) + i18n (>= 1.8.11, < 2) + faraday (0.17.6) multipart-post (>= 1.2, < 3) fast_jsonapi (1.5) activesupport (>= 4.2) - ffi (1.9.25) - figaro (1.1.1) - thor (~> 0.14) + ffi (1.15.5) + figaro (1.2.0) + thor (>= 0.14.0, < 2) flamegraph (0.9.5) - flay (2.12.0) - erubis (~> 2.7.0) + flay (2.13.0) + erubi (~> 1.10) path_expander (~> 1.0) ruby_parser (~> 3.0) sexp_processor (~> 4.0) - flipper (0.16.1) - flipper-active_record (0.16.1) - activerecord (>= 3.2, < 6) - flipper (~> 0.16.1) - flipper-ui (0.16.1) - erubis (~> 2.7.0) - flipper (~> 0.16.1) + flipper (0.26.0) + concurrent-ruby (< 2) + flipper-active_record (0.26.0) + activerecord (>= 4.2, < 8) + flipper (~> 0.26.0) + flipper-ui (0.26.0) + erubi (>= 1.0.0, < 2.0.0) + flipper (~> 0.26.0) rack (>= 1.4, < 3) - rack-protection (>= 1.5.3, < 2.1.0) - font-awesome-rails (4.7.0.7) - railties (>= 3.2, < 7) - gitlab (4.18.0) - httparty (~> 0.18) + rack-protection (>= 1.5.3, <= 4.0.0) + sanitize (< 7) + gitlab (4.19.0) + httparty (~> 0.20) terminal-table (>= 1.5.1) - globalid (1.0.0) + globalid (1.0.1) activesupport (>= 5.0) - haml (5.2.1) - temple (>= 0.8.0) - tilt - hashdiff (0.3.7) - heroku-deflater (0.6.3) - rack (>= 1.4.5) + hashdiff (1.0.1) http-accept (1.7.0) http-cookie (1.0.5) domain_name (~> 0.5) - httparty (0.20.0) - mime-types (~> 3.0) + httparty (0.21.0) + mini_mime (>= 1.0.0) multi_xml (>= 0.5.2) i18n (1.12.0) concurrent-ruby (~> 1.0) immigrant (0.3.6) activerecord (>= 3.0) - jbuilder (2.8.0) - activesupport (>= 4.2.0) - multi_json (>= 1.2) - jmespath (1.4.0) + jbuilder (2.11.5) + actionview (>= 5.0.0) + activesupport (>= 5.0.0) + jmespath (1.6.2) jquery-rails (4.3.5) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) @@ -224,157 +243,158 @@ GEM railties (>= 3.2.16) json (2.3.0) json-diff (0.4.1) - kaminari (1.2.1) + kaminari (1.2.2) activesupport (>= 4.1.0) - kaminari-actionview (= 1.2.1) - kaminari-activerecord (= 1.2.1) - kaminari-core (= 1.2.1) - kaminari-actionview (1.2.1) + kaminari-actionview (= 1.2.2) + kaminari-activerecord (= 1.2.2) + kaminari-core (= 1.2.2) + kaminari-actionview (1.2.2) actionview - kaminari-core (= 1.2.1) - kaminari-activerecord (1.2.1) + kaminari-core (= 1.2.2) + kaminari-activerecord (1.2.2) activerecord - kaminari-core (= 1.2.1) - kaminari-core (1.2.1) + kaminari-core (= 1.2.2) + kaminari-core (1.2.2) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - lograge (0.10.0) + lograge (0.12.0) actionpack (>= 4) activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.14.0) + loofah (2.19.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) - mail (2.7.1) + mail (2.8.0.1) mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp marcel (1.0.2) - memory_profiler (0.9.12) - method_source (0.9.2) + memory_profiler (1.0.1) + method_source (1.0.0) mime-types (3.4.1) mime-types-data (~> 3.2015) mime-types-data (3.2022.0105) mini_mime (1.1.2) - mini_portile2 (2.6.1) - minitest (5.15.0) - msgpack (1.3.3) - multi_json (1.13.1) + minitest (5.17.0) + msgpack (1.6.0) multi_xml (0.6.0) - multipart-post (2.1.1) + multipart-post (2.2.3) naturalsort (1.2.0) nested_form (0.3.2) + net-imap (0.3.4) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.1) + timeout + net-smtp (0.3.3) + net-protocol netrc (0.11.0) nio4r (2.5.8) - nokogiri (1.12.5) - mini_portile2 (~> 2.6.1) + nokogiri (1.14.0-x86_64-linux) racc (~> 1.4) octokit (4.22.0) faraday (>= 0.9) sawyer (~> 0.8.0, >= 0.5.3) orm_adapter (0.5.0) - paper_trail (10.1.0) - activerecord (>= 4.2, < 6.0) + paper_trail (13.0.0) + activerecord (>= 5.2) request_store (~> 1.1) - paper_trail-association_tracking (1.0.0) - parallel (1.21.0) - parser (3.1.0.0) + paper_trail-association_tracking (2.2.1) + paper_trail (>= 12.0) + parallel (1.22.1) + parser (3.2.0.0) ast (~> 2.4.1) - path_expander (1.0.3) - pg (0.21.0) + path_expander (1.1.1) + pg (1.4.5) pretender (0.3.4) actionpack (>= 4.2) - pronto (0.9.5) - gitlab (~> 4.0, >= 4.0.0) - httparty (>= 0.13.7) - octokit (~> 4.7, >= 4.7.0) - rainbow (~> 2.1) - rugged (~> 0.24, >= 0.23.0) - thor (~> 0.19.0) - pronto-flay (0.9.0) + pronto (0.11.1) + gitlab (>= 4.4.0, < 5.0) + httparty (>= 0.13.7, < 1.0) + octokit (>= 4.7.0, < 7.0) + rainbow (>= 2.2, < 4.0) + rexml (>= 3.2.5, < 4.0) + rugged (>= 0.23.0, < 2.0) + thor (>= 0.20.3, < 2.0) + pronto-flay (0.11.1) flay (~> 2.8) - pronto (~> 0.9.0) - pronto-rubocop (0.9.1) - pronto (~> 0.9.0) - rubocop (~> 0.50, >= 0.49.1) - pronto-simplecov (0.1.1) - pronto (~> 0.9.0) + pronto (~> 0.11.0) + pronto-rubocop (0.11.4) + pronto (~> 0.11.0) + rubocop (>= 0.63.1, < 2.0) + pronto-simplecov (0.11.0) + pronto (~> 0.11.0) simplecov - pry (0.12.2) - coderay (~> 1.1.0) - method_source (~> 0.9.0) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) pry-rails (0.3.9) pry (>= 0.10.4) - public_suffix (4.0.6) + public_suffix (5.0.1) puma (4.3.12) nio4r (~> 2.0) - racc (1.6.0) - rack (2.2.3) - rack-mini-profiler (1.0.1) + racc (1.6.2) + rack (2.2.6.2) + rack-mini-profiler (3.0.0) rack (>= 1.2.0) - rack-pjax (1.1.0) - nokogiri (~> 1.5) - rack (>= 1.1) - rack-protection (2.0.8.1) + rack-protection (3.0.5) rack - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (5.2.6.2) - actioncable (= 5.2.6.2) - actionmailer (= 5.2.6.2) - actionpack (= 5.2.6.2) - actionview (= 5.2.6.2) - activejob (= 5.2.6.2) - activemodel (= 5.2.6.2) - activerecord (= 5.2.6.2) - activestorage (= 5.2.6.2) - activesupport (= 5.2.6.2) - bundler (>= 1.3.0) - railties (= 5.2.6.2) - sprockets-rails (>= 2.0.0) - rails-controller-testing (1.0.4) - actionpack (>= 5.0.1.x) - actionview (>= 5.0.1.x) - activesupport (>= 5.0.1.x) + rack-test (2.0.2) + rack (>= 1.3) + rails (7.0.4.1) + actioncable (= 7.0.4.1) + actionmailbox (= 7.0.4.1) + actionmailer (= 7.0.4.1) + actionpack (= 7.0.4.1) + actiontext (= 7.0.4.1) + actionview (= 7.0.4.1) + activejob (= 7.0.4.1) + activemodel (= 7.0.4.1) + activerecord (= 7.0.4.1) + activestorage (= 7.0.4.1) + activesupport (= 7.0.4.1) + bundler (>= 1.15.0) + railties (= 7.0.4.1) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.4.2) - loofah (~> 2.3) + rails-html-sanitizer (1.5.0) + loofah (~> 2.19, >= 2.19.1) rails-jquery-autocomplete (1.0.5) rails (>= 3.2) - rails_admin (1.4.3) - builder (~> 3.1) - coffee-rails (~> 4.0) - font-awesome-rails (>= 3.0, < 5) - haml (>= 4.0, < 6) - jquery-rails (>= 3.0, < 5) - jquery-ui-rails (>= 5.0, < 7) + rails_admin (3.1.1) + activemodel-serializers-xml (>= 1.0) kaminari (>= 0.14, < 2.0) nested_form (~> 0.3) - rack-pjax (>= 0.7) - rails (>= 4.0, < 6) - remotipart (~> 1.3) - sass-rails (>= 4.0, < 6) - railties (5.2.6.2) - actionpack (= 5.2.6.2) - activesupport (= 5.2.6.2) + rails (>= 6.0, < 8) + turbo-rails (~> 1.0) + railties (7.0.4.1) + actionpack (= 7.0.4.1) + activesupport (= 7.0.4.1) method_source - rake (>= 0.8.7) - thor (>= 0.19.0, < 2.0) - rainbow (2.2.2) - rake - rake (12.3.3) - rb-fsevent (0.10.4) + rake (>= 12.2) + thor (~> 1.0) + zeitwerk (~> 2.5) + rainbow (3.1.1) + rake (13.0.6) + rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) redis (4.5.1) redis-prescription (1.0.0) - regexp_parser (1.7.1) - remotipart (1.4.4) - request_store (1.4.1) + regexp_parser (2.6.1) + request_store (1.5.1) rack (>= 1.4) - responders (3.0.0) + responders (3.0.1) actionpack (>= 5.0) railties (>= 5.0) rest-client (2.1.0) @@ -383,65 +403,57 @@ GEM mime-types (>= 1.16, < 4.0) netrc (~> 0.8) rexml (3.2.5) - rspec-core (3.8.0) - rspec-support (~> 3.8.0) - rspec-expectations (3.8.2) + rspec-core (3.12.0) + rspec-support (~> 3.12.0) + rspec-expectations (3.12.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.8.0) - rspec-its (1.2.0) + rspec-support (~> 3.12.0) + rspec-its (1.3.0) rspec-core (>= 3.0.0) rspec-expectations (>= 3.0.0) - rspec-mocks (3.8.0) + rspec-mocks (3.12.3) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.8.0) - rspec-rails (3.8.1) - actionpack (>= 3.0) - activesupport (>= 3.0) - railties (>= 3.0) - rspec-core (~> 3.8.0) - rspec-expectations (~> 3.8.0) - rspec-mocks (~> 3.8.0) - rspec-support (~> 3.8.0) - rspec-sidekiq (3.0.3) + rspec-support (~> 3.12.0) + rspec-rails (6.0.1) + actionpack (>= 6.1) + activesupport (>= 6.1) + railties (>= 6.1) + rspec-core (~> 3.11) + rspec-expectations (~> 3.11) + rspec-mocks (~> 3.11) + rspec-support (~> 3.11) + rspec-sidekiq (3.1.0) rspec-core (~> 3.0, >= 3.0.0) sidekiq (>= 2.4.0) - rspec-support (3.8.0) - rubocop (0.92.0) + rspec-support (3.12.0) + rubocop (1.43.0) + json (~> 2.3) parallel (~> 1.10) - parser (>= 2.7.1.5) + parser (>= 3.2.0.0) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.7) - rexml - rubocop-ast (>= 0.5.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.24.1, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (1.15.1) - parser (>= 3.0.1.1) - rubocop-rails (2.3.2) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.24.1) + parser (>= 3.1.1.0) + rubocop-rails (2.17.4) + activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 0.72.0) - ruby-prof (0.17.0) + rubocop (>= 1.33.0, < 2.0) + ruby-prof (1.4.5) ruby-progressbar (1.11.0) - ruby_parser (3.12.0) - sexp_processor (~> 4.9) + ruby_parser (3.19.2) + sexp_processor (~> 4.16) rubyzip (1.3.0) - rugged (0.99.0) - safe_yaml (1.0.4) - sass (3.7.4) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.1.0) - railties (>= 5.2.0) - sass (~> 3.1) - sprockets (>= 2.8, < 4.0) - sprockets-rails (>= 2.0, < 4.0) - tilt (>= 1.1, < 3) - sassc (2.0.0) - ffi (~> 1.9.6) - rake - sassc-rails (2.0.0) + rugged (1.5.0.1) + sanitize (6.0.0) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + sassc (2.4.0) + ffi (~> 1.9) + sassc-rails (2.1.2) railties (>= 4.0.0) sassc (>= 2.0) sprockets (> 3.0) @@ -450,14 +462,11 @@ GEM sawyer (0.8.2) addressable (>= 2.3.5) faraday (> 0.8, < 2.0) - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) - rubyzip (>= 1.2.2) sentry-raven (2.7.4) faraday (>= 0.7.6, < 1.0) - sexp_processor (4.11.0) - shoulda-matchers (3.1.2) - activesupport (>= 4.0.0) + sexp_processor (4.16.1) + shoulda-matchers (5.3.0) + activesupport (>= 5.2.0) sidekiq (5.2.10) connection_pool (~> 2.2, >= 2.2.2) rack (~> 2.0) @@ -467,93 +476,93 @@ GEM concurrent-ruby redis-prescription sidekiq - simple_form (5.0.0) - actionpack (>= 5.0) - activemodel (>= 5.0) - simplecov (0.13.0) - docile (~> 1.1.0) - json (>= 1.8, < 3) - simplecov-html (~> 0.10.0) - simplecov-html (0.10.2) - spring (2.0.2) - activesupport (>= 4.2) + simple_form (5.1.0) + actionpack (>= 5.2) + activemodel (>= 5.2) + simplecov (0.22.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.4) + spring (2.1.1) spring-watcher-listen (2.0.1) listen (>= 2.7, < 4.0) spring (>= 1.2, < 3.0) - sprockets (3.7.2) + sprockets (4.2.0) concurrent-ruby (~> 1.0) - rack (> 1, < 3) + rack (>= 2.2.4, < 4) sprockets-rails (3.4.2) actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - stackprof (0.2.12) - temple (0.8.2) + stackprof (0.2.23) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) - thor (0.19.4) - thread_safe (0.3.6) - tilt (2.0.10) - turbolinks (5.2.0) + thor (1.2.1) + tilt (2.0.11) + timeout (0.3.1) + turbo-rails (1.3.2) + actionpack (>= 6.0.0) + activejob (>= 6.0.0) + railties (>= 6.0.0) + turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) typhoeus (1.3.1) ethon (>= 0.9.0) - tzinfo (1.2.10) - thread_safe (~> 0.1) - uglifier (4.1.20) + tzinfo (2.0.5) + concurrent-ruby (~> 1.0) + uglifier (4.2.0) execjs (>= 0.3.0, < 3) unf (0.1.4) unf_ext unf_ext (0.0.8.2) - unicode-display_width (1.8.0) - warden (1.2.8) - rack (>= 2.0.6) - web-console (3.7.0) - actionview (>= 5.0) - activemodel (>= 5.0) + unicode-display_width (2.4.2) + warden (1.2.9) + rack (>= 2.0.9) + web-console (4.2.0) + actionview (>= 6.0.0) + activemodel (>= 6.0.0) bindex (>= 0.4.0) - railties (>= 5.0) - webmock (3.4.2) - addressable (>= 2.3.6) + railties (>= 6.0.0) + webmock (3.18.1) + addressable (>= 2.8.0) crack (>= 0.3.2) - hashdiff + hashdiff (>= 0.4.0, < 2.0.0) websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - xpath (3.2.0) - nokogiri (~> 1.8) + zeitwerk (2.6.6) PLATFORMS - ruby + x86_64-linux DEPENDENCIES activerecord-nulldb-adapter - annotate (~> 2.7.4) + annotate (~> 3.2.0) aws-sdk-s3 (~> 1.48) - bootsnap (~> 1.3.2) + bootsnap (~> 1.15.0) bootstrap-datepicker-rails bootstrap-sass (~> 3.4.1) byebug - capybara cocoon coffee-rails (~> 4.2) database_cleaner deep_cloneable dentaku - devise (~> 4.7.1) + devise (~> 4.8.1) dhis2! differ - factory_bot_rails (~> 4.11.1) + factory_bot_rails (~> 6.2.0) faker fast_jsonapi figaro flamegraph - flipper (~> 0.16.1) - flipper-active_record (~> 0.16.1) - flipper-ui (~> 0.16.1) + flipper (~> 0.26.0) + flipper-active_record (~> 0.26.0) + flipper-ui (~> 0.26.0) hashdiff - heroku-deflater hesabu! immigrant jbuilder (~> 2.5) @@ -562,38 +571,37 @@ DEPENDENCIES json (= 2.3.0) json-diff (~> 0.4.1) listen (~> 3.0.5) - lograge (~> 0.10.0) + lograge (~> 0.12.0) loofah (>= 2.2.3) memory_profiler naturalsort orbf-rules_engine! - paper_trail (~> 10.1.0) - paper_trail-association_tracking (~> 1.0.0) - pg (~> 0.18) + paper_trail (~> 13.0.0) + paper_trail-association_tracking (~> 2.2.1) + pg (~> 1.4.5) pretender (~> 0.3.4) pronto pronto-flay pronto-rubocop pronto-simplecov - pry (~> 0.12.2) + pry (~> 0.14.2) pry-rails (~> 0.3.9) puma (~> 4.3) rack (>= 2.0.6) rack-mini-profiler - rails (~> 5.2, < 5.3) + rails (~> 7.0.4.1) rails-controller-testing rails-jquery-autocomplete - rails_admin (~> 1.4.2) + rails_admin (~> 3.1.1) rest-client-logger! rspec-its - rspec-rails (~> 3.0) + rspec-rails (~> 6.0.1) rspec-sidekiq rubocop rubocop-rails ruby-prof rubyzip (~> 1.3.0) - sassc-rails (~> 2.0.0) - selenium-webdriver + sassc-rails (~> 2.1.2) sentry-raven (~> 2.7.4) shoulda-matchers sidekiq (< 6) @@ -602,7 +610,7 @@ DEPENDENCIES simplecov spring spring-watcher-listen (~> 2.0.0) - sprockets (~> 3.7.2) + sprockets (~> 4.2.0) stackprof turbolinks (~> 5) typhoeus (~> 1.3.1) @@ -612,7 +620,7 @@ DEPENDENCIES webmock RUBY VERSION - ruby 2.5.8p224 + ruby 3.2.0p0 BUNDLED WITH - 2.3.5 + 2.4.4 diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index f55f30e0..d3d30b24 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -14,7 +14,6 @@ // "bootstrap-sprockets" must be imported before "bootstrap" and "bootstrap/variables" @import "bootstrap-sprockets"; @import "bootstrap"; -@import "font-awesome"; @import "jquery-ui/core"; @import "jquery-ui/menu"; @import "jquery-ui/theme"; diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb deleted file mode 100644 index e69de29b..00000000 diff --git a/app/controllers/oauth/oauth_controller.rb b/app/controllers/oauth/oauth_controller.rb index ac83ed44..ea1c3af3 100644 --- a/app/controllers/oauth/oauth_controller.rb +++ b/app/controllers/oauth/oauth_controller.rb @@ -1,48 +1,57 @@ -require 'net/http' -require 'uri' +require "net/http" +require "uri" class Oauth::OauthController < Devise::OmniauthCallbacksController def dhis2_login # https://sandbox.bluesquare.org/uaa/oauth/authorize?client_id=[client_id]&response_type=code - program = Program.find(params["program_id"]) rescue nil + program = begin + Program.find(params["program_id"]) + rescue StandardError + nil + end if program.nil? - flash[:failure] = "Log-in failed: program with ID #{params["program_id"]} does not exist" + flash[:failure] = "Log-in failed: program with ID #{params['program_id']} does not exist" redirect_to("/users/sign_in") return end oauth_client_id = program.oauth_client_id - + if oauth_client_id.blank? - flash[:failure] = "Log-in failed: program with ID #{params["program_id"]} is not configured for sign-in with DHIS2" + flash[:failure] = +"Log-in failed: program with ID #{params['program_id']} is not configured for sign-in with DHIS2" redirect_to("/users/sign_in") return end url_redirect = program.project_anchor.project.dhis2_url + "/uaa/oauth/authorize?client_id=#{oauth_client_id}&response_type=code" - redirect_to(url_redirect) + redirect_to(url_redirect, allow_other_host: true) end def callback - program = Program.find(params["program_id"]) rescue nil + program = begin + Program.find(params["program_id"]) + rescue StandardError + nil + end if program.nil? - flash[:failure] = "Log-in failed: program with ID #{params["program_id"]} does not exist" + flash[:failure] = "Log-in failed: program with ID #{params['program_id']} does not exist" redirect_to("/users/sign_in") return end - + url_post = program.project_anchor.project.dhis2_url + "/uaa/oauth/token" - + uri = URI.parse(url_post) request = Net::HTTP::Post.new(uri) request.basic_auth(program.oauth_client_id, program.oauth_client_secret) request["Accept"] = "application/json" request.set_form_data( - "code" => params["code"], + "code" => params["code"], "grant_type" => "authorization_code" ) req_options = { @@ -58,7 +67,11 @@ def callback return end - access_token = JSON.parse(response.body)["access_token"] rescue nil + access_token = begin + JSON.parse(response.body)["access_token"] + rescue StandardError + nil + end if access_token.nil? flash[:failure] = "Log-in failed: bad response from DHIS2, please check the logs" @@ -66,9 +79,14 @@ def callback return end - user_info = RestClient.get(program.project_anchor.project.dhis2_url + "/api/me", { "Authorization": "Bearer #{access_token}" }) + user_info = RestClient.get(program.project_anchor.project.dhis2_url + "/api/me", + { "Authorization": "Bearer #{access_token}" }) - user_info = JSON.parse(user_info) rescue nil + user_info = begin + JSON.parse(user_info) + rescue StandardError + nil + end if user_info.nil? flash[:failure] = "Log-in failed: bad response from DHIS2, please check the logs" @@ -79,13 +97,14 @@ def callback dhis2_user_ref = user_info["id"] user = program.users.find_by_dhis2_user_ref(dhis2_user_ref) - + if user sign_in_and_redirect(user) - else - flash[:failure] = "Log-in failed: no ORBF2 user associated to the DHIS2 user with name #{user_info["displayName"]} and ID #{dhis2_user_ref}" + else + flash[:failure] = +"Log-in failed: no ORBF2 user associated to the DHIS2 user with name #{user_info['displayName']} and ID #{dhis2_user_ref}" redirect_to("/users/sign_in") - return + nil end end -end \ No newline at end of file +end diff --git a/app/models/activity_state.rb b/app/models/activity_state.rb index 304ab568..a7be1242 100644 --- a/app/models/activity_state.rb +++ b/app/models/activity_state.rb @@ -30,16 +30,16 @@ class ActivityStateValidator def self.validate(activity_state) - if activity_state.kind_data_element_coc? && activity_state.external_reference.presence - if !activity_state.external_reference.include?(".") - activity_state.errors[:external_reference] << "should contains a dot like DATAELEMENTID.COCID" - end - end - if (activity_state.kind_indicator? || activity_state.kind_data_element?) && activity_state.external_reference.presence - if activity_state.external_reference.include?(".") - activity_state.errors[:external_reference] << "should NOT contains a dot like DATAELEMENTID.COCID" - end + if activity_state.kind_data_element_coc? && activity_state.external_reference.presence && !activity_state.external_reference.include?(".") + activity_state.errors.add(:external_reference, + "should contains a dot like DATAELEMENTID.COCID") end + de_or_indicator = activity_state.kind_indicator? || activity_state.kind_data_element? + return unless de_or_indicator && activity_state.external_reference.presence + return unless activity_state.external_reference.include?(".") + + activity_state.errors.add(:external_reference, + "should NOT contains a dot like DATAELEMENTID.COCID") end end @@ -52,7 +52,8 @@ class ActivityState < ApplicationRecord belongs_to :state validates :state, presence: { message: "Select a state or remove this activity from the list" } - validates :external_reference, presence: true, uniqueness: { scope: [:activity_id] }, if: :dhis2_related? + validates :external_reference, presence: true, uniqueness: { scope: [:activity_id] }, +if: :dhis2_related? validates :name, presence: true validates :formula, presence: true, if: :kind_formula? diff --git a/app/models/decision_table.rb b/app/models/decision_table.rb index fda698b1..a8603868 100644 --- a/app/models/decision_table.rb +++ b/app/models/decision_table.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: decision_tables @@ -49,7 +50,7 @@ def normalize_blank_values def in_headers_belong_to_facts in_headers.each do |header| unless HEADER_PREFIXES.include?(header) || header.starts_with?("groupset_code_") - errors[:content] << "Not '#{header}' in available org unit facts !" + errors.add(:content, "Not '#{header}' in available org unit facts !") end end end @@ -59,8 +60,13 @@ def in_activity_code_exists available_codes = rule.package.activity_packages.map(&:activity).map(&:code).compact available_codes.push Decision::Rule::ANY - invalid_rules = decision_table.rules.reject { |rule| available_codes.include?(rule[HEADER_IN_ACTIVITY_CODE]) } - invalid_rules.each { |invalid_rule| errors[:content] << "#{invalid_rule.inspect} not in available package codes #{available_codes}!" } + invalid_rules = decision_table.rules.reject do |rule| + available_codes.include?(rule[HEADER_IN_ACTIVITY_CODE]) + end + invalid_rules.each do |invalid_rule| + errors.add(:content, + "#{invalid_rule.inspect} not in available package codes #{available_codes}!") + end end def period_start_before_end @@ -68,12 +74,12 @@ def period_start_before_end return if !start_period.presence && !end_period.presence if start_period.presence && !end_period.presence - errors[:end_period] << "Should be filled in if start period is filled" + errors.add(:end_period, "Should be filled in if start period is filled") elsif !start_period.presence && end_period.presence - errors[:start_period] << "Should be filled in if end period is filled" + errors.add(:start_period, "Should be filled in if end period is filled") else if start_period.presence > end_period.presence - errors[:start_period] << "Should be before end period" + errors.add(:start_period, "Should be before end period") end package_frequency = rule.package.frequency @@ -86,10 +92,10 @@ def period_start_before_end def validate_period_type(value, field, expected_frequency) frequency = Periods.detect(value) if frequency != expected_frequency - errors[field] << "Should be of period type " + expected_frequency + errors.add(field, "Should be of period type " + expected_frequency) end rescue StandardError => e - errors[field] << "Should be of period type " + expected_frequency + " : " + e.message + errors.add(field, "Should be of period type " + expected_frequency + " : " + e.message) end def in_headers diff --git a/app/models/formula_mapping.rb b/app/models/formula_mapping.rb index 0cc5c73a..031da4b0 100644 --- a/app/models/formula_mapping.rb +++ b/app/models/formula_mapping.rb @@ -36,7 +36,9 @@ class FormulaMapping < ApplicationRecord belongs_to :formula, inverse_of: :formula_mappings belongs_to :activity, optional: true - validates :activity, presence: true, if: -> { [Rule::RULE_TYPE_ACTIVITY, Rule::RULE_TYPE_ZONE_ACTIVITY].include?(kind) } + validates :activity, presence: true, if: lambda { + [Rule::RULE_TYPE_ACTIVITY, Rule::RULE_TYPE_ZONE_ACTIVITY].include?(kind) + } def project formula.rule.project @@ -55,7 +57,7 @@ def names short: format(naming_patterns[:short], substitutions).strip, code: format(naming_patterns[:code], substitutions).strip } - Dhis2Name.new(dhis2_name) + Dhis2Name.new(**dhis2_name) end def data_element_ext_ref diff --git a/app/models/invoicing_job.rb b/app/models/invoicing_job.rb index 932e3e6f..1a2c40f9 100644 --- a/app/models/invoicing_job.rb +++ b/app/models/invoicing_job.rb @@ -62,18 +62,17 @@ def execute(project_anchor, period, orgunit_ref) start_time = time instrument :execute do |payload| - begin - payload[:found] = "FOUND #{invoicing_job.inspect} vs #{period} #{orgunit_ref}" - yield(invoicing_job) - ensure - payload[:processed] = "mark_as_processed #{invoicing_job.inspect}" - find_invoicing_job(project_anchor, period, orgunit_ref)&.mark_as_processed(start_time, time) - end + payload[:found] = "FOUND #{invoicing_job.inspect} vs #{period} #{orgunit_ref}" + yield(invoicing_job) + ensure + payload[:processed] = "mark_as_processed #{invoicing_job.inspect}" + find_invoicing_job(project_anchor, period, + orgunit_ref)&.mark_as_processed(start_time, time) end - rescue StandardError => err - warn "ERROR #{invoicing_job.inspect} #{err.message}" - find_invoicing_job(project_anchor, period, orgunit_ref)&.mark_as_error(start_time, time, err) - raise err + rescue StandardError => e + warn "ERROR #{invoicing_job.inspect} #{e.message}" + find_invoicing_job(project_anchor, period, orgunit_ref)&.mark_as_error(start_time, time, e) + raise e end private @@ -102,8 +101,8 @@ def find_invoicing_job(project_anchor, period, orgunit_ref) end def processed_after?(time_stamp: 10.minutes.ago) - return errored_at > time_stamp if errored? - return processed_at > time_stamp if processed? + return errored_at > time_stamp if errored? && errored_at + return processed_at > time_stamp if processed? && processed_at false end diff --git a/app/models/project.rb b/app/models/project.rb index dd2957f5..a6b1fab8 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -394,7 +394,7 @@ def changelog(other_project = original) diff_symbols = { "+" => :added, "-" => :removed, "~" => :modified } all_names = to_unified_names.merge(other_project.to_unified_names) - HashDiff.diff(other_project.to_unified_h, to_unified_h).map do |hash_diff| + Hashdiff.diff(other_project.to_unified_h, to_unified_h).map do |hash_diff| operation, path, value, current = hash_diff ChangelogEntry.new( diff --git a/app/models/rule_types/base_rule_type.rb b/app/models/rule_types/base_rule_type.rb index c8fdc805..d557fe8c 100644 --- a/app/models/rule_types/base_rule_type.rb +++ b/app/models/rule_types/base_rule_type.rb @@ -5,6 +5,7 @@ def initialize(rule) end attr_reader :rule + delegate :package, to: :rule delegate :formulas, to: :rule delegate :activity_kind?, to: :rule @@ -75,8 +76,8 @@ def package_formula_uniqness formula_by_codes.each do |code, formulas| next unless formulas.size > 1 - rule.errors[:formulas] << "Formula's code must be unique,"\ - " you have #{formulas.size} formulas with '#{code}'" + rule.errors.add(:formulas, "Formula's code must be unique,"\ + " you have #{formulas.size} formulas with '#{code}'") end end end diff --git a/app/models/rule_types/package_rule_type.rb b/app/models/rule_types/package_rule_type.rb index 701e13a7..ce14a017 100644 --- a/app/models/rule_types/package_rule_type.rb +++ b/app/models/rule_types/package_rule_type.rb @@ -57,14 +57,14 @@ def package_formula_uniqness next unless formula_by_codes[code] if non_uniq_formulas.size > 1 - rule.errors[:formulas] << "Formula's code must be unique accross packages, you have #{non_uniq_formulas.size} formulas with '#{code}' in #{non_uniq_formulas.map(&:rule).map(&:package).map(&:name).join(' and ')}" + rule.errors.add(:formulas, "Formula's code must be unique accross packages, you have #{non_uniq_formulas.size} formulas with '#{code}' in #{non_uniq_formulas.map(&:rule).map(&:package).map(&:name).join(' and ')}") end end end formula_by_codes.each do |code, formulas| if formulas.size > 1 - rule.errors[:formulas] << "Formula's code must be unique, you have #{formulas.size} formulas with '#{code}'" + rule.errors.add(:formulas, "Formula's code must be unique, you have #{formulas.size} formulas with '#{code}'") end end end diff --git a/app/models/url_validator.rb b/app/models/url_validator.rb index dae11808..01b3c740 100644 --- a/app/models/url_validator.rb +++ b/app/models/url_validator.rb @@ -8,6 +8,6 @@ def validate_each(record, attribute, value) rescue URI::InvalidURIError resp = false end - record.errors[attribute] << (options[:message] || "is not an url") unless resp == true + record.errors.add(attribute, (options[:message] || "is not an url")) unless resp == true end end diff --git a/app/serializers/invoicing_job_serializer.rb b/app/serializers/invoicing_job_serializer.rb index 85165b48..c1bd0054 100644 --- a/app/serializers/invoicing_job_serializer.rb +++ b/app/serializers/invoicing_job_serializer.rb @@ -32,12 +32,12 @@ class InvoicingJobSerializer include FastJsonapi::ObjectSerializer set_key_transform :camel_lower - attribute :org_unit, &:orgunit_ref + attribute :org_unit do |rec| rec.orgunit_ref end attribute :dhis2_period - attribute :user, &:user_ref + attribute :user do |rec| rec.user_ref end attributes :created_at, :processed_at, :errored_at, :duration_ms, :status, :last_error attribute :sidekiq_job_ref - attribute :is_alive, &:alive? - attribute :result_url, &:result_url + attribute :is_alive do |rec| rec.alive? end + attribute :result_url do |rec| rec.result_url end end diff --git a/app/serializers/v2/activity_serializer.rb b/app/serializers/v2/activity_serializer.rb index d34a9c57..e487ccf7 100644 --- a/app/serializers/v2/activity_serializer.rb +++ b/app/serializers/v2/activity_serializer.rb @@ -10,7 +10,7 @@ class V2::ActivitySerializer < V2::BaseSerializer attributes :updated_at attributes :stable_id - has_many :input_mappings, serializer: ActivityStateSerializer do |activity| + has_many :input_mappings, serializer: ::V2::ActivityStateSerializer do |activity| activity.activity_states end diff --git a/app/serializers/v2/dhis_value_item_serializer.rb b/app/serializers/v2/dhis_value_item_serializer.rb index 072f5da8..f9403b19 100644 --- a/app/serializers/v2/dhis_value_item_serializer.rb +++ b/app/serializers/v2/dhis_value_item_serializer.rb @@ -1,10 +1,15 @@ # frozen_string_literal: true class V2::DhisValueItemSerializer < V2::BaseSerializer - attribute :value, &:display_name - + attribute :value do |rec| + rec.display_name + end attribute :id - attribute :name, &:display_name - attribute :display_name + attribute :name do |rec| + rec.display_name + end + attribute :display_name do |rec| + rec.display_name + end attribute :kind, if: Proc.new { |record, params| record.respond_to?(:kind) && record&.kind.present? } end diff --git a/app/serializers/v2/invoicing_job_serializer.rb b/app/serializers/v2/invoicing_job_serializer.rb index 699f1194..0b5dcf64 100644 --- a/app/serializers/v2/invoicing_job_serializer.rb +++ b/app/serializers/v2/invoicing_job_serializer.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true class V2::InvoicingJobSerializer < V2::BaseSerializer - attribute :org_unit, &:orgunit_ref + attribute :org_unit do |rec| rec.orgunit_ref end attribute :org_unit_name attribute :dhis2_period - attribute :user, &:user_ref + attribute :user do |rec| rec.user_ref end attributes :created_at, :processed_at, :errored_at, :duration_ms, :status, :last_error attribute :sidekiq_job_ref - attribute :is_alive, &:alive? - attribute :result_url, &:result_url + attribute :is_alive do |rec| rec.alive? end + attribute :result_url do |rec| rec.result_url end end diff --git a/app/services/invoicing/invoice_entity.rb b/app/services/invoicing/invoice_entity.rb index 3c982ddd..f3f28b43 100644 --- a/app/services/invoicing/invoice_entity.rb +++ b/app/services/invoicing/invoice_entity.rb @@ -48,22 +48,22 @@ def ignore_non_contracted? def fetch_and_solve @fetch_and_solve ||= begin - solve_options = { - pyramid: pyramid, - mock_values: invoicing_request.mocked_data - } - - @fetch_and_solve = Orbf::RulesEngine::FetchAndSolve.new( - orbf_project, - invoicing_request.entity, - invoicing_request.year_quarter.to_dhis2, - solve_options - ) - @pyramid = @fetch_and_solve.pyramid - @dhis2_export_values = @fetch_and_solve.call - @dhis2_input_values = @fetch_and_solve.dhis2_values - @fetch_and_solve - end + solve_options = { + pyramid: pyramid, + mock_values: invoicing_request.mocked_data + } + + @fetch_and_solve = Orbf::RulesEngine::FetchAndSolve.new( + orbf_project, + invoicing_request.entity, + invoicing_request.year_quarter.to_dhis2, + **solve_options + ) + @pyramid = @fetch_and_solve.pyramid + @dhis2_export_values = @fetch_and_solve.call + @dhis2_input_values = @fetch_and_solve.dhis2_values + @fetch_and_solve + end end def publish_to_dhis2 diff --git a/app/services/map_project_to_orbf_project.rb b/app/services/map_project_to_orbf_project.rb index 793f7e1f..c95073fe 100644 --- a/app/services/map_project_to_orbf_project.rb +++ b/app/services/map_project_to_orbf_project.rb @@ -27,7 +27,8 @@ def map private - attr_reader :project, :packages, :dhis2_indicators_by_id, :data_elements_by_id, :category_combos_by_id + attr_reader :project, :packages, :dhis2_indicators_by_id, :data_elements_by_id, + :category_combos_by_id PACKAGE_KINDS = { "multi-groupset" => "subcontract" @@ -129,7 +130,7 @@ def map_formulas(formulas) formula.code, formula.expression, formula.description, - map_formula_mappings(formula) + **map_formula_mappings(formula) ) end end @@ -137,7 +138,10 @@ def map_formulas(formulas) def map_formula_mappings(formula) formula_mappings = {} formula_mappings[:frequency] = formula.frequency if formula.frequency - formula_mappings[:exportable_formula_code] = formula.exportable_formula_code if formula.exportable_formula_code + if formula.exportable_formula_code + formula_mappings[:exportable_formula_code] = +formula.exportable_formula_code + end if formula.rule.activity_related_kind? && formula.formula_mappings.any? formula_mappings[:activity_mappings] = formula.formula_mappings .each_with_object({}) do |mapping, hash| diff --git a/app/services/meta/meta_data_service.rb b/app/services/meta/meta_data_service.rb index 6cf79a6a..e5d59778 100644 --- a/app/services/meta/meta_data_service.rb +++ b/app/services/meta/meta_data_service.rb @@ -40,7 +40,7 @@ def build_package_formula_mappings_meta_datas def new_meta_formula_mapping(formula_mapping, package) name = formula_mapping.names Meta::Metadata.new( - dhis2_props(formula_mapping.external_reference).merge( + **dhis2_props(formula_mapping.external_reference).merge( formula_mapping: formula_mapping, package: package, orbf_type: "Formula mapping", @@ -68,7 +68,7 @@ def new_meta_activity_state(activity_state, activity_package) project.naming_patterns, activity_state.activity ) Meta::Metadata.new( - dhis2_props(activity_state.external_reference).merge( + **dhis2_props(activity_state.external_reference).merge( activity_state: activity_state, package: activity_package.package, orbf_type: "Activity state", diff --git a/app/services/rules/solver.rb b/app/services/rules/solver.rb index 15270fe5..249ebcbb 100644 --- a/app/services/rules/solver.rb +++ b/app/services/rules/solver.rb @@ -15,12 +15,12 @@ def solve!(message, facts_and_rules, debug = false) log "********** #{message} #{Time.new}\n#{JSON.pretty_generate(facts_and_rules)}\n" if debug begin solution = calculator.solve!(facts_and_rules) - rescue TSort::Cyclic => cycle_error + rescue TSort::Cyclic => e log JSON.pretty_generate(facts_and_rules) - log cycle_error.message - raise SolvingError.new("a cycle has been created : " + cycle_error.message, facts_and_rules), + log e.message + raise SolvingError.new("a cycle has been created : " + e.message, facts_and_rules), "Failed to solve this problem : a cycle exist between formulas: "\ - "#{message} : #{cycle_error.message}" + "#{message} : #{e.message}" rescue StandardError => e log JSON.pretty_generate(facts_and_rules) log e.message @@ -39,11 +39,11 @@ def validate_expression(formula) ) ) rescue KeyError => e - formula.errors[:expression] << "#{e.message}. " \ - "Remove extra spaces or verify it's in the available variables" + formula.errors.add(:expression, "#{e.message}. " \ + "Remove extra spaces or verify it's in the available variables") rescue StandardError => e Rails.logger.warn("FAILED to validate #{formula} : #{e.backtrace.join("\n")}") - formula.errors[:expression] << e.message + formula.errors.add(:expression, e.message) end def dependencies(formula) @@ -53,7 +53,7 @@ def dependencies(formula) formula.rule.available_variables_for_values ) ) - rescue StandardError => ignored + rescue StandardError => e [] end @@ -70,12 +70,13 @@ def validate_formulas(rule) facts[:actictity_rule_name] = Solver.escape_string(rule.name) solve!("validate_all_formulas", facts) rescue Rules::SolvingError => e - rule.errors[:formulas] << e.original_message + rule.errors.add(:formulas, e.original_message) rescue KeyError => e - rule.errors[:formulas] << "#{e.message}. Remove extra spaces or verify it's in the available variables" + rule.errors.add(:formulas, + "#{e.message}. Remove extra spaces or verify it's in the available variables") rescue StandardError => e log(e.message) - rule.errors[:formulas] << e.message + rule.errors.add(:formulas, e.message) end def self.escape_string(string) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 5b19c485..29432d26 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -3,6 +3,8 @@ Open RBF 2.0 <%= csrf_meta_tags %> + + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> diff --git a/app/views/layouts/private.html.erb b/app/views/layouts/private.html.erb index 4f836be3..66dc66a3 100644 --- a/app/views/layouts/private.html.erb +++ b/app/views/layouts/private.html.erb @@ -3,6 +3,8 @@ Open RBF 2.0 <%= csrf_meta_tags %> + + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <% if log_rocket_token = ENV["LOG_ROCKET_TOKEN"] %> diff --git a/app/workers/fetchers/organisation_units_snapshot_fetcher.rb b/app/workers/fetchers/organisation_units_snapshot_fetcher.rb index f5b5fafc..ce42a450 100644 --- a/app/workers/fetchers/organisation_units_snapshot_fetcher.rb +++ b/app/workers/fetchers/organisation_units_snapshot_fetcher.rb @@ -7,11 +7,13 @@ def initialize(fields:) end def fetch_data(project, kind, params) - raise "OrganisationUnitsSnapshotFetcher works only on organisation_units" unless kind == :organisation_units + unless kind == :organisation_units + raise "OrganisationUnitsSnapshotFetcher works only on organisation_units" + end filters = build_filters(project) filters.each_with_object([]) do |filter, data| - data.push(*fetcher.fetch_data(project, kind, { filter: filter }.merge(params))) + data.push(*fetcher.fetch_data(project, kind, **{ filter: filter }.merge(params))) end end diff --git a/bin/rails b/bin/rails index 07396602..efc03774 100755 --- a/bin/rails +++ b/bin/rails @@ -1,4 +1,4 @@ #!/usr/bin/env ruby -APP_PATH = File.expand_path('../config/application', __dir__) -require_relative '../config/boot' -require 'rails/commands' +APP_PATH = File.expand_path("../config/application", __dir__) +require_relative "../config/boot" +require "rails/commands" diff --git a/bin/rake b/bin/rake index 17240489..4fbf10b9 100755 --- a/bin/rake +++ b/bin/rake @@ -1,4 +1,4 @@ #!/usr/bin/env ruby -require_relative '../config/boot' -require 'rake' +require_relative "../config/boot" +require "rake" Rake.application.run diff --git a/bin/setup b/bin/setup index 4ccb4fac..ec47b79b 100755 --- a/bin/setup +++ b/bin/setup @@ -1,17 +1,16 @@ #!/usr/bin/env ruby -require "pathname" require "fileutils" -include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path("../../", __FILE__) +APP_ROOT = File.expand_path("..", __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") end -chdir APP_ROOT do - # This script is a starting point to setup your application. +FileUtils.chdir APP_ROOT do + # This script is a way to set up or update your development environment automatically. + # This script is idempotent, so that you can run it at any time and get an expectable outcome. # Add necessary setup steps to this file. puts "== Installing dependencies ==" @@ -19,12 +18,12 @@ chdir APP_ROOT do system("bundle check") || system!("bundle install") # puts "\n== Copying sample files ==" - # unless File.exist?('config/database.yml') - # cp 'config/database.yml.sample', 'config/database.yml' + # unless File.exist?("config/database.yml") + # FileUtils.cp "config/database.yml.sample", "config/database.yml" # end puts "\n== Preparing database ==" - system! "bin/rails db:setup" + system! "bin/rails db:prepare" puts "\n== Removing old logs and tempfiles ==" system! "bin/rails log:clear tmp:clear" diff --git a/config/application.rb b/config/application.rb index a7f21da5..8b3ddea4 100644 --- a/config/application.rb +++ b/config/application.rb @@ -20,7 +20,8 @@ module Scorpio class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 5.1 + config.load_defaults 7.0 + config.autoloader = :zeitwerk # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers diff --git a/config/environments/development.rb b/config/environments/development.rb index 77f5b2c7..093528a5 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -27,7 +27,7 @@ end # Store uploaded files on the local file system (see config/storage.yml for options) - config.active_storage.service = ENV.fetch("RAILS_ACTIVE_STORAGE", 'amazon') + config.active_storage.service = ENV.fetch("RAILS_ACTIVE_STORAGE", "amazon") # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false @@ -61,24 +61,29 @@ config.action_mailer.default_url_options = { host: "localhost", port: 3000 } config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { address: "localhost", port: 1025 } + config.autoload_paths += %W[#{config.root}/app/services] ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::Dhis2ValuesPrinter, :print) ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::Solver, :solve!) ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::FetchAndSolve, :call) ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::GroupOrgunitsResolver, :call) ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::ResolveArguments, :call) - ::Rack::MiniProfiler.profile_singleton_method(Orbf::RulesEngine::ActivityVariablesBuilder, :to_variables) - #::Rack::MiniProfiler.profile_singleton_method(Orbf::RulesEngine::PeriodIterator, :periods) + ::Rack::MiniProfiler.profile_singleton_method(Orbf::RulesEngine::ActivityVariablesBuilder, + :to_variables) + # ::Rack::MiniProfiler.profile_singleton_method(Orbf::RulesEngine::PeriodIterator, :periods) ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::SolverFactory, :new_solver) ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::DecisionVariablesBuilder, :to_variables) - ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::ActivityConstantVariablesBuilder, :to_variables) - ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::ActivityFormulaVariablesBuilder, :to_variables) + ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::ActivityConstantVariablesBuilder, + :to_variables) + ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::ActivityFormulaVariablesBuilder, + :to_variables) ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::PackageVariablesBuilder, :to_variables) ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::ZoneFormulaVariablesBuilder, :to_variables) - ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::PaymentFormulaVariablesBuilder, :to_variables) + ::Rack::MiniProfiler.profile_method(Orbf::RulesEngine::PaymentFormulaVariablesBuilder, + :to_variables) ::Rack::MiniProfiler.profile_method(ActionView::Template, :render) ::Rack::MiniProfiler.profile_method(Hesabu::Solver, :solve!) - ::Rack::MiniProfiler.profile_method(Invoicing::InvoiceEntity, :call) + # ::Rack::MiniProfiler.profile_method(Invoicing::InvoiceEntity, :call) end diff --git a/config/environments/production.rb b/config/environments/production.rb index 09586d39..1b1e388f 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -23,12 +23,13 @@ config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? # Compress JavaScripts and CSS. - config.assets.js_compressor = Uglifier.new(harmony: true) - # config.assets.css_compressor = :sass - + config.assets.configure do |env| + env.js_compressor = :uglifier # or :closure, :yui + env.css_compressor = :sass # or :yui + end # Do not fallback to assets pipeline if a precompiled asset is missed. config.assets.compile = false - + config.assets.precompile = ["manifest.js"] # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb # Enable serving of images, stylesheets, and JavaScripts from an asset server. @@ -38,7 +39,7 @@ # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX - config.active_storage.service = ENV.fetch("RAILS_ACTIVE_STORAGE", 'amazon') + config.active_storage.service = ENV.fetch("RAILS_ACTIVE_STORAGE", "amazon") # Mount Action Cable outside main process or domain # config.action_cable.mount_path = nil diff --git a/config/environments/test.rb b/config/environments/test.rb index 36114db2..4526ceb6 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,6 +1,6 @@ Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. - config.paper_trail.enabled = true + # config.paper_trail.enabled = true # The test environment is used exclusively to run your application's # test suite. You never need to work with it otherwise. Remember that # your test database is "scratch space" for the test suite and is wiped diff --git a/config/initializers/new_framework_defaults_5_2.rb b/config/initializers/new_framework_defaults_5_2.rb index b3aebc13..3e92a4b3 100644 --- a/config/initializers/new_framework_defaults_5_2.rb +++ b/config/initializers/new_framework_defaults_5_2.rb @@ -29,10 +29,6 @@ # ApplicationController. # Rails.application.config.action_controller.default_protect_from_forgery = true -# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and -# 'f' after migrating old data. -Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true - # Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header. Rails.application.config.active_support.use_sha1_digests = true diff --git a/config/initializers/rails_admin.rb b/config/initializers/rails_admin.rb index 9bc48a37..d5bd72d5 100644 --- a/config/initializers/rails_admin.rb +++ b/config/initializers/rails_admin.rb @@ -3,6 +3,7 @@ end RailsAdmin.config do |config| + config.asset_source = :sprockets EDITABLE_MODELS = %w[ Program User diff --git a/db/migrate/20230117110948_add_service_name_to_active_storage_blobs.active_storage.rb b/db/migrate/20230117110948_add_service_name_to_active_storage_blobs.active_storage.rb new file mode 100644 index 00000000..a15c6ce8 --- /dev/null +++ b/db/migrate/20230117110948_add_service_name_to_active_storage_blobs.active_storage.rb @@ -0,0 +1,22 @@ +# This migration comes from active_storage (originally 20190112182829) +class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0] + def up + return unless table_exists?(:active_storage_blobs) + + unless column_exists?(:active_storage_blobs, :service_name) + add_column :active_storage_blobs, :service_name, :string + + if configured_service = ActiveStorage::Blob.service.name + ActiveStorage::Blob.unscoped.update_all(service_name: configured_service) + end + + change_column :active_storage_blobs, :service_name, :string, null: false + end + end + + def down + return unless table_exists?(:active_storage_blobs) + + remove_column :active_storage_blobs, :service_name + end +end diff --git a/db/migrate/20230117110949_create_active_storage_variant_records.active_storage.rb b/db/migrate/20230117110949_create_active_storage_variant_records.active_storage.rb new file mode 100644 index 00000000..94ac83af --- /dev/null +++ b/db/migrate/20230117110949_create_active_storage_variant_records.active_storage.rb @@ -0,0 +1,27 @@ +# This migration comes from active_storage (originally 20191206030411) +class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0] + def change + return unless table_exists?(:active_storage_blobs) + + # Use Active Record's configured type for primary key + create_table :active_storage_variant_records, id: primary_key_type, if_not_exists: true do |t| + t.belongs_to :blob, null: false, index: false, type: blobs_primary_key_type + t.string :variation_digest, null: false + + t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true + t.foreign_key :active_storage_blobs, column: :blob_id + end + end + + private + def primary_key_type + config = Rails.configuration.generators + config.options[config.orm][:primary_key_type] || :primary_key + end + + def blobs_primary_key_type + pkey_name = connection.primary_key(:active_storage_blobs) + pkey_column = connection.columns(:active_storage_blobs).find { |c| c.name == pkey_name } + pkey_column.bigint? ? :bigint : pkey_column.type + end +end diff --git a/db/migrate/20230117110950_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb b/db/migrate/20230117110950_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb new file mode 100644 index 00000000..93c8b85a --- /dev/null +++ b/db/migrate/20230117110950_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb @@ -0,0 +1,8 @@ +# This migration comes from active_storage (originally 20211119233751) +class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0] + def change + return unless table_exists?(:active_storage_blobs) + + change_column_null(:active_storage_blobs, :checksum, true) + end +end diff --git a/db/migrate/20230118133922_add_foreign_type_to_version_associations.rb b/db/migrate/20230118133922_add_foreign_type_to_version_associations.rb new file mode 100644 index 00000000..3778ab96 --- /dev/null +++ b/db/migrate/20230118133922_add_foreign_type_to_version_associations.rb @@ -0,0 +1,21 @@ +# This migration and AddTransactionIdColumnToVersions provide the necessary +# schema for tracking associations. +class AddForeignTypeToVersionAssociations < ActiveRecord::Migration[7.0] + def self.up + add_column :version_associations, :foreign_type, :string, index: true + remove_index :version_associations, + name: "index_version_associations_on_foreign_key" + add_index :version_associations, + %i(foreign_key_name foreign_key_id foreign_type), + name: "index_version_associations_on_foreign_key" + end + + def self.down + remove_index :version_associations, + name: "index_version_associations_on_foreign_key" + remove_column :version_associations, :foreign_type + add_index :version_associations, + %i(foreign_key_name foreign_key_id), + name: "index_version_associations_on_foreign_key" + end +end diff --git a/db/schema.rb b/db/schema.rb index 5ed853bf..dc7b4c22 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -2,16 +2,15 @@ # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2022_10_11_074011) do - +ActiveRecord::Schema[7.0].define(version: 2023_01_18_133922) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" enable_extension "uuid-ossp" @@ -21,7 +20,7 @@ t.string "record_type", null: false t.bigint "record_id", null: false t.bigint "blob_id", null: false - t.datetime "created_at", null: false + t.datetime "created_at", precision: nil, null: false t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true end @@ -32,17 +31,24 @@ t.string "content_type" t.text "metadata" t.bigint "byte_size", null: false - t.string "checksum", null: false - t.datetime "created_at", null: false + t.string "checksum" + t.datetime "created_at", precision: nil, null: false + t.string "service_name", null: false t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true end + create_table "active_storage_variant_records", force: :cascade do |t| + t.bigint "blob_id", null: false + t.string "variation_digest", null: false + t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true + end + create_table "activities", force: :cascade do |t| t.string "name", null: false t.integer "project_id", null: false t.uuid "stable_id", default: -> { "uuid_generate_v4()" }, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "code" t.string "short_name" t.index ["name", "project_id"], name: "index_activities_on_name_and_project_id", unique: true @@ -54,8 +60,8 @@ t.integer "activity_id", null: false t.integer "package_id", null: false t.uuid "stable_id", default: -> { "uuid_generate_v4()" }, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["activity_id"], name: "index_activity_packages_on_activity_id" t.index ["package_id", "activity_id"], name: "index_activity_packages_on_package_id_and_activity_id", unique: true t.index ["package_id"], name: "index_activity_packages_on_package_id" @@ -67,8 +73,8 @@ t.integer "state_id", null: false t.integer "activity_id", null: false t.uuid "stable_id", default: -> { "uuid_generate_v4()" }, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "kind", default: "data_element", null: false t.string "formula" t.string "origin", default: "dataValueSets" @@ -92,8 +98,8 @@ t.jsonb "sent" t.jsonb "status" t.integer "project_anchor_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.bigint "invoicing_job_id" t.string "sidekiq_job_ref" t.index ["invoicing_job_id"], name: "index_dhis2_logs_on_invoicing_job_id" @@ -106,8 +112,8 @@ t.jsonb "values_before" t.jsonb "values_after" t.string "whodunnit" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["dhis2_snapshot_id"], name: "index_dhis2_snapshot_changes_on_dhis2_snapshot_id" end @@ -119,8 +125,8 @@ t.integer "year", null: false t.integer "month", null: false t.string "job_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["project_anchor_id"], name: "index_dhis2_snapshots_on_project_anchor_id" end @@ -128,8 +134,8 @@ t.string "name" t.string "external_reference" t.integer "project_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.boolean "limit_snaphot_to_active_regions", default: false, null: false t.string "kind", default: "group_based" t.string "program_reference" @@ -141,8 +147,8 @@ create_table "flipper_features", force: :cascade do |t| t.string "key", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["key"], name: "index_flipper_features_on_key", unique: true end @@ -150,8 +156,8 @@ t.string "feature_key", null: false t.string "key", null: false t.string "value" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["feature_key", "key", "value"], name: "index_flipper_gates_on_feature_key_and_key_and_value", unique: true end @@ -169,8 +175,8 @@ t.string "description", null: false t.text "expression", null: false t.integer "rule_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "frequency" t.string "short_name" t.string "exportable_formula_code" @@ -182,14 +188,14 @@ t.string "orgunit_ref", null: false t.string "dhis2_period", null: false t.string "user_ref" - t.datetime "processed_at" - t.datetime "errored_at" + t.datetime "processed_at", precision: nil + t.datetime "errored_at", precision: nil t.string "last_error" t.integer "duration_ms" t.string "status", default: "enqueued" t.string "sidekiq_job_ref" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "type", default: "InvoicingJob" t.index ["project_anchor_id", "orgunit_ref", "dhis2_period", "type"], name: "index_invoicing_jobs_on_anchor_ou_period", unique: true t.index ["project_anchor_id"], name: "index_invoicing_jobs_on_project_anchor_id" @@ -199,8 +205,8 @@ t.string "name" t.integer "package_id" t.string "organisation_unit_group_ext_ref" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "kind", default: "main", null: false t.index ["package_id"], name: "index_package_entity_groups_on_package_id" end @@ -208,8 +214,8 @@ create_table "package_payment_rules", force: :cascade do |t| t.integer "package_id", null: false t.integer "payment_rule_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["package_id"], name: "index_package_payment_rules_on_package_id" t.index ["payment_rule_id"], name: "index_package_payment_rules_on_payment_rule_id" end @@ -217,8 +223,8 @@ create_table "package_states", force: :cascade do |t| t.integer "package_id" t.integer "state_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "ds_external_reference" t.string "deg_external_reference" t.string "de_external_reference" @@ -233,8 +239,8 @@ t.string "data_element_group_ext_ref", null: false t.string "frequency", null: false t.integer "project_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.uuid "stable_id", default: -> { "uuid_generate_v4()" }, null: false t.string "kind", default: "single" t.string "ogs_reference" @@ -250,27 +256,27 @@ t.integer "payment_rule_id" t.string "frequency" t.string "external_reference" - t.datetime "last_synched_at" + t.datetime "last_synched_at", precision: nil t.string "last_error" t.boolean "desynchronized" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["payment_rule_id", "frequency"], name: "index_payment_rule_datasets_on_payment_rule_id_and_frequency", unique: true t.index ["payment_rule_id"], name: "index_payment_rule_datasets_on_payment_rule_id" end create_table "payment_rules", force: :cascade do |t| t.integer "project_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "frequency", default: "quarterly", null: false t.index ["project_id"], name: "index_payment_rules_on_project_id" end create_table "programs", force: :cascade do |t| t.string "code", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "oauth_client_id" t.string "oauth_client_secret" t.index ["code"], name: "index_programs_on_code", unique: true @@ -278,8 +284,8 @@ create_table "project_anchors", force: :cascade do |t| t.integer "program_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "token" t.index ["program_id"], name: "index_project_anchors_on_program_id" end @@ -291,10 +297,10 @@ t.string "password" t.boolean "bypass_ssl", default: false t.boolean "boolean", default: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "status", default: "draft", null: false - t.datetime "publish_date" + t.datetime "publish_date", precision: nil t.integer "project_anchor_id" t.integer "original_id" t.string "cycle", default: "quarterly", null: false @@ -302,7 +308,7 @@ t.string "default_coc_reference" t.string "default_aoc_reference" t.string "qualifier" - t.datetime "publish_end_date" + t.datetime "publish_end_date", precision: nil t.string "calendar_name", default: "gregorian", null: false t.boolean "read_through_deg", default: true, null: false t.string "invoice_app_path", default: "/api/apps/ORBF2---Invoices-and-Reports/index.html", null: false @@ -315,8 +321,8 @@ t.string "name", null: false t.string "kind", null: false t.integer "package_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.integer "payment_rule_id" t.uuid "stable_id", default: -> { "uuid_generate_v4()" }, null: false t.index ["package_id"], name: "index_rules_on_package_id" @@ -325,8 +331,8 @@ create_table "states", force: :cascade do |t| t.string "name", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.integer "project_id", null: false t.string "short_name" t.index ["project_id", "name"], name: "index_states_on_project_id_and_name", unique: true @@ -337,15 +343,15 @@ t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false t.string "reset_password_token" - t.datetime "reset_password_sent_at" - t.datetime "remember_created_at" + t.datetime "reset_password_sent_at", precision: nil + t.datetime "remember_created_at", precision: nil t.integer "sign_in_count", default: 0, null: false - t.datetime "current_sign_in_at" - t.datetime "last_sign_in_at" + t.datetime "current_sign_in_at", precision: nil + t.datetime "last_sign_in_at", precision: nil t.inet "current_sign_in_ip" t.inet "last_sign_in_ip" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.integer "program_id" t.string "dhis2_user_ref" t.index ["email"], name: "index_users_on_email", unique: true @@ -357,17 +363,19 @@ t.integer "version_id" t.string "foreign_key_name", null: false t.integer "foreign_key_id" - t.index ["foreign_key_name", "foreign_key_id"], name: "index_version_associations_on_foreign_key" + t.string "foreign_type" + t.index ["foreign_key_name", "foreign_key_id", "foreign_type"], name: "index_version_associations_on_foreign_key" t.index ["version_id"], name: "index_version_associations_on_version_id" end create_table "versions", force: :cascade do |t| - t.string "item_type", null: false + t.string "item_type" + t.string "{:null=>false}" t.integer "item_id", null: false t.string "event", null: false t.string "whodunnit" t.text "old_object" - t.datetime "created_at" + t.datetime "created_at", precision: nil t.integer "transaction_id" t.jsonb "object" t.integer "program_id" @@ -380,6 +388,7 @@ end add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" + add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" add_foreign_key "activities", "projects" add_foreign_key "activity_packages", "activities" add_foreign_key "activity_packages", "packages" diff --git a/docker/.env b/docker/.env new file mode 100644 index 00000000..42b27f9d --- /dev/null +++ b/docker/.env @@ -0,0 +1,12 @@ +HESABU_VERSION=6b5a40d.local.local +REDIS_VERSION=5.0.6 +REDIS_PASSWORD=zersdfsdf +POSTGRES_VERSION=14.5 +POSTGRES_USER=orbf2 +POSTGRES_PASSWORD=12346547sdqd +POSTGRES_DB=orbf2-demo +MINIO_ROOT_USER=miniousr +MINIO_ROOT_PASSWORD=r8fgfd54g +MINIO_URL=http://minio +SECRET_KEY_BASE=a0d3846d697ce472fcbcce09bbe301482c56e41366bfa011511c82dca294b94b2de06bcb2f18d590b5603fd71e4aba33eeb81bb4f934f0b6ca8709832a8111d0 +ADMIN_PASSWORD=demoadmin diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 00000000..1a6f2d28 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,12 @@ +# docker compose + +the goal isn't not to be used as dev environment (make a seperate docker-compose.yml with hot reload) + +test the "official" docker image "as if in prod/local hosting" + +``` +./script/docker_build +cd docker +# update .env HESABU_VERSION with the docker_build values +docker-compose up +``` diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 00000000..45c9f807 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,66 @@ +version: "3" +services: + hesabu-db: + image: postgres:${POSTGRES_VERSION} + volumes: + - ./storage/db:/var/lib/postgresql/data + environment: + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: ${POSTGRES_DB} + + hesabu-redis: + image: redis:${REDIS_VERSION} + command: redis-server --requirepass ${REDIS_PASSWORD} + + hesabu-web: + image: blsq/hesabu:${HESABU_VERSION} + command: bash -c "bundle exec rake db:migrate && rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" + ports: + - "3000:3000" + depends_on: + - hesabu-db + - hesabu-redis + environment: + - REDIS_URL=redis://:${REDIS_PASSWORD}@hesabu-redis:6379 + - DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@hesabu-db:5432/${POSTGRES_DB} + - ADMIN_PASSWORD=${ADMIN_PASSWORD} + - DISABLE_FORCE_SSL=TRUE + - SECRET_KEY_BASE=${SECRET_KEY_BASE} + - RAILS_ACTIVE_STORAGE=minio + - S3_SIMULATION_ACCESS=${MINIO_ROOT_USER} + - S3_SIMULATION_BUCKET=simulation + - S3_SIMULATION_REGION=us-east-1 + - S3_SIMULATION_SECRET=${MINIO_ROOT_PASSWORD} + - S3_SIMULATION_ENDPOINT=${MINIO_URL} + - RAILS_SERVE_STATIC_FILES=true + - RAILS_ENV=production + - RACK_ENV=production + labels: + - "ofelia.enabled=true" + # job1 to flag in db jobs no more appearing in sidekiq + - "ofelia.job-exec.invoicing_jobs.schedule=@every 10m" + - "ofelia.job-exec.invoicing_jobs.command=rake invoicing_jobs:discard" + # job2 to remove from sidekiq queue duplicated jobs + - "ofelia.job-exec.duplicate_jobs.schedule=@every 11m" + - "ofelia.job-exec.duplicate_jobs.command=rake duplicate_jobs:clear" + + hesabu-worker: + image: blsq/hesabu:${HESABU_VERSION} + command: bash -c "bundle exec sidekiq -q dhis2-safe -q default" + depends_on: + - hesabu-db + - hesabu-redis + environment: + - REDIS_URL=redis://:${REDIS_PASSWORD}@hesabu-redis:6379 + - DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@hesabu-db:5432/${POSTGRES_DB} + - RAILS_ENV=production + - RACK_ENV=production + - SECRET_KEY_BASE=${SECRET_KEY_BASE} + - RAILS_ACTIVE_STORAGE=minio + - S3_SIMULATION_ACCESS=${MINIO_ROOT_USER} + - S3_SIMULATION_BUCKET=simulation + - S3_SIMULATION_REGION=us-east-1 + - S3_SIMULATION_SECRET=${MINIO_ROOT_PASSWORD} + - S3_SIMULATION_ENDPOINT=${MINIO_URL} + - RAILS_SERVE_STATIC_FILES=true diff --git a/lib/data_test/compare.rb b/lib/data_test/compare.rb index a48e70c1..61f14829 100644 --- a/lib/data_test/compare.rb +++ b/lib/data_test/compare.rb @@ -82,7 +82,8 @@ def json_diff(filename) if result.empty? Result.new(success: true) else - Result.new(success: false, key_count: [a.keys.count, b.keys.count], short: result.sample(10), full: result) + Result.new(success: false, key_count: [a.keys.count, b.keys.count], + short: result.sample(10), full: result) end end end @@ -94,11 +95,12 @@ def hash_diff(filename) a = JSON.parse(File.open(file_a).read) b = JSON.parse(File.open(file_b).read) guard_timeout do - diff = HashDiff.diff(a, b, use_lcs: false) + diff = Hashdiff.diff(a, b, use_lcs: false, numeric_tolerance: 0.000000001) if diff.empty? Result.new(success: true) else - Result.new(success: false, key_count: [a.count, b.count], short: diff.sample(10), full: diff) + Result.new(success: false, key_count: [a.count, b.count], short: diff.sample(10), + full: diff) end end end @@ -123,7 +125,8 @@ def handle_json_diff(name, result) puts " #{result.message}" puts " + Differences (first 10 out of #{result.full.count})" result.short.each do |item| - puts format(" [%s] Was: %s Is: %s Path: %s", item["op"], item["was"], item["value"], item["path"]) + puts format(" [%s] Was: %s Is: %s Path: %s", item["op"], item["was"], item["value"], + item["path"]) end end end @@ -148,7 +151,7 @@ def call handle_hash_diff(filename, hash_diff(filename)) [ %w[project yml], - ["data-compound", "yml"], + %w[data-compound yml], %w[pyramid yml] ].each do |(name, extension)| filename = subject.filename(name, extension) diff --git a/lib/data_test/file_helpers.rb b/lib/data_test/file_helpers.rb index 3805b6c4..a425cdd1 100644 --- a/lib/data_test/file_helpers.rb +++ b/lib/data_test/file_helpers.rb @@ -3,7 +3,7 @@ module DataTest module FileHelpers def read_yaml(file_path) - YAML.load_file(file_path) + YAML.unsafe_load_file(file_path) end def record_yaml(file_path, yamlable) diff --git a/lib/tasks/spec.rake b/lib/tasks/spec.rake index 101fc5df..913ca983 100644 --- a/lib/tasks/spec.rake +++ b/lib/tasks/spec.rake @@ -4,7 +4,6 @@ if Rake::Task.task_defined?("spec") Rake::Task["spec"].clear # Clear out rspec/rails tasks as well, to avoid double run Rake::Task["spec:models"].clear - Rake::Task["spec:system"].clear end namespace :spec do @@ -16,14 +15,6 @@ namespace :spec do run_commands(cmds) end - desc "Run feature/request/system specs" - task :system do - cmds = [ - %w[rspec spec --tag @type:system] - ] - run_commands(cmds) - end - desc "Run full data test" task :data_test do cmds = [ diff --git a/script/cibuild b/script/cibuild index b431ace6..b5a22c90 100755 --- a/script/cibuild +++ b/script/cibuild @@ -29,11 +29,6 @@ fi script/test status=$? -echo "[cibuild] Running system tests ..." -date "+%H:%M:%S" -SKIP_SIMPLECOV=1 bundle exec rails spec:system -status=$? - echo "[cibuild] Running data tests ..." date "+%H:%M:%S" SKIP_SIMPLECOV=1 bundle exec rails spec:data_test diff --git a/script/docker_build b/script/docker_build index 9806c08d..67b63a1d 100755 --- a/script/docker_build +++ b/script/docker_build @@ -10,7 +10,7 @@ PATCH=`echo $DESCRIBE | awk '{split($0,a,"-"); print a[3]}'` echo "version $DESCRIBE => VERSION:${VERSION} BUILD:${BUILD} PATCH:${PATCH}" -VERSION=${VERSION}"."${BUILD}"."${PATCH} +VERSION=${VERSION}"."${BUILD:-local}"."${PATCH:-local} echo "building image with tags : ${VERSION} patch ${PATCH} ($DESCRIBE)" docker build -t blsq/hesabu:$VERSION --file Dockerfile.build . diff --git a/script/setup b/script/setup index 955f1bc1..b28a59a9 100755 --- a/script/setup +++ b/script/setup @@ -33,45 +33,6 @@ if [ -z "${CI+x}" ]; then createuser --superuser --createdb hesabu-test-user fi else - # We're on CI - if ! command -v chromedriver &> /dev/null; then - echo "Chromedriver was already found" - which chromedriver - chromedriver --version - whoami - else - cat < $(/usr/bin/chromedriver --version) - - chromedriver --version - -> $(chromedriver --version) - - path - -> ${PATH} - - Me - -> $(whoami) - -STR - - if [ -f "/usr/local/bin/chromedriver" ]; then - echo "==> Using cached chromedriver" - sudo chmod +x /usr/local/share/chromedriver - sudo ln -s /usr/local/share/chromedriver /usr/local/bin/chromedriver - else - echo "==> Fetching chromedriver" - version=$(curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE) - wget -N https://chromedriver.storage.googleapis.com/$version/chromedriver_linux64.zip -P ~/ - unzip ~/chromedriver_linux64.zip -d ~/ - rm ~/chromedriver_linux64.zip - sudo mv -f ~/chromedriver /usr/local/share/ - sudo chmod +x /usr/local/share/chromedriver - sudo ln -s /usr/local/share/chromedriver /usr/local/bin/chromedriver - fi - fi export RAILS_ENV="test" export RACK_ENV="test" export CI="CIJOE" diff --git a/spec/config/lint_data_files_spec.rb b/spec/config/lint_data_files_spec.rb index a261dfec..27eaf02f 100644 --- a/spec/config/lint_data_files_spec.rb +++ b/spec/config/lint_data_files_spec.rb @@ -16,7 +16,7 @@ yaml_paths.each do |path| it "load from #{path}" do - assert YAML.load_file(path) + assert YAML.unsafe_load_file(path) end end end @@ -24,7 +24,7 @@ describe "ruby version" do it "Gemfile and .ruby_version match" do ruby_version = File.read(".ruby-version").strip - gemfile_ruby_version = File.readlines("Gemfile").grep(/^ruby/).first.gsub("ruby ", "").gsub('"', '').strip + gemfile_ruby_version = File.readlines("Gemfile").grep(/^ruby/).first.gsub("ruby ", "").gsub('"', "").strip assert ruby_version == gemfile_ruby_version, ".ruby-version (#{ruby_version}) needs to have the same version as Gemfile (#{gemfile_ruby_version})" end diff --git a/spec/controllers/setup/changes_controller_spec.rb b/spec/controllers/setup/changes_controller_spec.rb index 3553b707..3d3a71d4 100644 --- a/spec/controllers/setup/changes_controller_spec.rb +++ b/spec/controllers/setup/changes_controller_spec.rb @@ -28,8 +28,8 @@ it "should display a form for current project with a few default" do with_versioning do project - project.update_attributes(dhis2_url: "http://new.url.be") - project.entity_group.update_attributes(name: "updategroup") + project.update(dhis2_url: "http://new.url.be") + project.entity_group.update(name: "updategroup") end get :index, params: { project_id: project.id } versions = assigns(:versions) diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index d28f4cc8..42a42d74 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -44,7 +44,7 @@ name { Faker::Address.country } dhis2_url { Faker::Internet.url } user { Faker::Internet.user_name } - password { Faker::Internet.password(8) } + password { "password123" } bypass_ssl { false } end end diff --git a/spec/lib/data_test_spec.rb b/spec/lib/data_test_spec.rb index 3d712c63..8513a590 100644 --- a/spec/lib/data_test_spec.rb +++ b/spec/lib/data_test_spec.rb @@ -53,10 +53,14 @@ def result(name) it "solution" do original = artefact("#{name}-solution.json") - new = result("#{name}-solution.json") - result = JsonDiff.diff(original, new, include_was: true) + new_solution = result("#{name}-solution.json") + result = JsonDiff.diff(original, new_solution, include_was: true) + # omit type changes since dentaku upgrade (expected_float - actual_float).abs <= delta + result = result.reject do |change| + change["op"] == "replace" && (change["was"].to_f - change["value"].to_f).abs <= 0.000000001 + end unless result.empty? - puts " + original: #{original.keys.count} vs new: #{new.keys.count}" + puts " + original: #{original.keys.count} vs new: #{new_solution.keys.count}" puts " + diff (first 10): #{result.sample(10)}" end expect(result).to be_empty @@ -65,7 +69,7 @@ def result(name) it "exported_values" do original = artefact("#{name}-exported_values.json") new = result("#{name}-exported_values.json") - diff = HashDiff.diff(original, new, use_lcs: false) + diff = Hashdiff.diff(original, new, use_lcs: false, numeric_tolerance: 0.000000001) unless diff.empty? puts " + original: #{original.count} vs new: #{new.count}" puts " + diff (first 10): #{diff.sample(10)}" @@ -77,13 +81,13 @@ def result(name) else message = <<~DESC No FETCHER_S3_ACCESS and FETCHER_S3_KEY found in ENV-variables. - + These are needed to download the artefacts to verify the results with, so now skipping. DESC if ENV["CI"] - it 'has S3 configured' do - fail message + it "has S3 configured" do + raise message end else puts message diff --git a/spec/lib/font_awesome_upgrade_spec.rb b/spec/lib/font_awesome_upgrade_spec.rb deleted file mode 100644 index d2e8e209..00000000 --- a/spec/lib/font_awesome_upgrade_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -require "rails_helper" - -RSpec.describe "Font Awesome" do - it 'alerts the developer if font-awesome-rails ever goes away' do - unless defined?(FontAwesome::Rails) - message = <<~STR - font-awesome-rails is dead, long live font-awesome! - - Great, font-awesome-rails disappeared from out stack. Less great is that now no one is providing us with the font-awesome assets. So to fix that: - - - Add the font-awesome-sass gem - - Remove our icon-helper - - Look for fa5 and fix those - - Remove this test - - Profit! - STR - fail message - end - end -end diff --git a/spec/models/concerns/paper_trailed_spec.rb b/spec/models/concerns/paper_trailed_spec.rb index 6215af14..90a954f7 100644 --- a/spec/models/concerns/paper_trailed_spec.rb +++ b/spec/models/concerns/paper_trailed_spec.rb @@ -13,6 +13,7 @@ EXCEPTIONS = [ ActiveRecord::SchemaMigration, PaperTrail::Version, + PaperTrail::VersionAssociation, Version, Dhis2Log, Dhis2Snapshot, @@ -22,6 +23,10 @@ InvoicingSimulationJob, Flipper::Adapters::ActiveRecord::Feature, Flipper::Adapters::ActiveRecord::Gate, + ActiveStorage::Blob, + ActiveStorage::Attachment, + ActiveStorage::VariantRecord, + ActiveRecord::InternalMetadata ].freeze ActiveRecord::Base.descendants diff --git a/spec/models/invoicing_job_spec.rb b/spec/models/invoicing_job_spec.rb index 384305c5..38616abf 100644 --- a/spec/models/invoicing_job_spec.rb +++ b/spec/models/invoicing_job_spec.rb @@ -137,19 +137,19 @@ def action end describe "processed_after?" do - it 'true for processed and after' do + it "true for processed and after" do job = FactoryBot.build_stubbed(:invoicing_simulation_job, :processed) job.processed_at = 9.minutes.ago expect(job.processed_after?(time_stamp: 10.minutes.ago)).to eq true end - it 'false for processed and before timestamp' do + it "false for processed and before timestamp" do job = FactoryBot.build_stubbed(:invoicing_simulation_job, :processed) job.processed_at = 11.minutes.ago expect(job.processed_after?(time_stamp: 10.minutes.ago)).to eq false end - it 'false for not processed' do + it "false for not processed" do job = FactoryBot.build_stubbed(:invoicing_simulation_job, :errored) job.processed_at = 11.minutes.ago expect(job.processed_after?(time_stamp: 10.minutes.ago)).to eq false @@ -157,7 +157,7 @@ def action end describe "status" do - it 'adds scopes' do + it "adds scopes" do processed_job = FactoryBot.create(:invoicing_simulation_job, :processed) errored_job = FactoryBot.create(:invoicing_simulation_job, :errored) new_job = FactoryBot.create(:invoicing_simulation_job) @@ -166,7 +166,7 @@ def action expect(InvoicingJob.enqueued.pluck(:id)).to eq([new_job.id]) end - it 'complains on invalid state' do + it "complains on invalid state" do new_job = FactoryBot.create(:invoicing_simulation_job) expect { @@ -174,7 +174,7 @@ def action }.to raise_error(ArgumentError) end - it 'defaults to enqueued' do + it "defaults to enqueued" do new_job = FactoryBot.create(:invoicing_simulation_job) expect(new_job.enqueued?).to eq(true) end diff --git a/spec/models/periods/year_quarter_spec.rb b/spec/models/periods/year_quarter_spec.rb index 693f38df..62a4769d 100644 --- a/spec/models/periods/year_quarter_spec.rb +++ b/spec/models/periods/year_quarter_spec.rb @@ -5,19 +5,19 @@ let(:year_quarter) { Periods::YearQuarter.from_yyyyqq(yyyyqq) } let(:last_quarter) { Periods::YearQuarter.from_yyyyqq("2016Q4") } - describe 'fails fast' do + describe "fails fast" do it "when nil" do - expect {Periods::YearQuarter.new(nil)}.to raise_error(ArgumentError, "Argument yyyyqq can't be nil") + expect { Periods::YearQuarter.new(nil) }.to raise_error(ArgumentError, "Argument yyyyqq can't be nil") end it "when year is a alpha" do - expect {Periods::YearQuarter.new("yearQ1")}.to raise_error('invalid value for Integer(): "year"') + expect { Periods::YearQuarter.new("yearQ1") }.to raise_error('invalid value for Integer(): "year"') end it "when no Q for quarter" do - expect {Periods::YearQuarter.new("201601")}.to raise_error("no a valid quarter number for '201601'") + expect { Periods::YearQuarter.new("201601") }.to raise_error("no a valid quarter number for '201601'") end it "when alha for Q for quarter" do - expect {Periods::YearQuarter.new("2016Qa")}.to raise_error('invalid value for Integer(): "a"') + expect { Periods::YearQuarter.new("2016Qa") }.to raise_error('invalid value for Integer(): "a"') end end @@ -58,7 +58,7 @@ expect(Periods::YearQuarter.from_year_month(2016, 12).to_s).to eq "2016Q4" end it "should be immutable" do - expect { year_quarter.months.delete_at(1) }.to raise_error("can't modify frozen Array") + expect { year_quarter.months.delete_at(1) }.to raise_error(FrozenError) end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 4c16ea96..12a81c0d 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: projects @@ -52,16 +53,16 @@ it "should validate url " do expect(project.valid?).to eq true - project.dhis2_url = "http:// bad : userexport@/dev:456.url" + project.dhis2_url = "http://:456.url" expect(project.valid?).to eq false end describe "#verify_connection" do it "should validate url before testing" do - project.dhis2_url = "http:// bad : userexport@/dev:456.url" + project.dhis2_url = "http://bad:userexport@/dev:456.url" expect(project.verify_connection).to eq( status: :ko, - message: "Dhis2 url is not an url" + message: "no host component for URI" ) end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 677dda90..273c7f79 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -55,15 +55,6 @@ # The different available types are documented in the features, such as in # https://relishapp.com/rspec/rspec-rails/docs config.infer_spec_type_from_file_location! - - config.before(:each, type: :system) do - if ENV["SHOW_BROWSER"] - # This can be handy when diagnosing system tests that break - driven_by :selenium, using: :chrome, screen_size: [1400, 1400] - else - driven_by :headless_chrome - end - end end Shoulda::Matchers.configure do |config| diff --git a/spec/services/project_factory_spec.rb b/spec/services/project_factory_spec.rb index 97f699ab..97bdad46 100644 --- a/spec/services/project_factory_spec.rb +++ b/spec/services/project_factory_spec.rb @@ -25,7 +25,9 @@ PaperTrail::Version, PaperTrail::VersionAssociation, Flipper::Adapters::ActiveRecord::Feature, - Flipper::Adapters::ActiveRecord::Gate + Flipper::Adapters::ActiveRecord::Gate, + ActiveRecord::InternalMetadata, + ActiveStorage::VariantRecord ].freeze NON_PROJECT_AR = [ @@ -78,7 +80,7 @@ end old_activity_ids = project.activities.map(&:id) - formula_mappings_with_bad_activities = new_draft.packages.flat_map { |p| p.activity_rule.formulas.flat_map(&:formula_mappings)}.select { |fm| old_activity_ids.include?(fm.activity_id) } + formula_mappings_with_bad_activities = new_draft.packages.flat_map { |p| p.activity_rule.formulas.flat_map(&:formula_mappings) }.select { |fm| old_activity_ids.include?(fm.activity_id) } expect(formula_mappings_with_bad_activities).to(eq([])) end diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb deleted file mode 100644 index b10a2f40..00000000 --- a/spec/support/capybara.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -Capybara.register_driver :headless_chrome do |app| - capabilities = Selenium::WebDriver::Remote::Capabilities.chrome( - # This enables access to logs with `page.driver.manage.get_log(:browser)` - loggingPrefs: { - browser: "ALL", - client: "ALL", - driver: "ALL", - server: "ALL" - } - ) - - options = Selenium::WebDriver::Chrome::Options.new - options.add_argument("window-size=1400,1400") - - # Chrome won't work properly in a Docker container in sandbox mode - # because the user namespace is not enabled in the container by default - options.add_argument("no-sandbox") - - # Run headless by default unless CHROME_HEADLESS specified - options.add_argument("headless") unless ENV["CHROME_HEADLESS"] =~ /^(false|no|0)$/i - - # Disable /dev/shm use in CI. See https://gitlab.com/gitlab-org/gitlab-ee/issues/4252 - options.add_argument("disable-dev-shm-usage") if ENV["CI"] || ENV["CI_SERVER"] - - Capybara::Selenium::Driver.new( - app, - browser: :chrome, - desired_capabilities: capabilities, - options: options - ) -end diff --git a/spec/system/admin_dashboard_spec.rb b/spec/system/admin_dashboard_spec.rb deleted file mode 100644 index 11ec7568..00000000 --- a/spec/system/admin_dashboard_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true - -require "rails_helper" - -describe "Rails Admin" do - before do - WebMock.disable_net_connect!(allow_localhost: true) - end - - it "can load the dashboard" do - visit rails_admin.dashboard_url - expect(page).to have_content "Scorpio Admin" - end -end diff --git a/spec/workers/invoice_for_project_anchor_worker_spec.rb b/spec/workers/invoice_for_project_anchor_worker_spec.rb index 49566fbd..a869c444 100644 --- a/spec/workers/invoice_for_project_anchor_worker_spec.rb +++ b/spec/workers/invoice_for_project_anchor_worker_spec.rb @@ -12,7 +12,7 @@ let!(:project) do project = full_project project.save! - project.update_attributes(read_through_deg: false) + project.update(read_through_deg: false) user.save! user.program = program @@ -202,7 +202,7 @@ let(:org_unit_ids) do %w[AhnK8hb3JWm BLVKubgVxkF Bift1B4gjru Bq5nb7UAEGd C9uduqDZr9d DSBXsRQSXUW DmaLM8WYmWv ENHOJz3UH5L Ea3j0kUvyWg EmTN0L4EAVi GvFqTavdpGE HPg74Rr7UWp IXJg79fclDm ImspTQPwCqd JLKGG67z7oj JNJIPX9DfaW KIUCimTXf8Q KKkLOTpMXGV KuR0y0h0mOM LV2b3vaLRl1 LaxJ6CD2DHq Ls2ESQONh9S M2qEv692lS6 M721NHGtdZV O6uvpzGd5pu OuwX8H2CcRO PD1fqyvJssC PLoeN9CaL7z PMa2VCrupOd PQZJPIpTepd Qw7c6Ckb0XC QywkxFudXrC RUCp6OaTSAD T2Cn45nBY0u TEQlaapDQoK TQkG0sX9nca U6Kr7Gtpidn Uo4cyJwAhTW VCtF1DbspR5 VGAFxBXz16y Vnc2qIRLbyw Vth0fbpFcsO W5fN3G6y1VI XEyIRFd9pct XJ6DqDkMlPv at6UHUQatSo bM4Ky73uMao bPHn9IgjKLC bVZTNrnfn9G cDw53Ej8rju cM2BKSrj9F9 cZtKKa9eJZ3 cgqkFdShPzg ctfiYW0ePJ8 eIQbndfxQMb fXT1scbEObM fdc6uOvgoji gmen7SXL9CU jCnyQOKQBFX jUb8gELQApl jmIPBj66vD6 kBP1UvZpsNj kJq2mPyFEHo kLNQT4KQ9hT kMTHqMgenme lc3eMKXaEfw mTNOoGXuC39 nCh5dBoJVNw nV3OkyzF4US nq7F0t1Pz6t qhqAxPSTUXp qtr8GGlm4gg roQ2l7TX0eZ tHUYjt9cU6h u6ZGNI8yUmt uNEhNuBUr0i vRC0stJ5y9Q vn9KJsLyP5f vv1QJFONsT6 wNYYRm2c9EK wicmjKI3xiP yP2nhllbQPh] end - let(:dataset_ext_ids) { ["ds-0", "ds-1", "ds-2"] } + let(:dataset_ext_ids) { %w[ds-0 ds-1 ds-2] } let(:periods) { %w[2014July 2015 201501 201502 201503 2015Q1] } it "should perform for sub contracted entities pattern with new engine" do @@ -272,7 +272,7 @@ let(:org_unit_ids) do %w[AhnK8hb3JWm BLVKubgVxkF Bift1B4gjru Bq5nb7UAEGd C9uduqDZr9d DSBXsRQSXUW DmaLM8WYmWv ENHOJz3UH5L Ea3j0kUvyWg EmTN0L4EAVi GvFqTavdpGE HPg74Rr7UWp IXJg79fclDm ImspTQPwCqd JLKGG67z7oj JNJIPX9DfaW KIUCimTXf8Q KKkLOTpMXGV KuR0y0h0mOM LV2b3vaLRl1 LaxJ6CD2DHq Ls2ESQONh9S M2qEv692lS6 M721NHGtdZV O6uvpzGd5pu OuwX8H2CcRO PD1fqyvJssC PLoeN9CaL7z PMa2VCrupOd PQZJPIpTepd Qw7c6Ckb0XC QywkxFudXrC RUCp6OaTSAD T2Cn45nBY0u TEQlaapDQoK TQkG0sX9nca U6Kr7Gtpidn Uo4cyJwAhTW VCtF1DbspR5 VGAFxBXz16y Vnc2qIRLbyw Vth0fbpFcsO W5fN3G6y1VI XEyIRFd9pct XJ6DqDkMlPv at6UHUQatSo bM4Ky73uMao bPHn9IgjKLC bVZTNrnfn9G cDw53Ej8rju cM2BKSrj9F9 cZtKKa9eJZ3 cgqkFdShPzg ctfiYW0ePJ8 eIQbndfxQMb fXT1scbEObM fdc6uOvgoji gmen7SXL9CU jCnyQOKQBFX jUb8gELQApl jmIPBj66vD6 kBP1UvZpsNj kJq2mPyFEHo kLNQT4KQ9hT kMTHqMgenme lc3eMKXaEfw mTNOoGXuC39 nCh5dBoJVNw nV3OkyzF4US nq7F0t1Pz6t qhqAxPSTUXp qtr8GGlm4gg roQ2l7TX0eZ tHUYjt9cU6h u6ZGNI8yUmt uNEhNuBUr0i vRC0stJ5y9Q vn9KJsLyP5f vv1QJFONsT6 wNYYRm2c9EK wicmjKI3xiP yP2nhllbQPh] end - let(:dataset_ext_ids) { ["ds-0", "ds-1", "ds-2"] } + let(:dataset_ext_ids) { %w[ds-0 ds-1 ds-2] } let(:periods) { %w[2014July 2015 201501 201502 201503 2015Q1] } it "should perform for sub contracted entities pattern with new engine" do @@ -340,14 +340,14 @@ describe "retry logic" do it "doesn't fail if equation fails" do - expect(InvoicingJob).to receive(:execute) { raise Hesabu::Error.new("In equation and so on")} + expect(InvoicingJob).to receive(:execute) { raise Hesabu::Error, "In equation and so on" } expect { worker.perform(project.project_anchor.id, 2015, 1, ["Rp268JB6Ne4"]) }.to_not raise_error end - it 'fails if hesabu error other than equation fails' do - expect(InvoicingJob).to receive(:execute) { raise Hesabu::Error.new("Some error in Hesabu")} + it "fails if hesabu error other than equation fails" do + expect(InvoicingJob).to receive(:execute) { raise Hesabu::Error, "Some error in Hesabu" } expect { worker.perform(project.project_anchor.id, 2015, 1, ["Rp268JB6Ne4"]) @@ -376,8 +376,7 @@ def stub_export_values(expected_fixture) end def sorted_datavalues(json) - sorted = json["dataValues"].sort_by { |e| [e["dataElement"], e["orgUnit"], e["period"]] } + json["dataValues"].sort_by { |e| [e["dataElement"], e["orgUnit"], e["period"]] } # Rails.logger.info "sorted\n #{sorted}\n\n\n" - sorted end end