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.
- checksums.yaml +7 -0
- data/README.md +136 -0
- data/cap-runit.gemspec +17 -0
- data/lib/cap-runit.rb +134 -0
- data/lib/capistrano/runit.rb +1 -0
- metadata +63 -0
checksums.yaml
ADDED
@@ -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
|
data/README.md
ADDED
@@ -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
|
+
|
data/cap-runit.gemspec
ADDED
@@ -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
|
data/lib/cap-runit.rb
ADDED
@@ -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:
|