From c891909e519201b62e4d85d956d177419642a927 Mon Sep 17 00:00:00 2001 From: kudakwashe SIziva Date: Wed, 1 Apr 2026 14:58:01 +0200 Subject: [PATCH 01/10] upgrade ruby 4 and rails 8 --- Gemfile | 45 +++--- Gemfile.lock | 388 ++++++++++++++++++++++++++------------------------- 2 files changed, 220 insertions(+), 213 deletions(-) diff --git a/Gemfile b/Gemfile index d127b71..7d79458 100644 --- a/Gemfile +++ b/Gemfile @@ -1,32 +1,28 @@ source "https://rubygems.org" -ruby "3.2.10" +ruby "4.0.1" -gem "rails", "~> 7.2", ">= 7.2.3" -gem "bootsnap", require: false -gem "rack-cors" -gem "shoryuken", "~> 7.0" -gem "aws-sdk-sqs", "~> 1.3" -gem "lograge", "~> 0.11.2" -gem "logstash-event", "~> 1.2", ">= 1.2.02" -gem "logstash-logger", "~> 0.26.1" -gem "mysql2", "~> 0.5.3" -gem "dotenv" -gem "sentry-ruby" -gem "sentry-rails" -gem "elasticsearch", "~> 7.17", ">= 7.17.10" -gem "elasticsearch-model", "~> 7.2.1", ">= 7.2.1", require: "elasticsearch/model" -gem "elasticsearch-rails", "~> 7.2.1", ">= 7.2.1" -gem "elasticsearch-transport", "~> 7.17", ">= 7.17.10" +gem "rails", "~> 8.1", ">= 8.1.2.1" +gem "bootsnap", "~> 1.23", require: false +gem "rack-cors", "~> 3.0" +gem "shoryuken", "~> 7.0", ">= 7.0.1" +gem "aws-sdk-sqs", "~> 1.112" +gem "lograge", "~> 0.14.0" +gem "logstash-logger", "~> 1.0" +gem "mysql2", "~> 0.5.7" +gem "dotenv", "~> 3.2" +gem "sentry-ruby", "~> 6.5" +gem "sentry-rails", "~> 6.5" +gem "elasticsearch", "~> 8.19", ">= 8.19.3" +gem "elasticsearch-model", "~> 8.0", ">= 8.0.1", require: "elasticsearch/model" +gem "elasticsearch-rails", "~> 8.0", ">= 8.0.1" +gem "elastic-transport", "~> 8.0", ">= 8.0.1" gem "git", "~> 1.5" -gem "faraday", "~> 2.9" -gem "faraday_middleware-aws-sigv4", "~> 0.3.0" -gem "faraday-excon" +gem "faraday", "~> 2.14", ">= 2.14.1" +gem "faraday_middleware-aws-sigv4", "~> 1.0", ">= 1.0.1" +gem "faraday-excon", "~> 2.4" gem "uuid", "~> 2.3", ">= 2.3.9" -gem "oj", "~> 3.16", ">= 3.16.11" - -# This gem will allow us to write tests without the need for a database -gem "activerecord-nulldb-adapter", "~> 1.1", ">= 1.1.1" +gem "oj", "~> 3.16", ">= 3.16.16" gem "parallel", "~> 1.27" group :development, :test do @@ -48,4 +44,5 @@ group :test do gem "simplecov", require: false gem "shoulda-matchers" gem "coveralls_reborn", require: false + gem "activerecord-nulldb-adapter", "~> 1.2", ">= 1.2.2" # This gem will allow us to write tests without the need for a database end diff --git a/Gemfile.lock b/Gemfile.lock index 67f88f4..ee2826f 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,87 +1,88 @@ GEM remote: https://rubygems.org/ specs: - actioncable (7.2.3) - actionpack (= 7.2.3) - activesupport (= 7.2.3) + action_text-trix (2.1.18) + railties + actioncable (8.1.3) + actionpack (= 8.1.3) + activesupport (= 8.1.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (7.2.3) - actionpack (= 7.2.3) - activejob (= 7.2.3) - activerecord (= 7.2.3) - activestorage (= 7.2.3) - activesupport (= 7.2.3) + actionmailbox (8.1.3) + actionpack (= 8.1.3) + activejob (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) mail (>= 2.8.0) - actionmailer (7.2.3) - actionpack (= 7.2.3) - actionview (= 7.2.3) - activejob (= 7.2.3) - activesupport (= 7.2.3) + actionmailer (8.1.3) + actionpack (= 8.1.3) + actionview (= 8.1.3) + activejob (= 8.1.3) + activesupport (= 8.1.3) mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (7.2.3) - actionview (= 7.2.3) - activesupport (= 7.2.3) - cgi + actionpack (8.1.3) + actionview (= 8.1.3) + activesupport (= 8.1.3) nokogiri (>= 1.8.5) - racc - rack (>= 2.2.4, < 3.3) + rack (>= 2.2.4) rack-session (>= 1.0.1) rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) useragent (~> 0.16) - actiontext (7.2.3) - actionpack (= 7.2.3) - activerecord (= 7.2.3) - activestorage (= 7.2.3) - activesupport (= 7.2.3) + actiontext (8.1.3) + action_text-trix (~> 2.1.15) + actionpack (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.2.3) - activesupport (= 7.2.3) + actionview (8.1.3) + activesupport (= 8.1.3) builder (~> 3.1) - cgi erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (7.2.3) - activesupport (= 7.2.3) + activejob (8.1.3) + activesupport (= 8.1.3) globalid (>= 0.3.6) - activemodel (7.2.3) - activesupport (= 7.2.3) - activerecord (7.2.3) - activemodel (= 7.2.3) - activesupport (= 7.2.3) + activemodel (8.1.3) + activesupport (= 8.1.3) + activerecord (8.1.3) + activemodel (= 8.1.3) + activesupport (= 8.1.3) timeout (>= 0.4.0) - activerecord-nulldb-adapter (1.1.1) - activerecord (>= 6.0, < 8.1) - activestorage (7.2.3) - actionpack (= 7.2.3) - activejob (= 7.2.3) - activerecord (= 7.2.3) - activesupport (= 7.2.3) + activerecord-nulldb-adapter (1.2.2) + activerecord (>= 6.1, < 8.2) + activestorage (8.1.3) + actionpack (= 8.1.3) + activejob (= 8.1.3) + activerecord (= 8.1.3) + activesupport (= 8.1.3) marcel (~> 1.0) - activesupport (7.2.3) + activesupport (8.1.3) base64 - benchmark (>= 0.3) bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + json logger (>= 1.4.2) minitest (>= 5.1) securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) - addressable (2.8.7) - public_suffix (>= 2.0.2, < 7.0) - ast (2.4.2) + uri (>= 0.13.1) + addressable (2.8.9) + public_suffix (>= 2.0.2, < 8.0) + ast (2.4.3) aws-eventstream (1.4.0) - aws-partitions (1.1206.0) - aws-sdk-core (3.241.4) + aws-partitions (1.1233.0) + aws-sdk-core (3.244.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) @@ -89,101 +90,101 @@ GEM bigdecimal jmespath (~> 1, >= 1.6.1) logger - aws-sdk-sqs (1.93.0) - aws-sdk-core (~> 3, >= 3.216.0) + aws-sdk-sqs (1.112.0) + aws-sdk-core (~> 3, >= 3.244.0) aws-sigv4 (~> 1.5) aws-sigv4 (1.12.1) aws-eventstream (~> 1, >= 1.0.2) base64 (0.3.0) - benchmark (0.5.0) - bigdecimal (4.0.1) - bootsnap (1.18.4) + bigdecimal (4.1.0) + bootsnap (1.23.0) msgpack (~> 1.2) - brakeman (7.0.0) + brakeman (8.0.4) racc builder (3.3.0) - bundler-audit (0.9.2) - bundler (>= 1.2.0, < 3) + bundler-audit (0.9.3) + bundler (>= 1.2.0) thor (~> 1.0) - cgi (0.5.1) concurrent-ruby (1.3.6) connection_pool (3.0.2) - coveralls_reborn (0.28.0) + coveralls_reborn (0.29.0) simplecov (~> 0.22.0) term-ansicolor (~> 1.7) thor (~> 1.2) tins (~> 1.32) crass (1.0.6) date (3.5.1) - debug (1.10.0) + debug (1.11.1) irb (~> 1.10) reline (>= 0.3.8) - diff-lcs (1.6.0) + diff-lcs (1.6.2) docile (1.4.1) - dotenv (3.1.7) + dotenv (3.2.0) drb (2.2.3) - elasticsearch (7.17.11) - elasticsearch-api (= 7.17.11) - elasticsearch-transport (= 7.17.11) - elasticsearch-api (7.17.11) + elastic-transport (8.4.1) + faraday (< 3) + multi_json + elasticsearch (8.19.3) + elastic-transport (~> 8.3) + elasticsearch-api (= 8.19.3) + ostruct + elasticsearch-api (8.19.3) multi_json - elasticsearch-model (7.2.1) + elasticsearch-model (8.0.1) activesupport (> 3) - elasticsearch (~> 7) + elasticsearch (~> 8) hashie - elasticsearch-rails (7.2.1) - elasticsearch-transport (7.17.11) - base64 - faraday (>= 1, < 3) - multi_json - erb (6.0.1) + elasticsearch-rails (8.0.1) + erb (6.0.2) erubi (1.13.1) - excon (1.2.5) + excon (1.4.2) logger - factory_bot (6.5.1) + factory_bot (6.5.6) activesupport (>= 6.1.0) - factory_bot_rails (6.4.4) + factory_bot_rails (6.5.1) factory_bot (~> 6.5) - railties (>= 5.0.0) - faraday (2.13.0) + railties (>= 6.1.0) + faraday (2.14.1) faraday-net_http (>= 2.0, < 3.5) json logger - faraday-excon (2.3.0) + faraday-excon (2.4.0) excon (>= 1.0.0) faraday (>= 2.11.0, < 3) - faraday-net_http (3.4.0) - net-http (>= 0.5.0) - faraday_middleware-aws-sigv4 (0.3.0) + faraday-net_http (3.4.2) + net-http (~> 0.5) + faraday_middleware-aws-sigv4 (1.0.1) aws-sigv4 (~> 1.0) - faraday (>= 0.15) + faraday (>= 2.0, < 3) git (1.19.1) addressable (~> 2.8) rchardet (~> 1.8) globalid (1.3.0) activesupport (>= 6.1) - hashie (5.0.0) + hashie (5.1.0) + logger i18n (1.14.8) concurrent-ruby (~> 1.0) io-console (0.8.2) - irb (1.16.0) + irb (1.17.0) pp (>= 0.6.0) + prism (>= 1.3.0) rdoc (>= 4.0.0) reline (>= 0.4.2) jmespath (1.6.2) - json (2.10.2) - language_server-protocol (3.17.0.4) + json (2.19.3) + language_server-protocol (3.17.0.5) lint_roller (1.1.0) logger (1.7.0) - lograge (0.11.2) + lograge (0.14.0) actionpack (>= 4) activesupport (>= 4) railties (>= 4) request_store (~> 1.0) logstash-event (1.2.02) - logstash-logger (0.26.1) + logstash-logger (1.0.0) logstash-event (~> 1.2) - loofah (2.25.0) + loofah (2.25.1) crass (~> 1.0.2) nokogiri (>= 1.12.0) macaddr (1.7.2) @@ -196,14 +197,17 @@ GEM net-smtp marcel (1.1.0) mini_mime (1.1.5) - minitest (6.0.1) + minitest (6.0.3) + drb (~> 2.0) prism (~> 1.5) + mize (0.6.1) msgpack (1.8.0) - multi_json (1.15.0) - mysql2 (0.5.6) - net-http (0.6.0) - uri - net-imap (0.6.2) + multi_json (1.19.1) + mysql2 (0.5.7) + bigdecimal + net-http (0.9.1) + uri (>= 0.11.1) + net-imap (0.6.3) date net-protocol net-pop (0.1.2) @@ -213,32 +217,33 @@ GEM net-smtp (0.5.1) net-protocol nio4r (2.7.5) - nokogiri (1.19.0-aarch64-linux-gnu) + nokogiri (1.19.2-aarch64-linux-gnu) racc (~> 1.4) - nokogiri (1.19.0-arm64-darwin) + nokogiri (1.19.2-arm64-darwin) racc (~> 1.4) - nokogiri (1.19.0-x86_64-linux-gnu) + nokogiri (1.19.2-x86_64-linux-gnu) racc (~> 1.4) - oj (3.16.11) + oj (3.16.16) bigdecimal (>= 3.0) ostruct (>= 0.2) - ostruct (0.6.1) + ostruct (0.6.3) parallel (1.27.0) - parser (3.3.7.1) + parser (3.3.11.1) ast (~> 2.4.1) racc pp (0.6.3) prettyprint prettyprint (0.2.0) - prism (1.8.0) + prism (1.9.0) psych (5.3.1) date stringio - public_suffix (6.0.1) + public_suffix (7.0.5) racc (1.8.1) - rack (3.2.4) - rack-cors (2.0.2) - rack (>= 2.0.0) + rack (3.2.6) + rack-cors (3.0.0) + logger + rack (>= 3.0.14) rack-session (2.1.1) base64 (>= 0.1.0) rack (>= 3.0.0) @@ -246,31 +251,30 @@ GEM rack (>= 1.3) rackup (2.3.1) rack (>= 3) - rails (7.2.3) - actioncable (= 7.2.3) - actionmailbox (= 7.2.3) - actionmailer (= 7.2.3) - actionpack (= 7.2.3) - actiontext (= 7.2.3) - actionview (= 7.2.3) - activejob (= 7.2.3) - activemodel (= 7.2.3) - activerecord (= 7.2.3) - activestorage (= 7.2.3) - activesupport (= 7.2.3) + rails (8.1.3) + actioncable (= 8.1.3) + actionmailbox (= 8.1.3) + actionmailer (= 8.1.3) + actionpack (= 8.1.3) + actiontext (= 8.1.3) + actionview (= 8.1.3) + activejob (= 8.1.3) + activemodel (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) bundler (>= 1.15.0) - railties (= 7.2.3) + railties (= 8.1.3) rails-dom-testing (2.3.0) activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.2) - loofah (~> 2.21) + rails-html-sanitizer (1.7.0) + loofah (~> 2.25) nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) - railties (7.2.3) - actionpack (= 7.2.3) - activesupport (= 7.2.3) - cgi + railties (8.1.3) + actionpack (= 8.1.3) + activesupport (= 8.1.3) irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) @@ -279,22 +283,24 @@ GEM zeitwerk (~> 2.6) rainbow (3.1.1) rake (13.3.1) - rchardet (1.9.0) - rdoc (7.1.0) + rchardet (1.10.0) + rdoc (7.2.0) erb psych (>= 4.0.0) tsort - regexp_parser (2.10.0) + readline (0.0.4) + reline + regexp_parser (2.11.3) reline (0.6.3) io-console (~> 0.5) request_store (1.7.0) rack (>= 1.4) - rspec-core (3.13.3) + rspec-core (3.13.6) rspec-support (~> 3.13.0) - rspec-expectations (3.13.3) + rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-mocks (3.13.2) + rspec-mocks (3.13.8) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-rails (7.0.2) @@ -305,8 +311,8 @@ GEM rspec-expectations (~> 3.13) rspec-mocks (~> 3.13) rspec-support (~> 3.13) - rspec-support (3.13.2) - rubocop (1.73.2) + rspec-support (3.13.7) + rubocop (1.86.0) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) @@ -314,70 +320,75 @@ GEM parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 2.9.3, < 3.0) - rubocop-ast (>= 1.38.0, < 2.0) + rubocop-ast (>= 1.49.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.38.1) - parser (>= 3.3.1.0) - rubocop-factory_bot (2.26.1) - rubocop (~> 1.61) - rubocop-performance (1.24.0) + rubocop-ast (1.49.1) + parser (>= 3.3.7.2) + prism (~> 1.7) + rubocop-factory_bot (2.28.0) + lint_roller (~> 1.1) + rubocop (~> 1.72, >= 1.72.1) + rubocop-performance (1.26.1) lint_roller (~> 1.1) - rubocop (>= 1.72.1, < 2.0) - rubocop-ast (>= 1.38.0, < 2.0) - rubocop-rails (2.30.3) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.47.1, < 2.0) + rubocop-rails (2.34.3) activesupport (>= 4.2.0) lint_roller (~> 1.1) rack (>= 1.1) - rubocop (>= 1.72.1, < 2.0) - rubocop-ast (>= 1.38.0, < 2.0) - rubocop-rspec (3.5.0) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.44.0, < 2.0) + rubocop-rspec (3.9.0) lint_roller (~> 1.1) - rubocop (~> 1.72, >= 1.72.1) - rubocop-rspec_rails (2.31.0) + rubocop (~> 1.81) + rubocop-rspec_rails (2.32.0) lint_roller (~> 1.1) rubocop (~> 1.72, >= 1.72.1) rubocop-rspec (~> 3.5) - rubocop-shopify (2.16.0) + rubocop-shopify (2.18.0) rubocop (~> 1.62) ruby-progressbar (1.13.0) securerandom (0.4.1) - sentry-rails (5.23.0) - railties (>= 5.0) - sentry-ruby (~> 5.23.0) - sentry-ruby (5.23.0) + sentry-rails (6.5.0) + railties (>= 5.2.0) + sentry-ruby (~> 6.5.0) + sentry-ruby (6.5.0) bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) - shoryuken (7.0.0) + logger + shoryuken (7.0.1) aws-sdk-sqs (>= 1.66.0) concurrent-ruby thor zeitwerk (~> 2.6) - shoulda-matchers (6.5.0) - activesupport (>= 5.2.0) + shoulda-matchers (7.0.1) + activesupport (>= 7.1) simplecov (0.22.0) docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) - simplecov-html (0.13.1) + simplecov-html (0.13.2) simplecov_json_formatter (0.1.4) stringio (3.2.0) sync (0.5.0) systemu (2.6.5) - term-ansicolor (1.11.2) - tins (~> 1.0) + term-ansicolor (1.11.3) + tins (~> 1) thor (1.5.0) - timeout (0.6.0) - tins (1.38.0) + timeout (0.6.1) + tins (1.52.0) bigdecimal + mize (~> 0.6) + readline sync tsort (0.2.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (3.1.4) - unicode-emoji (~> 4.0, >= 4.0.4) - unicode-emoji (4.0.4) - uri (1.0.3) + unicode-display_width (3.2.0) + unicode-emoji (~> 4.1) + unicode-emoji (4.2.0) + uri (1.1.1) useragent (0.16.11) uuid (2.3.9) macaddr (~> 1.0) @@ -385,7 +396,7 @@ GEM base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - zeitwerk (2.7.4) + zeitwerk (2.7.5) PLATFORMS aarch64-linux @@ -393,31 +404,30 @@ PLATFORMS x86_64-linux DEPENDENCIES - activerecord-nulldb-adapter (~> 1.1, >= 1.1.1) - aws-sdk-sqs (~> 1.3) - bootsnap + activerecord-nulldb-adapter (~> 1.2, >= 1.2.2) + aws-sdk-sqs (~> 1.112) + bootsnap (~> 1.23) brakeman bundler-audit coveralls_reborn debug - dotenv - elasticsearch (~> 7.17, >= 7.17.10) - elasticsearch-model (~> 7.2.1, >= 7.2.1) - elasticsearch-rails (~> 7.2.1, >= 7.2.1) - elasticsearch-transport (~> 7.17, >= 7.17.10) + dotenv (~> 3.2) + elastic-transport (~> 8.0, >= 8.0.1) + elasticsearch (~> 8.19, >= 8.19.3) + elasticsearch-model (~> 8.0, >= 8.0.1) + elasticsearch-rails (~> 8.0, >= 8.0.1) factory_bot_rails - faraday (~> 2.9) - faraday-excon - faraday_middleware-aws-sigv4 (~> 0.3.0) + faraday (~> 2.14, >= 2.14.1) + faraday-excon (~> 2.4) + faraday_middleware-aws-sigv4 (~> 1.0, >= 1.0.1) git (~> 1.5) - lograge (~> 0.11.2) - logstash-event (~> 1.2, >= 1.2.02) - logstash-logger (~> 0.26.1) - mysql2 (~> 0.5.3) - oj (~> 3.16, >= 3.16.11) + lograge (~> 0.14.0) + logstash-logger (~> 1.0) + mysql2 (~> 0.5.7) + oj (~> 3.16, >= 3.16.16) parallel (~> 1.27) - rack-cors - rails (~> 7.2, >= 7.2.3) + rack-cors (~> 3.0) + rails (~> 8.1, >= 8.1.2.1) rspec-rails (~> 7.0.0) rubocop rubocop-factory_bot @@ -426,15 +436,15 @@ DEPENDENCIES rubocop-rspec rubocop-rspec_rails rubocop-shopify - sentry-rails - sentry-ruby - shoryuken (~> 7.0) + sentry-rails (~> 6.5) + sentry-ruby (~> 6.5) + shoryuken (~> 7.0, >= 7.0.1) shoulda-matchers simplecov uuid (~> 2.3, >= 2.3.9) RUBY VERSION - ruby 3.2.10p266 + ruby 4.0.1p0 BUNDLED WITH 2.6.9 From d3c3249cae6f3ed1c5acc6f38e67475d69e5517d Mon Sep 17 00:00:00 2001 From: kudakwashe SIziva Date: Wed, 1 Apr 2026 15:15:29 +0200 Subject: [PATCH 02/10] remove git gem and restructure how we get version, and add security check in ci --- .github/workflows/build.yml | 2 ++ .github/workflows/parallel_ci.yml | 7 ++++++- .github/workflows/rubocop.yml | 2 +- Dockerfile | 5 ++++- Gemfile | 1 - Gemfile.lock | 8 -------- config/initializers/_version.rb | 14 +------------- 7 files changed, 14 insertions(+), 25 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 17a95dd..85b0031 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,5 +50,7 @@ jobs: tags: | ${{ inputs.image_name }}:${{ inputs.image_tag }} ghcr.io/${{ inputs.image_name }}:${{ inputs.image_tag }} + build-args: | + GIT_TAG=${{ inputs.image_tag }} cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache diff --git a/.github/workflows/parallel_ci.yml b/.github/workflows/parallel_ci.yml index 448e5ac..7421e14 100644 --- a/.github/workflows/parallel_ci.yml +++ b/.github/workflows/parallel_ci.yml @@ -25,10 +25,15 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: "3.2.10" + ruby-version: "4.0.1" bundler-cache: true - name: Run Specs run: bundle exec rspec env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} + + - name: Security Check + run: | + bundle exec bundler-audit check --update + bundle exec brakeman --no-pager diff --git a/.github/workflows/rubocop.yml b/.github/workflows/rubocop.yml index 505ad66..cb95a9c 100644 --- a/.github/workflows/rubocop.yml +++ b/.github/workflows/rubocop.yml @@ -12,7 +12,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 3.2.10 + ruby-version: 4.0.1 - name: Cache gems uses: actions/cache@v4 with: diff --git a/Dockerfile b/Dockerfile index 1fdc01d..e95c60e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,12 @@ -FROM phusion/passenger-ruby32:3.1.6 +FROM phusion/passenger-ruby40:3.1.6 + +ARG GIT_TAG=1.0 # Set correct environment variables. ENV HOME=/home/app ENV LC_ALL=en_US.UTF-8 ENV LANG=en_US.UTF-8 +ENV GIT_TAG=${GIT_TAG} # Allow app user to read /etc/container_environment RUN usermod -a -G docker_env app diff --git a/Gemfile b/Gemfile index 7d79458..f17a3d7 100644 --- a/Gemfile +++ b/Gemfile @@ -17,7 +17,6 @@ gem "elasticsearch", "~> 8.19", ">= 8.19.3" gem "elasticsearch-model", "~> 8.0", ">= 8.0.1", require: "elasticsearch/model" gem "elasticsearch-rails", "~> 8.0", ">= 8.0.1" gem "elastic-transport", "~> 8.0", ">= 8.0.1" -gem "git", "~> 1.5" gem "faraday", "~> 2.14", ">= 2.14.1" gem "faraday_middleware-aws-sigv4", "~> 1.0", ">= 1.0.1" gem "faraday-excon", "~> 2.4" diff --git a/Gemfile.lock b/Gemfile.lock index ee2826f..b8838e1 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -77,8 +77,6 @@ GEM securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) uri (>= 0.13.1) - addressable (2.8.9) - public_suffix (>= 2.0.2, < 8.0) ast (2.4.3) aws-eventstream (1.4.0) aws-partitions (1.1233.0) @@ -156,9 +154,6 @@ GEM faraday_middleware-aws-sigv4 (1.0.1) aws-sigv4 (~> 1.0) faraday (>= 2.0, < 3) - git (1.19.1) - addressable (~> 2.8) - rchardet (~> 1.8) globalid (1.3.0) activesupport (>= 6.1) hashie (5.1.0) @@ -238,7 +233,6 @@ GEM psych (5.3.1) date stringio - public_suffix (7.0.5) racc (1.8.1) rack (3.2.6) rack-cors (3.0.0) @@ -283,7 +277,6 @@ GEM zeitwerk (~> 2.6) rainbow (3.1.1) rake (13.3.1) - rchardet (1.10.0) rdoc (7.2.0) erb psych (>= 4.0.0) @@ -420,7 +413,6 @@ DEPENDENCIES faraday (~> 2.14, >= 2.14.1) faraday-excon (~> 2.4) faraday_middleware-aws-sigv4 (~> 1.0, >= 1.0.1) - git (~> 1.5) lograge (~> 0.14.0) logstash-logger (~> 1.0) mysql2 (~> 0.5.7) diff --git a/config/initializers/_version.rb b/config/initializers/_version.rb index f8f1c83..bc5f90b 100644 --- a/config/initializers/_version.rb +++ b/config/initializers/_version.rb @@ -2,18 +2,6 @@ module Events class Application - begin - if File.directory?(Rails.root.join(".git")) - g = Git.open(Rails.root) - VERSION = g.tags.map { |t| Gem::Version.new(t.name) }.max.to_s - REVISION = g.object("HEAD").sha - else - VERSION = "unknown" - REVISION = "unknown" - end - rescue => _ - VERSION = "unknown" - REVISION = "unknown" - end + VERSION = ENV.fetch("GIT_TAG", "1.0.0") end end From 1ff68d81e8abd90a63004059b5ed584a367e6cb2 Mon Sep 17 00:00:00 2001 From: kudakwashe SIziva Date: Wed, 1 Apr 2026 15:17:09 +0200 Subject: [PATCH 03/10] update ruby version --- .ruby-version | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ruby-version b/.ruby-version index f15386a..90cdbdc 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.10 +ruby-4.0.1 diff --git a/Dockerfile b/Dockerfile index e95c60e..86d2100 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ RUN usermod -a -G docker_env app CMD ["/sbin/my_init"] # Use Ruby -RUN bash -lc 'rvm --default use ruby-3.2.10' +RUN bash -lc 'rvm --default use ruby-4.0.1' # Update installed APT packages RUN apt-get update && apt-get upgrade -y -o Dpkg::Options::="--force-confold" && \ From 76cb601959e184a9f9a2798c273388c42adaae48 Mon Sep 17 00:00:00 2001 From: kudakwashe SIziva Date: Wed, 1 Apr 2026 15:39:23 +0200 Subject: [PATCH 04/10] upgrade rails and ruby --- bin/bundler-audit | 6 ++ bin/ci | 6 ++ bin/dev | 2 + bin/rubocop | 2 +- bin/setup | 11 +-- config/application.rb | 5 +- config/bundler-audit.yml | 5 ++ config/ci.rb | 23 ++++++ config/environments/development.rb | 32 ++++---- config/environments/test.rb | 24 ++---- config/initializers/_version.rb | 2 - .../initializers/filter_parameter_logging.rb | 2 +- .../new_framework_defaults_7_2.rb | 70 ------------------ .../new_framework_defaults_8_1.rb | 74 +++++++++++++++++++ config/initializers/opensearch.rb | 30 ++++---- 15 files changed, 160 insertions(+), 134 deletions(-) create mode 100755 bin/bundler-audit create mode 100755 bin/ci create mode 100755 bin/dev create mode 100644 config/bundler-audit.yml create mode 100644 config/ci.rb delete mode 100644 config/initializers/new_framework_defaults_7_2.rb create mode 100644 config/initializers/new_framework_defaults_8_1.rb diff --git a/bin/bundler-audit b/bin/bundler-audit new file mode 100755 index 0000000..e2ef226 --- /dev/null +++ b/bin/bundler-audit @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +require_relative "../config/boot" +require "bundler/audit/cli" + +ARGV.concat %w[ --config config/bundler-audit.yml ] if ARGV.empty? || ARGV.include?("check") +Bundler::Audit::CLI.start diff --git a/bin/ci b/bin/ci new file mode 100755 index 0000000..4137ad5 --- /dev/null +++ b/bin/ci @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +require_relative "../config/boot" +require "active_support/continuous_integration" + +CI = ActiveSupport::ContinuousIntegration +require_relative "../config/ci.rb" diff --git a/bin/dev b/bin/dev new file mode 100755 index 0000000..5f91c20 --- /dev/null +++ b/bin/dev @@ -0,0 +1,2 @@ +#!/usr/bin/env ruby +exec "./bin/rails", "server", *ARGV diff --git a/bin/rubocop b/bin/rubocop index 40330c0..5a20504 100755 --- a/bin/rubocop +++ b/bin/rubocop @@ -2,7 +2,7 @@ require "rubygems" require "bundler/setup" -# explicit rubocop config increases performance slightly while avoiding config confusion. +# Explicit RuboCop config increases performance slightly while avoiding config confusion. ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__)) load Gem.bin_path("rubocop", "rubocop") diff --git a/bin/setup b/bin/setup index 69c173a..81be011 100755 --- a/bin/setup +++ b/bin/setup @@ -1,9 +1,7 @@ #!/usr/bin/env ruby require "fileutils" -# path to your application root. APP_ROOT = File.expand_path("..", __dir__) -APP_NAME = "events" def system!(*args) system(*args, exception: true) @@ -15,7 +13,6 @@ FileUtils.chdir APP_ROOT do # Add necessary setup steps to this file. puts "== Installing dependencies ==" - system! "gem install bundler --conservative" system("bundle check") || system!("bundle install") # puts "\n== Copying sample files ==" @@ -25,10 +22,14 @@ FileUtils.chdir APP_ROOT do puts "\n== Preparing database ==" system! "bin/rails db:prepare" + system! "bin/rails db:reset" if ARGV.include?("--reset") puts "\n== Removing old logs and tempfiles ==" system! "bin/rails log:clear tmp:clear" - puts "\n== Restarting application server ==" - system! "bin/rails restart" + unless ARGV.include?("--skip-server") + puts "\n== Starting development server ==" + STDOUT.flush # flush the output before exec(2) so that it displays + exec "bin/dev" + end end diff --git a/config/application.rb b/config/application.rb index f2c3248..35bc007 100644 --- a/config/application.rb +++ b/config/application.rb @@ -17,11 +17,9 @@ env_vars.each { |k, v| ENV[k] = v } end -ENV["GITHUB_URL"] ||= "https://github.com/datacite/events" - module Events class Application < Rails::Application - config.load_defaults(7.2) + config.load_defaults 8.1 config.autoload_lib(ignore: nil) @@ -48,5 +46,6 @@ class Application < Rails::Application config.active_job.queue_adapter = :shoryuken config.active_job.queue_name_prefix = Rails.env + config.active_storage.variant_processor = :disabled end end diff --git a/config/bundler-audit.yml b/config/bundler-audit.yml new file mode 100644 index 0000000..e74b3af --- /dev/null +++ b/config/bundler-audit.yml @@ -0,0 +1,5 @@ +# Audit all gems listed in the Gemfile for known security problems by running bin/bundler-audit. +# CVEs that are not relevant to the application can be enumerated on the ignore list below. + +ignore: + - CVE-THAT-DOES-NOT-APPLY diff --git a/config/ci.rb b/config/ci.rb new file mode 100644 index 0000000..407cf23 --- /dev/null +++ b/config/ci.rb @@ -0,0 +1,23 @@ +# Run using bin/ci + +CI.run do + step "Setup", "bin/setup --skip-server" + + step "Style: Ruby", "bin/rubocop" + + step "Security: Gem audit", "bin/bundler-audit" + step "Security: Brakeman code analysis", "bin/brakeman --quiet --no-pager --exit-on-warn --exit-on-error" + step "Tests: Rails", "bin/rails test" + step "Tests: Seeds", "env RAILS_ENV=test bin/rails db:seed:replant" + + # Optional: Run system tests + # step "Tests: System", "bin/rails test:system" + + # Optional: set a green GitHub commit status to unblock PR merge. + # Requires the `gh` CLI and `gh extension install basecamp/gh-signoff`. + # if success? + # step "Signoff: All systems go. Ready for merge and deploy.", "gh signoff" + # else + # failure "Signoff: CI failed. Do not merge or deploy.", "Fix the issues and try again." + # end +end diff --git a/config/environments/development.rb b/config/environments/development.rb index 98128ff..c05ef19 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -3,9 +3,7 @@ Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. - # In the development environment your application's code is reloaded any time - # it changes. This slows down response time but is perfect for development - # since you don't have to restart the web server when you make code changes. + # Make code changes take effect immediately without server restart. config.enable_reloading = true # Do not eager load code on boot. @@ -17,47 +15,47 @@ # Enable server timing. config.server_timing = true - # Enable/disable caching. By default caching is disabled. - # Run rails dev:cache to toggle caching. + # Enable/disable Action Controller caching. By default Action Controller caching is disabled. + # Run rails dev:cache to toggle Action Controller caching. if Rails.root.join("tmp/caching-dev.txt").exist? - config.cache_store = :memory_store - config.public_file_server.headers = { "Cache-Control" => "public, max-age=#{2.days.to_i}" } + config.public_file_server.headers = { "cache-control" => "public, max-age=#{2.days.to_i}" } else config.action_controller.perform_caching = false - - config.cache_store = :null_store end + # Change to :null_store to avoid any caching. + config.cache_store = :memory_store + # Store uploaded files on the local file system (see config/storage.yml for options). config.active_storage.service = :local # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false - # Disable caching for Action Mailer templates even if Action Controller - # caching is enabled. + # Make template changes take effect immediately. config.action_mailer.perform_caching = false + # Set localhost to be used by links generated in mailer templates. config.action_mailer.default_url_options = { host: "localhost", port: 3000 } # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log - # Raise exceptions for disallowed deprecations. - config.active_support.disallowed_deprecation = :raise - - # Tell Active Support which deprecation messages to disallow. - config.active_support.disallowed_deprecation_warnings = [] - # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load # Highlight code that triggered database queries in logs. config.active_record.verbose_query_logs = true + # Append comments with runtime information tags to SQL queries in logs. + config.active_record.query_log_tags_enabled = true + # Highlight code that enqueued background job in logs. config.active_job.verbose_enqueue_logs = true + # Highlight code that triggered redirect in logs. + config.action_dispatch.verbose_redirect_logs = true + # Raises error for missing translations. # config.i18n.raise_on_missing_translations = true diff --git a/config/environments/test.rb b/config/environments/test.rb index 0c616a1..c2095b1 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,5 +1,3 @@ -require "active_support/core_ext/integer/time" - # 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 @@ -17,12 +15,11 @@ # loading is working properly before deploying your code. config.eager_load = ENV["CI"].present? - # Configure public file server for tests with Cache-Control for performance. - config.public_file_server.headers = { "Cache-Control" => "public, max-age=#{1.hour.to_i}" } + # Configure public file server for tests with cache-control for performance. + config.public_file_server.headers = { "cache-control" => "public, max-age=3600" } - # Show full error reports and disable caching. + # Show full error reports. config.consider_all_requests_local = true - config.action_controller.perform_caching = false config.cache_store = :null_store # Render exception templates for rescuable exceptions and raise for other exceptions. @@ -34,28 +31,17 @@ # Store uploaded files on the local file system in a temporary directory. config.active_storage.service = :test - # Disable caching for Action Mailer templates even if Action Controller - # caching is enabled. - config.action_mailer.perform_caching = false - # Tell Action Mailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test - # Unlike controllers, the mailer instance doesn't have any context about the - # incoming request so you'll need to provide the :host parameter yourself. - config.action_mailer.default_url_options = { host: "www.example.com" } + # Set host to be used by links generated in mailer templates. + config.action_mailer.default_url_options = { host: "example.com" } # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr - # Raise exceptions for disallowed deprecations. - config.active_support.disallowed_deprecation = :raise - - # Tell Active Support which deprecation messages to disallow. - config.active_support.disallowed_deprecation_warnings = [] - # Raises error for missing translations. # config.i18n.raise_on_missing_translations = true diff --git a/config/initializers/_version.rb b/config/initializers/_version.rb index bc5f90b..d435de5 100644 --- a/config/initializers/_version.rb +++ b/config/initializers/_version.rb @@ -1,5 +1,3 @@ -require "git" - module Events class Application VERSION = ENV.fetch("GIT_TAG", "1.0.0") diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index 0121a7f..c0b717f 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -4,5 +4,5 @@ # Use this to limit dissemination of sensitive information. # See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. Rails.application.config.filter_parameters += [ - :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, + :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, :cvv, :cvc ] diff --git a/config/initializers/new_framework_defaults_7_2.rb b/config/initializers/new_framework_defaults_7_2.rb deleted file mode 100644 index b549c4a..0000000 --- a/config/initializers/new_framework_defaults_7_2.rb +++ /dev/null @@ -1,70 +0,0 @@ -# Be sure to restart your server when you modify this file. -# -# This file eases your Rails 7.2 framework defaults upgrade. -# -# Uncomment each configuration one by one to switch to the new default. -# Once your application is ready to run with all new defaults, you can remove -# this file and set the `config.load_defaults` to `7.2`. -# -# Read the Guide for Upgrading Ruby on Rails for more info on each option. -# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html - -### -# Controls whether Active Job's `#perform_later` and similar methods automatically defer -# the job queuing to after the current Active Record transaction is committed. -# -# Example: -# Topic.transaction do -# topic = Topic.create(...) -# NewTopicNotificationJob.perform_later(topic) -# end -# -# In this example, if the configuration is set to `:never`, the job will -# be enqueued immediately, even though the `Topic` hasn't been committed yet. -# Because of this, if the job is picked up almost immediately, or if the -# transaction doesn't succeed for some reason, the job will fail to find this -# topic in the database. -# -# If `enqueue_after_transaction_commit` is set to `:default`, the queue adapter -# will define the behaviour. -# -# Note: Active Job backends can disable this feature. This is generally done by -# backends that use the same database as Active Record as a queue, hence they -# don't need this feature. -#++ -# Rails.application.config.active_job.enqueue_after_transaction_commit = :default - -### -# Adds image/webp to the list of content types Active Storage considers as an image -# Prevents automatic conversion to a fallback PNG, and assumes clients support WebP, as they support gif, jpeg, and png. -# This is possible due to broad browser support for WebP, but older browsers and email clients may still not support -# WebP. Requires imagemagick/libvips built with WebP support. -#++ -# Rails.application.config.active_storage.web_image_content_types = %w[image/png image/jpeg image/gif image/webp] - -### -# Enable validation of migration timestamps. When set, an ActiveRecord::InvalidMigrationTimestampError -# will be raised if the timestamp prefix for a migration is more than a day ahead of the timestamp -# associated with the current time. This is done to prevent forward-dating of migration files, which can -# impact migration generation and other migration commands. -# -# Applications with existing timestamped migrations that do not adhere to the -# expected format can disable validation by setting this config to `false`. -#++ -# Rails.application.config.active_record.validate_migration_timestamps = true - -### -# Controls whether the PostgresqlAdapter should decode dates automatically with manual queries. -# -# Example: -# ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.select_value("select '2024-01-01'::date") #=> Date -# -# This query used to return a `String`. -#++ -# Rails.application.config.active_record.postgresql_adapter_decode_dates = true - -### -# Enables YJIT as of Ruby 3.3, to bring sizeable performance improvements. If you are -# deploying to a memory constrained environment you may want to set this to `false`. -#++ -# Rails.application.config.yjit = true diff --git a/config/initializers/new_framework_defaults_8_1.rb b/config/initializers/new_framework_defaults_8_1.rb new file mode 100644 index 0000000..2dcf3ca --- /dev/null +++ b/config/initializers/new_framework_defaults_8_1.rb @@ -0,0 +1,74 @@ +# Be sure to restart your server when you modify this file. +# +# This file eases your Rails 8.1 framework defaults upgrade. +# +# Uncomment each configuration one by one to switch to the new default. +# Once your application is ready to run with all new defaults, you can remove +# this file and set the `config.load_defaults` to `8.1`. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. +# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html + +### +# Skips escaping HTML entities and line separators. When set to `false`, the +# JSON renderer no longer escapes these to improve performance. +# +# Example: +# class PostsController < ApplicationController +# def index +# render json: { key: "\u2028\u2029<>&" } +# end +# end +# +# Renders `{"key":"\u2028\u2029\u003c\u003e\u0026"}` with the previous default, but `{"key":"<>&"}` with the config +# set to `false`. +# +# Applications that want to keep the escaping behavior can set the config to `true`. +#++ +# Rails.configuration.action_controller.escape_json_responses = false + +### +# Skips escaping LINE SEPARATOR (U+2028) and PARAGRAPH SEPARATOR (U+2029) in JSON. +# +# Historically these characters were not valid inside JavaScript literal strings but that changed in ECMAScript 2019. +# As such it's no longer a concern in modern browsers: https://caniuse.com/mdn-javascript_builtins_json_json_superset. +#++ +# Rails.configuration.active_support.escape_js_separators_in_json = false + +### +# Raises an error when order dependent finder methods (e.g. `#first`, `#second`) are called without `order` values +# on the relation, and the model does not have any order columns (`implicit_order_column`, `query_constraints`, or +# `primary_key`) to fall back on. +# +# The current behavior of not raising an error has been deprecated, and this configuration option will be removed in +# Rails 8.2. +#++ +# Rails.configuration.active_record.raise_on_missing_required_finder_order_columns = true + +### +# Controls how Rails handles path relative URL redirects. +# When set to `:raise`, Rails will raise an `ActionController::Redirecting::UnsafeRedirectError` +# for relative URLs without a leading slash, which can help prevent open redirect vulnerabilities. +# +# Example: +# redirect_to "example.com" # Raises UnsafeRedirectError +# redirect_to "@attacker.com" # Raises UnsafeRedirectError +# redirect_to "/safe/path" # Works correctly +# +# Applications that want to allow these redirects can set the config to `:log` (previous default) +# to only log warnings, or `:notify` to send ActiveSupport notifications. +#++ +# Rails.configuration.action_controller.action_on_path_relative_redirect = :raise + +### +# Use a Ruby parser to track dependencies between Action View templates +#++ +# Rails.configuration.action_view.render_tracker = :ruby + +### +# When enabled, hidden inputs generated by `form_tag`, `token_tag`, `method_tag`, and the hidden parameter fields +# included in `button_to` forms will omit the `autocomplete="off"` attribute. +# +# Applications that want to keep generating the `autocomplete` attribute for those tags can set it to `false`. +#++ +# Rails.configuration.action_view.remove_hidden_field_autocomplete = true diff --git a/config/initializers/opensearch.rb b/config/initializers/opensearch.rb index 3f3cf69..9f32a53 100644 --- a/config/initializers/opensearch.rb +++ b/config/initializers/opensearch.rb @@ -2,6 +2,20 @@ require "faraday_middleware/aws_sigv4" require "faraday/excon" +# Bypass Elasticsearch product check to allow OpenSearch-compatible endpoints. +# elasticsearch-ruby 8.x raises UnsupportedProductError unless the server returns +# x-elastic-product: Elasticsearch, which OpenSearch does not. +module ElasticsearchV8OpenSearchBypass + private + def verify_elasticsearch(*args, &block) + response = @transport.perform_request(*args, &block) + @verified = true + response + end +end + +Elasticsearch::Client.prepend(ElasticsearchV8OpenSearchBypass) + Elasticsearch::Model.client = if ENV["ES_HOST"].end_with?(".datacite.org") Elasticsearch::Client.new( host: ENV["ES_HOST"], @@ -31,19 +45,3 @@ password: ENV["ELASTIC_PASSWORD"], ) { |f| f.adapter(:excon) } end - -# Monkeypactch to ignore the Elasticsearch::UnsupportedProductError. -# This error is raised because our gem version does not match the elasticsearch version in AWS OpenSearch. -# As such, it should be safe to ignore the error. -module Elasticsearch - class Client - alias_method :original_verify_with_version_or_header, :verify_with_version_or_header - - def verify_with_version_or_header(...) - original_verify_with_version_or_header(...) - rescue Elasticsearch::UnsupportedProductError - # let's ignore this it's adding a lot of noise to the logs - # warn("Ignoring elasticsearch complaint: #{exception.message}") - end - end -end From 4fcab74e2be1c764490b4ca3f704e28a23c841a6 Mon Sep 17 00:00:00 2001 From: kudakwashe SIziva Date: Wed, 1 Apr 2026 15:54:34 +0200 Subject: [PATCH 05/10] upgrade and pin test group gems --- Gemfile | 30 +++++++++++++++--------------- Gemfile.lock | 46 +++++++++++++++++++++++----------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Gemfile b/Gemfile index f17a3d7..29675e3 100644 --- a/Gemfile +++ b/Gemfile @@ -25,23 +25,23 @@ gem "oj", "~> 3.16", ">= 3.16.16" gem "parallel", "~> 1.27" group :development, :test do - gem "debug", platforms: [:mri, :windows] - gem "rubocop", require: false - gem "rubocop-shopify", require: false - gem "rubocop-rspec", require: false - gem "rubocop-performance", require: false - gem "rubocop-factory_bot", require: false - gem "rubocop-rails", require: false - gem "rubocop-rspec_rails", require: false - gem "factory_bot_rails" - gem "bundler-audit", require: false - gem "brakeman", require: false - gem "rspec-rails", "~> 7.0.0" + gem "debug", "~> 1.11", ">= 1.11.1", platforms: [:mri, :windows] + gem "rubocop", "~> 1.86", require: false + gem "rubocop-shopify", "~> 2.18", require: false + gem "rubocop-rspec", "~> 3.9", require: false + gem "rubocop-performance", "~> 1.26", ">= 1.26.1", require: false + gem "rubocop-factory_bot", "~> 2.28", require: false + gem "rubocop-rails", "~> 2.34", ">= 2.34.3", require: false + gem "rubocop-rspec_rails", "~> 2.32", require: false + gem "factory_bot_rails", "~> 6.5", ">= 6.5.1" + gem "bundler-audit", "~> 0.9.3", require: false + gem "brakeman", "~> 8.0", ">= 8.0.4", require: false + gem "rspec-rails", "~> 8.0", ">= 8.0.4" end group :test do - gem "simplecov", require: false - gem "shoulda-matchers" - gem "coveralls_reborn", require: false + gem "simplecov", "~> 0.22.0", require: false + gem "shoulda-matchers", "~> 7.0", ">= 7.0.1" + gem "coveralls_reborn", "~> 0.29.0", require: false gem "activerecord-nulldb-adapter", "~> 1.2", ">= 1.2.2" # This gem will allow us to write tests without the need for a database end diff --git a/Gemfile.lock b/Gemfile.lock index b8838e1..4dd16d5 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -296,14 +296,14 @@ GEM rspec-mocks (3.13.8) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-rails (7.0.2) - actionpack (>= 7.0) - activesupport (>= 7.0) - railties (>= 7.0) - rspec-core (~> 3.13) - rspec-expectations (~> 3.13) - rspec-mocks (~> 3.13) - rspec-support (~> 3.13) + rspec-rails (8.0.4) + actionpack (>= 7.2) + activesupport (>= 7.2) + railties (>= 7.2) + rspec-core (>= 3.13.0, < 5.0.0) + rspec-expectations (>= 3.13.0, < 5.0.0) + rspec-mocks (>= 3.13.0, < 5.0.0) + rspec-support (>= 3.13.0, < 5.0.0) rspec-support (3.13.7) rubocop (1.86.0) json (~> 2.3) @@ -400,16 +400,16 @@ DEPENDENCIES activerecord-nulldb-adapter (~> 1.2, >= 1.2.2) aws-sdk-sqs (~> 1.112) bootsnap (~> 1.23) - brakeman - bundler-audit - coveralls_reborn - debug + brakeman (~> 8.0, >= 8.0.4) + bundler-audit (~> 0.9.3) + coveralls_reborn (~> 0.29.0) + debug (~> 1.11, >= 1.11.1) dotenv (~> 3.2) elastic-transport (~> 8.0, >= 8.0.1) elasticsearch (~> 8.19, >= 8.19.3) elasticsearch-model (~> 8.0, >= 8.0.1) elasticsearch-rails (~> 8.0, >= 8.0.1) - factory_bot_rails + factory_bot_rails (~> 6.5, >= 6.5.1) faraday (~> 2.14, >= 2.14.1) faraday-excon (~> 2.4) faraday_middleware-aws-sigv4 (~> 1.0, >= 1.0.1) @@ -420,19 +420,19 @@ DEPENDENCIES parallel (~> 1.27) rack-cors (~> 3.0) rails (~> 8.1, >= 8.1.2.1) - rspec-rails (~> 7.0.0) - rubocop - rubocop-factory_bot - rubocop-performance - rubocop-rails - rubocop-rspec - rubocop-rspec_rails - rubocop-shopify + rspec-rails (~> 8.0, >= 8.0.4) + rubocop (~> 1.86) + rubocop-factory_bot (~> 2.28) + rubocop-performance (~> 1.26, >= 1.26.1) + rubocop-rails (~> 2.34, >= 2.34.3) + rubocop-rspec (~> 3.9) + rubocop-rspec_rails (~> 2.32) + rubocop-shopify (~> 2.18) sentry-rails (~> 6.5) sentry-ruby (~> 6.5) shoryuken (~> 7.0, >= 7.0.1) - shoulda-matchers - simplecov + shoulda-matchers (~> 7.0, >= 7.0.1) + simplecov (~> 0.22.0) uuid (~> 2.3, >= 2.3.9) RUBY VERSION From e7d3e1ac69e9bbeef035959aab3ffcf3f548974e Mon Sep 17 00:00:00 2001 From: kudakwashe SIziva Date: Wed, 1 Apr 2026 16:25:12 +0200 Subject: [PATCH 06/10] update simplecov config --- app/jobs/event_index_job.rb | 4 ++-- spec/jobs/event_index_job_spec.rb | 14 +++++++------- spec/rails_helper.rb | 13 ++++++------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/app/jobs/event_index_job.rb b/app/jobs/event_index_job.rb index 8975109..64a64f5 100644 --- a/app/jobs/event_index_job.rb +++ b/app/jobs/event_index_job.rb @@ -3,8 +3,8 @@ class EventIndexJob < ApplicationJob rescue_from ActiveJob::DeserializationError, SocketError, - Elasticsearch::Transport::Transport::Errors::BadRequest, - Elasticsearch::Transport::Transport::Error do |error| + Elastic::Transport::Transport::Errors::BadRequest, + Elastic::Transport::Transport::Error do |error| Rails.logger.error(error.message) end diff --git a/spec/jobs/event_index_job_spec.rb b/spec/jobs/event_index_job_spec.rb index d1f830e..27897e6 100644 --- a/spec/jobs/event_index_job_spec.rb +++ b/spec/jobs/event_index_job_spec.rb @@ -61,11 +61,11 @@ end end - describe "Elasticsearch::Transport::Transport::Errors::BadRequest" do - let(:error) { Elasticsearch::Transport::Transport::Errors::BadRequest.allocate } + describe "Elastic::Transport::Transport::Errors::BadRequest" do + let(:error) { Elastic::Transport::Transport::Errors::BadRequest.allocate } before do - allow(error).to(receive(:message).and_return("Elasticsearch::Transport::Transport::Errors::BadRequest")) + allow(error).to(receive(:message).and_return("Elastic::Transport::Transport::Errors::BadRequest")) allow(event.__elasticsearch__) .to(receive(:index_document) @@ -79,15 +79,15 @@ it "logs the error" do described_class.perform_now(event) - expect(Rails.logger).to(have_received(:error).with("Elasticsearch::Transport::Transport::Errors::BadRequest")) + expect(Rails.logger).to(have_received(:error).with("Elastic::Transport::Transport::Errors::BadRequest")) end end - describe "Elasticsearch::Transport::Transport::Error" do + describe "Elastic::Transport::Transport::Error" do let(:error) { SocketError.allocate } before do - allow(error).to(receive(:message).and_return("Elasticsearch::Transport::Transport::Error")) + allow(error).to(receive(:message).and_return("Elastic::Transport::Transport::Error")) allow(event.__elasticsearch__) .to(receive(:index_document) @@ -101,7 +101,7 @@ it "logs the error" do described_class.perform_now(event) - expect(Rails.logger).to(have_received(:error).with("Elasticsearch::Transport::Transport::Error")) + expect(Rails.logger).to(have_received(:error).with("Elastic::Transport::Transport::Error")) end end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 21fb2c4..31f2a2d 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,13 +1,12 @@ require "simplecov" require "coveralls" -SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([ - SimpleCov::Formatter::HTMLFormatter, - Coveralls::SimpleCov::Formatter, -]) - -require "simplecov" -SimpleCov.start("rails") +SimpleCov.start("rails") do + formatter SimpleCov::Formatter::MultiFormatter.new([ + SimpleCov::Formatter::HTMLFormatter, + Coveralls::SimpleCov::Formatter, + ]) +end require "spec_helper" ENV["RAILS_ENV"] ||= "test" From b7056204d95fd9bf1f61ca02aec63710030bd805 Mon Sep 17 00:00:00 2001 From: kudakwashe SIziva Date: Wed, 1 Apr 2026 16:31:06 +0200 Subject: [PATCH 07/10] fix rubocop issues --- .rubocop.yml | 2 -- config/application.rb | 2 +- config/initializers/_version.rb | 2 +- config/initializers/filter_parameter_logging.rb | 2 +- config/initializers/opensearch.rb | 11 ++++++----- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 49170f3..35f4f46 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -6,8 +6,6 @@ plugins: - rubocop-rails - rubocop-rspec - rubocop-rspec_rails - -require: - rubocop-factory_bot AllCops: diff --git a/config/application.rb b/config/application.rb index 35bc007..18e7645 100644 --- a/config/application.rb +++ b/config/application.rb @@ -19,7 +19,7 @@ module Events class Application < Rails::Application - config.load_defaults 8.1 + config.load_defaults(8.1) config.autoload_lib(ignore: nil) diff --git a/config/initializers/_version.rb b/config/initializers/_version.rb index d435de5..b49e7cf 100644 --- a/config/initializers/_version.rb +++ b/config/initializers/_version.rb @@ -1,5 +1,5 @@ module Events class Application - VERSION = ENV.fetch("GIT_TAG", "1.0.0") + VERSION = ENV.fetch("GIT_TAG", "1.0.0") end end diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index c0b717f..ee2ed8c 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -4,5 +4,5 @@ # Use this to limit dissemination of sensitive information. # See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. Rails.application.config.filter_parameters += [ - :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, :cvv, :cvc + :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, :cvv, :cvc, ] diff --git a/config/initializers/opensearch.rb b/config/initializers/opensearch.rb index 9f32a53..1653922 100644 --- a/config/initializers/opensearch.rb +++ b/config/initializers/opensearch.rb @@ -7,11 +7,12 @@ # x-elastic-product: Elasticsearch, which OpenSearch does not. module ElasticsearchV8OpenSearchBypass private - def verify_elasticsearch(*args, &block) - response = @transport.perform_request(*args, &block) - @verified = true - response - end + + def verify_elasticsearch(*args, &block) + response = @transport.perform_request(*args, &block) + @verified = true + response + end end Elasticsearch::Client.prepend(ElasticsearchV8OpenSearchBypass) From ba3d362930c684d286ba843d4d6fe9d6ba5669e2 Mon Sep 17 00:00:00 2001 From: kudakwashe SIziva Date: Thu, 2 Apr 2026 10:41:48 +0200 Subject: [PATCH 08/10] Add addressable gem --- Gemfile | 1 + Gemfile.lock | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/Gemfile b/Gemfile index 29675e3..b7f963c 100644 --- a/Gemfile +++ b/Gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" ruby "4.0.1" gem "rails", "~> 8.1", ">= 8.1.2.1" +gem "addressable", "~> 2.8", ">= 2.8.9" gem "bootsnap", "~> 1.23", require: false gem "rack-cors", "~> 3.0" gem "shoryuken", "~> 7.0", ">= 7.0.1" diff --git a/Gemfile.lock b/Gemfile.lock index 4dd16d5..ccc69a4 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -77,6 +77,8 @@ GEM securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) uri (>= 0.13.1) + addressable (2.8.9) + public_suffix (>= 2.0.2, < 8.0) ast (2.4.3) aws-eventstream (1.4.0) aws-partitions (1.1233.0) @@ -233,6 +235,7 @@ GEM psych (5.3.1) date stringio + public_suffix (7.0.5) racc (1.8.1) rack (3.2.6) rack-cors (3.0.0) @@ -398,6 +401,7 @@ PLATFORMS DEPENDENCIES activerecord-nulldb-adapter (~> 1.2, >= 1.2.2) + addressable (~> 2.8, >= 2.8.9) aws-sdk-sqs (~> 1.112) bootsnap (~> 1.23) brakeman (~> 8.0, >= 8.0.4) From da02b32609a554184c01c83703af2dbd14689db2 Mon Sep 17 00:00:00 2001 From: kudakwashe SIziva Date: Thu, 2 Apr 2026 11:00:15 +0200 Subject: [PATCH 09/10] address feedback --- Dockerfile | 6 +++--- bin/bundler-audit | 1 - config/bundler-audit.yml | 5 ----- config/environments/development.rb | 1 + 4 files changed, 4 insertions(+), 9 deletions(-) delete mode 100644 config/bundler-audit.yml diff --git a/Dockerfile b/Dockerfile index 86d2100..4af8063 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,9 @@ FROM phusion/passenger-ruby40:3.1.6 -ARG GIT_TAG=1.0 - # Set correct environment variables. ENV HOME=/home/app ENV LC_ALL=en_US.UTF-8 ENV LANG=en_US.UTF-8 -ENV GIT_TAG=${GIT_TAG} # Allow app user to read /etc/container_environment RUN usermod -a -G docker_env app @@ -70,5 +67,8 @@ COPY vendor/docker/90_migrate.sh /etc/my_init.d/90_migrate.sh # Add the directory to the list of safe directories RUN git config --global --add safe.directory /home/app/webapp +ARG GIT_TAG=1.0 +ENV GIT_TAG=${GIT_TAG} + # Expose web EXPOSE 80 diff --git a/bin/bundler-audit b/bin/bundler-audit index e2ef226..d626f5d 100755 --- a/bin/bundler-audit +++ b/bin/bundler-audit @@ -2,5 +2,4 @@ require_relative "../config/boot" require "bundler/audit/cli" -ARGV.concat %w[ --config config/bundler-audit.yml ] if ARGV.empty? || ARGV.include?("check") Bundler::Audit::CLI.start diff --git a/config/bundler-audit.yml b/config/bundler-audit.yml deleted file mode 100644 index e74b3af..0000000 --- a/config/bundler-audit.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Audit all gems listed in the Gemfile for known security problems by running bin/bundler-audit. -# CVEs that are not relevant to the application can be enumerated on the ignore list below. - -ignore: - - CVE-THAT-DOES-NOT-APPLY diff --git a/config/environments/development.rb b/config/environments/development.rb index c05ef19..2285fa3 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -18,6 +18,7 @@ # Enable/disable Action Controller caching. By default Action Controller caching is disabled. # Run rails dev:cache to toggle Action Controller caching. if Rails.root.join("tmp/caching-dev.txt").exist? + config.action_controller.perform_caching = true config.public_file_server.headers = { "cache-control" => "public, max-age=#{2.days.to_i}" } else config.action_controller.perform_caching = false From 7f95854113c440d0b1cf089e4b0c5fdfb0201161 Mon Sep 17 00:00:00 2001 From: kudakwashe SIziva Date: Tue, 14 Apr 2026 12:22:09 +0200 Subject: [PATCH 10/10] separate security check from parallel ci --- .github/workflows/parallel_ci.yml | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/workflows/parallel_ci.yml b/.github/workflows/parallel_ci.yml index 7421e14..041145d 100644 --- a/.github/workflows/parallel_ci.yml +++ b/.github/workflows/parallel_ci.yml @@ -2,6 +2,24 @@ name: Parallel CI on: workflow_call: jobs: + security: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: "4.0.1" + bundler-cache: true + + - name: Run Brakeman + run: bundle exec brakeman --no-pager + + - name: Run Bundler Audit + run: | + bundle exec bundler-audit check --update parallel-test: runs-on: ubuntu-latest strategy: @@ -32,8 +50,3 @@ jobs: run: bundle exec rspec env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} - - - name: Security Check - run: | - bundle exec bundler-audit check --update - bundle exec brakeman --no-pager