From 384345b0de9cc6b8cc62bbf60f2361449995717d Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Wed, 24 May 2023 05:55:40 -0400
Subject: [PATCH] Add CLI Base class for command line code (#25106)

---
 lib/mastodon/cli/accounts.rb                  | 12 ++------
 lib/mastodon/cli/base.rb                      | 19 +++++++++++++
 lib/mastodon/cli/cache.rb                     | 12 ++------
 lib/mastodon/cli/canonical_email_blocks.rb    | 12 ++------
 lib/mastodon/cli/domains.rb                   | 12 ++------
 lib/mastodon/cli/email_domain_blocks.rb       | 12 ++------
 lib/mastodon/cli/emoji.rb                     | 10 ++-----
 lib/mastodon/cli/feeds.rb                     | 11 ++------
 lib/mastodon/cli/ip_blocks.rb                 | 10 ++-----
 lib/mastodon/cli/main.rb                      | 28 ++++++++-----------
 lib/mastodon/cli/maintenance.rb               | 12 ++------
 lib/mastodon/cli/media.rb                     | 11 ++------
 lib/mastodon/cli/preview_cards.rb             | 11 ++------
 lib/mastodon/cli/search.rb                    |  8 ++----
 lib/mastodon/cli/settings.rb                  | 12 ++------
 lib/mastodon/cli/statuses.rb                  | 11 ++------
 lib/mastodon/cli/upgrade.rb                   | 12 ++------
 spec/lib/mastodon/cli/accounts_spec.rb        | 12 ++++++++
 spec/lib/mastodon/cli/cache_spec.rb           | 12 ++++++++
 .../cli/canonical_email_blocks_spec.rb        | 12 ++++++++
 spec/lib/mastodon/cli/domains_spec.rb         | 12 ++++++++
 .../mastodon/cli/email_domain_blocks_spec.rb  | 12 ++++++++
 spec/lib/mastodon/cli/emoji_spec.rb           | 12 ++++++++
 spec/lib/mastodon/cli/feeds_spec.rb           | 12 ++++++++
 spec/lib/mastodon/cli/ip_blocks_spec.rb       |  8 +++++-
 spec/lib/mastodon/cli/main_spec.rb            |  6 ++++
 spec/lib/mastodon/cli/maintenance_spec.rb     | 12 ++++++++
 spec/lib/mastodon/cli/media_spec.rb           | 12 ++++++++
 spec/lib/mastodon/cli/preview_cards_spec.rb   | 12 ++++++++
 spec/lib/mastodon/cli/search_spec.rb          | 12 ++++++++
 spec/lib/mastodon/cli/settings_spec.rb        |  8 +++++-
 spec/lib/mastodon/cli/statuses_spec.rb        | 12 ++++++++
 spec/lib/mastodon/cli/upgrade_spec.rb         | 12 ++++++++
 33 files changed, 238 insertions(+), 155 deletions(-)
 create mode 100644 lib/mastodon/cli/base.rb
 create mode 100644 spec/lib/mastodon/cli/accounts_spec.rb
 create mode 100644 spec/lib/mastodon/cli/cache_spec.rb
 create mode 100644 spec/lib/mastodon/cli/canonical_email_blocks_spec.rb
 create mode 100644 spec/lib/mastodon/cli/domains_spec.rb
 create mode 100644 spec/lib/mastodon/cli/email_domain_blocks_spec.rb
 create mode 100644 spec/lib/mastodon/cli/emoji_spec.rb
 create mode 100644 spec/lib/mastodon/cli/feeds_spec.rb
 create mode 100644 spec/lib/mastodon/cli/maintenance_spec.rb
 create mode 100644 spec/lib/mastodon/cli/media_spec.rb
 create mode 100644 spec/lib/mastodon/cli/preview_cards_spec.rb
 create mode 100644 spec/lib/mastodon/cli/search_spec.rb
 create mode 100644 spec/lib/mastodon/cli/statuses_spec.rb
 create mode 100644 spec/lib/mastodon/cli/upgrade_spec.rb

diff --git a/lib/mastodon/cli/accounts.rb b/lib/mastodon/cli/accounts.rb
index a44f63db03..417f126ccd 100644
--- a/lib/mastodon/cli/accounts.rb
+++ b/lib/mastodon/cli/accounts.rb
@@ -1,18 +1,10 @@
 # frozen_string_literal: true
 
 require 'set'
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class Accounts < Thor
-    include Helper
-
-    def self.exit_on_failure?
-      true
-    end
-
+  class Accounts < Base
     option :all, type: :boolean
     desc 'rotate [USERNAME]', 'Generate and broadcast new keys'
     long_desc <<-LONG_DESC
diff --git a/lib/mastodon/cli/base.rb b/lib/mastodon/cli/base.rb
new file mode 100644
index 0000000000..f3c9fea921
--- /dev/null
+++ b/lib/mastodon/cli/base.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require_relative '../../../config/boot'
+require_relative '../../../config/environment'
+
+require 'thor'
+require_relative 'helper'
+
+module Mastodon
+  module CLI
+    class Base < Thor
+      include CLI::Helper
+
+      def self.exit_on_failure?
+        true
+      end
+    end
+  end
+end
diff --git a/lib/mastodon/cli/cache.rb b/lib/mastodon/cli/cache.rb
index b0bf6aabd8..105d4b3c32 100644
--- a/lib/mastodon/cli/cache.rb
+++ b/lib/mastodon/cli/cache.rb
@@ -1,17 +1,9 @@
 # frozen_string_literal: true
 
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class Cache < Thor
-    include Helper
-
-    def self.exit_on_failure?
-      true
-    end
-
+  class Cache < Base
     desc 'clear', 'Clear out the cache storage'
     def clear
       Rails.cache.clear
diff --git a/lib/mastodon/cli/canonical_email_blocks.rb b/lib/mastodon/cli/canonical_email_blocks.rb
index f3c427a2c7..dd5e6596dd 100644
--- a/lib/mastodon/cli/canonical_email_blocks.rb
+++ b/lib/mastodon/cli/canonical_email_blocks.rb
@@ -1,18 +1,10 @@
 # frozen_string_literal: true
 
 require 'concurrent'
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class CanonicalEmailBlocks < Thor
-    include Helper
-
-    def self.exit_on_failure?
-      true
-    end
-
+  class CanonicalEmailBlocks < Base
     desc 'find EMAIL', 'Find a given e-mail address in the canonical e-mail blocks'
     long_desc <<-LONG_DESC
       When suspending a local user, a hash of a "canonical" version of their e-mail
diff --git a/lib/mastodon/cli/domains.rb b/lib/mastodon/cli/domains.rb
index 8b5f03ce0f..d885c95638 100644
--- a/lib/mastodon/cli/domains.rb
+++ b/lib/mastodon/cli/domains.rb
@@ -1,18 +1,10 @@
 # frozen_string_literal: true
 
 require 'concurrent'
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class Domains < Thor
-    include Helper
-
-    def self.exit_on_failure?
-      true
-    end
-
+  class Domains < Base
     option :concurrency, type: :numeric, default: 5, aliases: [:c]
     option :verbose, type: :boolean, aliases: [:v]
     option :dry_run, type: :boolean
diff --git a/lib/mastodon/cli/email_domain_blocks.rb b/lib/mastodon/cli/email_domain_blocks.rb
index 6ef35cc8cf..abbbdfe31c 100644
--- a/lib/mastodon/cli/email_domain_blocks.rb
+++ b/lib/mastodon/cli/email_domain_blocks.rb
@@ -1,18 +1,10 @@
 # frozen_string_literal: true
 
 require 'concurrent'
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class EmailDomainBlocks < Thor
-    include Helper
-
-    def self.exit_on_failure?
-      true
-    end
-
+  class EmailDomainBlocks < Base
     desc 'list', 'List blocked e-mail domains'
     def list
       EmailDomainBlock.where(parent_id: nil).order(id: 'DESC').find_each do |entry|
diff --git a/lib/mastodon/cli/emoji.rb b/lib/mastodon/cli/emoji.rb
index 9b41a59c29..912c099124 100644
--- a/lib/mastodon/cli/emoji.rb
+++ b/lib/mastodon/cli/emoji.rb
@@ -1,16 +1,10 @@
 # frozen_string_literal: true
 
 require 'rubygems/package'
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class Emoji < Thor
-    def self.exit_on_failure?
-      true
-    end
-
+  class Emoji < Base
     option :prefix
     option :suffix
     option :overwrite, type: :boolean
diff --git a/lib/mastodon/cli/feeds.rb b/lib/mastodon/cli/feeds.rb
index 4307b880f7..342b550ca3 100644
--- a/lib/mastodon/cli/feeds.rb
+++ b/lib/mastodon/cli/feeds.rb
@@ -1,18 +1,11 @@
 # frozen_string_literal: true
 
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class Feeds < Thor
-    include Helper
+  class Feeds < Base
     include Redisable
 
-    def self.exit_on_failure?
-      true
-    end
-
     option :all, type: :boolean, default: false
     option :concurrency, type: :numeric, default: 5, aliases: [:c]
     option :verbose, type: :boolean, aliases: [:v]
diff --git a/lib/mastodon/cli/ip_blocks.rb b/lib/mastodon/cli/ip_blocks.rb
index 561d64d182..d12919c360 100644
--- a/lib/mastodon/cli/ip_blocks.rb
+++ b/lib/mastodon/cli/ip_blocks.rb
@@ -1,16 +1,10 @@
 # frozen_string_literal: true
 
 require 'rubygems/package'
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class IpBlocks < Thor
-    def self.exit_on_failure?
-      true
-    end
-
+  class IpBlocks < Base
     option :severity, required: true, enum: %w(no_access sign_up_requires_approval sign_up_block), desc: 'Severity of the block'
     option :comment, aliases: [:c], desc: 'Optional comment'
     option :duration, aliases: [:d], type: :numeric, desc: 'Duration of the block in seconds'
diff --git a/lib/mastodon/cli/main.rb b/lib/mastodon/cli/main.rb
index 0f2236f78f..e61a6f9c46 100644
--- a/lib/mastodon/cli/main.rb
+++ b/lib/mastodon/cli/main.rb
@@ -1,29 +1,25 @@
 # frozen_string_literal: true
 
-require 'thor'
-require_relative 'media'
-require_relative 'emoji'
+require_relative 'base'
+
 require_relative 'accounts'
+require_relative 'cache'
+require_relative 'canonical_email_blocks'
+require_relative 'domains'
+require_relative 'email_domain_blocks'
+require_relative 'emoji'
 require_relative 'feeds'
+require_relative 'ip_blocks'
+require_relative 'maintenance'
+require_relative 'media'
+require_relative 'preview_cards'
 require_relative 'search'
 require_relative 'settings'
 require_relative 'statuses'
-require_relative 'domains'
-require_relative 'preview_cards'
-require_relative 'cache'
 require_relative 'upgrade'
-require_relative 'email_domain_blocks'
-require_relative 'canonical_email_blocks'
-require_relative 'ip_blocks'
-require_relative 'maintenance'
-require_relative '../version'
 
 module Mastodon::CLI
-  class Main < Thor
-    def self.exit_on_failure?
-      true
-    end
-
+  class Main < Base
     desc 'media SUBCOMMAND ...ARGS', 'Manage media files'
     subcommand 'media', Media
 
diff --git a/lib/mastodon/cli/maintenance.rb b/lib/mastodon/cli/maintenance.rb
index d9f1b02570..660adef80e 100644
--- a/lib/mastodon/cli/maintenance.rb
+++ b/lib/mastodon/cli/maintenance.rb
@@ -1,18 +1,10 @@
 # frozen_string_literal: true
 
 require 'tty-prompt'
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class Maintenance < Thor
-    include Helper
-
-    def self.exit_on_failure?
-      true
-    end
-
+  class Maintenance < Base
     MIN_SUPPORTED_VERSION = 2019_10_01_213028
     MAX_SUPPORTED_VERSION = 2022_11_04_133904
 
diff --git a/lib/mastodon/cli/media.rb b/lib/mastodon/cli/media.rb
index 509c4ca264..045f6351ad 100644
--- a/lib/mastodon/cli/media.rb
+++ b/lib/mastodon/cli/media.rb
@@ -1,20 +1,13 @@
 # frozen_string_literal: true
 
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class Media < Thor
+  class Media < Base
     include ActionView::Helpers::NumberHelper
-    include Helper
 
     VALID_PATH_SEGMENTS_SIZE = [7, 10].freeze
 
-    def self.exit_on_failure?
-      true
-    end
-
     option :days, type: :numeric, default: 7, aliases: [:d]
     option :prune_profiles, type: :boolean, default: false
     option :remove_headers, type: :boolean, default: false
diff --git a/lib/mastodon/cli/preview_cards.rb b/lib/mastodon/cli/preview_cards.rb
index 794b25693a..c66bcb504a 100644
--- a/lib/mastodon/cli/preview_cards.rb
+++ b/lib/mastodon/cli/preview_cards.rb
@@ -1,18 +1,11 @@
 # frozen_string_literal: true
 
 require 'tty-prompt'
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class PreviewCards < Thor
+  class PreviewCards < Base
     include ActionView::Helpers::NumberHelper
-    include Helper
-
-    def self.exit_on_failure?
-      true
-    end
 
     option :days, type: :numeric, default: 180
     option :concurrency, type: :numeric, default: 5, aliases: [:c]
diff --git a/lib/mastodon/cli/search.rb b/lib/mastodon/cli/search.rb
index ccece5b5f8..6f48dcb096 100644
--- a/lib/mastodon/cli/search.rb
+++ b/lib/mastodon/cli/search.rb
@@ -1,13 +1,9 @@
 # frozen_string_literal: true
 
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class Search < Thor
-    include Helper
-
+  class Search < Base
     # Indices are sorted by amount of data to be expected in each, so that
     # smaller indices can go online sooner
     INDICES = [
diff --git a/lib/mastodon/cli/settings.rb b/lib/mastodon/cli/settings.rb
index 5869efc466..7d4c13b78e 100644
--- a/lib/mastodon/cli/settings.rb
+++ b/lib/mastodon/cli/settings.rb
@@ -1,15 +1,9 @@
 # frozen_string_literal: true
 
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class Registrations < Thor
-    def self.exit_on_failure?
-      true
-    end
-
+  class Registrations < Base
     desc 'open', 'Open registrations'
     def open
       Setting.registrations_mode = 'open'
@@ -37,7 +31,7 @@ module Mastodon::CLI
     end
   end
 
-  class Settings < Thor
+  class Settings < Base
     desc 'registrations SUBCOMMAND ...ARGS', 'Manage state of registrations'
     subcommand 'registrations', Registrations
   end
diff --git a/lib/mastodon/cli/statuses.rb b/lib/mastodon/cli/statuses.rb
index e5eb759608..bd5b047077 100644
--- a/lib/mastodon/cli/statuses.rb
+++ b/lib/mastodon/cli/statuses.rb
@@ -1,18 +1,11 @@
 # frozen_string_literal: true
 
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class Statuses < Thor
-    include Helper
+  class Statuses < Base
     include ActionView::Helpers::NumberHelper
 
-    def self.exit_on_failure?
-      true
-    end
-
     option :days, type: :numeric, default: 90
     option :batch_size, type: :numeric, default: 1_000, aliases: [:b], desc: 'Number of records in each batch'
     option :continue, type: :boolean, default: false, desc: 'If remove is not completed, execute from the previous continuation'
diff --git a/lib/mastodon/cli/upgrade.rb b/lib/mastodon/cli/upgrade.rb
index f20fa4cdf4..e5c86b3d73 100644
--- a/lib/mastodon/cli/upgrade.rb
+++ b/lib/mastodon/cli/upgrade.rb
@@ -1,17 +1,9 @@
 # frozen_string_literal: true
 
-require_relative '../../../config/boot'
-require_relative '../../../config/environment'
-require_relative 'helper'
+require_relative 'base'
 
 module Mastodon::CLI
-  class Upgrade < Thor
-    include Helper
-
-    def self.exit_on_failure?
-      true
-    end
-
+  class Upgrade < Base
     CURRENT_STORAGE_SCHEMA_VERSION = 1
 
     option :dry_run, type: :boolean, default: false
diff --git a/spec/lib/mastodon/cli/accounts_spec.rb b/spec/lib/mastodon/cli/accounts_spec.rb
new file mode 100644
index 0000000000..25f1311d40
--- /dev/null
+++ b/spec/lib/mastodon/cli/accounts_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/accounts'
+
+describe Mastodon::CLI::Accounts do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end
diff --git a/spec/lib/mastodon/cli/cache_spec.rb b/spec/lib/mastodon/cli/cache_spec.rb
new file mode 100644
index 0000000000..f101bc200f
--- /dev/null
+++ b/spec/lib/mastodon/cli/cache_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/cache'
+
+describe Mastodon::CLI::Cache do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end
diff --git a/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb b/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb
new file mode 100644
index 0000000000..fb481e8a82
--- /dev/null
+++ b/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/canonical_email_blocks'
+
+describe Mastodon::CLI::CanonicalEmailBlocks do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end
diff --git a/spec/lib/mastodon/cli/domains_spec.rb b/spec/lib/mastodon/cli/domains_spec.rb
new file mode 100644
index 0000000000..ea58845c00
--- /dev/null
+++ b/spec/lib/mastodon/cli/domains_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/domains'
+
+describe Mastodon::CLI::Domains do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end
diff --git a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb
new file mode 100644
index 0000000000..333ae3f2b7
--- /dev/null
+++ b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/email_domain_blocks'
+
+describe Mastodon::CLI::EmailDomainBlocks do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end
diff --git a/spec/lib/mastodon/cli/emoji_spec.rb b/spec/lib/mastodon/cli/emoji_spec.rb
new file mode 100644
index 0000000000..9b58653729
--- /dev/null
+++ b/spec/lib/mastodon/cli/emoji_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/emoji'
+
+describe Mastodon::CLI::Emoji do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end
diff --git a/spec/lib/mastodon/cli/feeds_spec.rb b/spec/lib/mastodon/cli/feeds_spec.rb
new file mode 100644
index 0000000000..4e1e214eff
--- /dev/null
+++ b/spec/lib/mastodon/cli/feeds_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/feeds'
+
+describe Mastodon::CLI::Feeds do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end
diff --git a/spec/lib/mastodon/cli/ip_blocks_spec.rb b/spec/lib/mastodon/cli/ip_blocks_spec.rb
index e7639d9aaf..e192679a59 100644
--- a/spec/lib/mastodon/cli/ip_blocks_spec.rb
+++ b/spec/lib/mastodon/cli/ip_blocks_spec.rb
@@ -3,9 +3,15 @@
 require 'rails_helper'
 require 'mastodon/cli/ip_blocks'
 
-RSpec.describe Mastodon::CLI::IpBlocks do
+describe Mastodon::CLI::IpBlocks do
   let(:cli) { described_class.new }
 
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+
   describe '#add' do
     let(:ip_list) do
       [
diff --git a/spec/lib/mastodon/cli/main_spec.rb b/spec/lib/mastodon/cli/main_spec.rb
index 105c4ec371..e3709afe37 100644
--- a/spec/lib/mastodon/cli/main_spec.rb
+++ b/spec/lib/mastodon/cli/main_spec.rb
@@ -4,6 +4,12 @@ require 'rails_helper'
 require 'mastodon/cli/main'
 
 describe Mastodon::CLI::Main do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+
   describe 'version' do
     it 'returns the Mastodon version' do
       expect { described_class.new.invoke(:version) }.to output(
diff --git a/spec/lib/mastodon/cli/maintenance_spec.rb b/spec/lib/mastodon/cli/maintenance_spec.rb
new file mode 100644
index 0000000000..12cd9ca8a6
--- /dev/null
+++ b/spec/lib/mastodon/cli/maintenance_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/maintenance'
+
+describe Mastodon::CLI::Maintenance do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end
diff --git a/spec/lib/mastodon/cli/media_spec.rb b/spec/lib/mastodon/cli/media_spec.rb
new file mode 100644
index 0000000000..29f7d424a9
--- /dev/null
+++ b/spec/lib/mastodon/cli/media_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/media'
+
+describe Mastodon::CLI::Media do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end
diff --git a/spec/lib/mastodon/cli/preview_cards_spec.rb b/spec/lib/mastodon/cli/preview_cards_spec.rb
new file mode 100644
index 0000000000..b4b018b3be
--- /dev/null
+++ b/spec/lib/mastodon/cli/preview_cards_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/preview_cards'
+
+describe Mastodon::CLI::PreviewCards do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end
diff --git a/spec/lib/mastodon/cli/search_spec.rb b/spec/lib/mastodon/cli/search_spec.rb
new file mode 100644
index 0000000000..d5cae5bf49
--- /dev/null
+++ b/spec/lib/mastodon/cli/search_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/search'
+
+describe Mastodon::CLI::Search do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end
diff --git a/spec/lib/mastodon/cli/settings_spec.rb b/spec/lib/mastodon/cli/settings_spec.rb
index 01f0775628..ae58e74e56 100644
--- a/spec/lib/mastodon/cli/settings_spec.rb
+++ b/spec/lib/mastodon/cli/settings_spec.rb
@@ -3,7 +3,13 @@
 require 'rails_helper'
 require 'mastodon/cli/settings'
 
-RSpec.describe Mastodon::CLI::Settings do
+describe Mastodon::CLI::Settings do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+
   describe 'subcommand "registrations"' do
     let(:cli) { Mastodon::CLI::Registrations.new }
 
diff --git a/spec/lib/mastodon/cli/statuses_spec.rb b/spec/lib/mastodon/cli/statuses_spec.rb
new file mode 100644
index 0000000000..2430a88416
--- /dev/null
+++ b/spec/lib/mastodon/cli/statuses_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/statuses'
+
+describe Mastodon::CLI::Statuses do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end
diff --git a/spec/lib/mastodon/cli/upgrade_spec.rb b/spec/lib/mastodon/cli/upgrade_spec.rb
new file mode 100644
index 0000000000..9e0ab9d06e
--- /dev/null
+++ b/spec/lib/mastodon/cli/upgrade_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'mastodon/cli/upgrade'
+
+describe Mastodon::CLI::Upgrade do
+  describe '.exit_on_failure?' do
+    it 'returns true' do
+      expect(described_class.exit_on_failure?).to be true
+    end
+  end
+end