From 0446e516697bc0d3cc85abab82d1345888500c3a Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Mon, 2 Mar 2026 16:01:31 +0000 Subject: [PATCH 01/11] rm old jobs and update existing to perform_now --- scripts/change_to_wilson_scores.rb | 33 ------------------- scripts/cleanup_votes.rb | 2 +- scripts/create_backup_2fa_codes.rb | 4 --- .../create_general_thread_for_old_comments.rb | 15 --------- scripts/recalc_abilities.rb | 2 +- .../recalc_abilities_upon_first_migration.rb | 26 --------------- scripts/run_complaints_closure.rb | 2 +- scripts/run_new_thread_followers_cleanup.rb | 2 +- scripts/run_spam_cleanup.rb | 4 +-- scripts/run_summary_mailer.rb | 2 +- scripts/run_thread_followers_cleanup.rb | 2 +- 11 files changed, 8 insertions(+), 86 deletions(-) delete mode 100644 scripts/change_to_wilson_scores.rb delete mode 100644 scripts/create_backup_2fa_codes.rb delete mode 100644 scripts/create_general_thread_for_old_comments.rb delete mode 100644 scripts/recalc_abilities_upon_first_migration.rb diff --git a/scripts/change_to_wilson_scores.rb b/scripts/change_to_wilson_scores.rb deleted file mode 100644 index ae0389346..000000000 --- a/scripts/change_to_wilson_scores.rb +++ /dev/null @@ -1,33 +0,0 @@ -# First we grab votes so we can populate upvote_count and downvote_count -puts "01: Vote grab" -votes = Vote.unscoped.all.group(:post_id, :vote_type).count - -# Format translation -# {[123, 1] => 34, [123, -1] => 43, [124, 1] => 45, [124, -1] => 56} into -# {123 => {1 => 34, -1 => 43}, 124 => {1 => 45, -1 => 56}} -puts "02: Vote translation" -all_ids = Post.unscoped.all.pluck(:id).map { |i| [i, {}] }.to_h -votes = all_ids.merge(votes.to_a.group_by { |v| v[0][0] }.map { |i, v| [i, v.map { |g| [g[0][1], g[1]] }.to_h] }.to_h) - -# Generate and execute sanitized update SQL for each post. -progress = ProgressBar.create(title: "03: UPDATEs", total: votes.size, progress_mark: '█') -votes.each do |post_id, vote_counts| - params = [] - vote_counts = { 1 => 0, -1 => 0 }.merge(vote_counts) - updates = vote_counts.map do |vt, count| - attrib = { 1 => 'upvote_count', -1 => 'downvote_count' }[vt] - params << count - "#{attrib} = ?" - end - params << post_id - sql = "UPDATE posts SET #{updates.join(', ')} WHERE id = ?" - sanitized = ActiveRecord::Base.sanitize_sql_array([sql, *params]) - ActiveRecord::Base.connection.execute sanitized - progress.increment -end - -puts "04: update scores" -score_update = "UPDATE posts p INNER JOIN (SELECT * FROM " \ - "(SELECT id, (upvote_count + 2)/(upvote_count + downvote_count + 4) AS score FROM posts) i) q " \ - "ON p.id = q.id SET p.score = q.score" -ActiveRecord::Base.connection.execute score_update \ No newline at end of file diff --git a/scripts/cleanup_votes.rb b/scripts/cleanup_votes.rb index 67707824e..4637722a0 100644 --- a/scripts/cleanup_votes.rb +++ b/scripts/cleanup_votes.rb @@ -1 +1 @@ -CleanupVotesJob.perform_later \ No newline at end of file +CleanupVotesJob.perform_now \ No newline at end of file diff --git a/scripts/create_backup_2fa_codes.rb b/scripts/create_backup_2fa_codes.rb deleted file mode 100644 index ddeac6793..000000000 --- a/scripts/create_backup_2fa_codes.rb +++ /dev/null @@ -1,4 +0,0 @@ -User.where(enabled_2fa: true).each do |user| - user.update(backup_2fa_code: SecureRandom.alphanumeric(24)) - TwoFactorMailer.with(user: user, host: 'meta.codidact.com').backup_code.deliver_now -end diff --git a/scripts/create_general_thread_for_old_comments.rb b/scripts/create_general_thread_for_old_comments.rb deleted file mode 100644 index 0a05726f0..000000000 --- a/scripts/create_general_thread_for_old_comments.rb +++ /dev/null @@ -1,15 +0,0 @@ -Post.unscoped.where(id: Comment.unscoped.where(comment_thread: nil) - .select(Arel.sql('distinct post_id'))).each do |post| - comments = Comment.unscoped.where(post: post, comment_thread: nil) - next unless comments.any? - - comments = comments.all - - new_thread = CommentThread.new(title: 'General comments', post: post, reply_count: comments.size, locked: false, - archived: false, deleted: false, community: post.community) - new_thread.save - - comments.update_all(comment_thread_id: new_thread.id) - - puts "#{comments.size} comments updated for post Id=#{post.id}" -end \ No newline at end of file diff --git a/scripts/recalc_abilities.rb b/scripts/recalc_abilities.rb index cb2566483..aff36903e 100644 --- a/scripts/recalc_abilities.rb +++ b/scripts/recalc_abilities.rb @@ -36,7 +36,7 @@ puts "Scope: CommunityUser : #{cu.id}" end - cu.recalc_abilities + cu.recalc_abilities! # Grant mod ability if mod status is given if cu.at_least_moderator? && !cu.ability?('mod') diff --git a/scripts/recalc_abilities_upon_first_migration.rb b/scripts/recalc_abilities_upon_first_migration.rb deleted file mode 100644 index b7394be55..000000000 --- a/scripts/recalc_abilities_upon_first_migration.rb +++ /dev/null @@ -1,26 +0,0 @@ -puts "Recalculating all the Abilities" -puts - -User.unscoped.all.map do |u| - puts "Scope: User.Id=#{u.id}" - - u.community_users.each do |cu| - puts " Attempt CommunityUser.Id=#{cu.id}" - RequestContext.community = cu.community - cu.recalc_privileges! - - if cu.at_least_moderator? && !cu.privilege?('mod') - puts " Granting mod privilege to CommunityUser.Id=#{cu.id}" - cu.grant_privilege!('mod') - end - - puts " Recalc success for CommunityUser.Id=#{cu.id}" - rescue - puts " !!! Error recalcing for CommunityUser.Id=#{cu.id}" - end - puts "End" - puts -end - -puts "---" -puts "Recalculating completed" diff --git a/scripts/run_complaints_closure.rb b/scripts/run_complaints_closure.rb index b3fc37fc0..3a590319b 100644 --- a/scripts/run_complaints_closure.rb +++ b/scripts/run_complaints_closure.rb @@ -1 +1 @@ -AutoCloseComplaintsJob.perform_later \ No newline at end of file +AutoCloseComplaintsJob.perform_now \ No newline at end of file diff --git a/scripts/run_new_thread_followers_cleanup.rb b/scripts/run_new_thread_followers_cleanup.rb index 73305dbde..8170d081b 100644 --- a/scripts/run_new_thread_followers_cleanup.rb +++ b/scripts/run_new_thread_followers_cleanup.rb @@ -1 +1 @@ -CleanUpNewThreadFollowersJob.perform_later +CleanUpNewThreadFollowersJob.perform_now diff --git a/scripts/run_spam_cleanup.rb b/scripts/run_spam_cleanup.rb index 82122f9c5..a6d0afd4b 100644 --- a/scripts/run_spam_cleanup.rb +++ b/scripts/run_spam_cleanup.rb @@ -1,2 +1,2 @@ -CleanUpSpammyUsersJob.perform_later -PotentialSpamProfilesJob.perform_later +CleanUpSpammyUsersJob.perform_now +PotentialSpamProfilesJob.perform_now diff --git a/scripts/run_summary_mailer.rb b/scripts/run_summary_mailer.rb index ce82f1544..99dbc5e16 100644 --- a/scripts/run_summary_mailer.rb +++ b/scripts/run_summary_mailer.rb @@ -1 +1 @@ -SendSummaryEmailsJob.perform_later +SendSummaryEmailsJob.perform_now diff --git a/scripts/run_thread_followers_cleanup.rb b/scripts/run_thread_followers_cleanup.rb index 06bbee308..e304c345d 100644 --- a/scripts/run_thread_followers_cleanup.rb +++ b/scripts/run_thread_followers_cleanup.rb @@ -1 +1 @@ -CleanUpThreadFollowersJob.perform_later +CleanUpThreadFollowersJob.perform_now From 53ec03b52475152204eb2ff99ddf0ff4624e424e Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Mon, 2 Mar 2026 16:18:44 +0000 Subject: [PATCH 02/11] Move recalc abilities to a job --- app/jobs/recalc_abilities_job.rb | 57 ++++++++++++++++++++++++++ scripts/recalc_abilities.rb | 45 +------------------- test/jobs/recalc_abilities_job_test.rb | 10 +++++ 3 files changed, 68 insertions(+), 44 deletions(-) create mode 100644 app/jobs/recalc_abilities_job.rb create mode 100644 test/jobs/recalc_abilities_job_test.rb diff --git a/app/jobs/recalc_abilities_job.rb b/app/jobs/recalc_abilities_job.rb new file mode 100644 index 000000000..948d62d46 --- /dev/null +++ b/app/jobs/recalc_abilities_job.rb @@ -0,0 +1,57 @@ +class RecalcAbilitiesJob < ApplicationJob + queue_as :default + + ## + # Perform ability recalculations. + # @param options [OpenStruct] additional options for the job. Currently supports +verbose+ and +quiet+. + def perform(options) + resolved = [] + destroy = [] + all = AbilityQueue.pending.to_a + + all.each do |q| + begin + cu = q.community_user + u = cu&.user + + if cu.nil? || u.nil? + destroy << q.id + next + end + + RequestContext.community = cu.community + + if options.verbose && !options.quiet + logger.debug "Scope: Community : #{cu.community.name} (#{cu.community.host})" + logger.debug " User : #{u.username} (#{cu.user_id})" + logger.debug " CommunityUser : #{cu.id}" + elsif !options.verbose && !options.quiet + logger.debug "Scope: CommunityUser : #{cu.id}" + end + + cu.recalc_abilities! + + # Grant mod ability if mod status is given + if cu.at_least_moderator? && !cu.ability?('mod') + cu.grant_ability!('mod') + end + + resolved << q.id + rescue => e + logger.error " Failed: #{e.class.name}: #{e.message}" + logger.error e.backtrace + + if Rails.env.test? + raise e + end + end + end + + AbilityQueue.where(id: resolved).update(completed: true) + AbilityQueue.where(id: destroy).delete_all + + unless options.quiet + logger.info "Completed, #{resolved.size}/#{all.size} tasks successful, #{destroy.size} tasks invalid" + end + end +end diff --git a/scripts/recalc_abilities.rb b/scripts/recalc_abilities.rb index aff36903e..7b5ae35ba 100644 --- a/scripts/recalc_abilities.rb +++ b/scripts/recalc_abilities.rb @@ -12,47 +12,4 @@ end end.parse! -resolved = [] -destroy = [] -all = AbilityQueue.pending.to_a - -all.each do |q| - begin - cu = q.community_user - u = cu&.user - - if cu.nil? || u.nil? - destroy << q.id - next - end - - RequestContext.community = cu.community - - if options.verbose && !options.quiet - puts "Scope: Community : #{cu.community.name} (#{cu.community.host})" - puts " User : #{u.username} (#{cu.user_id})" - puts " CommunityUser : #{cu.id}" - elsif !options.verbose && !options.quiet - puts "Scope: CommunityUser : #{cu.id}" - end - - cu.recalc_abilities! - - # Grant mod ability if mod status is given - if cu.at_least_moderator? && !cu.ability?('mod') - cu.grant_ability!('mod') - end - - resolved << q.id - rescue => e - $stderr.puts " Failed: #{e.class.name}: #{e.message}" - $stderr.puts e.backtrace - end -end - -AbilityQueue.where(id: resolved).update(completed: true) -AbilityQueue.where(id: destroy).delete_all - -unless options.quiet - puts "Completed, #{resolved.size}/#{all.size} tasks successful, #{destroy.size} tasks invalid" -end +RecalcAbilitiesJob.perform_now(options) diff --git a/test/jobs/recalc_abilities_job_test.rb b/test/jobs/recalc_abilities_job_test.rb new file mode 100644 index 000000000..500f65316 --- /dev/null +++ b/test/jobs/recalc_abilities_job_test.rb @@ -0,0 +1,10 @@ +require "test_helper" + +class RecalcAbilitiesJobTest < ActiveJob::TestCase + test 'should run job successfully' do + perform_enqueued_jobs do + RecalcAbilitiesJob.perform_later + end + assert_performed_jobs 1 + end +end From c8b27edd07b255e558d5361b39559e7d7f4f2130 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Mon, 2 Mar 2026 16:26:30 +0000 Subject: [PATCH 03/11] Move uncaptured donations to a job --- app/jobs/mail_uncaptured_donations_job.rb | 30 +++++++++++++++++++ scripts/mail_uncaptured_donations.rb | 19 +----------- .../mail_uncaptured_donations_job_test.rb | 10 +++++++ 3 files changed, 41 insertions(+), 18 deletions(-) create mode 100644 app/jobs/mail_uncaptured_donations_job.rb create mode 100644 test/jobs/mail_uncaptured_donations_job_test.rb diff --git a/app/jobs/mail_uncaptured_donations_job.rb b/app/jobs/mail_uncaptured_donations_job.rb new file mode 100644 index 000000000..219b1d52d --- /dev/null +++ b/app/jobs/mail_uncaptured_donations_job.rb @@ -0,0 +1,30 @@ +class MailUncapturedDonationsJob < ApplicationJob + queue_as :default + + def perform(*args) + intents = Stripe::PaymentIntent.list + mailed = 0 + errors = 0 + intents.auto_paging_each do |pi| + begin + break unless Time.at(pi.created) >= 24.hours.ago + next unless pi.status == 'requires_payment_method' + next unless pi.metadata['user_id'].present? + next if pi.metadata['emailed'].present? + user = User.find(pi.metadata['user_id']) + symbol = { 'GBP' => '£', 'USD' => '$', 'EUR' => '€' }[pi.currency.upcase] + amount = pi.amount / 100 + DonationMailer.with(currency: symbol, amount: amount, email: user.email, name: user.username, intent: pi) + .donation_uncaptured.deliver_now + Stripe::PaymentIntent.update(pi.id, { metadata: { emailed: true } }) + logger.debug "Mailed ##{user.id} for PaymentIntent #{pi.id}" + mailed += 1 + rescue => ex + Stripe::PaymentIntent.update(pi.id, { metadata: { email_error: "#{ex.message}" } }) + logger.error "Error sending email for user #{user.id}, PaymentIntent #{pi.id}: #{ex.message}" + errors += 1 + end + end + logger.info "Mailed #{mailed} donations, #{errors} errors" + end +end diff --git a/scripts/mail_uncaptured_donations.rb b/scripts/mail_uncaptured_donations.rb index e82cfabd0..2cc89b570 100644 --- a/scripts/mail_uncaptured_donations.rb +++ b/scripts/mail_uncaptured_donations.rb @@ -1,18 +1 @@ -intents = Stripe::PaymentIntent.list -intents.auto_paging_each do |pi| - begin - break unless Time.at(pi.created) >= 24.hours.ago - next unless pi.status == 'requires_payment_method' - next unless pi.metadata['user_id'].present? - next if pi.metadata['emailed'].present? - user = User.find(pi.metadata['user_id']) - symbol = { 'GBP' => '£', 'USD' => '$', 'EUR' => '€' }[pi.currency.upcase] - amount = pi.amount / 100 - DonationMailer.with(currency: symbol, amount: amount, email: user.email, name: user.username, intent: pi) - .donation_uncaptured.deliver_now - Stripe::PaymentIntent.update(pi.id, { metadata: { emailed: true } }) - puts "Mailed ##{user.id} for PaymentIntent #{pi.id}" - rescue => ex - Stripe::PaymentIntent.update(pi.id, { metadata: { email_error: "#{ex.message}" } }) - end -end +MailUncapturedDonations.perform_now diff --git a/test/jobs/mail_uncaptured_donations_job_test.rb b/test/jobs/mail_uncaptured_donations_job_test.rb new file mode 100644 index 000000000..a40450262 --- /dev/null +++ b/test/jobs/mail_uncaptured_donations_job_test.rb @@ -0,0 +1,10 @@ +require "test_helper" + +class MailUncapturedDonationsJobTest < ActiveJob::TestCase + test 'should run job successfully' do + perform_enqueued_jobs do + MailUncapturedDonationsJob.perform_later + end + assert_performed_jobs 1 + end +end From 4f4529886ce942f474fbbc6a6d441a67854c6891 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Mon, 2 Mar 2026 17:04:19 +0000 Subject: [PATCH 04/11] Rubocop --- app/jobs/mail_uncaptured_donations_job.rb | 37 +++++------ app/jobs/recalc_abilities_job.rb | 66 +++++++++---------- .../mail_uncaptured_donations_job_test.rb | 2 +- test/jobs/recalc_abilities_job_test.rb | 2 +- 4 files changed, 52 insertions(+), 55 deletions(-) diff --git a/app/jobs/mail_uncaptured_donations_job.rb b/app/jobs/mail_uncaptured_donations_job.rb index 219b1d52d..94fbe5b18 100644 --- a/app/jobs/mail_uncaptured_donations_job.rb +++ b/app/jobs/mail_uncaptured_donations_job.rb @@ -1,29 +1,28 @@ class MailUncapturedDonationsJob < ApplicationJob queue_as :default - def perform(*args) + def perform(*_args) intents = Stripe::PaymentIntent.list mailed = 0 errors = 0 intents.auto_paging_each do |pi| - begin - break unless Time.at(pi.created) >= 24.hours.ago - next unless pi.status == 'requires_payment_method' - next unless pi.metadata['user_id'].present? - next if pi.metadata['emailed'].present? - user = User.find(pi.metadata['user_id']) - symbol = { 'GBP' => '£', 'USD' => '$', 'EUR' => '€' }[pi.currency.upcase] - amount = pi.amount / 100 - DonationMailer.with(currency: symbol, amount: amount, email: user.email, name: user.username, intent: pi) - .donation_uncaptured.deliver_now - Stripe::PaymentIntent.update(pi.id, { metadata: { emailed: true } }) - logger.debug "Mailed ##{user.id} for PaymentIntent #{pi.id}" - mailed += 1 - rescue => ex - Stripe::PaymentIntent.update(pi.id, { metadata: { email_error: "#{ex.message}" } }) - logger.error "Error sending email for user #{user.id}, PaymentIntent #{pi.id}: #{ex.message}" - errors += 1 - end + break unless Time.at(pi.created) >= 24.hours.ago + next unless pi.status == 'requires_payment_method' + next unless pi.metadata['user_id'].present? + next if pi.metadata['emailed'].present? + + user = User.find(pi.metadata['user_id']) + symbol = { 'GBP' => '£', 'USD' => '$', 'EUR' => '€' }[pi.currency.upcase] + amount = pi.amount / 100 + DonationMailer.with(currency: symbol, amount: amount, email: user.email, name: user.username, intent: pi) + .donation_uncaptured.deliver_now + Stripe::PaymentIntent.update(pi.id, { metadata: { emailed: true } }) + logger.debug "Mailed ##{user.id} for PaymentIntent #{pi.id}" + mailed += 1 + rescue => e + Stripe::PaymentIntent.update(pi.id, { metadata: { email_error: e.message.to_s } }) + logger.error "Error sending email for user #{user.id}, PaymentIntent #{pi.id}: #{e.message}" + errors += 1 end logger.info "Mailed #{mailed} donations, #{errors} errors" end diff --git a/app/jobs/recalc_abilities_job.rb b/app/jobs/recalc_abilities_job.rb index 948d62d46..90f737d12 100644 --- a/app/jobs/recalc_abilities_job.rb +++ b/app/jobs/recalc_abilities_job.rb @@ -10,40 +10,38 @@ def perform(options) all = AbilityQueue.pending.to_a all.each do |q| - begin - cu = q.community_user - u = cu&.user - - if cu.nil? || u.nil? - destroy << q.id - next - end - - RequestContext.community = cu.community - - if options.verbose && !options.quiet - logger.debug "Scope: Community : #{cu.community.name} (#{cu.community.host})" - logger.debug " User : #{u.username} (#{cu.user_id})" - logger.debug " CommunityUser : #{cu.id}" - elsif !options.verbose && !options.quiet - logger.debug "Scope: CommunityUser : #{cu.id}" - end - - cu.recalc_abilities! - - # Grant mod ability if mod status is given - if cu.at_least_moderator? && !cu.ability?('mod') - cu.grant_ability!('mod') - end - - resolved << q.id - rescue => e - logger.error " Failed: #{e.class.name}: #{e.message}" - logger.error e.backtrace - - if Rails.env.test? - raise e - end + cu = q.community_user + u = cu&.user + + if cu.nil? || u.nil? + destroy << q.id + next + end + + RequestContext.community = cu.community + + if options.verbose && !options.quiet + logger.debug "Scope: Community : #{cu.community.name} (#{cu.community.host})" + logger.debug " User : #{u.username} (#{cu.user_id})" + logger.debug " CommunityUser : #{cu.id}" + elsif !options.verbose && !options.quiet + logger.debug "Scope: CommunityUser : #{cu.id}" + end + + cu.recalc_abilities! + + # Grant mod ability if mod status is given + if cu.at_least_moderator? && !cu.ability?('mod') + cu.grant_ability!('mod') + end + + resolved << q.id + rescue => e + logger.error " Failed: #{e.class.name}: #{e.message}" + logger.error e.backtrace + + if Rails.env.test? + raise e end end diff --git a/test/jobs/mail_uncaptured_donations_job_test.rb b/test/jobs/mail_uncaptured_donations_job_test.rb index a40450262..11f8cc2be 100644 --- a/test/jobs/mail_uncaptured_donations_job_test.rb +++ b/test/jobs/mail_uncaptured_donations_job_test.rb @@ -1,4 +1,4 @@ -require "test_helper" +require 'test_helper' class MailUncapturedDonationsJobTest < ActiveJob::TestCase test 'should run job successfully' do diff --git a/test/jobs/recalc_abilities_job_test.rb b/test/jobs/recalc_abilities_job_test.rb index 500f65316..b5b535693 100644 --- a/test/jobs/recalc_abilities_job_test.rb +++ b/test/jobs/recalc_abilities_job_test.rb @@ -1,4 +1,4 @@ -require "test_helper" +require 'test_helper' class RecalcAbilitiesJobTest < ActiveJob::TestCase test 'should run job successfully' do From 1d978142adab07e07a2f95b8c67548fe94651eff Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Mon, 2 Mar 2026 17:05:50 +0000 Subject: [PATCH 05/11] Add argument to job --- test/jobs/recalc_abilities_job_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jobs/recalc_abilities_job_test.rb b/test/jobs/recalc_abilities_job_test.rb index b5b535693..30865db95 100644 --- a/test/jobs/recalc_abilities_job_test.rb +++ b/test/jobs/recalc_abilities_job_test.rb @@ -3,7 +3,7 @@ class RecalcAbilitiesJobTest < ActiveJob::TestCase test 'should run job successfully' do perform_enqueued_jobs do - RecalcAbilitiesJob.perform_later + RecalcAbilitiesJob.perform_later OpenStruct.new end assert_performed_jobs 1 end From c6281e216903eae9dd8f9f1156420edd258db005 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Mon, 2 Mar 2026 17:25:19 +0000 Subject: [PATCH 06/11] Parameterise initialize --- app/jobs/application_job.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb index 9c5500d84..7e4c96974 100644 --- a/app/jobs/application_job.rb +++ b/app/jobs/application_job.rb @@ -5,9 +5,9 @@ class ApplicationJob < ActiveJob::Base # Most jobs are safe to ignore if the underlying records are no longer available discard_on ActiveJob::DeserializationError - def initialize + def initialize(*args, **opts) @job_id = SecureRandom.uuid - super + super(*args, **opts) end def logger From 5f81af3f4859d558c3bbd681f4940ef99f515425 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Mon, 2 Mar 2026 17:49:49 +0000 Subject: [PATCH 07/11] Use a hash instead --- app/jobs/application_job.rb | 2 +- app/jobs/recalc_abilities_job.rb | 10 +++++----- scripts/recalc_abilities.rb | 6 +++--- test/jobs/recalc_abilities_job_test.rb | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb index 7e4c96974..7f1bb2ba6 100644 --- a/app/jobs/application_job.rb +++ b/app/jobs/application_job.rb @@ -7,7 +7,7 @@ class ApplicationJob < ActiveJob::Base def initialize(*args, **opts) @job_id = SecureRandom.uuid - super(*args, **opts) + super end def logger diff --git a/app/jobs/recalc_abilities_job.rb b/app/jobs/recalc_abilities_job.rb index 90f737d12..af45cbe10 100644 --- a/app/jobs/recalc_abilities_job.rb +++ b/app/jobs/recalc_abilities_job.rb @@ -3,8 +3,8 @@ class RecalcAbilitiesJob < ApplicationJob ## # Perform ability recalculations. - # @param options [OpenStruct] additional options for the job. Currently supports +verbose+ and +quiet+. - def perform(options) + # @param options [Hash] additional options for the job. Currently supports +verbose+ and +quiet+. + def perform(**options) resolved = [] destroy = [] all = AbilityQueue.pending.to_a @@ -20,11 +20,11 @@ def perform(options) RequestContext.community = cu.community - if options.verbose && !options.quiet + if options[:verbose] && !options[:quiet] logger.debug "Scope: Community : #{cu.community.name} (#{cu.community.host})" logger.debug " User : #{u.username} (#{cu.user_id})" logger.debug " CommunityUser : #{cu.id}" - elsif !options.verbose && !options.quiet + elsif !options[:verbose] && !options[:quiet] logger.debug "Scope: CommunityUser : #{cu.id}" end @@ -48,7 +48,7 @@ def perform(options) AbilityQueue.where(id: resolved).update(completed: true) AbilityQueue.where(id: destroy).delete_all - unless options.quiet + unless options[:quiet] logger.info "Completed, #{resolved.size}/#{all.size} tasks successful, #{destroy.size} tasks invalid" end end diff --git a/scripts/recalc_abilities.rb b/scripts/recalc_abilities.rb index 7b5ae35ba..09733238c 100644 --- a/scripts/recalc_abilities.rb +++ b/scripts/recalc_abilities.rb @@ -1,14 +1,14 @@ -options = OpenStruct.new +options = {} OptionParser.new do |opts| opts.banner = "Usage: rails r scripts/recalc_abilities.rb [options]" opts.on('-v', '--verbose', 'Run with additional logging') do - options.verbose = true + options[:verbose] = true end opts.on('-q', '--quiet', 'Run with minimal logging') do - options.quiet = true + options[:quiet] = true end end.parse! diff --git a/test/jobs/recalc_abilities_job_test.rb b/test/jobs/recalc_abilities_job_test.rb index 30865db95..6e56bc0c9 100644 --- a/test/jobs/recalc_abilities_job_test.rb +++ b/test/jobs/recalc_abilities_job_test.rb @@ -3,7 +3,7 @@ class RecalcAbilitiesJobTest < ActiveJob::TestCase test 'should run job successfully' do perform_enqueued_jobs do - RecalcAbilitiesJob.perform_later OpenStruct.new + RecalcAbilitiesJob.perform_later(verbose: false, quiet: true) end assert_performed_jobs 1 end From 9393ecfe6e1b6c21a0fb97c068c3c733469adba4 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Mon, 2 Mar 2026 17:56:09 +0000 Subject: [PATCH 08/11] Copy master key for credentials --- .github/workflows/ci-cd.yml | 1 + config/credentials.yml.enc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 2c5c2ec82..369709f05 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -87,6 +87,7 @@ jobs: bundler-cache: true - name: Prepare for testing run: | + echo "${{ secrets.MASTER_KEY }}" > config/master.key cp config/database.sample.yml config/database.yml cp config/storage.sample.yml config/storage.yml bundle exec rails db:create diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc index fc62796fc..dc092dbf6 100644 --- a/config/credentials.yml.enc +++ b/config/credentials.yml.enc @@ -1 +1 @@ -SA7h7Xm7xF3AEvje/xZiPMzem0wh2CysuvvB+iM6R0Epkg+z+vZG2oxI/9tVzDGELWtwoNDPeqNa0bUbGjo6gt7xyEpmQbivEVKnwcbVK+1bxPHKke+hveVEUhmY/axFIIpty+VTnZVnrJkZ35/rW9egcRr5O2HikuAuBz8KrYLvB2w3h8EdmcIbbfjMvKWlUVvc8D9t3v+k56B1CbTghTmGeG0NLijWAA+U+pDmErPOR9JUAVY/nbF2/T8aQ5Szameuoj88Pk5P6alFDHwlWUSHhuEY5Z7A5LKM1NtzlTGc+CAcTVzKvx6DCg8WUJugy3uS7Bpp6uNj9TvJoZzrb0i5G1nDmIl7tK2GCNclp3JFEklrUJIrF4asRuDQUzdvuPeTEXNyi2cc5d6hSBG+MwEvG90P6n0td5+gv+rr1FCKuzP5ftyxqPsnvZuBKRxNSw0+VTTXhTO73jcwttHYrD9Jwc9tVbCVqegwsEO0dB0sNL6M89rudDMbpPnz7rJXr6lXD4Az3qJ/0N3ubYDwiuGOk7UHDntm4Id4BFDm5qeLeOUg1n2PDhsQUWh2Lfnk7ADvjQMinfXhdAQkYVim9sDtNO/Grn9xSXfCn3vs1xOdTtKLb23+EIxO2STtkHTsJG5XvxC2jmzL5/zQx/vO/zepHom7POdso4Ygoqw9oEttm/KPG85lcX0edXv/l1i5JBMMbzaQgd1PL4uWwrv+3LoSq+vQORijR50OiLdlMZ5IFn+QagJEdeVtUiCbYA3AhUK/FcH3L5QtSGNObEUrUJ4fVuWP6X8E34vd+DoY++D6PtG89SFIGBRmQ23cT111uIw3p2A9HP4N9B/uNKwxAnr4S1he6EkoA5CtDE0NZufy25s0IVf//FDWXS8FDg3ZhtOUeMWB0dew9VeCCWwr8RrLu4jP46IvVqfFeiVWf7gJcenEJ0QuqPlBeukSpgNxckDjwijRz5obzeS9ZAWYgCZg2kg/6CmuIM2VjkWMJ13uKYkFgpheoNsk1jZwH4+0fdm+Zc+fE4KQFcSkkazea/qEanN2/tDo6pRowSlRpi/nWJqHxcu87QMm7cBq5/E9DNjwyKOPmgr7c2NzDrlPYMRgzdcauPz6Y4qfcg9C6lKwJIo18VQhrqwh7wW+nNTov3Shw/yclkVrxnHTQbyH3mOstJsVPpYeYewxOQj/gikvvkx/lUeUnyo2/Ebff2nJCbnLmJ8/7Vwz9c/yvg==--d1HPd+AnhFU1woqD--z2ikkRr6d5WTzC7X5xOVPA== \ No newline at end of file +ukMy8KvWRehfYquyl3GRlaSkFk/8OAjIw3HK2LIH4u1HhtiY2XrkXbwg3rKeCofCW1K5lxNf7r+w+v0IMfVnOkmOPI0eB/TNotrq0ieomzMnhYOXzBBQb/31vFFMFCGOZIRbk9vyduQGg/wifWMjoEk9ooL++YP2q+fXm/80d2gDF/G4hMNgdAq0SFPjn3cVM2Qty1ru1BuOJwgqo4yKDBjvuL7ZOxudDuPnKujY2IpgykCkKCk7TE80v9B4ZKdIi27P1ciWmP5Kc50jk7SWlhHVbo3FdJy1a/n5RadGq/vdlwOXFdyNUvlRF7xRvjlgiqoyqDHcyOuOyIP86v2qgeDl5Y7yYwIhe8FwqPy/oW/jMDP8OvDZuWtNwpxIFJYT7sKdvIvEvjrPR+0pyTVsVMZomTiUIcFC/IA9KV+DVjtj+Tfy2UZH4W8AU6i8hObiSs4CbT081L2AHc0ZcLKMI/bh8+vBay4J2UB6vcBbpNbAaNPyj7bXsrM0+YxpPJidgrEMyoVt+fIiA5H/kXhp8WV3Jkr2eEriq5z9+m6IZFSFs58i06hN0ZH5WHUdhJcVIgMBiLOex4SVd9zL6NW2y+ZK9Fs27z8u22zn+51oQHcpz2wbmVV3sGBYaFLFinqm3/HoW60eAcvM4SfXErz0fwIzq7yN7XIY9q5/6E0hhAdHZQqVlEJWOhUAIH9ik+Ga90gWLfkkoym/G1PIUYnmeJtLUKYyj94b+YdxQNkgzGtJA7FCGVmNUuy8wCw0OIG1hg3z9TSg5mbN7ZNhBRVDvKQENJqg9tFXM0MgXn+lQ0v+io4ds6Ist2BGr4gJIz5R7bRFOIG6G60/+ZEfPBjNcj5rrGYDBATmqKo9myaSLQ68WyJB37Fs3CchM4lAdoVbXnEyJwP8HGRaips+ZhjBVvSs/8w7yQteBswFrc00+gts5TpqCz3AjNNMsHTP5cr5IhqoNWdpxvFgHHLBAPtn0HWJ5C3OP3X/4GhxG3G9Z99pxbH1ZjWn1vnKadKUfY4vzPYCZsMaokTr2/XuL8wROLohCD53SVATsGsbiL947u+X6WYEZVuOH2IY5xMhTO9JW8DYb0Rm31Te8oOpzoIrz9Ck70YDQcADiNg4SEeLTQlpve40C5+YI5Xr+60GbOHRHSGv31ENnubVTCTv3q6otE0iqCOAQ62RdqhzT23aaz0NuH5DtLIlWn/3ev9Js6mm1rnF7AzVKey01IsS--p3woHV6iIC4KuPxP--fRXQKncEML1whOWmVm2Z8w== \ No newline at end of file From a135a4a20d4fd422bbaf888eabfee8abbe3b3ef1 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Mon, 2 Mar 2026 18:10:28 +0000 Subject: [PATCH 09/11] Allow net connections for Stripe test --- test/controllers/donations_controller_test.rb | 8 ++++++++ test/jobs/mail_uncaptured_donations_job_test.rb | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/test/controllers/donations_controller_test.rb b/test/controllers/donations_controller_test.rb index 21fa129a2..e675e2f26 100644 --- a/test/controllers/donations_controller_test.rb +++ b/test/controllers/donations_controller_test.rb @@ -3,6 +3,14 @@ class DonationsControllerTest < ActionController::TestCase include Devise::Test::ControllerHelpers + setup do + WebMock.allow_net_connect! + end + + teardown do + WebMock.disable_net_connect! + end + test 'should get index' do get :index assert_response(:success) diff --git a/test/jobs/mail_uncaptured_donations_job_test.rb b/test/jobs/mail_uncaptured_donations_job_test.rb index 11f8cc2be..08574d242 100644 --- a/test/jobs/mail_uncaptured_donations_job_test.rb +++ b/test/jobs/mail_uncaptured_donations_job_test.rb @@ -1,7 +1,16 @@ require 'test_helper' class MailUncapturedDonationsJobTest < ActiveJob::TestCase + setup do + WebMock.allow_net_connect! + end + + teardown do + WebMock.disable_net_connect! + end + test 'should run job successfully' do + WebMock.allow_net_connect! perform_enqueued_jobs do MailUncapturedDonationsJob.perform_later end From b02ccef91de7ffcf5db12a848b24e51d2f5b4c7c Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Mon, 2 Mar 2026 20:09:24 +0000 Subject: [PATCH 10/11] Skip test if no API key --- test/jobs/mail_uncaptured_donations_job_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jobs/mail_uncaptured_donations_job_test.rb b/test/jobs/mail_uncaptured_donations_job_test.rb index 08574d242..ac62482c5 100644 --- a/test/jobs/mail_uncaptured_donations_job_test.rb +++ b/test/jobs/mail_uncaptured_donations_job_test.rb @@ -10,6 +10,7 @@ class MailUncapturedDonationsJobTest < ActiveJob::TestCase end test 'should run job successfully' do + skip unless Stripe.api_key WebMock.allow_net_connect! perform_enqueued_jobs do MailUncapturedDonationsJob.perform_later From 833786a2d0711efdb3ec70ada599f68aca0ecc8a Mon Sep 17 00:00:00 2001 From: Oleg Valter Date: Tue, 3 Mar 2026 02:22:25 +0300 Subject: [PATCH 11/11] fixed missing EoF newlines --- config/credentials.yml.enc | 2 +- scripts/cleanup_votes.rb | 2 +- scripts/run_complaints_closure.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc index dc092dbf6..1765efcd9 100644 --- a/config/credentials.yml.enc +++ b/config/credentials.yml.enc @@ -1 +1 @@ -ukMy8KvWRehfYquyl3GRlaSkFk/8OAjIw3HK2LIH4u1HhtiY2XrkXbwg3rKeCofCW1K5lxNf7r+w+v0IMfVnOkmOPI0eB/TNotrq0ieomzMnhYOXzBBQb/31vFFMFCGOZIRbk9vyduQGg/wifWMjoEk9ooL++YP2q+fXm/80d2gDF/G4hMNgdAq0SFPjn3cVM2Qty1ru1BuOJwgqo4yKDBjvuL7ZOxudDuPnKujY2IpgykCkKCk7TE80v9B4ZKdIi27P1ciWmP5Kc50jk7SWlhHVbo3FdJy1a/n5RadGq/vdlwOXFdyNUvlRF7xRvjlgiqoyqDHcyOuOyIP86v2qgeDl5Y7yYwIhe8FwqPy/oW/jMDP8OvDZuWtNwpxIFJYT7sKdvIvEvjrPR+0pyTVsVMZomTiUIcFC/IA9KV+DVjtj+Tfy2UZH4W8AU6i8hObiSs4CbT081L2AHc0ZcLKMI/bh8+vBay4J2UB6vcBbpNbAaNPyj7bXsrM0+YxpPJidgrEMyoVt+fIiA5H/kXhp8WV3Jkr2eEriq5z9+m6IZFSFs58i06hN0ZH5WHUdhJcVIgMBiLOex4SVd9zL6NW2y+ZK9Fs27z8u22zn+51oQHcpz2wbmVV3sGBYaFLFinqm3/HoW60eAcvM4SfXErz0fwIzq7yN7XIY9q5/6E0hhAdHZQqVlEJWOhUAIH9ik+Ga90gWLfkkoym/G1PIUYnmeJtLUKYyj94b+YdxQNkgzGtJA7FCGVmNUuy8wCw0OIG1hg3z9TSg5mbN7ZNhBRVDvKQENJqg9tFXM0MgXn+lQ0v+io4ds6Ist2BGr4gJIz5R7bRFOIG6G60/+ZEfPBjNcj5rrGYDBATmqKo9myaSLQ68WyJB37Fs3CchM4lAdoVbXnEyJwP8HGRaips+ZhjBVvSs/8w7yQteBswFrc00+gts5TpqCz3AjNNMsHTP5cr5IhqoNWdpxvFgHHLBAPtn0HWJ5C3OP3X/4GhxG3G9Z99pxbH1ZjWn1vnKadKUfY4vzPYCZsMaokTr2/XuL8wROLohCD53SVATsGsbiL947u+X6WYEZVuOH2IY5xMhTO9JW8DYb0Rm31Te8oOpzoIrz9Ck70YDQcADiNg4SEeLTQlpve40C5+YI5Xr+60GbOHRHSGv31ENnubVTCTv3q6otE0iqCOAQ62RdqhzT23aaz0NuH5DtLIlWn/3ev9Js6mm1rnF7AzVKey01IsS--p3woHV6iIC4KuPxP--fRXQKncEML1whOWmVm2Z8w== \ No newline at end of file +ukMy8KvWRehfYquyl3GRlaSkFk/8OAjIw3HK2LIH4u1HhtiY2XrkXbwg3rKeCofCW1K5lxNf7r+w+v0IMfVnOkmOPI0eB/TNotrq0ieomzMnhYOXzBBQb/31vFFMFCGOZIRbk9vyduQGg/wifWMjoEk9ooL++YP2q+fXm/80d2gDF/G4hMNgdAq0SFPjn3cVM2Qty1ru1BuOJwgqo4yKDBjvuL7ZOxudDuPnKujY2IpgykCkKCk7TE80v9B4ZKdIi27P1ciWmP5Kc50jk7SWlhHVbo3FdJy1a/n5RadGq/vdlwOXFdyNUvlRF7xRvjlgiqoyqDHcyOuOyIP86v2qgeDl5Y7yYwIhe8FwqPy/oW/jMDP8OvDZuWtNwpxIFJYT7sKdvIvEvjrPR+0pyTVsVMZomTiUIcFC/IA9KV+DVjtj+Tfy2UZH4W8AU6i8hObiSs4CbT081L2AHc0ZcLKMI/bh8+vBay4J2UB6vcBbpNbAaNPyj7bXsrM0+YxpPJidgrEMyoVt+fIiA5H/kXhp8WV3Jkr2eEriq5z9+m6IZFSFs58i06hN0ZH5WHUdhJcVIgMBiLOex4SVd9zL6NW2y+ZK9Fs27z8u22zn+51oQHcpz2wbmVV3sGBYaFLFinqm3/HoW60eAcvM4SfXErz0fwIzq7yN7XIY9q5/6E0hhAdHZQqVlEJWOhUAIH9ik+Ga90gWLfkkoym/G1PIUYnmeJtLUKYyj94b+YdxQNkgzGtJA7FCGVmNUuy8wCw0OIG1hg3z9TSg5mbN7ZNhBRVDvKQENJqg9tFXM0MgXn+lQ0v+io4ds6Ist2BGr4gJIz5R7bRFOIG6G60/+ZEfPBjNcj5rrGYDBATmqKo9myaSLQ68WyJB37Fs3CchM4lAdoVbXnEyJwP8HGRaips+ZhjBVvSs/8w7yQteBswFrc00+gts5TpqCz3AjNNMsHTP5cr5IhqoNWdpxvFgHHLBAPtn0HWJ5C3OP3X/4GhxG3G9Z99pxbH1ZjWn1vnKadKUfY4vzPYCZsMaokTr2/XuL8wROLohCD53SVATsGsbiL947u+X6WYEZVuOH2IY5xMhTO9JW8DYb0Rm31Te8oOpzoIrz9Ck70YDQcADiNg4SEeLTQlpve40C5+YI5Xr+60GbOHRHSGv31ENnubVTCTv3q6otE0iqCOAQ62RdqhzT23aaz0NuH5DtLIlWn/3ev9Js6mm1rnF7AzVKey01IsS--p3woHV6iIC4KuPxP--fRXQKncEML1whOWmVm2Z8w== diff --git a/scripts/cleanup_votes.rb b/scripts/cleanup_votes.rb index 4637722a0..2420dafed 100644 --- a/scripts/cleanup_votes.rb +++ b/scripts/cleanup_votes.rb @@ -1 +1 @@ -CleanupVotesJob.perform_now \ No newline at end of file +CleanupVotesJob.perform_now diff --git a/scripts/run_complaints_closure.rb b/scripts/run_complaints_closure.rb index 3a590319b..487cbb12c 100644 --- a/scripts/run_complaints_closure.rb +++ b/scripts/run_complaints_closure.rb @@ -1 +1 @@ -AutoCloseComplaintsJob.perform_now \ No newline at end of file +AutoCloseComplaintsJob.perform_now