bitballoon 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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