From d9fcf1cfd7a980f159f0ad3770ac80e6a04ba72c Mon Sep 17 00:00:00 2001 From: elg0nz Date: Tue, 20 May 2025 14:53:00 -0700 Subject: [PATCH 01/23] add UPGRADE_PLAN.md --- .ruby-version | 2 +- UPGRADE_PLAN.md | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 UPGRADE_PLAN.md diff --git a/.ruby-version b/.ruby-version index 1f7da99d..f9892605 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.7 +3.4.4 diff --git a/UPGRADE_PLAN.md b/UPGRADE_PLAN.md new file mode 100644 index 00000000..9a9cc800 --- /dev/null +++ b/UPGRADE_PLAN.md @@ -0,0 +1,113 @@ +# Ruby and Rails Upgrade Plan + +This document outlines the steps to upgrade this project to the latest stable versions of Ruby and Rails. + +## 1. Assessment + +* [ ] **Determine Current Versions:** + * Ruby version: `2.7.7` (from `.ruby-version`) + * Rails version: `6.0.4.7` (from `Gemfile.lock`) +* [ ] **Identify Key Dependencies:** + * Review `Gemfile` and `Gemfile.lock` for critical gems. + * Note versions of major gems (e.g., Devise, Sidekiq, database adapters). +* [ ] **Review Existing Test Coverage:** + * Ensure tests are comprehensive and passing before starting the upgrade. + * Note current test coverage percentage if available. + +## 2. Research & Planning + +* [ ] **Identify Target Versions:** + * Latest stable Ruby version: `3.4.4` (as of May 2025) + * Latest stable Rails version: `8.0.x` (e.g., `8.0.0.1` or newer patch, as of May 2025) +* [ ] **Consult Official Documentation:** + * Read Ruby release notes for versions between current and target. + * Read Rails upgrade guides (e.g., `https://guides.rubyonrails.org/upgrading_ruby_on_rails.html`). Pay close attention to breaking changes. +* [ ] **Check Gem Compatibility:** + * Use resources like [RubyGems.org](https://rubygems.org/) or [The Ruby Toolbox](https://www.ruby-toolbox.com/) to check compatibility of key gems with target Ruby/Rails versions. + * Identify any gems that need updating or replacing. +* [ ] **Decide on Upgrade Strategy:** + * **Incremental Jumps (Recommended for large upgrades):** Upgrade Rails one minor version at a time (e.g., 5.1 -> 5.2 -> 6.0 -> 6.1 -> 7.0 -> 7.1). This makes debugging easier. + * **Direct to Latest:** Possible for smaller upgrades or if time is a constraint, but carries higher risk. + * Create a new branch for the upgrade: `git checkout -b upgrade-ruby-rails` + +## 3. Execution - Ruby Upgrade + +* [ ] **Update Local Ruby Version:** + * Use a version manager (e.g., `rbenv install `, `rvm install `). + * Set the local version: `rbenv local ` or `rvm use `. +* [ ] **Update Project Ruby Version:** + * Modify `.ruby-version` file (if used). + * Update Ruby version in `Gemfile`: `ruby ''`. +* [ ] **Install Gems:** + * Run `bundle install`. + * Resolve any gem dependency issues. +* [ ] **Test Ruby Upgrade:** + * Run the test suite: `bundle exec rspec` (or `bundle exec rails test`). + * Fix any Ruby-specific errors. + +## 4. Execution - Rails Upgrade + +*This section might be repeated if doing incremental Rails version upgrades.* + +* [ ] **Update Rails Version in Gemfile:** + * Change `gem 'rails', '~> X.Y.Z'` to the next target version. +* [ ] **Update Rails Gem:** + * Run `bundle update rails`. This will attempt to update Rails and its dependencies. +* [ ] **Run Rails Update Task:** + * `bundle exec rails app:update` (for Rails 5+) or `bundle exec rake rails:update` (older versions). + * Carefully review changes to configuration files (initializers, `routes.rb`, etc.). Use `d` to see diffs and decide whether to overwrite. It's often safer to review and merge manually. +* [ ] **Address Deprecations and Breaking Changes:** + * Consult the specific Rails version upgrade guide. + * Run tests frequently. Look for deprecation warnings in test output and server logs. +* [ ] **Update Other Gems:** + * Address any gem incompatibilities flagged during `bundle update` or testing. Update other gems as necessary. +* [ ] **Install Gems:** + * Run `bundle install` again if gems were changed. +* [ ] **Test Rails Upgrade Increment:** + * Run the full test suite: `bundle exec rspec` (or `bundle exec rails test`). + * Fix any Rails-specific errors and deprecations. + * Commit changes: `git commit -m "Upgrade to Rails X.Y"` + +## 5. Testing (After Final Target Version is Reached) + +* [ ] **Run All Automated Tests:** + * Ensure the entire test suite passes on the final target Ruby and Rails versions. +* [ ] **Perform Thorough Manual Testing:** + * Test all critical user flows and application features in a development/staging environment. + * Check for UI/UX issues. + * Test background jobs, API endpoints, and integrations. +* [ ] **Address Bugs and Regressions:** + * Fix any issues identified during automated or manual testing. + +## 6. Code Refactoring & Cleanup (Optional but Recommended) + +* [ ] **Adopt New Rails Features:** + * Leverage new APIs, conventions, or features introduced in the upgraded Rails versions (e.g., Zeitwerk autoloader, Action Cable improvements, Active Storage variants). +* [ ] **Remove Old Workarounds:** + * Delete any monkey patches or code that was specific to older versions. +* [ ] **Review Deprecation Warnings:** + * Ensure all deprecation warnings have been addressed. + +## 7. Deployment + +* [ ] **Prepare Production Environment:** + * Ensure the production servers have the target Ruby version installed. + * Update any necessary environment variables or configurations. +* [ ] **Deploy to Staging:** + * Deploy the upgraded application to a staging environment that mirrors production. + * Perform final smoke tests and user acceptance testing (UAT). +* [ ] **Production Deployment:** + * Schedule a maintenance window if necessary. + * Deploy to production. +* [ ] **Post-Deployment Monitoring:** + * Closely monitor application logs, error tracking services, and performance metrics. + * Be prepared to roll back if critical issues arise. + +## Notes & Potential Issues + +* [Add any project-specific notes, known problematic gems, or areas of concern here] +* **Bundler version:** Consider updating Bundler itself (`gem install bundler`, `bundle update --bundler`). +* **Database considerations:** Check if any database-specific configurations or adapter gems need updates. + +--- +This plan is a general guideline. Adjust it based on your project's specific needs and complexity. From fa0e9b299694a12393d7dab1d91bd1285990f206 Mon Sep 17 00:00:00 2001 From: elg0nz Date: Wed, 21 May 2025 09:41:11 -0700 Subject: [PATCH 02/23] WIP --- .ruby-version | 2 +- .tool-versions | 1 + Dockerfile | 37 ++- Gemfile | 7 + Gemfile.lock | 608 +++++++++++++++++++++++++----------------- UPGRADE_PLAN.md | 242 +++++++++++++---- config/application.rb | 2 +- docker-compose.yml | 83 ++++-- 8 files changed, 653 insertions(+), 329 deletions(-) create mode 100644 .tool-versions diff --git a/.ruby-version b/.ruby-version index f9892605..6cb9d3dd 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.4.4 +3.4.3 diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 00000000..a72ead61 --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +ruby 3.4.3 diff --git a/Dockerfile b/Dockerfile index dc012bf9..cb069678 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,38 @@ -FROM ruby:2.7.1-slim +FROM ruby:3.4.3-slim +# Install essential packages, PostgreSQL client, and a JavaScript runtime RUN apt-get update -qq && \ - apt-get install -y build-essential curl cmake git libpq-dev tzdata + apt-get install -y --no-install-recommends \ + build-essential \ + curl \ + git \ + libpq-dev \ + nodejs \ + npm \ + tzdata && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -RUN mkdir /app +# Set the working directory in the container WORKDIR /app -RUN gem install bundler -v 2.0.1 +# Copy Gemfile and Gemfile.lock to leverage Docker cache +COPY Gemfile Gemfile.lock ./ + +# Install Bundler. Use a version compatible with your Gemfile.lock (e.g., if BUNDLED WITH is 2.6.9, this covers it) +RUN gem install bundler -v '~> 2.4' --conservative --minimal-deps + +# Configure Bundler to install gems to /usr/local/bundle (shared volume via docker-compose) +ENV BUNDLE_PATH /usr/local/bundle + +# Install gems +RUN bundle install --jobs $(nproc) --retry 3 + +# Copy the rest of the application code into the container +COPY . . + +# Expose the port Rails runs on +EXPOSE 3000 +# Default command to start the application (can be overridden) CMD ["bash"] diff --git a/Gemfile b/Gemfile index 9f10967a..45add399 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,11 @@ source "https://rubygems.org" ruby File.read(".ruby-version").strip +gem 'concurrent-ruby', '1.3.4' +gem 'mutex_m' +gem 'drb' +gem 'benchmark' +gem 'ostruct' gem "rails", "~>6.0" gem "jquery-rails", ">= 4.3.5" @@ -30,6 +35,7 @@ gem "coffee-rails", ">= 4.2.2" gem "bootstrap-sass" gem "jquery-datatables-rails", ">= 3.4.0" gem 'jwt' +gem "rubyzip", "~> 2.4.1" # Avoid low-severity security issue: https://github.com/advisories/GHSA-vr8q-g5c7-m54m gem "nokogiri", ">= 1.11.0.rc4" @@ -59,6 +65,7 @@ group :production do end group :test do + gem "minitest", ">= 5.22.0" gem "capybara" gem "webdrivers" gem "database_cleaner" diff --git a/Gemfile.lock b/Gemfile.lock index d72d2e77..9943d771 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,122 +1,139 @@ GEM remote: https://rubygems.org/ specs: - actioncable (6.0.4.7) - actionpack (= 6.0.4.7) + actioncable (6.1.7.10) + actionpack (= 6.1.7.10) + activesupport (= 6.1.7.10) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.4.7) - actionpack (= 6.0.4.7) - activejob (= 6.0.4.7) - activerecord (= 6.0.4.7) - activestorage (= 6.0.4.7) - activesupport (= 6.0.4.7) + actionmailbox (6.1.7.10) + actionpack (= 6.1.7.10) + activejob (= 6.1.7.10) + activerecord (= 6.1.7.10) + activestorage (= 6.1.7.10) + activesupport (= 6.1.7.10) mail (>= 2.7.1) - actionmailer (6.0.4.7) - actionpack (= 6.0.4.7) - actionview (= 6.0.4.7) - activejob (= 6.0.4.7) + actionmailer (6.1.7.10) + actionpack (= 6.1.7.10) + actionview (= 6.1.7.10) + activejob (= 6.1.7.10) + activesupport (= 6.1.7.10) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.4.7) - actionview (= 6.0.4.7) - activesupport (= 6.0.4.7) - rack (~> 2.0, >= 2.0.8) + actionpack (6.1.7.10) + actionview (= 6.1.7.10) + activesupport (= 6.1.7.10) + rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.4.7) - actionpack (= 6.0.4.7) - activerecord (= 6.0.4.7) - activestorage (= 6.0.4.7) - activesupport (= 6.0.4.7) + actiontext (6.1.7.10) + actionpack (= 6.1.7.10) + activerecord (= 6.1.7.10) + activestorage (= 6.1.7.10) + activesupport (= 6.1.7.10) nokogiri (>= 1.8.5) - actionview (6.0.4.7) - activesupport (= 6.0.4.7) + actionview (6.1.7.10) + activesupport (= 6.1.7.10) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.4.7) - activesupport (= 6.0.4.7) + activejob (6.1.7.10) + activesupport (= 6.1.7.10) globalid (>= 0.3.6) - activemodel (6.0.4.7) - activesupport (= 6.0.4.7) - activerecord (6.0.4.7) - activemodel (= 6.0.4.7) - activesupport (= 6.0.4.7) - activestorage (6.0.4.7) - actionpack (= 6.0.4.7) - activejob (= 6.0.4.7) - activerecord (= 6.0.4.7) - marcel (~> 1.0.0) - activesupport (6.0.4.7) + activemodel (6.1.7.10) + activesupport (= 6.1.7.10) + activerecord (6.1.7.10) + activemodel (= 6.1.7.10) + activesupport (= 6.1.7.10) + activestorage (6.1.7.10) + actionpack (= 6.1.7.10) + activejob (= 6.1.7.10) + activerecord (= 6.1.7.10) + activesupport (= 6.1.7.10) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (6.1.7.10) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) annotate (3.2.0) activerecord (>= 3.2, < 8.0) rake (>= 10.4, < 14.0) - ast (2.4.2) - autoprefixer-rails (9.6.0) - execjs + ast (2.4.3) + autoprefixer-rails (10.4.21.0) + execjs (~> 2) awesome_print (1.9.2) - aws-eventstream (1.2.0) - aws-partitions (1.607.0) - aws-record (2.7.0) - aws-sdk-dynamodb (~> 1.18) - aws-sdk-core (3.131.2) - aws-eventstream (~> 1, >= 1.0.2) - aws-partitions (~> 1, >= 1.525.0) - aws-sigv4 (~> 1.1) + aws-eventstream (1.3.2) + aws-partitions (1.1106.0) + aws-record (2.13.3) + aws-sdk-dynamodb (~> 1, >= 1.85.0) + aws-sdk-core (3.224.0) + aws-eventstream (~> 1, >= 1.3.0) + aws-partitions (~> 1, >= 1.992.0) + aws-sigv4 (~> 1.9) + base64 jmespath (~> 1, >= 1.6.1) - aws-sdk-dynamodb (1.75.0) - aws-sdk-core (~> 3, >= 3.127.0) - aws-sigv4 (~> 1.1) - aws-sdk-rails (3.6.2) + logger + aws-sdk-dynamodb (1.144.0) + aws-sdk-core (~> 3, >= 3.216.0) + aws-sigv4 (~> 1.5) + aws-sdk-rails (3.13.0) aws-record (~> 2) - aws-sdk-ses (~> 1) - aws-sdk-sqs (~> 1) + aws-sdk-ses (~> 1, >= 1.50.0) + aws-sdk-sesv2 (~> 1, >= 1.34.0) + aws-sdk-sqs (~> 1, >= 1.56.0) aws-sessionstore-dynamodb (~> 2) - concurrent-ruby (~> 1) + concurrent-ruby (>= 1.3.1) railties (>= 5.2.0) - aws-sdk-ses (1.47.0) - aws-sdk-core (~> 3, >= 3.127.0) - aws-sigv4 (~> 1.1) - aws-sdk-sqs (1.51.1) - aws-sdk-core (~> 3, >= 3.127.0) - aws-sigv4 (~> 1.1) - aws-sessionstore-dynamodb (2.0.1) - aws-sdk-dynamodb (~> 1) - rack (~> 2) - aws-sigv4 (1.5.0) + aws-sdk-ses (1.84.0) + aws-sdk-core (~> 3, >= 3.216.0) + aws-sigv4 (~> 1.5) + aws-sdk-sesv2 (1.76.0) + aws-sdk-core (~> 3, >= 3.216.0) + aws-sigv4 (~> 1.5) + aws-sdk-sqs (1.95.0) + aws-sdk-core (~> 3, >= 3.216.0) + aws-sigv4 (~> 1.5) + aws-sessionstore-dynamodb (2.2.0) + aws-sdk-dynamodb (~> 1, >= 1.85.0) + rack (>= 2, < 4) + rack-session (>= 1, < 3) + aws-sigv4 (1.11.0) aws-eventstream (~> 1, >= 1.0.2) - better_errors (2.9.1) - coderay (>= 1.0.0) + base64 (0.2.0) + benchmark (0.4.0) + better_errors (2.10.1) erubi (>= 1.0.0) rack (>= 0.9.0) - binding_of_caller (1.0.0) - debug_inspector (>= 0.0.1) + rouge (>= 1.0.0) + bigdecimal (3.1.9) + binding_of_caller (1.0.1) + debug_inspector (>= 1.2.0) bootstrap-sass (3.4.1) autoprefixer-rails (>= 5.2.1) sassc (>= 2.0.0) - brakeman (5.4.0) - bugsnag (6.24.2) + brakeman (7.0.2) + racc + bugsnag (6.27.1) concurrent-ruby (~> 1.0) - builder (3.2.4) - capybara (3.37.1) + builder (3.3.0) + capybara (3.40.0) addressable matrix mini_mime (>= 0.1.3) - nokogiri (~> 1.8) + nokogiri (~> 1.11) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) + childprocess (5.1.0) + logger (~> 1.5) coderay (1.1.3) coffee-rails (5.0.0) coffee-script (>= 2.2.0) @@ -125,49 +142,58 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.2.0) + concurrent-ruby (1.3.4) configurable_engine (2.0.2) rails (> 5.2.0) crass (1.0.6) dante (0.2.0) - database_cleaner (2.0.1) - database_cleaner-active_record (~> 2.0.0) - database_cleaner-active_record (2.0.1) + database_cleaner (2.1.0) + database_cleaner-active_record (>= 2, < 3) + database_cleaner-active_record (2.2.1) activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) - debug_inspector (1.1.0) - diff-lcs (1.5.0) - docile (1.4.0) - email_spec (2.2.0) + date (3.4.1) + debug_inspector (1.2.0) + diff-lcs (1.6.2) + docile (1.4.1) + drb (2.2.1) + email_spec (2.3.0) htmlentities (~> 4.3.3) - launchy (~> 2.1) + launchy (>= 2.1, < 4.0) mail (~> 2.7) - erubi (1.10.0) + erubi (1.13.1) erubis (2.7.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) + execjs (2.10.0) + factory_bot (6.5.1) + activesupport (>= 6.1.0) + factory_bot_rails (6.4.4) + factory_bot (~> 6.5) railties (>= 5.0.0) - faker (2.23.0) + faker (3.5.1) i18n (>= 1.8.11, < 2) - faraday (0.17.5) + faraday (0.17.6) multipart-post (>= 1.2, < 3) - ffi (1.13.1) + ffi (1.17.2-aarch64-linux-gnu) + ffi (1.17.2-aarch64-linux-musl) + ffi (1.17.2-arm-linux-gnu) + ffi (1.17.2-arm-linux-musl) + ffi (1.17.2-arm64-darwin) + ffi (1.17.2-x86_64-darwin) + ffi (1.17.2-x86_64-linux-gnu) + ffi (1.17.2-x86_64-linux-musl) figaro (1.2.0) thor (>= 0.14.0, < 2) - globalid (1.1.0) - activesupport (>= 5.0) - haml (5.2.2) - temple (>= 0.8.0) + globalid (1.2.1) + activesupport (>= 6.1) + haml (6.3.0) + temple (>= 0.8.2) + thor tilt - haml-rails (2.0.1) + haml-rails (2.1.0) actionpack (>= 5.1) activesupport (>= 5.1) - haml (>= 4.0.6, < 6.0) - html2haml (>= 1.0.1) + haml (>= 4.0.6) railties (>= 5.1) hashie (5.0.0) html2haml (2.3.0) @@ -176,23 +202,24 @@ GEM nokogiri (>= 1.6.0) ruby_parser (~> 3.5) htmlentities (4.3.4) - i18n (1.12.0) + i18n (1.14.7) concurrent-ruby (~> 1.0) - jbuilder (2.11.5) + jbuilder (2.13.0) actionview (>= 5.0.0) activesupport (>= 5.0.0) - jmespath (1.6.1) + jmespath (1.6.2) jquery-datatables-rails (3.4.0) actionpack (>= 3.1) jquery-rails railties (>= 3.1) sass-rails - jquery-rails (4.5.0) + jquery-rails (4.6.0) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - json (2.6.2) - jwt (2.3.0) + json (2.12.0) + jwt (2.10.1) + base64 kaminari (1.2.2) activesupport (>= 4.1.0) kaminari-actionview (= 1.2.2) @@ -206,187 +233,252 @@ GEM kaminari-core (= 1.2.2) kaminari-core (1.2.2) kgio (2.11.4) - launchy (2.5.0) - addressable (~> 2.7) - loofah (2.19.1) + language_server-protocol (3.17.0.5) + launchy (3.1.1) + addressable (~> 2.8) + childprocess (~> 5.0) + logger (~> 1.6) + lint_roller (1.1.0) + logger (1.7.0) + loofah (2.24.1) crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.1) + nokogiri (>= 1.12.0) + mail (2.8.1) mini_mime (>= 0.1.1) - marcel (1.0.2) + net-imap + net-pop + net-smtp + marcel (1.0.4) matrix (0.4.2) - method_source (1.0.0) - mini_mime (1.1.2) - mini_portile2 (2.8.1) - minitest (5.17.0) + method_source (1.1.0) + mini_mime (1.1.5) + minitest (5.25.5) multi_json (1.15.0) - multi_xml (0.6.0) - multipart-post (2.2.3) - nio4r (2.5.8) - nokogiri (1.14.1) - mini_portile2 (~> 2.8.0) + multi_xml (0.7.2) + bigdecimal (~> 3.1) + multipart-post (2.4.1) + mutex_m (0.3.0) + net-imap (0.5.8) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.5.1) + net-protocol + nio4r (2.7.4) + nokogiri (1.18.8-aarch64-linux-gnu) + racc (~> 1.4) + nokogiri (1.18.8-aarch64-linux-musl) + racc (~> 1.4) + nokogiri (1.18.8-arm-linux-gnu) + racc (~> 1.4) + nokogiri (1.18.8-arm-linux-musl) racc (~> 1.4) - oauth2 (1.4.9) - faraday (>= 0.17.3, < 3.0) - jwt (>= 1.0, < 3.0) - multi_json (~> 1.3) + nokogiri (1.18.8-arm64-darwin) + racc (~> 1.4) + nokogiri (1.18.8-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.18.8-x86_64-linux-gnu) + racc (~> 1.4) + nokogiri (1.18.8-x86_64-linux-musl) + racc (~> 1.4) + oauth2 (2.0.10) + faraday (>= 0.17.3, < 4.0) + jwt (>= 1.0, < 4.0) + logger (~> 1.2) multi_xml (~> 0.5) - rack (>= 1.2, < 3) - omniauth (1.9.2) + rack (>= 1.2, < 4) + snaky_hash (~> 2.0) + version_gem (>= 1.1.8, < 3) + omniauth (2.1.3) hashie (>= 3.4.6) - rack (>= 1.6.2, < 3) - omniauth-github (1.4.0) - omniauth (~> 1.5) - omniauth-oauth2 (>= 1.4.0, < 2.0) - omniauth-google-oauth2 (0.8.2) - jwt (>= 2.0) - oauth2 (~> 1.1) - omniauth (~> 1.1) - omniauth-oauth2 (>= 1.6) - omniauth-oauth2 (1.7.2) - oauth2 (~> 1.4) - omniauth (>= 1.9, < 3) - parallel (1.22.1) - parser (3.1.2.1) + rack (>= 2.2.3) + rack-protection + omniauth-github (2.0.1) + omniauth (~> 2.0) + omniauth-oauth2 (~> 1.8) + omniauth-google-oauth2 (1.2.1) + jwt (>= 2.9.2) + oauth2 (~> 2.0) + omniauth (~> 2.0) + omniauth-oauth2 (~> 1.8) + omniauth-oauth2 (1.8.0) + oauth2 (>= 1.4, < 3) + omniauth (~> 2.0) + ostruct (0.6.1) + parallel (1.27.0) + parser (3.3.8.0) ast (~> 2.4.1) - pg (1.4.3) - protected_attributes_continued (1.8.2) + racc + pg (1.5.9) + prism (1.4.0) + protected_attributes_continued (1.9.0) activemodel (>= 5.0) - pry (0.14.1) + pry (0.15.2) coderay (~> 1.1) method_source (~> 1.0) - pry-rails (0.3.9) - pry (>= 0.10.4) - public_suffix (4.0.7) - puma (5.6.5) + pry-rails (0.3.11) + pry (>= 0.13.0) + public_suffix (6.0.2) + puma (5.6.9) nio4r (~> 2.0) - racc (1.6.2) - rack (2.2.6.2) - rack-canonical-host (1.1.0) + racc (1.8.1) + rack (2.2.15) + rack-canonical-host (1.3.0) addressable (> 0, < 3) - rack (>= 1.0.0, < 3) - rack-cors (1.1.1) + rack (>= 1.6, < 4) + rack-cors (2.0.2) rack (>= 2.0.0) - rack-test (2.0.2) + rack-protection (3.2.0) + base64 (>= 0.1.0) + rack (~> 2.2, >= 2.2.4) + rack-session (1.0.2) + rack (< 3) + rack-test (2.2.0) rack (>= 1.3) rack_session_access (0.2.0) builder (>= 2.0.0) rack (>= 1.0.0) - rails (6.0.4.7) - actioncable (= 6.0.4.7) - actionmailbox (= 6.0.4.7) - actionmailer (= 6.0.4.7) - actionpack (= 6.0.4.7) - actiontext (= 6.0.4.7) - actionview (= 6.0.4.7) - activejob (= 6.0.4.7) - activemodel (= 6.0.4.7) - activerecord (= 6.0.4.7) - activestorage (= 6.0.4.7) - activesupport (= 6.0.4.7) - bundler (>= 1.3.0) - railties (= 6.0.4.7) + rails (6.1.7.10) + actioncable (= 6.1.7.10) + actionmailbox (= 6.1.7.10) + actionmailer (= 6.1.7.10) + actionpack (= 6.1.7.10) + actiontext (= 6.1.7.10) + actionview (= 6.1.7.10) + activejob (= 6.1.7.10) + activemodel (= 6.1.7.10) + activerecord (= 6.1.7.10) + activestorage (= 6.1.7.10) + activesupport (= 6.1.7.10) + bundler (>= 1.15.0) + railties (= 6.1.7.10) sprockets-rails (>= 2.0.0) 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) + rails-dom-testing (2.3.0) + activesupport (>= 5.0.0) + minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.5.0) - loofah (~> 2.19, >= 2.19.1) + rails-html-sanitizer (1.6.2) + loofah (~> 2.21) + 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) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging - rails_autolink (1.1.6) - rails (> 3.1) + rails_autolink (1.1.8) + actionview (> 3.1) + activesupport (> 3.1) + railties (> 3.1) rails_serve_static_assets (0.0.5) rails_stdout_logging (0.0.5) - railties (6.0.4.7) - actionpack (= 6.0.4.7) - activesupport (= 6.0.4.7) + railties (6.1.7.10) + actionpack (= 6.1.7.10) + activesupport (= 6.1.7.10) method_source - rake (>= 0.8.7) - thor (>= 0.20.3, < 2.0) + rake (>= 12.2) + thor (~> 1.0) rainbow (3.1.1) - raindrops (0.20.0) - rake (13.0.6) - redcarpet (3.5.1) - regexp_parser (2.5.0) - rexml (3.2.5) - rspec-collection_matchers (1.2.0) + raindrops (0.20.1) + rake (13.2.1) + redcarpet (3.6.1) + regexp_parser (2.10.0) + rexml (3.4.1) + rouge (4.5.2) + rspec-collection_matchers (1.2.1) rspec-expectations (>= 2.99.0.beta1) - rspec-core (3.11.0) - rspec-support (~> 3.11.0) - rspec-expectations (3.11.0) + rspec-core (3.13.3) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.4) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.11.0) - rspec-mocks (3.11.1) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.4) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.11.0) - rspec-rails (5.1.2) - actionpack (>= 5.2) - activesupport (>= 5.2) - railties (>= 5.2) - rspec-core (~> 3.10) - rspec-expectations (~> 3.10) - rspec-mocks (~> 3.10) - rspec-support (~> 3.10) - rspec-support (3.11.0) - rubocop (1.35.1) + rspec-support (~> 3.13.0) + rspec-rails (6.1.5) + actionpack (>= 6.1) + activesupport (>= 6.1) + railties (>= 6.1) + rspec-core (~> 3.13) + rspec-expectations (~> 3.13) + rspec-mocks (~> 3.13) + rspec-support (~> 3.13) + rspec-support (3.13.3) + rubocop (1.75.6) json (~> 2.3) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) parallel (~> 1.10) - parser (>= 3.1.2.1) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.20.1, < 2.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.44.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.21.0) - parser (>= 3.1.1.0) - rubocop-performance (1.14.3) - rubocop (>= 1.7.0, < 2.0) - rubocop-ast (>= 0.4.0) - ruby-progressbar (1.11.0) - ruby_parser (3.19.1) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.44.1) + parser (>= 3.3.7.2) + prism (~> 1.4) + rubocop-performance (1.25.0) + lint_roller (~> 1.1) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.38.0, < 2.0) + ruby-progressbar (1.13.0) + ruby_parser (3.21.1) + racc (~> 1.5) sexp_processor (~> 4.16) - rubyzip (2.3.2) + rubyzip (2.4.1) sass-rails (6.0.0) sassc-rails (~> 2.1, >= 2.1.1) - sassc (2.0.1) + sassc (2.4.0) ffi (~> 1.9) - rake sassc-rails (2.1.2) railties (>= 4.0.0) sassc (>= 2.0) sprockets (> 3.0) sprockets-rails tilt - selenium-webdriver (4.8.1) + selenium-webdriver (4.32.0) + base64 (~> 0.2) + logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) - sexp_processor (4.16.1) - shoulda-matchers (5.3.0) + sexp_processor (4.17.3) + shoulda-matchers (6.5.0) activesupport (>= 5.2.0) simplecov (0.22.0) docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) - simplecov-html (0.12.3) + simplecov-html (0.13.1) simplecov_json_formatter (0.1.4) - sprockets (4.1.1) + snaky_hash (2.0.1) + hashie + version_gem (~> 1.1, >= 1.1.1) + sprockets (4.2.2) concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.4.2) - actionpack (>= 5.2) - activesupport (>= 5.2) + logger + rack (>= 2.2.4, < 4) + sprockets-rails (3.5.2) + actionpack (>= 6.1) + activesupport (>= 6.1) sprockets (>= 3.0.0) - standard (1.16.1) - rubocop (= 1.35.1) - rubocop-performance (= 1.14.3) + standard (1.50.0) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.75.5) + standard-custom (~> 1.0.0) + standard-performance (~> 1.8) + standard-custom (1.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.50) + standard-performance (1.8.0) + lint_roller (~> 1.1) + rubocop-performance (~> 1.25.0) state_machine_deuxito (0.0.1) stripe (3.31.1) faraday (~> 0.10) @@ -394,44 +486,56 @@ GEM dante (>= 0.2.0) multi_json (~> 1.0) stripe (>= 2.0.3) - stripe_event (2.6.0) + stripe_event (2.12.0) activesupport (>= 3.1) - stripe (>= 2.8, < 8) - temple (0.8.2) - thor (1.2.1) - thread_safe (0.3.6) - tilt (2.0.11) - timecop (0.9.5) + stripe (>= 2.8, < 16) + temple (0.10.3) + thor (1.3.2) + tilt (2.6.0) + timecop (0.9.10) + timeout (0.4.3) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) - tzinfo (1.2.11) - thread_safe (~> 0.1) - uglifier (4.2.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + uglifier (4.2.1) execjs (>= 0.3.0, < 3) - unicode-display_width (2.2.0) + unicode-display_width (3.1.4) + unicode-emoji (~> 4.0, >= 4.0.4) + unicode-emoji (4.0.4) unicorn (6.1.0) kgio (~> 2.6) raindrops (~> 0.7) + version_gem (1.1.8) webdrivers (5.2.0) nokogiri (~> 1.6) rubyzip (>= 1.3.0) selenium-webdriver (~> 4.0) - websocket (1.2.9) - websocket-driver (0.7.5) + websocket (1.2.11) + websocket-driver (0.7.7) + base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.6) + zeitwerk (2.7.3) PLATFORMS - ruby + aarch64-linux-gnu + aarch64-linux-musl + arm-linux-gnu + arm-linux-musl + arm64-darwin + x86_64-darwin + x86_64-linux-gnu + x86_64-linux-musl DEPENDENCIES annotate awesome_print aws-sdk-rails (~> 3) + benchmark better_errors binding_of_caller bootstrap-sass @@ -439,8 +543,10 @@ DEPENDENCIES bugsnag capybara coffee-rails (>= 4.2.2) + concurrent-ruby (= 1.3.4) configurable_engine (~> 2) database_cleaner + drb email_spec factory_bot_rails (>= 6.1.0) faker @@ -453,10 +559,13 @@ DEPENDENCIES jwt kaminari (>= 1.2.1) launchy + minitest (>= 5.22.0) + mutex_m nokogiri (>= 1.11.0.rc4) omniauth omniauth-github omniauth-google-oauth2 + ostruct pg protected_attributes_continued pry @@ -472,6 +581,7 @@ DEPENDENCIES redcarpet rspec-collection_matchers rspec-rails (>= 4.0.0) + rubyzip (~> 2.4.1) sass-rails (>= 5.0.7) selenium-webdriver shoulda-matchers @@ -488,7 +598,7 @@ DEPENDENCIES webdrivers RUBY VERSION - ruby 2.7.7p221 + ruby 3.4.3p32 BUNDLED WITH - 2.1.4 + 2.6.9 diff --git a/UPGRADE_PLAN.md b/UPGRADE_PLAN.md index 9a9cc800..d70485da 100644 --- a/UPGRADE_PLAN.md +++ b/UPGRADE_PLAN.md @@ -1,13 +1,159 @@ # Ruby and Rails Upgrade Plan -This document outlines the steps to upgrade this project to the latest stable versions of Ruby and Rails. +This document outlines the steps to upgrade this project to the latest stable versions of Ruby and Rails, and how to set up the recommended Dockerized development environment. + +## 0. Dockerized Development & Testing Environment Setup + +These instructions outline how to set up and use the Docker-based environment for developing and testing the Arooo application. This is the recommended way to work on the project, especially during the upgrade process. + +### Prerequisites + +1. **Docker Desktop:** Install Docker Desktop for your operating system (Mac, Windows, or Linux). Make sure the Docker daemon is running. + * [Docker for Mac](https://docs.docker.com/docker-for-mac/install/) + * [Docker for Windows](https://docs.docker.com/docker-for-windows/install/) + * [Docker for Linux](https://docs.docker.com/engine/install/) (choose your distribution) +2. **Git:** Ensure Git is installed for cloning the repository. +3. **Code Editor:** Your preferred code editor (e.g., VS Code). + +### Getting Started + +1. **Clone the Repository:** + If you haven't already, clone your fork of the `arooo` repository: + ```bash + git clone https://github.com/YOUR_USERNAME/arooo.git + cd arooo + ``` + +2. **Review Docker Configuration:** + * `Dockerfile`: Defines the image for the Rails application, using Ruby 3.4.3. + * `docker-compose.yml`: Configures the `app` (Rails), `db` (PostgreSQL), and `test` services. + +3. **Configure Local Application Settings:** + * **Database Configuration:** + Copy the example database configuration if it doesn't exist: + ```bash + cp -n config/database.example.yml config/database.yml + ``` + Ensure your `config/database.yml` is set up to read credentials from environment variables for the `development` and `test` environments. The `docker-compose.yml` file provides these (e.g., `DATABASE_HOST`, `DATABASE_USERNAME`, `DATABASE_PASSWORD`). It should look something like this for the relevant sections: + ```yaml + # config/database.yml + + default: &default + adapter: postgresql + encoding: unicode + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + + development: + <<: *default + database: arooo_development # Or your preferred dev DB name + username: <%= ENV['DATABASE_USERNAME'] %> + password: <%= ENV['DATABASE_PASSWORD'] %> + host: <%= ENV['DATABASE_HOST'] %> + + test: + <<: *default + database: arooo_test # This will be the name of the test database + username: <%= ENV['DATABASE_USERNAME'] %> + password: <%= ENV['DATABASE_PASSWORD'] %> + host: <%= ENV['DATABASE_HOST'] %> + ``` + + * **Application Secrets & Credentials:** + * Copy the example application configuration: + ```bash + cp -n config/application.example.yml config/application.yml + ``` + * **`SECRET_KEY_BASE`**: The `docker-compose.yml` file requires `SECRET_KEY_BASE` to be set for both `app` and `test` services. You can generate new keys by running `bundle exec rake secret` locally (if you have a Ruby environment) or `docker-compose run --rm app bundle exec rake secret`. Add these to the `environment` section of the `app` and `test` services in `docker-compose.yml` or, preferably, manage them via your `config/application.yml` if Figaro is configured to load them and `docker-compose.yml` points to it. + Example for `docker-compose.yml` (less ideal for secrets, prefer Figaro): + ```yaml + # In docker-compose.yml under app: and test: services + environment: + # ... other env vars + SECRET_KEY_BASE: "your_generated_secret_for_app_or_test" + ``` + * **OAuth Keys (GitHub/Google):** For local development requiring OAuth, follow the instructions in `CONTRIBUTING.md` ("Set up an application for local OAuth") to generate keys. Add these to your `config/application.yml` (which is gitignored). + ```yaml + # config/application.yml + GITHUB_CLIENT_KEY: "your_github_client_key" + GITHUB_CLIENT_SECRET: "your_github_client_secret" + GOOGLE_CLIENT_ID: "your_google_client_id" + GOOGLE_CLIENT_SECRET: "your_google_client_secret" + ``` + * **`RAILS_MASTER_KEY`**: If the application uses encrypted credentials (`config/credentials.yml.enc`) and they are *essential* for the test or development environment, you'll need to provide `RAILS_MASTER_KEY` as an environment variable in `docker-compose.yml`. If not essential, a dummy value or omitting it might be fine, depending on Rails version and configuration. + +4. **Build Docker Images:** + This command builds the `app` image based on the `Dockerfile`. + ```bash + docker-compose build + ``` + *(For newer Docker versions, you might use `docker compose build`)* + +5. **Set up the Development Database:** + This command runs the `db:setup` rake task inside a temporary `app` container. + ```bash + docker-compose run --rm app bundle exec rake db:setup + ``` + +### Running the Application (Development) + +1. **Start Services:** + This starts the `app` and `db` services in detached mode. + ```bash + docker-compose up -d app db + ``` + *(Or `docker compose up -d app db`)* + +2. **Access the Application:** + Open your web browser and go to [http://localhost:3000](http://localhost:3000). + +3. **View Logs:** + ```bash + docker-compose logs -f app + ``` + +4. **Run Rails Console:** + ```bash + docker-compose exec app bundle exec rails console + ``` + +5. **Stop Services:** + ```bash + docker-compose down + ``` + +### Running Tests + +1. **Ensure Test Database is Prepared:** + The test command in `docker-compose.yml` includes `db:create` and `db:schema:load`. If you need to prepare it separately or reset it: + ```bash + docker-compose run --rm test bundle exec rake db:test:prepare + ``` + +2. **Run RSpec Tests:** + This command starts the `test` service (and its `db` dependency), runs the test preparation tasks, then executes `rspec`. The `--rm` flag removes the container after tests complete. + ```bash + docker-compose run --rm test + ``` + The command configured in `docker-compose.yml` for the `test` service is: + `bundle exec rake db:create db:schema:load && bundle exec rspec` + +### Troubleshooting Common Docker Issues + +* **Port Conflicts:** If port 3000 (for Rails) or 5432 (for PostgreSQL, if you choose to expose it) is in use on your host, `docker-compose up` will fail. Stop the conflicting service or change the port mapping in `docker-compose.yml` (e.g., `"3001:3000"`). +* **Volume Permission Issues (Linux):** Ensure the user running Docker has permissions to write to the mounted volumes. Sometimes, files created inside the container might have `root` ownership. +* **Outdated Images/Gems:** If you encounter strange errors, try rebuilding images without cache (`docker-compose build --no-cache`) and removing gem volumes (`docker-compose down -v` followed by `docker volume rm arooo_bundle_cache arooo_pg_data` - **Caution**: `arooo_pg_data` removal deletes your dev database). +* **Database Connection Errors:** + * Verify `DATABASE_HOST` in `config/database.yml` points to the service name in `docker-compose.yml` (which is `db`). + * Ensure `POSTGRES_USER` and `POSTGRES_PASSWORD` in the `db` service match what the `app` and `test` services expect (via `DATABASE_USERNAME`, `DATABASE_PASSWORD`). + +--- ## 1. Assessment -* [ ] **Determine Current Versions:** +* [x] **Determine Current Versions:** * Ruby version: `2.7.7` (from `.ruby-version`) * Rails version: `6.0.4.7` (from `Gemfile.lock`) -* [ ] **Identify Key Dependencies:** +* [x] **Identify Key Dependencies:** * Review `Gemfile` and `Gemfile.lock` for critical gems. * Note versions of major gems (e.g., Devise, Sidekiq, database adapters). * [ ] **Review Existing Test Coverage:** @@ -17,8 +163,8 @@ This document outlines the steps to upgrade this project to the latest stable ve ## 2. Research & Planning * [ ] **Identify Target Versions:** - * Latest stable Ruby version: `3.4.4` (as of May 2025) - * Latest stable Rails version: `8.0.x` (e.g., `8.0.0.1` or newer patch, as of May 2025) + * Latest stable Ruby version: `3.4.3` (as of May 2025, per our Dockerfile) + * Latest stable Rails version: `8.0.x` (e.g., `8.0.0.1` or newer patch, as of May 2025) - current interim target is `6.1.7.10`. * [ ] **Consult Official Documentation:** * Read Ruby release notes for versions between current and target. * Read Rails upgrade guides (e.g., `https://guides.rubyonrails.org/upgrading_ruby_on_rails.html`). Pay close attention to breaking changes. @@ -26,88 +172,82 @@ This document outlines the steps to upgrade this project to the latest stable ve * Use resources like [RubyGems.org](https://rubygems.org/) or [The Ruby Toolbox](https://www.ruby-toolbox.com/) to check compatibility of key gems with target Ruby/Rails versions. * Identify any gems that need updating or replacing. * [ ] **Decide on Upgrade Strategy:** - * **Incremental Jumps (Recommended for large upgrades):** Upgrade Rails one minor version at a time (e.g., 5.1 -> 5.2 -> 6.0 -> 6.1 -> 7.0 -> 7.1). This makes debugging easier. + * **Incremental Jumps (Recommended for large upgrades):** Upgrade Rails one minor version at a time (e.g., 6.0 -> 6.1 -> 7.0 -> 7.1 -> ...). This makes debugging easier. * **Direct to Latest:** Possible for smaller upgrades or if time is a constraint, but carries higher risk. * Create a new branch for the upgrade: `git checkout -b upgrade-ruby-rails` -## 3. Execution - Ruby Upgrade - -* [ ] **Update Local Ruby Version:** - * Use a version manager (e.g., `rbenv install `, `rvm install `). - * Set the local version: `rbenv local ` or `rvm use `. -* [ ] **Update Project Ruby Version:** - * Modify `.ruby-version` file (if used). - * Update Ruby version in `Gemfile`: `ruby ''`. -* [ ] **Install Gems:** - * Run `bundle install`. - * Resolve any gem dependency issues. -* [ ] **Test Ruby Upgrade:** - * Run the test suite: `bundle exec rspec` (or `bundle exec rails test`). - * Fix any Ruby-specific errors. +## 3. Execution - Ruby Upgrade (Accomplished via Dockerfile) + +* [x] **Update Local Ruby Version:** Managed by Docker image `ruby:3.4.3-slim`. +* [x] **Update Project Ruby Version:** + * `.ruby-version` should reflect `3.4.3` for local tooling if used outside Docker. + * `Gemfile` should specify `ruby '3.4.3'`. +* [x] **Install Gems:** Handled by `docker-compose build` and `bundle install` within Docker. +* [ ] **Test Ruby Upgrade:** Run tests within the Docker environment. ## 4. Execution - Rails Upgrade *This section might be repeated if doing incremental Rails version upgrades.* * [ ] **Update Rails Version in Gemfile:** - * Change `gem 'rails', '~> X.Y.Z'` to the next target version. -* [ ] **Update Rails Gem:** - * Run `bundle update rails`. This will attempt to update Rails and its dependencies. -* [ ] **Run Rails Update Task:** - * `bundle exec rails app:update` (for Rails 5+) or `bundle exec rake rails:update` (older versions). - * Carefully review changes to configuration files (initializers, `routes.rb`, etc.). Use `d` to see diffs and decide whether to overwrite. It's often safer to review and merge manually. + * Change `gem 'rails', '~> X.Y.Z'` to the next target version (e.g., `~> 6.1.7.10`). +* [ ] **Update Rails Gem (within Docker):** + * Rebuild the Docker image if `Gemfile` changes: `docker-compose build app test` + * Or run `docker-compose run --rm app bundle update rails` (and for `test` service if its bundle is separate or commit `Gemfile.lock` and rebuild). +* [ ] **Run Rails Update Task (within Docker):** + * `docker-compose run --rm app bundle exec rails app:update` + * Carefully review changes to configuration files. Use `d` to see diffs and decide whether to overwrite. It's often safer to review and merge manually. * [ ] **Address Deprecations and Breaking Changes:** * Consult the specific Rails version upgrade guide. - * Run tests frequently. Look for deprecation warnings in test output and server logs. -* [ ] **Update Other Gems:** - * Address any gem incompatibilities flagged during `bundle update` or testing. Update other gems as necessary. -* [ ] **Install Gems:** - * Run `bundle install` again if gems were changed. -* [ ] **Test Rails Upgrade Increment:** - * Run the full test suite: `bundle exec rspec` (or `bundle exec rails test`). + * Run tests frequently within Docker. Look for deprecation warnings. +* [ ] **Update Other Gems (within Docker):** + * Address any gem incompatibilities. Update other gems as necessary using `bundle update some_gem_name` inside the container or by editing `Gemfile` and rebuilding. +* [ ] **Install Gems (within Docker):** + * Ensure `Gemfile.lock` is updated and committed. `docker-compose build` will use it. +* [ ] **Test Rails Upgrade Increment (within Docker):** + * Run the full test suite: `docker-compose run --rm test`. * Fix any Rails-specific errors and deprecations. * Commit changes: `git commit -m "Upgrade to Rails X.Y"` ## 5. Testing (After Final Target Version is Reached) -* [ ] **Run All Automated Tests:** - * Ensure the entire test suite passes on the final target Ruby and Rails versions. -* [ ] **Perform Thorough Manual Testing:** - * Test all critical user flows and application features in a development/staging environment. +* [ ] **Run All Automated Tests (within Docker):** + * Ensure the entire test suite passes. +* [ ] **Perform Thorough Manual Testing (using Dockerized app):** + * Test all critical user flows. * Check for UI/UX issues. * Test background jobs, API endpoints, and integrations. * [ ] **Address Bugs and Regressions:** - * Fix any issues identified during automated or manual testing. + * Fix any issues identified. ## 6. Code Refactoring & Cleanup (Optional but Recommended) * [ ] **Adopt New Rails Features:** - * Leverage new APIs, conventions, or features introduced in the upgraded Rails versions (e.g., Zeitwerk autoloader, Action Cable improvements, Active Storage variants). + * Leverage new APIs, conventions, or features. * [ ] **Remove Old Workarounds:** - * Delete any monkey patches or code that was specific to older versions. + * Delete any monkey patches or code specific to older versions. * [ ] **Review Deprecation Warnings:** * Ensure all deprecation warnings have been addressed. -## 7. Deployment +## 7. Deployment (Considerations for Dockerized App) * [ ] **Prepare Production Environment:** - * Ensure the production servers have the target Ruby version installed. - * Update any necessary environment variables or configurations. -* [ ] **Deploy to Staging:** - * Deploy the upgraded application to a staging environment that mirrors production. - * Perform final smoke tests and user acceptance testing (UAT). -* [ ] **Production Deployment:** + * Production will need a Docker hosting solution (e.g., Heroku with Docker deploys, AWS ECS, Kubernetes). + * Ensure production Ruby version matches, or container handles it. +* [ ] **Deploy to Staging (using Docker):** + * Deploy the Dockerized application to a staging environment. + * Perform final smoke tests and UAT. +* [ ] **Production Deployment (using Docker):** * Schedule a maintenance window if necessary. * Deploy to production. * [ ] **Post-Deployment Monitoring:** - * Closely monitor application logs, error tracking services, and performance metrics. - * Be prepared to roll back if critical issues arise. + * Closely monitor application logs, error tracking, and performance. ## Notes & Potential Issues * [Add any project-specific notes, known problematic gems, or areas of concern here] -* **Bundler version:** Consider updating Bundler itself (`gem install bundler`, `bundle update --bundler`). -* **Database considerations:** Check if any database-specific configurations or adapter gems need updates. +* **Bundler version:** Dockerfile installs a compatible Bundler. Ensure `Gemfile.lock`'s `BUNDLED WITH` section is consistent. +* **Database considerations:** Docker setup uses PostgreSQL. Ensure any specific configurations are handled. --- This plan is a general guideline. Adjust it based on your project's specific needs and complexity. diff --git a/config/application.rb b/config/application.rb index a319c6aa..09be865c 100644 --- a/config/application.rb +++ b/config/application.rb @@ -8,7 +8,7 @@ module Doubleunion class Application < Rails::Application - config.load_defaults 6.0 + config.load_defaults 6.1 # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. diff --git a/docker-compose.yml b/docker-compose.yml index ba0e6a14..4c010770 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,34 +1,75 @@ -version: "3" +version: "3.8" + services: db: - image: postgres:10.6-alpine - ports: - - 5432:5432 + image: postgres:14-alpine volumes: - pg_data:/var/lib/postgresql/data environment: - - POSTGRES_PASSWORD=password + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password # Change this for production! + POSTGRES_DB: arooo_development # Optional: creates DB on init + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d arooo_development"] + interval: 10s + timeout: 5s + retries: 5 app: - build: . - depends_on: - - db + build: + context: . + dockerfile: Dockerfile + command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" + volumes: + - .:/app # Mounts the current directory to /app in the container for live code changes + - bundle_cache:/usr/local/bundle # Persists installed gems ports: - - 3000:3000 - command: /bin/sh -c "rm -f /app/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" + - "3000:3000" + depends_on: + db: + condition: service_healthy + environment: + RAILS_ENV: development + DATABASE_HOST: db + DATABASE_USERNAME: postgres + DATABASE_PASSWORD: password # Should match POSTGRES_PASSWORD in db service + # For Figaro, you might use these if your database.yml expects them via Figaro.env + # DB_HOST: db + # DB_USERNAME: postgres + # DB_PASSWORD: password + FIGARO_APPLICATION_YML_PATH: "config/application.yml" # If you want to point Figaro to it + SECRET_KEY_BASE: "your_development_secret_key_base_here_if_not_using_credentials_or_figaro_for_it" # Ensure this is set + + test: + build: + context: . + dockerfile: Dockerfile + command: /bin/sh -c "bundle exec rake db:create db:schema:load && bundle exec rspec" volumes: - .:/app - - bundle_cache:/bundle + - bundle_cache:/usr/local/bundle + depends_on: + db: + condition: service_healthy environment: - - BUNDLE_PATH=/bundle/vendor - - RAILS_ENV=development - - PSQL_USERNAME=postgres - - PSQL_PASSWORD=password - - PSQL_HOST=db - - SECRET_TOKEN=development - tty: true - stdin_open: true + RAILS_ENV: test + DATABASE_HOST: db + DATABASE_USERNAME: postgres + DATABASE_PASSWORD: password + # Ensure your config/database.yml for the 'test' environment is configured to use these variables. + # For example: + # test: + # adapter: postgresql + # encoding: unicode + # database: arooo_test # Or read from ENV + # host: <%= ENV['DATABASE_HOST'] %> + # username: <%= ENV['DATABASE_USERNAME'] %> + # password: <%= ENV['DATABASE_PASSWORD'] %> + # pool: 5 + FIGARO_APPLICATION_YML_PATH: "config/application.yml" # If test db config is in application.yml + RAILS_MASTER_KEY: "dummy_master_key_for_tests_if_needed" # if using encrypted credentials and they are needed for tests + SECRET_KEY_BASE: "your_test_secret_key_base_here" # Ensure this is set for test env volumes: - bundle_cache: - pg_data: + pg_data: # Persists PostgreSQL data + bundle_cache: # Persists gems From fef836a5fc743aa54ca0557ba0f5db3431e58ea0 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 13 Jun 2025 15:23:58 +0000 Subject: [PATCH 03/23] I've updated Ruby to 3.2.8 and Rails to 8.0.2. Here's a summary of the changes: - Ruby has been updated from version 2.7.7 to 3.2.8. - Rails has been updated from approximately version 6.0 to approximately 8.0.2. - I moved StripeEventHelper to lib/stripe_event_handlers. This was done to resolve a NameError that appeared after the Rails update, as initializers now run before helpers are typically loaded, and the lib directory is autoloaded. Please note that further testing and running `rails app:update` couldn't be completed due to the current environment's limitations. You'll need to perform these steps manually in your local environment. --- .ruby-version | 2 +- Gemfile | 2 +- Gemfile.lock | 299 +++++++++++------- bin/brakeman | 7 + bin/dev | 2 + bin/rails | 8 +- bin/rubocop | 8 + bin/setup | 33 +- config/application.rb | 40 +-- config/boot.rb | 2 +- config/cable.yml | 10 + config/environment.rb | 2 +- config/environments/development.rb | 75 +++-- config/environments/production.rb | 103 +++--- config/environments/test.rb | 54 ++-- config/initializers/assets.rb | 6 +- .../initializers/content_security_policy.rb | 25 ++ .../initializers/filter_parameter_logging.rb | 8 +- config/initializers/inflections.rb | 8 +- .../new_framework_defaults_8_0.rb | 30 ++ config/puma.rb | 41 +++ config/storage.yml | 34 ++ .../stripe_event_helper.rb | 0 public/400.html | 114 +++++++ public/404.html | 170 ++++++---- public/406-unsupported-browser.html | 114 +++++++ public/422.html | 170 ++++++---- public/500.html | 169 ++++++---- public/icon.png | Bin 0 -> 4166 bytes public/icon.svg | 3 + public/robots.txt | 6 +- 31 files changed, 1093 insertions(+), 452 deletions(-) create mode 100755 bin/brakeman create mode 100755 bin/dev create mode 100755 bin/rubocop create mode 100644 config/cable.yml create mode 100644 config/initializers/content_security_policy.rb create mode 100644 config/initializers/new_framework_defaults_8_0.rb create mode 100644 config/puma.rb create mode 100644 config/storage.yml rename {app/helpers => lib/stripe_event_handlers}/stripe_event_helper.rb (100%) create mode 100644 public/400.html create mode 100644 public/406-unsupported-browser.html create mode 100644 public/icon.png create mode 100644 public/icon.svg diff --git a/.ruby-version b/.ruby-version index 1f7da99d..f092941a 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.7 +3.2.8 diff --git a/Gemfile b/Gemfile index 9f10967a..9f0b3383 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" ruby File.read(".ruby-version").strip -gem "rails", "~>6.0" +gem "rails", "~> 8.0.2" gem "jquery-rails", ">= 4.3.5" gem "turbolinks" gem "jbuilder" diff --git a/Gemfile.lock b/Gemfile.lock index d72d2e77..59f89ddb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,66 +1,82 @@ GEM remote: https://rubygems.org/ specs: - actioncable (6.0.4.7) - actionpack (= 6.0.4.7) + actioncable (8.0.2) + actionpack (= 8.0.2) + activesupport (= 8.0.2) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.4.7) - actionpack (= 6.0.4.7) - activejob (= 6.0.4.7) - activerecord (= 6.0.4.7) - activestorage (= 6.0.4.7) - activesupport (= 6.0.4.7) - mail (>= 2.7.1) - actionmailer (6.0.4.7) - actionpack (= 6.0.4.7) - actionview (= 6.0.4.7) - activejob (= 6.0.4.7) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 2.0) - actionpack (6.0.4.7) - actionview (= 6.0.4.7) - activesupport (= 6.0.4.7) - rack (~> 2.0, >= 2.0.8) + zeitwerk (~> 2.6) + actionmailbox (8.0.2) + actionpack (= 8.0.2) + activejob (= 8.0.2) + activerecord (= 8.0.2) + activestorage (= 8.0.2) + activesupport (= 8.0.2) + mail (>= 2.8.0) + actionmailer (8.0.2) + actionpack (= 8.0.2) + actionview (= 8.0.2) + activejob (= 8.0.2) + activesupport (= 8.0.2) + mail (>= 2.8.0) + rails-dom-testing (~> 2.2) + actionpack (8.0.2) + actionview (= 8.0.2) + activesupport (= 8.0.2) + nokogiri (>= 1.8.5) + rack (>= 2.2.4) + rack-session (>= 1.0.1) rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.4.7) - actionpack (= 6.0.4.7) - activerecord (= 6.0.4.7) - activestorage (= 6.0.4.7) - activesupport (= 6.0.4.7) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + useragent (~> 0.16) + actiontext (8.0.2) + actionpack (= 8.0.2) + activerecord (= 8.0.2) + activestorage (= 8.0.2) + activesupport (= 8.0.2) + globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (6.0.4.7) - activesupport (= 6.0.4.7) + actionview (8.0.2) + activesupport (= 8.0.2) builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.4.7) - activesupport (= 6.0.4.7) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (8.0.2) + activesupport (= 8.0.2) globalid (>= 0.3.6) - activemodel (6.0.4.7) - activesupport (= 6.0.4.7) - activerecord (6.0.4.7) - activemodel (= 6.0.4.7) - activesupport (= 6.0.4.7) - activestorage (6.0.4.7) - actionpack (= 6.0.4.7) - activejob (= 6.0.4.7) - activerecord (= 6.0.4.7) - marcel (~> 1.0.0) - activesupport (6.0.4.7) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) + activemodel (8.0.2) + activesupport (= 8.0.2) + activerecord (8.0.2) + activemodel (= 8.0.2) + activesupport (= 8.0.2) + timeout (>= 0.4.0) + activestorage (8.0.2) + actionpack (= 8.0.2) + activejob (= 8.0.2) + activerecord (= 8.0.2) + activesupport (= 8.0.2) + marcel (~> 1.0) + activesupport (8.0.2) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) - annotate (3.2.0) - activerecord (>= 3.2, < 8.0) - rake (>= 10.4, < 14.0) + annotate (2.6.5) + activerecord (>= 2.3.0) + rake (>= 0.8.7) ast (2.4.2) autoprefixer-rails (9.6.0) execjs @@ -95,10 +111,13 @@ GEM rack (~> 2) aws-sigv4 (1.5.0) aws-eventstream (~> 1, >= 1.0.2) + base64 (0.3.0) + benchmark (0.4.1) better_errors (2.9.1) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) + bigdecimal (3.2.2) binding_of_caller (1.0.0) debug_inspector (>= 0.0.1) bootstrap-sass (3.4.1) @@ -107,7 +126,7 @@ GEM brakeman (5.4.0) bugsnag (6.24.2) concurrent-ruby (~> 1.0) - builder (3.2.4) + builder (3.3.0) capybara (3.37.1) addressable matrix @@ -125,9 +144,10 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.2.0) + concurrent-ruby (1.3.5) configurable_engine (2.0.2) rails (> 5.2.0) + connection_pool (2.5.3) crass (1.0.6) dante (0.2.0) database_cleaner (2.0.1) @@ -136,14 +156,17 @@ GEM activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) + date (3.4.1) debug_inspector (1.1.0) diff-lcs (1.5.0) docile (1.4.0) + drb (2.2.3) email_spec (2.2.0) htmlentities (~> 4.3.3) launchy (~> 2.1) mail (~> 2.7) - erubi (1.10.0) + erb (5.0.1) + erubi (1.13.1) erubis (2.7.0) execjs (2.8.1) factory_bot (6.2.1) @@ -153,13 +176,13 @@ GEM railties (>= 5.0.0) faker (2.23.0) i18n (>= 1.8.11, < 2) - faraday (0.17.5) + faraday (0.17.6) multipart-post (>= 1.2, < 3) ffi (1.13.1) figaro (1.2.0) thor (>= 0.14.0, < 2) - globalid (1.1.0) - activesupport (>= 5.0) + globalid (1.2.1) + activesupport (>= 6.1) haml (5.2.2) temple (>= 0.8.0) tilt @@ -176,9 +199,14 @@ GEM nokogiri (>= 1.6.0) ruby_parser (~> 3.5) htmlentities (4.3.4) - i18n (1.12.0) + i18n (1.14.7) concurrent-ruby (~> 1.0) - jbuilder (2.11.5) + io-console (0.8.0) + irb (1.15.2) + pp (>= 0.6.0) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + jbuilder (2.13.0) actionview (>= 5.0.0) activesupport (>= 5.0.0) jmespath (1.6.1) @@ -208,23 +236,36 @@ GEM kgio (2.11.4) launchy (2.5.0) addressable (~> 2.7) - loofah (2.19.1) + logger (1.7.0) + loofah (2.24.1) crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.1) + nokogiri (>= 1.12.0) + mail (2.8.1) mini_mime (>= 0.1.1) - marcel (1.0.2) + net-imap + net-pop + net-smtp + marcel (1.0.4) matrix (0.4.2) - method_source (1.0.0) - mini_mime (1.1.2) - mini_portile2 (2.8.1) - minitest (5.17.0) + method_source (1.1.0) + mini_mime (1.1.5) + mini_portile2 (2.8.9) + minitest (5.25.5) multi_json (1.15.0) multi_xml (0.6.0) - multipart-post (2.2.3) - nio4r (2.5.8) - nokogiri (1.14.1) - mini_portile2 (~> 2.8.0) + multipart-post (2.4.1) + net-imap (0.5.8) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.5.1) + net-protocol + nio4r (2.7.4) + nokogiri (1.18.8) + mini_portile2 (~> 2.8.2) racc (~> 1.4) oauth2 (1.4.9) faraday (>= 0.17.3, < 3.0) @@ -250,6 +291,9 @@ GEM parser (3.1.2.1) ast (~> 2.4.1) pg (1.4.3) + pp (0.6.2) + prettyprint + prettyprint (0.2.0) protected_attributes_continued (1.8.2) activemodel (>= 5.0) pry (0.14.1) @@ -257,45 +301,54 @@ GEM method_source (~> 1.0) pry-rails (0.3.9) pry (>= 0.10.4) + psych (5.2.6) + date + stringio public_suffix (4.0.7) puma (5.6.5) nio4r (~> 2.0) - racc (1.6.2) - rack (2.2.6.2) + racc (1.8.1) + rack (2.2.17) rack-canonical-host (1.1.0) addressable (> 0, < 3) rack (>= 1.0.0, < 3) rack-cors (1.1.1) rack (>= 2.0.0) - rack-test (2.0.2) + rack-session (1.0.2) + rack (< 3) + rack-test (2.2.0) rack (>= 1.3) rack_session_access (0.2.0) builder (>= 2.0.0) rack (>= 1.0.0) - rails (6.0.4.7) - actioncable (= 6.0.4.7) - actionmailbox (= 6.0.4.7) - actionmailer (= 6.0.4.7) - actionpack (= 6.0.4.7) - actiontext (= 6.0.4.7) - actionview (= 6.0.4.7) - activejob (= 6.0.4.7) - activemodel (= 6.0.4.7) - activerecord (= 6.0.4.7) - activestorage (= 6.0.4.7) - activesupport (= 6.0.4.7) - bundler (>= 1.3.0) - railties (= 6.0.4.7) - sprockets-rails (>= 2.0.0) + rackup (1.0.1) + rack (< 3) + webrick + rails (8.0.2) + actioncable (= 8.0.2) + actionmailbox (= 8.0.2) + actionmailer (= 8.0.2) + actionpack (= 8.0.2) + actiontext (= 8.0.2) + actionview (= 8.0.2) + activejob (= 8.0.2) + activemodel (= 8.0.2) + activerecord (= 8.0.2) + activestorage (= 8.0.2) + activesupport (= 8.0.2) + bundler (>= 1.15.0) + railties (= 8.0.2) 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) + rails-dom-testing (2.3.0) + activesupport (>= 5.0.0) + minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.5.0) - loofah (~> 2.19, >= 2.19.1) + rails-html-sanitizer (1.6.2) + loofah (~> 2.21) + 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) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging @@ -303,17 +356,24 @@ GEM rails (> 3.1) rails_serve_static_assets (0.0.5) rails_stdout_logging (0.0.5) - railties (6.0.4.7) - actionpack (= 6.0.4.7) - activesupport (= 6.0.4.7) - method_source - rake (>= 0.8.7) - thor (>= 0.20.3, < 2.0) + railties (8.0.2) + actionpack (= 8.0.2) + activesupport (= 8.0.2) + irb (~> 1.13) + rackup (>= 1.0.0) + rake (>= 12.2) + thor (~> 1.0, >= 1.2.2) + zeitwerk (~> 2.6) rainbow (3.1.1) raindrops (0.20.0) - rake (13.0.6) + rake (13.3.0) + rdoc (6.14.0) + erb + psych (>= 4.0.0) redcarpet (3.5.1) regexp_parser (2.5.0) + reline (0.6.1) + io-console (~> 0.5) rexml (3.2.5) rspec-collection_matchers (1.2.0) rspec-expectations (>= 2.99.0.beta1) @@ -364,6 +424,7 @@ GEM sprockets (> 3.0) sprockets-rails tilt + securerandom (0.4.1) selenium-webdriver (4.8.1) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) @@ -377,53 +438,59 @@ GEM simplecov_json_formatter (~> 0.1) simplecov-html (0.12.3) simplecov_json_formatter (0.1.4) - sprockets (4.1.1) + sprockets (4.2.2) concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.4.2) - actionpack (>= 5.2) - activesupport (>= 5.2) + logger + rack (>= 2.2.4, < 4) + sprockets-rails (3.5.2) + actionpack (>= 6.1) + activesupport (>= 6.1) sprockets (>= 3.0.0) standard (1.16.1) rubocop (= 1.35.1) rubocop-performance (= 1.14.3) state_machine_deuxito (0.0.1) + stringio (3.1.7) stripe (3.31.1) faraday (~> 0.10) stripe-ruby-mock (2.5.8) dante (>= 0.2.0) multi_json (~> 1.0) stripe (>= 2.0.3) - stripe_event (2.6.0) + stripe_event (2.12.0) activesupport (>= 3.1) - stripe (>= 2.8, < 8) + stripe (>= 2.8, < 16) temple (0.8.2) - thor (1.2.1) - thread_safe (0.3.6) + thor (1.3.2) tilt (2.0.11) timecop (0.9.5) + timeout (0.4.3) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) - tzinfo (1.2.11) - thread_safe (~> 0.1) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) uglifier (4.2.0) execjs (>= 0.3.0, < 3) unicode-display_width (2.2.0) unicorn (6.1.0) kgio (~> 2.6) raindrops (~> 0.7) + uri (1.0.3) + useragent (0.16.11) webdrivers (5.2.0) nokogiri (~> 1.6) rubyzip (>= 1.3.0) selenium-webdriver (~> 4.0) + webrick (1.9.1) websocket (1.2.9) - websocket-driver (0.7.5) + websocket-driver (0.8.0) + base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.6) + zeitwerk (2.7.3) PLATFORMS ruby @@ -465,7 +532,7 @@ DEPENDENCIES rack-canonical-host rack-cors rack_session_access - rails (~> 6.0) + rails (~> 8.0.2) rails-controller-testing (>= 1.0.5) rails_12factor rails_autolink (>= 1.1.6) @@ -488,7 +555,7 @@ DEPENDENCIES webdrivers RUBY VERSION - ruby 2.7.7p221 + ruby 3.2.8p263 BUNDLED WITH 2.1.4 diff --git a/bin/brakeman b/bin/brakeman new file mode 100755 index 00000000..ace1c9ba --- /dev/null +++ b/bin/brakeman @@ -0,0 +1,7 @@ +#!/usr/bin/env ruby +require "rubygems" +require "bundler/setup" + +ARGV.unshift("--ensure-latest") + +load Gem.bin_path("brakeman", "brakeman") diff --git a/bin/dev b/bin/dev new file mode 100755 index 00000000..5f91c205 --- /dev/null +++ b/bin/dev @@ -0,0 +1,2 @@ +#!/usr/bin/env ruby +exec "./bin/rails", "server", *ARGV diff --git a/bin/rails b/bin/rails index 8a217f6a..efc03774 100755 --- a/bin/rails +++ b/bin/rails @@ -1,10 +1,4 @@ #!/usr/bin/env ruby -if ENV["RAILS_ENV"] == "test" - require "simplecov" - SimpleCov.start "rails" - puts "required simplecov" -end - -APP_PATH = File.expand_path("../../config/application", __FILE__) +APP_PATH = File.expand_path("../config/application", __dir__) require_relative "../config/boot" require "rails/commands" diff --git a/bin/rubocop b/bin/rubocop new file mode 100755 index 00000000..40330c0f --- /dev/null +++ b/bin/rubocop @@ -0,0 +1,8 @@ +#!/usr/bin/env ruby +require "rubygems" +require "bundler/setup" + +# 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 67e27f0a..be3db3c0 100755 --- a/bin/setup +++ b/bin/setup @@ -1,29 +1,34 @@ #!/usr/bin/env ruby -require "pathname" +require "fileutils" -# path to your application root. -APP_ROOT = Pathname.new File.expand_path("../../", __FILE__) +APP_ROOT = File.expand_path("..", __dir__) -Dir.chdir APP_ROOT do - # This script is a starting point to setup your application. - # Add necessary setup steps to this file: +def system!(*args) + system(*args, exception: true) +end + +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 ==" - system "gem install bundler --conservative" - system "bundle check || bundle install" + system("bundle check") || system!("bundle install") # puts "\n== Copying sample files ==" # unless File.exist?("config/database.yml") - # system "cp config/database.yml.sample config/database.yml" + # FileUtils.cp "config/database.yml.sample", "config/database.yml" # end puts "\n== Preparing database ==" - system "bin/rake db:setup" + system! "bin/rails db:prepare" puts "\n== Removing old logs and tempfiles ==" - system "rm -f log/*" - system "rm -rf tmp/cache" + system! "bin/rails log:clear tmp:clear" - puts "\n== Restarting application server ==" - system "touch tmp/restart.txt" + 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 a319c6aa..36d64c88 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,4 +1,4 @@ -require File.expand_path("../boot", __FILE__) +require_relative "boot" require "rails/all" @@ -8,32 +8,20 @@ module Doubleunion class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. config.load_defaults 6.0 - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. - # config.time_zone = 'Central Time (US & Canada)' - - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - # config.i18n.default_locale = :de - - # explicitly loading locales so they will be available in the initializers - I18n.load_path += Dir[Rails.root.join("config", "locales", "**", "*.{rb,yml}")] - - config.eager_load_paths += %W[#{config.root}/lib] - config.autoload_paths += %W[#{config.root}/lib] - - # CORS – this allows doubleunion.org to request the api from javascript - config.middleware.insert_before 0, Rack::Cors do - allow do - origins "*" - - resource "/public_members", headers: :any, methods: [:get], max_age: 0 - end - end + # 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. + # Common ones are `templates`, `generators`, or `middleware`, for example. + config.autoload_lib(ignore: %w[assets tasks]) + + # Configuration for the application, engines, and railties goes here. + # + # These settings can be overridden in specific environments using the files + # in config/environments, which are processed later. + # + # config.time_zone = "Central Time (US & Canada)" + # config.eager_load_paths << Rails.root.join("extras") end end diff --git a/config/boot.rb b/config/boot.rb index fb24cf2e..28201161 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,3 +1,3 @@ -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) require "bundler/setup" # Set up gems listed in the Gemfile. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 00000000..b1f9fa90 --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: test + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: doubleunion_production diff --git a/config/environment.rb b/config/environment.rb index 17119856..cac53157 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,5 +1,5 @@ # Load the Rails application. -require File.expand_path("../application", __FILE__) +require_relative "application" # Initialize the Rails application. Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb index e1a2155a..4cc21c4e 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,51 +1,72 @@ +require "active_support/core_ext/integer/time" + 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 on - # every request. 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. - config.cache_classes = false + # Make code changes take effect immediately without server restart. + config.enable_reloading = true # Do not eager load code on boot. config.eager_load = false - # Show full error reports and disable caching. + # Show full error reports. config.consider_all_requests_local = true - config.action_controller.perform_caching = false + + # Enable server timing. + config.server_timing = true + + # 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.action_controller.enable_fragment_cache_logging = true + config.public_file_server.headers = { "cache-control" => "public, max-age=#{2.days.to_i}" } + else + config.action_controller.perform_caching = false + 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 + # 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 an error on page load if there are pending migrations. config.active_record.migration_error = :page_load - # We're in San Francisco, forever! - config.time_zone = "Pacific Time (US & Canada)" - config.active_record.default_timezone = :local + # 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 - # Debug mode disables concatenation and preprocessing of assets. - # This option may cause significant delays in view rendering with a large - # number of complex assets. - config.assets.debug = true + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true - # Asset digests allow you to set far-future HTTP expiration dates on all assets, - # yet still be able to expire them through the digest params. - config.assets.digest = true + # Annotate rendered view with file names. + config.action_view.annotate_rendered_view_with_filenames = true - # Adds additional error checking when serving assets at runtime. - # Checks for improperly declared sprockets dependencies. - # Raises helpful error messages. - config.assets.raise_runtime_errors = true + # Uncomment if you wish to allow Action Cable access from any origin. + # config.action_cable.disable_request_forgery_protection = true - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true + # Raise error when a before_action's only/except options reference missing actions. + config.action_controller.raise_on_missing_callback_actions = true - # Send email in development mode using MailCatcher: http://mailcatcher.me/. - config.action_mailer.default_url_options = {host: "localhost:3000"} - config.action_mailer.perform_deliveries = true - config.action_mailer.delivery_method = :smtp - config.action_mailer.smtp_settings = {address: "localhost", port: 1025} + # Apply autocorrection by RuboCop to files generated by `bin/rails generate`. + # config.generators.apply_rubocop_autocorrect_after_generate! end diff --git a/config/environments/production.rb b/config/environments/production.rb index 211127de..17496077 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,82 +1,89 @@ +require "active_support/core_ext/integer/time" + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # Code is not reloaded between requests. - config.cache_classes = true + config.enable_reloading = false - # Eager load code on boot. This eager loads most of Rails and - # your application in memory, allowing both threaded web servers - # and those relying on copy on write to perform better. - # Rake tasks automatically ignore this option for performance. + # Eager load code on boot for better performance and memory savings (ignored by Rake tasks). config.eager_load = true - # Full error reports are disabled and caching is turned on. + # Full error reports are disabled. config.consider_all_requests_local = false - config.action_controller.perform_caching = true - - # Enable Rack::Cache to put a simple HTTP cache in front of your application - # Add `rack-cache` to your Gemfile before enabling this. - # For large-scale production use, consider using a caching reverse proxy like - # NGINX, varnish or squid. - # config.action_dispatch.rack_cache = true - - # Disable serving static files from the `/public` folder by default since - # Apache or NGINX already handles this. - config.serve_static_files = ENV["RAILS_SERVE_STATIC_FILES"].present? - # Compress JavaScripts and CSS. - config.assets.js_compressor = Uglifier.new(harmony: true) - # config.assets.css_compressor = :sass + # Turn on fragment caching in view templates. + config.action_controller.perform_caching = true - # Do not fallback to assets pipeline if a precompiled asset is missed. - config.assets.compile = false + # Cache assets for far-future expiry since they are all digest stamped. + config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" } - # Asset digests allow you to set far-future HTTP expiration dates on all assets, - # yet still be able to expire them through the digest params. - config.assets.digest = true + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.asset_host = "http://assets.example.com" - # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + # Store uploaded files on the local file system (see config/storage.yml for options). + config.active_storage.service = :local - # Specifies the header that your server uses for sending files. - # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache - # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + # Assume all access to the app is happening through a SSL-terminating reverse proxy. + config.assume_ssl = true # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. config.force_ssl = true - # Use the lowest log level to ensure availability of diagnostic information - # when problems arise. - config.log_level = :debug + # Skip http-to-https redirect for the default health check endpoint. + # config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } } + + # Log to STDOUT with the current request id as a default log tag. + config.log_tags = [ :request_id ] + config.logger = ActiveSupport::TaggedLogging.logger(STDOUT) + + # Change to "debug" to log everything (including potentially personally-identifiable information!) + config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") - # Prepend all log lines with the following tags. - # config.log_tags = [ :subdomain, :uuid ] + # Prevent health checks from clogging up the logs. + config.silence_healthcheck_path = "/up" - # Use a different logger for distributed setups. - # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + # Don't log any deprecations. + config.active_support.report_deprecations = false - # Use a different cache store in production. + # Replace the default in-process memory cache store with a durable alternative. # config.cache_store = :mem_cache_store - # Enable serving of images, stylesheets, and JavaScripts from an asset server. - # config.action_controller.asset_host = 'http://assets.example.com' + # Replace the default in-process and non-durable queuing backend for Active Job. + # config.active_job.queue_adapter = :resque # Ignore bad email addresses and do not raise email delivery errors. # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false + # Set host to be used by links generated in mailer templates. + config.action_mailer.default_url_options = { host: "example.com" } + + # Specify outgoing SMTP server. Remember to add smtp/* credentials via rails credentials:edit. + # config.action_mailer.smtp_settings = { + # user_name: Rails.application.credentials.dig(:smtp, :user_name), + # password: Rails.application.credentials.dig(:smtp, :password), + # address: "smtp.example.com", + # port: 587, + # authentication: :plain + # } + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation cannot be found). config.i18n.fallbacks = true - # Send deprecation notices to registered listeners. - config.active_support.deprecation = :notify - - config.action_mailer.delivery_method = :ses - config.action_mailer.default_url_options = {host: ENV["HOST_URL"]} - - # Use default logging formatter so that PID and timestamp are not suppressed. - config.log_formatter = ::Logger::Formatter.new - # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false + + # Only use :id for inspections in production. + config.active_record.attributes_for_inspect = [ :id ] + + # Enable DNS rebinding protection and other `Host` header attacks. + # config.hosts = [ + # "example.com", # Allow requests from example.com + # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` + # ] + # + # Skip DNS rebinding protection for the default health check endpoint. + # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } end diff --git a/config/environments/test.rb b/config/environments/test.rb index 89631f71..c2095b11 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,47 +1,53 @@ +# 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 +# and recreated between test runs. Don't rely on the data there! + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. - # 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 - # and recreated between test runs. Don't rely on the data there! - config.cache_classes = true + # While tests run files are not watched, reloading is not necessary. + config.enable_reloading = false - # Do not eager load code on boot. This avoids loading your whole application - # just for the purpose of running a single test. If you are using a tool that - # preloads Rails for running tests, you may have to set it to true. - config.eager_load = false + # Eager loading loads your entire application. When running a single test locally, + # this is usually not necessary, and can slow down your test suite. However, it's + # recommended that you enable it in continuous integration systems to ensure eager + # loading is working properly before deploying your code. + config.eager_load = ENV["CI"].present? - # Configure static file server for tests with Cache-Control for performance. - config.serve_static_files = true - config.static_cache_control = "public, max-age=3600" + # 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 - # Raise exceptions instead of rendering exception templates. - config.action_dispatch.show_exceptions = false + # Render exception templates for rescuable exceptions and raise for other exceptions. + config.action_dispatch.show_exceptions = :rescuable # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false + # Store uploaded files on the local file system in a temporary directory. + config.active_storage.service = :test + # 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 - config.action_mailer.default_url_options = {host: "localhost:3000"} - # Randomize the order test cases are executed. - config.active_support.test_order = :random + # 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 - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true - # using rack_session_access gem for auth in integration tests - # see: http://pivotallabs.com/faking-authentication-for-capybara-tests-within-a-rails-engine/ - config.middleware.use RackSessionAccess::Middleware + # Raise error when a before_action's only/except options reference missing actions. + config.action_controller.raise_on_missing_callback_actions = true end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 90c3ddd5..48732442 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -3,9 +3,5 @@ # Version of your assets, change this if you want to expire all your assets. Rails.application.config.assets.version = "1.0" -# Add additional assets to the asset load path +# Add additional assets to the asset load path. # Rails.application.config.assets.paths << Emoji.images_path - -# Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. -Rails.application.config.assets.precompile %w[manifest.js] diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb new file mode 100644 index 00000000..b3076b38 --- /dev/null +++ b/config/initializers/content_security_policy.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy. +# See the Securing Rails Applications Guide for more information: +# https://guides.rubyonrails.org/security.html#content-security-policy-header + +# Rails.application.configure do +# config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end +# +# # Generate session nonces for permitted importmap, inline scripts, and inline styles. +# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } +# config.content_security_policy_nonce_directives = %w(script-src style-src) +# +# # Report violations without enforcing the policy. +# # config.content_security_policy_report_only = true +# end diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index 4a994e1e..c0b717f7 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,4 +1,8 @@ # Be sure to restart your server when you modify this file. -# Configure sensitive parameters which will be filtered from the log file. -Rails.application.config.filter_parameters += [:password] +# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file. +# 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 +] diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index ac033bf9..3860f659 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -4,13 +4,13 @@ # are locale specific, and you may define rules for as many different # locales as you wish. All of these examples are active by default: # ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.plural /^(ox)$/i, '\1en' -# inflect.singular /^(ox)en/i, '\1' -# inflect.irregular 'person', 'people' +# inflect.plural /^(ox)$/i, "\\1en" +# inflect.singular /^(ox)en/i, "\\1" +# inflect.irregular "person", "people" # inflect.uncountable %w( fish sheep ) # end # These inflection rules are supported but not enabled by default: # ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.acronym 'RESTful' +# inflect.acronym "RESTful" # end diff --git a/config/initializers/new_framework_defaults_8_0.rb b/config/initializers/new_framework_defaults_8_0.rb new file mode 100644 index 00000000..92efa951 --- /dev/null +++ b/config/initializers/new_framework_defaults_8_0.rb @@ -0,0 +1,30 @@ +# Be sure to restart your server when you modify this file. +# +# This file eases your Rails 8.0 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.0`. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. +# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html + +### +# Specifies whether `to_time` methods preserve the UTC offset of their receivers or preserves the timezone. +# If set to `:zone`, `to_time` methods will use the timezone of their receivers. +# If set to `:offset`, `to_time` methods will use the UTC offset. +# If `false`, `to_time` methods will convert to the local system UTC offset instead. +#++ +# Rails.application.config.active_support.to_time_preserves_timezone = :zone + +### +# When both `If-Modified-Since` and `If-None-Match` are provided by the client +# only consider `If-None-Match` as specified by RFC 7232 Section 6. +# If set to `false` both conditions need to be satisfied. +#++ +# Rails.application.config.action_dispatch.strict_freshness = true + +### +# Set `Regexp.timeout` to `1`s by default to improve security over Regexp Denial-of-Service attacks. +#++ +# Regexp.timeout = 1 diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 00000000..a248513b --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,41 @@ +# This configuration file will be evaluated by Puma. The top-level methods that +# are invoked here are part of Puma's configuration DSL. For more information +# about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html. +# +# Puma starts a configurable number of processes (workers) and each process +# serves each request in a thread from an internal thread pool. +# +# You can control the number of workers using ENV["WEB_CONCURRENCY"]. You +# should only set this value when you want to run 2 or more workers. The +# default is already 1. +# +# The ideal number of threads per worker depends both on how much time the +# application spends waiting for IO operations and on how much you wish to +# prioritize throughput over latency. +# +# As a rule of thumb, increasing the number of threads will increase how much +# traffic a given process can handle (throughput), but due to CRuby's +# Global VM Lock (GVL) it has diminishing returns and will degrade the +# response time (latency) of the application. +# +# The default is set to 3 threads as it's deemed a decent compromise between +# throughput and latency for the average Rails application. +# +# Any libraries that use a connection pool or another resource pool should +# be configured to provide at least as many connections as the number of +# threads. This includes Active Record's `pool` parameter in `database.yml`. +threads_count = ENV.fetch("RAILS_MAX_THREADS", 3) +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +port ENV.fetch("PORT", 3000) + +# Allow puma to be restarted by `bin/rails restart` command. +plugin :tmp_restart + +# Run the Solid Queue supervisor inside of Puma for single-server deployments +plugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"] + +# Specify the PID file. Defaults to tmp/pids/server.pid in development. +# In other environments, only set the PID file if requested. +pidfile ENV["PIDFILE"] if ENV["PIDFILE"] diff --git a/config/storage.yml b/config/storage.yml new file mode 100644 index 00000000..4942ab66 --- /dev/null +++ b/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket-<%= Rails.env %> + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket-<%= Rails.env %> + +# Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name-<%= Rails.env %> + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/app/helpers/stripe_event_helper.rb b/lib/stripe_event_handlers/stripe_event_helper.rb similarity index 100% rename from app/helpers/stripe_event_helper.rb rename to lib/stripe_event_handlers/stripe_event_helper.rb diff --git a/public/400.html b/public/400.html new file mode 100644 index 00000000..282dbc8c --- /dev/null +++ b/public/400.html @@ -0,0 +1,114 @@ + + + + + + + The server cannot process the request due to a client error (400 Bad Request) + + + + + + + + + + + + + +
+
+ +
+
+

