meroku 0.0.0 → 0.1.28

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,416 @@
1
+ module Meroku
2
+
3
+ # Methods that doesn't have a proper namespace yet
4
+ module Util
5
+
6
+ require 'open3'
7
+ class Subprocess
8
+ def initialize(cmd, &block)
9
+ # see: http://stackoverflow.com/a/1162850/83386
10
+ Open3.popen3(cmd) do |stdin, stdout, stderr, thread|
11
+ stdin.close
12
+ # read each stream from a new thread
13
+ { :out => stdout, :err => stderr }.each do |key, stream|
14
+ Thread.new do
15
+ until (line = stream.gets).nil? do
16
+ # yield the block depending on the stream
17
+ if key == :out
18
+ yield line, nil, thread if block_given?
19
+ else
20
+ yield nil, line, thread if block_given?
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ thread.join # don't exit until the external process is done
27
+ raise "ErrorDuringPopen3" if thread.value != 0
28
+ end
29
+ end
30
+ end
31
+
32
+ def additional_env_vars(app_name, dbtype)
33
+ require 'rest-client'
34
+ resp = RestClient.post 'https://www.meroku.com/meroku/apps/0/additional_env_vars.json', { :"dbtype" => dbtype, authentication: { app_name: app_name, token: cli_token} }
35
+ JSON.parse(resp)["data"]
36
+ end
37
+
38
+ def update_authorized_keys_file
39
+ `sudo -i -u u#{self.user_id} sh -c "echo '#{self.key}' | tee /home/u#{self.user_id}/.ssh/authorized_keys"`
40
+ end
41
+
42
+ def setup_repo
43
+ app = Meroku::App.find(self.app_id)
44
+ user = Meroku::User.find(self.user_id)
45
+ `sudo -i -u u#{user.id} sh -c "mkdir ~/#{app.name}.git"`
46
+ `sudo -i -u u#{user.id} sh -c "cd ~/#{app.name}.git && git init --bare"`
47
+ end
48
+
49
+
50
+ def self.add_unix_users
51
+ puts "DB8 #{Meroku::User.all.size} users to add..."
52
+ Meroku::User.all.each do |user|
53
+ puts "DB8 Adding #{user.id} #{user.email}"
54
+ `sudo adduser --disabled-password --gecos "" u#{user.id}`
55
+ `sudo usermod -aG meroku u#{user.id}`
56
+ #`sudo -i -u u#{user.id} sh -c "mkdir ~/.ssh/"`
57
+ #`sudo -i -u u#{user.id} sh -c "touch ~/.ssh/authorized_keys"`
58
+ #a = IO.write("/tmp/tmp.txt",user.encrypted_password)
59
+ #`sudo -i -u u#{user.id} sh -c "cp /tmp/tmp.txt /home/u1/.encrypted_password"`
60
+ #`sudo -i -u u#{user.id} sh -c "cp /tmp/tmp.txt /home/u1/.encrypted_password 2>&1"`
61
+ `sudo -i -u u#{user.id} sh -c "git config --global core.hooksPath /opt/githooks"`
62
+
63
+ #user.keys.each do |key|
64
+ # puts "DB8 Adding key #{key.id} #{key.key[0..9]} ..."
65
+ # `sudo -i -u u#{user.id} sh -c "echo '#{key.key}' | tee /home/u#{user.id}/.ssh/authorized_keys"`
66
+ #end
67
+
68
+ end
69
+ end
70
+
71
+ # this is a callback called from the User model
72
+ def add_unix_user
73
+ `sudo adduser --disabled-password --gecos "" u#{self.id}`
74
+ `sudo usermod -aG meroku u#{self.id}`
75
+ `sudo -i -u u#{self.id} sh -c "mkdir ~/.ssh/"`
76
+ `sudo -i -u u#{self.id} sh -c "touch ~/.ssh/authorized_keys"`
77
+ Rails.logger.debug "DB8 A"
78
+ a = IO.write("/tmp/tmp.txt",self.encrypted_password)
79
+ Rails.logger.debug a
80
+ Rails.logger.debug `sudo -i -u u#{self.id} sh -c "cp /tmp/tmp.txt /home/u1/.encrypted_password"`
81
+ Rails.logger.debug `sudo -i -u u#{self.id} sh -c "cp /tmp/tmp.txt /home/u1/.encrypted_password 2>&1"`
82
+ Rails.logger.debug "DB8 A end"
83
+ `sudo -i -u u#{self.id} sh -c "git config --global core.hooksPath /opt/githooks"`
84
+ end
85
+
86
+ # this is a callback called from the Meroku::Collaborator model
87
+ def add_mysql_user
88
+ user = Meroku::User.find(self.user_id)
89
+ `sudo mysql -pbitnami -e 'FLUSH PRIVILEGES; set password for "u#{self.user_id}"@"localhost" = PASSWORD("#{user.database_password}"); FLUSH PRIVILEGES;'`
90
+ Rails.logger.debug "DB8 add_mysql_user db password for user id #{user.id} set to #{user.database_password}"
91
+ end
92
+
93
+ # self is a Meroku::Collaborator
94
+ def add_mysql_grants
95
+ app = Meroku::App.find(self.app_id)
96
+ `sudo mysql -pbitnami -e 'FLUSH PRIVILEGES; GRANT ALL PRIVILEGES ON #{app.name}.* TO "u#{self.user_id}"@"localhost"; FLUSH PRIVILEGES;'`
97
+ end
98
+
99
+ def create_empty_pg_db
100
+ app = Meroku::App.find(self.app_id)
101
+ `PGPASSWORD=bitnami psql -U postgres -c "CREATE DATABASE #{app.name};"`
102
+ end
103
+
104
+ def add_pg_user
105
+ user = Meroku::User.find(self.user_id)
106
+ `PGPASSWORD=bitnami psql -U postgres -c "CREATE USER u#{self.user_id} WITH PASSWORD '#{user.database_password}';"`
107
+ end
108
+
109
+ def add_pg_grants
110
+ app = Meroku::App.find(self.app_id)
111
+ `PGPASSWORD=bitnami psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE #{app.name} TO u#{self.user_id};"`
112
+ end
113
+
114
+ # self is a Meroku::Collaborator
115
+ def create_empty_mysql_db
116
+ app = Meroku::App.find(self.app_id)
117
+ `sudo mysql -pbitnami -e 'CREATE DATABASE #{app.name}'`
118
+ end
119
+
120
+ # self refers to a Meroku::User
121
+ def install_rvm_for_user
122
+ `sudo -i -u u#{self.id} /bin/bash -c 'curl -sSL https://get.rvm.io | bash'`
123
+ end
124
+
125
+ def public_key_exists?
126
+ File.exist?(Dir.home + "/.ssh/id_rsa.pub")
127
+ end
128
+
129
+ def valid_json?(json)
130
+ JSON.parse(json)
131
+ return true
132
+ rescue JSON::ParserError => e
133
+ return false
134
+ end
135
+
136
+ def cli_logged_in?
137
+ if File.exist?("/tmp/meroku.token")
138
+ return true
139
+ else
140
+ puts "Not logged in"
141
+ return false
142
+ end
143
+ end
144
+
145
+ def cli_token
146
+ `cat /tmp/meroku.token`.chomp
147
+ end
148
+
149
+ def cli_user_id
150
+ user_id = `cat /tmp/meroku.id`
151
+ end
152
+
153
+ def app_name
154
+ git_remote = `git remote get-url meroku`.chomp
155
+ git_remote =~ /\@www.meroku.com\:(.*?).git\Z/
156
+ $1
157
+ end
158
+
159
+ def ssh(ip, command)
160
+ puts `ssh -tt -o "StrictHostKeyChecking=no" -i ~/crypto/meroku/meroku.id_rsa bitnami@#{ip} '#{command}'`
161
+ end
162
+
163
+ def ssh2(ip, command)
164
+ print "+ #{command} "
165
+ Meroku::Util::Subprocess.new "ssh -tt -o StrictHostKeyChecking=no -i ~/crypto/meroku/meroku.id_rsa bitnami@#{ip} '#{command}'" do |stdout, stderr, thread|
166
+ print "."
167
+ end
168
+ print "\n"
169
+
170
+ end
171
+
172
+ def ssh3(ip, command)
173
+ puts "+ #{command} "
174
+ Meroku::Util::Subprocess.new "ssh -tt -o StrictHostKeyChecking=no -i ~/crypto/meroku/meroku.id_rsa bitnami@#{ip} '#{command}'" do |stdout, stderr, thread|
175
+ print stdout
176
+ print stderr
177
+ end
178
+ print "\n"
179
+
180
+ end
181
+
182
+ def ec2_client
183
+ @ec2_client ||= Aws::EC2::Client.new(
184
+ region: 'us-east-1',
185
+ access_key_id: ENV['AWS_ACCESS_KEY_ID'],
186
+ secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
187
+ )
188
+ end
189
+
190
+ def server_being_built
191
+ ec2_get_ip_by_instance_id(unused_servers.first)
192
+ end
193
+
194
+ def ec2_get_ip_by_instance_id(instance_id)
195
+ ec2_client.describe_instances(
196
+ filters:
197
+ [
198
+ { name: "instance-id", values: [ instance_id ] }
199
+ ]
200
+ ).reservations.first.instances.first.public_ip_address
201
+ end
202
+
203
+ def meroku_servers
204
+ ec2_client.describe_instances(
205
+ filters:
206
+ [
207
+ { name: "tag:Name", values: ['meroku'] },
208
+ { name: "instance-state-name", values: ['pending', 'running'] }
209
+ ]
210
+ ).reservations
211
+ .map{ |a| a.instances }
212
+ .map{ |b|
213
+ b.map { |c| c.instance_id }
214
+ }
215
+ .flatten
216
+ end
217
+
218
+ # Returns the production servers instance id
219
+ def production_servers
220
+ ec2_client.describe_instances(
221
+ filters:
222
+ [
223
+ { name: "ip-address", values: [ Meroku::PRODUCTION_IP ] },
224
+ { name: "tag:Name", values: ['meroku'] },
225
+ { name: "instance-state-name", values: ['pending', 'running'] }
226
+ ]
227
+ ).map { |x| x.reservations }.flatten.map { |x| x.instances }.flatten.map { |x| x.instance_id }
228
+ rescue
229
+ []
230
+ end
231
+
232
+ def unused_servers
233
+ meroku_servers - production_servers
234
+ end
235
+
236
+ def terminate_unused_servers
237
+ unused_servers.each do |server|
238
+ puts "Terminating #{server}"
239
+ ec2_client.terminate_instances({ instance_ids: [ server ] })
240
+ sleep 1
241
+ end
242
+ end
243
+
244
+ def ec2_start_instance
245
+ resp = ec2_client.run_instances(
246
+ {
247
+ :image_id => 'ami-52a5dd44', #bitnami 2.4.1
248
+ :min_count => 1,
249
+ :max_count => 1,
250
+ :instance_type => "t2.small",
251
+ :key_name => "meroku.id_rsa"
252
+ }
253
+ )
254
+ resp[:instances][0][:instance_id]
255
+ end
256
+
257
+ def ec2_tag_instance(instance_id)
258
+ retries ||= 0
259
+ puts "create_tags try ##{ retries }"
260
+ ec2_client.create_tags( resources: [ instance_id ], tags: [ { key: 'Name', value: "meroku"}])
261
+ rescue
262
+ sleep 1
263
+ retry if (retries += 1) < 3
264
+ end
265
+
266
+ def ec2_await_boot(instance_id)
267
+ wait_timeout = 60
268
+ ec2_client.wait_until(:instance_running, instance_ids:[ instance_id ]) do |w|
269
+ w.max_attempts = 10
270
+ w.interval = wait_timeout/10
271
+ w.before_attempt do |n|
272
+ print "#{n}/10 "
273
+ end
274
+ end
275
+ public_ip_address = ec2_client.describe_instances(instance_ids: [instance_id])[0][0].instances[0].public_ip_address
276
+ puts public_ip_address
277
+ wait_time=40
278
+ 10.times do |i|
279
+ port_is_open = Socket.tcp(public_ip_address, 22, connect_timeout: 6) { true } rescue false
280
+ print "#{i}/10 "
281
+ break if port_is_open
282
+ sleep 8
283
+ end
284
+ print "\n"
285
+ puts `ssh -o "StrictHostKeyChecking=no" -i ~/crypto/meroku/meroku.id_rsa ubuntu@#{public_ip_address} uptime 2>/dev/null`
286
+ end
287
+
288
+ def self.shell_exec(command)
289
+ require 'open3'
290
+ Open3.popen2e(command) do |stdin, stdout_err, wait_thr|
291
+ while line = stdout_err.gets
292
+ IO.write("/home/bitnami/meroku/rails_app/log/nginx_rebuild.log", line, mode: 'a')
293
+ end
294
+ exit_status = wait_thr.value
295
+ unless exit_status.success?
296
+ raise "FAILED !!!"
297
+ end
298
+ end
299
+ end
300
+
301
+ def self.nginx_rebuild
302
+ IO.write("/home/bitnami/meroku/rails_app/log/nginx_rebuild.log", "ngin_rebuild() started\n")
303
+ command = <<-'HEREDOC'
304
+ set -ex;
305
+ sudo rm -vf /opt/bitnami/nginx/conf/vhosts/*;
306
+ sudo rm -vf /opt/bitnami/nginx/keys/clients/*;
307
+ HEREDOC
308
+ shell_exec(command)
309
+ IO.write("/tmp/www.conf", generate_nginx_config("www.meroku.com", "3000", nil) )
310
+ IO.write("/tmp/_.conf",nginx_fallback_vhost)
311
+
312
+ command = <<-'HEREDOC'
313
+ set -ex;
314
+ sudo mv -v /tmp/www.conf /opt/bitnami/nginx/conf/vhosts/;
315
+ sudo mv -v /tmp/_.conf /opt/bitnami/nginx/conf/vhosts/;
316
+ HEREDOC
317
+ shell_exec(command)
318
+
319
+ Meroku::App.all.each do |app|
320
+ port = (3000 + app.id).to_s
321
+ domains = "#{app.name}.meroku.com"
322
+ domains = "#{app.name}.meroku.com"
323
+ domains += " #{app.domains.pluck(:domain).join(" ")}" if app.domains.size > 0
324
+ cert = nil
325
+ cert = app.name if app.server_crt
326
+ IO.write("/tmp/#{app.name}.conf", generate_nginx_config(domains, port, cert) )
327
+ shell_exec("sudo mv -v /tmp/#{app.name}.conf /opt/bitnami/nginx/conf/vhosts/")
328
+ if app.server_crt
329
+ IO.write("/tmp/#{app.name}.crt", app.server_crt )
330
+ IO.write("/tmp/#{app.name}.key", app.server_key )
331
+ shell_exec "set -ex; sudo mv -v /tmp/#{app.name}.crt /opt/bitnami/nginx/keys/cli\
332
+ ents/"
333
+ shell_exec "set -ex; sudo mv -v /tmp/#{app.name}.key /opt/bitnami/nginx/keys/cli\
334
+ ents/"
335
+ end
336
+ end
337
+ command = <<-'HEREDOC'
338
+ set -ex;
339
+ sudo /opt/bitnami/nginx/sbin/nginx -s reload;
340
+ ls -la /opt/bitnami/nginx/conf/vhosts/;
341
+ HEREDOC
342
+ shell_exec(command)
343
+ IO.write("/home/bitnami/meroku/rails_app/log/nginx_rebuild.log", "ngin_rebuild() ended\n", mode: 'a')
344
+ end
345
+
346
+
347
+ def self.generate_nginx_config(domains, port, cert)
348
+ if cert
349
+ server_crt = "/opt/bitnami/nginx/keys/clients/#{cert}.crt"
350
+ server_key = "/opt/bitnami/nginx/keys/clients/#{cert}.key"
351
+ else
352
+ server_crt = "/opt/bitnami/nginx/keys/meroku_site_fullchain.pem"
353
+ server_key = "/opt/bitnami/nginx/keys/meroku_site_privkey.pem"
354
+ end
355
+
356
+ template = nginx_template
357
+ template.gsub!('REPLACEMEDOMAINS', domains)
358
+ template.gsub!('REPLACEMEPORT', port)
359
+ template.gsub!('REPLACEMESERVERCERT', server_crt)
360
+ template.gsub!('REPLACEMESERVERKEY', server_key)
361
+ template
362
+ end
363
+
364
+ def self.nginx_template
365
+ <<-'HEREDOC'
366
+ server {
367
+ listen 80;
368
+ server_name REPLACEMEDOMAINS;
369
+ listen 443 ssl;
370
+ ssl_certificate REPLACEMESERVERCERT;
371
+ ssl_certificate_key REPLACEMESERVERKEY;
372
+
373
+ root /home/u1/onebody/public;
374
+
375
+ location ~ ^/assets/ {
376
+ expires 1y;
377
+ add_header Cache-Control public;
378
+
379
+ add_header ETag "";
380
+ break;
381
+ }
382
+
383
+ ssl_session_timeout 5m;
384
+ ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
385
+ ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
386
+ ssl_prefer_server_ciphers on;
387
+
388
+ location / {
389
+ proxy_pass http://127.0.0.1:REPLACEMEPORT;
390
+ # got from https://github.com/mperham/sidekiq/issues/2560
391
+ proxy_set_header Host $http_host;
392
+ proxy_set_header X-Real-IP $proxy_protocol_addr;
393
+ proxy_set_header X-Forwarded-For $proxy_protocol_addr;
394
+ proxy_set_header X-Forwarded-Proto https;
395
+
396
+ }
397
+ }
398
+ HEREDOC
399
+ end
400
+
401
+ def self.nginx_fallback_vhost
402
+ <<-'HEREDOC'
403
+ # _.conf
404
+ # Default server for clients who do not send correct Host header.
405
+ # The underline in the file name makes sure that this file comes first in the dir.
406
+ server {
407
+ server_name _;
408
+ listen *:80 default_server deferred;
409
+ return 404;
410
+ }
411
+ HEREDOC
412
+ end
413
+
414
+
415
+ end
416
+ end
@@ -0,0 +1,3 @@
1
+ module Meroku
2
+ VERSION = "0.1.28"
3
+ end
data/lib/meroku.rb CHANGED
@@ -1,5 +1,21 @@
1
- class Meroku
2
- def self.present?
3
- "Meroku has been successfully distributed as a gem"
4
- end
1
+ require "meroku/version"
2
+ require "meroku/util"
3
+ require "meroku/sanitychecks"
4
+ require "meroku/cli"
5
+ require "meroku/cli/server"
6
+ require "meroku/cli/keys"
7
+ require "meroku/cli/domains"
8
+ require "meroku/cli/remote"
9
+ require "meroku/cli/certs"
10
+ require "meroku/cli/config"
11
+ require "meroku/cli/cli"
12
+
13
+ require "meroku/error"
14
+ require "meroku/core_ext"
15
+ require 'aws-sdk'
16
+
17
+ module Meroku
18
+
19
+ PRODUCTION_IP = "34.239.241.218"
20
+
5
21
  end
metadata CHANGED
@@ -1,57 +1,182 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meroku
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.28
5
5
  platform: ruby
6
6
  authors:
7
- - Grayson Wright
7
+ - Meroku System
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2014-08-19 00:00:00.000000000 Z
12
- dependencies: []
13
- description: |
14
- # Meroku
15
-
16
- ## Under Development
17
-
18
- A self-hosted git-powered simple deployment option. No more messing with
19
- headache-inducing NginX configuration files or paying $30 a month for hosted
20
- services.
21
-
22
- ## Prerequisites:
23
-
24
- - Git
25
- - A web application (v0.1.0 will only support Rack)
26
- - Your own server (v0.1.0 will only support Debian 7)
27
- - A DNS provider with a public API (v0.1.0 will only support DNSimple)
28
-
29
- Future versions will hopefully support more application languages & frameworks,
30
- DNS providers, and server operating systems.
31
-
32
- ## Usage
33
-
34
- In the directory that contains your Rack application:
35
-
36
- ```bash
37
- gem install meroku
38
- meroku setup # This will guide you through setting up meroku to talk to your server
39
- meroku new subdomain.yourdomain.com
40
- git push meroku master # Watch your application start up, and visit it online!
41
- ```
42
-
43
- ## License
44
-
45
- Meroku is released under the [MIT License](http://www.opensource.org/licenses/MIT).
46
- email: wright.grayson@gmail.com
47
- executables: []
11
+ date: 2017-06-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.6.8
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.6.8
55
+ - !ruby/object:Gem::Dependency
56
+ name: thor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: aws-sdk
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: dotenv
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rest-client
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 1.6.8
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 1.6.8
111
+ - !ruby/object:Gem::Dependency
112
+ name: activesupport
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: actionview
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '='
130
+ - !ruby/object:Gem::Version
131
+ version: 4.1.1
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '='
137
+ - !ruby/object:Gem::Version
138
+ version: 4.1.1
139
+ description:
140
+ email:
141
+ - meroku.system@gmail.com
142
+ executables:
143
+ - meroku
48
144
  extensions: []
49
145
  extra_rdoc_files: []
50
146
  files:
147
+ - bin/console
148
+ - bin/setup
149
+ - exe/meroku
51
150
  - lib/meroku.rb
52
- homepage: https://github.com/graysonwright/meroku
53
- licenses:
54
- - MIT
151
+ - lib/meroku/app.rb
152
+ - lib/meroku/app/collaborator.rb
153
+ - lib/meroku/application_record.rb
154
+ - lib/meroku/apps_controller.rb
155
+ - lib/meroku/cli.rb
156
+ - lib/meroku/cli/certs.rb
157
+ - lib/meroku/cli/certs.rb~
158
+ - lib/meroku/cli/cli.rb
159
+ - lib/meroku/cli/config.rb
160
+ - lib/meroku/cli/domains.rb
161
+ - lib/meroku/cli/keys.rb
162
+ - lib/meroku/cli/remote.rb
163
+ - lib/meroku/cli/remote.rb~
164
+ - lib/meroku/cli/server.rb
165
+ - lib/meroku/cli/server.rb~
166
+ - lib/meroku/config.rb
167
+ - lib/meroku/configs_controller.rb
168
+ - lib/meroku/core_ext.rb
169
+ - lib/meroku/domain.rb
170
+ - lib/meroku/domains_controller.rb
171
+ - lib/meroku/error.rb
172
+ - lib/meroku/key.rb
173
+ - lib/meroku/keys_controller.rb
174
+ - lib/meroku/sanitychecks.rb
175
+ - lib/meroku/user.rb
176
+ - lib/meroku/util.rb
177
+ - lib/meroku/version.rb
178
+ homepage: http://example.net
179
+ licenses: []
55
180
  metadata: {}
56
181
  post_install_message:
57
182
  rdoc_options: []
@@ -69,9 +194,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
194
  version: '0'
70
195
  requirements: []
71
196
  rubyforge_project:
72
- rubygems_version: 2.2.2
197
+ rubygems_version: 2.6.12
73
198
  signing_key:
74
199
  specification_version: 4
75
- summary: A self-hosted git-powered simple deployment option
200
+ summary: The command line tool for meroku.com
76
201
  test_files: []
77
- has_rdoc: