Load with Zeitwerk

This commit is contained in:
Xavier Noria
2023-02-03 22:45:12 +01:00
parent 94b28a1b29
commit 539752e9bd
38 changed files with 25 additions and 100 deletions

View File

@@ -6,6 +6,7 @@ PATH
dotenv (~> 2.8) dotenv (~> 2.8)
sshkit (~> 1.21) sshkit (~> 1.21)
thor (~> 1.2) thor (~> 1.2)
zeitwerk (~> 2.5)
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
@@ -91,6 +92,7 @@ PLATFORMS
arm64-darwin-22 arm64-darwin-22
x86_64-darwin-20 x86_64-darwin-20
x86_64-darwin-21 x86_64-darwin-21
x86_64-darwin-22
x86_64-linux x86_64-linux
DEPENDENCIES DEPENDENCIES

View File

@@ -4,7 +4,7 @@
Thread.report_on_exception = false Thread.report_on_exception = false
require "dotenv/load" require "dotenv/load"
require "mrsk/cli" require "mrsk"
begin begin
Mrsk::Cli::Main.start(ARGV) Mrsk::Cli::Main.start(ARGV)

View File

@@ -1,5 +1,9 @@
module Mrsk module Mrsk
end end
require "mrsk/version" require "zeitwerk"
require "mrsk/commander"
loader = Zeitwerk::Loader.for_gem
loader.ignore("#{__dir__}/mrsk/sshkit_with_ext.rb")
loader.setup
loader.eager_load # We need all commands loaded.

View File

@@ -1,9 +1,5 @@
require "mrsk"
module Mrsk::Cli module Mrsk::Cli
end end
# SSHKit uses instance eval, so we need a global const for ergonomics # SSHKit uses instance eval, so we need a global const for ergonomics
MRSK = Mrsk::Commander.new MRSK = Mrsk::Commander.new
require "mrsk/cli/main"

View File

@@ -1,5 +1,3 @@
require "mrsk/cli/base"
class Mrsk::Cli::Accessory < Mrsk::Cli::Base class Mrsk::Cli::Accessory < Mrsk::Cli::Base
desc "boot [NAME]", "Boot accessory service on host (use NAME=all to boot all accessories)" desc "boot [NAME]", "Boot accessory service on host (use NAME=all to boot all accessories)"
def boot(name) def boot(name)

View File

@@ -1,5 +1,3 @@
require "mrsk/cli/base"
class Mrsk::Cli::App < Mrsk::Cli::Base class Mrsk::Cli::App < Mrsk::Cli::Base
desc "boot", "Boot app on servers (or reboot app if already running)" desc "boot", "Boot app on servers (or reboot app if already running)"
def boot def boot
@@ -40,7 +38,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
execute *MRSK.app.start, raise_on_non_zero_exit: false execute *MRSK.app.start, raise_on_non_zero_exit: false
end end
end end
desc "stop", "Stop app on servers" desc "stop", "Stop app on servers"
def stop def stop
on(MRSK.hosts) do on(MRSK.hosts) do
@@ -48,12 +46,12 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
execute *MRSK.app.stop, raise_on_non_zero_exit: false execute *MRSK.app.stop, raise_on_non_zero_exit: false
end end
end end
desc "details", "Display details about app containers" desc "details", "Display details about app containers"
def details def details
on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.info) } on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.info) }
end end
desc "exec [CMD]", "Execute a custom command on servers" desc "exec [CMD]", "Execute a custom command on servers"
option :interactive, aliases: "-i", type: :boolean, default: false, desc: "Execute command over ssh for an interactive shell (use for console/bash)" option :interactive, aliases: "-i", type: :boolean, default: false, desc: "Execute command over ssh for an interactive shell (use for console/bash)"
option :reuse, type: :boolean, default: false, desc: "Reuse currently running container instead of starting a new one" option :reuse, type: :boolean, default: false, desc: "Reuse currently running container instead of starting a new one"
@@ -110,7 +108,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
def current def current
on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.current_container_id) } on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.current_container_id) }
end end
desc "logs", "Show lines from app on servers" desc "logs", "Show lines from app on servers"
option :since, aliases: "-s", desc: "Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)" option :since, aliases: "-s", desc: "Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)"
option :lines, type: :numeric, aliases: "-n", desc: "Number of log lines to pull from each server" option :lines, type: :numeric, aliases: "-n", desc: "Number of log lines to pull from each server"

View File

@@ -1,5 +1,3 @@
require "mrsk/cli/base"
class Mrsk::Cli::Build < Mrsk::Cli::Base class Mrsk::Cli::Build < Mrsk::Cli::Base
desc "deliver", "Deliver a newly built app image to servers" desc "deliver", "Deliver a newly built app image to servers"
def deliver def deliver
@@ -11,7 +9,7 @@ class Mrsk::Cli::Build < Mrsk::Cli::Base
def push def push
cli = self cli = self
run_locally do run_locally do
begin begin
MRSK.with_verbosity(:debug) { execute *MRSK.builder.push } MRSK.with_verbosity(:debug) { execute *MRSK.builder.push }
rescue SSHKit::Command::Failed => e rescue SSHKit::Command::Failed => e

View File

@@ -1,13 +1,3 @@
require "mrsk/cli/base"
require "mrsk/cli/accessory"
require "mrsk/cli/app"
require "mrsk/cli/build"
require "mrsk/cli/prune"
require "mrsk/cli/registry"
require "mrsk/cli/server"
require "mrsk/cli/traefik"
class Mrsk::Cli::Main < Mrsk::Cli::Base class Mrsk::Cli::Main < Mrsk::Cli::Base
desc "setup", "Setup all accessories and deploy the app to servers" desc "setup", "Setup all accessories and deploy the app to servers"
def setup def setup

View File

@@ -1,5 +1,3 @@
require "mrsk/cli/base"
class Mrsk::Cli::Prune < Mrsk::Cli::Base class Mrsk::Cli::Prune < Mrsk::Cli::Base
desc "all", "Prune unused images and stopped containers" desc "all", "Prune unused images and stopped containers"
def all def all

View File

@@ -1,5 +1,3 @@
require "mrsk/cli/base"
class Mrsk::Cli::Registry < Mrsk::Cli::Base class Mrsk::Cli::Registry < Mrsk::Cli::Base
desc "login", "Login to the registry locally and remotely" desc "login", "Login to the registry locally and remotely"
def login def login

View File

@@ -1,5 +1,3 @@
require "mrsk/cli/base"
class Mrsk::Cli::Server < Mrsk::Cli::Base class Mrsk::Cli::Server < Mrsk::Cli::Base
desc "bootstrap", "Ensure Docker is installed on the servers" desc "bootstrap", "Ensure Docker is installed on the servers"
def bootstrap def bootstrap

View File

@@ -1,5 +1,3 @@
require "mrsk/cli/base"
class Mrsk::Cli::Traefik < Mrsk::Cli::Base class Mrsk::Cli::Traefik < Mrsk::Cli::Base
desc "boot", "Boot Traefik on servers" desc "boot", "Boot Traefik on servers"
def boot def boot

View File

@@ -1,14 +1,5 @@
require "active_support/core_ext/enumerable" require "active_support/core_ext/enumerable"
require "mrsk/configuration"
require "mrsk/commands/accessory"
require "mrsk/commands/app"
require "mrsk/commands/auditor"
require "mrsk/commands/builder"
require "mrsk/commands/prune"
require "mrsk/commands/traefik"
require "mrsk/commands/registry"
class Mrsk::Commander class Mrsk::Commander
attr_accessor :config_file, :destination, :verbosity, :version attr_accessor :config_file, :destination, :verbosity, :version
@@ -83,7 +74,7 @@ class Mrsk::Commander
end end
def with_verbosity(level) def with_verbosity(level)
old_level = SSHKit.config.output_verbosity old_level = SSHKit.config.output_verbosity
SSHKit.config.output_verbosity = level SSHKit.config.output_verbosity = level
yield yield

View File

@@ -1,5 +1,3 @@
require "mrsk/commands/base"
class Mrsk::Commands::Accessory < Mrsk::Commands::Base class Mrsk::Commands::Accessory < Mrsk::Commands::Base
attr_reader :accessory_config attr_reader :accessory_config
delegate :service_name, :image, :host, :port, :files, :directories, :env_args, :volume_args, :label_args, to: :accessory_config delegate :service_name, :image, :host, :port, :files, :directories, :env_args, :volume_args, :label_args, to: :accessory_config
@@ -10,7 +8,7 @@ class Mrsk::Commands::Accessory < Mrsk::Commands::Base
end end
def run def run
docker :run, docker :run,
"--name", service_name, "--name", service_name,
"-d", "-d",
"--restart", "unless-stopped", "--restart", "unless-stopped",

