diff --git a/README.md b/README.md index d47c3303..f16e74e5 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,19 @@ Join us on Discord: https://discord.gg/YgHVT7GCXS ## Installation -Install MRSK globally with `gem install mrsk`. Then, inside your app directory, run `mrsk init` (or `mrsk init --bundle` within Rails apps where you want a bin/mrsk binstub). Now edit the new file `config/deploy.yml`. It could look as simple as this: +If you have a Ruby environment available, you can install MRSK globally with: + +```sh +gem install mrsk +``` + +...otherwise, you can run a dockerized version via an alias (add this to your ${SHELL}rc to simplify re-use): + +```sh +alias mrsk='docker run --rm -it -v $HOME/.ssh:/root/.ssh -v /var/run/docker.sock:/var/run/docker.sock -v ${PWD}/:/workdir ghcr.io/mrsked/mrsk' +``` + +Then, inside your app directory, run `mrsk init` (or `mrsk init --bundle` within Rails apps where you want a bin/mrsk binstub). Now edit the new file `config/deploy.yml`. It could look as simple as this: ```yaml service: hey @@ -36,7 +48,7 @@ mrsk deploy This will: 1. Connect to the servers over SSH (using root by default, authenticated by your ssh key) -2. Install Docker on any server that might be missing it (using apt-get) +2. Install Docker on any server that might be missing it (using apt-get): root access is needed via ssh for this. 3. Log into the registry both locally and remotely 4. Build the image using the standard Dockerfile in the root of the application. 5. Push the image to the registry. diff --git a/lib/mrsk/cli/app.rb b/lib/mrsk/cli/app.rb index 0898a509..f009d5f7 100644 --- a/lib/mrsk/cli/app.rb +++ b/lib/mrsk/cli/app.rb @@ -2,7 +2,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base desc "boot", "Boot app on servers (or reboot app if already running)" def boot say "Get most recent version available as an image...", :magenta unless options[:version] - using_version(options[:version] || most_recent_version_available) do |version| + using_version(version_or_latest) do |version| say "Start container with version #{version} using a #{MRSK.config.readiness_delay}s readiness delay (or reboot if already running)...", :magenta cli = self @@ -70,7 +70,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base when options[:interactive] say "Get most recent version available as an image...", :magenta unless options[:version] - using_version(options[:version] || most_recent_version_available) do |version| + using_version(version_or_latest) do |version| say "Launching interactive command with version #{version} via SSH from new container on #{MRSK.primary_host}...", :magenta run_locally { exec MRSK.app.execute_in_new_container_over_ssh(cmd, host: MRSK.primary_host) } end @@ -88,7 +88,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base else say "Get most recent version available as an image...", :magenta unless options[:version] - using_version(options[:version] || most_recent_version_available) do |version| + using_version(version_or_latest) do |version| say "Launching command with version #{version} from new container...", :magenta on(MRSK.hosts) do |host| execute *MRSK.auditor.record("Executed cmd '#{cmd}' on app version #{version}"), verbosity: :debug @@ -189,20 +189,13 @@ class Mrsk::Cli::App < Mrsk::Cli::Base end end - def most_recent_version_available(host: MRSK.primary_host) - version = nil - on(host) { version = capture_with_info(*MRSK.app.most_recent_version_from_available_images).strip } - - if version == "" - raise "Most recent image available was not tagged with a version (returned )" - else - version.presence - end - end - def current_running_version(host: MRSK.primary_host) version = nil on(host) { version = capture_with_info(*MRSK.app.current_running_version).strip } version.presence end + + def version_or_latest + options[:version] || "latest" + end end diff --git a/lib/mrsk/cli/main.rb b/lib/mrsk/cli/main.rb index eb441d30..4a3e16bd 100644 --- a/lib/mrsk/cli/main.rb +++ b/lib/mrsk/cli/main.rb @@ -11,7 +11,7 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base desc "deploy", "Deploy app to servers" option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push" def deploy - invoke_options = options.without(:skip_push) + invoke_options = deploy_options runtime = print_runtime do say "Ensure curl and Docker are installed...", :magenta @@ -46,7 +46,7 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base desc "redeploy", "Deploy app to servers without bootstrapping servers, starting Traefik, pruning, and registry login" option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push" def redeploy - invoke_options = options.without(:skip_push) + invoke_options = deploy_options runtime = print_runtime do if options[:skip_push] @@ -207,6 +207,10 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base Array(container_names).include?(container_name) end + def deploy_options + { "version" => MRSK.config.version }.merge(options.without("skip_push")) + end + def service_version(version = MRSK.config.abbreviated_version) [ MRSK.config.service, version ].compact.join("@") end diff --git a/lib/mrsk/commands/accessory.rb b/lib/mrsk/commands/accessory.rb index d3d3215d..3208424c 100644 --- a/lib/mrsk/commands/accessory.rb +++ b/lib/mrsk/commands/accessory.rb @@ -100,7 +100,7 @@ class Mrsk::Commands::Accessory < Mrsk::Commands::Base end def remove_image - docker :image, :prune, "--all", "--force", *service_filter + docker :image, :rm, "--force", image end private diff --git a/lib/mrsk/commands/app.rb b/lib/mrsk/commands/app.rb index 82ea7986..8234f24d 100644 --- a/lib/mrsk/commands/app.rb +++ b/lib/mrsk/commands/app.rb @@ -87,19 +87,6 @@ class Mrsk::Commands::App < Mrsk::Commands::Base "tail -n 1" end - def most_recent_version_from_available_images - pipe \ - docker(:image, :ls, "--format", '"{{.Tag}}"', config.repository), - "head -n 1" - end - - def all_versions_from_available_containers - pipe \ - docker(:image, :ls, "--format", '"{{.Tag}}"', config.repository), - "head -n 1" - end - - def list_containers docker :container, :ls, "--all", *filter_args end diff --git a/lib/mrsk/commands/builder/base.rb b/lib/mrsk/commands/builder/base.rb index 91276260..448ecca4 100644 --- a/lib/mrsk/commands/builder/base.rb +++ b/lib/mrsk/commands/builder/base.rb @@ -7,6 +7,7 @@ class Mrsk::Commands::Builder::Base < Mrsk::Commands::Base def pull docker :pull, config.absolute_image + docker :pull, config.latest_image end def build_options diff --git a/test/cli/accessory_test.rb b/test/cli/accessory_test.rb index 28fadc7e..a2e4d73d 100644 --- a/test/cli/accessory_test.rb +++ b/test/cli/accessory_test.rb @@ -126,7 +126,7 @@ class CliAccessoryTest < CliTestCase end test "remove_image" do - assert_match "docker image prune --all --force --filter label=service=app-mysql", run_command("remove_image", "mysql") + assert_match "docker image rm --force mysql", run_command("remove_image", "mysql") end test "remove_service_directory" do diff --git a/test/cli/app_test.rb b/test/cli/app_test.rb index 36fc0691..b2b6786a 100644 --- a/test/cli/app_test.rb +++ b/test/cli/app_test.rb @@ -28,9 +28,8 @@ class CliAppTest < CliTestCase .returns([ :docker, :run ]) run_command("boot").tap do |output| - assert_match "Rebooting container with same version 999 already deployed", output # Can't start what's already running - assert_match "docker container ls --all --filter name=app-999 --quiet | xargs docker container rm", output # Stop old running - assert_match "docker container ls --all --filter name=app-999 --quiet | xargs docker container rm", output # Remove old container + assert_match "Rebooting container with same version latest already deployed", output # Can't start what's already running + assert_match "docker container ls --all --filter name=app-latest --quiet | xargs docker container rm", output # Remove old container assert_match "docker run", output # Start new container end ensure diff --git a/test/cli/build_test.rb b/test/cli/build_test.rb index 44802549..d721373b 100644 --- a/test/cli/build_test.rb +++ b/test/cli/build_test.rb @@ -29,7 +29,7 @@ class CliBuildTest < CliTestCase test "pull" do run_command("pull").tap do |output| assert_match /docker image rm --force dhh\/app:999/, output - assert_match /docker pull dhh\/app:999/, output + assert_match /docker pull dhh\/app:latest/, output end end diff --git a/test/cli/main_test.rb b/test/cli/main_test.rb index 151fa7b8..d4aa3d82 100644 --- a/test/cli/main_test.rb +++ b/test/cli/main_test.rb @@ -10,7 +10,7 @@ class CliMainTest < CliTestCase end test "deploy" do - invoke_options = { "config_file" => "test/fixtures/deploy_with_accessories.yml", "skip_broadcast" => false, "skip_push" => false } + invoke_options = { "config_file" => "test/fixtures/deploy_with_accessories.yml", "skip_broadcast" => false, "version" => "999" } Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:server:bootstrap", [], invoke_options) Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:registry:login", [], invoke_options) @@ -31,7 +31,7 @@ class CliMainTest < CliTestCase end test "deploy with skip_push" do - invoke_options = { "config_file" => "test/fixtures/deploy_with_accessories.yml", "skip_broadcast" => false, "skip_push" => true } + invoke_options = { "config_file" => "test/fixtures/deploy_with_accessories.yml", "skip_broadcast" => false, "version" => "999" } Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:server:bootstrap", [], invoke_options) Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:registry:login", [], invoke_options) @@ -52,7 +52,7 @@ class CliMainTest < CliTestCase end test "redeploy" do - invoke_options = { "config_file" => "test/fixtures/deploy_with_accessories.yml", "skip_broadcast" => false, "skip_push" => false} + invoke_options = { "config_file" => "test/fixtures/deploy_with_accessories.yml", "skip_broadcast" => false, "version" => "999" } Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:build:deliver", [], invoke_options) Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:healthcheck:perform", [], invoke_options) @@ -65,7 +65,7 @@ class CliMainTest < CliTestCase end test "redeploy with skip_push" do - invoke_options = { "config_file" => "test/fixtures/deploy_with_accessories.yml", "skip_broadcast" => false, "skip_push" => true } + invoke_options = { "config_file" => "test/fixtures/deploy_with_accessories.yml", "skip_broadcast" => false, "version" => "999" } Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:build:pull", [], invoke_options) Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:healthcheck:perform", [], invoke_options) @@ -235,12 +235,12 @@ class CliMainTest < CliTestCase assert_match /docker container stop app-mysql/, output assert_match /docker container prune --force --filter label=service=app-mysql/, output - assert_match /docker image prune --all --force --filter label=service=app-mysql/, output + assert_match /docker image rm --force mysql/, output assert_match /rm -rf app-mysql/, output assert_match /docker container stop app-redis/, output assert_match /docker container prune --force --filter label=service=app-redis/, output - assert_match /docker image prune --all --force --filter label=service=app-redis/, output + assert_match /docker image rm --force redis/, output assert_match /rm -rf app-redis/, output assert_match /docker logout/, output diff --git a/test/commands/accessory_test.rb b/test/commands/accessory_test.rb index 71a3058b..a7931a90 100644 --- a/test/commands/accessory_test.rb +++ b/test/commands/accessory_test.rb @@ -140,7 +140,7 @@ class CommandsAccessoryTest < ActiveSupport::TestCase test "remove image" do assert_equal \ - "docker image prune --all --force --filter label=service=app-mysql", + "docker image rm --force private.registry/mysql:8.0", new_command(:mysql).remove_image.join(" ") end diff --git a/test/commands/app_test.rb b/test/commands/app_test.rb index 2904e7dc..1198370a 100644 --- a/test/commands/app_test.rb +++ b/test/commands/app_test.rb @@ -197,12 +197,6 @@ class CommandsAppTest < ActiveSupport::TestCase new_command.current_running_version.join(" ") end - test "most_recent_version_from_available_images" do - assert_equal \ - "docker image ls --format \"{{.Tag}}\" dhh/app | head -n 1", - new_command.most_recent_version_from_available_images.join(" ") - end - test "list_containers" do assert_equal \ "docker container ls --all --filter label=service=app",