bitballoon 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bitballoon (0.0.3)
4
+ bitballoon (0.0.4)
5
5
  highline
6
6
  oauth2 (>= 0.9.2)
7
7
  slop
data/README.md CHANGED
@@ -46,40 +46,65 @@ If you're not authenticating on behalf of a user you can authorize directly with
46
46
  bitballoon.authorize_from_credentials!
47
47
  ```
48
48
 
49
+ Command Line Utility
50
+ ====================
51
+
52
+ The BitBalloon gem comes with a handy command line utility for deploying and redeploying sites.
53
+
54
+ To deploy the site in the current working directory:
55
+
56
+ ```ruby
57
+ bitballoon deploy
58
+ ```
59
+
60
+ The first time you deploy, you will be asked for your `client id` and `client secret`. After the deploy the tool will store an `access_token` and the `site_id` in `.bitballoon`. Next time you run the command the tool will redeploy the site using the stored `access_token`.
61
+
62
+ You can also deploy a specific path:
63
+
64
+ ```ruby
65
+ bitballoon deploy /path/to/my/site
66
+ ```
67
+
68
+ Or a zip file:
69
+
70
+ ```ruby
71
+ bitballoon deploy /path/to/my/site.zip
72
+ ```
73
+
49
74
  Sites
50
75
  =====
51
76
 
52
77
  Getting a list of all sites you have access to:
53
78
 
54
79
  ```ruby
55
- bitballoon.sites.each do |site|
56
- puts site.url
57
- end
80
+ bitballoon.sites.each do |site|
81
+ puts site.url
82
+ end
58
83
  ```
59
84
 
60
85
  Getting a specific site by id:
61
86
 
62
87
  ```ruby
63
- site = bitballoon.sites.get(id)
88
+ site = bitballoon.sites.get(id)
64
89
  ```
65
90
 
66
91
  Creating a site from a directory:
67
92
 
68
93
  ```ruby
69
- site = bitballoon.sites.create(:dir => "/tmp/my-site")
94
+ site = bitballoon.sites.create(:dir => "/tmp/my-site")
70
95
  ```
71
96
 
72
97
  Creating a site from a zip file:
73
98
 
74
99
  ```ruby
75
- site = bitballoon.sites.create(:zip => "/tmp/my-site.zip")
100
+ site = bitballoon.sites.create(:zip => "/tmp/my-site.zip")
76
101
  ```
77
102
 
78
103
  Both methods will create the site and upload the files. The site will then be processing.
79
104
 
80
105
  ```ruby
81
- site.state == "processing"
82
- site.processing? == true
106
+ site.state == "processing"
107
+ site.processing? == true
83
108
  ```
84
109
 
85
110
  Refresh a site to update the state:
@@ -91,9 +116,25 @@ Refresh a site to update the state:
91
116
  Use `wait_until_ready` to wait until a site has finished processing.
92
117
 
93
118
  ```ruby
94
- site = bitballoon.sites.create(:dir => "/tmp/my-site")
95
- site.wait_for_ready
96
- site.state == "ready"
119
+ site = bitballoon.sites.create(:dir => "/tmp/my-site")
120
+ site.wait_for_ready
121
+ site.state == "ready"
122
+ ```
123
+
124
+ Redeploy a site from a dir:
125
+
126
+ ```ruby
127
+ site = bitballoon.sites.get(site_id)
128
+ site.update(:dir => "/tmp/my-site")
129
+ site.wait_for_ready
130
+ ```
131
+
132
+ Redeploy a site from a zip file:
133
+
134
+ ```ruby
135
+ site = bitballoon.sites.get(site_id)
136
+ site.update(:zip => "/tmp/my-site.zip")
137
+ site.wait_for_ready
97
138
  ```
98
139
 
99
140
  Update the name of the site (its subdomain), the custom domain and the notification email for form submissions:
data/bin/bitballoon CHANGED
@@ -12,33 +12,44 @@ opts = Slop.parse do
12
12
  command 'deploy' do
13
13
  run do |opts, args|
14
14
  path = args.first ? File.expand_path(args.first) : Dir.getwd
15
+ zip = path.match(/\.zip$/)
15
16
 
16
17
  raise "File or dir doesn't exist: #{path}" unless File.exist?(path)
17
- raise "Can't deploy a single file" if File.file?(path) && !path.match(/\.zip$/)
18
+ raise "Can't deploy a single file" if File.file?(path) && !zip
18
19
 
20
+ credentials_path = File.expand_path(".bitballoon", zip ? File.dirname(path) : path)
19
21
 
20
-
21
- credentials_path = File.exist?(File.expand_path(".bitballoon")) ? File.expand_path(".bitballoon") : "#{Dir.home}/.bitballoon"
22
22
  if File.exist?(credentials_path)
23
- access_token = JSON.parse(File.read(credentials_path))['access_token']
24
- client = BitBalloon::Client.new(:access_token => access_token)
23
+ credentials = JSON.parse(File.read(credentials_path))
24
+ client = BitBalloon::Client.new(:access_token => credentials['access_token'])
25
25
  else
26
26
  puts "Please enter your BitBalloon API Credentials (if you don't have any, you can create your credentials at https://www.bitballoon.com/applications)"
27
27
  client_id = ask("Client ID:")
28
28
  client_secret = ask("Client Secret:")
29
29
  client = BitBalloon::Client.new(:client_id => client_id, :client_secret => client_secret)
30
30
  client.authorize_from_credentials!
31
- File.open(credentials_path, "w") do |file|
32
- file.write(JSON.generate(:access_token => client.access_token))
33
- end
34
- puts "Wrote access token to '#{credentials_path}'"
31
+ credentials = {'access_token' => client.access_token}
35
32
  end
36
33
 
37
- site = path.match(/\.zip$/) ? client.sites.create(:zip => path) : client.sites.create(:dir => path)
34
+ attributes = zip ? {:zip => path} : {:dir => path}
35
+
36
+ if credentials['site_id']
37
+ site = client.sites.get(credentials['site_id'])
38
+ site.update(attributes)
39
+ else
40
+ site = client.sites.create(attributes)
41
+ end
38
42
  puts "Waiting for processing"
39
43
  site.wait_for_ready do |site|
40
44
  puts "Polling site: #{site.id} - #{site.state}"
41
45
  end
46
+
47
+ credentials['site_id'] = site.id
48
+
49
+ File.open(credentials_path, "w") do |file|
50
+ file.write(JSON.generate(credentials))
51
+ end
52
+
42
53
  puts "Site deployed: #{site.url}"
43
54
  end
44
55
  end
data/lib/bitballoon.rb CHANGED
@@ -8,5 +8,6 @@ require "bitballoon/forms"
8
8
  require "bitballoon/submissions"
9
9
  require "bitballoon/files"
10
10
  require "bitballoon/snippets"
11
+ require "bitballoon/deploys"
11
12
 
12
13
  module BitBalloon; end
@@ -5,6 +5,12 @@ module BitBalloon
5
5
  ENDPOINT = ENV['OAUTH_CLIENT_API_URL'] || 'https://www.bitballoon.com'
6
6
  API_VERSION = "v1"
7
7
 
8
+ class BitBalloonError < StandardError; end
9
+ class NotFoundError < BitBalloonError; end
10
+ class ConnectionError < BitBalloonError; end
11
+ class InternalServerError < BitBalloonError; end
12
+ class AuthenticationError < BitBalloonError; end
13
+
8
14
  attr_accessor :client_id, :client_secret, :oauth, :access_token
9
15
 
10
16
  def initialize(options)
@@ -45,13 +51,31 @@ module BitBalloon
45
51
  end
46
52
 
47
53
  def request(verb, path, opts={}, &block)
48
- raise "Authorize with BitBalloon before making requests" unless oauth_token
54
+ raise AuthenticationError, "Authorize with BitBalloon before making requests" unless oauth_token
55
+
49
56
  oauth_token.request(verb, ::File.join("/api", API_VERSION, path), opts, &block)
57
+ rescue OAuth2::Error => e
58
+ case e.response.status
59
+ when 401
60
+ raise AuthenticationError, message_for(e, "Authentication Error")
61
+ when 404
62
+ raise NotFoundError, message_for(e, "Not Found")
63
+ when 500
64
+ raise InternalServerError, message_for(e, "Internal Server Error")
65
+ else
66
+ raise BitBalloonError, message_for(e, "OAuth2 Error")
67
+ end
68
+ rescue Faraday::Error::ConnectionFailed => e
69
+ raise ConnectionError, message_for(e, "Connection Error")
50
70
  end
51
71
 
52
72
  private
53
73
  def oauth_token
54
74
  @oauth_token ||= access_token && OAuth2::AccessToken.new(oauth, access_token)
55
75
  end
76
+
77
+ def message_for(error, default)
78
+ error.message.strip == "" ? default : error.message
79
+ end
56
80
  end
57
81
  end
@@ -0,0 +1,13 @@
1
+ module BitBalloon
2
+ class Deploy < Model
3
+ fields :id, :state, :premium, :claimed, :name, :custom_domain, :url,
4
+ :admin_url, :deploy_url, :screenshot_url, :created_at, :updated_at,
5
+ :user_id, :required
6
+
7
+ def restore
8
+ response = client.request(:post, File.join(path, "restore"))
9
+ process(response.parsed)
10
+ self
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ require "bitballoon/deploy"
2
+
3
+ module BitBalloon
4
+ class Deploys < CollectionProxy
5
+ path "/deploys"
6
+ end
7
+ end
@@ -1,6 +1,6 @@
1
1
  module BitBalloon
2
2
  class Model
3
- attr_reader :client
3
+ attr_reader :client, :attributes
4
4
 
5
5
  def self.fields(*names)
6
6
  return @fields if names.empty?
@@ -3,8 +3,8 @@ require 'digest/sha1'
3
3
  module BitBalloon
4
4
  class Site < Model
5
5
  fields :id, :state, :premium, :claimed, :name, :custom_domain, :url,
6
- :admin_url, :screenshot_url, :created_at, :updated_at, :user_id,
7
- :required
6
+ :admin_url, :deploy_url, :screenshot_url, :created_at, :updated_at,
7
+ :user_id, :required, :error_message
8
8
 
9
9
  def upload_dir(dir)
10
10
  return unless state == "uploading"
@@ -25,14 +25,19 @@ module BitBalloon
25
25
  end
26
26
 
27
27
  def ready?
28
- state == "ready"
28
+ state == "current"
29
+ end
30
+
31
+ def error?
32
+ state == "error"
29
33
  end
30
34
 
31
35
  def wait_for_ready(timeout = 900)
32
36
  start = Time.now
33
- while !ready?
37
+ while !(ready?)
34
38
  sleep 5
35
39
  refresh
40
+ raise "Error processing site: #{error_message}" if error?
36
41
  yield(self) if block_given?
37
42
  raise "Timeout while waiting for ready" if Time.now - start > timeout
38
43
  end
@@ -40,8 +45,13 @@ module BitBalloon
40
45
  end
41
46
 
42
47
  def update(attributes)
43
- response = client.request(:put, path, :body => mutable_attributes(attributes))
44
- process(response.parsed)
48
+ if attributes[:zip] || attributes[:dir]
49
+ site = collection.new(client).create(attributes.merge(:id => id))
50
+ process(site.attributes)
51
+ else
52
+ response = client.request(:put, path, :body => mutable_attributes(attributes))
53
+ process(response.parsed)
54
+ end
45
55
  self
46
56
  end
47
57
 
@@ -6,15 +6,18 @@ module BitBalloon
6
6
  path "/sites"
7
7
 
8
8
  def create(attributes = {})
9
+ site_id = attributes.delete(:id)
10
+ path = site_id ? "/sites/#{site_id}" : "/sites"
11
+ method = site_id ? :put : :post
9
12
  if attributes[:dir]
10
13
  dir = attributes[:dir]
11
- response = client.request(:post, "/sites", :body => JSON.generate({:files => inventory(dir)}), :headers => {"Content-Type" => "application/json"})
14
+ response = client.request(method, path, :body => JSON.generate({:files => inventory(dir)}), :headers => {"Content-Type" => "application/json"})
12
15
  Site.new(client, response.parsed).tap do |site|
13
16
  site.upload_dir(dir)
14
17
  end
15
18
  elsif attributes[:zip]
16
19
  ::File.open(attributes[:zip]) do |file|
17
- response = client.request(:post, "/sites", :body => {
20
+ response = client.request(method, path, :body => {
18
21
  :zip => Faraday::UploadIO.new(file, 'application/zip')
19
22
  })
20
23
  Site.new(client, response.parsed)
@@ -1,3 +1,3 @@
1
1
  module BitBalloon
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitballoon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-27 00:00:00.000000000 Z
12
+ date: 2013-10-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: oauth2
@@ -109,6 +109,8 @@ files:
109
109
  - lib/bitballoon.rb
110
110
  - lib/bitballoon/client.rb
111
111
  - lib/bitballoon/collection_proxy.rb
112
+ - lib/bitballoon/deploy.rb
113
+ - lib/bitballoon/deploys.rb
112
114
  - lib/bitballoon/file.rb
113
115
  - lib/bitballoon/files.rb
114
116
  - lib/bitballoon/form.rb