View File

@@ -1,5 +1,3 @@
require "mrsk/commands/base"
class Mrsk::Commands::App < Mrsk::Commands::Base class Mrsk::Commands::App < Mrsk::Commands::Base
def run(role: :web) def run(role: :web)
role = config.role(role) role = config.role(role)

View File

@@ -1,5 +1,4 @@
require "active_support/core_ext/time/conversions" require "active_support/core_ext/time/conversions"
require "mrsk/commands/base"
class Mrsk::Commands::Auditor < Mrsk::Commands::Base class Mrsk::Commands::Auditor < Mrsk::Commands::Base
def record(line) def record(line)

View File

@@ -1,5 +1,3 @@
require "mrsk/commands/base"
class Mrsk::Commands::Builder < Mrsk::Commands::Base class Mrsk::Commands::Builder < Mrsk::Commands::Base
delegate :create, :remove, :push, :pull, :info, to: :target delegate :create, :remove, :push, :pull, :info, to: :target
@@ -36,8 +34,3 @@ class Mrsk::Commands::Builder < Mrsk::Commands::Base
@multiarch_remote ||= Mrsk::Commands::Builder::Multiarch::Remote.new(config) @multiarch_remote ||= Mrsk::Commands::Builder::Multiarch::Remote.new(config)
end end
end end
require "mrsk/commands/builder/native"
require "mrsk/commands/builder/native/remote"
require "mrsk/commands/builder/multiarch"
require "mrsk/commands/builder/multiarch/remote"

View File

@@ -1,5 +1,3 @@
require "mrsk/commands/base"
class Mrsk::Commands::Builder::Base < Mrsk::Commands::Base class Mrsk::Commands::Builder::Base < Mrsk::Commands::Base
delegate :argumentize, to: Mrsk::Utils delegate :argumentize, to: Mrsk::Utils

View File

@@ -1,5 +1,3 @@
require "mrsk/commands/builder/base"
class Mrsk::Commands::Builder::Multiarch < Mrsk::Commands::Builder::Base class Mrsk::Commands::Builder::Multiarch < Mrsk::Commands::Builder::Base
def create def create
docker :buildx, :create, "--use", "--name", builder_name docker :buildx, :create, "--use", "--name", builder_name

View File

@@ -1,5 +1,3 @@
require "mrsk/commands/builder/multiarch"
class Mrsk::Commands::Builder::Multiarch::Remote < Mrsk::Commands::Builder::Multiarch class Mrsk::Commands::Builder::Multiarch::Remote < Mrsk::Commands::Builder::Multiarch
def create def create
combine \ combine \

View File

@@ -1,5 +1,3 @@
require "mrsk/commands/builder/base"
class Mrsk::Commands::Builder::Native < Mrsk::Commands::Builder::Base class Mrsk::Commands::Builder::Native < Mrsk::Commands::Builder::Base
def create def create
# No-op on native # No-op on native

View File

@@ -1,5 +1,3 @@
require "mrsk/commands/builder/native"
class Mrsk::Commands::Builder::Native::Remote < Mrsk::Commands::Builder::Native class Mrsk::Commands::Builder::Native::Remote < Mrsk::Commands::Builder::Native
def create def create
chain \ chain \

View File

@@ -1,4 +1,3 @@
require "mrsk/commands/base"
require "active_support/duration" require "active_support/duration"
require "active_support/core_ext/numeric/time" require "active_support/core_ext/numeric/time"

View File

@@ -1,5 +1,3 @@
require "mrsk/commands/base"
class Mrsk::Commands::Registry < Mrsk::Commands::Base class Mrsk::Commands::Registry < Mrsk::Commands::Base
delegate :registry, to: :config delegate :registry, to: :config

View File

@@ -1,5 +1,3 @@
require "mrsk/commands/base"
class Mrsk::Commands::Traefik < Mrsk::Commands::Base class Mrsk::Commands::Traefik < Mrsk::Commands::Base
def run def run
docker :run, "--name traefik", docker :run, "--name traefik",

View File

@@ -3,7 +3,6 @@ require "active_support/core_ext/string/inquiry"
require "active_support/core_ext/module/delegation" require "active_support/core_ext/module/delegation"
require "pathname" require "pathname"
require "erb" require "erb"
require "mrsk/utils"
class Mrsk::Configuration class Mrsk::Configuration
delegate :service, :image, :servers, :env, :labels, :registry, :builder, to: :raw_config, allow_nil: true delegate :service, :image, :servers, :env, :labels, :registry, :builder, to: :raw_config, allow_nil: true
@@ -171,6 +170,3 @@ class Mrsk::Configuration
raw_config.servers.is_a?(Array) ? [ "web" ] : raw_config.servers.keys.sort raw_config.servers.is_a?(Array) ? [ "web" ] : raw_config.servers.keys.sort
end end
end end
require "mrsk/configuration/role"
require "mrsk/configuration/accessory"

View File

@@ -16,4 +16,5 @@ Gem::Specification.new do |spec|
spec.add_dependency "sshkit", "~> 1.21" spec.add_dependency "sshkit", "~> 1.21"
spec.add_dependency "thor", "~> 1.2" spec.add_dependency "thor", "~> 1.2"
spec.add_dependency "dotenv", "~> 2.8" spec.add_dependency "dotenv", "~> 2.8"
spec.add_dependency "zeitwerk", "~> 2.5"
end end

View File

@@ -1,6 +1,5 @@
require "test_helper" require "test_helper"
require "active_support/testing/stream" require "active_support/testing/stream"
require "mrsk/cli"
class CliTestCase < ActiveSupport::TestCase class CliTestCase < ActiveSupport::TestCase
include ActiveSupport::Testing::Stream include ActiveSupport::Testing::Stream

View File

@@ -1,5 +1,4 @@
require "test_helper" require "test_helper"
require "mrsk/commander"
class CommanderTest < ActiveSupport::TestCase class CommanderTest < ActiveSupport::TestCase
setup do setup do

View File

@@ -1,10 +1,8 @@
require "test_helper" require "test_helper"
require "mrsk/configuration"
require "mrsk/commands/accessory"
class CommandsAccessoryTest < ActiveSupport::TestCase class CommandsAccessoryTest < ActiveSupport::TestCase
setup do setup do
@config = { @config = {
service: "app", image: "dhh/app", registry: { "username" => "dhh", "password" => "secret" }, service: "app", image: "dhh/app", registry: { "username" => "dhh", "password" => "secret" },
servers: [ "1.1.1.1" ], servers: [ "1.1.1.1" ],
accessories: { accessories: {

View File

@@ -1,6 +1,4 @@
require "test_helper" require "test_helper"
require "mrsk/configuration"
require "mrsk/commands/app"
class CommandsAppTest < ActiveSupport::TestCase class CommandsAppTest < ActiveSupport::TestCase
setup do setup do

View File

@@ -1,6 +1,4 @@
require "test_helper" require "test_helper"
require "mrsk/configuration"
require "mrsk/commands/builder"
class CommandsBuilderTest < ActiveSupport::TestCase class CommandsBuilderTest < ActiveSupport::TestCase
setup do setup do

View File

@@ -1,10 +1,8 @@
require "test_helper" require "test_helper"
require "mrsk/configuration"
require "mrsk/commands/registry"
class CommandsRegistryTest < ActiveSupport::TestCase class CommandsRegistryTest < ActiveSupport::TestCase
setup do setup do
@config = { service: "app", @config = { service: "app",
image: "dhh/app", image: "dhh/app",
registry: { "username" => "dhh", registry: { "username" => "dhh",
"password" => "secret", "password" => "secret",

View File

@@ -1,6 +1,4 @@
require "test_helper" require "test_helper"
require "mrsk/configuration"
require "mrsk/commands/traefik"
class CommandsTraefikTest < ActiveSupport::TestCase class CommandsTraefikTest < ActiveSupport::TestCase
setup do setup do

View File

@@ -1,5 +1,4 @@
require "test_helper" require "test_helper"
require "mrsk/configuration"
class ConfigurationAccessoryTest < ActiveSupport::TestCase class ConfigurationAccessoryTest < ActiveSupport::TestCase
setup do setup do
@@ -66,7 +65,7 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase
test "missing host" do test "missing host" do
@deploy[:accessories]["mysql"]["host"] = nil @deploy[:accessories]["mysql"]["host"] = nil
@config = Mrsk::Configuration.new(@deploy) @config = Mrsk::Configuration.new(@deploy)
assert_raises(ArgumentError) do assert_raises(ArgumentError) do
@config.accessory(:mysql).host @config.accessory(:mysql).host
end end

View File

@@ -1,5 +1,4 @@
require "test_helper" require "test_helper"
require "mrsk/configuration"
class ConfigurationRoleTest < ActiveSupport::TestCase class ConfigurationRoleTest < ActiveSupport::TestCase
setup do setup do
@@ -63,7 +62,7 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
end end
test "default traefik label on non-web role" do test "default traefik label on non-web role" do
config = Mrsk::Configuration.new(@deploy_with_roles.tap { |c| config = Mrsk::Configuration.new(@deploy_with_roles.tap { |c|
c[:servers]["beta"] = { "traefik" => "true", "hosts" => [ "1.1.1.5" ] } c[:servers]["beta"] = { "traefik" => "true", "hosts" => [ "1.1.1.5" ] }
}) })
@@ -97,7 +96,7 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
ENV["REDIS_PASSWORD"] = "secret456" ENV["REDIS_PASSWORD"] = "secret456"
ENV["DB_PASSWORD"] = "secret123" ENV["DB_PASSWORD"] = "secret123"
assert_equal ["-e", "REDIS_PASSWORD=secret456", "-e", "DB_PASSWORD=secret123", "-e", "REDIS_URL=redis://a/b", "-e", "WEB_CONCURRENCY=4"], @config_with_roles.role(:workers).env_args assert_equal ["-e", "REDIS_PASSWORD=secret456", "-e", "DB_PASSWORD=secret123", "-e", "REDIS_URL=redis://a/b", "-e", "WEB_CONCURRENCY=4"], @config_with_roles.role(:workers).env_args
ensure ensure
ENV["REDIS_PASSWORD"] = nil ENV["REDIS_PASSWORD"] = nil
@@ -116,7 +115,7 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
} }
ENV["DB_PASSWORD"] = "secret123" ENV["DB_PASSWORD"] = "secret123"
assert_equal ["-e", "DB_PASSWORD=secret123", "-e", "REDIS_URL=redis://a/b", "-e", "WEB_CONCURRENCY=4"], @config_with_roles.role(:workers).env_args assert_equal ["-e", "DB_PASSWORD=secret123", "-e", "REDIS_URL=redis://a/b", "-e", "WEB_CONCURRENCY=4"], @config_with_roles.role(:workers).env_args
ensure ensure
ENV["DB_PASSWORD"] = nil ENV["DB_PASSWORD"] = nil
@@ -133,7 +132,7 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
} }
ENV["REDIS_PASSWORD"] = "secret456" ENV["REDIS_PASSWORD"] = "secret456"
assert_equal ["-e", "REDIS_PASSWORD=secret456", "-e", "REDIS_URL=redis://a/b", "-e", "WEB_CONCURRENCY=4"], @config_with_roles.role(:workers).env_args assert_equal ["-e", "REDIS_PASSWORD=secret456", "-e", "REDIS_URL=redis://a/b", "-e", "WEB_CONCURRENCY=4"], @config_with_roles.role(:workers).env_args
ensure ensure
ENV["REDIS_PASSWORD"] = nil ENV["REDIS_PASSWORD"] = nil

View File

@@ -1,5 +1,4 @@
require "test_helper" require "test_helper"
require "mrsk/configuration"
class ConfigurationTest < ActiveSupport::TestCase class ConfigurationTest < ActiveSupport::TestCase
setup do setup do

View File

@@ -5,6 +5,7 @@ require "debug"
require "mocha/minitest" # using #stubs that can alter returns require "mocha/minitest" # using #stubs that can alter returns
require "minitest/autorun" # using #stub that take args require "minitest/autorun" # using #stub that take args
require "sshkit" require "sshkit"
require "mrsk"
ActiveSupport::LogSubscriber.logger = ActiveSupport::Logger.new(STDOUT) if ENV["VERBOSE"] ActiveSupport::LogSubscriber.logger = ActiveSupport::Logger.new(STDOUT) if ENV["VERBOSE"]