mrsk 0.8.1 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a560b5048509237f8c8440a41b35d674915ac493bcf0176256b1006a6aef004
4
- data.tar.gz: d69f0682c43e62fd0574d626456bcb62452ec972b8dd1182b1780958a65aadbd
3
+ metadata.gz: 0065b91bb3c00ef0ef6db78eb605d8db5df3606ccf97be15bb059ab1985231d5
4
+ data.tar.gz: 2ed2b0c6235ea398bc5717aebf99e2a4f1e6c9434c64da5eed6d8899b0ca335e
5
5
  SHA512:
6
- metadata.gz: d670dd54f94d64b2e35f5082f3a5cd78100780b0e0c5d51d050dc25f00ca4cdca26d0a4d797c01860d04205a2cd0fa4285089a944f72977d287e1c6fd313845e
7
- data.tar.gz: 6d28b436a2a0d33da1e32af340e5cd80972b57b946b6b51ec6481b5c832020867075ac53f24dd53f0d86e0d1738a78fb233986530a4ad0d9be1e83e73136522b
6
+ metadata.gz: c00ed2e4693b62e0eeb238c17d4c17b3e06ed03ed580aea7ca724a4629c28274d77bc31fa63ca1d1e5f07b1f73e6b2ecc164a076d2ad5307b7e30625cea2ee7a
7
+ data.tar.gz: ee273834e9e330640ef6b55acc4dabeeef6c4e9178112351376c3ab1e23afeb9fa389a08b6cf5a8c3bbaafc079d7cabc98d316fd08030a8886c12d5020a68653
data/README.md CHANGED
@@ -330,6 +330,21 @@ accessories:
330
330
 
331
331
  Now run `mrsk accessory start mysql` to start the MySQL server on 1.1.1.3. See `mrsk accessory` for all the commands possible.
332
332
 
333
+ ### Using Cron
334
+
335
+ You can use a specific container to run your Cron jobs:
336
+
337
+ ```yaml
338
+ servers:
339
+ cron:
340
+ hosts:
341
+ - 192.168.0.1
342
+ cmd:
343
+ bash -c "cat config/crontab | crontab - && cron -f"
344
+ ```
345
+
346
+ This assumes the Cron settings are stored in `config/crontab`.
347
+
333
348
  ### Using a generated .env file
334
349
 
335
350
  If you're using a centralized secret store, like 1Password, you can create `.env.erb` as a template which looks up the secrets. Example of a .env.erb file:
@@ -498,7 +513,7 @@ If you wish to remove the entire application, including Traefik, containers, ima
498
513
 
499
514
  ## Stage of development
500
515
 
501
- This is alpha software. Lots of stuff is missing. Lots of stuff will keep moving around for a while.
516
+ This is beta software. Commands may still move around. But we're live in production at [37signals](https://37signals.com).
502
517
 
503
518
  ## License
504
519
 
@@ -13,7 +13,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base
13
13
  execute *accessory.run
14
14
  end
15
15
 
16
- audit_broadcast "Booted accessory #{name}"
16
+ audit_broadcast "Booted accessory #{name}" unless options[:skip_broadcast]
17
17
  end
18
18
  end
19
19
  end
data/lib/mrsk/cli/app.rb CHANGED
@@ -5,18 +5,27 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
5
5
  using_version(options[:version] || most_recent_version_available) do |version|
6
6
  say "Start container with version #{version} (or reboot if already running)...", :magenta
7
7
 
8
+ cli = self
9
+
8
10
  MRSK.config.roles.each do |role|
9
11
  on(role.hosts) do |host|
10
12
  execute *MRSK.auditor.record("Booted app version #{version}"), verbosity: :debug
11
13
 
12
14
  begin
13
- execute *MRSK.app.stop, raise_on_non_zero_exit: false
15
+ old_version = capture_with_info(*MRSK.app.current_running_version).strip
14
16
  execute *MRSK.app.run(role: role.name)
17
+
18
+ cli.say "Waiting #{MRSK.config.readiness_delay}s for app to boot...", :magenta
19
+ sleep MRSK.config.readiness_delay
20
+
21
+ execute *MRSK.app.stop(version: old_version), raise_on_non_zero_exit: false if old_version.present?
22
+
15
23
  rescue SSHKit::Command::Failed => e
16
24
  if e.message =~ /already in use/
17
- error "Rebooting container with same version already deployed on #{host}"
25
+ error "Rebooting container with same version #{version} already deployed on #{host} (may cause gap in zero-downtime promise!)"
18
26
  execute *MRSK.auditor.record("Rebooted app version #{version}"), verbosity: :debug
19
27
 
28
+ execute *MRSK.app.stop(version: version)
20
29
  execute *MRSK.app.remove_container(version: version)
21
30
  execute *MRSK.app.run(role: role.name)
22
31
  else
data/lib/mrsk/cli/base.rb CHANGED
@@ -20,6 +20,8 @@ module Mrsk::Cli
20
20
  class_option :config_file, aliases: "-c", default: "config/deploy.yml", desc: "Path to config file"
21
21
  class_option :destination, aliases: "-d", desc: "Specify destination to be used for config file (staging -> deploy.staging.yml)"
22
22
 
23
+ class_option :skip_broadcast, aliases: "-B", type: :boolean, default: false, desc: "Skip audit broadcasts"
24
+
23
25
  def initialize(*)
24
26
  super
25
27
  load_envs
@@ -1,5 +1,7 @@
1
1
  class Mrsk::Cli::Healthcheck < Mrsk::Cli::Base
2
- MAX_ATTEMPTS = 5
2
+ MAX_ATTEMPTS = 7
3
+
4
+ class HealthcheckError < StandardError; end
3
5
 
4
6
  default_command :perform
5
7
 
@@ -18,7 +20,7 @@ class Mrsk::Cli::Healthcheck < Mrsk::Cli::Base
18
20
  if status == "200"
19
21
  info "#{target} succeeded with 200 OK!"
20
22
  else
21
- raise "#{target} failed with status #{status}"
23
+ raise HealthcheckError, "#{target} failed with status #{status}"
22
24
  end
23
25
  rescue SSHKit::Command::Failed
24
26
  if attempt <= MAX_ATTEMPTS
@@ -31,7 +33,7 @@ class Mrsk::Cli::Healthcheck < Mrsk::Cli::Base
31
33
  raise
32
34
  end
33
35
  end
34
- rescue SSHKit::Command::Failed => e
36
+ rescue SSHKit::Command::Failed, HealthcheckError => e
35
37
  error capture_with_info(*MRSK.healthcheck.logs)
36
38
 
37
39
  if e.message =~ /curl/
data/lib/mrsk/cli/main.rb CHANGED
@@ -32,7 +32,7 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base
32
32
  invoke "mrsk:cli:prune:all"
33
33
  end
34
34
 
35
- audit_broadcast "Deployed app in #{runtime.to_i} seconds"
35
+ audit_broadcast "Deployed app in #{runtime.to_i} seconds" unless options[:skip_broadcast]
36
36
  end
37
37
 
38
38
  desc "redeploy", "Deploy app to servers without bootstrapping servers, starting Traefik, pruning, and registry login"
@@ -47,7 +47,7 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base
47
47
  invoke "mrsk:cli:app:boot"
48
48
  end
49
49
 
50
- audit_broadcast "Redeployed app in #{runtime.to_i} seconds"
50
+ audit_broadcast "Redeployed app in #{runtime.to_i} seconds" unless options[:skip_broadcast]
51
51
  end
52
52
 
53
53
  desc "rollback [VERSION]", "Rollback app to VERSION"
@@ -55,14 +55,22 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base
55
55
  MRSK.version = version
56
56
 
57
57
  if container_name_available?(MRSK.config.service_with_version)
58
- say "Stop current version, then start version #{version}...", :magenta
58
+ say "Start version #{version}, then stop the old version...", :magenta
59
+
60
+ cli = self
59
61
 
60
62
  on(MRSK.hosts) do |host|
61
- execute *MRSK.app.stop, raise_on_non_zero_exit: false
63
+ old_version = capture_with_info(*MRSK.app.current_running_version).strip.presence
64
+
62
65
  execute *MRSK.app.start
66
+
67
+ cli.say "Waiting #{MRSK.config.readiness_delay}s for app to start...", :magenta
68
+ sleep MRSK.config.readiness_delay
69
+
70
+ execute *MRSK.app.stop(version: old_version), raise_on_non_zero_exit: false
63
71
  end
64
72
 
65
- audit_broadcast "Rolled back app to version #{version}"
73
+ audit_broadcast "Rolled back app to version #{version}" unless options[:skip_broadcast]
66
74
  else
67
75
  say "The app version '#{version}' is not available as a container (use 'mrsk app containers' for available versions)", :red
68
76
  end
@@ -138,7 +146,7 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base
138
146
  if options[:confirmed] || ask(remove_confirmation_question, limited_to: %w( y N ), default: "N") == "y"
139
147
  invoke "mrsk:cli:traefik:remove", [], options.without(:confirmed)
140
148
  invoke "mrsk:cli:app:remove", [], options.without(:confirmed)
141
- invoke "mrsk:cli:accessory:remove", [ "all" ]
149
+ invoke "mrsk:cli:accessory:remove", [ "all" ], options
142
150
  invoke "mrsk:cli:registry:logout", [], options.without(:confirmed)
143
151
  end
144
152
  end
@@ -18,8 +18,10 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
18
18
  docker :start, service_with_version
19
19
  end
20
20
 
21
- def stop
22
- pipe current_container_id, xargs(docker(:stop))
21
+ def stop(version: nil)
22
+ pipe \
23
+ version ? container_id_for_version(version) : current_container_id,
24
+ xargs(docker(:stop))
23
25
  end
24
26
 
25
27
  def info
@@ -132,6 +134,10 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
132
134
  end
133
135
  end
134
136
 
137
+ def container_id_for_version(version)
138
+ container_id_for(container_name: service_with_version(version))
139
+ end
140
+
135
141
  def service_filter
136
142
  [ "--filter", "label=service=#{config.service}" ]
137
143
  end
@@ -61,7 +61,7 @@ class Mrsk::Configuration::Role
61
61
  "traefik.http.routers.#{config.service}.rule" => "PathPrefix(`/`)",
62
62
  "traefik.http.services.#{config.service}.loadbalancer.healthcheck.path" => config.healthcheck["path"],
63
63
  "traefik.http.services.#{config.service}.loadbalancer.healthcheck.interval" => "1s",
64
- "traefik.http.middlewares.#{config.service}.retry.attempts" => "3",
64
+ "traefik.http.middlewares.#{config.service}.retry.attempts" => "5",
65
65
  "traefik.http.middlewares.#{config.service}.retry.initialinterval" => "500ms"
66
66
  }
67
67
  else
@@ -136,6 +136,9 @@ class Mrsk::Configuration
136
136
  { "path" => "/up", "port" => 3000 }.merge(raw_config.healthcheck || {})
137
137
  end
138
138
 
139
+ def readiness_delay
140
+ raw_config.readiness_delay || 7
141
+ end
139
142
 
140
143
  def valid?
141
144
  ensure_required_keys_present && ensure_env_available
data/lib/mrsk/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mrsk
2
- VERSION = "0.8.1"
2
+ VERSION = "0.8.3"
3
3
  end
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.8.1
4
+ version: 0.8.3
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-02-20 00:00:00.000000000 Z
11
+ date: 2023-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport