oye 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +2 -0
  4. data/lib/oye.rb +156 -40
  5. data/lib/oye/version.rb +1 -1
  6. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba0137a6da4e4541a1691339760c047d60c4b223aafbdccc7195ceb85ebef815
4
- data.tar.gz: b489de80c32505ff4009e30924ba1e1ba45698b456371a57dc6c917600e7e7ff
3
+ metadata.gz: bd9695ade1c74d7e4a4c0593cd39f0e559f94a3242586e905d33eb66dbc30f49
4
+ data.tar.gz: ca15ae1503c2fe6777c0a3f9dfc1a7be7a8975407931c8d192930a0524812ef3
5
5
  SHA512:
6
- metadata.gz: bdf339dfbbae4ab3e961002c952532ce6aad899ce6f1d453ecf23afbaaa94aed67430cc2fcfca7845a2dba608df6b66e59d95530bf15d6fc0b00c894f707ef52
7
- data.tar.gz: e22782ff4bfcf7f59ea864c52ac72e5469c265e90a0fe4fb21d2fee86b4cb3f85d6c3fef5ed9e44c1a726f6ee0944340d444a39f0495d1b1d128da640b093fb4
6
+ metadata.gz: e59fb07e4d00d6551cbec9edd4524da762bedb0641cc27e546d11f809d7424b6b995180d66ee0f4b425a646806e381a8699a112c8136977bf23c9967c03d39a5
7
+ data.tar.gz: '009310c48f9299dc31750fcb4fbc5316a1b2f52e3a1ae48973e2eab950ce563ddf6cc065c7896a4dc355ec6a2bdcd65bef73d4e52d74eabf4bf17a03a8d9c810'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- oye (0.1.1)
4
+ oye (0.1.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -7,3 +7,5 @@ A continuous monitoring tool that does a few things:
7
7
  3. restarts the rails app with the new code
8
8
 
9
9
  [ ] use multithreaading. each thread should watch a unique repo.
10
+ [ ] run rails tests inside Oye.monitor
11
+ [ ] check for irregularities in @repos, e.g two repeated cloned repos
data/lib/oye.rb CHANGED
@@ -2,11 +2,16 @@ $LOAD_PATH.unshift __dir__
2
2
 
3
3
  require "oye/version"
4
4
  require 'fileutils'
5
+ require 'yaml'
5
6
 
6
7
  module Oye
7
8
  class Error < StandardError; end
8
9
 
9
- @interval = 5
10
+ DEFAULT_WATCH_INTERVAL = 5
11
+ DEFAULT_PORT = 3000
12
+ DEFAULT_ENVIRONMENTS = %w(development production test)
13
+ LOG_FORMAT = "[%Y-%m-%d %H:%M:%S]"
14
+
10
15
 
11
16
  class << self
12
17
  def start(args)
@@ -18,97 +23,136 @@ module Oye
18
23
 
19
24
  FileUtils.mkdir_p(oyedir)
20
25
 
26
+ @repos = {}
21
27
  read_config
22
28
 
23
29
  list if(args.include?('-l') or args.include?('--list'))
24
30
 
25
31
  if(args.include?('-i') or args.include?('--info'))
26
32
  args.map! {|a| a == '--info' ? '-i' : a}
27
- _, @pattern = args.slice!(args.index('-i'),2)
33
+ _, @pattern = args.slice(args.index('-i'),2)
28
34
  @pattern = @pattern.nil? ? /.*/ : Regexp.new(@pattern)
29
35
  info
30
36
  end
31
37
 
38
+ @interval = DEFAULT_WATCH_INTERVAL
32
39
  if(args.include?('-t') or args.include?('--time'))
33
40
  args.map! {|a| a == '--time' ? '-t' : a}
34
- _, @interval = args.slice!(args.index('-i'),2)
41
+ _, @interval = args.slice(args.index('-t'),2)
35
42
  @interval = @interval.to_i
43
+ unless @interval > 0
44
+ puts "Interval must a positive integer"
45
+ exit
46
+ end
47
+ end
48
+
49
+ @port = DEFAULT_PORT
50
+ if(args.include?('-p') or args.include?('--port'))
51
+ args.map! {|a| a == '--port' ? '-p' : a}
52
+ _, @port = args.slice(args.index('-p'),2)
53
+ @port = @port.to_i
54
+ unless @port > 0
55
+ puts "Port must a positive integer"
56
+ exit
57
+ end
58
+ end
59
+
60
+ @environment = 'production'
61
+ if(args.include?('-e') or args.include?('--environment'))
62
+ args.map! {|a| a == '--environment' ? '-e' : a}
63
+ _, @environment = args.slice(args.index('-e'),2)
64
+ unless DEFAULT_ENVIRONMENTS.include?(@environment)
65
+ puts "Specify a supported environment for -e option"
66
+ exit
67
+ end
36
68
  end
37
69
 
38
70
  monitor
39
71
  end
40
72
 
41
73
  def read_config
42
- @repos = {}
43
-
44
- YAML.load(File.open(oye_config)).each do |origin, clone|
45
- @repos[origin] = {'clone' => clone}
74
+ YAML.load(File.open(oye_config)).each do |origin, clones|
75
+ @repos[origin] = {'clones' => clones}
46
76
  end
47
77
  end
48
78
 
49
79
  def help
50
80
  puts <<~eos
51
- -c, --config print config and log files
81
+ -c, --config print config, log and pid files
82
+ -e, --environment ENV environment for the app server [development|production|test] (default production)
52
83
  -h, --help print this message
53
84
  -i, --info [PATTERN] print info of repos matching PATTERN (default .*)
54
85
  -l, --list print monitored repos
86
+ -p, --port PORT port for app server (default 3000)
55
87
  -r, --restart restart oye
56
88
  -s, --stop stop oye
57
- -t, --time [SECS] time interval for repo monitoring (default 5)
89
+ -t, --time SECS time interval for repo monitoring (default 5)
58
90
  -v, --version print oye version
59
91
  eos
60
92
  exit
61
93
  end
62
94
 
63
- def restart_clone
64
- system("cd #{File.dirname(@repos[repo]['clone']}")
65
- system("git pull")
66
- system("kill $(cat pids/*)")
67
- system("unicorn_rails -l 178.128.15.65:3001 -c config/unicorn.rb -E production -D")
68
- end
69
-
70
95
  def monitor
71
96
  trap('TERM') { exit }
72
97
  trap('INT') { exit }
73
98
 
74
- not_found = []
75
- repos_dup = @repos
76
-
77
- repos_dup.keys.filter_map do |repo|
78
- unless File.exists?(repo)
79
- not_found << @repos.delete(repo)
80
- next
81
- end
82
-
83
- @repos[repo]['stat'] = File.stat(repo).ctime
84
- end
99
+ @repos.keys.filter_map do |origin|
100
+ next unless File.exists?(origin)
85
101
 
86
- unless not_found.empty?
87
- puts "\nWARNING Could not find repos:", not_found
102
+ @repos[origin]['stat'] = File.stat(origin).ctime
88
103
  end
89
104
 
90
- log_format = "[%Y-%m-%d %H:%M:%S]"
91
-
92
105
  pid = fork do
93
106
  begin
107
+ # initialize apps if they are not running
108
+ # TODO i dont like this loop
109
+ @repos.values.flatten.each do |app|
110
+ app['clones'].each do |clone|
111
+
112
+ if !File.exists?(clone)
113
+ log(clone, status: :warn, message: "Could not find repo")
114
+ next
115
+ elsif !File.exists?(app_pid_dir(clone))
116
+ log(clone, status: :warn, message: "Could not find pids directory")
117
+ next
118
+ elsif File.exists?(app_pid_file(clone))
119
+ # if pid fle exists, the app should be running and there's no need to be initialize it
120
+ next
121
+ end
122
+
123
+ initialize_clone(clone)
124
+
125
+ rescue Errno::ESRCH
126
+ end
127
+ end
128
+
94
129
  loop do
95
130
  repos_dup = @repos
96
- repos_dup.each do |repo|
97
- unless @repos[repo]['stat'] == File.stat(name).ctime
98
- @repos[repo]['stats'] = File.stat(name).ctime
131
+ repos_dup.keys.each do |origin|
132
+ unless File.exists?(origin)
133
+ log(origin, {status: :warn, message: "Could not find repo"})
134
+ next
135
+ end
99
136
 
100
- File.open(oye_logfile, 'a') do |f|
101
- f.puts "#{@repos[repo]['stats'].strftime(log_format)} #{repo}"
137
+ repos_dup[origin]['clones'].each do |clone|
138
+ unless File.exists?(clone)
139
+ log(clone, {status: :warn, message: "Could not find repo"})
140
+ next
102
141
  end
103
142
 
104
- restart_clone
143
+ unless @repos[origin]['stat'] == File.stat(origin).ctime
144
+ @repos[origin]['stat'] = File.stat(origin).ctime
145
+ stop_clone(clone) if File.exists?(app_pid_file(clone))
146
+ update_clone(clone)
147
+ initialize_clone(clone)
148
+ end
105
149
  end
106
150
  end
107
151
  sleep @interval
108
152
  end
109
- rescue => e
110
- abort "There was a fatal system error while starting oye: #{e.message}, #{caller}"
111
153
  end
154
+ rescue => e
155
+ abort "Fatal system error while initializing oye: #{e.message}, #{caller}"
112
156
  end
113
157
 
114
158
  File.open(oye_pidfile, 'w') { |f| f.puts pid }
@@ -116,14 +160,59 @@ module Oye
116
160
  ::Process.detach pid
117
161
  end
118
162
 
163
+ def log(repo, options = {})
164
+ log_message = [
165
+ Time.now.strftime(LOG_FORMAT),
166
+ repo,
167
+ "[#{options[:status].to_s.upcase}]",
168
+ "\"#{options[:message]}\""
169
+ ].join(' ')
170
+
171
+ File.open(oye_logfile, 'a') do |f|
172
+ f.puts log_message
173
+ end
174
+ end
175
+
176
+ def initialize_clone(dir)
177
+ Dir.chdir(dir) do
178
+ %x(bundle)
179
+
180
+ %x(RAILS_ENV=#{@environment} rails db:migrate)
181
+
182
+ if @environment == 'production'
183
+ %x(RAILS_ENV=production rails assets:{clean,precompile})
184
+ end
185
+ end
186
+
187
+ %x{unicorn_rails -l :#{@port} -c #{unicorn_file(dir)} -E #{@environment} -D}
188
+ rescue => e
189
+ log(dir, status: :warn, message: "#{__method__.to_s} (#{e.message})")
190
+ end
191
+
192
+ def stop_clone(dir)
193
+ Process.kill 'TERM', app_pid(dir)
194
+ end
195
+
196
+ def update_clone(dir)
197
+ system("git -C #{dir} pull", [:out, :err] => File::NULL)
198
+
199
+ log(dir, status: :info, message: "Pulled from origin")
200
+ rescue => e
201
+ log(dir, status: :warn, message: "#{__method__.to_s} (#{e.message})")
202
+ end
203
+
119
204
  def list
120
- puts @repos.keys
205
+ @repos.each do |origin, clones|
206
+ puts origin
207
+ clones.values.flatten.map {|clone| puts clone.prepend " - "}
208
+ end
121
209
  exit
122
210
  end
123
211
 
124
212
  def config
125
213
  puts "Config file: #{oye_config}"
126
214
  puts "Log file: #{oye_logfile}"
215
+ puts "PID file: #{oye_pidfile}"
127
216
  exit
128
217
  end
129
218
 
@@ -162,12 +251,18 @@ module Oye
162
251
  exit
163
252
  end
164
253
 
254
+ # TODO ensure that pid corresponds to 'oye' process. maybe check
255
+ # command name like 'ps(1)'
165
256
  def stop
257
+ Process.kill oye_pid
166
258
  end
167
259
 
260
+ # TODO implement
168
261
  def restart
169
262
  end
170
263
 
264
+ private
265
+
171
266
  def oyedir
172
267
  "#{ENV['HOME']}/.oye"
173
268
  end
@@ -184,5 +279,26 @@ module Oye
184
279
  def oye_pidfile
185
280
  "#{oyedir}/oye.pid"
186
281
  end
282
+
283
+ def oye_pid
284
+ File.read(oye_pidfile).to_i
285
+ end
286
+
287
+
288
+ def unicorn_file(dir)
289
+ File.join(dir, "config/unicorn.rb")
290
+ end
291
+
292
+ def app_pid(dir)
293
+ File.read(app_pid_file(dir)).to_i
294
+ end
295
+
296
+ def app_pid_file(dir)
297
+ File.join(app_pid_dir(dir), "unicorn.pid")
298
+ end
299
+
300
+ def app_pid_dir(dir)
301
+ File.join(dir, "pids")
302
+ end
187
303
  end
188
304
  end
data/lib/oye/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Oye
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oye
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - sergioro
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-21 00:00:00.000000000 Z
11
+ date: 2020-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips