diff --git a/.rubocop.yml b/.rubocop.yml deleted file mode 100644 index 25f5ca5..0000000 --- a/.rubocop.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Omakase Ruby styling for Rails -inherit_gem: - rubocop-rails-omakase: rubocop.yml - -# Your own specialized rules go here diff --git a/Dockerfile b/Dockerfile index 0639c80..f19c5f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,36 +1,25 @@ # syntax = docker/dockerfile:1 -# This Dockerfile is designed for production, not development. Use with Kamal or build'n'run by hand: -# docker build -t my-app . -# docker run -d -p 80:80 -p 443:443 --name my-app -e RAILS_MASTER_KEY= my-app - -# For a containerized dev environment, see Dev Containers: https://guides.rubyonrails.org/getting_started_with_devcontainer.html - -# Make sure RUBY_VERSION matches the Ruby version in .ruby-version -ARG RUBY_VERSION=3.3.1 -FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base +# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile +ARG RUBY_VERSION=3.2.2 +FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base # Rails app lives here WORKDIR /rails -# Install base packages -RUN apt-get update -qq && \ - apt-get install --no-install-recommends -y curl libjemalloc2 libsqlite3-0 libvips && \ - rm -rf /var/lib/apt/lists /var/cache/apt/archives - # Set production environment ENV RAILS_ENV="production" \ BUNDLE_DEPLOYMENT="1" \ BUNDLE_PATH="/usr/local/bundle" \ BUNDLE_WITHOUT="development" + # Throw-away build stage to reduce size of final image -FROM base AS build +FROM base as build # Install packages needed to build gems RUN apt-get update -qq && \ - apt-get install --no-install-recommends -y build-essential git pkg-config && \ - rm -rf /var/lib/apt/lists /var/cache/apt/archives + apt-get install --no-install-recommends -y build-essential git libvips pkg-config # Install application gems COPY Gemfile Gemfile.lock ./ @@ -38,6 +27,7 @@ RUN bundle install && \ rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \ bundle exec bootsnap precompile --gemfile + # Copy application code COPY . . @@ -48,20 +38,24 @@ RUN bundle exec bootsnap precompile app/ lib/ RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile - - # Final stage for app image FROM base +# Install packages needed for deployment +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y curl libsqlite3-0 libvips libjemalloc2 && \ + rm -rf /var/lib/apt/lists /var/cache/apt/archives + # Copy built artifacts: gems, application -COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}" +COPY --from=build /usr/local/bundle /usr/local/bundle COPY --from=build /rails /rails # Run and own only the runtime files as a non-root user for security -RUN groupadd --system --gid 1000 rails && \ - useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \ +RUN useradd rails --create-home --shell /bin/bash && \ chown -R rails:rails db log storage tmp -USER 1000:1000 +USER rails:rails + +ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 # Entrypoint prepares the database. ENTRYPOINT ["/rails/bin/docker-entrypoint"] diff --git a/Gemfile b/Gemfile index ef1c2ba..033ab42 100644 --- a/Gemfile +++ b/Gemfile @@ -1,61 +1,32 @@ source "https://rubygems.org" +git_source(:github) { |repo| "https://github.com/#{repo}.git" } gem "rails", github: "rails/rails", branch: "main" -# The modern asset pipeline for Rails [https://github.com/rails/propshaft] -gem "propshaft" -# Use sqlite3 as the database for Active Record -gem "sqlite3", ">= 1.4" -# Use the Puma web server [https://github.com/puma/puma] -gem "puma", ">= 5.0" -# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails] +gem "sprockets-rails" +gem "sqlite3" +gem "puma" gem "importmap-rails" -# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev] gem "turbo-rails" -# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev] gem "stimulus-rails" -# Build JSON APIs with ease [https://github.com/rails/jbuilder] gem "jbuilder" -# Use Redis adapter to run Action Cable in production -# gem "redis", ">= 4.0.1" -# Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis] -# gem "kredis" - -# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] -# gem "bcrypt", "~> 3.1.7" - -# Windows does not include zoneinfo files, so bundle the tzinfo-data gem -gem "tzinfo-data", platforms: %i[ windows jruby ] - -# Reduces boot times through caching; required in config/boot.rb gem "bootsnap", require: false -# Deploy this application anywhere as a Docker container [https://kamal-deploy.org] -# gem "kamal", require: false - -# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] # gem "image_processing", "~> 1.2" group :development, :test do - # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem - gem "debug", platforms: %i[ mri windows ], require: "debug/prelude" - - # Static analysis for security vulnerabilities [https://brakemanscanner.org/] - gem "brakeman", require: false - - # Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/] - gem "rubocop-rails-omakase", require: false + gem "debug", platforms: %i[mri mingw x64_mingw] end group :development do - # Use console on exceptions pages [https://github.com/rails/web-console] + gem "standard" gem "web-console" end group :test do - # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing] gem "capybara" gem "selenium-webdriver" + gem "webdrivers" end gem "tailwindcss-rails", "~> 2.0" diff --git a/Gemfile.lock b/Gemfile.lock index 5b0b297..f34018e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -106,8 +106,6 @@ GEM bindex (0.8.1) bootsnap (1.18.3) msgpack (~> 1.2) - brakeman (6.1.2) - racc builder (3.3.0) capybara (3.40.0) addressable @@ -144,6 +142,7 @@ GEM activesupport (>= 5.0.0) json (2.7.2) language_server-protocol (3.17.0.3) + lint_roller (1.1.0) logger (1.6.0) loofah (2.22.0) crass (~> 1.0.2) @@ -168,8 +167,6 @@ GEM net-smtp (0.5.0) net-protocol nio4r (2.7.3) - nokogiri (1.16.6-aarch64-linux) - racc (~> 1.4) nokogiri (1.16.6-arm64-darwin) racc (~> 1.4) nokogiri (1.16.6-x86_64-linux) @@ -178,11 +175,6 @@ GEM parser (3.3.3.0) ast (~> 2.4.1) racc - propshaft (0.9.0) - actionpack (>= 7.0.0) - activesupport (>= 7.0.0) - rack - railties (>= 7.0.0) psych (5.1.2) stringio public_suffix (6.0.0) @@ -226,39 +218,40 @@ GEM unicode-display_width (>= 2.4.0, < 3.0) rubocop-ast (1.31.3) parser (>= 3.3.1.0) - rubocop-minitest (0.35.0) - rubocop (>= 1.61, < 2.0) - rubocop-ast (>= 1.31.1, < 2.0) rubocop-performance (1.21.1) rubocop (>= 1.48.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rails (2.25.0) - activesupport (>= 4.2.0) - rack (>= 1.1) - rubocop (>= 1.33.0, < 2.0) - rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rails-omakase (1.0.0) - rubocop - rubocop-minitest - rubocop-performance - rubocop-rails ruby-progressbar (1.13.0) rubyzip (2.3.2) - selenium-webdriver (4.22.0) - base64 (~> 0.2) - logger (~> 1.4) + selenium-webdriver (4.10.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) - sqlite3 (2.0.2-aarch64-linux-gnu) + sprockets (4.2.1) + concurrent-ruby (~> 1.0) + rack (>= 2.2.4, < 4) + sprockets-rails (3.5.1) + actionpack (>= 6.1) + activesupport (>= 6.1) + sprockets (>= 3.0.0) sqlite3 (2.0.2-arm64-darwin) sqlite3 (2.0.2-x86_64-linux-gnu) + standard (1.37.0) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.64.0) + standard-custom (~> 1.0.0) + standard-performance (~> 1.4) + standard-custom (1.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.50) + standard-performance (1.4.0) + lint_roller (~> 1.1) + rubocop-performance (~> 1.21.0) stimulus-rails (1.3.3) railties (>= 6.0.0) stringio (3.1.1) strscan (3.1.0) - tailwindcss-rails (2.6.1-aarch64-linux) - railties (>= 7.0.0) tailwindcss-rails (2.6.1-arm64-darwin) railties (>= 7.0.0) tailwindcss-rails (2.6.1-x86_64-linux) @@ -278,6 +271,10 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) + webdrivers (5.3.1) + nokogiri (~> 1.6) + rubyzip (>= 1.3.0) + selenium-webdriver (~> 4.0, < 4.11) webrick (1.8.1) websocket (1.2.10) websocket-driver (0.7.6) @@ -288,28 +285,26 @@ GEM zeitwerk (2.6.16) PLATFORMS - aarch64-linux arm64-darwin-23 x86_64-linux DEPENDENCIES bootsnap - brakeman capybara debug importmap-rails jbuilder - propshaft - puma (>= 5.0) + puma rails! - rubocop-rails-omakase selenium-webdriver - sqlite3 (>= 1.4) + sprockets-rails + sqlite3 + standard stimulus-rails tailwindcss-rails (~> 2.0) turbo-rails - tzinfo-data web-console + webdrivers BUNDLED WITH 2.5.9 diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js new file mode 100644 index 0000000..b06fc42 --- /dev/null +++ b/app/assets/config/manifest.js @@ -0,0 +1,5 @@ +//= link_tree ../images +//= link_directory ../stylesheets .css +//= link_tree ../../javascript .js +//= link_tree ../../../vendor/javascript .js +//= link_tree ../builds diff --git a/app/helpers/expenses_helper.rb b/app/helpers/expenses_helper.rb index 263c8f3..739166e 100644 --- a/app/helpers/expenses_helper.rb +++ b/app/helpers/expenses_helper.rb @@ -2,6 +2,6 @@ module ExpensesHelper def expense_periods Expense .periods - .map { |key, value| [ key.titleize, Expense.periods.key(value) ] } + .map { |key, value| [key.titleize, Expense.periods.key(value)] } end end diff --git a/app/helpers/incomes_helper.rb b/app/helpers/incomes_helper.rb index 8275806..9d6b84f 100644 --- a/app/helpers/incomes_helper.rb +++ b/app/helpers/incomes_helper.rb @@ -2,6 +2,6 @@ module IncomesHelper def members Member .all - .map { |member, value| [ member.name, member.id ] } + .map { |member, value| [member.name, member.id] } end end diff --git a/bin/docker-entrypoint b/bin/docker-entrypoint index 840d093..dffd4ba 100755 --- a/bin/docker-entrypoint +++ b/bin/docker-entrypoint @@ -1,12 +1,7 @@ #!/bin/bash -e -# Enable jemalloc for reduced memory usage and latency. -if [ -z "${LD_PRELOAD+x}" ] && [ -f /usr/lib/*/libjemalloc.so.2 ]; then - export LD_PRELOAD="$(echo /usr/lib/*/libjemalloc.so.2)" -fi - # If running the rails server then create or migrate existing database -if [ "${1}" == "./bin/rails" ] && [ "${2}" == "server" ]; then +if [ "${*}" == "./bin/rails server" ]; then ./bin/rails db:prepare fi diff --git a/config/application.rb b/config/application.rb index 36fd491..3526226 100644 --- a/config/application.rb +++ b/config/application.rb @@ -9,7 +9,7 @@ Bundler.require(*Rails.groups) module FamilyBudget class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 8.0 + config.load_defaults 7.1 # Please, add to the `ignore` list any other `lib` subdirectories that do # not contain `.rb` files, or that should not be reloaded or eager loaded. diff --git a/config/environments/development.rb b/config/environments/development.rb index d969821..61c8aa6 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -24,7 +24,7 @@ Rails.application.configure do config.action_controller.enable_fragment_cache_logging = true 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 @@ -39,7 +39,7 @@ Rails.application.configure do config.action_mailer.perform_caching = false - config.action_mailer.default_url_options = { host: "localhost", port: 3000 } + config.action_mailer.default_url_options = {host: "localhost", port: 3000} # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log diff --git a/config/environments/production.rb b/config/environments/production.rb index 8f42c8c..e0ae758 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -60,7 +60,7 @@ Rails.application.configure do .then { |logger| ActiveSupport::TaggedLogging.new(logger) } # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] + config.log_tags = [:request_id] # "info" includes generic and useful information about system operation, but avoids logging too much # information to avoid inadvertent exposure of personally identifiable information (PII). If you diff --git a/config/environments/test.rb b/config/environments/test.rb index 83d1fa9..3064700 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -18,7 +18,7 @@ Rails.application.configure do 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}" } + config.public_file_server.headers = {"Cache-Control" => "public, max-age=#{1.hour.to_i}"} # Show full error reports and disable caching. config.consider_all_requests_local = true @@ -43,7 +43,7 @@ Rails.application.configure do # 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" } + config.action_mailer.default_url_options = {host: "www.example.com"} # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb index e2db3a5..2ac80b6 100644 --- a/test/application_system_test_case.rb +++ b/test/application_system_test_case.rb @@ -3,5 +3,5 @@ require "test_helper" class ApplicationSystemTestCase < ActionDispatch::SystemTestCase driven_by :selenium, using: ENV["VISIBLE_SYSTEM_TESTS"].present? ? :chrome : :headless_chrome, - screen_size: [ 1400, 1400 ] + screen_size: [1400, 1400] end