diff --git a/.rubocop.yml b/.rubocop.yml index 472e0f0..5a901d6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,9 +1,17 @@ -require: +inherit_from: .rubocop_todo.yml + +inherit_mode: + merge: + - Exclude + +plugins: - rubocop-performance - rubocop-rails # Stolen from https://gist.github.com/jhass/a5ae80d87f18e53e7b56 AllCops: + NewCops: disable + SuggestExtensions: false Exclude: - "bin/**/*" - "db/schema.rb" @@ -13,7 +21,7 @@ Rails: Enabled: true # Commonly used screens these days easily fit more than 80 characters. -Metrics/LineLength: +Layout/LineLength: Max: 120 # Too short methods lead to extraction of single-use methods, which can make @@ -36,7 +44,7 @@ Metrics/AbcSize: Max: 50 Metrics/BlockLength: - ExcludedMethods: + AllowedMethods: - "namespace" - "create_table" Exclude: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..de039d0 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,563 @@ +# This configuration was generated by +# `rubocop --auto-gen-config --no-exclude-limit` +# on 2026-04-28 09:58:15 UTC using RuboCop version 1.86.1. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation. +Bundler/OrderedGems: + Exclude: + - 'Gemfile' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleAlignWith. +# SupportedStylesAlignWith: either, start_of_block, start_of_line +Layout/BlockAlignment: + Exclude: + - 'spec/routing/tournaments_routing_spec.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowForAlignment. +Layout/CommentIndentation: + Exclude: + - 'app/serializers/tournament_serializer.rb' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLineAfterGuardClause: + Exclude: + - 'app/controllers/tournaments_controller.rb' + - 'config/spring.rb' + - 'spec/factories/tournaments.rb' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, DefLikeMacros, AllowAdjacentOneLineDefs, NumberOfEmptyLines. +Layout/EmptyLineBetweenDefs: + Exclude: + - 'app/controllers/tournaments_controller.rb' + - 'app/services/tournament_snapshot_importer.rb' + - 'e2e/lib/scenario_runner.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLines: + Exclude: + - 'app/controllers/tournaments_controller.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: around, only_before +Layout/EmptyLinesAroundAccessModifier: + Exclude: + - 'db/migrate/20220516203839_create_active_storage_variant_records.active_storage.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only +Layout/EmptyLinesAroundClassBody: + Exclude: + - 'config/application.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_brackets +Layout/FirstArrayElementIndentation: + EnforcedStyle: consistent + +# Offense count: 6 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_braces +Layout/FirstHashElementIndentation: + Exclude: + - 'spec/e2e/http/tournament_follow_sync_spec.rb' + +# Offense count: 5 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: normal, indented_internal_methods +Layout/IndentationConsistency: + Exclude: + - 'db/migrate/20220516203839_create_active_storage_variant_records.active_storage.rb' + - 'e2e/lib/scenario_runner.rb' + - 'spec/routing/tournaments_routing_spec.rb' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Width, EnforcedStyleAlignWith, AllowedPatterns. +# SupportedStylesAlignWith: start_of_line, relative_to_receiver +Layout/IndentationWidth: + Exclude: + - 'db/migrate/20220516203839_create_active_storage_variant_records.active_storage.rb' + - 'spec/routing/tournaments_routing_spec.rb' + +# Offense count: 10 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: aligned, indented, indented_relative_to_receiver +Layout/MultilineMethodCallIndentation: + Exclude: + - 'app/interactors/advance_teams_in_intermediate_stage.rb' + - 'e2e/lib/scenario_runner.rb' + - 'spec/e2e/http/api_surface_spec.rb' + - 'spec/e2e/http/tournament_follow_sync_live_websocket_spec.rb' + - 'spec/e2e/http/tournament_follow_sync_spec.rb' + - 'spec/e2e/http/tournament_lifecycle_spec.rb' + - 'spec/e2e/http/tournament_live_websocket_spec.rb' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: aligned, indented +Layout/MultilineOperationIndentation: + Exclude: + - 'app/services/group_stage_service.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Layout/SpaceInsidePercentLiteralDelimiters: + Exclude: + - 'db/migrate/20220516203839_create_active_storage_variant_records.active_storage.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: final_newline, final_blank_line +Layout/TrailingEmptyLines: + Exclude: + - 'spec/support/profile.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowSafeAssignment. +Lint/AssignmentInCondition: + Exclude: + - 'db/migrate/20220516203838_add_service_name_to_active_storage_blobs.active_storage.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Lint/ScriptPermission: + Exclude: + - 'script/e2e_scenarios.rb' + - 'script/wait_for_http.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions. +# NotImplementedExceptions: NotImplementedError +Lint/UnusedMethodArgument: + Exclude: + - 'app/controllers/application_controller.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Lint/UselessAssignment: + Exclude: + - 'e2e/lib/scenario_runner.rb' + - 'spec/models/beamer_spec.rb' + +# Offense count: 6 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max. +Metrics/AbcSize: + Exclude: + - 'app/controllers/tournaments_controller.rb' + - 'app/services/tournament_snapshot_importer.rb' + - 'e2e/lib/scenario_runner.rb' + - 'spec/e2e/http/tournament_follow_sync_spec.rb' + - 'spec/services/tournament_snapshot_importer_spec.rb' + +# Offense count: 2 +# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns. +# AllowedMethods: refine +Metrics/BlockLength: + Exclude: + - 'app/services/tournament_snapshot_importer.rb' + - 'db/schema.rb' + +# Offense count: 15 +# Configuration parameters: AllowedMethods, AllowedPatterns, Max. +Metrics/CyclomaticComplexity: + Exclude: + - 'app/controllers/matches_controller.rb' + - 'app/controllers/tournaments_controller.rb' + - 'app/models/group_score.rb' + - 'app/models/stage.rb' + - 'app/services/group_stage_service.rb' + - 'app/services/playoff_stage_service.rb' + - 'e2e/lib/api_client.rb' + - 'spec/e2e/http/tournament_follow_sync_spec.rb' + - 'spec/services/tournament_snapshot_importer_spec.rb' + +# Offense count: 1 +# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns. +Metrics/MethodLength: + Exclude: + - 'app/controllers/tournaments_controller.rb' + +# Offense count: 1 +# Configuration parameters: Max, CountKeywordArgs, MaxOptionalParameters. +Metrics/ParameterLists: + Exclude: + - 'e2e/lib/api_client.rb' + +# Offense count: 14 +# Configuration parameters: AllowedMethods, AllowedPatterns, Max. +Metrics/PerceivedComplexity: + Exclude: + - 'app/controllers/matches_controller.rb' + - 'app/controllers/tournaments_controller.rb' + - 'app/models/group_score.rb' + - 'app/models/stage.rb' + - 'app/services/group_stage_service.rb' + - 'e2e/lib/api_client.rb' + - 'spec/e2e/http/tournament_follow_sync_spec.rb' + - 'spec/services/tournament_snapshot_importer_spec.rb' + +# Offense count: 3 +# This cop supports unsafe autocorrection (--autocorrect-all). +Performance/Count: + Exclude: + - 'app/controllers/tournaments_controller.rb' + - 'spec/services/tournament_snapshot_importer_spec.rb' + +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: SafeMultiline. +Performance/DeleteSuffix: + Exclude: + - 'e2e/lib/action_cable_client.rb' + - 'e2e/lib/api_client.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Performance/RegexpMatch: + Exclude: + - 'config/spring.rb' + +# Offense count: 14 +# This cop supports unsafe autocorrection (--autocorrect-all). +Performance/TimesMap: + Exclude: + - 'e2e/lib/scenario_runner.rb' + - 'spec/e2e/http/api_surface_spec.rb' + - 'spec/e2e/http/tournament_beamers_websocket_spec.rb' + - 'spec/e2e/http/tournament_follow_sync_beamers_websocket_spec.rb' + - 'spec/e2e/http/tournament_follow_sync_spec.rb' + - 'spec/e2e/http/tournament_follow_sync_websocket_spec.rb' + - 'spec/e2e/http/tournament_sync_test_spec.rb' + - 'spec/e2e/http/tournament_team_action_lists_websocket_spec.rb' + - 'spec/e2e/http/tournament_timer_follow_sync_websocket_spec.rb' + - 'spec/e2e/http/tournament_timer_websocket_spec.rb' + - 'spec/services/tournament_snapshot_importer_spec.rb' + +# Offense count: 3 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: NilOrEmpty, NotPresent, UnlessPresent. +Rails/Blank: + Exclude: + - 'e2e/lib/scenario_runner.rb' + - 'spec/e2e/http/tournament_sync_test_spec.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforceForPrefixed. +Rails/Delegate: + Exclude: + - 'e2e/lib/action_cable_client.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: slashes, arguments +Rails/FilePath: + Exclude: + - 'config/environments/development.rb' + - 'spec/rails_helper.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Rails/IndexBy: + Exclude: + - 'spec/e2e/http/tournament_follow_sync_spec.rb' + +# Offense count: 1 +# Configuration parameters: IgnoreScopes. +Rails/InverseOf: + Exclude: + - 'app/models/tournament.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: NotNilAndNotEmpty, NotBlank, UnlessBlank. +Rails/Present: + Exclude: + - 'e2e/lib/api_client.rb' + +# Offense count: 1 +Rails/ReversibleMigration: + Exclude: + - 'db/migrate/20240407180900_add_default_to_position_in_group_scores.rb' + +# Offense count: 9 +# Configuration parameters: ForbiddenMethods, AllowedMethods. +# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all +Rails/SkipsModelValidations: + Exclude: + - 'app/models/tournament_sync_queue_entry.rb' + - 'app/services/tournament_sync_pusher.rb' + - 'db/migrate/20220516203838_add_service_name_to_active_storage_blobs.active_storage.rb' + - 'db/migrate/20260416102000_backfill_default_beamers_by_name.rb' + - 'spec/controllers/tournaments_controller_spec.rb' + +# Offense count: 33 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: strict, flexible +Rails/TimeZone: + Exclude: + - 'e2e/lib/action_cable_client.rb' + - 'e2e/lib/scenario_runner.rb' + - 'spec/e2e/http/tournament_beamers_websocket_spec.rb' + - 'spec/e2e/http/tournament_follow_sync_beamers_websocket_spec.rb' + - 'spec/e2e/http/tournament_follow_sync_spec.rb' + - 'spec/e2e/http/tournament_follow_sync_websocket_spec.rb' + - 'spec/e2e/http/tournament_team_action_lists_websocket_spec.rb' + - 'spec/e2e/http/tournament_timer_follow_sync_websocket_spec.rb' + - 'spec/e2e/http/tournament_timer_websocket_spec.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. +# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces +# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object +# FunctionalMethods: let, let!, subject, watch +# AllowedMethods: lambda, proc, it +Style/BlockDelimiters: + Exclude: + - 'spec/controllers/beamers_controller_spec.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Keywords, RequireColon. +# Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW, NOTE +Style/CommentAnnotation: + Exclude: + - 'spec/controllers/matches_controller_spec.rb' + - 'spec/services/group_stage_service_spec.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions. +# SupportedStyles: assign_to_condition, assign_inside_condition +Style/ConditionalAssignment: + Exclude: + - 'spec/factories/tournaments.rb' + +# Offense count: 12 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, always_true, never +Style/FrozenStringLiteralComment: + Exclude: + - 'config/boot.rb' + - 'config/initializers/filter_parameter_logging.rb' + - 'config/initializers/new_framework_defaults_7_0.rb' + - 'db/migrate/20220516203838_add_service_name_to_active_storage_blobs.active_storage.rb' + - 'db/migrate/20220516203839_create_active_storage_variant_records.active_storage.rb' + - 'db/migrate/20220516203840_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb' + - 'db/migrate/20240407175005_add_position_to_group_scores.rb' + - 'db/migrate/20240407180900_add_default_to_position_in_group_scores.rb' + - 'db/migrate/20250309202658_add_timer_end_to_tournaments.rb' + - 'db/migrate/20260423133000_add_timer_mode_to_tournaments.rb' + - 'db/schema.rb' + - 'spec/support/profile.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/GlobalStdStream: + Exclude: + - 'config/environments/production.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. +Style/GuardClause: + Exclude: + - 'db/migrate/20220516203838_add_service_name_to_active_storage_blobs.active_storage.rb' + +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/IdenticalConditionalBranches: + Exclude: + - 'spec/e2e/http/tournament_lifecycle_spec.rb' + +# Offense count: 18 +# This cop supports safe autocorrection (--autocorrect). +Style/IfUnlessModifier: + Exclude: + - 'app/controllers/tournaments_controller.rb' + - 'app/services/group_stage_service.rb' + - 'app/services/playoff_stage_service.rb' + - 'e2e/lib/scenario_runner.rb' + +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: InverseMethods, InverseBlocks. +Style/InverseMethods: + Exclude: + - 'spec/e2e/http/tournament_lifecycle_spec.rb' + +# Offense count: 3 +Style/MultilineBlockChain: + Exclude: + - 'e2e/lib/api_client.rb' + - 'spec/e2e/http/tournament_follow_sync_spec.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: MinDigits, Strict, AllowedNumbers, AllowedPatterns. +Style/NumericLiterals: + Exclude: + - 'db/schema.rb' + +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. +# SupportedStyles: predicate, comparison +Style/NumericPredicate: + Exclude: + - 'e2e/lib/scenario_runner.rb' + +# Offense count: 1 +# Configuration parameters: AllowedMethods. +# AllowedMethods: respond_to_missing? +Style/OptionalBooleanParameter: + Exclude: + - 'app/services/playoff_stage_service.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantFreeze: + Exclude: + - 'e2e/lib/scenario_runner.rb' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowMultipleReturnValues. +Style/RedundantReturn: + Exclude: + - 'app/controllers/tournaments_controller.rb' + +# Offense count: 3 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/RedundantSort: + Exclude: + - 'spec/e2e/http/tournament_follow_sync_spec.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. +# AllowedMethods: present?, blank?, presence, try, try! +Style/SafeNavigation: + Exclude: + - 'config/spring.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: Mode. +Style/StringConcatenation: + Exclude: + - 'config/spring.rb' + +# Offense count: 246 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiterals: + Exclude: + - 'config/boot.rb' + - 'db/migrate/20220516203839_create_active_storage_variant_records.active_storage.rb' + - 'db/schema.rb' + - 'spec/e2e/http/api_surface_spec.rb' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: . +# SupportedStyles: percent, brackets +Style/SymbolArray: + EnforcedStyle: percent + MinSize: 10 + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. +# AllowedMethods: define_method, mail, respond_to +Style/SymbolProc: + Exclude: + - 'spec/services/tournament_snapshot_importer_spec.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma +Style/TrailingCommaInArrayLiteral: + Exclude: + - 'spec/services/playoff_stage_service_spec.rb' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: WordRegex. +# SupportedStyles: percent, brackets +Style/WordArray: + EnforcedStyle: percent + MinSize: 3 + +# Offense count: 6 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/ZeroLengthPredicate: + Exclude: + - 'app/models/stage.rb' + - 'app/services/group_stage_service.rb' + +# Offense count: 113 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings. +# URISchemes: http, https +Layout/LineLength: + Exclude: + - 'app/controllers/matches_controller.rb' + - 'app/controllers/tournaments_controller.rb' + - 'app/models/team_action_list.rb' + - 'app/services/group_stage_service.rb' + - 'app/services/playoff_stage_service.rb' + - 'db/schema.rb' + - 'e2e/lib/api_client.rb' + - 'e2e/lib/scenario_runner.rb' + - 'script/e2e_scenarios.rb' + - 'spec/controllers/groups_controller_spec.rb' + - 'spec/controllers/matches_controller_spec.rb' + - 'spec/controllers/stages_controller_spec.rb' + - 'spec/controllers/team_action_lists_controller_spec.rb' + - 'spec/e2e/http/api_surface_spec.rb' + - 'spec/e2e/http/tournament_follow_sync_spec.rb' + - 'spec/e2e/http/tournament_follow_sync_websocket_spec.rb' + - 'spec/e2e/http/tournament_lifecycle_spec.rb' + - 'spec/e2e/http/tournament_rendering_spec.rb' + - 'spec/e2e/http/tournament_sync_test_spec.rb' + - 'spec/e2e/http/tournament_team_action_lists_websocket_spec.rb' + - 'spec/e2e/http/tournament_timer_follow_sync_websocket_spec.rb' + - 'spec/factories/tournaments.rb' + - 'spec/services/group_stage_service_spec.rb' + - 'spec/services/team_action_list_service_spec.rb' + - 'spec/services/tournament_snapshot_importer_spec.rb' + - 'spec/services/tournament_sync_processor_spec.rb' diff --git a/.ruby-version b/.ruby-version index ef538c2..c4e41f9 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.1.2 +4.0.3 diff --git a/Dockerfile b/Dockerfile index f44458b..7d09b59 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ # syntax=docker/dockerfile:1.7 -ARG RUBY_VERSION=3.1.2 -ARG BUNDLER_VERSION=2.3.13 -ARG base_commit=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +ARG RUBY_VERSION=4.0.3 +ARG BUNDLER_VERSION=4.0.6 +ARG GIT_COMMIT_SHA=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa FROM ruby:${RUBY_VERSION}-slim AS runtime-base @@ -19,6 +19,7 @@ WORKDIR /app RUN apt-get update -qq \ && apt-get install -y --no-install-recommends \ libpq5 \ + libyaml-0-2 \ nodejs \ openssl \ && rm -rf /var/lib/apt/lists/* \ @@ -33,6 +34,7 @@ RUN apt-get update -qq \ git \ libpq-dev \ libsqlite3-dev \ + libyaml-dev \ pkg-config \ python3 \ python3-pip \ @@ -55,10 +57,10 @@ RUN bundle config set with 'development test' \ FROM runtime-base AS production -ARG base_commit=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +ARG GIT_COMMIT_SHA=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ENV RAILS_ENV=production \ - GIT_COMMIT_SHA=${base_commit} + GIT_COMMIT_SHA=${GIT_COMMIT_SHA} COPY --from=bundle-production /usr/local/bundle /usr/local/bundle COPY --from=bundle-production /app/vendor/bundle /app/vendor/bundle @@ -81,10 +83,10 @@ CMD ["sh", "-lc", "bundle exec rails db:migrate && bundle exec rails s -p 3000 - FROM runtime-base AS test -ARG base_commit=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +ARG GIT_COMMIT_SHA=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ENV RAILS_ENV=test \ - GIT_COMMIT_SHA=${base_commit} + GIT_COMMIT_SHA=${GIT_COMMIT_SHA} RUN apt-get update -qq \ && apt-get install -y --no-install-recommends \ @@ -92,7 +94,7 @@ RUN apt-get update -qq \ python3 \ python3-pip \ && rm -rf /var/lib/apt/lists/* \ - && python3 -m pip install --no-cache-dir invoke + && python3 -m pip install --break-system-packages --no-cache-dir invoke COPY --from=bundle-test /usr/local/bundle /usr/local/bundle COPY --from=bundle-test /app/vendor/bundle /app/vendor/bundle diff --git a/Gemfile b/Gemfile index 91dfd63..29fdec4 100644 --- a/Gemfile +++ b/Gemfile @@ -3,12 +3,12 @@ source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } -ruby '3.1.2' +ruby '4.0.3' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 7.0.3' +gem 'rails', '~> 8.1' # Use Puma as the app server -gem 'puma', '~> 5.0' +gem 'puma', '~> 8.0' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder # gem 'jbuilder', '~> 2.5' # Use ActiveModel has_secure_password @@ -28,7 +28,7 @@ gem 'bootsnap', require: false # Authentication gem 'devise' -gem 'devise_token_auth', git: 'https://github.com/Thor77/devise_token_auth', branch: 'fix-api-only-mode' +gem 'devise_token_auth' gem 'rack-cors' @@ -59,7 +59,7 @@ group :development, optional: true do gem 'rubocop-rails' gem 'solargraph' gem 'spring' - gem 'spring-watcher-listen', '~> 2.0.0' + gem 'spring-watcher-listen', '~> 2.1' end group :production do @@ -67,4 +67,4 @@ group :production do end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem -gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby] +gem 'tzinfo-data', platforms: %i[windows jruby] diff --git a/Gemfile.lock b/Gemfile.lock index 15088d9..b38a9d2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,326 +1,407 @@ -GIT - remote: https://github.com/Thor77/devise_token_auth - revision: 30ba21add5c87b2964b909c6fc5cd18cfeae2191 - branch: fix-api-only-mode - specs: - devise_token_auth (1.2.0) - bcrypt (~> 3.0) - devise (> 3.5.2, < 5) - rails (>= 4.2.0, < 7.1) - GEM remote: https://rubygems.org/ specs: - actioncable (7.0.8.1) - actionpack (= 7.0.8.1) - activesupport (= 7.0.8.1) + action_text-trix (2.1.18) + railties + actioncable (8.1.3) + actionpack (= 8.1.3) + activesupport (= 8.1.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (7.0.8.1) - actionpack (= 7.0.8.1) - activejob (= 7.0.8.1) - activerecord (= 7.0.8.1) - activestorage (= 7.0.8.1) - activesupport (= 7.0.8.1) - mail (>= 2.7.1) - net-imap - net-pop - net-smtp - actionmailer (7.0.8.1) - actionpack (= 7.0.8.1) - actionview (= 7.0.8.1) - activejob (= 7.0.8.1) - activesupport (= 7.0.8.1) - mail (~> 2.5, >= 2.5.4) - net-imap - net-pop - net-smtp - rails-dom-testing (~> 2.0) - actionpack (7.0.8.1) - actionview (= 7.0.8.1) - activesupport (= 7.0.8.1) - rack (~> 2.0, >= 2.2.4) + zeitwerk (~> 2.6) + actionmailbox (8.1.3) + actionpack (= 8.1.3) + activejob (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) + mail (>= 2.8.0) + actionmailer (8.1.3) + actionpack (= 8.1.3) + actionview (= 8.1.3) + activejob (= 8.1.3) + activesupport (= 8.1.3) + mail (>= 2.8.0) + rails-dom-testing (~> 2.2) + actionpack (8.1.3) + actionview (= 8.1.3) + activesupport (= 8.1.3) + 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 (7.0.8.1) - actionpack (= 7.0.8.1) - activerecord (= 7.0.8.1) - activestorage (= 7.0.8.1) - activesupport (= 7.0.8.1) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + useragent (~> 0.16) + actiontext (8.1.3) + action_text-trix (~> 2.1.15) + actionpack (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.0.8.1) - activesupport (= 7.0.8.1) + actionview (8.1.3) + activesupport (= 8.1.3) builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.1, >= 1.2.0) - active_model_serializers (0.10.14) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + active_model_serializers (0.10.16) actionpack (>= 4.1) activemodel (>= 4.1) case_transform (>= 0.2) jsonapi-renderer (>= 0.1.1.beta1, < 0.3) - activejob (7.0.8.1) - activesupport (= 7.0.8.1) + activejob (8.1.3) + activesupport (= 8.1.3) globalid (>= 0.3.6) - activemodel (7.0.8.1) - activesupport (= 7.0.8.1) - activerecord (7.0.8.1) - activemodel (= 7.0.8.1) - activesupport (= 7.0.8.1) - activestorage (7.0.8.1) - actionpack (= 7.0.8.1) - activejob (= 7.0.8.1) - activerecord (= 7.0.8.1) - activesupport (= 7.0.8.1) + activemodel (8.1.3) + activesupport (= 8.1.3) + activerecord (8.1.3) + activemodel (= 8.1.3) + activesupport (= 8.1.3) + timeout (>= 0.4.0) + activestorage (8.1.3) + actionpack (= 8.1.3) + activejob (= 8.1.3) + activerecord (= 8.1.3) + activesupport (= 8.1.3) marcel (~> 1.0) - mini_mime (>= 1.1.0) - activesupport (7.0.8.1) - concurrent-ruby (~> 1.0, >= 1.0.2) + activesupport (8.1.3) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb i18n (>= 1.6, < 2) + json + logger (>= 1.4.2) minitest (>= 5.1) - tzinfo (~> 2.0) - ast (2.4.2) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + ast (2.4.3) backport (1.2.0) - bcrypt (3.1.20) - benchmark (0.3.0) - bootsnap (1.18.3) + base64 (0.3.0) + bcrypt (3.1.22) + benchmark (0.5.0) + bigdecimal (4.1.2) + bootsnap (1.24.0) msgpack (~> 1.2) - builder (3.2.4) + builder (3.3.0) case_transform (0.2) activesupport - concurrent-ruby (1.2.3) + concurrent-ruby (1.3.6) + connection_pool (3.0.2) crass (1.0.6) - date (3.3.4) - devise (4.9.3) + date (3.5.1) + devise (4.9.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) - diff-lcs (1.5.1) - domain_name (0.6.20240107) - e2mmap (0.1.0) - erubi (1.12.0) - factory_bot (6.4.6) - activesupport (>= 5.0.0) - factory_bot_rails (6.4.3) - factory_bot (~> 6.4) - railties (>= 5.0.0) - faker (3.3.1) + devise_token_auth (1.2.6) + bcrypt (~> 3.0) + devise (> 3.5.2, < 5) + rails (>= 4.2.0, < 8.2) + diff-lcs (1.6.2) + drb (2.2.3) + erb (6.0.4) + erubi (1.13.1) + factory_bot (6.5.6) + activesupport (>= 6.1.0) + factory_bot_rails (6.5.1) + factory_bot (~> 6.5) + railties (>= 6.1.0) + faker (3.8.0) i18n (>= 1.8.11, < 2) - ffi (1.16.3) - globalid (1.2.1) + faraday (2.14.1) + faraday-net_http (>= 2.0, < 3.5) + json + logger + faraday-multipart (1.2.0) + multipart-post (~> 2.0) + faraday-net_http (3.4.2) + net-http (~> 0.5) + ffi (1.17.4-aarch64-linux-gnu) + ffi (1.17.4-aarch64-linux-musl) + ffi (1.17.4-arm64-darwin) + ffi (1.17.4-x86_64-linux-gnu) + globalid (1.3.0) activesupport (>= 6.1) - http-accept (1.7.0) - http-cookie (1.0.5) - domain_name (~> 0.5) - i18n (1.14.4) + i18n (1.14.8) concurrent-ruby (~> 1.0) - interactor (3.1.2) - interactor-rails (2.2.1) + interactor (3.2.0) + ostruct + interactor-rails (2.3.0) interactor (~> 3.0) - rails (>= 4.2) - jaro_winkler (1.5.6) - json (2.7.2) + railties (>= 7.0) + io-console (0.8.2) + irb (1.18.0) + pp (>= 0.6.0) + prism (>= 1.3.0) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + jaro_winkler (1.7.0) + json (2.19.4) jsonapi-renderer (0.2.2) - kramdown (2.4.0) - rexml + kramdown (2.5.2) + rexml (>= 3.4.4) kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) - language_server-protocol (3.17.0.3) - listen (3.9.0) + language_server-protocol (3.17.0.5) + lint_roller (1.1.0) + listen (3.10.0) + logger rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - loofah (2.22.0) + logger (1.7.0) + loofah (2.25.1) crass (~> 1.0.2) nokogiri (>= 1.12.0) - mail (2.8.1) + mail (2.9.0) + logger mini_mime (>= 0.1.1) net-imap net-pop net-smtp - mailgun-ruby (1.2.14) - rest-client (>= 2.0.2) - marcel (1.0.4) - method_source (1.0.0) - mime-types (3.5.2) - mime-types-data (~> 3.2015) - mime-types-data (3.2024.0305) + mailgun-ruby (1.4.3) + faraday (~> 2.1) + faraday-multipart (< 2) + mini_mime + zeitwerk + marcel (1.1.0) mini_mime (1.1.5) - minitest (5.22.3) - msgpack (1.7.2) - net-imap (0.4.10) + minitest (6.0.5) + drb (~> 2.0) + prism (~> 1.5) + msgpack (1.8.0) + multipart-post (2.4.1) + net-http (0.9.1) + uri (>= 0.11.1) + net-imap (0.6.4) date net-protocol net-pop (0.1.2) net-protocol net-protocol (0.2.2) timeout - net-smtp (0.5.0) + net-smtp (0.5.1) net-protocol - netrc (0.11.0) - nio4r (2.7.1) - nokogiri (1.16.3-aarch64-linux) + nio4r (2.7.5) + nokogiri (1.19.3-aarch64-linux-gnu) racc (~> 1.4) - nokogiri (1.16.3-arm64-darwin) + nokogiri (1.19.3-aarch64-linux-musl) racc (~> 1.4) - nokogiri (1.16.3-x86_64-linux) + nokogiri (1.19.3-arm64-darwin) racc (~> 1.4) + nokogiri (1.19.3-x86_64-linux-gnu) + racc (~> 1.4) + observer (0.1.2) + open3 (0.2.1) orm_adapter (0.5.0) - parallel (1.24.0) - parser (3.3.0.5) + ostruct (0.6.3) + parallel (2.1.0) + parser (3.3.11.1) ast (~> 2.4.1) racc - pg (1.5.6) - puma (5.6.8) + pg (1.6.3-aarch64-linux) + pg (1.6.3-aarch64-linux-musl) + pg (1.6.3-arm64-darwin) + pg (1.6.3-x86_64-linux) + pp (0.6.3) + prettyprint + prettyprint (0.2.0) + prism (1.9.0) + psych (5.3.1) + date + stringio + puma (8.0.1) nio4r (~> 2.0) - racc (1.7.3) - rack (2.2.9) - rack-cors (2.0.2) - rack (>= 2.0.0) - rack-test (2.1.0) + racc (1.8.1) + rack (3.2.6) + rack-cors (3.0.0) + logger + rack (>= 3.0.14) + rack-session (2.1.2) + base64 (>= 0.1.0) + rack (>= 3.0.0) + rack-test (2.2.0) rack (>= 1.3) + rackup (2.3.1) + rack (>= 3) railroady (1.6.0) - rails (7.0.8.1) - actioncable (= 7.0.8.1) - actionmailbox (= 7.0.8.1) - actionmailer (= 7.0.8.1) - actionpack (= 7.0.8.1) - actiontext (= 7.0.8.1) - actionview (= 7.0.8.1) - activejob (= 7.0.8.1) - activemodel (= 7.0.8.1) - activerecord (= 7.0.8.1) - activestorage (= 7.0.8.1) - activesupport (= 7.0.8.1) + rails (8.1.3) + actioncable (= 8.1.3) + actionmailbox (= 8.1.3) + actionmailer (= 8.1.3) + actionpack (= 8.1.3) + actiontext (= 8.1.3) + actionview (= 8.1.3) + activejob (= 8.1.3) + activemodel (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) bundler (>= 1.15.0) - railties (= 7.0.8.1) - rails-dom-testing (2.2.0) + railties (= 8.1.3) + rails-dom-testing (2.3.0) activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.0) - loofah (~> 2.21) - nokogiri (~> 1.14) - railties (7.0.8.1) - actionpack (= 7.0.8.1) - activesupport (= 7.0.8.1) - method_source + rails-html-sanitizer (1.7.0) + loofah (~> 2.25) + nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) + railties (8.1.3) + actionpack (= 8.1.3) + activesupport (= 8.1.3) + irb (~> 1.13) + rackup (>= 1.0.0) rake (>= 12.2) - thor (~> 1.0) - zeitwerk (~> 2.5) + thor (~> 1.0, >= 1.2.2) + tsort (>= 0.2) + zeitwerk (~> 2.6) rainbow (3.1.1) - rake (13.2.1) + rake (13.4.2) rb-fsevent (0.11.2) - rb-inotify (0.10.1) + rb-inotify (0.11.1) ffi (~> 1.0) - rbs (2.8.4) - regexp_parser (2.9.0) - responders (3.1.1) - actionpack (>= 5.2) - railties (>= 5.2) - rest-client (2.1.0) - http-accept (>= 1.7.0, < 2.0) - http-cookie (>= 1.0.2, < 2.0) - mime-types (>= 1.16, < 4.0) - netrc (~> 0.8) - reverse_markdown (2.1.1) + rbs (3.10.4) + logger + tsort + rdoc (7.2.0) + erb + psych (>= 4.0.0) + tsort + regexp_parser (2.12.0) + reline (0.6.3) + io-console (~> 0.5) + responders (3.2.0) + actionpack (>= 7.0) + railties (>= 7.0) + reverse_markdown (3.0.2) nokogiri - rexml (3.2.6) - rspec-core (3.13.0) + rexml (3.4.4) + rspec-core (3.13.6) rspec-support (~> 3.13.0) - rspec-expectations (3.13.0) + rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-mocks (3.13.0) + rspec-mocks (3.13.8) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-rails (6.1.2) - 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.1) - rubocop (1.62.1) + rspec-rails (8.0.4) + actionpack (>= 7.2) + activesupport (>= 7.2) + railties (>= 7.2) + rspec-core (>= 3.13.0, < 5.0.0) + rspec-expectations (>= 3.13.0, < 5.0.0) + rspec-mocks (>= 3.13.0, < 5.0.0) + rspec-support (>= 3.13.0, < 5.0.0) + rspec-support (3.13.7) + rubocop (1.86.1) json (~> 2.3) - language_server-protocol (>= 3.17.0) - parallel (~> 1.10) + 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.49.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.31.2) - parser (>= 3.3.0.4) - rubocop-performance (1.21.0) - rubocop (>= 1.48.1, < 2.0) - rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rails (2.24.1) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.49.1) + parser (>= 3.3.7.2) + prism (~> 1.7) + rubocop-performance (1.26.1) + lint_roller (~> 1.1) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.47.1, < 2.0) + rubocop-rails (2.34.3) activesupport (>= 4.2.0) + lint_roller (~> 1.1) rack (>= 1.1) - rubocop (>= 1.33.0, < 2.0) - rubocop-ast (>= 1.31.1, < 2.0) - ruby-prof (1.7.1) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.44.0, < 2.0) + ruby-prof (2.0.4) + base64 + ostruct ruby-progressbar (1.13.0) - shoulda-matchers (6.2.0) - activesupport (>= 5.2.0) - solargraph (0.50.0) + securerandom (0.4.1) + shoulda-matchers (7.0.1) + activesupport (>= 7.1) + solargraph (0.58.3) + ast (~> 2.4.3) backport (~> 1.2) - benchmark - bundler (~> 2.0) + benchmark (~> 0.4) + bundler (>= 2.0) diff-lcs (~> 1.4) - e2mmap - jaro_winkler (~> 1.5) + jaro_winkler (~> 1.6, >= 1.6.1) kramdown (~> 2.3) kramdown-parser-gfm (~> 1.1) + logger (~> 1.6) + observer (~> 0.1) + open3 (~> 0.2.1) + ostruct (~> 0.6) parser (~> 3.0) - rbs (~> 2.0) - reverse_markdown (~> 2.0) - rubocop (~> 1.38) + prism (~> 1.4) + rbs (>= 3.6.1, <= 4.0.0.dev.4) + reverse_markdown (~> 3.0) + rubocop (~> 1.76) thor (~> 1.0) tilt (~> 2.0) yard (~> 0.9, >= 0.9.24) - spring (2.1.1) - spring-watcher-listen (2.0.1) + yard-activesupport-concern (~> 0.0) + yard-solargraph (~> 0.1) + spring (4.4.2) + spring-watcher-listen (2.1.0) listen (>= 2.7, < 4.0) - spring (>= 1.2, < 3.0) - sqlite3 (1.7.3-aarch64-linux) - sqlite3 (1.7.3-arm64-darwin) - sqlite3 (1.7.3-x86_64-linux) - thor (1.3.1) - tilt (2.3.0) - timeout (0.4.1) + spring (>= 4) + sqlite3 (2.9.3-aarch64-linux-gnu) + sqlite3 (2.9.3-aarch64-linux-musl) + sqlite3 (2.9.3-arm64-darwin) + sqlite3 (2.9.3-x86_64-linux-gnu) + stringio (3.2.0) + thor (1.5.0) + tilt (2.7.0) + timeout (0.6.1) + tsort (0.2.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (2.5.0) + unicode-display_width (3.2.0) + unicode-emoji (~> 4.1) + unicode-emoji (4.2.0) + uri (1.1.1) + useragent (0.16.11) warden (1.2.9) rack (>= 2.0.9) - websocket-driver (0.7.6) + websocket-driver (0.8.0) + base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - yard (0.9.36) - zeitwerk (2.6.13) + yard (0.9.43) + yard-activesupport-concern (0.0.1) + yard (>= 0.8) + yard-solargraph (0.1.0) + yard (~> 0.9) + zeitwerk (2.7.5) PLATFORMS + aarch64-linux aarch64-linux-musl arm64-darwin-22 arm64-darwin-23 arm64-darwin-24 arm64-darwin-25 x86_64-linux + x86_64-linux-gnu DEPENDENCIES active_model_serializers bootsnap devise - devise_token_auth! + devise_token_auth factory_bot_rails faker interactor @@ -328,10 +409,10 @@ DEPENDENCIES listen (~> 3.3) mailgun-ruby pg - puma (~> 5.0) + puma (~> 8.0) rack-cors railroady - rails (~> 7.0.3) + rails (~> 8.1) rspec-rails rubocop rubocop-performance @@ -340,12 +421,12 @@ DEPENDENCIES shoulda-matchers solargraph spring - spring-watcher-listen (~> 2.0.0) + spring-watcher-listen (~> 2.1) sqlite3 tzinfo-data RUBY VERSION - ruby 3.1.2p20 + ruby 4.0.3 BUNDLED WITH - 2.3.7 + 4.0.6 diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 158102a..6c56364 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -10,6 +10,10 @@ class ApplicationController < ActionController::API end rescue_from ActiveRecord::RecordNotFound, with: :render_not_found_error + def bypass_sign_in(_resource, scope: nil) + true + end + protected def configure_permitted_parameters @@ -42,6 +46,11 @@ class ApplicationController < ActionController::API end def render_not_found_error(exception) - render json: { error: exception.to_s }, status: :not_found + error = if exception.is_a?(ActiveRecord::RecordNotFound) && exception.model.present? + "Couldn't find #{exception.model} with '#{exception.primary_key}'=#{exception.id.inspect}" + else + 'Record not found' + end + render json: { error: error }, status: :not_found end end diff --git a/app/models/match.rb b/app/models/match.rb index af4adee..de64aec 100644 --- a/app/models/match.rb +++ b/app/models/match.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true class Match < ApplicationRecord - enum state: { single_team: 0, not_ready: 1, not_started: 2, in_progress: 3, finished: 4, - undecided: 5 } + enum :state, { single_team: 0, not_ready: 1, not_started: 2, in_progress: 3, finished: 4, + undecided: 5 } belongs_to :stage, optional: true belongs_to :group, optional: true diff --git a/app/models/stage.rb b/app/models/stage.rb index 3466c8e..fd78498 100644 --- a/app/models/stage.rb +++ b/app/models/stage.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Stage < ApplicationRecord - enum state: { playoff_stage: 0, intermediate_stage: 1, in_progress: 2, finished: 3 } + enum :state, { playoff_stage: 0, intermediate_stage: 1, in_progress: 2, finished: 3 } belongs_to :tournament has_many :matches, dependent: :destroy diff --git a/app/models/tournament.rb b/app/models/tournament.rb index 3debf27..2128b6e 100644 --- a/app/models/tournament.rb +++ b/app/models/tournament.rb @@ -4,6 +4,7 @@ require 'securerandom' class Tournament < ApplicationRecord belongs_to :user + belongs_to :owner, class_name: 'User', foreign_key: :user_id has_many :teams, dependent: :destroy has_many :stages, dependent: :destroy has_many :beamers, dependent: :destroy @@ -17,8 +18,6 @@ class Tournament < ApplicationRecord validate :playoff_teams_amount_is_positive_power_of_two - alias_attribute :owner, :user - after_initialize :generate_code after_create_commit :ensure_default_beamer! before_validation :clear_follower_sync_token_when_disabling_read_only_mode diff --git a/config/application.rb b/config/application.rb index bd16c7a..e6e619b 100644 --- a/config/application.rb +++ b/config/application.rb @@ -50,7 +50,5 @@ module TurniereBackend from: 'noreply@turnie.re' } - # Active Record - config.active_record.legacy_connection_handling = false end end diff --git a/config/environments/production.rb b/config/environments/production.rb index 3c74f73..360a4b1 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -79,12 +79,16 @@ Rails.application.configure do # Mail config.action_mailer.raise_delivery_errors = true config.action_mailer.default_url_options = { host: 'api.turnie.re' } - config.action_mailer.delivery_method = :mailgun - config.action_mailer.mailgun_settings = { - api_key: ENV.fetch('MAILGUN_API_KEY'), - domain: ENV.fetch('MAILGUN_DOMAIN'), - api_host: 'api.eu.mailgun.net' # Uncomment this line for EU region domains - } + if ENV['TURNIERE_DISABLE_EMAIL_DELIVERY'].present? + config.action_mailer.perform_deliveries = false + else + config.action_mailer.delivery_method = :mailgun + config.action_mailer.mailgun_settings = { + api_key: ENV.fetch('MAILGUN_API_KEY'), + domain: ENV.fetch('MAILGUN_DOMAIN'), + api_host: 'api.eu.mailgun.net' # Uncomment this line for EU region domains + } + end # Logging to STDOUT (running in docker by default) config.logger = Logger.new(STDOUT) diff --git a/db/schema.rb b/db/schema.rb index 002741a..011a77f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,96 +10,96 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2026_04_26_121000) do +ActiveRecord::Schema[8.1].define(version: 2026_04_26_121000) do create_table "beamers", force: :cascade do |t| - t.string "name", null: false + t.json "config", default: {}, null: false + t.datetime "created_at", null: false t.string "display_state", default: "during_game", null: false t.boolean "is_default", default: false - t.integer "tournament_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "name", null: false t.integer "sync_source_id" - t.json "config", default: {}, null: false + t.integer "tournament_id", null: false + t.datetime "updated_at", null: false t.index ["tournament_id", "name"], name: "index_beamers_on_tournament_id_and_name", unique: true t.index ["tournament_id"], name: "index_beamers_on_tournament_id" end create_table "bets", force: :cascade do |t| - t.integer "user_id", null: false + t.datetime "created_at", precision: nil, null: false t.integer "match_id", null: false t.integer "team_id" - t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false + t.integer "user_id", null: false t.index ["match_id"], name: "index_bets_on_match_id" t.index ["team_id"], name: "index_bets_on_team_id" t.index ["user_id"], name: "index_bets_on_user_id" end create_table "group_scores", force: :cascade do |t| - t.integer "group_points", default: 0 - t.integer "scored_points", default: 0 - t.integer "received_points", default: 0 - t.integer "team_id", null: false - t.integer "group_id", null: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false + t.integer "group_id", null: false + t.integer "group_points", default: 0 t.integer "position", default: 0 + t.integer "received_points", default: 0 + t.integer "scored_points", default: 0 t.integer "sync_source_id" + t.integer "team_id", null: false + t.datetime "updated_at", precision: nil, null: false t.index ["group_id"], name: "index_group_scores_on_group_id" t.index ["team_id"], name: "index_group_scores_on_team_id" end create_table "groups", force: :cascade do |t| + t.datetime "created_at", precision: nil, null: false t.integer "number" t.integer "stage_id", null: false - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false t.integer "sync_source_id" + t.datetime "updated_at", precision: nil, null: false t.index ["stage_id"], name: "index_groups_on_stage_id" end create_table "match_scores", force: :cascade do |t| - t.integer "points", default: 0 - t.integer "match_id", null: false - t.integer "team_id", null: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false t.integer "hidden_points", default: 0, null: false + t.integer "match_id", null: false + t.integer "points", default: 0 t.integer "sync_source_id" + t.integer "team_id", null: false + t.datetime "updated_at", precision: nil, null: false t.index ["match_id"], name: "index_match_scores_on_match_id" t.index ["team_id"], name: "index_match_scores_on_team_id" end create_table "matches", force: :cascade do |t| - t.integer "state", default: 0 + t.datetime "created_at", precision: nil, null: false + t.boolean "decider", default: false, null: false + t.integer "group_id" t.integer "position" t.integer "stage_id" - t.integer "group_id" - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.boolean "decider", default: false, null: false + t.integer "state", default: 0 t.integer "sync_source_id" + t.datetime "updated_at", precision: nil, null: false t.index ["group_id"], name: "index_matches_on_group_id" t.index ["stage_id"], name: "index_matches_on_stage_id" end create_table "stages", force: :cascade do |t| + t.datetime "created_at", precision: nil, null: false t.integer "level" t.integer "state", default: 0 - t.integer "tournament_id", null: false - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false t.integer "sync_source_id" + t.integer "tournament_id", null: false + t.datetime "updated_at", precision: nil, null: false t.index ["tournament_id"], name: "index_stages_on_tournament_id" end create_table "team_action_items", force: :cascade do |t| - t.integer "team_action_list_id", null: false - t.integer "team_id", null: false t.boolean "completed", default: false, null: false t.datetime "completed_at" - t.integer "sync_source_id" t.datetime "created_at", null: false + t.integer "sync_source_id" + t.integer "team_action_list_id", null: false + t.integer "team_id", null: false t.datetime "updated_at", null: false t.index ["sync_source_id"], name: "index_team_action_items_on_sync_source_id" t.index ["team_action_list_id", "team_id"], name: "index_team_action_items_on_team_action_list_id_and_team_id", unique: true @@ -108,13 +108,13 @@ ActiveRecord::Schema[7.0].define(version: 2026_04_26_121000) do end create_table "team_action_lists", force: :cascade do |t| - t.integer "tournament_id", null: false - t.string "name", null: false - t.string "key", null: false t.string "action_name", null: false + t.datetime "created_at", null: false + t.string "key", null: false + t.string "name", null: false t.string "source", null: false t.integer "sync_source_id" - t.datetime "created_at", null: false + t.integer "tournament_id", null: false t.datetime "updated_at", null: false t.index ["sync_source_id"], name: "index_team_action_lists_on_sync_source_id" t.index ["tournament_id", "key"], name: "index_team_action_lists_on_tournament_id_and_key", unique: true @@ -122,25 +122,25 @@ ActiveRecord::Schema[7.0].define(version: 2026_04_26_121000) do end create_table "teams", force: :cascade do |t| - t.string "name" - t.integer "tournament_id" t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false + t.string "name" t.integer "sync_source_id" + t.integer "tournament_id" + t.datetime "updated_at", precision: nil, null: false t.index ["tournament_id"], name: "index_teams_on_tournament_id" end create_table "tournament_sync_queue_entries", force: :cascade do |t| - t.integer "tournament_id", null: false - t.text "snapshot_json", null: false - t.datetime "next_attempt_at", null: false - t.datetime "last_attempt_at" - t.datetime "locked_at" - t.string "lock_token" t.integer "attempts", default: 0, null: false - t.string "status", default: "pending", null: false - t.string "last_error" t.datetime "created_at", null: false + t.datetime "last_attempt_at" + t.string "last_error" + t.string "lock_token" + t.datetime "locked_at" + t.datetime "next_attempt_at", null: false + t.text "snapshot_json", null: false + t.string "status", default: "pending", null: false + t.integer "tournament_id", null: false t.datetime "updated_at", null: false t.index ["next_attempt_at"], name: "index_tournament_sync_queue_entries_on_next_attempt_at" t.index ["status"], name: "index_tournament_sync_queue_entries_on_status" @@ -148,51 +148,51 @@ ActiveRecord::Schema[7.0].define(version: 2026_04_26_121000) do end create_table "tournaments", force: :cascade do |t| - t.string "name", null: false t.string "code", null: false + t.datetime "created_at", precision: nil, null: false t.string "description" - t.boolean "public", default: true - t.integer "playoff_teams_amount", default: 0 t.integer "instant_finalists_amount", default: 0 t.integer "intermediate_round_participants_amount", default: 0 - t.integer "user_id", null: false - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.datetime "timestamp" + t.string "name", null: false + t.integer "playoff_teams_amount", default: 0 + t.boolean "public", default: true t.boolean "read_only_mode", default: false, null: false - t.string "sync_target_url" t.string "sync_auth_token" - t.integer "sync_source_tournament_id" - t.datetime "sync_last_pushed_at" - t.string "sync_last_push_error" t.datetime "sync_last_imported_snapshot_at" + t.string "sync_last_push_error" + t.datetime "sync_last_pushed_at" + t.integer "sync_source_tournament_id" + t.string "sync_target_url" t.string "timer_mode" + t.datetime "timestamp" + t.datetime "updated_at", precision: nil, null: false + t.integer "user_id", null: false t.index ["code"], name: "index_tournaments_on_code", unique: true t.index ["user_id"], name: "index_tournaments_on_user_id" end create_table "users", force: :cascade do |t| - t.string "provider", default: "email", null: false - t.string "uid", default: "", null: false - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" - t.datetime "reset_password_sent_at", precision: nil t.boolean "allow_password_change", default: false - t.datetime "remember_created_at", precision: nil - t.integer "sign_in_count", default: 0, null: false - t.datetime "current_sign_in_at", precision: nil - t.datetime "last_sign_in_at", precision: nil - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" + t.datetime "confirmation_sent_at", precision: nil t.string "confirmation_token" t.datetime "confirmed_at", precision: nil - t.datetime "confirmation_sent_at", precision: nil - t.string "unconfirmed_email" - t.string "username" - t.string "email" - t.text "tokens" t.datetime "created_at", precision: nil, null: false + t.datetime "current_sign_in_at", precision: nil + t.string "current_sign_in_ip" + t.string "email" + t.string "encrypted_password", default: "", null: false + t.datetime "last_sign_in_at", precision: nil + t.string "last_sign_in_ip" + t.string "provider", default: "email", null: false + t.datetime "remember_created_at", precision: nil + t.datetime "reset_password_sent_at", precision: nil + t.string "reset_password_token" + t.integer "sign_in_count", default: 0, null: false + t.text "tokens" + t.string "uid", default: "", null: false + t.string "unconfirmed_email" t.datetime "updated_at", precision: nil, null: false + t.string "username" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["email"], name: "index_users_on_email", unique: true t.index ["provider"], name: "index_users_on_provider" diff --git a/docker-compose.blackbox-follow.yml b/docker-compose.blackbox-follow.yml index cfb49d9..a192dc1 100644 --- a/docker-compose.blackbox-follow.yml +++ b/docker-compose.blackbox-follow.yml @@ -43,6 +43,7 @@ services: SECRET_KEY_BASE: ${TURNIERE_BLACKBOX_SECRET_KEY_BASE:-turniere-blackbox-secret-key-base-please-change-in-real-prod} MAILGUN_API_KEY: ${TURNIERE_BLACKBOX_MAILGUN_API_KEY:-blackbox-test-api-key} MAILGUN_DOMAIN: ${TURNIERE_BLACKBOX_MAILGUN_DOMAIN:-blackbox.example.com} + TURNIERE_DISABLE_EMAIL_DELIVERY: ${TURNIERE_BLACKBOX_DISABLE_EMAIL_DELIVERY:-1} TOURNAMENT_SYNC_HTTP_TIMEOUT_SECONDS: ${TURNIERE_BLACKBOX_TOURNAMENT_SYNC_HTTP_TIMEOUT_SECONDS:-3} RAILS_LOG_TO_STDOUT: "1" RAILS_SERVE_STATIC_FILES: "1" @@ -64,6 +65,7 @@ services: SECRET_KEY_BASE: ${TURNIERE_BLACKBOX_SECRET_KEY_BASE:-turniere-blackbox-secret-key-base-please-change-in-real-prod} MAILGUN_API_KEY: ${TURNIERE_BLACKBOX_MAILGUN_API_KEY:-blackbox-test-api-key} MAILGUN_DOMAIN: ${TURNIERE_BLACKBOX_MAILGUN_DOMAIN:-blackbox.example.com} + TURNIERE_DISABLE_EMAIL_DELIVERY: ${TURNIERE_BLACKBOX_DISABLE_EMAIL_DELIVERY:-1} TOURNAMENT_SYNC_HTTP_TIMEOUT_SECONDS: ${TURNIERE_BLACKBOX_TOURNAMENT_SYNC_HTTP_TIMEOUT_SECONDS:-3} RAILS_LOG_TO_STDOUT: "1" RAILS_SERVE_STATIC_FILES: "1" diff --git a/docker-compose.blackbox.yml b/docker-compose.blackbox.yml index fae52d2..15e5d3b 100644 --- a/docker-compose.blackbox.yml +++ b/docker-compose.blackbox.yml @@ -25,6 +25,7 @@ services: SECRET_KEY_BASE: ${TURNIERE_BLACKBOX_SECRET_KEY_BASE:-turniere-blackbox-secret-key-base-please-change-in-real-prod} MAILGUN_API_KEY: ${TURNIERE_BLACKBOX_MAILGUN_API_KEY:-blackbox-test-api-key} MAILGUN_DOMAIN: ${TURNIERE_BLACKBOX_MAILGUN_DOMAIN:-blackbox.example.com} + TURNIERE_DISABLE_EMAIL_DELIVERY: ${TURNIERE_BLACKBOX_DISABLE_EMAIL_DELIVERY:-1} RAILS_LOG_TO_STDOUT: "1" RAILS_SERVE_STATIC_FILES: "1" ports: diff --git a/spec/e2e/http/api_surface_spec.rb b/spec/e2e/http/api_surface_spec.rb index 2c1b5ed..9a7803f 100644 --- a/spec/e2e/http/api_surface_spec.rb +++ b/spec/e2e/http/api_surface_spec.rb @@ -52,7 +52,7 @@ RSpec.describe 'Backend API surface HTTP E2E' do }) login = TurniereE2E::ApiClient.new(base_url: base_url).login!(email: email, password: password) - expect([500, *200..299]).to include(registration[:status]) + expect(registration[:status]).to be_between(200, 299) expect(registration[:json]).not_to eq({}) expect(login[:status]).to eq(401) end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 15c095d..b8e1dc6 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -36,7 +36,7 @@ rescue ActiveRecord::PendingMigrationError => e end RSpec.configure do |config| # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" + config.fixture_paths = ["#{::Rails.root}/spec/fixtures"] # Run only focused tests # TODO REVERT ME diff --git a/tasks.py b/tasks.py index 3bb5306..36f6bb9 100644 --- a/tasks.py +++ b/tasks.py @@ -189,6 +189,7 @@ def _compose_env( TURNIERE_BLACKBOX_SECRET_KEY_BASE=BLACKBOX_SECRET_KEY_BASE, TURNIERE_BLACKBOX_MAILGUN_API_KEY=BLACKBOX_MAILGUN_API_KEY, TURNIERE_BLACKBOX_MAILGUN_DOMAIN=BLACKBOX_MAILGUN_DOMAIN, + TURNIERE_BLACKBOX_DISABLE_EMAIL_DELIVERY="1", TURNIERE_E2E_BASE_URL=BLACKBOX_INTERNAL_BASE_URL, TURNIERE_E2E_EXPECT_PROFILING=expect_profiling, TURNIERE_E2E_EMAIL=E2E_EMAIL, @@ -220,6 +221,7 @@ def _follow_compose_env( TURNIERE_BLACKBOX_SECRET_KEY_BASE=BLACKBOX_SECRET_KEY_BASE, TURNIERE_BLACKBOX_MAILGUN_API_KEY=BLACKBOX_MAILGUN_API_KEY, TURNIERE_BLACKBOX_MAILGUN_DOMAIN=BLACKBOX_MAILGUN_DOMAIN, + TURNIERE_BLACKBOX_DISABLE_EMAIL_DELIVERY="1", TURNIERE_SOURCE_E2E_BASE_URL=BLACKBOX_SOURCE_INTERNAL_BASE_URL, TURNIERE_FOLLOWER_E2E_BASE_URL=BLACKBOX_FOLLOWER_INTERNAL_BASE_URL, TURNIERE_E2E_EMAIL=E2E_EMAIL, @@ -471,6 +473,7 @@ def _shared_production_env(): SECRET_KEY_BASE=os.environ.get("SECRET_KEY_BASE", BLACKBOX_SECRET_KEY_BASE), MAILGUN_API_KEY=os.environ.get("MAILGUN_API_KEY", BLACKBOX_MAILGUN_API_KEY), MAILGUN_DOMAIN=os.environ.get("MAILGUN_DOMAIN", BLACKBOX_MAILGUN_DOMAIN), + TURNIERE_DISABLE_EMAIL_DELIVERY=os.environ.get("TURNIERE_DISABLE_EMAIL_DELIVERY", "1"), RAILS_LOG_TO_STDOUT=os.environ.get("RAILS_LOG_TO_STDOUT", "1"), RAILS_SERVE_STATIC_FILES=os.environ.get("RAILS_SERVE_STATIC_FILES", "1"), ) @@ -485,6 +488,7 @@ def _production_env_for(db_host, db_name): SECRET_KEY_BASE=BLACKBOX_SECRET_KEY_BASE, MAILGUN_API_KEY=BLACKBOX_MAILGUN_API_KEY, MAILGUN_DOMAIN=BLACKBOX_MAILGUN_DOMAIN, + TURNIERE_DISABLE_EMAIL_DELIVERY="1", RAILS_LOG_TO_STDOUT="1", RAILS_SERVE_STATIC_FILES="1", ) @@ -525,7 +529,7 @@ def _run_blackbox_rspec(base_url, email, password, username, alt_email=E2E_ALT_E def _start_server(command, env, log_path="/tmp/turniere-e2e-server.log"): log_handle = open(log_path, "w") process = subprocess.Popen( - ["/bin/sh", "-lc", command], + ["/bin/sh", "-c", command], env=env, stdout=log_handle, stderr=subprocess.STDOUT, @@ -537,7 +541,7 @@ def _start_server(command, env, log_path="/tmp/turniere-e2e-server.log"): def _start_test_server(host=SERVER_HOST, port=SERVER_PORT): return _start_server( f"{_bundle_exec('rails', 's')} -e test -b {host} -p {port}", - _env(), + _env(GIT_COMMIT_SHA=_git_commit_sha()), ) @@ -603,7 +607,11 @@ def db_reset(c, env="test"): @task def server(c, host=SERVER_HOST, port=SERVER_PORT, env=None): """Start the backend locally in development.""" - c.run(f"RAILS_ENV={_rails_env(env)} {_bundle_exec('rails', 's')} -b {host} -p {port}", pty=True) + c.run( + f"RAILS_ENV={_rails_env(env)} {_bundle_exec('rails', 's')} -b {host} -p {port}", + env=_env(GIT_COMMIT_SHA=_git_commit_sha()), + pty=True, + ) @task(name="start-local")