The server cannot process the request due to a client error. Please check the request and try again. If you’re the application owner check the logs for more information.

+
+
+ + + + diff --git a/public/404.html b/public/404.html index a0daa0c1..c0670bc8 100644 --- a/public/404.html +++ b/public/404.html @@ -1,58 +1,114 @@ - - - - The page you were looking for doesn't exist (404) - - - - - -
-

The page you were looking for doesn't exist.

-

You may have mistyped the address or the page may have moved.

-
-

If you are the application owner check the logs for more information.

- + + + + + + + The page you were looking for doesn’t exist (404 Not found) + + + + + + + + + + + + + +
+
+ +
+
+

The page you were looking for doesn’t exist. You may have mistyped the address or the page may have moved. If you’re the application owner check the logs for more information.

+
+
+ + + diff --git a/public/406-unsupported-browser.html b/public/406-unsupported-browser.html new file mode 100644 index 00000000..9532a9cc --- /dev/null +++ b/public/406-unsupported-browser.html @@ -0,0 +1,114 @@ + + + + + + + Your browser is not supported (406 Not Acceptable) + + + + + + + + + + + + + +
+
+ +
+
+

Your browser is not supported.
Please upgrade your browser to continue.

+
+
+ + + + diff --git a/public/422.html b/public/422.html index fbb4b84d..8bcf0601 100644 --- a/public/422.html +++ b/public/422.html @@ -1,58 +1,114 @@ - - - - The change you wanted was rejected (422) - - - - - -
-

The change you wanted was rejected.

-

Maybe you tried to change something you didn't have access to.

-
-

If you are the application owner check the logs for more information.

- + + + + + + + The change you wanted was rejected (422 Unprocessable Entity) + + + + + + + + + + + + + +
+
+ +
+
+

The change you wanted was rejected. Maybe you tried to change something you didn’t have access to. If you’re the application owner check the logs for more information.

+
+
+ + + diff --git a/public/500.html b/public/500.html index e9052d35..d77718c3 100644 --- a/public/500.html +++ b/public/500.html @@ -1,57 +1,114 @@ - - - - We're sorry, but something went wrong (500) - - - - - -
-

We're sorry, but something went wrong.

-
-

If you are the application owner check the logs for more information.

- + + + + + + + We’re sorry, but something went wrong (500 Internal Server Error) + + + + + + + + + + + + + +
+
+ +
+
+

We’re sorry, but something went wrong.
If you’re the application owner check the logs for more information.

+
+
+ + + diff --git a/public/icon.png b/public/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c4c9dbfbbd2f7c1421ffd5727188146213abbcef GIT binary patch literal 4166 zcmd6qU;WFw?|v@m)Sk^&NvB8tcujdV-r1b=i(NJxn&7{KTb zX$3(M+3TP2o^#KAo{#tIjl&t~(8D-k004kqPglzn0HFG(Q~(I*AKsD#M*g7!XK0T7 zN6P7j>HcT8rZgKl$v!xr806dyN19Bd4C0x_R*I-a?#zsTvb_89cyhuC&T**i|Rc zq5b8M;+{8KvoJ~uj9`u~d_f6`V&3+&ZX9x5pc8s)d175;@pjm(?dapmBcm0&vl9+W zx1ZD2o^nuyUHWj|^A8r>lUorO`wFF;>9XL-Jy!P}UXC{(z!FO%SH~8k`#|9;Q|eue zqWL0^Bp(fg_+Pkm!fDKRSY;+^@BF?AJE zCUWpXPst~hi_~u)SzYBDZroR+Z4xeHIlm_3Yc_9nZ(o_gg!jDgVa=E}Y8uDgem9`b zf=mfJ_@(BXSkW53B)F2s!&?_R4ptb1fYXlF++@vPhd=marQgEGRZS@B4g1Mu?euknL= z67P~tZ?*>-Hmi7GwlisNHHJDku-dSm7g@!=a}9cSL6Pa^w^2?&?$Oi8ibrr>w)xqx zOH_EMU@m05)9kuNR>>4@H%|){U$^yvVQ(YgOlh;5oU_-vivG-p4=LrN-k7D?*?u1u zsWly%tfAzKd6Fb=`eU2un_uaTXmcT#tlOL+aRS=kZZf}A7qT8lvcTx~7j` z*b>=z)mwg7%B2_!D0!1IZ?Nq{^Y$uI4Qx*6T!E2Col&2{k?ImCO=dD~A&9f9diXy^$x{6CwkBimn|1E09 zAMSezYtiL?O6hS37KpvDM?22&d{l)7h-!F)C-d3j8Z`c@($?mfd{R82)H>Qe`h{~G z!I}(2j(|49{LR?w4Jspl_i!(4T{31|dqCOpI52r5NhxYV+cDAu(xp*4iqZ2e-$YP= zoFOPmm|u*7C?S{Fp43y+V;>~@FFR76bCl@pTtyB93vNWy5yf;HKr8^0d7&GVIslYm zo3Tgt@M!`8B6IW&lK{Xk>%zp41G%`(DR&^u z5^pwD4>E6-w<8Kl2DzJ%a@~QDE$(e87lNhy?-Qgep!$b?5f7+&EM7$e>|WrX+=zCb z=!f5P>MxFyy;mIRxjc(H*}mceXw5a*IpC0PEYJ8Y3{JdoIW)@t97{wcUB@u+$FCCO z;s2Qe(d~oJC^`m$7DE-dsha`glrtu&v&93IZadvl_yjp!c89>zo;Krk+d&DEG4?x$ zufC1n+c1XD7dolX1q|7}uelR$`pT0Z)1jun<39$Sn2V5g&|(j~Z!wOddfYiZo7)A< z!dK`aBHOOk+-E_xbWCA3VR-+o$i5eO9`rMI#p_0xQ}rjEpGW;U!&&PKnivOcG(|m9 z!C8?WC6nCXw25WVa*eew)zQ=h45k8jSIPbq&?VE{oG%?4>9rwEeB4&qe#?-y_es4c|7ufw%+H5EY#oCgv!Lzv291#-oNlX~X+Jl5(riC~r z=0M|wMOP)Tt8@hNg&%V@Z9@J|Q#K*hE>sr6@oguas9&6^-=~$*2Gs%h#GF@h)i=Im z^iKk~ipWJg1VrvKS;_2lgs3n1zvNvxb27nGM=NXE!D4C!U`f*K2B@^^&ij9y}DTLB*FI zEnBL6y{jc?JqXWbkIZd7I16hA>(f9T!iwbIxJj~bKPfrO;>%*5nk&Lf?G@c2wvGrY&41$W{7HM9+b@&XY@>NZM5s|EK_Dp zQX60CBuantx>|d#DsaZ*8MW(we|#KTYZ=vNa#d*DJQe6hr~J6{_rI#?wi@s|&O}FR zG$kfPxheXh1?IZ{bDT-CWB4FTvO-k5scW^mi8?iY5Q`f8JcnnCxiy@m@D-%lO;y0pTLhh6i6l@x52j=#^$5_U^os}OFg zzdHbo(QI`%9#o*r8GCW~T3UdV`szO#~)^&X_(VW>o~umY9-ns9-V4lf~j z`QBD~pJ4a#b`*6bJ^3RS5y?RAgF7K5$ll97Y8#WZduZ`j?IEY~H(s^doZg>7-tk*t z4_QE1%%bb^p~4F5SB$t2i1>DBG1cIo;2(xTaj*Y~hlM{tSDHojL-QPg%Mo%6^7FrpB*{ z4G0@T{-77Por4DCMF zB_5Y~Phv%EQ64W8^GS6h?x6xh;w2{z3$rhC;m+;uD&pR74j+i22P5DS-tE8ABvH(U~indEbBUTAAAXfHZg5QpB@TgV9eI<)JrAkOI z8!TSOgfAJiWAXeM&vR4Glh;VxH}WG&V$bVb`a`g}GSpwggti*&)taV1@Ak|{WrV|5 zmNYx)Ans=S{c52qv@+jmGQ&vd6>6yX6IKq9O$3r&0xUTdZ!m1!irzn`SY+F23Rl6# zFRxws&gV-kM1NX(3(gnKpGi0Q)Dxi~#?nyzOR9!en;Ij>YJZVFAL*=R%7y%Mz9hU% zs>+ZB?qRmZ)nISx7wxY)y#cd$iaC~{k0avD>BjyF1q^mNQ1QcwsxiTySe<6C&cC6P zE`vwO9^k-d`9hZ!+r@Jnr+MF*2;2l8WjZ}DrwDUHzSF{WoG zucbSWguA!3KgB3MU%HH`R;XqVv0CcaGq?+;v_A5A2kpmk5V%qZE3yzQ7R5XWhq=eR zyUezH=@V)y>L9T-M-?tW(PQYTRBKZSVb_!$^H-Pn%ea;!vS_?M<~Tm>_rWIW43sPW z=!lY&fWc1g7+r?R)0p8(%zp&vl+FK4HRkns%BW+Up&wK8!lQ2~bja|9bD12WrKn#M zK)Yl9*8$SI7MAwSK$%)dMd>o+1UD<2&aQMhyjS5R{-vV+M;Q4bzl~Z~=4HFj_#2V9 zB)Gfzx3ncy@uzx?yzi}6>d%-?WE}h7v*w)Jr_gBl!2P&F3DX>j_1#--yjpL%<;JMR z*b70Gr)MMIBWDo~#<5F^Q0$VKI;SBIRneuR7)yVsN~A9I@gZTXe)E?iVII+X5h0~H zx^c(fP&4>!*q>fb6dAOC?MI>Cz3kld#J*;uik+Ps49cwm1B4 zZc1|ZxYyTv;{Z!?qS=D)sgRKx^1AYf%;y_V&VgZglfU>d+Ufk5&LV$sKv}Hoj+s; xK3FZRYdhbXT_@RW*ff3@`D1#ps#~H)p+y&j#(J|vk^lW{fF9OJt5(B-_&*Xgn9~3N literal 0 HcmV?d00001 diff --git a/public/icon.svg b/public/icon.svg new file mode 100644 index 00000000..04b34bf8 --- /dev/null +++ b/public/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/robots.txt b/public/robots.txt index 1a3a5e4d..c19f78ab 100644 --- a/public/robots.txt +++ b/public/robots.txt @@ -1,5 +1 @@ -# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file -# -# To ban all spiders from the entire site uncomment the next two lines: -# User-agent: * -# Disallow: / +# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file From 58a3f51eac4dd97b8d85d18773c2cd05b77730b6 Mon Sep 17 00:00:00 2001 From: elg0nz Date: Fri, 13 Jun 2025 08:26:44 -0700 Subject: [PATCH 04/23] add dockerfile & docker-compose --- Dockerfile | 2 +- docker-compose.yml | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index cb069678..6fd4a54b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ RUN apt-get update -qq && \ WORKDIR /app # Copy Gemfile and Gemfile.lock to leverage Docker cache -COPY Gemfile Gemfile.lock ./ +COPY Gemfile Gemfile.lock .ruby-version ./ # Install Bundler. Use a version compatible with your Gemfile.lock (e.g., if BUNDLED WITH is 2.6.9, this covers it) RUN gem install bundler -v '~> 2.4' --conservative --minimal-deps diff --git a/docker-compose.yml b/docker-compose.yml index 4c010770..32f540fa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3.8" - services: db: image: postgres:14-alpine From 3a22196fdef1259a6352b043b5592c6d057c84e1 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 15 Jun 2025 22:23:22 +0000 Subject: [PATCH 05/23] I've added a GitHub Actions workflow for CI. This involves adding the `.github/workflows/ruby-ci.yml` file to this branch to enable CI runs. The workflow is configured to: - Trigger on pushes to all branches and PRs to main. - Use Ruby 3.2.8. - Cache Bundler dependencies. - Set up the test database using PostgreSQL. - Run RSpec tests. --- .github/workflows/ruby-ci.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/ruby-ci.yml diff --git a/.github/workflows/ruby-ci.yml b/.github/workflows/ruby-ci.yml new file mode 100644 index 00000000..10f522c7 --- /dev/null +++ b/.github/workflows/ruby-ci.yml @@ -0,0 +1,25 @@ +name: Ruby CI + +on: + push: + branches: [ '**' ] + pull_request: + branches: [ main ] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.2.8' + bundler-cache: true # runs 'bundle install' and caches installed gems + - name: Set up database + run: | + cp config/database.github-actions.yml config/database.yml + bundle exec rails db:create + bundle exec rails db:schema:load --trace + - name: Run tests + run: bundle exec rspec From a2da4bdd17468e081536b6594be72a93a8b4df06 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 15 Jun 2025 22:56:41 +0000 Subject: [PATCH 06/23] Fix: Explicitly require StripeEventHelper in initializer Adds a direct `require 'stripe_event_handlers/stripe_event_helper'` to the beginning of `config/initializers/stripe.rb`. This is to resolve a `NameError: uninitialized constant StripeEventHelper` that was occurring during CI runs (specifically during `db:create` or `db:schema:load` which run initializers). While autoloading for `lib` is configured, this explicit require ensures the helper is available when the Stripe events are being subscribed, avoiding potential load order issues in the Rake task execution context. --- config/initializers/stripe.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/initializers/stripe.rb b/config/initializers/stripe.rb index ef8d2f1c..958661bb 100644 --- a/config/initializers/stripe.rb +++ b/config/initializers/stripe.rb @@ -1,3 +1,5 @@ +require 'stripe_event_handlers/stripe_event_helper' + Rails.configuration.stripe = { event_signing_secret: ENV["STRIPE_SIGNING_SECRET"], publishable_key: ENV["STRIPE_PUBLISHABLE_KEY"], From d95787d57d2031eb241f1b39a5c8ced363219f45 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 15 Jun 2025 23:06:05 +0000 Subject: [PATCH 07/23] Fix: Remove protected_attributes_continued gem Removes the `protected_attributes_continued` gem to resolve a `TypeError: superclass mismatch for class SchemaMigration` error encountered during CI when running `db:create` or `db:schema:load`. This gem is incompatible with Rails 8 and was used for `attr_accessible` functionality, which is replaced by Strong Parameters in modern Rails. Occurrences of `attr_accessible` were found in User and Authentication models; these will now rely on controller-level Strong Parameters. Note: `Gemfile.lock` was not updated by `bundle install` due to a persistent sandbox error. The CI environment or a local `bundle install` run should correctly update the lockfile based on this Gemfile change. --- Gemfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Gemfile b/Gemfile index 9f0b3383..d466f535 100644 --- a/Gemfile +++ b/Gemfile @@ -12,7 +12,6 @@ gem "omniauth-github" gem "omniauth-google-oauth2" gem "pg" gem "state_machine_deuxito", require: 'state_machine' -gem "protected_attributes_continued" # works w rails 5 gem "kaminari", ">= 1.2.1" gem "rails_autolink", ">= 1.1.6" gem "redcarpet" From 6cfbc3886eca41f3e0e63091c80b06f0814bfa3d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 15 Jun 2025 23:19:52 +0000 Subject: [PATCH 08/23] Feat: Add Dockerized .devcontainer setup with Docker Compose I've implemented a more comprehensive .devcontainer configuration using a custom Dockerfile and Docker Compose to define your development environment. This setup includes: - `.devcontainer/Dockerfile`: This defines the application environment starting from Ruby 3.2.8, installs system dependencies (PostgreSQL client, Node.js, Yarn), creates a non-root user, and handles gem installation. - `.devcontainer/docker-compose.yml`: This defines `app` and `db` services. The `app` service builds from the Dockerfile and mounts your project code. The `db` service uses a standard PostgreSQL image. - `.devcontainer/devcontainer.json`: I've updated this to use the Docker Compose setup, specifying the `app` service and `/workspace` folder. I removed redundant features and updated the `postCreateCommand` to ensure dependencies are installed and the database is prepared. This provides an integrated environment with the Rails application and a PostgreSQL database service, suitable for GitHub Codespaces and VS Code Remote - Containers. --- .devcontainer/.gitkeep | 1 + .devcontainer/Dockerfile | 58 ++++++++++++++++++++++++++++++++ .devcontainer/devcontainer.json | 44 ++++++++++++++++++++++++ .devcontainer/docker-compose.yml | 33 ++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 .devcontainer/.gitkeep create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .devcontainer/docker-compose.yml diff --git a/.devcontainer/.gitkeep b/.devcontainer/.gitkeep new file mode 100644 index 00000000..61739198 --- /dev/null +++ b/.devcontainer/.gitkeep @@ -0,0 +1 @@ +# Placeholder to ensure the .devcontainer directory is created. diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..909ed9d0 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,58 @@ +# Use an official Ruby image as a parent image +FROM ruby:3.2.8-bullseye + +# Set environment variables +ENV LANG C.UTF-8 +ENV RAILS_ENV development +ENV RACK_ENV development +ENV PORT 3000 + +# Install system dependencies +# - build-essential: For compiling native extensions +# - libpq-dev: For the pg gem (PostgreSQL client library) +# - nodejs, yarn: For JavaScript runtime and package management (if needed by Rails asset pipeline) +# - postgresql-client: For psql command-line utility +RUN apt-get update -qq && apt-get install -y --no-install-recommends \ + build-essential \ + libpq-dev \ + nodejs \ + yarn \ + postgresql-client \ + && rm -rf /var/lib/apt/lists/* + +# Create a non-root user +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=$USER_UID +RUN groupadd --gid $USER_GID $USERNAME \ + && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \ + # Add user to sudoers with no password (optional, for convenience) + && apt-get update && apt-get install -y sudo \ + && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME \ + && rm -rf /var/lib/apt/lists/* + +# Set up work directory +WORKDIR /workspace + +# Copy Gemfile and Gemfile.lock +COPY Gemfile Gemfile.lock ./ + +# Install gems for the non-root user to avoid permission issues with host mounts +# Ensure bundle path is writable by the user +USER $USERNAME +RUN mkdir -p /home/$USERNAME/.bundle \ + && chown -R $USERNAME:$USERNAME /home/$USERNAME/.bundle \ + && bundle install --jobs $(nproc) --retry 3 + +# Copy the rest of the application code +USER root +COPY . . +RUN chown -R $USERNAME:$USERNAME /workspace + +# Switch back to non-root user +USER $USERNAME + +# Expose port 3000 and set the default command +EXPOSE 3000 +CMD ["bin/rails", "server", "-b", "0.0.0.0"] diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..9877b53c --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,44 @@ +{ + "name": "Arooo Dockerized Dev", + "dockerComposeFile": "docker-compose.yml", + "service": "app", + "workspaceFolder": "/workspace", + // Features like node and postgres client are now handled by the Dockerfile for the 'app' service. + // We can keep common-utils if desired for the general container experience, or remove if not needed. + "features": { + "ghcr.io/devcontainers/features/common-utils:2": { + "installZsh": "true", + "configureZshAsDefaultShell": "true", + "installOhMyZsh": "true" + } + }, + "customizations": { + "vscode": { + "extensions": [ + "Shopify.ruby-lsp", + "Shopify.rubocop-lsp", + "rebornix.Ruby", + "castwide.solargraph", + "KoichiSasada.vscode-rdbg", + "ms-azuretools.vscode-docker", + "GitHub.codespaces", + "GitHub.vscode-pull-request-github" + ], + "settings": { + // Since rbenv/rvm are not explicitly installed in the Dockerfile (it uses system ruby), + // 'none' is appropriate. If a version manager were added to Dockerfile, this might change. + "rubyLsp.rubyVersionManager": "none", + "editor.formatOnSave": true + } + } + }, + // Ports are now forwarded by docker-compose.yml, but listing the primary app port here is good for Codespaces UI. + "forwardPorts": [3000], + // The Dockerfile and docker-compose setup should handle gem installation and user setup. + // postCreateCommand might still be useful for other setup, or could be removed/simplified. + // For example, ensuring the database is created if it's the first time. + "postCreateCommand": "bundle check || bundle install && bundle exec rails db:prepare", + // The user is defined in the Dockerfile and docker-compose.yml for the app service. + // Ensure this matches if not 'vscode', or remove if service user is different and correctly set. + "remoteUser": "vscode" +} diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 00000000..1bc810a5 --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,33 @@ +version: '3.8' +services: + app: + build: + context: . # Use the Dockerfile in the .devcontainer directory + dockerfile: Dockerfile + volumes: + - ..:/workspace:cached # Mount the project root (one level up) to /workspace in the container + ports: + - "3000:3000" # Map port 3000 on the host to port 3000 in the container + depends_on: + - db + environment: + - DATABASE_URL=postgres://arooo_user:arooo_password@db:5432/arooo_development + - RAILS_ENV=development + - RACK_ENV=development + # Add any other necessary environment variables for the app service here + # e.g., GITHUB_CLIENT_KEY, GITHUB_CLIENT_SECRET, etc. + # These would ideally be sourced from a .env file or user secrets in Codespaces + + db: + image: postgres:15 # Or your preferred PostgreSQL version + volumes: + - postgres_data:/var/lib/postgresql/data # Persist PostgreSQL data + environment: + - POSTGRES_USER=arooo_user + - POSTGRES_PASSWORD=arooo_password + - POSTGRES_DB=arooo_development + ports: + - "5432:5432" # Optionally map PostgreSQL port to host (for external tools) + +volumes: + postgres_data: # Defines the named volume for data persistence From 29bbf097d56f4ee531b812d44eb45d7dd5159be9 Mon Sep 17 00:00:00 2001 From: elg0nz Date: Sun, 15 Jun 2025 16:22:07 -0700 Subject: [PATCH 09/23] wip --- .github/workflows/ci.yml | 6 +++--- .github/workflows/ruby_lint.yml | 6 +++--- .github/workflows/security.yml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1fa26cc6..82990969 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,14 +3,14 @@ name: Ruby CI on: push: branches: - - main + - '**' paths-ignore: - 'docs/**' - '*.md' - 'bin/*' pull_request: branches: - - main + - '**' paths-ignore: - 'docs/**' - '*.md' @@ -32,7 +32,7 @@ jobs: options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 diff --git a/.github/workflows/ruby_lint.yml b/.github/workflows/ruby_lint.yml index bb4dbe55..70bda158 100644 --- a/.github/workflows/ruby_lint.yml +++ b/.github/workflows/ruby_lint.yml @@ -3,14 +3,14 @@ name: standardrb lint on: push: branches: - - main + - '**' paths-ignore: - 'docs/**' - '*.md' - 'bin/*' pull_request: branches: - - main + - '**' paths-ignore: - 'docs/**' - '*.md' @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 2dae5940..e026a930 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -3,14 +3,14 @@ name: brakeman on: push: branches: - - main + - '**' paths-ignore: - 'docs/**' - '*.md' - 'bin/*' pull_request: branches: - - main + - '**' paths-ignore: - 'docs/**' - '*.md' @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 From e0f8a49b80b750d05fc9f66819a39e45abf391b3 Mon Sep 17 00:00:00 2001 From: elg0nz Date: Mon, 16 Jun 2025 08:28:53 -0700 Subject: [PATCH 10/23] fix gemfile --- .ruby-version | 2 +- Gemfile.lock | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.ruby-version b/.ruby-version index f092941a..6cb9d3dd 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.8 +3.4.3 diff --git a/Gemfile.lock b/Gemfile.lock index 59f89ddb..f74a7fe4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -144,7 +144,7 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.3.5) + concurrent-ruby (1.3.4) configurable_engine (2.0.2) rails (> 5.2.0) connection_pool (2.5.3) @@ -254,6 +254,7 @@ GEM multi_json (1.15.0) multi_xml (0.6.0) multipart-post (2.4.1) + mutex_m (0.3.0) net-imap (0.5.8) date net-protocol @@ -287,6 +288,7 @@ GEM omniauth-oauth2 (1.7.2) oauth2 (~> 1.4) omniauth (>= 1.9, < 3) + ostruct (0.6.1) parallel (1.22.1) parser (3.1.2.1) ast (~> 2.4.1) @@ -294,8 +296,6 @@ GEM pp (0.6.2) prettyprint prettyprint (0.2.0) - protected_attributes_continued (1.8.2) - activemodel (>= 5.0) pry (0.14.1) coderay (~> 1.1) method_source (~> 1.0) @@ -412,7 +412,7 @@ GEM ruby-progressbar (1.11.0) ruby_parser (3.19.1) sexp_processor (~> 4.16) - rubyzip (2.3.2) + rubyzip (2.4.1) sass-rails (6.0.0) sassc-rails (~> 2.1, >= 2.1.1) sassc (2.0.1) @@ -499,6 +499,7 @@ DEPENDENCIES annotate awesome_print aws-sdk-rails (~> 3) + benchmark better_errors binding_of_caller bootstrap-sass @@ -506,8 +507,10 @@ DEPENDENCIES bugsnag capybara coffee-rails (>= 4.2.2) + concurrent-ruby (= 1.3.4) configurable_engine (~> 2) database_cleaner + drb email_spec factory_bot_rails (>= 6.1.0) faker @@ -520,12 +523,14 @@ DEPENDENCIES jwt kaminari (>= 1.2.1) launchy + minitest (>= 5.22.0) + mutex_m nokogiri (>= 1.11.0.rc4) omniauth omniauth-github omniauth-google-oauth2 + ostruct pg - protected_attributes_continued pry pry-rails puma (~> 5.6) @@ -539,6 +544,7 @@ DEPENDENCIES redcarpet rspec-collection_matchers rspec-rails (>= 4.0.0) + rubyzip (~> 2.4.1) sass-rails (>= 5.0.7) selenium-webdriver shoulda-matchers @@ -555,7 +561,7 @@ DEPENDENCIES webdrivers RUBY VERSION - ruby 3.2.8p263 + ruby 3.4.3p32 BUNDLED WITH - 2.1.4 + 2.6.9 From 52c6760adc4d8eab3ff70ad8072dbd722e00829a Mon Sep 17 00:00:00 2001 From: elg0nz Date: Mon, 16 Jun 2025 19:27:16 -0700 Subject: [PATCH 11/23] fix ci --- .github/workflows/ci.yml | 1 + .github/workflows/ruby-ci.yml | 2 +- .github/workflows/ruby_lint.yml | 1 + .github/workflows/security.yml | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82990969..70335901 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,6 +37,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: + ruby-version: '3.4.3' bundler-cache: true - name: Bundle install diff --git a/.github/workflows/ruby-ci.yml b/.github/workflows/ruby-ci.yml index 10f522c7..2d8a2d84 100644 --- a/.github/workflows/ruby-ci.yml +++ b/.github/workflows/ruby-ci.yml @@ -14,7 +14,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: '3.2.8' + ruby-version: '3.4.3' bundler-cache: true # runs 'bundle install' and caches installed gems - name: Set up database run: | diff --git a/.github/workflows/ruby_lint.yml b/.github/workflows/ruby_lint.yml index 70bda158..23d03fbd 100644 --- a/.github/workflows/ruby_lint.yml +++ b/.github/workflows/ruby_lint.yml @@ -27,6 +27,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: + ruby-version: '3.4.3' bundler-cache: true - name: lint diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index e026a930..1852ca2b 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -27,6 +27,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: + ruby-version: '3.4.3' bundler-cache: true - name: brakeman From 55fdc93cb321a23bdfc43cb197a6ea2a71ffaeaa Mon Sep 17 00:00:00 2001 From: elg0nz Date: Mon, 16 Jun 2025 19:57:10 -0700 Subject: [PATCH 12/23] fix RAILS_ENV --- .github/workflows/ruby-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ruby-ci.yml b/.github/workflows/ruby-ci.yml index 2d8a2d84..5be431e7 100644 --- a/.github/workflows/ruby-ci.yml +++ b/.github/workflows/ruby-ci.yml @@ -17,6 +17,8 @@ jobs: ruby-version: '3.4.3' bundler-cache: true # runs 'bundle install' and caches installed gems - name: Set up database + env: + RAILS_ENV: test run: | cp config/database.github-actions.yml config/database.yml bundle exec rails db:create From 9609d555c368a6fd14b7c4343c59ea3d2734ee2a Mon Sep 17 00:00:00 2001 From: elg0nz Date: Mon, 16 Jun 2025 20:30:07 -0700 Subject: [PATCH 13/23] Fix observer dep --- Gemfile | 1 + Gemfile.lock | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Gemfile b/Gemfile index fea08e65..717de25c 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,7 @@ gem 'mutex_m' gem 'drb' gem 'benchmark' gem 'ostruct' +gem 'observer' gem "rails", "~> 8.0.2" gem "jquery-rails", ">= 4.3.5" diff --git a/Gemfile.lock b/Gemfile.lock index f74a7fe4..c72be855 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -274,6 +274,7 @@ GEM multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) + observer (0.1.2) omniauth (1.9.2) hashie (>= 3.4.6) rack (>= 1.6.2, < 3) @@ -526,6 +527,7 @@ DEPENDENCIES minitest (>= 5.22.0) mutex_m nokogiri (>= 1.11.0.rc4) + observer omniauth omniauth-github omniauth-google-oauth2 From 228ddd6e3d1024dda7981b278255fa2bfeff10b3 Mon Sep 17 00:00:00 2001 From: elg0nz Date: Wed, 18 Jun 2025 17:10:57 -0700 Subject: [PATCH 14/23] update brakeman --- Gemfile | 5 ++--- Gemfile.lock | 8 +++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Gemfile b/Gemfile index 717de25c..ae1ab19e 100644 --- a/Gemfile +++ b/Gemfile @@ -46,7 +46,7 @@ group :development do gem "binding_of_caller" # Retrieve the binding of a method's caller gem "html2haml" gem "awesome_print" -end + end group :development, :test do gem "rspec-rails", ">= 4.0.0" @@ -54,7 +54,7 @@ group :development, :test do gem "rack_session_access" gem "pry-rails" gem "pry" - gem "puma", "~> 5.6" + gem "brakeman", "~> 7.0", :require => false gem "standard" gem "timecop" end @@ -80,4 +80,3 @@ group :test do gem "rails-controller-testing", ">= 1.0.5" end -gem "brakeman" diff --git a/Gemfile.lock b/Gemfile.lock index c72be855..e40d0f0d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -123,7 +123,8 @@ GEM bootstrap-sass (3.4.1) autoprefixer-rails (>= 5.2.1) sassc (>= 2.0.0) - brakeman (5.4.0) + brakeman (7.0.2) + racc bugsnag (6.24.2) concurrent-ruby (~> 1.0) builder (3.3.0) @@ -306,8 +307,6 @@ GEM date stringio public_suffix (4.0.7) - puma (5.6.5) - nio4r (~> 2.0) racc (1.8.1) rack (2.2.17) rack-canonical-host (1.1.0) @@ -504,7 +503,7 @@ DEPENDENCIES better_errors binding_of_caller bootstrap-sass - brakeman + brakeman (~> 7.0) bugsnag capybara coffee-rails (>= 4.2.2) @@ -535,7 +534,6 @@ DEPENDENCIES pg pry pry-rails - puma (~> 5.6) rack-canonical-host rack-cors rack_session_access From 98a6849c0dc9bc6ddaf2c580d0aada74c6a83126 Mon Sep 17 00:00:00 2001 From: elg0nz Date: Wed, 18 Jun 2025 18:37:28 -0700 Subject: [PATCH 15/23] updating rubocop and standard --- Gemfile | 2 +- Gemfile.lock | 45 ++++++++++++++++++++++++++++++--------------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/Gemfile b/Gemfile index ae1ab19e..080e8d97 100644 --- a/Gemfile +++ b/Gemfile @@ -55,7 +55,7 @@ group :development, :test do gem "pry-rails" gem "pry" gem "brakeman", "~> 7.0", :require => false - gem "standard" + gem "standard", "~> 1.35.1" gem "timecop" end diff --git a/Gemfile.lock b/Gemfile.lock index e40d0f0d..68f5c788 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -235,8 +235,10 @@ GEM kaminari-core (= 1.2.2) kaminari-core (1.2.2) kgio (2.11.4) + language_server-protocol (3.17.0.5) launchy (2.5.0) addressable (~> 2.7) + lint_roller (1.1.0) logger (1.7.0) loofah (2.24.1) crass (~> 1.0.2) @@ -292,12 +294,14 @@ GEM omniauth (>= 1.9, < 3) ostruct (0.6.1) parallel (1.22.1) - parser (3.1.2.1) + parser (3.3.8.0) ast (~> 2.4.1) + racc pg (1.4.3) pp (0.6.2) prettyprint prettyprint (0.2.0) + prism (1.4.0) pry (0.14.1) coderay (~> 1.1) method_source (~> 1.0) @@ -394,21 +398,23 @@ GEM rspec-mocks (~> 3.10) rspec-support (~> 3.10) rspec-support (3.11.0) - rubocop (1.35.1) + rubocop (1.62.1) json (~> 2.3) + language_server-protocol (>= 3.17.0) parallel (~> 1.10) - parser (>= 3.1.2.1) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.20.1, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.21.0) - parser (>= 3.1.1.0) - rubocop-performance (1.14.3) - rubocop (>= 1.7.0, < 2.0) - rubocop-ast (>= 0.4.0) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.45.1) + parser (>= 3.3.7.2) + prism (~> 1.4) + rubocop-performance (1.23.1) + rubocop (>= 1.48.1, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) ruby-progressbar (1.11.0) ruby_parser (3.19.1) sexp_processor (~> 4.16) @@ -446,9 +452,18 @@ GEM actionpack (>= 6.1) activesupport (>= 6.1) sprockets (>= 3.0.0) - standard (1.16.1) - rubocop (= 1.35.1) - rubocop-performance (= 1.14.3) + standard (1.35.1) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.62.0) + standard-custom (~> 1.0.0) + standard-performance (~> 1.3) + standard-custom (1.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.50) + standard-performance (1.6.0) + lint_roller (~> 1.1) + rubocop-performance (~> 1.23.0) state_machine_deuxito (0.0.1) stringio (3.1.7) stripe (3.31.1) @@ -472,7 +487,7 @@ GEM concurrent-ruby (~> 1.0) uglifier (4.2.0) execjs (>= 0.3.0, < 3) - unicode-display_width (2.2.0) + unicode-display_width (2.6.0) unicorn (6.1.0) kgio (~> 2.6) raindrops (~> 0.7) @@ -549,7 +564,7 @@ DEPENDENCIES selenium-webdriver shoulda-matchers simplecov - standard + standard (~> 1.35.1) state_machine_deuxito stripe (~> 3) stripe-ruby-mock From 2bf4a799954e99024cb7058308b8a82d7ddc648c Mon Sep 17 00:00:00 2001 From: elg0nz Date: Wed, 18 Jun 2025 18:42:40 -0700 Subject: [PATCH 16/23] fix the CI healthcheck --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70335901..372abbfd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: ports: - 5432:5432 # needed because the postgres container does not provide a healthcheck - options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + options: --health-cmd 'pg_isready -U postgres' --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v4 From 8d2b9352b7637265d900b51642df9e738be1989d Mon Sep 17 00:00:00 2001 From: elg0nz Date: Wed, 18 Jun 2025 19:07:38 -0700 Subject: [PATCH 17/23] add .devcontainer --- .devcontainer/devcontainer.json | 12 ++++++---- CONTRIBUTING.md | 40 +++++++++++++++++++++++++++++++++ Dockerfile | 2 +- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 9877b53c..2c577a38 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,8 +1,11 @@ { "name": "Arooo Dockerized Dev", - "dockerComposeFile": "docker-compose.yml", + "dockerComposeFile": [ + "../docker-compose.yml" + ], "service": "app", - "workspaceFolder": "/workspace", + "runServices": ["app", "db"], + "workspaceFolder": "/app", // Features like node and postgres client are now handled by the Dockerfile for the 'app' service. // We can keep common-utils if desired for the general container experience, or remove if not needed. "features": { @@ -22,7 +25,8 @@ "KoichiSasada.vscode-rdbg", "ms-azuretools.vscode-docker", "GitHub.codespaces", - "GitHub.vscode-pull-request-github" + "GitHub.vscode-pull-request-github", + "standard.vscode-standard" ], "settings": { // Since rbenv/rvm are not explicitly installed in the Dockerfile (it uses system ruby), @@ -37,7 +41,7 @@ // The Dockerfile and docker-compose setup should handle gem installation and user setup. // postCreateCommand might still be useful for other setup, or could be removed/simplified. // For example, ensuring the database is created if it's the first time. - "postCreateCommand": "bundle check || bundle install && bundle exec rails db:prepare", + "postCreateCommand": "cp -n config/database.example.yml config/database.yml && cp -n config/application.example.yml config/application.yml && bundle check || bundle install && bundle exec rails db:prepare", // The user is defined in the Dockerfile and docker-compose.yml for the app service. // Ensure this matches if not 'vscode', or remove if service user is different and correctly set. "remoteUser": "vscode" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 47545bad..af2ff07f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -76,6 +76,46 @@ $ bundle exec rake spec 1. `bundle exec rails server` don't forget to use http://localhost:3000 and not https 1. `bundle exec rails console` Optional - useful for looking at and changing your local data) +### Development Container Setup (Recommended for VS Code Users) + +This project supports [VS Code Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers), which provides a fully configured development environment, including all necessary tools, extensions, and a running PostgreSQL database. This is the recommended way to get started if you use VS Code. + +**Prerequisites:** + +* [Docker Desktop](https://www.docker.com/products/docker-desktop/) installed and running. +* [Visual Studio Code](https://code.visualstudio.com/) installed. +* The [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) installed in VS Code. + +**Getting Started:** + +1. **Clone the Repository:** If you haven't already, clone this repository to your local machine. + ```bash + git clone + cd arooo + ``` +2. **Open in Dev Container:** + * Open the cloned `arooo` directory in VS Code. + * VS Code should automatically detect the `.devcontainer/devcontainer.json` file and show a notification in the bottom-right corner asking if you want to "Reopen in Container." Click it. + * Alternatively, open the Command Palette (Cmd+Shift+P or Ctrl+Shift+P), type "Dev Containers: Reopen in Container", and select it. +3. **First-Time Setup:** The first time you open the project in the dev container, it will build the Docker image and set up the environment. This might take a few minutes. The `postCreateCommand` defined in `devcontainer.json` will automatically: + * Copy `config/database.example.yml` to `config/database.yml` (if it doesn't exist). + * Copy `config/application.example.yml` to `config/application.yml` (if it doesn't exist). + * Run `bundle install` to install all gem dependencies. + * Run `bundle exec rails db:prepare` to set up your development database. +4. **Start the Rails Server:** Once the container is ready and VS Code is connected, open a new terminal within VS Code (Terminal > New Terminal). This terminal is inside the dev container. Then, start the Rails server: + ```bash + bundle exec rails s -p 3000 -b '0.0.0.0' + ``` +5. **Access the Application:** Open your web browser and navigate to [http://localhost:3000](http://localhost:3000). +6. **OAuth Setup (Manual Step):** For features requiring GitHub or Google OAuth (like login), you'll still need to manually: + * Create OAuth applications on GitHub and Google as described in the "[Set up an application for local OAuth](#set-up-an-application-for-local-oauth)" section below. + * Add your `CLIENT_ID` and `CLIENT_SECRET` to the `config/application.yml` file inside the dev container. (Remember, this file is created from `application.example.yml` if it didn't exist). + * Restart the Rails server after updating `config/application.yml`. + +This setup provides a consistent environment matching the project's requirements, with Ruby, PostgreSQL, and necessary VS Code extensions pre-configured. + +--- + ### Docker setup (optional) 1. Install docker and docker compose diff --git a/Dockerfile b/Dockerfile index 6fd4a54b..75b2084d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ WORKDIR /app COPY Gemfile Gemfile.lock .ruby-version ./ # Install Bundler. Use a version compatible with your Gemfile.lock (e.g., if BUNDLED WITH is 2.6.9, this covers it) -RUN gem install bundler -v '~> 2.4' --conservative --minimal-deps +RUN gem install bundler -v '~> 2.6' --conservative --minimal-deps # Configure Bundler to install gems to /usr/local/bundle (shared volume via docker-compose) ENV BUNDLE_PATH /usr/local/bundle From a058671235f0b91e252c6b6b306cb56bd52caea1 Mon Sep 17 00:00:00 2001 From: elg0nz Date: Wed, 18 Jun 2025 19:14:41 -0700 Subject: [PATCH 18/23] Apply standardrb auto-corrections --- Gemfile | 33 +++++++++---------- .../admin/memberships_controller.rb | 2 +- app/controllers/applications_controller.rb | 2 +- app/controllers/members/access_controller.rb | 4 +-- app/controllers/members/dues_controller.rb | 22 ++++++------- .../members/key_members_controller.rb | 2 +- app/controllers/members/users_controller.rb | 4 +-- app/controllers/sessions_controller.rb | 1 - app/models/application.rb | 12 +++---- app/models/door_code.rb | 18 +++++----- app/models/profile.rb | 2 +- app/models/user.rb | 8 ++--- bin/setup | 4 +-- config/environments/development.rb | 4 +-- config/environments/production.rb | 10 +++--- config/environments/test.rb | 4 +-- config/initializers/stripe.rb | 4 +-- .../20200709004913_create_door_codes.rb | 4 +-- lib/tasks/populate.rake | 2 +- .../admin/door_codes_controller_spec.rb | 12 +++---- .../applications_controller_spec.rb | 28 ++++++++-------- .../members/applications_controller_spec.rb | 22 ++++++------- .../members/dues_controller_spec.rb | 4 +-- .../members/key_members_controller_spec.rb | 4 +-- .../members/users_controller_spec.rb | 10 +++--- .../members/voting_members_controller_spec.rb | 4 +-- spec/controllers/sessions_controller_spec.rb | 10 +++--- spec/factories.rb | 2 +- spec/features/sponsorship_spec.rb | 30 ++++++++--------- spec/helpers/application_helper_spec.rb | 12 +++---- spec/models/door_code_spec.rb | 2 +- 31 files changed, 139 insertions(+), 143 deletions(-) diff --git a/Gemfile b/Gemfile index 080e8d97..ce246f34 100644 --- a/Gemfile +++ b/Gemfile @@ -1,12 +1,12 @@ source "https://rubygems.org" ruby File.read(".ruby-version").strip -gem 'concurrent-ruby', '1.3.4' -gem 'mutex_m' -gem 'drb' -gem 'benchmark' -gem 'ostruct' -gem 'observer' +gem "concurrent-ruby", "1.3.4" +gem "mutex_m" +gem "drb" +gem "benchmark" +gem "ostruct" +gem "observer" gem "rails", "~> 8.0.2" gem "jquery-rails", ">= 4.3.5" @@ -17,11 +17,11 @@ gem "omniauth" gem "omniauth-github" gem "omniauth-google-oauth2" gem "pg" -gem "state_machine_deuxito", require: 'state_machine' +gem "state_machine_deuxito", require: "state_machine" gem "kaminari", ">= 1.2.1" gem "rails_autolink", ">= 1.1.6" gem "redcarpet" -gem "configurable_engine" , "~> 2" +gem "configurable_engine", "~> 2" gem "bugsnag" gem "stripe", "~> 3" # TODO upgrade this! Carefully... gem "stripe_event" @@ -34,19 +34,19 @@ gem "uglifier" gem "coffee-rails", ">= 4.2.2" gem "bootstrap-sass" gem "jquery-datatables-rails", ">= 3.4.0" -gem 'jwt' +gem "jwt" gem "rubyzip", "~> 2.4.1" # Avoid low-severity security issue: https://github.com/advisories/GHSA-vr8q-g5c7-m54m gem "nokogiri", ">= 1.11.0.rc4" group :development do - gem "annotate" # Show db schema as comments in models - gem "better_errors" # Provides a better error page for Rails and other Rack apps - gem "binding_of_caller" # Retrieve the binding of a method's caller - gem "html2haml" - gem "awesome_print" - end + gem "annotate" # Show db schema as comments in models + gem "better_errors" # Provides a better error page for Rails and other Rack apps + gem "binding_of_caller" # Retrieve the binding of a method's caller + gem "html2haml" + gem "awesome_print" +end group :development, :test do gem "rspec-rails", ">= 4.0.0" @@ -54,7 +54,7 @@ group :development, :test do gem "rack_session_access" gem "pry-rails" gem "pry" - gem "brakeman", "~> 7.0", :require => false + gem "brakeman", "~> 7.0", require: false gem "standard", "~> 1.35.1" gem "timecop" end @@ -79,4 +79,3 @@ group :test do gem "simplecov" gem "rails-controller-testing", ">= 1.0.5" end - diff --git a/app/controllers/admin/memberships_controller.rb b/app/controllers/admin/memberships_controller.rb index 0ad4daf0..9706e06a 100644 --- a/app/controllers/admin/memberships_controller.rb +++ b/app/controllers/admin/memberships_controller.rb @@ -35,7 +35,7 @@ def change_membership_state unless allowed_updated_state raise ArgumentError.new("Unrecognized user state: #{params.dig(:user, :updated_state)}") end - action_method = user.method("make_#{allowed_updated_state}") + action_method = user.method(:"make_#{allowed_updated_state}") flash[:message] = if action_method.call "#{user.name} is now a #{user.state.humanize.downcase}." diff --git a/app/controllers/applications_controller.rb b/app/controllers/applications_controller.rb index 36b5454e..cd46ce8e 100644 --- a/app/controllers/applications_controller.rb +++ b/app/controllers/applications_controller.rb @@ -32,7 +32,7 @@ def update begin @user.application.submit! flash[:notice] = "Application submitted!" - rescue StandardError => e + rescue => e errors = @user.application.errors.full_messages.to_sentence errors = e.inspect if errors.empty? flash[:error] = "Application not submitted: #{errors}" diff --git a/app/controllers/members/access_controller.rb b/app/controllers/members/access_controller.rb index cf8f40e3..8abc56a3 100644 --- a/app/controllers/members/access_controller.rb +++ b/app/controllers/members/access_controller.rb @@ -1,4 +1,4 @@ -require 'jwt' +require "jwt" class Members::AccessController < Members::MembersController def token @@ -10,6 +10,6 @@ def token exp: Time.now.to_i + 30 } - render json: { token: JWT.encode(payload, ENV['ACCESS_CONTROL_SIGNING_KEY'], 'HS256') } + render json: {token: JWT.encode(payload, ENV["ACCESS_CONTROL_SIGNING_KEY"], "HS256")} end end diff --git a/app/controllers/members/dues_controller.rb b/app/controllers/members/dues_controller.rb index e649bf8d..6c7058d2 100644 --- a/app/controllers/members/dues_controller.rb +++ b/app/controllers/members/dues_controller.rb @@ -77,16 +77,16 @@ def redirect_target end def amount_plan_name - { 10000 => "extra_large_monthly", - 7500 => "75_monthly", - 5000 => "large_monthly", - 4500 => "45_monthly", - 4000 => "40_monthly", - 3500 => "35_monthly", - 3000 => "30_monthly", - 2500 => "medium_monthly", - 2000 => "20_monthly", - 1500 => "15_monthly", - 1000 => "small_monthly" } + {10000 => "extra_large_monthly", + 7500 => "75_monthly", + 5000 => "large_monthly", + 4500 => "45_monthly", + 4000 => "40_monthly", + 3500 => "35_monthly", + 3000 => "30_monthly", + 2500 => "medium_monthly", + 2000 => "20_monthly", + 1500 => "15_monthly", + 1000 => "small_monthly"} end end diff --git a/app/controllers/members/key_members_controller.rb b/app/controllers/members/key_members_controller.rb index 4565e748..7aa1164a 100644 --- a/app/controllers/members/key_members_controller.rb +++ b/app/controllers/members/key_members_controller.rb @@ -24,7 +24,7 @@ def agreements_missing? return true if params[:agreements].nil? agreements = params[:agreements] - !(agreements.values.all?("1")) + !agreements.values.all?("1") end def send_keymember_email diff --git a/app/controllers/members/users_controller.rb b/app/controllers/members/users_controller.rb index 6ba99514..27e0610b 100644 --- a/app/controllers/members/users_controller.rb +++ b/app/controllers/members/users_controller.rb @@ -48,8 +48,8 @@ def user_params def profile_attributes [:id, :twitter, :facebook, :website, :linkedin, :blog, - :summary, :reasons, :projects, :pronouns, :skills, - :show_name_on_site, :gravatar_email, :show_reasons, :show_projects, :show_skills] + :summary, :reasons, :projects, :pronouns, :skills, + :show_name_on_site, :gravatar_email, :show_reasons, :show_projects, :show_skills] end def set_user diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index f775a0a6..71fe4329 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,5 +1,4 @@ class SessionsController < ApplicationController - def login redirect_to members_root_path if current_user.try(:general_member?) end diff --git a/app/models/application.rb b/app/models/application.rb index 1824a8d3..b72bbcae 100644 --- a/app/models/application.rb +++ b/app/models/application.rb @@ -25,7 +25,7 @@ def self.minimum_yes_votes scope :for_applicant, -> { includes(:user) - .where('users.state': "applicant") + .where("users.state": "applicant") } scope :submitted, -> { @@ -49,9 +49,7 @@ def no_votes end def not_voted_count - @_not_voted_count ||= begin - User.voting_members.count - votes.size - end + @_not_voted_count ||= User.voting_members.count - votes.size end def stale? @@ -126,15 +124,15 @@ def sufficient_votes? end def self.to_approve - all.map { |x| x if x.approvable? && x.state == "submitted" }.compact.sort_by { |x| x.submitted_at } + all.select { |x| x.approvable? && x.state == "submitted" }.sort_by { |x| x.submitted_at } end def self.to_reject - all.map { |x| x if x.rejectable? && x.state == "submitted" }.compact.sort_by { |x| x.submitted_at } + all.select { |x| x.rejectable? && x.state == "submitted" }.sort_by { |x| x.submitted_at } end def self.not_enough_info - all.map { |x| x if !x.rejectable? && !x.approvable? && x.state == "submitted" }.compact.sort_by { |x| x.submitted_at } + all.select { |x| !x.rejectable? && !x.approvable? && x.state == "submitted" }.sort_by { |x| x.submitted_at } end private diff --git a/app/models/door_code.rb b/app/models/door_code.rb index 01d48da0..62ed71dc 100644 --- a/app/models/door_code.rb +++ b/app/models/door_code.rb @@ -2,37 +2,37 @@ class DoorCode < ApplicationRecord # We don't need an "assigned to user" status: can use the user_id field to check if a code belongs to a user enum status: { # This code is not entered in the physical lock. - not_in_lock: 'not_in_lock', + not_in_lock: "not_in_lock", # This code is entered in the physical lock. - in_lock: 'in_lock', + in_lock: "in_lock", # This code was previously assigned to a user and is still available in the lock. - formerly_assigned_in_lock: 'formerly_assigned_in_lock', + formerly_assigned_in_lock: "formerly_assigned_in_lock", # This code was previously assigned to a user, and is no longer in the lock. # We keep such codes around to avoid code re-use. - formerly_assigned_not_in_lock: 'formerly_assigned_not_in_lock', + formerly_assigned_not_in_lock: "formerly_assigned_not_in_lock", # Denylisted (assumed to not be in the lock). # Used for disallowing easily guessable codes. - denylisted: 'denylisted' + denylisted: "denylisted" } # A code without a user is available for assigning to a member belongs_to :user, optional: true validates :code, presence: true - validates :code, numericality: { only_integer: true } - validates :code, length: { minimum: 6 } + validates :code, numericality: {only_integer: true} + validates :code, length: {minimum: 6} validates_uniqueness_of :code, case_sensitive: false validates_uniqueness_of :index_number, if: -> { index_number.present? } class << self # @return [String] A randomly generated number of the requested length, as a string. May be zero-padded. def make_random_code(digits: 7) - (1..digits).map{ "0123456789".chars.to_a.sample }.join + (1..digits).map { "0123456789".chars.to_a.sample }.join end end def is_assigned? - return user.present? + user.present? end def unassign diff --git a/app/models/profile.rb b/app/models/profile.rb index c178d04c..e9ebad3b 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -18,7 +18,7 @@ def github_url # hacks -- we set username as the auth provider's username, and didn't # store it on the auth. We should write a migration, instead, and remove # this once we're confident the data looks good. - return make_github_url(user.username) unless user.username.include?("@") + make_github_url(user.username) unless user.username.include?("@") end private diff --git a/app/models/user.rb b/app/models/user.rb index c5eac94e..0946aa8e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -53,7 +53,7 @@ class User < ApplicationRecord scope :show_public, -> { all_members .includes(:profile) - .where('profiles.show_name_on_site': true) + .where("profiles.show_name_on_site": true) .where("name IS NOT NULL") .order_by_state } @@ -62,7 +62,7 @@ class User < ApplicationRecord applicants .includes(:profile) .includes(:application) - .where('applications.state': "submitted") + .where("applications.state": "submitted") .order("applications.submitted_at DESC") } @@ -70,7 +70,7 @@ class User < ApplicationRecord applicants .includes(:profile) .includes(:application) - .where('applications.state': "started") + .where("applications.state": "started") .order("applications.submitted_at DESC") } @@ -187,7 +187,7 @@ def vote_for(application) def number_applications_needing_vote if voting_member? n = Application.where(state: "submitted").count - Application.joins("JOIN votes ON votes.application_id = applications.id AND applications.state = 'submitted' AND votes.user_id = #{id}").count - n == 0 ? nil : n + (n == 0) ? nil : n end end diff --git a/bin/setup b/bin/setup index be3db3c0..3ce36fed 100755 --- a/bin/setup +++ b/bin/setup @@ -3,8 +3,8 @@ require "fileutils" APP_ROOT = File.expand_path("..", __dir__) -def system!(*args) - system(*args, exception: true) +def system!(*) + system(*, exception: true) end FileUtils.chdir APP_ROOT do diff --git a/config/environments/development.rb b/config/environments/development.rb index 4cc21c4e..4ba93a0c 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -20,7 +20,7 @@ if Rails.root.join("tmp/caching-dev.txt").exist? config.action_controller.perform_caching = true config.action_controller.enable_fragment_cache_logging = true - 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 end @@ -38,7 +38,7 @@ 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 } + 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 17496077..e351bdce 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -16,7 +16,7 @@ config.action_controller.perform_caching = true # Cache assets for far-future expiry since they are all digest stamped. - config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" } + config.public_file_server.headers = {"cache-control" => "public, max-age=#{1.year.to_i}"} # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.asset_host = "http://assets.example.com" @@ -34,8 +34,8 @@ # config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } } # Log to STDOUT with the current request id as a default log tag. - config.log_tags = [ :request_id ] - config.logger = ActiveSupport::TaggedLogging.logger(STDOUT) + config.log_tags = [:request_id] + config.logger = ActiveSupport::TaggedLogging.logger(STDOUT) # Change to "debug" to log everything (including potentially personally-identifiable information!) config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") @@ -57,7 +57,7 @@ # config.action_mailer.raise_delivery_errors = false # Set host to be used by links generated in mailer templates. - config.action_mailer.default_url_options = { host: "example.com" } + config.action_mailer.default_url_options = {host: "example.com"} # Specify outgoing SMTP server. Remember to add smtp/* credentials via rails credentials:edit. # config.action_mailer.smtp_settings = { @@ -76,7 +76,7 @@ config.active_record.dump_schema_after_migration = false # Only use :id for inspections in production. - config.active_record.attributes_for_inspect = [ :id ] + config.active_record.attributes_for_inspect = [:id] # Enable DNS rebinding protection and other `Host` header attacks. # config.hosts = [ diff --git a/config/environments/test.rb b/config/environments/test.rb index c2095b11..0fb6d30c 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -16,7 +16,7 @@ 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=3600" } + config.public_file_server.headers = {"cache-control" => "public, max-age=3600"} # Show full error reports. config.consider_all_requests_local = true @@ -37,7 +37,7 @@ config.action_mailer.delivery_method = :test # Set host to be used by links generated in mailer templates. - config.action_mailer.default_url_options = { host: "example.com" } + config.action_mailer.default_url_options = {host: "example.com"} # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr diff --git a/config/initializers/stripe.rb b/config/initializers/stripe.rb index 958661bb..6f58350a 100644 --- a/config/initializers/stripe.rb +++ b/config/initializers/stripe.rb @@ -1,4 +1,4 @@ -require 'stripe_event_handlers/stripe_event_helper' +require "stripe_event_handlers/stripe_event_helper" Rails.configuration.stripe = { event_signing_secret: ENV["STRIPE_SIGNING_SECRET"], @@ -10,7 +10,7 @@ # You can verify which Stripe API version is in use, or upgrade it, through the # Stripe developer dashboard: https://dashboard.stripe.com/developers -Stripe.api_version = '2016-02-03' +Stripe.api_version = "2016-02-03" StripeEvent.signing_secret = Rails.configuration.stripe[:event_signing_secret] diff --git a/db/migrate/20200709004913_create_door_codes.rb b/db/migrate/20200709004913_create_door_codes.rb index 3bc34ce3..56e5b3dd 100644 --- a/db/migrate/20200709004913_create_door_codes.rb +++ b/db/migrate/20200709004913_create_door_codes.rb @@ -1,8 +1,8 @@ class CreateDoorCodes < ActiveRecord::Migration[4.2] def change create_table :door_codes do |t| - t.references :user, null: false, index: { unique: true } - t.string :code, null: false, index: { unique: true } + t.references :user, null: false, index: {unique: true} + t.string :code, null: false, index: {unique: true} t.boolean :enabled, null: false, default: false t.timestamps end diff --git a/lib/tasks/populate.rake b/lib/tasks/populate.rake index 09ab53b9..5a35cff2 100644 --- a/lib/tasks/populate.rake +++ b/lib/tasks/populate.rake @@ -17,7 +17,7 @@ namespace :populate do # Some parts of the app expect members to have an application with a valid processed_at date. if %w[member key_member voting_member].include? user.state - user.application.processed_at = (1 + rand(5)).days.ago + user.application.processed_at = rand(1..5).days.ago user.save! end end diff --git a/spec/controllers/admin/door_codes_controller_spec.rb b/spec/controllers/admin/door_codes_controller_spec.rb index 5c81102c..256c23d4 100644 --- a/spec/controllers/admin/door_codes_controller_spec.rb +++ b/spec/controllers/admin/door_codes_controller_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'spec_helper' +require "spec_helper" describe Admin::DoorCodesController do include AuthHelper @@ -8,7 +8,7 @@ render_views let(:door_code) { create(:door_code) } - let(:params) { { id: door_code.id } } + let(:params) { {id: door_code.id} } describe "GET :index" do context "logged in as a non-admin member" do @@ -21,7 +21,7 @@ end context "when logged in as an admin" do - let!(:door_codes) { create_list(:door_code, 5)} + let!(:door_codes) { create_list(:door_code, 5) } before { login_as(:voting_member, is_admin: true) } @@ -45,14 +45,14 @@ it "saves the new door code" do expect { - post :create, params: { door_code: { code: "1234567", status: "in_lock", user_id: existing_member.id } } + post :create, params: {door_code: {code: "1234567", status: "in_lock", user_id: existing_member.id}} }.to change(DoorCode, :count).from(1).to(2) expect(existing_member.door_code.code).to eq("1234567") end it "doesn't save a duplicated door code" do expect { - post :create, params: { door_code: { code: existing_door_code.code, status: "in_lock" } } + post :create, params: {door_code: {code: existing_door_code.code, status: "in_lock"}} }.not_to change(DoorCode, :count) end end @@ -67,7 +67,7 @@ it "updates the door code" do expect { - patch :update, params: { id: door_code.id, door_code: { user_id: member.id } } + patch :update, params: {id: door_code.id, door_code: {user_id: member.id}} }.not_to change(DoorCode, :count) expect(door_code.reload.user.id).to eq(member.id) end diff --git a/spec/controllers/applications_controller_spec.rb b/spec/controllers/applications_controller_spec.rb index 991d64a0..f4ca846e 100644 --- a/spec/controllers/applications_controller_spec.rb +++ b/spec/controllers/applications_controller_spec.rb @@ -30,19 +30,19 @@ describe "GET show" do it "should redirect to root if not logged in" do - get :show, params: { id: 1 } + get :show, params: {id: 1} expect(response).to redirect_to :root end it "should redirect to root if logged in as visitor" do user = login_as(:visitor) - get :show, params: { id: user.application.id } + get :show, params: {id: user.application.id} expect(response).to redirect_to :root end it "should redirect to root if logged in as member" do user = login_as(:member) - get :show, params: { id: user.application.id } + get :show, params: {id: user.application.id} expect(response).to redirect_to :root end @@ -53,12 +53,12 @@ before { log_in(user) } it "should render own application" do - get :show, params: { id: user.application.id } + get :show, params: {id: user.application.id} expect(response).to render_template :show end it "should redirect to root for another user's application" do - get :show, params: { id: other_user.application.id } + get :show, params: {id: other_user.application.id} expect(response).to redirect_to :root end end @@ -66,19 +66,19 @@ describe "GET edit" do it "should redirect to root if not logged in" do - get :edit, params: { id: create(:user, state: :applicant).application.id } + get :edit, params: {id: create(:user, state: :applicant).application.id} expect(response).to redirect_to :root end it "should redirect to root if logged in as visitor" do user = login_as(:visitor) - get :edit, params: { id: user.application.id } + get :edit, params: {id: user.application.id} expect(response).to redirect_to :root end it "should redirect to root if logged in as member" do user = login_as(:member) - get :edit, params: { id: user.application.id } + get :edit, params: {id: user.application.id} expect(response).to redirect_to :root end @@ -89,12 +89,12 @@ before { log_in(user) } it "should render edit for own application" do - get :edit, params: { id: user.application.id } + get :edit, params: {id: user.application.id} expect(response).to render_template :edit end it "should redirect to root for another user's application" do - get :edit, params: { id: other_user.application.id } + get :edit, params: {id: other_user.application.id} expect(response).to redirect_to :root end end @@ -102,19 +102,19 @@ describe "POST update" do it "should redirect to root if not logged in" do - post :update, params: { id: create(:user, state: :applicant).application.id } + post :update, params: {id: create(:user, state: :applicant).application.id} expect(response).to redirect_to :root end it "should redirect to root if logged in as visitor" do user = login_as(:visitor) - post :update, params: { id: user.application.id } + post :update, params: {id: user.application.id} expect(response).to redirect_to :root end it "should redirect to root if logged in as member" do user = login_as(:member) - post :update, params: { id: user.application.id } + post :update, params: {id: user.application.id} expect(response).to redirect_to :root end @@ -225,7 +225,7 @@ end context "missing required profile fields" do - let(:profile_params) { { summary: "lemurs!", reasons: "lemur reasonss!" } } + let(:profile_params) { {summary: "lemurs!", reasons: "lemur reasonss!"} } it "should add an error to the flash" do subject diff --git a/spec/controllers/members/applications_controller_spec.rb b/spec/controllers/members/applications_controller_spec.rb index ad1d100d..1bfbe354 100644 --- a/spec/controllers/members/applications_controller_spec.rb +++ b/spec/controllers/members/applications_controller_spec.rb @@ -30,26 +30,26 @@ describe "GET show" do it "redirects if not logged in" do - get :show, params: { id: @applicant.application.id } + get :show, params: {id: @applicant.application.id} expect(response).to redirect_to :root end it "redirects if logged in as visitor" do login_as(:visitor) - get :show, params: { id: @applicant.application.id } + get :show, params: {id: @applicant.application.id} expect(response).to redirect_to :root end it "redirects if logged in as applicant" do login_as(@applicant) - get :show, params: { id: @applicant.application.id } + get :show, params: {id: @applicant.application.id} expect(response).to redirect_to :root end describe "for authenticated member" do it "redirects if application is in started state" do login_as(:member) - get :show, params: { id: @applicant.application.id } + get :show, params: {id: @applicant.application.id} expect(flash[:error]).to match(/not currently visible/) expect(response).to redirect_to members_root_path end @@ -61,7 +61,7 @@ application = applicant.application application.update_attribute(:state, "submitted") - get :show, params: { id: application.id } + get :show, params: {id: application.id} expect(response).to render_template :show end @@ -72,7 +72,7 @@ application = applicant.application application.update_attribute(:state, "approved") - get :show, params: { id: application.id } + get :show, params: {id: application.id} expect(response).to redirect_to members_root_path end @@ -83,7 +83,7 @@ application = applicant.application application.update_attribute(:state, "rejected") - get :show, params: { id: application.id } + get :show, params: {id: application.id} expect(response).to redirect_to members_root_path end @@ -96,7 +96,7 @@ end it "shows all the comments" do - get :show, params: { id: submitted_application.id } + get :show, params: {id: submitted_application.id} expect(response).to render_template :show expect(assigns(:comments)).to eq(comments) end @@ -113,7 +113,7 @@ end it "shows only comments authored by the current logged in member" do - get :show, params: { id: submitted_application.id } + get :show, params: {id: submitted_application.id} expect(assigns(:comments)).to include(comment_by_self) expect(assigns(:comments)).to_not include(comment_by_someone_else) end @@ -128,14 +128,14 @@ it "does not render voting form for member" do login_as(:member) - get :show, params: { id: @submitted_application.id } + get :show, params: {id: @submitted_application.id} expect(response).to render_template :show expect(response.body).not_to have_selector(:css, "form#new_vote") end it "renders voting form for voting member" do login_as(:voting_member) - get :show, params: { id: @submitted_application.id } + get :show, params: {id: @submitted_application.id} expect(response).to render_template :show expect(response.body).to have_selector(:css, "form#new_vote") end diff --git a/spec/controllers/members/dues_controller_spec.rb b/spec/controllers/members/dues_controller_spec.rb index 0bfbe47d..a562f880 100644 --- a/spec/controllers/members/dues_controller_spec.rb +++ b/spec/controllers/members/dues_controller_spec.rb @@ -6,7 +6,7 @@ let(:member) { create(:member) } describe "GET show" do - subject { get :show, params: { user_id: member.id } } + subject { get :show, params: {user_id: member.id} } it_should_behave_like "deny non-members", [:visitor, :applicant] it_should_behave_like "allow members", [:member, :voting_member] @@ -22,7 +22,7 @@ :member, name: "Foo Bar", email: "someone@example.com", - stripe_customer_id: 'stripe-user-id-abc123' + stripe_customer_id: "stripe-user-id-abc123" ) end diff --git a/spec/controllers/members/key_members_controller_spec.rb b/spec/controllers/members/key_members_controller_spec.rb index 76a3cb4c..9fd52d21 100644 --- a/spec/controllers/members/key_members_controller_spec.rb +++ b/spec/controllers/members/key_members_controller_spec.rb @@ -6,7 +6,7 @@ let(:member) { create :member } describe "get edit" do - let(:subject) { get :edit, params: { user_id: member } } + let(:subject) { get :edit, params: {user_id: member} } it_should_behave_like "deny non-members", [:visitor, :applicant] it_should_behave_like "allow members", [:member, :voting_member] @@ -23,7 +23,7 @@ end describe "post update" do - let(:subject) { patch :update, params: { user_id: member } } + let(:subject) { patch :update, params: {user_id: member} } it_should_behave_like "deny non-members", [:visitor, :applicant] it_should_behave_like "allow members", [:member, :voting_member] diff --git a/spec/controllers/members/users_controller_spec.rb b/spec/controllers/members/users_controller_spec.rb index 11b484ce..d2d13927 100644 --- a/spec/controllers/members/users_controller_spec.rb +++ b/spec/controllers/members/users_controller_spec.rb @@ -18,7 +18,7 @@ end describe "GET show" do - subject { get :show, params: { id: someone_cool.id } } + subject { get :show, params: {id: someone_cool.id} } it_should_behave_like "deny non-members", [:visitor, :applicant] it_should_behave_like "allow members", [:member, :voting_member] @@ -30,7 +30,7 @@ end describe "GET edit" do - subject { get :edit, params: { id: someone_cool.id } } + subject { get :edit, params: {id: someone_cool.id} } it_should_behave_like "deny non-members", [:visitor, :applicant] it_should_behave_like "allow members", [:member, :voting_member] @@ -42,7 +42,7 @@ end describe "POST update" do - subject { post :update, params: { id: someone_cool.id, user: {id: someone_cool.id} } } + subject { post :update, params: {id: someone_cool.id, user: {id: someone_cool.id}} } it_should_behave_like "deny non-members", [:visitor, :applicant] it_should_behave_like "allow members", [:member, :voting_member] @@ -93,7 +93,7 @@ end describe "GET setup" do - subject { get :setup, params: { user_id: someone_cool.id } } + subject { get :setup, params: {user_id: someone_cool.id} } it_should_behave_like "deny non-members", [:visitor, :applicant] it_should_behave_like "allow members", [:member, :voting_member] @@ -105,7 +105,7 @@ end describe "PATCH finalize" do - subject { patch :finalize, params: { user_id: someone_cool.id, user: {dues_pledge: 25} } } + subject { patch :finalize, params: {user_id: someone_cool.id, user: {dues_pledge: 25}} } it_should_behave_like "deny non-members", [:visitor, :applicant] diff --git a/spec/controllers/members/voting_members_controller_spec.rb b/spec/controllers/members/voting_members_controller_spec.rb index 37840738..cc01dc49 100644 --- a/spec/controllers/members/voting_members_controller_spec.rb +++ b/spec/controllers/members/voting_members_controller_spec.rb @@ -6,7 +6,7 @@ let(:member) { create :member } describe "get edit" do - let(:subject) { get :edit, params: { user_id: member } } + let(:subject) { get :edit, params: {user_id: member} } it_should_behave_like "deny non-members", [:visitor, :applicant] it_should_behave_like "allow members", [:member, :key_member] @@ -23,7 +23,7 @@ end describe "post update" do - let(:subject) { patch :update, params: { user_id: member } } + let(:subject) { patch :update, params: {user_id: member} } it_should_behave_like "deny non-members", [:visitor, :applicant] it_should_behave_like "allow members", [:member, :key_member] diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index fc535b76..12c3d2f6 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -38,7 +38,7 @@ request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:github] end - subject { get :create, params: { provider: "github" } } + subject { get :create, params: {provider: "github"} } describe "for a new user" do it "redirects to confirm their email address" do @@ -137,7 +137,7 @@ describe "with an existing, logged-in user" do let(:user) { create_with_omniauth(OmniAuth.config.mock_auth[:github]) } - subject { get :create, params: { provider: "google_oauth2" } } + subject { get :create, params: {provider: "google_oauth2"} } before do log_in(user) @@ -164,7 +164,7 @@ request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:google_oauth2] end - subject { get :create, params: { provider: "google_oauth2" } } + subject { get :create, params: {provider: "google_oauth2"} } describe "for a new user" do it "redirects to confirm their email address" do @@ -204,7 +204,7 @@ session[:uid] = "12345" end - subject { post :confirm_email, params: { email: email } } + subject { post :confirm_email, params: {email: email} } context "with valid params" do # This email corresponds to the mock Github login defined in @@ -298,7 +298,7 @@ session[:email_for_google] = "basil+google@example.com" end - subject { post :confirm_email, params: { email: email } } + subject { post :confirm_email, params: {email: email} } context "with a new user" do let(:email) { "basil+email@example.com" } diff --git a/spec/factories.rb b/spec/factories.rb index 19ad79b6..924f48cb 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -110,7 +110,7 @@ end factory :door_code do - sequence(:code) { |n| "#{100000+n}" } + sequence(:code) { |n| "#{100000 + n}" } sequence(:index_number) { |n| n } trait :assigned do diff --git a/spec/features/sponsorship_spec.rb b/spec/features/sponsorship_spec.rb index 5a0f6883..49d1af58 100644 --- a/spec/features/sponsorship_spec.rb +++ b/spec/features/sponsorship_spec.rb @@ -44,19 +44,19 @@ end describe "someone who is already a sponsor" do - before do - page.set_rack_session(user_id: mature_member.id) - visit members_application_path(application) - check "is_sponsor" - click_button "Submit" - end - - it "gets a meaningful message if they try to sponsor again" do - visit members_application_path(application) - check "is_sponsor" - expect { click_button "Submit" }.to_not change(Sponsorship, :count) - expect(page).to_not have_content "Sorry, something went wrong!" - expect(page).to have_content "You are already sponsoring" - end - end + before do + page.set_rack_session(user_id: mature_member.id) + visit members_application_path(application) + check "is_sponsor" + click_button "Submit" + end + + it "gets a meaningful message if they try to sponsor again" do + visit members_application_path(application) + check "is_sponsor" + expect { click_button "Submit" }.to_not change(Sponsorship, :count) + expect(page).to_not have_content "Sorry, something went wrong!" + expect(page).to have_content "You are already sponsoring" + end + end end diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 14ccbb5b..dab84dd3 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -10,31 +10,31 @@ it "should replace line breaks (Windows and *nix) with HTML breaks" do unix_input_text = "This is some text with\na *nix line break" unix_output_text = "This is some text with
\na *nix line break" - expect(markdown(unix_input_text)). to eq("

#{unix_output_text}

\n") + expect(markdown(unix_input_text)).to eq("

#{unix_output_text}

\n") windows_input_text = "This is some text with\r\na Windows line break" windows_output_text = "This is some text with
\na Windows line break" - expect(markdown(windows_input_text)). to eq("

#{windows_output_text}

\n") + expect(markdown(windows_input_text)).to eq("

#{windows_output_text}

\n") end it "should interpret " do h1_underline_input_text = "h1\n==\nbody" h1_underline_output_text = "

h1

\n\n

body

\n" - expect(markdown(h1_underline_input_text)). to eq(h1_underline_output_text) + expect(markdown(h1_underline_input_text)).to eq(h1_underline_output_text) h1_hash_input_text = "# h1\nbody" h1_hash_output_text = "

h1

\n\n

body

\n" - expect(markdown(h1_hash_input_text)). to eq(h1_hash_output_text) + expect(markdown(h1_hash_input_text)).to eq(h1_hash_output_text) end it "should interpret code" do code_block_input_text = " code1\n code2" code_block_output_text = "
code1\ncode2\n
\n" - expect(markdown(code_block_input_text)). to eq(code_block_output_text) + expect(markdown(code_block_input_text)).to eq(code_block_output_text) code_inline_input_text = "````code1\ncode2````" code_inline_output_text = "
code2````\n
\n" - expect(markdown(code_inline_input_text)). to eq(code_inline_output_text) + expect(markdown(code_inline_input_text)).to eq(code_inline_output_text) end end end diff --git a/spec/models/door_code_spec.rb b/spec/models/door_code_spec.rb index 1dcaa12e..e8a99b3f 100644 --- a/spec/models/door_code_spec.rb +++ b/spec/models/door_code_spec.rb @@ -19,7 +19,7 @@ describe ".make_random_code" do it "returns a string" do - expect(DoorCode.make_random_code()).to be_a String + expect(DoorCode.make_random_code).to be_a String end it "returns a string of the requested length" do From ba104a4a860df97121b73be2a2dd80785a34c1de Mon Sep 17 00:00:00 2001 From: elg0nz Date: Wed, 18 Jun 2025 19:28:31 -0700 Subject: [PATCH 19/23] fix(lint): Resolve all standardrb offenses --- Gemfile | 12 ++--- Gemfile.lock | 47 ++++++++++--------- .../members/applications_controller.rb | 2 +- app/helpers/application_helper.rb | 2 +- bin/setup | 2 +- config/environments/production.rb | 2 +- .../applications_controller_spec.rb | 2 +- .../members/dues_controller_spec.rb | 32 ++++++------- .../members/votes_controller_spec.rb | 4 +- spec/factories.rb | 2 +- spec/features/sponsorship_spec.rb | 28 +++++------ spec/models/vote_spec.rb | 8 ++-- 12 files changed, 73 insertions(+), 70 deletions(-) diff --git a/Gemfile b/Gemfile index ce246f34..b1431a48 100644 --- a/Gemfile +++ b/Gemfile @@ -41,11 +41,11 @@ gem "rubyzip", "~> 2.4.1" gem "nokogiri", ">= 1.11.0.rc4" group :development do - gem "annotate" # Show db schema as comments in models - gem "better_errors" # Provides a better error page for Rails and other Rack apps - gem "binding_of_caller" # Retrieve the binding of a method's caller - gem "html2haml" - gem "awesome_print" + gem "annotate" # Show db schema as comments in models + gem "better_errors" # Provides a better error page for Rails and other Rack apps + gem "binding_of_caller" # Retrieve the binding of a method's caller + gem "html2haml" + gem "awesome_print" end group :development, :test do @@ -55,7 +55,7 @@ group :development, :test do gem "pry-rails" gem "pry" gem "brakeman", "~> 7.0", require: false - gem "standard", "~> 1.35.1" + gem "standard", "~> 1.39" gem "timecop" end diff --git a/Gemfile.lock b/Gemfile.lock index 68f5c788..04ab4ab7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -77,7 +77,7 @@ GEM annotate (2.6.5) activerecord (>= 2.3.0) rake (>= 0.8.7) - ast (2.4.2) + ast (2.4.3) autoprefixer-rails (9.6.0) execjs awesome_print (1.9.2) @@ -220,7 +220,7 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - json (2.6.2) + json (2.12.2) jwt (2.3.0) kaminari (1.2.2) activesupport (>= 4.1.0) @@ -293,7 +293,7 @@ GEM oauth2 (~> 1.4) omniauth (>= 1.9, < 3) ostruct (0.6.1) - parallel (1.22.1) + parallel (1.27.0) parser (3.3.8.0) ast (~> 2.4.1) racc @@ -375,10 +375,10 @@ GEM erb psych (>= 4.0.0) redcarpet (3.5.1) - regexp_parser (2.5.0) + regexp_parser (2.10.0) reline (0.6.1) io-console (~> 0.5) - rexml (3.2.5) + rexml (3.4.1) rspec-collection_matchers (1.2.0) rspec-expectations (>= 2.99.0.beta1) rspec-core (3.11.0) @@ -398,24 +398,25 @@ GEM rspec-mocks (~> 3.10) rspec-support (~> 3.10) rspec-support (3.11.0) - rubocop (1.62.1) + rubocop (1.75.8) json (~> 2.3) - language_server-protocol (>= 3.17.0) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.31.1, < 2.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.44.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 2.4.0, < 3.0) + unicode-display_width (>= 2.4.0, < 4.0) rubocop-ast (1.45.1) parser (>= 3.3.7.2) prism (~> 1.4) - rubocop-performance (1.23.1) - rubocop (>= 1.48.1, < 2.0) - rubocop-ast (>= 1.31.1, < 2.0) - ruby-progressbar (1.11.0) + rubocop-performance (1.25.0) + lint_roller (~> 1.1) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.38.0, < 2.0) + ruby-progressbar (1.13.0) ruby_parser (3.19.1) sexp_processor (~> 4.16) rubyzip (2.4.1) @@ -452,18 +453,18 @@ GEM actionpack (>= 6.1) activesupport (>= 6.1) sprockets (>= 3.0.0) - standard (1.35.1) + standard (1.50.0) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.0) - rubocop (~> 1.62.0) + rubocop (~> 1.75.5) standard-custom (~> 1.0.0) - standard-performance (~> 1.3) + standard-performance (~> 1.8) standard-custom (1.0.2) lint_roller (~> 1.0) rubocop (~> 1.50) - standard-performance (1.6.0) + standard-performance (1.8.0) lint_roller (~> 1.1) - rubocop-performance (~> 1.23.0) + rubocop-performance (~> 1.25.0) state_machine_deuxito (0.0.1) stringio (3.1.7) stripe (3.31.1) @@ -487,7 +488,9 @@ GEM concurrent-ruby (~> 1.0) uglifier (4.2.0) execjs (>= 0.3.0, < 3) - unicode-display_width (2.6.0) + unicode-display_width (3.1.4) + unicode-emoji (~> 4.0, >= 4.0.4) + unicode-emoji (4.0.4) unicorn (6.1.0) kgio (~> 2.6) raindrops (~> 0.7) @@ -564,7 +567,7 @@ DEPENDENCIES selenium-webdriver shoulda-matchers simplecov - standard (~> 1.35.1) + standard (~> 1.39) state_machine_deuxito stripe (~> 3) stripe-ruby-mock diff --git a/app/controllers/members/applications_controller.rb b/app/controllers/members/applications_controller.rb index f388d38c..057e7518 100644 --- a/app/controllers/members/applications_controller.rb +++ b/app/controllers/members/applications_controller.rb @@ -38,7 +38,7 @@ def sponsor elsif current_user.sponsorship(application) flash[:notice] = "You are already sponsoring this application!" else - flash[:error] = "Sorry, something went wrong!" + flash[:error] = "Sorry, something went wrong!" end else Sponsorship.where(user_id: current_user, application_id: application).destroy_all diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 6f1496f8..7614c4d3 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -65,7 +65,7 @@ def google_analytics end @@markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new(hard_wrap: true, - prettify: true), + prettify: true), no_intra_emphasis: true, tables: true, fenced_code_blocks: true, diff --git a/bin/setup b/bin/setup index 3ce36fed..c27f9c8c 100755 --- a/bin/setup +++ b/bin/setup @@ -28,7 +28,7 @@ FileUtils.chdir APP_ROOT do unless ARGV.include?("--skip-server") puts "\n== Starting development server ==" - STDOUT.flush # flush the output before exec(2) so that it displays + $stdout.flush # flush the output before exec(2) so that it displays exec "bin/dev" end end diff --git a/config/environments/production.rb b/config/environments/production.rb index e351bdce..aec64cdf 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -35,7 +35,7 @@ # Log to STDOUT with the current request id as a default log tag. config.log_tags = [:request_id] - config.logger = ActiveSupport::TaggedLogging.logger(STDOUT) + config.logger = ActiveSupport::TaggedLogging.logger($stdout) # Change to "debug" to log everything (including potentially personally-identifiable information!) config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") diff --git a/spec/controllers/applications_controller_spec.rb b/spec/controllers/applications_controller_spec.rb index f4ca846e..fb93c523 100644 --- a/spec/controllers/applications_controller_spec.rb +++ b/spec/controllers/applications_controller_spec.rb @@ -144,7 +144,7 @@ it "should update the user's application" do expect { subject }.to change { application.agreement_terms }.from(false).to(true) - .and change { user.email_for_google }.from(nil).to("lemurs@gmail.com") + .and change { user.email_for_google }.from(nil).to("lemurs@gmail.com") expect(response).to redirect_to edit_application_path(application) end diff --git a/spec/controllers/members/dues_controller_spec.rb b/spec/controllers/members/dues_controller_spec.rb index a562f880..091cd909 100644 --- a/spec/controllers/members/dues_controller_spec.rb +++ b/spec/controllers/members/dues_controller_spec.rb @@ -18,12 +18,12 @@ context "when a member has an associated Stripe account without a subscription" do let(:current_user) do - login_as( - :member, - name: "Foo Bar", - email: "someone@example.com", - stripe_customer_id: "stripe-user-id-abc123" - ) + login_as( + :member, + name: "Foo Bar", + email: "someone@example.com", + stripe_customer_id: "stripe-user-id-abc123" + ) end before do @@ -72,11 +72,11 @@ # https://github.com/rebelidealist/stripe-ruby-mock/issues/209 Stripe.api_key = "coolapikey" Stripe::Plan.create(id: "test_plan", - amount: 5000, - currency: "usd", - interval: "month", - product: "test product", - name: "test plan") + amount: 5000, + currency: "usd", + interval: "month", + product: "test product", + name: "test plan") # Must set referrer so that DuesController#redirect_target works request.env["HTTP_REFERER"] = "http://example.com/members/users/x/dues" @@ -121,11 +121,11 @@ # https://github.com/rebelidealist/stripe-ruby-mock/issues/209 Stripe.api_key = "coolapikey" Stripe::Plan.create(id: "test_plan", - amount: 5000, - currency: "usd", - interval: "month", - product: "test product", - name: "test plan") + amount: 5000, + currency: "usd", + interval: "month", + product: "test product", + name: "test plan") # Must set referrer so that DuesController#redirect_target works request.env["HTTP_REFERER"] = "http://example.com/members/users/x/dues" diff --git a/spec/controllers/members/votes_controller_spec.rb b/spec/controllers/members/votes_controller_spec.rb index c44fe2a5..e91ef951 100644 --- a/spec/controllers/members/votes_controller_spec.rb +++ b/spec/controllers/members/votes_controller_spec.rb @@ -67,8 +67,8 @@ let(:params) { {id: application.id} } let(:vote) { Vote.where(application_id: application.id, - user_id: member.id, - value: true).first + user_id: member.id, + value: true).first } it "allows me to remove my vote" do diff --git a/spec/factories.rb b/spec/factories.rb index 924f48cb..eee8ade5 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -110,7 +110,7 @@ end factory :door_code do - sequence(:code) { |n| "#{100000 + n}" } + sequence(:code) { |n| (100000 + n).to_s } sequence(:index_number) { |n| n } trait :assigned do diff --git a/spec/features/sponsorship_spec.rb b/spec/features/sponsorship_spec.rb index 49d1af58..315a290f 100644 --- a/spec/features/sponsorship_spec.rb +++ b/spec/features/sponsorship_spec.rb @@ -44,19 +44,19 @@ end describe "someone who is already a sponsor" do - before do - page.set_rack_session(user_id: mature_member.id) - visit members_application_path(application) - check "is_sponsor" - click_button "Submit" - end - - it "gets a meaningful message if they try to sponsor again" do - visit members_application_path(application) - check "is_sponsor" - expect { click_button "Submit" }.to_not change(Sponsorship, :count) - expect(page).to_not have_content "Sorry, something went wrong!" - expect(page).to have_content "You are already sponsoring" - end + before do + page.set_rack_session(user_id: mature_member.id) + visit members_application_path(application) + check "is_sponsor" + click_button "Submit" + end + + it "gets a meaningful message if they try to sponsor again" do + visit members_application_path(application) + check "is_sponsor" + expect { click_button "Submit" }.to_not change(Sponsorship, :count) + expect(page).to_not have_content "Sorry, something went wrong!" + expect(page).to have_content "You are already sponsoring" + end end end diff --git a/spec/models/vote_spec.rb b/spec/models/vote_spec.rb index 154fe6be..8348d559 100644 --- a/spec/models/vote_spec.rb +++ b/spec/models/vote_spec.rb @@ -38,8 +38,8 @@ create(:vote, application: application, user: voter) invalid = Vote.new(application: application, - user: voter, - value: true) + user: voter, + value: true) expect(invalid.valid?).to be_falsey expect(invalid).to have_at_least(1).error_on(:user_id) end @@ -47,8 +47,8 @@ it "should validate user is not applicant" do application = create(:application) invalid = Vote.new(application: application, - user: application.user, - value: true) + user: application.user, + value: true) expect(invalid.valid?).to be_falsey expect(invalid).to have_at_least(1).error_on(:user) end From f02508c785de7aacbfe61236b1419a142ee92c66 Mon Sep 17 00:00:00 2001 From: elg0nz Date: Wed, 18 Jun 2025 19:31:22 -0700 Subject: [PATCH 20/23] chore(ci): Remove redundant ruby-ci.yml workflow --- .github/workflows/ruby-ci.yml | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 .github/workflows/ruby-ci.yml diff --git a/.github/workflows/ruby-ci.yml b/.github/workflows/ruby-ci.yml deleted file mode 100644 index 5be431e7..00000000 --- a/.github/workflows/ruby-ci.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Ruby CI - -on: - push: - branches: [ '**' ] - pull_request: - branches: [ main ] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: '3.4.3' - bundler-cache: true # runs 'bundle install' and caches installed gems - - name: Set up database - env: - RAILS_ENV: test - run: | - cp config/database.github-actions.yml config/database.yml - bundle exec rails db:create - bundle exec rails db:schema:load --trace - - name: Run tests - run: bundle exec rspec From 537683cce1f69477fcf69949a41b3755f05e3ae1 Mon Sep 17 00:00:00 2001 From: elg0nz Date: Wed, 18 Jun 2025 21:40:28 -0700 Subject: [PATCH 21/23] update sass gems --- Gemfile | 6 ++---- Gemfile.lock | 39 ++++++++++++++++++++------------------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/Gemfile b/Gemfile index b1431a48..ec5f135b 100644 --- a/Gemfile +++ b/Gemfile @@ -29,10 +29,8 @@ gem "rack-canonical-host" gem "aws-sdk-rails", "~> 3" gem "rack-cors" gem "haml-rails", ">= 1.0.0" -gem "sass-rails", ">= 5.0.7" -gem "uglifier" -gem "coffee-rails", ">= 4.2.2" -gem "bootstrap-sass" +gem "dartsass-rails" +gem "bootstrap", "~> 5.3.3" gem "jquery-datatables-rails", ">= 3.4.0" gem "jwt" gem "rubyzip", "~> 2.4.1" diff --git a/Gemfile.lock b/Gemfile.lock index 04ab4ab7..7d1ce6c8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -78,8 +78,6 @@ GEM activerecord (>= 2.3.0) rake (>= 0.8.7) ast (2.4.3) - autoprefixer-rails (9.6.0) - execjs awesome_print (1.9.2) aws-eventstream (1.2.0) aws-partitions (1.607.0) @@ -120,9 +118,8 @@ GEM bigdecimal (3.2.2) binding_of_caller (1.0.0) debug_inspector (>= 0.0.1) - bootstrap-sass (3.4.1) - autoprefixer-rails (>= 5.2.1) - sassc (>= 2.0.0) + bootstrap (5.3.5) + popper_js (>= 2.11.8, < 3) brakeman (7.0.2) racc bugsnag (6.24.2) @@ -138,19 +135,15 @@ GEM regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) coderay (1.1.3) - coffee-rails (5.0.0) - coffee-script (>= 2.2.0) - railties (>= 5.2.0) - coffee-script (2.4.1) - coffee-script-source - execjs - coffee-script-source (1.12.2) concurrent-ruby (1.3.4) configurable_engine (2.0.2) rails (> 5.2.0) connection_pool (2.5.3) crass (1.0.6) dante (0.2.0) + dartsass-rails (0.5.1) + railties (>= 6.0.0) + sass-embedded (~> 1.63) database_cleaner (2.0.1) database_cleaner-active_record (~> 2.0.0) database_cleaner-active_record (2.0.1) @@ -169,7 +162,6 @@ GEM erb (5.0.1) erubi (1.13.1) erubis (2.7.0) - execjs (2.8.1) factory_bot (6.2.1) activesupport (>= 5.0.0) factory_bot_rails (6.2.0) @@ -184,6 +176,12 @@ GEM thor (>= 0.14.0, < 2) globalid (1.2.1) activesupport (>= 6.1) + google-protobuf (4.31.1) + bigdecimal + rake (>= 13) + google-protobuf (4.31.1-arm64-darwin) + bigdecimal + rake (>= 13) haml (5.2.2) temple (>= 0.8.0) tilt @@ -298,6 +296,7 @@ GEM ast (~> 2.4.1) racc pg (1.4.3) + popper_js (2.11.8) pp (0.6.2) prettyprint prettyprint (0.2.0) @@ -420,6 +419,11 @@ GEM ruby_parser (3.19.1) sexp_processor (~> 4.16) rubyzip (2.4.1) + sass-embedded (1.89.2) + google-protobuf (~> 4.31) + rake (>= 13) + sass-embedded (1.89.2-arm64-darwin) + google-protobuf (~> 4.31) sass-rails (6.0.0) sassc-rails (~> 2.1, >= 2.1.1) sassc (2.0.1) @@ -486,8 +490,6 @@ GEM turbolinks-source (5.2.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - uglifier (4.2.0) - execjs (>= 0.3.0, < 3) unicode-display_width (3.1.4) unicode-emoji (~> 4.0, >= 4.0.4) unicode-emoji (4.0.4) @@ -511,6 +513,7 @@ GEM zeitwerk (2.7.3) PLATFORMS + arm64-darwin-24 ruby DEPENDENCIES @@ -520,13 +523,13 @@ DEPENDENCIES benchmark better_errors binding_of_caller - bootstrap-sass + bootstrap (~> 5.3.3) brakeman (~> 7.0) bugsnag capybara - coffee-rails (>= 4.2.2) concurrent-ruby (= 1.3.4) configurable_engine (~> 2) + dartsass-rails database_cleaner drb email_spec @@ -563,7 +566,6 @@ DEPENDENCIES rspec-collection_matchers rspec-rails (>= 4.0.0) rubyzip (~> 2.4.1) - sass-rails (>= 5.0.7) selenium-webdriver shoulda-matchers simplecov @@ -574,7 +576,6 @@ DEPENDENCIES stripe_event timecop turbolinks - uglifier unicorn webdrivers From 69d39bdb5425f211067cafc0f250f4bc3c9c3547 Mon Sep 17 00:00:00 2001 From: elg0nz Date: Sun, 20 Jul 2025 15:11:23 -0700 Subject: [PATCH 22/23] fix ci.yml --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 372abbfd..d95d530b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,7 @@ on: jobs: rspec: + name: rspec runs-on: ubuntu-latest services: @@ -29,7 +30,7 @@ jobs: ports: - 5432:5432 # needed because the postgres container does not provide a healthcheck - options: --health-cmd 'pg_isready -U postgres' --health-interval 10s --health-timeout 5s --health-retries 5 + options: --health-cmd "pg_isready -U postgres" --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v4 From 6fbf74665e85fcce1480b2db827e52060c9cec41 Mon Sep 17 00:00:00 2001 From: elg0nz Date: Mon, 21 Jul 2025 09:32:28 -0700 Subject: [PATCH 23/23] update app_record and other items --- Gemfile | 9 +- Gemfile.lock | 335 +++++++++--------- UPGRADE_PLAN.md | 27 ++ app/models/application.rb | 82 ++--- app/models/application_record.rb | 2 +- app/models/user.rb | 72 ++-- config/environment.rb | 2 + .../stripe_event_helper.rb | 34 +- spec/spec_helper.rb | 5 +- 9 files changed, 311 insertions(+), 257 deletions(-) diff --git a/Gemfile b/Gemfile index ec5f135b..e2717053 100644 --- a/Gemfile +++ b/Gemfile @@ -17,16 +17,17 @@ gem "omniauth" gem "omniauth-github" gem "omniauth-google-oauth2" gem "pg" -gem "state_machine_deuxito", require: "state_machine" +# # gem 'state_machine_deuxito', require: "state_machine" gem "kaminari", ">= 1.2.1" gem "rails_autolink", ">= 1.1.6" gem "redcarpet" -gem "configurable_engine", "~> 2" -gem "bugsnag" +# gem "configurable_engine", "~> 2" +# gem "bugsnag" gem "stripe", "~> 3" # TODO upgrade this! Carefully... gem "stripe_event" gem "rack-canonical-host" gem "aws-sdk-rails", "~> 3" +gem "twitter-bootstrap-rails", "~> 3" gem "rack-cors" gem "haml-rails", ">= 1.0.0" gem "dartsass-rails" @@ -68,7 +69,7 @@ group :test do gem "webdrivers" gem "database_cleaner" gem "email_spec" - gem "factory_bot_rails", ">= 6.1.0" + gem "factory_bot_rails", ">= 6.1.0", require: false gem "launchy" gem "rspec-collection_matchers" gem "selenium-webdriver" diff --git a/Gemfile.lock b/Gemfile.lock index 7d1ce6c8..73df3f15 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -72,124 +72,122 @@ GEM securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) uri (>= 0.13.1) - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) annotate (2.6.5) activerecord (>= 2.3.0) rake (>= 0.8.7) ast (2.4.3) awesome_print (1.9.2) - aws-eventstream (1.2.0) - aws-partitions (1.607.0) - aws-record (2.7.0) - aws-sdk-dynamodb (~> 1.18) - aws-sdk-core (3.131.2) - aws-eventstream (~> 1, >= 1.0.2) - aws-partitions (~> 1, >= 1.525.0) - aws-sigv4 (~> 1.1) + aws-eventstream (1.4.0) + aws-partitions (1.1131.0) + aws-record (2.14.0) + aws-sdk-dynamodb (~> 1, >= 1.85.0) + aws-sdk-core (3.226.3) + aws-eventstream (~> 1, >= 1.3.0) + aws-partitions (~> 1, >= 1.992.0) + aws-sigv4 (~> 1.9) + base64 jmespath (~> 1, >= 1.6.1) - aws-sdk-dynamodb (1.75.0) - aws-sdk-core (~> 3, >= 3.127.0) - aws-sigv4 (~> 1.1) - aws-sdk-rails (3.6.2) + logger + aws-sdk-dynamodb (1.146.0) + aws-sdk-core (~> 3, >= 3.225.0) + aws-sigv4 (~> 1.5) + aws-sdk-rails (3.13.0) aws-record (~> 2) - aws-sdk-ses (~> 1) - aws-sdk-sqs (~> 1) + aws-sdk-ses (~> 1, >= 1.50.0) + aws-sdk-sesv2 (~> 1, >= 1.34.0) + aws-sdk-sqs (~> 1, >= 1.56.0) aws-sessionstore-dynamodb (~> 2) - concurrent-ruby (~> 1) + concurrent-ruby (>= 1.3.1) railties (>= 5.2.0) - aws-sdk-ses (1.47.0) - aws-sdk-core (~> 3, >= 3.127.0) - aws-sigv4 (~> 1.1) - aws-sdk-sqs (1.51.1) - aws-sdk-core (~> 3, >= 3.127.0) - aws-sigv4 (~> 1.1) - aws-sessionstore-dynamodb (2.0.1) - aws-sdk-dynamodb (~> 1) - rack (~> 2) - aws-sigv4 (1.5.0) + aws-sdk-ses (1.85.0) + aws-sdk-core (~> 3, >= 3.225.0) + aws-sigv4 (~> 1.5) + aws-sdk-sesv2 (1.79.0) + aws-sdk-core (~> 3, >= 3.225.0) + aws-sigv4 (~> 1.5) + aws-sdk-sqs (1.96.0) + aws-sdk-core (~> 3, >= 3.225.0) + aws-sigv4 (~> 1.5) + aws-sessionstore-dynamodb (2.2.0) + aws-sdk-dynamodb (~> 1, >= 1.85.0) + rack (>= 2, < 4) + rack-session (>= 1, < 3) + aws-sigv4 (1.12.1) aws-eventstream (~> 1, >= 1.0.2) base64 (0.3.0) benchmark (0.4.1) - better_errors (2.9.1) - coderay (>= 1.0.0) + better_errors (2.10.1) erubi (>= 1.0.0) rack (>= 0.9.0) + rouge (>= 1.0.0) bigdecimal (3.2.2) - binding_of_caller (1.0.0) - debug_inspector (>= 0.0.1) + binding_of_caller (1.0.1) + debug_inspector (>= 1.2.0) bootstrap (5.3.5) popper_js (>= 2.11.8, < 3) - brakeman (7.0.2) + brakeman (7.1.0) racc - bugsnag (6.24.2) - concurrent-ruby (~> 1.0) builder (3.3.0) - capybara (3.37.1) + capybara (3.40.0) addressable matrix mini_mime (>= 0.1.3) - nokogiri (~> 1.8) + nokogiri (~> 1.11) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) + childprocess (5.1.0) + logger (~> 1.5) coderay (1.1.3) + commonjs (0.2.7) concurrent-ruby (1.3.4) - configurable_engine (2.0.2) - rails (> 5.2.0) connection_pool (2.5.3) crass (1.0.6) dante (0.2.0) dartsass-rails (0.5.1) railties (>= 6.0.0) sass-embedded (~> 1.63) - 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.4.1) - debug_inspector (1.1.0) - diff-lcs (1.5.0) - docile (1.4.0) + debug_inspector (1.2.0) + diff-lcs (1.6.2) + docile (1.4.1) drb (2.2.3) - email_spec (2.2.0) + email_spec (2.3.0) htmlentities (~> 4.3.3) - launchy (~> 2.1) + launchy (>= 2.1, < 4.0) mail (~> 2.7) - erb (5.0.1) + erb (5.0.2) erubi (1.13.1) erubis (2.7.0) - 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 (2.23.0) + execjs (2.10.0) + factory_bot (6.5.4) + activesupport (>= 6.1.0) + factory_bot_rails (6.5.0) + factory_bot (~> 6.5) + railties (>= 6.1.0) + faker (3.5.2) i18n (>= 1.8.11, < 2) faraday (0.17.6) multipart-post (>= 1.2, < 3) - ffi (1.13.1) - figaro (1.2.0) + ffi (1.17.2-arm64-darwin) + figaro (1.3.0) thor (>= 0.14.0, < 2) globalid (1.2.1) activesupport (>= 6.1) - google-protobuf (4.31.1) - bigdecimal - rake (>= 13) google-protobuf (4.31.1-arm64-darwin) bigdecimal rake (>= 13) - haml (5.2.2) - temple (>= 0.8.0) + haml (6.3.0) + temple (>= 0.8.2) + thor tilt - haml-rails (2.0.1) + haml-rails (2.1.0) actionpack (>= 5.1) activesupport (>= 5.1) - haml (>= 4.0.6, < 6.0) - html2haml (>= 1.0.1) + haml (>= 4.0.6) railties (>= 5.1) hashie (5.0.0) html2haml (2.3.0) @@ -200,7 +198,7 @@ GEM htmlentities (4.3.4) i18n (1.14.7) concurrent-ruby (~> 1.0) - io-console (0.8.0) + io-console (0.8.1) irb (1.15.2) pp (>= 0.6.0) rdoc (>= 4.0.0) @@ -208,18 +206,19 @@ GEM jbuilder (2.13.0) actionview (>= 5.0.0) activesupport (>= 5.0.0) - jmespath (1.6.1) + jmespath (1.6.2) jquery-datatables-rails (3.4.0) actionpack (>= 3.1) jquery-rails railties (>= 3.1) sass-rails - jquery-rails (4.5.0) + jquery-rails (4.6.0) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - json (2.12.2) - jwt (2.3.0) + json (2.13.0) + jwt (3.1.2) + base64 kaminari (1.2.2) activesupport (>= 4.1.0) kaminari-actionview (= 1.2.2) @@ -234,8 +233,16 @@ GEM kaminari-core (1.2.2) kgio (2.11.4) language_server-protocol (3.17.0.5) - launchy (2.5.0) - addressable (~> 2.7) + launchy (3.1.1) + addressable (~> 2.8) + childprocess (~> 5.0) + logger (~> 1.6) + less (2.6.0) + commonjs (~> 0.2.7) + less-rails (4.0.0) + actionpack (>= 4) + less (~> 2.6.0) + sprockets (>= 2) lint_roller (1.1.0) logger (1.7.0) loofah (2.24.1) @@ -247,16 +254,16 @@ GEM net-pop net-smtp marcel (1.0.4) - matrix (0.4.2) + matrix (0.4.3) method_source (1.1.0) mini_mime (1.1.5) - mini_portile2 (2.8.9) minitest (5.25.5) - multi_json (1.15.0) - multi_xml (0.6.0) + multi_json (1.17.0) + multi_xml (0.7.2) + bigdecimal (~> 3.1) multipart-post (2.4.1) mutex_m (0.3.0) - net-imap (0.5.8) + net-imap (0.5.9) date net-protocol net-pop (0.1.2) @@ -266,67 +273,74 @@ GEM net-smtp (0.5.1) net-protocol nio4r (2.7.4) - nokogiri (1.18.8) - mini_portile2 (~> 2.8.2) + nokogiri (1.18.8-arm64-darwin) racc (~> 1.4) - oauth2 (1.4.9) - faraday (>= 0.17.3, < 3.0) - jwt (>= 1.0, < 3.0) - multi_json (~> 1.3) + oauth2 (2.0.12) + faraday (>= 0.17.3, < 4.0) + jwt (>= 1.0, < 4.0) + logger (~> 1.2) multi_xml (~> 0.5) - rack (>= 1.2, < 3) + rack (>= 1.2, < 4) + snaky_hash (~> 2.0, >= 2.0.3) + version_gem (>= 1.1.8, < 3) observer (0.1.2) - omniauth (1.9.2) + omniauth (2.1.3) hashie (>= 3.4.6) - rack (>= 1.6.2, < 3) - omniauth-github (1.4.0) - omniauth (~> 1.5) - omniauth-oauth2 (>= 1.4.0, < 2.0) - omniauth-google-oauth2 (0.8.2) - jwt (>= 2.0) - oauth2 (~> 1.1) - omniauth (~> 1.1) - omniauth-oauth2 (>= 1.6) - omniauth-oauth2 (1.7.2) - oauth2 (~> 1.4) - omniauth (>= 1.9, < 3) - ostruct (0.6.1) + rack (>= 2.2.3) + rack-protection + omniauth-github (2.0.1) + omniauth (~> 2.0) + omniauth-oauth2 (~> 1.8) + omniauth-google-oauth2 (1.2.1) + jwt (>= 2.9.2) + oauth2 (~> 2.0) + omniauth (~> 2.0) + omniauth-oauth2 (~> 1.8) + omniauth-oauth2 (1.8.0) + oauth2 (>= 1.4, < 3) + omniauth (~> 2.0) + ostruct (0.6.3) parallel (1.27.0) parser (3.3.8.0) ast (~> 2.4.1) racc - pg (1.4.3) + pg (1.5.9) popper_js (2.11.8) pp (0.6.2) prettyprint prettyprint (0.2.0) prism (1.4.0) - pry (0.14.1) + pry (0.15.2) coderay (~> 1.1) method_source (~> 1.0) - pry-rails (0.3.9) - pry (>= 0.10.4) + pry-rails (0.3.11) + pry (>= 0.13.0) psych (5.2.6) date stringio - public_suffix (4.0.7) + public_suffix (6.0.2) racc (1.8.1) - rack (2.2.17) - rack-canonical-host (1.1.0) + rack (3.1.16) + rack-canonical-host (1.3.0) addressable (> 0, < 3) - rack (>= 1.0.0, < 3) - rack-cors (1.1.1) - rack (>= 2.0.0) - rack-session (1.0.2) - rack (< 3) + rack (>= 1.6, < 4) + rack-cors (3.0.0) + logger + rack (>= 3.0.14) + rack-protection (4.1.1) + base64 (>= 0.1.0) + logger (>= 1.6.0) + rack (>= 3.0.0, < 4) + rack-session (2.1.1) + base64 (>= 0.1.0) + rack (>= 3.0.0) rack-test (2.2.0) rack (>= 1.3) rack_session_access (0.2.0) builder (>= 2.0.0) rack (>= 1.0.0) - rackup (1.0.1) - rack (< 3) - webrick + rackup (2.2.1) + rack (>= 3) rails (8.0.2) actioncable (= 8.0.2) actionmailbox (= 8.0.2) @@ -355,8 +369,10 @@ GEM rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging - rails_autolink (1.1.6) - rails (> 3.1) + rails_autolink (1.1.8) + actionview (> 3.1) + activesupport (> 3.1) + railties (> 3.1) rails_serve_static_assets (0.0.5) rails_stdout_logging (0.0.5) railties (8.0.2) @@ -368,35 +384,36 @@ GEM thor (~> 1.0, >= 1.2.2) zeitwerk (~> 2.6) rainbow (3.1.1) - raindrops (0.20.0) + raindrops (0.20.1) rake (13.3.0) - rdoc (6.14.0) + rdoc (6.14.2) erb psych (>= 4.0.0) - redcarpet (3.5.1) + redcarpet (3.6.1) regexp_parser (2.10.0) reline (0.6.1) io-console (~> 0.5) rexml (3.4.1) - rspec-collection_matchers (1.2.0) + rouge (4.5.2) + rspec-collection_matchers (1.2.1) rspec-expectations (>= 2.99.0.beta1) - rspec-core (3.11.0) - rspec-support (~> 3.11.0) - rspec-expectations (3.11.0) + rspec-core (3.13.5) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.11.0) - rspec-mocks (3.11.1) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.5) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.11.0) - rspec-rails (5.1.2) - actionpack (>= 5.2) - activesupport (>= 5.2) - railties (>= 5.2) - rspec-core (~> 3.10) - rspec-expectations (~> 3.10) - rspec-mocks (~> 3.10) - rspec-support (~> 3.10) - rspec-support (3.11.0) + rspec-support (~> 3.13.0) + rspec-rails (8.0.1) + actionpack (>= 7.2) + activesupport (>= 7.2) + railties (>= 7.2) + rspec-core (~> 3.13) + rspec-expectations (~> 3.13) + rspec-mocks (~> 3.13) + rspec-support (~> 3.13) + rspec-support (3.13.4) rubocop (1.75.8) json (~> 2.3) language_server-protocol (~> 3.17.0.2) @@ -408,7 +425,7 @@ GEM rubocop-ast (>= 1.44.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.45.1) + rubocop-ast (1.46.0) parser (>= 3.3.7.2) prism (~> 1.4) rubocop-performance (1.25.0) @@ -416,19 +433,16 @@ GEM rubocop (>= 1.75.0, < 2.0) rubocop-ast (>= 1.38.0, < 2.0) ruby-progressbar (1.13.0) - ruby_parser (3.19.1) + ruby_parser (3.21.1) + racc (~> 1.5) sexp_processor (~> 4.16) rubyzip (2.4.1) - sass-embedded (1.89.2) - google-protobuf (~> 4.31) - rake (>= 13) sass-embedded (1.89.2-arm64-darwin) google-protobuf (~> 4.31) sass-rails (6.0.0) sassc-rails (~> 2.1, >= 2.1.1) - sassc (2.0.1) + sassc (2.4.0) ffi (~> 1.9) - rake sassc-rails (2.1.2) railties (>= 4.0.0) sassc (>= 2.0) @@ -436,19 +450,24 @@ GEM sprockets-rails tilt securerandom (0.4.1) - selenium-webdriver (4.8.1) + selenium-webdriver (4.34.0) + base64 (~> 0.2) + logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) - sexp_processor (4.16.1) - shoulda-matchers (5.3.0) + sexp_processor (4.17.3) + shoulda-matchers (6.5.0) activesupport (>= 5.2.0) simplecov (0.22.0) docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) - simplecov-html (0.12.3) + simplecov-html (0.13.2) simplecov_json_formatter (0.1.4) + snaky_hash (2.0.3) + hashie (>= 0.1.0, < 6) + version_gem (>= 1.1.8, < 3) sprockets (4.2.2) concurrent-ruby (~> 1.0) logger @@ -469,7 +488,6 @@ GEM standard-performance (1.8.0) lint_roller (~> 1.1) rubocop-performance (~> 1.25.0) - state_machine_deuxito (0.0.1) stringio (3.1.7) stripe (3.31.1) faraday (~> 0.10) @@ -480,14 +498,19 @@ GEM stripe_event (2.12.0) activesupport (>= 3.1) stripe (>= 2.8, < 16) - temple (0.8.2) - thor (1.3.2) - tilt (2.0.11) - timecop (0.9.5) + temple (0.10.3) + thor (1.4.0) + tilt (2.6.1) + timecop (0.9.10) timeout (0.4.3) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) + twitter-bootstrap-rails (3.2.2) + actionpack (>= 3.1) + execjs (>= 2.2.2, >= 2.2) + less-rails (>= 2.5.0) + railties (>= 3.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (3.1.4) @@ -498,12 +521,12 @@ GEM raindrops (~> 0.7) uri (1.0.3) useragent (0.16.11) + version_gem (1.1.8) webdrivers (5.2.0) nokogiri (~> 1.6) rubyzip (>= 1.3.0) selenium-webdriver (~> 4.0) - webrick (1.9.1) - websocket (1.2.9) + websocket (1.2.11) websocket-driver (0.8.0) base64 websocket-extensions (>= 0.1.0) @@ -514,7 +537,6 @@ GEM PLATFORMS arm64-darwin-24 - ruby DEPENDENCIES annotate @@ -525,12 +547,9 @@ DEPENDENCIES binding_of_caller bootstrap (~> 5.3.3) brakeman (~> 7.0) - bugsnag capybara concurrent-ruby (= 1.3.4) - configurable_engine (~> 2) dartsass-rails - database_cleaner drb email_spec factory_bot_rails (>= 6.1.0) @@ -570,12 +589,12 @@ DEPENDENCIES shoulda-matchers simplecov standard (~> 1.39) - state_machine_deuxito stripe (~> 3) stripe-ruby-mock stripe_event timecop turbolinks + twitter-bootstrap-rails (~> 3) unicorn webdrivers diff --git a/UPGRADE_PLAN.md b/UPGRADE_PLAN.md index d70485da..9249c5f0 100644 --- a/UPGRADE_PLAN.md +++ b/UPGRADE_PLAN.md @@ -243,6 +243,33 @@ These instructions outline how to set up and use the Docker-based environment fo * [ ] **Post-Deployment Monitoring:** * Closely monitor application logs, error tracking, and performance. +## Debugging Upgrade Issues + +### `FrozenError: can't modify frozen Array` + +This error has been the primary blocker during the upgrade. It occurs during the Rails initialization process when running `rspec`. + +**Key Information:** +* **Ruby Version Upgrade:** From `2.7.7` to `3.4.3`. +* **Rails Version Upgrade:** From `~> 6.0` to `~> 8.0.2`. +* **Error Message:** `FrozenError: can't modify frozen Array: ["/Users/gonz/.asdf/installs/ruby/3.4.3/lib/ruby/gems/3.4.0/gems/actiontext-8.0.2/app/helpers", "/Users/gonz/.asdf/installs/ruby/3.4.3/lib/ruby/gems/3.4.0/gems/actiontext-8.0.2/app/models"]` + +**Investigation Log:** + +1. **Disabled Gems:** The following gems were disabled as initial suspects for causing the `FrozenError`: + * `state_machine_deuxito` + * `configurable_engine` + * `bugsnag` + * **Result:** The error persisted after disabling each of these. + +2. **`factory_bot_rails` Loading Order:** Investigated the possibility that `factory_bot_rails` was loading its definitions too early. + * **Action:** Modified `Gemfile` to use `require: false` and added `FactoryBot.find_definitions` to the `spec_helper.rb` `before(:suite)` block. + * **Result:** Error persisted, indicating this was not the root cause. + +3. **`simplecov`:** Identified as a likely culprit because it loads before the Rails environment in `spec_helper.rb` and could interfere with the initialization process in newer Rails/Ruby versions. + * **Action:** Commented out `simplecov` initialization in `spec_helper.rb`. + * **Next Step:** Run the test suite to confirm if the `FrozenError` is resolved. + ## Notes & Potential Issues * [Add any project-specific notes, known problematic gems, or areas of concern here] diff --git a/app/models/application.rb b/app/models/application.rb index b72bbcae..7f71206f 100644 --- a/app/models/application.rb +++ b/app/models/application.rb @@ -1,4 +1,4 @@ -require "state_machine" # from gem state_machine_deuxito +# require "state_machine" # from gem state_machine_deuxito class Application < ApplicationRecord belongs_to :user @@ -70,46 +70,46 @@ def votes_threshold_email end end - state_machine :state, initial: :started do - after_transition started: :submitted do |application, _| - application.touch :submitted_at - ApplicationsMailer.confirmation(application).deliver_now - - if Configurable[:send_new_application_emails] - member_emails = User.all_members.pluck(:email).compact - (member_emails << JOIN_EMAIL).each do |email| - ApplicationsMailer.notify_member_of_application(application, email).deliver_now - end - end - end - - after_transition submitted: [:approved, :rejected] do |application, transition| - application.touch :processed_at - end - - after_transition submitted: :approved do |application| - application.user.make_member - ApplicationsMailer.approved(application).deliver_now - end - - event :submit do - transition started: :submitted - transition rejected: :submitted - end - - event :approve do - transition submitted: :approved - end - - event :reject do - transition submitted: :rejected - end - - state :started - state :submitted - state :approved - state :rejected - end + # state_machine :state, initial: :started do + # after_transition started: :submitted do |application, _| + # application.touch :submitted_at + # ApplicationsMailer.confirmation(application).deliver_now + # + # if Configurable[:send_new_application_emails] + # member_emails = User.all_members.pluck(:email).compact + # (member_emails << JOIN_EMAIL).each do |email| + # ApplicationsMailer.notify_member_of_application(application, email).deliver_now + # end + # end + # end + # + # after_transition submitted: [:approved, :rejected] do |application, transition| + # application.touch :processed_at + # end + # + # after_transition submitted: :approved do |application| + # application.user.make_member + # ApplicationsMailer.approved(application).deliver_now + # end + # + # event :submit do + # transition started: :submitted + # transition rejected: :submitted + # end + # + # event :approve do + # transition submitted: :approved + # end + # + # event :reject do + # transition submitted: :rejected + # end + # + # state :started + # state :submitted + # state :approved + # state :rejected + # end def approvable? enough_yes && few_nos && sponsored diff --git a/app/models/application_record.rb b/app/models/application_record.rb index 6a57d9c2..45fb2f74 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,4 +1,4 @@ -require "state_machine" # from gem state_machine_deuxito +# require "state_machine" # from gem state_machine_deuxito class ApplicationRecord < ActiveRecord::Base self.abstract_class = true diff --git a/app/models/user.rb b/app/models/user.rb index 0946aa8e..9e7bfc1d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -95,42 +95,42 @@ class User < ApplicationRecord .squish)) } - state_machine :state, initial: :visitor do - event :make_applicant do - transition visitor: :applicant - end - - event :make_member do - transition [:applicant, :voting_member, :key_member, :former_member] => :member - end - - event :make_key_member do - transition [:member, :voting_member] => :key_member - end - - event :make_voting_member do - transition [:member, :key_member] => :voting_member - end - - event :make_former_member do - transition [:member, :voting_member, :key_member] => :former_member - end - - after_transition on: all - [:make_voting_member] do |user, _| - user.update(voting_policy_agreement: false) - end - - after_transition on: all - [:make_key_member, :make_voting_member] do |user, _| - user.door_code.unassign if user.door_code.present? - end - - state :visitor - state :applicant - state :member - state :key_member - state :voting_member - state :former_member - end + # state_machine :state, initial: :visitor do + # event :make_applicant do + # transition visitor: :applicant + # end + # + # event :make_member do + # transition [:applicant, :voting_member, :key_member, :former_member] => :member + # end + # + # event :make_key_member do + # transition [:member, :voting_member] => :key_member + # end + # + # event :make_voting_member do + # transition [:member, :key_member] => :voting_member + # end + # + # event :make_former_member do + # transition [:member, :voting_member, :key_member] => :former_member + # end + # + # after_transition on: all - [:make_voting_member] do |user, _| + # user.update(voting_policy_agreement: false) + # end + # + # after_transition on: all - [:make_key_member, :make_voting_member] do |user, _| + # user.door_code.unassign if user.door_code.present? + # end + # + # state :visitor + # state :applicant + # state :member + # state :key_member + # state :voting_member + # state :former_member + # end def general_member? member? || key_member? || voting_member? diff --git a/config/environment.rb b/config/environment.rb index cac53157..1410b7a3 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,5 +1,7 @@ # Load the Rails application. + require_relative "application" + # Initialize the Rails application. Rails.application.initialize! diff --git a/lib/stripe_event_handlers/stripe_event_helper.rb b/lib/stripe_event_handlers/stripe_event_helper.rb index 93b28f4f..ae514eb2 100644 --- a/lib/stripe_event_handlers/stripe_event_helper.rb +++ b/lib/stripe_event_handlers/stripe_event_helper.rb @@ -1,21 +1,25 @@ -module StripeEventHelper - class ChargeSucceeded - def call(event) - stripe_customer_id = event.data.object.customer - user = User.find_by stripe_customer_id: stripe_customer_id - user.last_stripe_charge_succeeded = Time.at(event.data.object.created).to_datetime - user.save! +module StripeEventHandlers + module StripeEventHelper + class ChargeSucceeded + def call(event) + stripe_customer_id = event.data.object.customer + user = User.find_by stripe_customer_id: stripe_customer_id + user.last_stripe_charge_succeeded = Time.at(event.data.object.created).to_datetime + user.save! + end end - end - class ChargeFailed - def call(event) - email = if event.data.object.customer.present? - User.find_by_stripe_customer_id(event.data.object.customer).email - else - event.data.object.source.name + class ChargeFailed + def call(event) + customer = User.find_by_stripe_customer_id(event.data.object.customer) + charge = event.data.object + email = if customer.respond_to?(:email) && customer.email.present? + customer.email + else + charge.receipt_email + end + DuesMailer.failed(email).deliver_now end - DuesMailer.failed(email).deliver_now end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 933f9137..f0f9d32d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,6 +1,6 @@ # This file is copied to spec/ when you run 'rails generate rspec:install' -require "simplecov" -SimpleCov.start +# require "simplecov" +# SimpleCov.start ENV["RAILS_ENV"] ||= "test" require File.expand_path("../../config/environment", __FILE__) @@ -80,6 +80,7 @@ config.before(:suite) do DatabaseCleaner.strategy = :truncation + FactoryBot.find_definitions end config.before(:each) do DatabaseCleaner.start