cap-runit 0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c3e6b7e1396dc85e4f664fac65423f7b17eb80e5
4
+ data.tar.gz: e68549492f3f0e5cf8301dd473b15ea4fe778347
5
+ SHA512:
6
+ metadata.gz: 0fd9c847ffb4cb4fffd273b5cd754b66f1a985427ca1e4c9fb303e7dff41ae4ff69a7d2577374836a0fa9bf2aa03cd50f0eca5bc771db15ace1f68d8d07e73af
7
+ data.tar.gz: d84be89f74bb843f7f3a676962463e1b6c68c31f8879eac2c0d84fdd670f89d7f2bab9547dd936ecd187e169513895b703685ac2e03678600b710cec392c11d2
@@ -0,0 +1,136 @@
1
+ # Capistrano 3 Runit Support
2
+
3
+ cap-runit provides a helper for building runit services. It lets you easily
4
+ deploy services using capistrano 3 and run them with runit.
5
+
6
+ ## Installation
7
+
8
+ Using bundler: Add `gem 'cap-runit'` to your `Gemfile` and `require 'bundler';
9
+ Bundler.require` to your `Capfile`.
10
+
11
+ Not using bundler: `gem install cap-runit` and add `require 'capistrano/runit'`
12
+ to your `Capfile`.
13
+
14
+ ## Usage
15
+
16
+ cap-runit provides a helper method `runit_service` to Capistrano. As the
17
+ philosophy of runit is that everything is just a shell script, `cap-runit`
18
+ requires you to write a shell script.
19
+
20
+ For example, to run sidekiq, you might do something like this:
21
+
22
+
23
+ ```ruby
24
+ runit_service 'sidekiq' do
25
+
26
+ run <<-EOF
27
+ #!/bin/bash
28
+ cd /var/www/app/current
29
+ exec bundle exec sidekiq -e production -C ./config/sidekiq.yml 2>&1
30
+ EOF
31
+
32
+ end
33
+ ```
34
+
35
+ This creates three capistrano tasks:
36
+
37
+ ```
38
+ cap sidekiq:restart # Restart bugsnag-event-server
39
+ cap sidekiq:start # Start bugsnag-event-server
40
+ cap sidekiq:stop # Stop bugsnag-event-server
41
+ ```
42
+
43
+ If you'd like to restart sidekiq when your app restarts, you also need to
44
+ specify:
45
+
46
+ ```ruby
47
+ namespace :deploy do
48
+ after :publishing, 'sidekiq:restart'
49
+ end
50
+ ```
51
+
52
+ ### Logging
53
+
54
+ Runit sends the STDOUT of your `run` script to the `log` script. To get these
55
+ logs somewhere useful, you can use any program that reads from STDIN. But
56
+ `svlogd` is recommended as it works well with runit and handles log rotation
57
+ automatically.
58
+
59
+ ```ruby
60
+ runit_service 'sidekiq' do
61
+
62
+ run <<-EOF
63
+ #!/bin/bash -l
64
+ cd /var/www/app/current
65
+ exec bundle exec sidekiq -e production -C ./config/sidekiq.yml 2>&1
66
+ EOF
67
+
68
+ log <<-EOF
69
+ #!/bin/sh
70
+ mkdir -p /var/log/sidekiq
71
+ exec svlogd -tt /var/log/sidekiq
72
+ EOF
73
+ end
74
+ ```
75
+
76
+ ### Crash notifications
77
+
78
+ If you need to be notified of when a crash happens in your app, you can also
79
+ configure a `finish` script. This is run whenever the `run` script exits.
80
+
81
+ ```ruby
82
+ runit_service 'sidekiq' do
83
+
84
+ run <<-EOF
85
+ #!/bin/bash -l
86
+ cd /var/www/app/current
87
+ exec bundle exec sidekiq -e production -C ./config/sidekiq.yml 2>&1
88
+ EOF
89
+
90
+ log <<-EOF
91
+ #!/bin/sh
92
+ mkdir -p /var/log/sidekiq
93
+ exec svlogd -tt /var/log/sidekiq
94
+ EOF
95
+
96
+ finish <<-EOF
97
+ #!/bin/sh
98
+ export BUGSNAG_API_KEY=bf04f47b034e8df9d22ee75f30fdae6a
99
+ [ "$1" = 0 ] || exec bugsnag-runit "$0"
100
+ EOF
101
+ end
102
+
103
+ ```
104
+
105
+ ## Configuration
106
+
107
+ The only configuration variable you need to pass is `runit_service_directory`
108
+
109
+ ```ruby
110
+ set :runit_service_directory, "/apps/service"
111
+ ```
112
+
113
+ The service directory needs to be run with `runsvdir` and owned by the
114
+ capistrano user. To configure `runsvdir` you can create the following files:
115
+
116
+
117
+ ```bash
118
+ #/etc/service/cap-runit/run
119
+
120
+ #!/bin/bash
121
+ exec chpst -udeploy -- runsvdir /apps/service 2>&1
122
+ ```
123
+
124
+ And
125
+
126
+ ```bash
127
+ #/etc/service/cap-runit/log/run
128
+
129
+ #!/bin/sh
130
+ exec svlogd -tt /var/log/cap-runit
131
+ ```
132
+
133
+ These files should both be owned by root and `chmod +x`. This way the deploy
134
+ user does not need root permissions to reboot a service on deploy.
135
+
136
+
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = 'cap-runit'
3
+ gem.version = '0.1'
4
+
5
+ gem.summary = 'Capistrano 3 Runit integration'
6
+ gem.description = "Template for managing runit directories with capistrano 3"
7
+
8
+ gem.authors = ['Conrad Irwin']
9
+ gem.email = %w(conrad@bugsnag.com)
10
+ gem.homepage = 'http://github.com/ConradIrwin/cap-runit'
11
+
12
+ gem.license = 'MIT'
13
+
14
+ gem.add_dependency 'capistrano', '>= 3.0'
15
+
16
+ gem.files = `git ls-files`.split("\n")
17
+ end
@@ -0,0 +1,134 @@
1
+ # TODO:CI make this into a gem.
2
+
3
+ set :runit_service_dir, "/apps/service"
4
+
5
+ class RunitServiceBuilder
6
+
7
+ def initialize(&block)
8
+ instance_eval(&block)
9
+ unless @roles
10
+ raise ArgumentError, "No role configured for runit service"
11
+ end
12
+ unless @run
13
+ raise ArgumentError, "No run script configured for runit service"
14
+ end
15
+ end
16
+
17
+ def roles(*roles)
18
+ @roles = roles unless roles == []
19
+ @roles
20
+ end
21
+
22
+ def run(str=nil)
23
+ @run = str unless str.nil?
24
+ @run
25
+ end
26
+
27
+ def log(str=nil)
28
+ @log = str unless str.nil?
29
+ @log
30
+ end
31
+
32
+ def finish(str=nil)
33
+ @finish = str unless str.nil?
34
+ @finish
35
+ end
36
+
37
+ end
38
+
39
+ # Defines a runit service.
40
+ #
41
+ # @example
42
+ #
43
+ # # A runit directory that your deploy user can write to.
44
+ # # You can set one of these up using runsvdir.
45
+ #
46
+ # set :runit_service_dir, '/etc/service'
47
+ #
48
+ # # The first argument is the name of the service.
49
+ # # The remainder are passed to "on" to decide
50
+ # # which servers to use
51
+ # runit_service 'sidekiq', roles(:sidekiq) do
52
+ #
53
+ # # required, a bash script that execs your app
54
+ # run <<-EOF
55
+ # #!/bin/bash
56
+ # cd /var/www/app
57
+ # exec bundle exec sidekiq 2>&1
58
+ # EOF
59
+ #
60
+ # # optional, a log script that reads stdin/stdout
61
+ # log <<-EOF
62
+ # #!/bin/bash
63
+ # mkdir -p /var/log/app/sidekiq
64
+ # exec syslogd -tt /var/log/app/sidekiq
65
+ # EOF
66
+ #
67
+ # # optional, a finish script that runs when your app quits
68
+ # finish <<-EOF
69
+ # #!/bin/bash
70
+ # echo 'QUIT' >> /var/log/app/sidekiq/current
71
+ # EOF
72
+ #
73
+ # end
74
+ #
75
+ def runit_service(name, &block)
76
+ runit_service_dir = fetch(:runit_service_dir)
77
+
78
+ service = RunitServiceBuilder.new(&block)
79
+
80
+ namespace name do
81
+ desc "Configure #{name} runit"
82
+ task :configure do
83
+ on roles(service.roles) do
84
+ unless test("[ -e #{runit_service_dir}/#{name}/run ]")
85
+ execute <<-EOF
86
+ rm -rf #{runit_service_dir}/#{name}
87
+ mkdir -p #{runit_service_dir}/#{name}/log
88
+ EOF
89
+
90
+ upload! StringIO.new(service.run), "#{runit_service_dir}/#{name}/run"
91
+
92
+ if service.log
93
+ upload! StringIO.new(service.log), "#{runit_service_dir}/#{name}/log/run"
94
+ end
95
+
96
+ if service.finish
97
+ upload! StringIO.new(service.finish), "#{runit_service_dir}/#{name}/finish"
98
+ end
99
+
100
+ execute "chmod +x #{runit_service_dir}/#{name}/run #{runit_service_dir}/#{name}/log/run"
101
+ end
102
+ end
103
+ end
104
+
105
+ desc "Start #{name}"
106
+ task start: :configure do
107
+ on roles(*service.roles) do
108
+ execute "sv start #{runit_service_dir}/#{name}"
109
+ end
110
+ end
111
+
112
+ desc "Stop #{name}"
113
+ task :stop do
114
+ on roles(*service.roles) do
115
+ execute "sv stop #{runit_service_dir}/#{name}"
116
+ end
117
+ end
118
+
119
+ desc "Restart #{name}"
120
+ task restart: :configure do
121
+ on roles(*service.roles) do
122
+ execute "sv restart #{runit_service_dir}/#{name}"
123
+ end
124
+ end
125
+
126
+ desc "Disable #{name}"
127
+ task :disable do
128
+ on roles(*service.roles) do
129
+ execute "rm -rf #{runit_service_dir}/#{name}"
130
+ end
131
+ end
132
+ end
133
+ end
134
+
@@ -0,0 +1 @@
1
+ require 'cap-runit'
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cap-runit
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Conrad Irwin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: capistrano
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ description: Template for managing runit directories with capistrano 3
28
+ email:
29
+ - conrad@bugsnag.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - README.md
35
+ - cap-runit.gemspec
36
+ - lib/cap-runit.rb
37
+ - lib/capistrano/runit.rb
38
+ homepage: http://github.com/ConradIrwin/cap-runit
39
+ licenses:
40
+ - MIT
41
+ metadata: {}
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 2.0.3
59
+ signing_key:
60
+ specification_version: 4
61
+ summary: Capistrano 3 Runit integration
62
+ test_files: []
63
+ has_rdoc: