railsonfire 0.2.13

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # A sample Gemfile
2
+ source "http://rubygems.org"
3
+
4
+ gemspec
@@ -0,0 +1,80 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ railsonfire (0.2.13)
5
+ activesupport (= 3.2.8)
6
+ gems (= 0.7.0)
7
+ git (= 1.2.5)
8
+ heroku (= 2.30.4)
9
+ httparty (= 0.8.3)
10
+ json_pure (= 1.7.5)
11
+ launchy (= 2.1.2)
12
+ multi_json (= 1.3.6)
13
+ sshkey (= 1.3.1)
14
+ thor (= 0.16.0)
15
+
16
+ GEM
17
+ remote: http://rubygems.org/
18
+ specs:
19
+ activesupport (3.2.8)
20
+ i18n (~> 0.6)
21
+ multi_json (~> 1.0)
22
+ addressable (2.3.2)
23
+ coderay (1.0.7)
24
+ diff-lcs (1.1.3)
25
+ excon (0.16.1)
26
+ gems (0.7.0)
27
+ git (1.2.5)
28
+ heroku (2.30.4)
29
+ heroku-api (~> 0.3.4)
30
+ launchy (>= 0.3.2)
31
+ netrc (~> 0.7.7)
32
+ rest-client (~> 1.6.1)
33
+ rubyzip
34
+ heroku-api (0.3.4)
35
+ excon (~> 0.16.1)
36
+ httparty (0.8.3)
37
+ multi_json (~> 1.0)
38
+ multi_xml
39
+ i18n (0.6.0)
40
+ json_pure (1.7.5)
41
+ launchy (2.1.2)
42
+ addressable (~> 2.3)
43
+ method_source (0.8)
44
+ mime-types (1.19)
45
+ multi_json (1.3.6)
46
+ multi_xml (0.5.1)
47
+ netrc (0.7.7)
48
+ pry (0.9.10)
49
+ coderay (~> 1.0.5)
50
+ method_source (~> 0.8)
51
+ slop (~> 3.3.1)
52
+ rake (0.9.2.2)
53
+ rest-client (1.6.7)
54
+ mime-types (>= 1.16)
55
+ rspec (2.11.0)
56
+ rspec-core (~> 2.11.0)
57
+ rspec-expectations (~> 2.11.0)
58
+ rspec-mocks (~> 2.11.0)
59
+ rspec-core (2.11.1)
60
+ rspec-expectations (2.11.2)
61
+ diff-lcs (~> 1.1.3)
62
+ rspec-mocks (2.11.2)
63
+ rubyzip (0.9.9)
64
+ simplecov (0.6.4)
65
+ multi_json (~> 1.0)
66
+ simplecov-html (~> 0.5.3)
67
+ simplecov-html (0.5.3)
68
+ slop (3.3.2)
69
+ sshkey (1.3.1)
70
+ thor (0.16.0)
71
+
72
+ PLATFORMS
73
+ ruby
74
+
75
+ DEPENDENCIES
76
+ pry
77
+ railsonfire!
78
+ rake
79
+ rspec
80
+ simplecov
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Florian Motlik
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,19 @@
1
+ = railsonfire-gem
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to railsonfire-gem
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 Florian Motlik. See LICENSE.txt for
18
+ further details.
19
+
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+ require 'rubygems'
4
+ require 'railsonfire'
5
+ require 'railsonfire/helpers/base'
6
+ require 'gems'
7
+
8
+ ENV["public-key"] = <<-eos
9
+ -----BEGIN RSA PUBLIC KEY-----
10
+ MIIBCgKCAQEAtuHyhunxRlbCGigqUFgA8XFlaberqgm+S0LQ0HGWY6hlwBsyo9oE
11
+ e06n1sHu3CgeCinOhdDVNS5r8y0neZrABpHnq9rizk49l6U/KBqmebZL5i90RD/8
12
+ 366UHAYDMAN3ensw8Fb1il3mBwVpdAFsTfmu1LyriJXOOGJKD3zeHzFaCbLqjyzL
13
+ sHtn9ve/nMUNI/V4z28sWSoP4gLlZD0yQd1loWYb9usjXPlL4ZqKELhn70bu+Omm
14
+ AxUaO2u0fk9ixurx9nIsydQWTRI3h8xLO1pfx/TcG3QDEhp3trD0KFNVU1a2UvCQ
15
+ Ynhi9CV9Q9alALkNpKGyhBEMuS4HNtcrVQIDAQAB
16
+ -----END RSA PUBLIC KEY-----
17
+ eos
18
+
19
+ include Railsonfire::Helper
20
+
21
+ begin
22
+ if `gem list railsonfire`[Gems.info('railsonfire')["version"]]
23
+ CLI.start
24
+ else
25
+ puts "You have an old version of Railsonfire installed. Please update by running gem update railsonfire."
26
+ end
27
+ rescue Exception => e
28
+ if e.class != SystemExit && e.class != Interrupt
29
+ puts ""
30
+ puts "Sorry, an Error occured and we were informed. Please try again."
31
+ notify(e.class, "Cought Exception with: #{e.class}", {:backtrace => e.backtrace, :error_class => e.class, :error_message => e.message})
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ require 'thor'
2
+ require 'railsonfire/helpers/constants'
3
+ require 'railsonfire/helpers/base_cli'
4
+ require 'railsonfire/cli'
5
+ require 'railsonfire/railsonfire'
6
+
7
+ module Railsonfire
8
+ end
@@ -0,0 +1,2 @@
1
+ require 'railsonfire/subcommands'
2
+ require 'railsonfire/commands'
@@ -0,0 +1,2 @@
1
+ require 'railsonfire/commands/create'
2
+ #require 'railsonfire/commands/post_receive'
@@ -0,0 +1,124 @@
1
+ require 'railsonfire/helpers/base'
2
+ require 'railsonfire/helpers/key'
3
+ require 'railsonfire/helpers/constants'
4
+ require 'active_support/core_ext/hash/deep_merge'
5
+
6
+
7
+ class CLI < BASECLI
8
+
9
+ def self.source_root
10
+ File.dirname(__FILE__)
11
+ end
12
+
13
+ desc "create", "Create a new Railsonfire project"
14
+ def create
15
+ invoke "auth:login"
16
+ send_signal :create_started
17
+ return unless is_git_managed?
18
+ if git_remotes.empty?
19
+ say "We couldn't find any GitHub remotes. Please add your GitHub remote with git remote add YOUR_GITHUB_REMOTE and start again."
20
+ return false
21
+ end
22
+ remote = ask_for_git_remote
23
+ set_project_data remote
24
+
25
+ if yes? "Create Project (y/n)?" and project.create
26
+ if(is_github_remote? remote)
27
+ send_signal :configure_github
28
+ configure_github
29
+ else
30
+ send_signal :create_post_receive
31
+ invoke "post_receive"
32
+ end
33
+ configure
34
+ true
35
+ else
36
+ send_signal :create_cancelled
37
+ false
38
+ end
39
+ end
40
+
41
+ private
42
+ def project
43
+ Railsonfire.project
44
+ end
45
+
46
+ def ask_for_git_remote
47
+ return git_remotes[0] if git_remotes.size == 1
48
+ select "Select the repository you store your code in and we should clone from:", git_remotes
49
+ end
50
+
51
+ def git_remotes
52
+ Git.open("./").remotes.collect(&:url).select{|u| is_github_remote? u}
53
+ end
54
+
55
+
56
+ def set_project_data remote
57
+ if(is_github_remote? remote)
58
+ project.name = github_repo_name_from remote
59
+ project.owner = github_repo_owner_from remote
60
+ send_signal :create_with_github
61
+ else
62
+ project.url = remote
63
+ project.name = ask "Name of your Project:"
64
+ send_signal :create_with_generic_git
65
+ end
66
+ say "Owner: #{project.owner}" if project.owner
67
+ say "Name: #{project.name}"
68
+ say "Repository: #{project.url}" if project.url
69
+ end
70
+
71
+ def is_github_remote? remote
72
+ remote["github.com"] != nil
73
+ end
74
+ def github_repo_name_from remote
75
+ if remote.start_with?("https")
76
+ remote.split("/")[4].split(".")[0]
77
+ else
78
+ split_git_remote(remote).last
79
+ end
80
+ end
81
+
82
+ def github_repo_owner_from remote
83
+ if remote.start_with?("https")
84
+ remote.split("/")[3]
85
+ else
86
+ split_git_remote(remote).first
87
+ end
88
+ end
89
+
90
+ def split_git_remote remote
91
+ remote.sub("git@github.com:", "").sub(".git", "").split("/")
92
+ end
93
+
94
+ def configure_github
95
+ invoke "github:upload_key"
96
+ invoke "github:add_hook"
97
+ end
98
+
99
+ def configure
100
+ merge_new_project_config
101
+ configure_heroku
102
+ write_config_file
103
+ end
104
+
105
+ def merge_new_project_config
106
+ new = {
107
+ "id" => Railsonfire.project.uuid,
108
+ "setup" => {
109
+ "commands" => ["bundle install --without production", "bundle exec rake db:migrate --trace"]
110
+ },
111
+ "test" => {
112
+ "commands" => ["bundle exec rake"]
113
+ },
114
+ "deploy" => {
115
+ },
116
+ "ruby_versions" => [RUBY_VERSION]
117
+ }
118
+ Railsonfire.config.deep_merge!(new)
119
+ end
120
+
121
+ def configure_heroku
122
+ invoke "railsonfire:heroku:configure" if yes? "Do you want to configure deployment to Heroku (y/n)?"
123
+ end
124
+ end
@@ -0,0 +1,20 @@
1
+ #!/bin/sh
2
+
3
+ while read oldrev newrev ref
4
+ do
5
+ echo "STARTING [$oldrev $newrev $ref]"
6
+ email=`git log $newrev --format=%ce -n 1`
7
+ name=`git log $newrev --format=%cn -n 1`
8
+ message=`git log $newrev --format=%B -n 1`
9
+ echo $email
10
+
11
+ wget --post-data "payload={\"ref\":\"$ref\", \
12
+ \"after\":\"$newrev\", \
13
+ \"commits\": \
14
+ [{ \
15
+ \"id\":\"$newrev\", \
16
+ \"author\":{\"email\":\"$email\", \"name\":\"$name\"}, \
17
+ \"message\":\"$message\" \
18
+ }] \
19
+ }" https://railsonfire.com/hook/<%= config[:uuid] %>
20
+ done
@@ -0,0 +1,9 @@
1
+ require 'thor'
2
+
3
+ class CLI < BASECLI
4
+ desc "post_receive", "Create a PostReceive File for the current Project"
5
+ def post_receive
6
+ template("post-receive", "post-receive", {:uuid => Railsonfire.project.uuid})
7
+ #@cli.should_receive(:template).with("post-receive", "post-receive", {:uuid => project.uuid})
8
+ end
9
+ end
@@ -0,0 +1,79 @@
1
+ require 'git'
2
+ require 'yaml'
3
+ require 'httparty'
4
+ require 'json'
5
+
6
+ module Railsonfire
7
+ module Helper
8
+ def shell
9
+ Thor::Base.shell.new
10
+ end
11
+
12
+ def notify class_name, message, parameters = {}
13
+ token = Railsonfire.user ? Railsonfire.user.railsonfire_token : ""
14
+ post_json "#{Railsonfire::DOMAIN}/airbrake/proxy", {
15
+ "error_class" => class_name,
16
+ "error_message" => message + " - #{token}",
17
+ "parameters" => parameters.merge({:railsonfire_id => token})
18
+ }
19
+ end
20
+
21
+ def send_signal signal
22
+ begin
23
+ token = Railsonfire.user ? Railsonfire.user.railsonfire_token : ""
24
+ HTTParty.post("#{Railsonfire::DOMAIN}/users/signal?railsonfire_token=#{token}&signal=#{signal}")
25
+ rescue Exception => e
26
+ notify e.class, e.message
27
+ end
28
+ end
29
+
30
+ def is_git_managed?
31
+ dir_exists?("./.git").tap do |git_folder|
32
+ error "Start railsonfire in the root folder of a git managed project" unless git_folder
33
+ end
34
+ end
35
+
36
+ def write_config_file
37
+ create_file(
38
+ Railsonfire::RAILSONFIRE_FILE,
39
+ Railsonfire.config.to_yaml.gsub("---\n", "").gsub("\n\n", "\n").gsub(": \n", ":\n"),
40
+ :force => true
41
+ )
42
+ end
43
+
44
+ def success message
45
+ say message, Thor::Shell::Color::GREEN
46
+ end
47
+
48
+ def error message
49
+ say message, Thor::Shell::Color::RED
50
+ end
51
+
52
+ def warning message
53
+ say message, Thor::Shell::Color::YELLOW
54
+ end
55
+
56
+ def heroku
57
+ @heroku ||= ::Heroku::Auth.api
58
+ end
59
+
60
+ def select msg, elements
61
+ elements.each_with_index do |element, index|
62
+ success(block_given? ? yield(element, index + 1) : ("%s. %s" % [index + 1, element]))
63
+ end
64
+ result = ask(msg, :limited_to => (1..elements.count).map(&:to_s)).to_i
65
+ elements[result - 1]
66
+ end
67
+
68
+ def post_json path, body
69
+ HTTParty.post(path,
70
+ :headers => {"Content-Type" => "application/json"},
71
+ :body => body.to_json)
72
+ end
73
+
74
+ private
75
+ def dir_exists? dir
76
+ File.exists?(dir) && File.directory?(dir)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,6 @@
1
+ require 'railsonfire/helpers/base'
2
+
3
+ class BASECLI < Thor
4
+ include Railsonfire::Helper
5
+ include Thor::Actions
6
+ end
@@ -0,0 +1,6 @@
1
+ module Railsonfire
2
+ DOMAIN = ENV["railsonfire_domain"] ||= "https://www.railsonfire.com"
3
+ RAILSONFIRE_FILE = "./railsonfire.yml"
4
+ PUBLIC_KEY_FILE = "railsonfire-ssh-public-key.pub"
5
+ PRIVATE_KEY_FILE = "railsonfire-ssh-private-key"
6
+ end
@@ -0,0 +1,48 @@
1
+ require 'sshkey'
2
+ require 'openssl'
3
+ require 'base64'
4
+
5
+ module Railsonfire
6
+ module Helper
7
+ module Keys
8
+ def create_ssh_key
9
+ SSHKey.generate()
10
+ end
11
+
12
+
13
+ def create_keys key
14
+ {}.tap do |keys|
15
+ cipher_data = create_encryption_cipher
16
+ keys[:cipher_iv] = encode(encrypt(cipher_data[:iv]))
17
+ keys[:cipher_key] = encode(encrypt(cipher_data[:key]))
18
+ keys[:public_key] = key.ssh_public_key
19
+ keys[:private_key] = encode(encrypt_symmetrically key.rsa_private_key, cipher_data[:cipher])
20
+ end
21
+ end
22
+
23
+ private
24
+ def create_encryption_cipher
25
+ cipher = OpenSSL::Cipher.new("AES256")
26
+ cipher.encrypt
27
+ iv = cipher.random_iv
28
+ key = cipher.random_key
29
+ {:cipher => cipher, :iv => iv, :key => key}
30
+ end
31
+
32
+ def encrypt content
33
+ rsa_key = OpenSSL::PKey::RSA.new(ENV["public-key"])
34
+ rsa_key.public_encrypt(content)
35
+ end
36
+
37
+ def encrypt_symmetrically content, cipher
38
+ ciphertext = cipher.update(content)
39
+ ciphertext << cipher.final
40
+ ciphertext
41
+ end
42
+
43
+ def encode content
44
+ Base64.encode64 content
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,114 @@
1
+ require 'railsonfire/helpers/key'
2
+ require 'railsonfire/helpers/constants'
3
+ require 'httparty'
4
+ require 'json'
5
+ require 'yaml'
6
+ require 'active_support/core_ext/hash/keys'
7
+
8
+ module Railsonfire
9
+ include Railsonfire::Helper
10
+
11
+ def self.config
12
+ @config ||= File.exists?(RAILSONFIRE_FILE) ? stringify(YAML.load(File.read(RAILSONFIRE_FILE))) : {}
13
+ end
14
+
15
+ def self.login token, github_token
16
+ @user = Railsonfire::User.new token, github_token
17
+ end
18
+
19
+ def self.user
20
+ @user
21
+ end
22
+
23
+ def self.project
24
+ id = Railsonfire.config["id"]
25
+ if id
26
+ @project ||= Project.new user.railsonfire_token, id
27
+ else
28
+ @project ||= Project.new user.railsonfire_token
29
+ end
30
+ end
31
+
32
+ class Project
33
+ include Helper
34
+ include Helper::Keys
35
+
36
+ attr_accessor :name, :owner, :url
37
+ attr_reader :ssh_public_key, :ssh_private_key, :uuid
38
+
39
+ def initialize token, id = nil
40
+ @token = token
41
+ load_project_data token, id if id
42
+ end
43
+
44
+ def create
45
+ send_signal :starting_create
46
+ ssh_key = create_ssh_key
47
+ @ssh_public_key = ssh_key.ssh_public_key
48
+ @ssh_private_key = ssh_key.rsa_private_key
49
+ keys = create_keys ssh_key
50
+ body = {:name => name, :owner => owner, :repo_url => url}.merge(keys)
51
+ response = HTTParty.post("#{Railsonfire::DOMAIN}/projects?token=#@token", :headers => {"Content-Type" => "application/json"}, :body => body.to_json)
52
+ case response.code
53
+ when 201
54
+ @uuid = response.body
55
+ Railsonfire.config["id"] = @uuid
56
+ send_signal :created
57
+ true
58
+ when 404
59
+ shell.say "Could not authenticate with Railsonfire. Please logout and back in via the railsonfire gem."
60
+ notify("create-authenticate", "Could not authenticate with Railsonfire")
61
+ false
62
+ else
63
+ shell.say "An Error occured on the Railsonfire Servers and we were notified. Please try again or contact us at flo@railsonfire.com"
64
+ notify("create-error", "Error occured when creating a project")
65
+ false
66
+ end
67
+ end
68
+
69
+ private
70
+ def load_project_data token, id
71
+ response = HTTParty.get("#{Railsonfire::DOMAIN}/projects/#{id}/project_data?access_token=#{token}")
72
+ if response.code != 200
73
+ shell.say "An Error occured on the Railsonfire server"
74
+ notify("load_project", "Project data couldn't be loaded", {:token => token, :id => id})
75
+ return nil
76
+ else
77
+ data = JSON.parse(response.body)
78
+ @name = data["name"]
79
+ @owner = data["owner"]
80
+ @ssh_public_key = data["public_key"]
81
+ end
82
+ end
83
+ end
84
+ class User
85
+ attr_reader :github_token, :railsonfire_token
86
+ def initialize railsonfire_token, github_token
87
+ @railsonfire_token = railsonfire_token
88
+ @github_token = github_token
89
+ end
90
+
91
+ def config
92
+ JSON.parse(HTTParty.get(Railsonfire::DOMAIN + "/projects/#{Railsonfire.config["id"]}/get_config?railsonfire_token=#{@railsonfire_token}").body)
93
+ end
94
+
95
+ def set_config key, value
96
+ HTTParty.post(Railsonfire::DOMAIN + "/projects/#{Railsonfire.config["id"]}/add_config?railsonfire_token=#{@railsonfire_token}", :headers => {"Content-Type" => "application/json"}, :body => {"config" => {key => value}}.to_json)
97
+ end
98
+
99
+ def remove_config key
100
+ HTTParty.delete(Railsonfire::DOMAIN + "/projects/#{Railsonfire.config["id"]}/remove_config?railsonfire_token=#{@railsonfire_token}&key=#{key}")
101
+ end
102
+
103
+ end
104
+
105
+ private
106
+ def self.stringify hash
107
+ hash.tap do |h|
108
+ h.stringify_keys!
109
+ h.each do |key, value|
110
+ stringify h[key] if h[key].is_a?(Hash)
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,18 @@
1
+ require 'railsonfire/subcommands/heroku'
2
+ require 'railsonfire/subcommands/github'
3
+ require 'railsonfire/subcommands/auth'
4
+ require 'railsonfire/subcommands/config'
5
+
6
+ class CLI < BASECLI
7
+ desc "heroku", "Manage Heroku connection with Railsonfire"
8
+ subcommand "heroku", Railsonfire::Heroku
9
+
10
+ desc "auth", "Configure your authentication with Railsonfire"
11
+ subcommand "auth", Auth
12
+
13
+ desc "github", "Manage GitHub connection with your Projects"
14
+ subcommand "github", Github
15
+
16
+ desc "config", "Manage configuration values set for your Railsonfire account"
17
+ subcommand "config", Railsonfire::Config
18
+ end
@@ -0,0 +1,79 @@
1
+ require 'launchy'
2
+ require 'httparty'
3
+ require 'heroku'
4
+
5
+ class Auth < BASECLI
6
+ CREDENTIALS_PATH = "#{ENV["HOME"]}/.railsonfire/"
7
+ CREDENTIALS_FILE = CREDENTIALS_PATH + "credentials"
8
+ desc "login", "Authenticate the local machine with Railsonfire"
9
+ def login
10
+ if File.exists?(CREDENTIALS_FILE)
11
+ say "Credentials Found. Checking with Railsonfire Servers"
12
+ token = File.read(CREDENTIALS_FILE)
13
+ else
14
+ Dir.mkdir(CREDENTIALS_PATH) unless File.exists?(CREDENTIALS_PATH)
15
+ token = load_token_from_heroku
16
+ token ||= ask_user_for_token
17
+ File.open(CREDENTIALS_FILE, "w").tap do |file|
18
+ file.write(token)
19
+ file.close
20
+ end
21
+ end
22
+ begin
23
+ response = HTTParty.get("#{Railsonfire::DOMAIN}/users/#{token}/token")
24
+ if response.code == 200 || response.code == 404
25
+ Railsonfire.login(token, response.body)
26
+ send_signal :logged_in
27
+ success "Credentials verified and logged in successfully"
28
+ true
29
+ else
30
+ error "Couldn't authenticate with Railsonfire servers. Please try again and check your Token."
31
+ notify("login", "Couldn't authenticate with railsonfire", {:token => token, :body => response.body})
32
+ logout
33
+ exit
34
+ end
35
+ rescue Exception => e
36
+ exit if e.class == SystemExit
37
+ logout
38
+ error "There was an Error when communicating with the Railsonfire server."
39
+ error "Please login again and make sure you logged in with the correct Railsonfire Token."
40
+ notify(e.class, "Request Error: #{e.message}", {:backtrace => e.backtrace, :error_class => e.class})
41
+ exit
42
+ end
43
+ end
44
+
45
+ desc "logout", "Delete all Authentication Data from the local machine"
46
+ def logout
47
+ say "Removing local credentials"
48
+ File.delete(CREDENTIALS_FILE) if File.exists?(CREDENTIALS_FILE)
49
+ end
50
+
51
+ private
52
+ def load_token_from_heroku
53
+ unless Heroku::Auth.read_credentials
54
+ warning "You are not authenticated with Heroku locally, thus we can not automatically detect your credentials."
55
+ return nil
56
+ end
57
+ success "Reading your credentials from Heroku.This may take a few seconds."
58
+ h = heroku
59
+ apps = h.get_apps.body.collect{|app| railsonfire_id = h.get_config_vars(app["name"]).body["RAILSONFIRE_ID"]; railsonfire_id ? [app["name"], railsonfire_id] : nil}.compact
60
+ case apps.count
61
+ when 0
62
+ error("Couldn't find any Heroku Addon Data for Railsonfire.")
63
+ return nil
64
+ when 1
65
+ app = apps.first
66
+ else
67
+ warning "You seem to have added Railsonfire to several apps. Please select the Heroku App you want to register with"
68
+ app = select("Please select the Heroku App you added our Addon to", apps){|element, index| "#{index}. #{element.first}"}
69
+ end
70
+ response = post_json("#{Railsonfire::DOMAIN}/heroku/exchange_token", {:railsonfire_id => app.last, :email => Heroku::Auth.get_credentials.first})
71
+ response.code == 200 ? response.body : nil
72
+ end
73
+
74
+ def ask_user_for_token
75
+ success("Please enter your Railsonfire Token. The Website to copy the token will open shortly")
76
+ Launchy.open("https://www.railsonfire.com/users/edit")
77
+ ask("Key:")
78
+ end
79
+ end
@@ -0,0 +1,30 @@
1
+ require 'launchy'
2
+ require 'httparty'
3
+
4
+ class Railsonfire::Config < BASECLI
5
+ desc "show", "show the current config values set for your Railsonfire project"
6
+ def show
7
+ invoke "auth:login"
8
+ send_signal :show_config
9
+ say "No configuration values set" and return if Railsonfire.user.config.empty?
10
+ Railsonfire.user.config.each do |cfg|
11
+ say "#{cfg[0]}=#{cfg[1]}"
12
+ end
13
+ end
14
+
15
+ desc "add", "Asks you for a Key and Value to add to your Railsonfire config"
16
+ def add
17
+ invoke "auth:login"
18
+ send_signal :add_config
19
+ key = ask "Key:"
20
+ value = ask "Value:"
21
+ Railsonfire.user.set_config key, value
22
+ end
23
+
24
+ desc "remove", "Remove a configuration value"
25
+ def remove
26
+ invoke "auth:login"
27
+ send_signal :remove_config
28
+ Railsonfire.user.remove_config(ask "Key:")
29
+ end
30
+ end
@@ -0,0 +1,67 @@
1
+ require 'thor'
2
+
3
+ class Github < BASECLI
4
+ GITHUB_KEY_URL = "https://api.github.com/repos/%s/%s/keys?access_token=%s"
5
+ RAILSONFIRE_HOOK_URL = "http://railsonfire.com/hook/%s"
6
+ GITHUB_HOOK_URL = "https://api.github.com/repos/%s/%s/hooks?access_token=%s"
7
+
8
+ desc "upload_key", "Upload the projects ssh Key to GitHub"
9
+ def upload_key
10
+ return false unless Railsonfire.user || invoke("auth:login")
11
+ send_signal :github_upload_key_started
12
+ return false unless has_github_token
13
+ project = Railsonfire.project
14
+ say "Adding SSH Key to Github Repository %s/%s" % [project.owner, project.name]
15
+ key = project.ssh_public_key.sub("\n", "") + " railsonfire/#{project.owner}/#{project.name}"
16
+ json = {:title => "railsonfire", :key => key}.to_json
17
+ response = HTTParty.post(github_url(GITHUB_KEY_URL), {:body => json})
18
+ if response.code != 201
19
+ error "Could not upload ssh key to Github"
20
+ error " Please make sure your Railsonfire account is connected with Github on https://www.railsonfire.com/users/edit and run railsonfire github upload_key"
21
+ error " If you do not want to give us access to your projects metadata and add the SSH key by hand please go to the edit page of your project and follow the instructions"
22
+ notify("github-key-upload", "Could not upload key to github", {:body => response.body, :code => response.code})
23
+ send_signal :github_upload_key_failed
24
+ false
25
+ else
26
+ send_signal :github_upload_key_finished
27
+ true
28
+ end
29
+ end
30
+
31
+ desc "add_hook", "Add Hook to GitHub repository"
32
+ def add_hook
33
+ return false unless Railsonfire.user || invoke("auth:login")
34
+ send_signal :github_add_hook_started
35
+ return false unless has_github_token
36
+ project = Railsonfire.project
37
+ say "Adding Post Receive Hook to Github Repository %s/%s" % [project.owner, project.name]
38
+ url = RAILSONFIRE_HOOK_URL % [Railsonfire.config["id"]]
39
+ json = {:name => "web", :config => {:url => url}}.to_json
40
+ response = HTTParty.post(github_url(GITHUB_HOOK_URL), {:body => json})
41
+ if response.code != 201
42
+ send_signal :github_add_hook_failed
43
+ error "Could not add post-receive Hook Github"
44
+ error " Please make sure your Railsonfire account is connected with Github on https://www.railsonfire.com/users/edit and run railsonfire github add_hook"
45
+ error " If you do not want to give us access to your projects metadata and set your Post-Receive-Hook by hand please go to the edit page of your project and follow the instructions"
46
+ notify("github-hook-upload", "Could not hook to github", {:body => response.body, :code => response.code})
47
+ false
48
+ else
49
+ send_signal :github_add_hook_finished
50
+ true
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def has_github_token
57
+ token = Railsonfire.user.github_token
58
+ has_token = !(token.nil? || token.empty?)
59
+ warning("Your account isn't connected with GitHub so we can not set the SSH Key and Hook automatically") unless has_token
60
+ return has_token
61
+ end
62
+
63
+ def github_url url
64
+ project = Railsonfire.project
65
+ url % [project.owner, project.name, Railsonfire.user.github_token]
66
+ end
67
+ end
@@ -0,0 +1,80 @@
1
+ require 'railsonfire/helpers/base'
2
+ require 'heroku'
3
+ require 'active_support/core_ext/hash/deep_merge'
4
+ require 'heroku/command'
5
+
6
+ class Railsonfire::Heroku < BASECLI
7
+
8
+ desc "upload_key", "Upload a key to Heroku"
9
+ def upload_key
10
+ invoke "auth:login"
11
+ send_signal :heroku_upload_key_started
12
+ say "Adding SSH Key to Heroku"
13
+ if project.ssh_public_key
14
+ heroku.post_key(project.ssh_public_key + " railsonfire/#{project.owner}/#{project.name}")
15
+ send_signal :heroku_upload_key_finished
16
+ else
17
+ error "Couldn't upload Key to Heroku"
18
+ end
19
+ end
20
+
21
+ desc "configure", "Configure Deployment to Heroku"
22
+ def configure
23
+ invoke "auth:login"
24
+ send_signal :heroku_configure_started
25
+ apps = heroku.get_apps.body.collect{|app| app["name"]}.sort
26
+ no_deployment = "No deployment to "
27
+ staging_name = select "Name of your Staging application:", apps + [no_deployment + "Staging"]
28
+ staging_name = "" if staging_name.start_with? no_deployment
29
+ production_name = select "Name of your Production application:", apps + [no_deployment + "Production"]
30
+ production_name = "" if production_name.start_with? no_deployment
31
+ has_pgbackups = has_pgbackups_addon_installed production_name unless production_name.empty?
32
+ deploy = {
33
+ "deploy" => {
34
+ "heroku" => {
35
+ "staging" =>{
36
+ "name" => staging_name
37
+ },
38
+ "production" =>{
39
+ "name" => production_name,
40
+ }
41
+ }
42
+ }
43
+ }
44
+ deploy.deep_merge!("deploy" => {"heroku" => {"production" => {"backup" => false}}}) if production_name != "" and !has_pgbackups
45
+ invoke "upload_key"
46
+ invoke "credentials"
47
+ Railsonfire.config.deep_merge!(deploy)
48
+ write_config_file
49
+ end
50
+
51
+ desc "credentials", "Upload Heroku Credentials to Railsonfire user"
52
+ def credentials
53
+ invoke "auth:login"
54
+ send_signal :heroku_credentials_started
55
+ token_key = "heroku_token"
56
+ config = Railsonfire.user.config
57
+ if config[token_key]
58
+ say "Your currently stored Heroku Token is:"
59
+ say " Token: #{config[token_key]}"
60
+ end
61
+ heroku_token = Heroku::Auth.get_credentials.last
62
+ if config[token_key] != heroku_token
63
+ return if config[token_key] != nil and no? "Do you want to replace your current Heroku Credentials with #{heroku_token}"
64
+ say "Setting Heroku token on Railsonfire"
65
+ Railsonfire.user.set_config token_key, heroku_token
66
+ send_signal :heroku_credentials_set
67
+ end
68
+ end
69
+
70
+ private
71
+ def has_pgbackups_addon_installed app
72
+ !heroku.get_addons(app).body.collect{|addon| addon["name"]}.select{|addon| addon["pgbackups"]}.empty?.tap do |h|
73
+ warning "You should add the pgbackups addon to #{app} with \"heroku addons:add pgbackups:auto-month --app #{app}\" and enable Backup in your railsonfire.yml file" if h
74
+ end
75
+ end
76
+
77
+ def project
78
+ Railsonfire.project
79
+ end
80
+ end
@@ -0,0 +1,47 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "railsonfire"
3
+ s.version = "0.2.13"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Florian Motlik"]
7
+ s.description = "The Railsonfire gem let's you create projects on the Railsonfire service"
8
+ s.email = "flo@railsonfire.com"
9
+ s.executables = ["railsonfire"]
10
+ s.extra_rdoc_files = [
11
+ "LICENSE.txt",
12
+ "README.rdoc"
13
+ ]
14
+ s.files = [
15
+ "Gemfile",
16
+ "Gemfile.lock",
17
+ "LICENSE.txt",
18
+ "bin/railsonfire",
19
+ "railsonfire.gemspec",
20
+ ] + Dir['lib/**/*']
21
+ s.homepage = "https://www.railsonfire.com"
22
+ s.licenses = ["MIT"]
23
+ s.require_paths = ["lib"]
24
+ s.rubygems_version = "1.8.10"
25
+ s.summary = "Interact with Railsonfire"
26
+
27
+ s.add_dependency("launchy", "2.1.2")
28
+ s.add_dependency("sshkey", "1.3.1")
29
+ s.add_dependency("httparty", "0.8.3")
30
+ s.add_dependency("heroku", "2.30.4")
31
+ s.add_dependency("git", "1.2.5")
32
+ s.add_dependency("json_pure", "1.7.5")
33
+ s.add_dependency("activesupport", "3.2.8")
34
+ s.add_dependency("multi_json", "1.3.6")
35
+ s.add_dependency("thor", "0.16.0")
36
+ s.add_dependency("gems", "0.7.0")
37
+
38
+
39
+
40
+ s.add_development_dependency('rspec')
41
+ s.add_development_dependency('rake')
42
+ s.add_development_dependency('pry')
43
+ #Do not work in Ruby 1.8.7, so enable when needed for debugging
44
+ #s.add_development_dependency('pry-nav')
45
+ #s.add_development_dependency('pry-exception_explorer')
46
+ s.add_development_dependency('simplecov')
47
+ end
metadata ADDED
@@ -0,0 +1,295 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: railsonfire
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.13
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Florian Motlik
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-26 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: launchy
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - '='
20
+ - !ruby/object:Gem::Version
21
+ version: 2.1.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - '='
28
+ - !ruby/object:Gem::Version
29
+ version: 2.1.2
30
+ - !ruby/object:Gem::Dependency
31
+ name: sshkey
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - '='
36
+ - !ruby/object:Gem::Version
37
+ version: 1.3.1
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - '='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.3.1
46
+ - !ruby/object:Gem::Dependency
47
+ name: httparty
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - '='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.8.3
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.3
62
+ - !ruby/object:Gem::Dependency
63
+ name: heroku
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - '='
68
+ - !ruby/object:Gem::Version
69
+ version: 2.30.4
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - '='
76
+ - !ruby/object:Gem::Version
77
+ version: 2.30.4
78
+ - !ruby/object:Gem::Dependency
79
+ name: git
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - '='
84
+ - !ruby/object:Gem::Version
85
+ version: 1.2.5
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - '='
92
+ - !ruby/object:Gem::Version
93
+ version: 1.2.5
94
+ - !ruby/object:Gem::Dependency
95
+ name: json_pure
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - '='
100
+ - !ruby/object:Gem::Version
101
+ version: 1.7.5
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - '='
108
+ - !ruby/object:Gem::Version
109
+ version: 1.7.5
110
+ - !ruby/object:Gem::Dependency
111
+ name: activesupport
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - '='
116
+ - !ruby/object:Gem::Version
117
+ version: 3.2.8
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - '='
124
+ - !ruby/object:Gem::Version
125
+ version: 3.2.8
126
+ - !ruby/object:Gem::Dependency
127
+ name: multi_json
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - '='
132
+ - !ruby/object:Gem::Version
133
+ version: 1.3.6
134
+ type: :runtime
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - '='
140
+ - !ruby/object:Gem::Version
141
+ version: 1.3.6
142
+ - !ruby/object:Gem::Dependency
143
+ name: thor
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - '='
148
+ - !ruby/object:Gem::Version
149
+ version: 0.16.0
150
+ type: :runtime
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - '='
156
+ - !ruby/object:Gem::Version
157
+ version: 0.16.0
158
+ - !ruby/object:Gem::Dependency
159
+ name: gems
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - '='
164
+ - !ruby/object:Gem::Version
165
+ version: 0.7.0
166
+ type: :runtime
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - '='
172
+ - !ruby/object:Gem::Version
173
+ version: 0.7.0
174
+ - !ruby/object:Gem::Dependency
175
+ name: rspec
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ type: :development
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ - !ruby/object:Gem::Dependency
191
+ name: rake
192
+ requirement: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ! '>='
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ type: :development
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ! '>='
204
+ - !ruby/object:Gem::Version
205
+ version: '0'
206
+ - !ruby/object:Gem::Dependency
207
+ name: pry
208
+ requirement: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ! '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :development
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ - !ruby/object:Gem::Dependency
223
+ name: simplecov
224
+ requirement: !ruby/object:Gem::Requirement
225
+ none: false
226
+ requirements:
227
+ - - ! '>='
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ none: false
234
+ requirements:
235
+ - - ! '>='
236
+ - !ruby/object:Gem::Version
237
+ version: '0'
238
+ description: The Railsonfire gem let's you create projects on the Railsonfire service
239
+ email: flo@railsonfire.com
240
+ executables:
241
+ - railsonfire
242
+ extensions: []
243
+ extra_rdoc_files:
244
+ - LICENSE.txt
245
+ - README.rdoc
246
+ files:
247
+ - Gemfile
248
+ - Gemfile.lock
249
+ - LICENSE.txt
250
+ - bin/railsonfire
251
+ - railsonfire.gemspec
252
+ - lib/railsonfire/subcommands/auth.rb
253
+ - lib/railsonfire/subcommands/config.rb
254
+ - lib/railsonfire/subcommands/github.rb
255
+ - lib/railsonfire/subcommands/heroku.rb
256
+ - lib/railsonfire/commands/post-receive
257
+ - lib/railsonfire/commands/create.rb
258
+ - lib/railsonfire/commands/post_receive.rb
259
+ - lib/railsonfire/cli.rb
260
+ - lib/railsonfire/subcommands.rb
261
+ - lib/railsonfire/railsonfire.rb
262
+ - lib/railsonfire/commands.rb
263
+ - lib/railsonfire/helpers/key.rb
264
+ - lib/railsonfire/helpers/base.rb
265
+ - lib/railsonfire/helpers/constants.rb
266
+ - lib/railsonfire/helpers/base_cli.rb
267
+ - lib/railsonfire.rb
268
+ - README.rdoc
269
+ homepage: https://www.railsonfire.com
270
+ licenses:
271
+ - MIT
272
+ post_install_message:
273
+ rdoc_options: []
274
+ require_paths:
275
+ - lib
276
+ required_ruby_version: !ruby/object:Gem::Requirement
277
+ none: false
278
+ requirements:
279
+ - - ! '>='
280
+ - !ruby/object:Gem::Version
281
+ version: '0'
282
+ required_rubygems_version: !ruby/object:Gem::Requirement
283
+ none: false
284
+ requirements:
285
+ - - ! '>='
286
+ - !ruby/object:Gem::Version
287
+ version: '0'
288
+ requirements: []
289
+ rubyforge_project:
290
+ rubygems_version: 1.8.24
291
+ signing_key:
292
+ specification_version: 3
293
+ summary: Interact with Railsonfire
294
+ test_files: []
295
+ has_rdoc: