meroku 0.0.0 → 0.1.28

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
  SHA1:
3
- metadata.gz: f9ab18133ae48e2a6e15280e68322739c5eb07e4
4
- data.tar.gz: 5571d041f52098496d053c4c8b9a0f4e8147c0ab
3
+ metadata.gz: 49c5433cbce12e5cfa8b9e3cac3b41d2e8af0f9f
4
+ data.tar.gz: 49d6a9a8b5fc2a57349d33fff57e5153fdc9f2ba
5
5
  SHA512:
6
- metadata.gz: eac6056c9adec91906cb35355a531d5a37df7c70d13b3d2d00343c23c4826bfa5bda10d52f72706293373b0431640446ee9a85c548bc44106cf8660128c396ba
7
- data.tar.gz: 9f9025bda77a268c481afe6ada57a2feea2ae9d0f610b8dee6640a29ba81c3d5f9b444e48836dc56c78cbc532112193bedfb4514877a724742be8f2a6473e0b4
6
+ metadata.gz: d0f969eb23f7da5db69bba1cbc398341eb0f4522a31b0ec82dee32d38e25ef7b88c105066b41b12d5397fad8dc0496e3fde68da23fe102c994d88f5971341068
7
+ data.tar.gz: da17716cb9ffa9d8b7cb8fc6172d9498469a5049ae99fa0f68d8f7a8bdd5fbf946ae7ff6088204df51c1143c7b18f207867655d5a94fb46c80a50c57902fc23f
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "meroku"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/exe/meroku ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require "meroku"
3
+ Meroku::CLI::Cli.start
4
+
5
+
@@ -0,0 +1,18 @@
1
+ class Meroku::App::Collaborator < Meroku::ApplicationRecord
2
+ include Meroku::Util
3
+ self.table_name = "meroku_app_collaborators"
4
+
5
+ validates :user_id, presence: true, allow_nil: false
6
+ validates :app_id, presence: true, allow_nil: false
7
+ validates_uniqueness_of :user_id, :scope => "app_id"
8
+
9
+ after_create :setup_repo
10
+ after_create :add_mysql_user
11
+ after_create :create_empty_mysql_db
12
+ after_create :add_mysql_grants
13
+ after_create :add_pg_user
14
+ after_create :create_empty_pg_db
15
+ after_create :add_pg_grants
16
+ end
17
+
18
+
data/lib/meroku/app.rb ADDED
@@ -0,0 +1,12 @@
1
+ module Meroku
2
+
3
+ class App < Meroku::ApplicationRecord
4
+ include Meroku::Util
5
+ validates_uniqueness_of :name
6
+ has_many :domains, class_name: "Meroku::Domain"
7
+ has_many :configs, class_name: "Meroku::Config"
8
+ end
9
+
10
+
11
+ end
12
+
@@ -0,0 +1,8 @@
1
+ module Meroku
2
+
3
+ # This class was auto generated by rails 5
4
+ class ApplicationRecord < ActiveRecord::Base
5
+ self.abstract_class = true
6
+ end
7
+
8
+ end
@@ -0,0 +1,112 @@
1
+ module Meroku
2
+
3
+ class AppsController < ApplicationController
4
+ #before_action :set_app, only: [:show, :edit, :update, :destroy]
5
+ skip_before_action :verify_authenticity_token, only: [:create, :update, :additional_env_vars]
6
+ before_action :authenticate, only: [:create, :update, :additional_env_vars]
7
+
8
+ ## GET /apps
9
+ ## GET /apps.json
10
+ #def index
11
+ # @apps = App.all
12
+ #end
13
+ #
14
+ ## GET /apps/1
15
+ ## GET /apps/1.json
16
+ #def show
17
+ #end
18
+ #
19
+ ## GET /apps/new
20
+ #def new
21
+ # @app = App.new
22
+ #end
23
+ #
24
+ ## GET /apps/1/edit
25
+ #def edit
26
+ #end
27
+ #
28
+ # POST /apps
29
+ # POST /apps.json
30
+ def create
31
+ @app = Meroku::App.new(app_params)
32
+ app_saved = @app.save
33
+ collaborator_saved = nil
34
+ if app_saved
35
+ @collaborator = Meroku::App::Collaborator.new(
36
+ app_id: @app.id,
37
+ user_id: @user.id
38
+ )
39
+ collaborator_saved = @collaborator.save
40
+ Meroku::Util.nginx_rebuild()
41
+ end
42
+
43
+ respond_to do |format|
44
+ if app_saved && collaborator_saved
45
+ format.json { render json: @app }
46
+ else
47
+ format.json {
48
+ if @app.errors
49
+ render json: { :errors => @app.errors }, :status => :unprocessable_entity
50
+ elsif @collaborator.errors
51
+ render json: { :errors => @collaborator.errors }, :status => :unprocessable_entity
52
+ end
53
+ }
54
+ end
55
+ end
56
+ end
57
+ #
58
+ # PATCH/PUT /apps/1
59
+ # PATCH/PUT /apps/1.json
60
+ def update
61
+ respond_to do |format|
62
+ if @app_.update(app_params)
63
+ format.json {
64
+ Meroku::Util.nginx_rebuild()
65
+ render json: @app_
66
+ }
67
+ else
68
+ format.json { render json: @app_.errors, status: :unprocessable_entity }
69
+ end
70
+ end
71
+ end
72
+ #
73
+ ## DELETE /apps/1
74
+ ## DELETE /apps/1.json
75
+ #def destroy
76
+ # @app.destroy
77
+ # respond_to do |format|
78
+ # format.html { redirect_to apps_url, notice: 'App was successfully destroyed.' }
79
+ # format.json { head :no_content }
80
+ # end
81
+ #end
82
+
83
+
84
+ # POST /?
85
+ def additional_env_vars
86
+ if params[:dbtype] == "mysql"
87
+ database_url = %Q[export DATABASE_URL=mysql2://u#{@user.id}:#{@user.database_password}@localhost/#{@app_.name}?socket=/opt/bitnami/mysql/tmp/mysql.sock]
88
+ else
89
+ database_url = %Q[export DATABASE_URL=postgres://u#{@user.id}:#{@user.database_password}@localhost/#{@app_.name}]
90
+ end
91
+
92
+ respond_to do |format|
93
+ Rails.logger.debug "DB8 #{"export RAILS_ENV=production export PORT=#{3000+@app_.id} #{database_url}"}"
94
+ format.json { render json: { :data => "export RAILS_ENV=production export PORT=#{3000+@app_.id} #{database_url} "} }
95
+ end
96
+ end
97
+
98
+ private
99
+ # Use callbacks to share common setup or constraints between actions.
100
+ #def set_app
101
+ # @app = App.find(params[:id])
102
+ #end
103
+
104
+ # Never trust parameters from the scary internet, only allow the white list through.
105
+ def app_params
106
+ params.fetch(:app, {}).permit(:name, :server_crt, :server_key)
107
+ end
108
+
109
+ end
110
+
111
+ end
112
+
@@ -0,0 +1,30 @@
1
+ module Meroku
2
+ module CLI
3
+ require 'action_view'
4
+ include ActionView::Helpers::TextHelper
5
+
6
+ class Certs < Thor
7
+ include Meroku::Util
8
+
9
+ desc "add server.crt server.key", "Upload domain certificate and key"
10
+ def add(cert, key)
11
+ require 'rest-client'
12
+ require 'active_support/all'
13
+ require 'rack'
14
+ require 'action_view'
15
+ server_crt = IO.read(cert)
16
+ server_key = IO.read(key)
17
+ resp = RestClient.put 'https://www.meroku.com/meroku/apps/0.json', { app: { server_crt: server_crt, server_key: server_key }, authentication: { token: cli_token, app_name: app_name } }
18
+ puts "Added. (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
19
+ rescue RestClient::Exception => e
20
+ abort e.to_s if e.response.code != 200
21
+ out_str = "ERROR"
22
+ if valid_json?(e.response) && JSON.parse(e.response)["errors"].size >= 1
23
+ out_str += " "
24
+ out_str += JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,14 @@
1
+ module Meroku
2
+ module CLI
3
+ require 'action_view'
4
+ include ActionView::Helpers::TextHelper
5
+
6
+ class Certs < Thor
7
+ include Meroku::Util
8
+
9
+ desc "add 'DOMAIN'", "Remove DOMAIN"
10
+ def remove(domain)
11
+ require 'rest-client'
12
+ require 'active_support/all'
13
+ require 'rack'
14
+ require 'action_view'
@@ -0,0 +1,97 @@
1
+ module Meroku
2
+ module CLI
3
+ require 'action_view'
4
+ include ActionView::Helpers::TextHelper
5
+
6
+ class Cli < Thor
7
+ include Meroku::Util
8
+ register(Meroku::CLI::Server, 'server', 'server <command>', 'Administer infrastructure')
9
+ register(Remote, 'remote', 'remote <command>', '')
10
+ register(Keys, 'keys', 'keys <command>', '')
11
+ register(Domains,'domains','domains <command>', '')
12
+ register(Certs ,'certs','certs <command>', '')
13
+ register(Config ,'config','config <command>', '')
14
+
15
+ desc "_run 'COMMAND'", "Run a command on the server"
16
+ def _run(command)
17
+ user_id = `cat /tmp/meroku.id`.chomp
18
+ server = "u#{user_id}@www.meroku.com"
19
+ name = app_name
20
+ if IO.read("Gemfile") =~ /^[^\#]*gem ["']mysql/
21
+ dbtype="mysql"
22
+ else
23
+ dbtype="postgres"
24
+ end
25
+
26
+ _additional_env_vars = additional_env_vars(name,dbtype)
27
+ if command == "bash"
28
+ exec "ssh -t -o StrictHostKeyChecking=no #{server} '#{_additional_env_vars} ;echo INFO: Type exit quit this remote shell; cd #{name}; bash --login'"
29
+ end
30
+ abort "ERROR: Unexpected output for \"git remote -v\"" if name.blank?
31
+ require 'open3'
32
+ stdout, stderr, exit_status = Open3.capture3(%Q[ssh -o 'StrictHostKeyChecking=no' #{server} 'export PATH=$PATH:/opt/bitnami/nodejs/bin; source ~/.rvm/scripts/rvm; cd #{name}; #{_additional_env_vars} ; #{command}'])
33
+ puts stdout if !stdout.empty?
34
+ puts stderr if !stderr.empty?
35
+ puts "meroku run finished with exit code #{exit_status.exitstatus}" if exit_status.exitstatus != 0
36
+ end
37
+
38
+ desc "create NAME", "Create an app named NAME on meroku"
39
+ def create(name)
40
+ require 'rest-client'
41
+ require 'rack'
42
+
43
+ return if !cli_logged_in?
44
+ resp = RestClient.post 'https://www.meroku.com/meroku/apps.json', { :"app[name]" => name, authentication: { app: name, token: cli_token} }
45
+ puts "Created #{JSON.parse(resp)["name"]}! (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
46
+ `git remote remove meroku 2>&1 >/dev/null`
47
+ `git remote add meroku u#{cli_user_id}@www.meroku.com:#{name}.git 2>&1 >/dev/null`
48
+ puts "Added git remote meroku ( u#{cli_user_id}@www.meroku.com:#{name}.git )"
49
+ rescue RestClient::Exception => e
50
+ abort e.to_s if e == RestClient::ServerBrokeConnection
51
+ out_str = "ERROR"
52
+ if valid_json?(e.response) && JSON.parse(e.response)["errors"].size >= 1
53
+ out_str += " "
54
+ out_str += JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence
55
+ end
56
+ out_str += " (#{e.to_s}) "
57
+ puts out_str
58
+ end
59
+
60
+ option :email, :required => true
61
+ option :password, :required => true
62
+ desc "login", "Login to meroku"
63
+ def login()
64
+ require 'rest-client'
65
+ require 'rack'
66
+ resp = RestClient.post 'https://www.meroku.com/users/sign_in.json', {:"user[email]" => options[:email], :"user[password]" => options[:password] }
67
+ puts "Logged in! (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
68
+ IO.write("/tmp/meroku.token", JSON.parse(resp)["encrypted_password"])
69
+ IO.write("/tmp/meroku.id", JSON.parse(resp)["id"])
70
+ rescue RestClient::Exception => e
71
+ abort e.to_s if e.response.code == 500 || e.response.code == 404
72
+ out_str = "ERROR"
73
+ if JSON.parse(e.response)["errors"].is_a? Array
74
+ out_str += " "
75
+ out_str += JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence
76
+ end
77
+ out_str += " (#{e.to_s}) "
78
+ puts out_str
79
+ end
80
+
81
+ option :email, :required => true
82
+ option :password, :required => true
83
+ desc "signup", "Sign up for a free meroku account"
84
+ def signup()
85
+ require 'rest-client'
86
+ require 'rack'
87
+ resp = RestClient.post 'https://www.meroku.com/users.json', {:"user[email]" => options[:email], :"user[password]" => options[:password], :"user[password_confirmation]" => options[:password] }
88
+ puts "Signed up #{JSON.parse(resp)["email"]}! (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
89
+ rescue RestClient::Exception => e
90
+ abort e.to_s if e.response.code == 500 || e.response.code == 404
91
+ puts "ERROR " +
92
+ JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence +
93
+ " (#{e.to_s})"
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,111 @@
1
+ module Meroku
2
+ module CLI
3
+ require 'action_view'
4
+ include ActionView::Helpers::TextHelper
5
+
6
+ class Config < Thor
7
+ include Meroku::Util
8
+
9
+ desc "list", "List environment variables"
10
+ def list
11
+ require 'rest-client'
12
+ #require 'active_support/all'
13
+ require 'rack'
14
+ require 'action_view'
15
+ resp = RestClient.get "https://www.meroku.com/meroku/configs.json?authentication_token=#{cli_token}&authentication_app_name=#{app_name}"
16
+ puts "#{JSON.parse(resp)["data"]}. (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
17
+ rescue RestClient::Exception => e
18
+ out_str = "ERROR"
19
+ if valid_json?(e.response) && JSON.parse(e.response)["errors"].size >= 1
20
+ out_str += " "
21
+ out_str += JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence
22
+ end
23
+ out_str += " (#{e.to_s}) "
24
+ puts out_str
25
+ end
26
+
27
+ #desc "remove 'DOMAIN'", "Remove DOMAIN"
28
+ #def remove(domain)
29
+ # require 'rest-client'
30
+ # require 'active_support/all'
31
+ # require 'rack'
32
+ # require 'action_view'
33
+ # resp = RestClient.delete "https://www.meroku.com/meroku/domains/0.json?domain=#{domain}&authentication_token=#{cli_token}&authentication_app_name=#{app_name}"
34
+ # puts "Removed #{truncate(JSON.parse(resp)["data"]["domain"])}. (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
35
+ #rescue RestClient::Exception => e
36
+ # abort e.to_s if e.response.code != 200
37
+ # out_str = "ERROR"
38
+ # if valid_json?(e.response) && JSON.parse(e.response)["errors"].size >= 1
39
+ # out_str += " "
40
+ # out_str += JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence
41
+ # end
42
+ # out_str += " (#{e.to_s}) "
43
+ # puts out_str
44
+ #end
45
+ #
46
+ #desc "list", "List domains associated with your app"
47
+ #def list
48
+ # require 'rest-client'
49
+ # require 'active_support/all'
50
+ # require 'rack'
51
+ # require 'action_view'
52
+ # resp = RestClient.get "https://www.meroku.com/meroku/domains.json?authentication_token=#{cli_token}&authentication_app_name=#{app_name}"
53
+ # puts "#{JSON.parse(resp)["data"]}. (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
54
+ #rescue RestClient::Exception => e
55
+ # out_str = "ERROR"
56
+ # if valid_json?(e.response) && JSON.parse(e.response)["errors"].size >= 1
57
+ # out_str += " "
58
+ # out_str += JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence
59
+ # end
60
+ # out_str += " (#{e.to_s}) "
61
+ # puts out_str
62
+ #end
63
+
64
+
65
+
66
+
67
+ desc "unset FOO", "Set environment variable FOO"
68
+ def unset(name)
69
+ require 'rest-client'
70
+ require 'rack'
71
+ require 'action_view'
72
+ resp = RestClient.delete "https://www.meroku.com/meroku/configs/0.json?name=#{name}&authentication_token=#{cli_token}&authentication_app_name=#{app_name}"
73
+ puts "Removed #{truncate(JSON.parse(resp)["data"]["name"])}. (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
74
+ rescue RestClient::Exception => e
75
+ abort e.to_s if e == RestClient::ServerBrokeConnection
76
+ out_str = "ERROR"
77
+ puts e.to_s
78
+ if valid_json?(e.response) && JSON.parse(e.response)["errors"].size >= 1
79
+ out_str += " "
80
+ out_str += JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence
81
+ end
82
+ out_str += " (#{e.to_s}) "
83
+ puts out_str
84
+ end
85
+
86
+
87
+
88
+
89
+ desc "set FOO baa", "Set environment variable FOO to baa"
90
+ def set(name, value)
91
+ require 'rest-client'
92
+ #require 'active_support/all'
93
+ require 'rack'
94
+ require 'action_view'
95
+
96
+ resp = RestClient.post 'https://www.meroku.com/meroku/configs.json', { name: name, value: value, authentication: { token: cli_token, app_name: app_name } }
97
+ puts "Added/Updated #{truncate(JSON.parse(resp)["data"]["name"])}. (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
98
+ rescue RestClient::Exception => e
99
+ abort e.to_s if e == RestClient::ServerBrokeConnection
100
+ out_str = "ERROR"
101
+ puts e.to_s
102
+ if valid_json?(e.response) && JSON.parse(e.response)["errors"].size >= 1
103
+ out_str += " "
104
+ out_str += JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence
105
+ end
106
+ out_str += " (#{e.to_s}) "
107
+ puts out_str
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,69 @@
1
+ module Meroku
2
+ module CLI
3
+ require 'action_view'
4
+ include ActionView::Helpers::TextHelper
5
+
6
+ class Domains < Thor
7
+ include Meroku::Util
8
+
9
+ desc "remove 'DOMAIN'", "Remove DOMAIN"
10
+ def remove(domain)
11
+ require 'rest-client'
12
+ require 'active_support/all'
13
+ require 'rack'
14
+ require 'action_view'
15
+ resp = RestClient.delete "https://www.meroku.com/meroku/domains/0.json?domain=#{domain}&authentication_token=#{cli_token}&authentication_app_name=#{app_name}"
16
+ puts "Removed #{truncate(JSON.parse(resp)["data"]["domain"])}. (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
17
+ rescue RestClient::Exception => e
18
+ abort e.to_s if e.response.code != 200
19
+ out_str = "ERROR"
20
+ if valid_json?(e.response) && JSON.parse(e.response)["errors"].size >= 1
21
+ out_str += " "
22
+ out_str += JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence
23
+ end
24
+ out_str += " (#{e.to_s}) "
25
+ puts out_str
26
+ end
27
+
28
+ desc "list", "List domains associated with your app"
29
+ def list
30
+ require 'rest-client'
31
+ require 'active_support/all'
32
+ require 'rack'
33
+ require 'action_view'
34
+ resp = RestClient.get "https://www.meroku.com/meroku/domains.json?authentication_token=#{cli_token}&authentication_app_name=#{app_name}"
35
+ puts "#{JSON.parse(resp)["data"]}. (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
36
+ rescue RestClient::Exception => e
37
+ out_str = "ERROR"
38
+ if valid_json?(e.response) && JSON.parse(e.response)["errors"].size >= 1
39
+ out_str += " "
40
+ out_str += JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence
41
+ end
42
+ out_str += " (#{e.to_s}) "
43
+ puts out_str
44
+ end
45
+
46
+ desc "add 'DOMAIN'", "Associate DOMAIN with your app"
47
+ def add(domain)
48
+ require 'rest-client'
49
+ require 'active_support/all'
50
+ require 'rack'
51
+ require 'action_view'
52
+
53
+ resp = RestClient.post 'https://www.meroku.com/meroku/domains.json', { domain: domain, authentication: { token: cli_token, app_name: app_name } }
54
+ puts "Added #{truncate(JSON.parse(resp)["data"]["domain"])}. (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
55
+ rescue RestClient::ServerBrokeConnection
56
+ raise
57
+ rescue RestClient::Exception => e
58
+ abort e.to_s if e == RestClient::ServerBrokeConnection
59
+ out_str = "ERROR"
60
+ if valid_json?(e.response) && JSON.parse(e.response)["errors"].size >= 1
61
+ out_str += " "
62
+ out_str += JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence
63
+ end
64
+ out_str += " (#{e.to_s}) "
65
+ puts out_str
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,38 @@
1
+ module Meroku
2
+ module CLI
3
+
4
+ require 'action_view'
5
+ include ActionView::Helpers::TextHelper
6
+ class Keys < Thor
7
+ include Meroku::Util
8
+ include ActionView::Helpers::TextHelper
9
+
10
+ desc "add", "Upload your public key (~/.ssh/id_rsa.pub) to meroku"
11
+ def add
12
+ require 'rest-client'
13
+ require 'rack'
14
+ require 'action_view'
15
+
16
+ if !public_key_exists?
17
+ puts "Public key not found at ~/.ssh/id_rsa.pub"
18
+ puts "see https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key"
19
+ return
20
+ end
21
+ key = IO.read("#{Dir.home}/.ssh/id_rsa.pub")
22
+ resp = RestClient.post 'https://www.meroku.com/meroku/keys.json', { key: key, authentication: { token: cli_token } }
23
+ puts "Added #{truncate(JSON.parse(resp)["data"]["key"])}. (#{resp.code} #{Rack::Utils::HTTP_STATUS_CODES[resp.code]})"
24
+ rescue RestClient::Exception => e
25
+ out_str = "ERROR"
26
+
27
+ if valid_json?(e.response) && JSON.parse(e.response)["errors"].size >= 1
28
+ out_str += " "
29
+ out_str += JSON.parse(e.response)["errors"].map { |e| e.join(' ') }.to_sentence
30
+ end
31
+ out_str += " (#{e.to_s}) "
32
+ puts out_str
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,13 @@
1
+ require 'action_view'
2
+ include ActionView::Helpers::TextHelper
3
+
4
+ class Remote < Thor
5
+ include ::Meroku::Util
6
+
7
+ desc "add APPNAME", "adds a git remote for app named APPNAME"
8
+ def add(name)
9
+ `git remote remove meroku 2>&1 >/dev/null`
10
+ `git remote add meroku u#{cli_user_id}@www.meroku.com:#{name}.git 2>&1 >/dev/null`
11
+ puts "Added git remote meroku ( u#{cli_user_id}@www.meroku.com:#{name}.git )"
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+
2
+
3
+ class Remote < Thor
4
+ include ::Meroku::Util
5
+
6
+ desc "add APPNAME", "adds a git remote for app named APPNAME"
7
+ def add(name)
8
+ `git remote remove meroku 2>&1 >/dev/null`
9
+ `git remote add meroku u#{cli_user_id}@www.meroku.com:#{name}.git 2>&1 >/dev/null`
10
+ puts "Added git remote meroku ( u#{cli_user_id}@www.meroku.com:#{name}.git )"
11
+ end
12
+ end