mrsk 0.13.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +41 -0
- data/lib/mrsk/cli/accessory.rb +11 -11
- data/lib/mrsk/cli/app.rb +8 -8
- data/lib/mrsk/cli/base.rb +16 -16
- data/lib/mrsk/cli/build.rb +5 -5
- data/lib/mrsk/cli/main.rb +5 -5
- data/lib/mrsk/cli/prune.rb +3 -3
- data/lib/mrsk/cli/templates/sample_hooks/pre-deploy.sample +49 -22
- data/lib/mrsk/cli/traefik.rb +8 -8
- data/lib/mrsk/commands/base.rb +5 -1
- data/lib/mrsk/commands/builder/base.rb +12 -16
- data/lib/mrsk/commands/builder/multiarch/remote.rb +6 -14
- data/lib/mrsk/commands/builder/native/cached.rb +16 -0
- data/lib/mrsk/commands/builder/native/remote.rb +3 -11
- data/lib/mrsk/commands/builder/native.rb +2 -2
- data/lib/mrsk/commands/builder.rb +9 -3
- data/lib/mrsk/commands/traefik.rb +5 -3
- data/lib/mrsk/configuration/builder.rb +114 -0
- data/lib/mrsk/configuration.rb +24 -7
- data/lib/mrsk/version.rb +1 -1
- metadata +4 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 39d645ed2ca51ebf7edeaca7502b9b9d83456ad4fd11d5b905903de2ee76f189
         | 
| 4 | 
            +
              data.tar.gz: c8fe80b16c14e89fd333224b887968620a88741c32a8b7cb4ee1cf9c37c1dcd5
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: fa4264e442bc470b02ebd946b4667535b9e5e8795cf9cb22c311693f381a0a9671c67d16dd6f1ae6391e48b8e7b2be51fc49671bccd2610e3ec98afd75002a12
         | 
| 7 | 
            +
              data.tar.gz: 408f3500ff87847217b08f21c86a189b77e73f54d3b1a407a7e16a9f73fea20a883233cf8970f9f5fb6b6ebdcd69d3a47ec5006e42b7190cffd41c1c5b9bfb60
         | 
    
        data/README.md
    CHANGED
    
    | @@ -380,6 +380,16 @@ servers: | |
| 380 380 |  | 
| 381 381 | 
             
            That'll start the job containers with `docker run ... --cap-add --cpu-count 4 ...`.
         | 
| 382 382 |  | 
| 383 | 
            +
            ### Setting a minimum version
         | 
| 384 | 
            +
             | 
| 385 | 
            +
            You can set the minimum MRSK version with:
         | 
| 386 | 
            +
             | 
| 387 | 
            +
            ```yaml
         | 
| 388 | 
            +
            minimum_version: 0.13.3
         | 
| 389 | 
            +
            ```
         | 
| 390 | 
            +
             | 
| 391 | 
            +
            Note: versions <= 0.13.2 will ignore this setting.
         | 
| 392 | 
            +
             | 
| 383 393 | 
             
            ### Configuring logging
         | 
| 384 394 |  | 
| 385 395 | 
             
            You can configure the logging driver and options passed to Docker using `logging`:
         | 
| @@ -463,6 +473,37 @@ builder: | |
| 463 473 | 
             
              context: ".."
         | 
| 464 474 | 
             
            ```
         | 
| 465 475 |  | 
| 476 | 
            +
            ### Using multistage builder cache
         | 
| 477 | 
            +
             | 
| 478 | 
            +
            Docker multistage build cache can singlehandedly speed up your builds by a lot. Currently MRSK only supports using the GHA cache or the Registry cache:
         | 
| 479 | 
            +
             | 
| 480 | 
            +
            ```yaml
         | 
| 481 | 
            +
            # Using GHA cache
         | 
| 482 | 
            +
            builder:
         | 
| 483 | 
            +
              cache:
         | 
| 484 | 
            +
                type: gha
         | 
| 485 | 
            +
             | 
| 486 | 
            +
            # Using Registry cache
         | 
| 487 | 
            +
            builder:
         | 
| 488 | 
            +
              cache:
         | 
| 489 | 
            +
                type: registry
         | 
| 490 | 
            +
             | 
| 491 | 
            +
            # Using Registry cache with different cache image
         | 
| 492 | 
            +
            builder:
         | 
| 493 | 
            +
              cache:
         | 
| 494 | 
            +
                type: registry
         | 
| 495 | 
            +
                # default image name is <image>-build-cache
         | 
| 496 | 
            +
                image: application-cache-image
         | 
| 497 | 
            +
             | 
| 498 | 
            +
            # Using Registry cache with additinonal cache-to options
         | 
| 499 | 
            +
            builder:
         | 
| 500 | 
            +
              cache:
         | 
| 501 | 
            +
                type: registry
         | 
| 502 | 
            +
                options: mode=max,image-manifest=true,oci-mediatypes=true
         | 
| 503 | 
            +
            ```
         | 
| 504 | 
            +
             | 
| 505 | 
            +
            For further insights into build cache optimization, check out documentation on Docker's official website: https://docs.docker.com/build/cache/.
         | 
| 506 | 
            +
             | 
| 466 507 | 
             
            ### Using build secrets for new images
         | 
| 467 508 |  | 
| 468 509 | 
             
            Some images need a secret passed in during build time, like a GITHUB_TOKEN, to give access to private gem repositories. This can be done by having the secret in ENV, then referencing it in the builder configuration:
         | 
    
        data/lib/mrsk/cli/accessory.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            class Mrsk::Cli::Accessory < Mrsk::Cli::Base
         | 
| 2 2 | 
             
              desc "boot [NAME]", "Boot new accessory service on host (use NAME=all to boot all accessories)"
         | 
| 3 3 | 
             
              def boot(name)
         | 
| 4 | 
            -
                 | 
| 4 | 
            +
                mutating do
         | 
| 5 5 | 
             
                  if name == "all"
         | 
| 6 6 | 
             
                    MRSK.accessory_names.each { |accessory_name| boot(accessory_name) }
         | 
| 7 7 | 
             
                  else
         | 
| @@ -21,7 +21,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base | |
| 21 21 |  | 
| 22 22 | 
             
              desc "upload [NAME]", "Upload accessory files to host", hide: true
         | 
| 23 23 | 
             
              def upload(name)
         | 
| 24 | 
            -
                 | 
| 24 | 
            +
                mutating do
         | 
| 25 25 | 
             
                  with_accessory(name) do |accessory|
         | 
| 26 26 | 
             
                    on(accessory.hosts) do
         | 
| 27 27 | 
             
                      accessory.files.each do |(local, remote)|
         | 
| @@ -38,7 +38,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base | |
| 38 38 |  | 
| 39 39 | 
             
              desc "directories [NAME]", "Create accessory directories on host", hide: true
         | 
| 40 40 | 
             
              def directories(name)
         | 
| 41 | 
            -
                 | 
| 41 | 
            +
                mutating do
         | 
| 42 42 | 
             
                  with_accessory(name) do |accessory|
         | 
| 43 43 | 
             
                    on(accessory.hosts) do
         | 
| 44 44 | 
             
                      accessory.directories.keys.each do |host_path|
         | 
| @@ -51,7 +51,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base | |
| 51 51 |  | 
| 52 52 | 
             
              desc "reboot [NAME]", "Reboot existing accessory on host (stop container, remove container, start new container)"
         | 
| 53 53 | 
             
              def reboot(name)
         | 
| 54 | 
            -
                 | 
| 54 | 
            +
                mutating do
         | 
| 55 55 | 
             
                  with_accessory(name) do |accessory|
         | 
| 56 56 | 
             
                    stop(name)
         | 
| 57 57 | 
             
                    remove_container(name)
         | 
| @@ -62,7 +62,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base | |
| 62 62 |  | 
| 63 63 | 
             
              desc "start [NAME]", "Start existing accessory container on host"
         | 
| 64 64 | 
             
              def start(name)
         | 
| 65 | 
            -
                 | 
| 65 | 
            +
                mutating do
         | 
| 66 66 | 
             
                  with_accessory(name) do |accessory|
         | 
| 67 67 | 
             
                    on(accessory.hosts) do
         | 
| 68 68 | 
             
                      execute *MRSK.auditor.record("Started #{name} accessory"), verbosity: :debug
         | 
| @@ -74,7 +74,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base | |
| 74 74 |  | 
| 75 75 | 
             
              desc "stop [NAME]", "Stop existing accessory container on host"
         | 
| 76 76 | 
             
              def stop(name)
         | 
| 77 | 
            -
                 | 
| 77 | 
            +
                mutating do
         | 
| 78 78 | 
             
                  with_accessory(name) do |accessory|
         | 
| 79 79 | 
             
                    on(accessory.hosts) do
         | 
| 80 80 | 
             
                      execute *MRSK.auditor.record("Stopped #{name} accessory"), verbosity: :debug
         | 
| @@ -86,7 +86,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base | |
| 86 86 |  | 
| 87 87 | 
             
              desc "restart [NAME]", "Restart existing accessory container on host"
         | 
| 88 88 | 
             
              def restart(name)
         | 
| 89 | 
            -
                 | 
| 89 | 
            +
                mutating do
         | 
| 90 90 | 
             
                  with_accessory(name) do
         | 
| 91 91 | 
             
                    stop(name)
         | 
| 92 92 | 
             
                    start(name)
         | 
| @@ -165,7 +165,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base | |
| 165 165 | 
             
              desc "remove [NAME]", "Remove accessory container, image and data directory from host (use NAME=all to remove all accessories)"
         | 
| 166 166 | 
             
              option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
         | 
| 167 167 | 
             
              def remove(name)
         | 
| 168 | 
            -
                 | 
| 168 | 
            +
                mutating do
         | 
| 169 169 | 
             
                  if name == "all"
         | 
| 170 170 | 
             
                    MRSK.accessory_names.each { |accessory_name| remove(accessory_name) }
         | 
| 171 171 | 
             
                  else
         | 
| @@ -183,7 +183,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base | |
| 183 183 |  | 
| 184 184 | 
             
              desc "remove_container [NAME]", "Remove accessory container from host", hide: true
         | 
| 185 185 | 
             
              def remove_container(name)
         | 
| 186 | 
            -
                 | 
| 186 | 
            +
                mutating do
         | 
| 187 187 | 
             
                  with_accessory(name) do |accessory|
         | 
| 188 188 | 
             
                    on(accessory.hosts) do
         | 
| 189 189 | 
             
                      execute *MRSK.auditor.record("Remove #{name} accessory container"), verbosity: :debug
         | 
| @@ -195,7 +195,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base | |
| 195 195 |  | 
| 196 196 | 
             
              desc "remove_image [NAME]", "Remove accessory image from host", hide: true
         | 
| 197 197 | 
             
              def remove_image(name)
         | 
| 198 | 
            -
                 | 
| 198 | 
            +
                mutating do
         | 
| 199 199 | 
             
                  with_accessory(name) do |accessory|
         | 
| 200 200 | 
             
                    on(accessory.hosts) do
         | 
| 201 201 | 
             
                      execute *MRSK.auditor.record("Removed #{name} accessory image"), verbosity: :debug
         | 
| @@ -207,7 +207,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base | |
| 207 207 |  | 
| 208 208 | 
             
              desc "remove_service_directory [NAME]", "Remove accessory directory used for uploaded files and data directories from host", hide: true
         | 
| 209 209 | 
             
              def remove_service_directory(name)
         | 
| 210 | 
            -
                 | 
| 210 | 
            +
                mutating do
         | 
| 211 211 | 
             
                  with_accessory(name) do |accessory|
         | 
| 212 212 | 
             
                    on(accessory.hosts) do
         | 
| 213 213 | 
             
                      execute *accessory.remove_service_directory
         | 
    
        data/lib/mrsk/cli/app.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            class Mrsk::Cli::App < Mrsk::Cli::Base
         | 
| 2 2 | 
             
              desc "boot", "Boot app on servers (or reboot app if already running)"
         | 
| 3 3 | 
             
              def boot
         | 
| 4 | 
            -
                 | 
| 4 | 
            +
                mutating do
         | 
| 5 5 | 
             
                  hold_lock_on_error do
         | 
| 6 6 | 
             
                    say "Get most recent version available as an image...", :magenta unless options[:version]
         | 
| 7 7 | 
             
                    using_version(version_or_latest) do |version|
         | 
| @@ -43,7 +43,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base | |
| 43 43 |  | 
| 44 44 | 
             
              desc "start", "Start existing app container on servers"
         | 
| 45 45 | 
             
              def start
         | 
| 46 | 
            -
                 | 
| 46 | 
            +
                mutating do
         | 
| 47 47 | 
             
                  on(MRSK.hosts) do |host|
         | 
| 48 48 | 
             
                    roles = MRSK.roles_on(host)
         | 
| 49 49 |  | 
| @@ -57,7 +57,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base | |
| 57 57 |  | 
| 58 58 | 
             
              desc "stop", "Stop app container on servers"
         | 
| 59 59 | 
             
              def stop
         | 
| 60 | 
            -
                 | 
| 60 | 
            +
                mutating do
         | 
| 61 61 | 
             
                  on(MRSK.hosts) do |host|
         | 
| 62 62 | 
             
                    roles = MRSK.roles_on(host)
         | 
| 63 63 |  | 
| @@ -135,7 +135,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base | |
| 135 135 | 
             
              desc "stale_containers", "Detect app stale containers"
         | 
| 136 136 | 
             
              option :stop, aliases: "-s", type: :boolean, default: false, desc: "Stop the stale containers found"
         | 
| 137 137 | 
             
              def stale_containers
         | 
| 138 | 
            -
                 | 
| 138 | 
            +
                mutating do
         | 
| 139 139 | 
             
                  stop = options[:stop]
         | 
| 140 140 |  | 
| 141 141 | 
             
                  cli = self
         | 
| @@ -202,7 +202,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base | |
| 202 202 |  | 
| 203 203 | 
             
              desc "remove", "Remove app containers and images from servers"
         | 
| 204 204 | 
             
              def remove
         | 
| 205 | 
            -
                 | 
| 205 | 
            +
                mutating do
         | 
| 206 206 | 
             
                  stop
         | 
| 207 207 | 
             
                  remove_containers
         | 
| 208 208 | 
             
                  remove_images
         | 
| @@ -211,7 +211,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base | |
| 211 211 |  | 
| 212 212 | 
             
              desc "remove_container [VERSION]", "Remove app container with given version from servers", hide: true
         | 
| 213 213 | 
             
              def remove_container(version)
         | 
| 214 | 
            -
                 | 
| 214 | 
            +
                mutating do
         | 
| 215 215 | 
             
                  on(MRSK.hosts) do |host|
         | 
| 216 216 | 
             
                    roles = MRSK.roles_on(host)
         | 
| 217 217 |  | 
| @@ -225,7 +225,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base | |
| 225 225 |  | 
| 226 226 | 
             
              desc "remove_containers", "Remove all app containers from servers", hide: true
         | 
| 227 227 | 
             
              def remove_containers
         | 
| 228 | 
            -
                 | 
| 228 | 
            +
                mutating do
         | 
| 229 229 | 
             
                  on(MRSK.hosts) do |host|
         | 
| 230 230 | 
             
                    roles = MRSK.roles_on(host)
         | 
| 231 231 |  | 
| @@ -239,7 +239,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base | |
| 239 239 |  | 
| 240 240 | 
             
              desc "remove_images", "Remove all app images from servers", hide: true
         | 
| 241 241 | 
             
              def remove_images
         | 
| 242 | 
            -
                 | 
| 242 | 
            +
                mutating do
         | 
| 243 243 | 
             
                  on(MRSK.hosts) do
         | 
| 244 244 | 
             
                    execute *MRSK.auditor.record("Removed all app images"), verbosity: :debug
         | 
| 245 245 | 
             
                    execute *MRSK.app.remove_images
         | 
    
        data/lib/mrsk/cli/base.rb
    CHANGED
    
    | @@ -72,28 +72,28 @@ module Mrsk::Cli | |
| 72 72 | 
             
                    puts "  Finished all in #{sprintf("%.1f seconds", runtime)}"
         | 
| 73 73 | 
             
                  end
         | 
| 74 74 |  | 
| 75 | 
            -
                  def  | 
| 76 | 
            -
                    if MRSK.holding_lock?
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                     | 
| 79 | 
            -
                      run_hook "pre-connect"
         | 
| 75 | 
            +
                  def mutating
         | 
| 76 | 
            +
                    return yield if MRSK.holding_lock?
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                    MRSK.config.ensure_env_available
         | 
| 80 79 |  | 
| 81 | 
            -
             | 
| 80 | 
            +
                    run_hook "pre-connect"
         | 
| 82 81 |  | 
| 83 | 
            -
             | 
| 84 | 
            -
                        yield
         | 
| 85 | 
            -
                      rescue
         | 
| 86 | 
            -
                        if MRSK.hold_lock_on_error?
         | 
| 87 | 
            -
                          error "  \e[31mDeploy lock was not released\e[0m"
         | 
| 88 | 
            -
                        else
         | 
| 89 | 
            -
                          release_lock
         | 
| 90 | 
            -
                        end
         | 
| 82 | 
            +
                    acquire_lock
         | 
| 91 83 |  | 
| 92 | 
            -
             | 
| 84 | 
            +
                    begin
         | 
| 85 | 
            +
                      yield
         | 
| 86 | 
            +
                    rescue
         | 
| 87 | 
            +
                      if MRSK.hold_lock_on_error?
         | 
| 88 | 
            +
                        error "  \e[31mDeploy lock was not released\e[0m"
         | 
| 89 | 
            +
                      else
         | 
| 90 | 
            +
                        release_lock
         | 
| 93 91 | 
             
                      end
         | 
| 94 92 |  | 
| 95 | 
            -
                       | 
| 93 | 
            +
                      raise
         | 
| 96 94 | 
             
                    end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                    release_lock
         | 
| 97 97 | 
             
                  end
         | 
| 98 98 |  | 
| 99 99 | 
             
                  def acquire_lock
         | 
    
        data/lib/mrsk/cli/build.rb
    CHANGED
    
    | @@ -3,7 +3,7 @@ class Mrsk::Cli::Build < Mrsk::Cli::Base | |
| 3 3 |  | 
| 4 4 | 
             
              desc "deliver", "Build app and push app image to registry then pull image on servers"
         | 
| 5 5 | 
             
              def deliver
         | 
| 6 | 
            -
                 | 
| 6 | 
            +
                mutating do
         | 
| 7 7 | 
             
                  push
         | 
| 8 8 | 
             
                  pull
         | 
| 9 9 | 
             
                end
         | 
| @@ -11,7 +11,7 @@ class Mrsk::Cli::Build < Mrsk::Cli::Base | |
| 11 11 |  | 
| 12 12 | 
             
              desc "push", "Build and push app image to registry"
         | 
| 13 13 | 
             
              def push
         | 
| 14 | 
            -
                 | 
| 14 | 
            +
                mutating do
         | 
| 15 15 | 
             
                  cli = self
         | 
| 16 16 |  | 
| 17 17 | 
             
                  verify_local_dependencies
         | 
| @@ -37,7 +37,7 @@ class Mrsk::Cli::Build < Mrsk::Cli::Base | |
| 37 37 |  | 
| 38 38 | 
             
              desc "pull", "Pull app image from registry onto servers"
         | 
| 39 39 | 
             
              def pull
         | 
| 40 | 
            -
                 | 
| 40 | 
            +
                mutating do
         | 
| 41 41 | 
             
                  on(MRSK.hosts) do
         | 
| 42 42 | 
             
                    execute *MRSK.auditor.record("Pulled image with version #{MRSK.config.version}"), verbosity: :debug
         | 
| 43 43 | 
             
                    execute *MRSK.builder.clean, raise_on_non_zero_exit: false
         | 
| @@ -48,7 +48,7 @@ class Mrsk::Cli::Build < Mrsk::Cli::Base | |
| 48 48 |  | 
| 49 49 | 
             
              desc "create", "Create a build setup"
         | 
| 50 50 | 
             
              def create
         | 
| 51 | 
            -
                 | 
| 51 | 
            +
                mutating do
         | 
| 52 52 | 
             
                  run_locally do
         | 
| 53 53 | 
             
                    begin
         | 
| 54 54 | 
             
                      debug "Using builder: #{MRSK.builder.name}"
         | 
| @@ -67,7 +67,7 @@ class Mrsk::Cli::Build < Mrsk::Cli::Base | |
| 67 67 |  | 
| 68 68 | 
             
              desc "remove", "Remove build setup"
         | 
| 69 69 | 
             
              def remove
         | 
| 70 | 
            -
                 | 
| 70 | 
            +
                mutating do
         | 
| 71 71 | 
             
                  run_locally do
         | 
| 72 72 | 
             
                    debug "Using builder: #{MRSK.builder.name}"
         | 
| 73 73 | 
             
                    execute *MRSK.builder.remove
         | 
    
        data/lib/mrsk/cli/main.rb
    CHANGED
    
    | @@ -2,7 +2,7 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base | |
| 2 2 | 
             
              desc "setup", "Setup all accessories and deploy app to servers"
         | 
| 3 3 | 
             
              def setup
         | 
| 4 4 | 
             
                print_runtime do
         | 
| 5 | 
            -
                   | 
| 5 | 
            +
                  mutating do
         | 
| 6 6 | 
             
                    invoke "mrsk:cli:server:bootstrap"
         | 
| 7 7 | 
             
                    invoke "mrsk:cli:accessory:boot", [ "all" ]
         | 
| 8 8 | 
             
                    deploy
         | 
| @@ -14,7 +14,7 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base | |
| 14 14 | 
             
              option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push"
         | 
| 15 15 | 
             
              def deploy
         | 
| 16 16 | 
             
                runtime = print_runtime do
         | 
| 17 | 
            -
                   | 
| 17 | 
            +
                  mutating do
         | 
| 18 18 | 
             
                    invoke_options = deploy_options
         | 
| 19 19 |  | 
| 20 20 | 
             
                    say "Log into image registry...", :magenta
         | 
| @@ -53,7 +53,7 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base | |
| 53 53 | 
             
              option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push"
         | 
| 54 54 | 
             
              def redeploy
         | 
| 55 55 | 
             
                runtime = print_runtime do
         | 
| 56 | 
            -
                   | 
| 56 | 
            +
                  mutating do
         | 
| 57 57 | 
             
                    invoke_options = deploy_options
         | 
| 58 58 |  | 
| 59 59 | 
             
                    if options[:skip_push]
         | 
| @@ -83,7 +83,7 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base | |
| 83 83 | 
             
              def rollback(version)
         | 
| 84 84 | 
             
                rolled_back = false
         | 
| 85 85 | 
             
                runtime = print_runtime do
         | 
| 86 | 
            -
                   | 
| 86 | 
            +
                  mutating do
         | 
| 87 87 | 
             
                    invoke_options = deploy_options
         | 
| 88 88 |  | 
| 89 89 | 
             
                    MRSK.config.version = version
         | 
| @@ -180,7 +180,7 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base | |
| 180 180 | 
             
              desc "remove", "Remove Traefik, app, accessories, and registry session from servers"
         | 
| 181 181 | 
             
              option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
         | 
| 182 182 | 
             
              def remove
         | 
| 183 | 
            -
                 | 
| 183 | 
            +
                mutating do
         | 
| 184 184 | 
             
                  if options[:confirmed] || ask("This will remove all containers and images. Are you sure?", limited_to: %w( y N ), default: "N") == "y"
         | 
| 185 185 | 
             
                    invoke "mrsk:cli:traefik:remove", [], options.without(:confirmed)
         | 
| 186 186 | 
             
                    invoke "mrsk:cli:app:remove", [], options.without(:confirmed)
         | 
    
        data/lib/mrsk/cli/prune.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            class Mrsk::Cli::Prune < Mrsk::Cli::Base
         | 
| 2 2 | 
             
              desc "all", "Prune unused images and stopped containers"
         | 
| 3 3 | 
             
              def all
         | 
| 4 | 
            -
                 | 
| 4 | 
            +
                mutating do
         | 
| 5 5 | 
             
                  containers
         | 
| 6 6 | 
             
                  images
         | 
| 7 7 | 
             
                end
         | 
| @@ -9,7 +9,7 @@ class Mrsk::Cli::Prune < Mrsk::Cli::Base | |
| 9 9 |  | 
| 10 10 | 
             
              desc "images", "Prune dangling images"
         | 
| 11 11 | 
             
              def images
         | 
| 12 | 
            -
                 | 
| 12 | 
            +
                mutating do
         | 
| 13 13 | 
             
                  on(MRSK.hosts) do
         | 
| 14 14 | 
             
                    execute *MRSK.auditor.record("Pruned images"), verbosity: :debug
         | 
| 15 15 | 
             
                    execute *MRSK.prune.dangling_images
         | 
| @@ -20,7 +20,7 @@ class Mrsk::Cli::Prune < Mrsk::Cli::Base | |
| 20 20 |  | 
| 21 21 | 
             
              desc "containers", "Prune all stopped containers, except the last 5"
         | 
| 22 22 | 
             
              def containers
         | 
| 23 | 
            -
                 | 
| 23 | 
            +
                mutating do
         | 
| 24 24 | 
             
                  on(MRSK.hosts) do
         | 
| 25 25 | 
             
                    execute *MRSK.auditor.record("Pruned containers"), verbosity: :debug
         | 
| 26 26 | 
             
                    execute *MRSK.prune.containers
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            #!/bin/ | 
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 2 |  | 
| 3 3 | 
             
            # A sample pre-deploy hook
         | 
| 4 4 | 
             
            #
         | 
| @@ -16,8 +16,6 @@ | |
| 16 16 | 
             
            # MRSK_ROLE (if set)
         | 
| 17 17 | 
             
            # MRSK_DESTINATION (if set)
         | 
| 18 18 |  | 
| 19 | 
            -
            #!/usr/bin/env ruby
         | 
| 20 | 
            -
             | 
| 21 19 | 
             
            # Only check the build status for production deployments
         | 
| 22 20 | 
             
            if ENV["MRSK_COMMAND"] == "rollback" || ENV["MRSK_DESTINATION"] != "production"
         | 
| 23 21 | 
             
              exit 0
         | 
| @@ -41,41 +39,70 @@ def exit_with_error(message) | |
| 41 39 | 
             
              exit 1
         | 
| 42 40 | 
             
            end
         | 
| 43 41 |  | 
| 44 | 
            -
             | 
| 45 | 
            -
               | 
| 46 | 
            -
             | 
| 42 | 
            +
            class GithubStatusChecks
         | 
| 43 | 
            +
              attr_reader :remote_url, :git_sha, :github_client, :combined_status
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              def initialize
         | 
| 46 | 
            +
                @remote_url = `git config --get remote.origin.url`.strip.delete_prefix("https://github.com/")
         | 
| 47 | 
            +
                @git_sha = `git rev-parse HEAD`.strip
         | 
| 48 | 
            +
                @github_client = Octokit::Client.new(access_token: ENV["GITHUB_TOKEN"])
         | 
| 49 | 
            +
                refresh!
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
              def refresh!
         | 
| 53 | 
            +
                @combined_status = github_client.combined_status(remote_url, git_sha)
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              def state
         | 
| 57 | 
            +
                combined_status[:state]
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              def first_status_url
         | 
| 61 | 
            +
                first_status = combined_status[:statuses].find { |status| status[:state] == state }
         | 
| 62 | 
            +
                first_status && first_status[:target_url]
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              def complete_count
         | 
| 66 | 
            +
                combined_status[:statuses].count { |status| status[:state] != "pending"}
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              def total_count
         | 
| 70 | 
            +
                combined_status[:statuses].count
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
              def current_status
         | 
| 74 | 
            +
                if total_count > 0
         | 
| 75 | 
            +
                  "Completed #{complete_count}/#{total_count} checks, see #{first_status_url} ..."
         | 
| 76 | 
            +
                else
         | 
| 77 | 
            +
                  "Build not started..."
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
              end
         | 
| 47 80 | 
             
            end
         | 
| 48 81 |  | 
| 49 | 
            -
            remote_url = `git config --get remote.origin.url`.strip.delete_prefix("https://github.com/")
         | 
| 50 | 
            -
            git_sha = `git rev-parse HEAD`.strip
         | 
| 51 82 |  | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 83 | 
            +
            $stdout.sync = true
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            puts "Checking build status..."
         | 
| 54 86 | 
             
            attempts = 0
         | 
| 87 | 
            +
            checks = GithubStatusChecks.new
         | 
| 55 88 |  | 
| 56 89 | 
             
            begin
         | 
| 57 90 | 
             
              loop do
         | 
| 58 | 
            -
                 | 
| 59 | 
            -
                state = combined_status[:state]
         | 
| 60 | 
            -
                first_status_url = first_status_url(combined_status, state)
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                case state
         | 
| 91 | 
            +
                case checks.state
         | 
| 63 92 | 
             
                when "success"
         | 
| 64 | 
            -
                  puts " | 
| 93 | 
            +
                  puts "Checks passed, see #{checks.first_status_url}"
         | 
| 65 94 | 
             
                  exit 0
         | 
| 66 95 | 
             
                when "failure"
         | 
| 67 | 
            -
                  exit_with_error " | 
| 96 | 
            +
                  exit_with_error "Checks failed, see #{checks.first_status_url}"
         | 
| 68 97 | 
             
                when "pending"
         | 
| 69 98 | 
             
                  attempts += 1
         | 
| 70 99 | 
             
                end
         | 
| 71 100 |  | 
| 72 | 
            -
                 | 
| 73 | 
            -
             | 
| 74 | 
            -
                if attempts == MAX_ATTEMPTS
         | 
| 75 | 
            -
                  exit_with_error "Build status is still pending, gave up after #{MAX_ATTEMPTS * ATTEMPTS_GAP} seconds"
         | 
| 76 | 
            -
                end
         | 
| 101 | 
            +
                exit_with_error "Checks are still pending, gave up after #{MAX_ATTEMPTS * ATTEMPTS_GAP} seconds" if attempts == MAX_ATTEMPTS
         | 
| 77 102 |  | 
| 103 | 
            +
                puts checks.current_status
         | 
| 78 104 | 
             
                sleep(ATTEMPTS_GAP)
         | 
| 105 | 
            +
                checks.refresh!
         | 
| 79 106 | 
             
              end
         | 
| 80 107 | 
             
            rescue Octokit::NotFound
         | 
| 81 108 | 
             
              exit_with_error "Build status could not be found"
         | 
    
        data/lib/mrsk/cli/traefik.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            class Mrsk::Cli::Traefik < Mrsk::Cli::Base
         | 
| 2 2 | 
             
              desc "boot", "Boot Traefik on servers"
         | 
| 3 3 | 
             
              def boot
         | 
| 4 | 
            -
                 | 
| 4 | 
            +
                mutating do
         | 
| 5 5 | 
             
                  on(MRSK.traefik_hosts) do
         | 
| 6 6 | 
             
                    execute *MRSK.registry.login
         | 
| 7 7 | 
             
                    execute *MRSK.traefik.run, raise_on_non_zero_exit: false
         | 
| @@ -11,7 +11,7 @@ class Mrsk::Cli::Traefik < Mrsk::Cli::Base | |
| 11 11 |  | 
| 12 12 | 
             
              desc "reboot", "Reboot Traefik on servers (stop container, remove container, start new container)"
         | 
| 13 13 | 
             
              def reboot
         | 
| 14 | 
            -
                 | 
| 14 | 
            +
                mutating do
         | 
| 15 15 | 
             
                  stop
         | 
| 16 16 | 
             
                  remove_container
         | 
| 17 17 | 
             
                  boot
         | 
| @@ -20,7 +20,7 @@ class Mrsk::Cli::Traefik < Mrsk::Cli::Base | |
| 20 20 |  | 
| 21 21 | 
             
              desc "start", "Start existing Traefik container on servers"
         | 
| 22 22 | 
             
              def start
         | 
| 23 | 
            -
                 | 
| 23 | 
            +
                mutating do
         | 
| 24 24 | 
             
                  on(MRSK.traefik_hosts) do
         | 
| 25 25 | 
             
                    execute *MRSK.auditor.record("Started traefik"), verbosity: :debug
         | 
| 26 26 | 
             
                    execute *MRSK.traefik.start, raise_on_non_zero_exit: false
         | 
| @@ -30,7 +30,7 @@ class Mrsk::Cli::Traefik < Mrsk::Cli::Base | |
| 30 30 |  | 
| 31 31 | 
             
              desc "stop", "Stop existing Traefik container on servers"
         | 
| 32 32 | 
             
              def stop
         | 
| 33 | 
            -
                 | 
| 33 | 
            +
                mutating do
         | 
| 34 34 | 
             
                  on(MRSK.traefik_hosts) do
         | 
| 35 35 | 
             
                    execute *MRSK.auditor.record("Stopped traefik"), verbosity: :debug
         | 
| 36 36 | 
             
                    execute *MRSK.traefik.stop, raise_on_non_zero_exit: false
         | 
| @@ -40,7 +40,7 @@ class Mrsk::Cli::Traefik < Mrsk::Cli::Base | |
| 40 40 |  | 
| 41 41 | 
             
              desc "restart", "Restart existing Traefik container on servers"
         | 
| 42 42 | 
             
              def restart
         | 
| 43 | 
            -
                 | 
| 43 | 
            +
                mutating do
         | 
| 44 44 | 
             
                  stop
         | 
| 45 45 | 
             
                  start
         | 
| 46 46 | 
             
                end
         | 
| @@ -77,7 +77,7 @@ class Mrsk::Cli::Traefik < Mrsk::Cli::Base | |
| 77 77 |  | 
| 78 78 | 
             
              desc "remove", "Remove Traefik container and image from servers"
         | 
| 79 79 | 
             
              def remove
         | 
| 80 | 
            -
                 | 
| 80 | 
            +
                mutating do
         | 
| 81 81 | 
             
                  stop
         | 
| 82 82 | 
             
                  remove_container
         | 
| 83 83 | 
             
                  remove_image
         | 
| @@ -86,7 +86,7 @@ class Mrsk::Cli::Traefik < Mrsk::Cli::Base | |
| 86 86 |  | 
| 87 87 | 
             
              desc "remove_container", "Remove Traefik container from servers", hide: true
         | 
| 88 88 | 
             
              def remove_container
         | 
| 89 | 
            -
                 | 
| 89 | 
            +
                mutating do
         | 
| 90 90 | 
             
                  on(MRSK.traefik_hosts) do
         | 
| 91 91 | 
             
                    execute *MRSK.auditor.record("Removed traefik container"), verbosity: :debug
         | 
| 92 92 | 
             
                    execute *MRSK.traefik.remove_container
         | 
| @@ -96,7 +96,7 @@ class Mrsk::Cli::Traefik < Mrsk::Cli::Base | |
| 96 96 |  | 
| 97 97 | 
             
              desc "remove_image", "Remove Traefik image from servers", hide: true
         | 
| 98 98 | 
             
              def remove_image
         | 
| 99 | 
            -
                 | 
| 99 | 
            +
                mutating do
         | 
| 100 100 | 
             
                  on(MRSK.traefik_hosts) do
         | 
| 101 101 | 
             
                    execute *MRSK.auditor.record("Removed traefik image"), verbosity: :debug
         | 
| 102 102 | 
             
                    execute *MRSK.traefik.remove_image
         | 
    
        data/lib/mrsk/commands/base.rb
    CHANGED
    
    | @@ -13,7 +13,11 @@ module Mrsk::Commands | |
| 13 13 |  | 
| 14 14 | 
             
                def run_over_ssh(*command, host:)
         | 
| 15 15 | 
             
                  "ssh".tap do |cmd|
         | 
| 16 | 
            -
                     | 
| 16 | 
            +
                    if config.ssh_proxy && config.ssh_proxy.is_a?(Net::SSH::Proxy::Jump)
         | 
| 17 | 
            +
                      cmd << " -J #{config.ssh_proxy.jump_proxies}"
         | 
| 18 | 
            +
                    elsif config.ssh_proxy && config.ssh_proxy.is_a?(Net::SSH::Proxy::Command)
         | 
| 19 | 
            +
                      cmd << " -o ProxyCommand='#{config.ssh_proxy.command_line_template}'"
         | 
| 20 | 
            +
                    end
         | 
| 17 21 | 
             
                    cmd << " -t #{config.ssh_user}@#{host} '#{command.join(" ")}'"
         | 
| 18 22 | 
             
                  end
         | 
| 19 23 | 
             
                end
         | 
| @@ -3,6 +3,7 @@ class Mrsk::Commands::Builder::Base < Mrsk::Commands::Base | |
| 3 3 | 
             
              class BuilderError < StandardError; end
         | 
| 4 4 |  | 
| 5 5 | 
             
              delegate :argumentize, to: Mrsk::Utils
         | 
| 6 | 
            +
              delegate :args, :secrets, :dockerfile, :local_arch, :local_host, :remote_arch, :remote_host, :cache_from, :cache_to, to: :builder_config
         | 
| 6 7 |  | 
| 7 8 | 
             
              def clean
         | 
| 8 9 | 
             
                docker :image, :rm, "--force", config.absolute_image
         | 
| @@ -13,11 +14,11 @@ class Mrsk::Commands::Builder::Base < Mrsk::Commands::Base | |
| 13 14 | 
             
              end
         | 
| 14 15 |  | 
| 15 16 | 
             
              def build_options
         | 
| 16 | 
            -
                [ *build_tags, *build_labels, *build_args, *build_secrets, *build_dockerfile ]
         | 
| 17 | 
            +
                [ *build_tags, *build_cache, *build_labels, *build_args, *build_secrets, *build_dockerfile ]
         | 
| 17 18 | 
             
              end
         | 
| 18 19 |  | 
| 19 20 | 
             
              def build_context
         | 
| 20 | 
            -
                context
         | 
| 21 | 
            +
                config.builder.context
         | 
| 21 22 | 
             
              end
         | 
| 22 23 |  | 
| 23 24 |  | 
| @@ -26,6 +27,13 @@ class Mrsk::Commands::Builder::Base < Mrsk::Commands::Base | |
| 26 27 | 
             
                  [ "-t", config.absolute_image, "-t", config.latest_image ]
         | 
| 27 28 | 
             
                end
         | 
| 28 29 |  | 
| 30 | 
            +
                def build_cache
         | 
| 31 | 
            +
                  if cache_to && cache_from
         | 
| 32 | 
            +
                    ["--cache-to", cache_to,
         | 
| 33 | 
            +
                      "--cache-from", cache_from]
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 29 37 | 
             
                def build_labels
         | 
| 30 38 | 
             
                  argumentize "--label", { service: config.service }
         | 
| 31 39 | 
             
                end
         | 
| @@ -46,19 +54,7 @@ class Mrsk::Commands::Builder::Base < Mrsk::Commands::Base | |
| 46 54 | 
             
                  end
         | 
| 47 55 | 
             
                end
         | 
| 48 56 |  | 
| 49 | 
            -
                def  | 
| 50 | 
            -
                   | 
| 51 | 
            -
                end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                def secrets
         | 
| 54 | 
            -
                  (config.builder && config.builder["secrets"]) || []
         | 
| 55 | 
            -
                end
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                def dockerfile
         | 
| 58 | 
            -
                  (config.builder && config.builder["dockerfile"]) || "Dockerfile"
         | 
| 59 | 
            -
                end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                def context
         | 
| 62 | 
            -
                  (config.builder && config.builder["context"]) || "."
         | 
| 57 | 
            +
                def builder_config
         | 
| 58 | 
            +
                  config.builder
         | 
| 63 59 | 
             
                end
         | 
| 64 60 | 
             
            end
         | 
| @@ -22,17 +22,17 @@ class Mrsk::Commands::Builder::Multiarch::Remote < Mrsk::Commands::Builder::Mult | |
| 22 22 | 
             
                end
         | 
| 23 23 |  | 
| 24 24 | 
             
                def create_local_buildx
         | 
| 25 | 
            -
                  docker :buildx, :create, "--name", builder_name, builder_name_with_arch( | 
| 25 | 
            +
                  docker :buildx, :create, "--name", builder_name, builder_name_with_arch(local_arch), "--platform", "linux/#{local_arch}"
         | 
| 26 26 | 
             
                end
         | 
| 27 27 |  | 
| 28 28 | 
             
                def append_remote_buildx
         | 
| 29 | 
            -
                  docker :buildx, :create, "--append", "--name", builder_name, builder_name_with_arch( | 
| 29 | 
            +
                  docker :buildx, :create, "--append", "--name", builder_name, builder_name_with_arch(remote_arch), "--platform", "linux/#{remote_arch}"
         | 
| 30 30 | 
             
                end
         | 
| 31 31 |  | 
| 32 32 | 
             
                def create_contexts
         | 
| 33 33 | 
             
                  combine \
         | 
| 34 | 
            -
                    create_context( | 
| 35 | 
            -
                    create_context( | 
| 34 | 
            +
                    create_context(local_arch, local_host),
         | 
| 35 | 
            +
                    create_context(remote_arch, remote_host)
         | 
| 36 36 | 
             
                end
         | 
| 37 37 |  | 
| 38 38 | 
             
                def create_context(arch, host)
         | 
| @@ -41,19 +41,11 @@ class Mrsk::Commands::Builder::Multiarch::Remote < Mrsk::Commands::Builder::Mult | |
| 41 41 |  | 
| 42 42 | 
             
                def remove_contexts
         | 
| 43 43 | 
             
                  combine \
         | 
| 44 | 
            -
                    remove_context( | 
| 45 | 
            -
                    remove_context( | 
| 44 | 
            +
                    remove_context(local_arch),
         | 
| 45 | 
            +
                    remove_context(remote_arch)
         | 
| 46 46 | 
             
                end
         | 
| 47 47 |  | 
| 48 48 | 
             
                def remove_context(arch)
         | 
| 49 49 | 
             
                  docker :context, :rm, builder_name_with_arch(arch)
         | 
| 50 50 | 
             
                end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                def local
         | 
| 53 | 
            -
                  config.builder["local"]
         | 
| 54 | 
            -
                end
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                def remote
         | 
| 57 | 
            -
                  config.builder["remote"]
         | 
| 58 | 
            -
                end
         | 
| 59 51 | 
             
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            class Mrsk::Commands::Builder::Native::Cached < Mrsk::Commands::Builder::Native
         | 
| 2 | 
            +
              def create
         | 
| 3 | 
            +
                docker :buildx, :create, "--use", "--driver=docker-container"
         | 
| 4 | 
            +
              end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def remove
         | 
| 7 | 
            +
                docker :buildx, :rm, builder_name
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def push
         | 
| 11 | 
            +
                docker :buildx, :build,
         | 
| 12 | 
            +
                  "--push",
         | 
| 13 | 
            +
                  *build_options,
         | 
| 14 | 
            +
                  build_context
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
| @@ -28,29 +28,21 @@ class Mrsk::Commands::Builder::Native::Remote < Mrsk::Commands::Builder::Native | |
| 28 28 |  | 
| 29 29 |  | 
| 30 30 | 
             
              private
         | 
| 31 | 
            -
                def arch
         | 
| 32 | 
            -
                  config.builder["remote"]["arch"]
         | 
| 33 | 
            -
                end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                def host
         | 
| 36 | 
            -
                  config.builder["remote"]["host"]
         | 
| 37 | 
            -
                end
         | 
| 38 | 
            -
             | 
| 39 31 | 
             
                def builder_name
         | 
| 40 32 | 
             
                  "mrsk-#{config.service}-native-remote"
         | 
| 41 33 | 
             
                end
         | 
| 42 34 |  | 
| 43 35 | 
             
                def builder_name_with_arch
         | 
| 44 | 
            -
                  "#{builder_name}-#{ | 
| 36 | 
            +
                  "#{builder_name}-#{remote_arch}"
         | 
| 45 37 | 
             
                end
         | 
| 46 38 |  | 
| 47 39 | 
             
                def platform
         | 
| 48 | 
            -
                  "linux/#{ | 
| 40 | 
            +
                  "linux/#{remote_arch}"
         | 
| 49 41 | 
             
                end
         | 
| 50 42 |  | 
| 51 43 | 
             
                def create_context
         | 
| 52 44 | 
             
                  docker :context, :create,
         | 
| 53 | 
            -
                    builder_name_with_arch, "--description", "'#{builder_name} #{ | 
| 45 | 
            +
                    builder_name_with_arch, "--description", "'#{builder_name} #{remote_arch} native host'", "--docker", "'host=#{remote_host}'"
         | 
| 54 46 | 
             
                end
         | 
| 55 47 |  | 
| 56 48 | 
             
                def remove_context
         | 
| @@ -7,11 +7,13 @@ class Mrsk::Commands::Builder < Mrsk::Commands::Base | |
| 7 7 |  | 
| 8 8 | 
             
              def target
         | 
| 9 9 | 
             
                case
         | 
| 10 | 
            -
                when config.builder && config.builder | 
| 10 | 
            +
                when !config.builder.multiarch? && !config.builder.cached?
         | 
| 11 11 | 
             
                  native
         | 
| 12 | 
            -
                when config.builder && config.builder | 
| 12 | 
            +
                when !config.builder.multiarch? && config.builder.cached?
         | 
| 13 | 
            +
                  native_cached
         | 
| 14 | 
            +
                when config.builder.local? && config.builder.remote?
         | 
| 13 15 | 
             
                  multiarch_remote
         | 
| 14 | 
            -
                when config.builder | 
| 16 | 
            +
                when config.builder.remote?
         | 
| 15 17 | 
             
                  native_remote
         | 
| 16 18 | 
             
                else
         | 
| 17 19 | 
             
                  multiarch
         | 
| @@ -22,6 +24,10 @@ class Mrsk::Commands::Builder < Mrsk::Commands::Base | |
| 22 24 | 
             
                @native ||= Mrsk::Commands::Builder::Native.new(config)
         | 
| 23 25 | 
             
              end
         | 
| 24 26 |  | 
| 27 | 
            +
              def native_cached
         | 
| 28 | 
            +
                @native ||= Mrsk::Commands::Builder::Native::Cached.new(config)
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 25 31 | 
             
              def native_remote
         | 
| 26 32 | 
             
                @native ||= Mrsk::Commands::Builder::Native::Remote.new(config)
         | 
| 27 33 | 
             
              end
         | 
| @@ -3,6 +3,9 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base | |
| 3 3 |  | 
| 4 4 | 
             
              DEFAULT_IMAGE = "traefik:v2.9"
         | 
| 5 5 | 
             
              CONTAINER_PORT = 80
         | 
| 6 | 
            +
              DEFAULT_ARGS = {
         | 
| 7 | 
            +
                'log.level' => 'DEBUG'
         | 
| 8 | 
            +
              }
         | 
| 6 9 |  | 
| 7 10 | 
             
              def run
         | 
| 8 11 | 
             
                docker :run, "--name traefik",
         | 
| @@ -16,7 +19,6 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base | |
| 16 19 | 
             
                  *docker_options_args,
         | 
| 17 20 | 
             
                  image,
         | 
| 18 21 | 
             
                  "--providers.docker",
         | 
| 19 | 
            -
                  "--log.level=DEBUG",
         | 
| 20 22 | 
             
                  *cmd_option_args
         | 
| 21 23 | 
             
              end
         | 
| 22 24 |  | 
| @@ -86,9 +88,9 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base | |
| 86 88 |  | 
| 87 89 | 
             
                def cmd_option_args
         | 
| 88 90 | 
             
                  if args = config.traefik["args"]
         | 
| 89 | 
            -
                    optionize args, with: "="
         | 
| 91 | 
            +
                    optionize DEFAULT_ARGS.merge(args), with: "="
         | 
| 90 92 | 
             
                  else
         | 
| 91 | 
            -
                     | 
| 93 | 
            +
                    optionize DEFAULT_ARGS, with: "="
         | 
| 92 94 | 
             
                  end
         | 
| 93 95 | 
             
                end
         | 
| 94 96 |  | 
| @@ -0,0 +1,114 @@ | |
| 1 | 
            +
            class Mrsk::Configuration::Builder
         | 
| 2 | 
            +
              def initialize(config:)
         | 
| 3 | 
            +
                @options = config.raw_config.builder || {}
         | 
| 4 | 
            +
                @image = config.image
         | 
| 5 | 
            +
                @server = config.registry["server"]
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                valid?
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def to_h
         | 
| 11 | 
            +
                @options
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              def multiarch?
         | 
| 15 | 
            +
                @options["multiarch"] != false
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              def local?
         | 
| 19 | 
            +
                !!@options["local"]
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              def remote?
         | 
| 23 | 
            +
                !!@options["remote"]
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              def cached?
         | 
| 27 | 
            +
                !!@options["cache"]
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              def args
         | 
| 31 | 
            +
                @options["args"] || {}
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              def secrets
         | 
| 35 | 
            +
                @options["secrets"] || []
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              def dockerfile
         | 
| 39 | 
            +
                @options["dockerfile"] || "Dockerfile"
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              def context
         | 
| 43 | 
            +
                @options["context"] || "."
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              def local_arch
         | 
| 47 | 
            +
                @options["local"]["arch"] if local?
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              def local_host
         | 
| 51 | 
            +
                @options["local"]["host"] if local?
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              def remote_arch
         | 
| 55 | 
            +
                @options["remote"]["arch"] if remote?
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              def remote_host
         | 
| 59 | 
            +
                @options["remote"]["host"] if remote?
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              def cache_from
         | 
| 63 | 
            +
                if cached?
         | 
| 64 | 
            +
                  case @options["cache"]["type"]
         | 
| 65 | 
            +
                  when "gha"
         | 
| 66 | 
            +
                    cache_from_config_for_gha
         | 
| 67 | 
            +
                  when "registry"
         | 
| 68 | 
            +
                    cache_from_config_for_registry
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
              def cache_to
         | 
| 74 | 
            +
                if cached?
         | 
| 75 | 
            +
                  case @options["cache"]["type"]
         | 
| 76 | 
            +
                  when "gha"
         | 
| 77 | 
            +
                    cache_to_config_for_gha
         | 
| 78 | 
            +
                  when "registry"
         | 
| 79 | 
            +
                    cache_to_config_for_registry
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
              end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
              private
         | 
| 85 | 
            +
                def valid?
         | 
| 86 | 
            +
                  if @options["local"] && !@options["remote"]
         | 
| 87 | 
            +
                    raise ArgumentError, "You must specify both local and remote builder config for remote multiarch builds"
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  if @options["cache"] && @options["cache"]["type"]
         | 
| 91 | 
            +
                    raise ArgumentError, "Invalid cache type: #{@options["cache"]["type"]}" unless ["gha", "registry"].include?(@options["cache"]["type"])
         | 
| 92 | 
            +
                  end
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                def cache_image
         | 
| 96 | 
            +
                  @options["cache"]&.fetch("image", nil) || "#{@image}-build-cache"
         | 
| 97 | 
            +
                end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                def cache_from_config_for_gha
         | 
| 100 | 
            +
                  "type=gha"
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                def cache_from_config_for_registry
         | 
| 104 | 
            +
                  [ "type=registry", "ref=#{@server}/#{cache_image}" ].compact.join(",")
         | 
| 105 | 
            +
                end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                def cache_to_config_for_gha
         | 
| 108 | 
            +
                  [ "type=gha", @options["cache"]&.fetch("options", nil)].compact.join(",")
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                def cache_to_config_for_registry
         | 
| 112 | 
            +
                  [ "type=registry", @options["cache"]&.fetch("options", nil), "ref=#{@server}/#{cache_image}" ].compact.join(",")
         | 
| 113 | 
            +
                end
         | 
| 114 | 
            +
            end
         | 
    
        data/lib/mrsk/configuration.rb
    CHANGED
    
    | @@ -6,7 +6,7 @@ require "erb" | |
| 6 6 | 
             
            require "net/ssh/proxy/jump"
         | 
| 7 7 |  | 
| 8 8 | 
             
            class Mrsk::Configuration
         | 
| 9 | 
            -
              delegate :service, :image, :servers, :env, :labels, :registry, : | 
| 9 | 
            +
              delegate :service, :image, :servers, :env, :labels, :registry, :stop_wait_time, :hooks_path, to: :raw_config, allow_nil: true
         | 
| 10 10 | 
             
              delegate :argumentize, :argumentize_env_with_secrets, :optionize, to: Mrsk::Utils
         | 
| 11 11 |  | 
| 12 12 | 
             
              attr_accessor :destination
         | 
| @@ -165,8 +165,12 @@ class Mrsk::Configuration | |
| 165 165 | 
             
                raw_config.readiness_delay || 7
         | 
| 166 166 | 
             
              end
         | 
| 167 167 |  | 
| 168 | 
            +
              def minimum_version
         | 
| 169 | 
            +
                raw_config.minimum_version
         | 
| 170 | 
            +
              end
         | 
| 171 | 
            +
             | 
| 168 172 | 
             
              def valid?
         | 
| 169 | 
            -
                ensure_required_keys_present &&  | 
| 173 | 
            +
                ensure_required_keys_present && ensure_valid_mrsk_version
         | 
| 170 174 | 
             
              end
         | 
| 171 175 |  | 
| 172 176 |  | 
| @@ -182,7 +186,7 @@ class Mrsk::Configuration | |
| 182 186 | 
             
                  env_args: env_args,
         | 
| 183 187 | 
             
                  volume_args: volume_args,
         | 
| 184 188 | 
             
                  ssh_options: ssh_options,
         | 
| 185 | 
            -
                  builder:  | 
| 189 | 
            +
                  builder: builder.to_h,
         | 
| 186 190 | 
             
                  accessories: raw_config.accessories,
         | 
| 187 191 | 
             
                  logging: logging_args,
         | 
| 188 192 | 
             
                  healthcheck: healthcheck
         | 
| @@ -197,6 +201,18 @@ class Mrsk::Configuration | |
| 197 201 | 
             
                raw_config.hooks_path || ".mrsk/hooks"
         | 
| 198 202 | 
             
              end
         | 
| 199 203 |  | 
| 204 | 
            +
              def builder
         | 
| 205 | 
            +
                Mrsk::Configuration::Builder.new(config: self)
         | 
| 206 | 
            +
              end
         | 
| 207 | 
            +
             | 
| 208 | 
            +
              # Will raise KeyError if any secret ENVs are missing
         | 
| 209 | 
            +
              def ensure_env_available
         | 
| 210 | 
            +
                env_args
         | 
| 211 | 
            +
                roles.each(&:env_args)
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                true
         | 
| 214 | 
            +
              end
         | 
| 215 | 
            +
             | 
| 200 216 | 
             
              private
         | 
| 201 217 | 
             
                # Will raise ArgumentError if any required config keys are missing
         | 
| 202 218 | 
             
                def ensure_required_keys_present
         | 
| @@ -221,14 +237,15 @@ class Mrsk::Configuration | |
| 221 237 | 
             
                  true
         | 
| 222 238 | 
             
                end
         | 
| 223 239 |  | 
| 224 | 
            -
                 | 
| 225 | 
            -
             | 
| 226 | 
            -
             | 
| 227 | 
            -
                   | 
| 240 | 
            +
                def ensure_valid_mrsk_version
         | 
| 241 | 
            +
                  if minimum_version && Gem::Version.new(minimum_version) > Gem::Version.new(Mrsk::VERSION)
         | 
| 242 | 
            +
                    raise ArgumentError, "Current version is #{Mrsk::VERSION}, minimum required is #{minimum_version}"
         | 
| 243 | 
            +
                  end
         | 
| 228 244 |  | 
| 229 245 | 
             
                  true
         | 
| 230 246 | 
             
                end
         | 
| 231 247 |  | 
| 248 | 
            +
             | 
| 232 249 | 
             
                def role_names
         | 
| 233 250 | 
             
                  raw_config.servers.is_a?(Array) ? [ "web" ] : raw_config.servers.keys.sort
         | 
| 234 251 | 
             
                end
         | 
    
        data/lib/mrsk/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: mrsk
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.14.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - David Heinemeier Hansson
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2023-06- | 
| 11 | 
            +
            date: 2023-06-20 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: activesupport
         | 
| @@ -204,6 +204,7 @@ files: | |
| 204 204 | 
             
            - lib/mrsk/commands/builder/multiarch.rb
         | 
| 205 205 | 
             
            - lib/mrsk/commands/builder/multiarch/remote.rb
         | 
| 206 206 | 
             
            - lib/mrsk/commands/builder/native.rb
         | 
| 207 | 
            +
            - lib/mrsk/commands/builder/native/cached.rb
         | 
| 207 208 | 
             
            - lib/mrsk/commands/builder/native/remote.rb
         | 
| 208 209 | 
             
            - lib/mrsk/commands/docker.rb
         | 
| 209 210 | 
             
            - lib/mrsk/commands/healthcheck.rb
         | 
| @@ -215,6 +216,7 @@ files: | |
| 215 216 | 
             
            - lib/mrsk/configuration.rb
         | 
| 216 217 | 
             
            - lib/mrsk/configuration/accessory.rb
         | 
| 217 218 | 
             
            - lib/mrsk/configuration/boot.rb
         | 
| 219 | 
            +
            - lib/mrsk/configuration/builder.rb
         | 
| 218 220 | 
             
            - lib/mrsk/configuration/role.rb
         | 
| 219 221 | 
             
            - lib/mrsk/sshkit_with_ext.rb
         | 
| 220 222 | 
             
            - lib/mrsk/tags.rb
         |