netlify 0.1.0
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.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +40 -0
- data/LICENSE.txt +22 -0
- data/README.md +423 -0
- data/Rakefile +7 -0
- data/lib/netlify.rb +17 -0
- data/lib/netlify/access_token.rb +5 -0
- data/lib/netlify/access_tokens.rb +7 -0
- data/lib/netlify/client.rb +113 -0
- data/lib/netlify/collection_proxy.rb +48 -0
- data/lib/netlify/deploy.rb +58 -0
- data/lib/netlify/deploys.rb +43 -0
- data/lib/netlify/dns_record.rb +5 -0
- data/lib/netlify/dns_records.rb +7 -0
- data/lib/netlify/dns_zone.rb +11 -0
- data/lib/netlify/dns_zones.rb +11 -0
- data/lib/netlify/file.rb +5 -0
- data/lib/netlify/files.rb +7 -0
- data/lib/netlify/form.rb +9 -0
- data/lib/netlify/forms.rb +7 -0
- data/lib/netlify/model.rb +65 -0
- data/lib/netlify/multipass.rb +70 -0
- data/lib/netlify/site.rb +69 -0
- data/lib/netlify/sites.rb +18 -0
- data/lib/netlify/snippet.rb +5 -0
- data/lib/netlify/snippets.rb +7 -0
- data/lib/netlify/submission.rb +6 -0
- data/lib/netlify/submissions.rb +7 -0
- data/lib/netlify/user.rb +17 -0
- data/lib/netlify/users.rb +7 -0
- data/lib/netlify/version.rb +3 -0
- data/test/client_test.rb +77 -0
- data/test/files/site-dir.zip +0 -0
- data/test/files/site-dir/index.html +5 -0
- data/test/multipass_test.rb +14 -0
- data/test/sites_test.rb +66 -0
- data/test/test_helper.rb +6 -0
- metadata +156 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
# Multipass implementation used for single-sign-on for resellers
|
2
|
+
require "openssl"
|
3
|
+
require "base64"
|
4
|
+
require "time"
|
5
|
+
require "json"
|
6
|
+
|
7
|
+
module Netlify
|
8
|
+
class Multipass
|
9
|
+
def initialize(multipass_secret)
|
10
|
+
### Use the Multipass secret to derive two cryptographic keys,
|
11
|
+
### one for encryption, one for signing
|
12
|
+
key_material = OpenSSL::Digest.new("sha256").digest(multipass_secret)
|
13
|
+
@encryption_key = key_material[ 0,16]
|
14
|
+
@signature_key = key_material[16,16]
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_token(customer_data_hash)
|
18
|
+
### Store the current time in ISO8601 format.
|
19
|
+
### The token will only be valid for a small timeframe around this timestamp.
|
20
|
+
customer_data_hash["created_at"] = Time.now.iso8601
|
21
|
+
|
22
|
+
### Serialize the customer data to JSON and encrypt it
|
23
|
+
ciphertext = encrypt(customer_data_hash.to_json)
|
24
|
+
|
25
|
+
### Create a signature (message authentication code) of the ciphertext
|
26
|
+
### and encode everything using URL-safe Base64 (RFC 4648)
|
27
|
+
sig = sign(ciphertext)
|
28
|
+
|
29
|
+
Base64.urlsafe_encode64(ciphertext + sign(ciphertext))
|
30
|
+
end
|
31
|
+
|
32
|
+
def decode_token(token)
|
33
|
+
decoded_token = Base64.urlsafe_decode64(token)
|
34
|
+
ciphertext, signature = [decoded_token[0..-33], decoded_token[-32..-1]]
|
35
|
+
|
36
|
+
sig = sign(ciphertext)
|
37
|
+
|
38
|
+
raise "Bad signature" unless sign(ciphertext) == signature
|
39
|
+
|
40
|
+
JSON.parse(decrypt(ciphertext))
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def encrypt(plaintext)
|
45
|
+
cipher = OpenSSL::Cipher::Cipher.new("aes-128-cbc")
|
46
|
+
cipher.encrypt
|
47
|
+
cipher.key = @encryption_key
|
48
|
+
|
49
|
+
### Use a random IV
|
50
|
+
cipher.iv = iv = cipher.random_iv
|
51
|
+
|
52
|
+
### Use IV as first block of ciphertext
|
53
|
+
iv + cipher.update(plaintext) + cipher.final
|
54
|
+
end
|
55
|
+
|
56
|
+
def decrypt(ciphertext)
|
57
|
+
decipher = OpenSSL::Cipher::Cipher.new("aes-128-cbc")
|
58
|
+
decipher.decrypt
|
59
|
+
decipher.key = @encryption_key
|
60
|
+
|
61
|
+
decipher.iv, encrypted = [ciphertext[0..15], ciphertext[16..-1]]
|
62
|
+
|
63
|
+
decipher.update(encrypted) + decipher.final
|
64
|
+
end
|
65
|
+
|
66
|
+
def sign(data)
|
67
|
+
OpenSSL::HMAC.digest("sha256", @signature_key, data)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/netlify/site.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Netlify
|
5
|
+
class Site < Model
|
6
|
+
fields :id, :state, :premium, :claimed, :name, :custom_domain, :url,
|
7
|
+
:admin_url, :deploy_id, :deploy_url, :screenshot_url, :created_at, :updated_at,
|
8
|
+
:password, :notification_email, :user_id, :error_message, :required
|
9
|
+
|
10
|
+
def ready?
|
11
|
+
state == "current"
|
12
|
+
end
|
13
|
+
|
14
|
+
def error?
|
15
|
+
state == "error"
|
16
|
+
end
|
17
|
+
|
18
|
+
def wait_for_ready(timeout = 900, &block)
|
19
|
+
deploy = deploys.get(deploy_id)
|
20
|
+
raise "Error fetching deploy #{deploy_id}" unless deploy
|
21
|
+
deploy.wait_for_ready(timeout, &block)
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def update(attributes)
|
26
|
+
response = client.request(:put, path, :body => mutable_attributes(attributes))
|
27
|
+
process(response.parsed)
|
28
|
+
if attributes[:zip] || attributes[:dir]
|
29
|
+
deploy = deploys.create(attributes)
|
30
|
+
self.deploy_id = deploy.id
|
31
|
+
end
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def destroy!
|
36
|
+
client.request(:delete, path)
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def forms
|
41
|
+
Forms.new(client, path)
|
42
|
+
end
|
43
|
+
|
44
|
+
def submissions
|
45
|
+
Submissions.new(client, path)
|
46
|
+
end
|
47
|
+
|
48
|
+
def files
|
49
|
+
Files.new(client, path)
|
50
|
+
end
|
51
|
+
|
52
|
+
def snippets
|
53
|
+
Snippets.new(client, path)
|
54
|
+
end
|
55
|
+
|
56
|
+
def deploys
|
57
|
+
Deploys.new(client, path)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def mutable_attributes(attributes)
|
62
|
+
Hash[*[:name, :custom_domain, :password, :notification_email].map {|key|
|
63
|
+
if attributes.has_key?(key) || attributes.has_key?(key.to_s)
|
64
|
+
[key, attributes[key] || attributes[key.to_s]]
|
65
|
+
end
|
66
|
+
}.compact.flatten]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "Netlify/site"
|
2
|
+
require "digest/sha1"
|
3
|
+
|
4
|
+
module Netlify
|
5
|
+
class Sites < CollectionProxy
|
6
|
+
path "/sites"
|
7
|
+
|
8
|
+
def create(attributes = {})
|
9
|
+
response = client.request(:post, path, :body => Site.new(client, {}).send(:mutable_attributes, attributes))
|
10
|
+
Site.new(client, response.parsed).tap do |site|
|
11
|
+
if attributes[:zip] || attributes[:dir]
|
12
|
+
deploy = site.deploys.create(attributes)
|
13
|
+
site.deploy_id = deploy.id
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/netlify/user.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Netlify
|
2
|
+
class User < Model
|
3
|
+
fields :id, :uid, :email, :affiliate_id, :site_count, :created_at, :last_login
|
4
|
+
|
5
|
+
def sites
|
6
|
+
Sites.new(client, path)
|
7
|
+
end
|
8
|
+
|
9
|
+
def submissions
|
10
|
+
Submissions.new(client, path)
|
11
|
+
end
|
12
|
+
|
13
|
+
def forms
|
14
|
+
Forms.new(client, path)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/test/client_test.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ClientTest < MiniTest::Unit::TestCase
|
4
|
+
attr_reader :client
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@client = Netlify::Client.new(:client_id => "client_id", :client_secret => "client_secret")
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_authorize_url
|
11
|
+
expected = URI.parse("https://api.netlify.com/oauth/authorize?response_type=code&client_id=client_id&redirect_uri=http%3A%2F%2Fexample.com%2Fcallback")
|
12
|
+
actual = URI.parse(client.authorize_url(:redirect_uri => "http://example.com/callback"))
|
13
|
+
assert_equal expected.scheme, actual.scheme
|
14
|
+
assert_equal expected.host, actual.host
|
15
|
+
assert_equal expected.port, actual.port
|
16
|
+
assert_equal expected.query.split("&").sort, actual.query.split("&").sort
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_authorize_from_code
|
20
|
+
stub_request(:post, "https://api.netlify.com/oauth/token").to_return(
|
21
|
+
:headers => {'Content-Type' => 'application/json'},
|
22
|
+
:body => {
|
23
|
+
"access_token" => "2YotnFZFEjr1zCsicMWpAA"
|
24
|
+
})
|
25
|
+
client.authorize_from_code!("authorization_code", :redirect_uri => "http://example.com/callback")
|
26
|
+
assert_equal "2YotnFZFEjr1zCsicMWpAA", client.access_token
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_authorize_from_credentials
|
30
|
+
stub_request(:post, "https://client_id:client_secret@api.netlify.com/oauth/token").to_return(
|
31
|
+
:headers => {'Content-Type' => 'application/json'},
|
32
|
+
:body => {
|
33
|
+
"access_token" => "2YotnFZFEjr1zCsicMWpAA"
|
34
|
+
})
|
35
|
+
|
36
|
+
client.authorize_from_credentials!
|
37
|
+
assert_equal "2YotnFZFEjr1zCsicMWpAA", client.access_token
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_simple_get_request
|
41
|
+
stub_request(:get, "https://api.netlify.com/api/v1/sites")
|
42
|
+
.with(:headers => {'Authorization' => "Bearer access_token"})
|
43
|
+
.to_return(
|
44
|
+
:headers => {'Content-Type' => 'application/json'},
|
45
|
+
:body => []
|
46
|
+
)
|
47
|
+
|
48
|
+
client.access_token = "access_token"
|
49
|
+
response = client.request(:get, "/sites")
|
50
|
+
assert_equal [], response.parsed
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_sites
|
54
|
+
stub_request(:get, "https://api.netlify.com/api/v1/sites")
|
55
|
+
.with(:headers => {'Authorization' => "Bearer access_token"})
|
56
|
+
.to_return(
|
57
|
+
:headers => {'Content-Type' => 'application/json'},
|
58
|
+
:body => JSON.generate([{:url => "http://www.example.com"}])
|
59
|
+
)
|
60
|
+
client.access_token = "access_token"
|
61
|
+
sites = client.sites.all
|
62
|
+
assert_equal "http://www.example.com", sites.first.url
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_get_site
|
66
|
+
stub_request(:get, "https://api.netlify.com/api/v1/sites/1234")
|
67
|
+
.with(:headers => {'Authorization' => "Bearer access_token"})
|
68
|
+
.to_return(
|
69
|
+
:headers => {'Content-Type' => 'application/json'},
|
70
|
+
:body => {:url => "http://www.example.com"}
|
71
|
+
)
|
72
|
+
|
73
|
+
client.access_token = "access_token"
|
74
|
+
site = client.sites.get("1234")
|
75
|
+
assert_equal "http://www.example.com", site.url
|
76
|
+
end
|
77
|
+
end
|
Binary file
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'digest/sha1'
|
3
|
+
|
4
|
+
class MultipassTest < MiniTest::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@mp = Netlify::Multipass.new("secret")
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_generate_and_decode_token
|
10
|
+
data = {"email" => "test@example.com", "uid" => "1234"}
|
11
|
+
token = @mp.generate_token(data)
|
12
|
+
assert_equal data, @mp.decode_token(token), "Data should be the same after generating and decoding"
|
13
|
+
end
|
14
|
+
end
|
data/test/sites_test.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'digest/sha1'
|
3
|
+
|
4
|
+
class SitesTest < MiniTest::Unit::TestCase
|
5
|
+
attr_reader :client
|
6
|
+
attr_accessor :_assertions
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@client = Netlify::Client.new(:client_id => "client_id", :client_secret => "client_secret")
|
10
|
+
@client.access_token = "access_token"
|
11
|
+
self._assertions = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_create_from_dir
|
15
|
+
body = nil
|
16
|
+
dir = ::File.expand_path("../files/site-dir", __FILE__)
|
17
|
+
index_sha = Digest::SHA1.hexdigest(::File.read(::File.join(dir, "index.html")))
|
18
|
+
|
19
|
+
stub_request(:post, "https://api.netlify.com/api/v1/sites")
|
20
|
+
.to_return {|request|
|
21
|
+
{
|
22
|
+
:headers => {'Content-Type' => 'application/json'},
|
23
|
+
:body => JSON.generate({:id => "1234"})
|
24
|
+
}
|
25
|
+
}
|
26
|
+
stub_request(:post, "https://api.netlify.com/api/v1/sites/1234/deploys")
|
27
|
+
.to_return {|request|
|
28
|
+
body = JSON.parse(request.body)
|
29
|
+
{
|
30
|
+
:headers => {'Content-Type' => 'application/json'},
|
31
|
+
:body => JSON.generate({:id => "2345", :state => "uploading", :required => [index_sha]})
|
32
|
+
}
|
33
|
+
}
|
34
|
+
stub_request(:put, "https://api.netlify.com/api/v1/deploys/2345/files/index.html")
|
35
|
+
stub_request(:get, "https://api.netlify.com/api/v1/deploys/2345")
|
36
|
+
.to_return(:headers => {'Content-Type' => 'application/json'}, :body => {:id => "2345", :state => "processing"})
|
37
|
+
|
38
|
+
site = client.sites.create(:dir => dir)
|
39
|
+
|
40
|
+
assert_equal index_sha, body['files']['/index.html']
|
41
|
+
|
42
|
+
assert_requested :put, "https://api.netlify.com/api/v1/deploys/2345/files/index.html",
|
43
|
+
:body => ::File.read(::File.join(dir, "index.html")), :times => 1 # ===> Success
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_create_from_zip
|
47
|
+
stub_request(:post, "https://api.netlify.com/api/v1/sites")
|
48
|
+
.to_return({
|
49
|
+
:headers => {'Content-Type' => 'application/json'},
|
50
|
+
:body => JSON.generate({:id => "1234"})
|
51
|
+
})
|
52
|
+
|
53
|
+
stub_request(:post, "https://api.netlify.com/api/v1/sites/1234/deploys")
|
54
|
+
.to_return {|request|
|
55
|
+
{
|
56
|
+
:headers => {'Content-Type' => 'application/json'},
|
57
|
+
:body => JSON.generate({:id => "2345", :state => "uploading", :required => []})
|
58
|
+
}
|
59
|
+
}
|
60
|
+
zip = ::File.expand_path("../files/site-dir.zip", __FILE__)
|
61
|
+
site = client.sites.create(:zip => zip)
|
62
|
+
|
63
|
+
assert_requested :post, "https://api.netlify.com/api/v1/sites/1234/deploys",
|
64
|
+
:body => ::File.read(zip), :times => 1
|
65
|
+
end
|
66
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: netlify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mathias Biilmann Christensen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: oauth2
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.9.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.9.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: slop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: highline
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
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: webmock
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: API Client for Netlify
|
84
|
+
email:
|
85
|
+
- mathias@Netlify.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- Gemfile
|
91
|
+
- Gemfile.lock
|
92
|
+
- LICENSE.txt
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- lib/netlify.rb
|
96
|
+
- lib/netlify/access_token.rb
|
97
|
+
- lib/netlify/access_tokens.rb
|
98
|
+
- lib/netlify/client.rb
|
99
|
+
- lib/netlify/collection_proxy.rb
|
100
|
+
- lib/netlify/deploy.rb
|
101
|
+
- lib/netlify/deploys.rb
|
102
|
+
- lib/netlify/dns_record.rb
|
103
|
+
- lib/netlify/dns_records.rb
|
104
|
+
- lib/netlify/dns_zone.rb
|
105
|
+
- lib/netlify/dns_zones.rb
|
106
|
+
- lib/netlify/file.rb
|
107
|
+
- lib/netlify/files.rb
|
108
|
+
- lib/netlify/form.rb
|
109
|
+
- lib/netlify/forms.rb
|
110
|
+
- lib/netlify/model.rb
|
111
|
+
- lib/netlify/multipass.rb
|
112
|
+
- lib/netlify/site.rb
|
113
|
+
- lib/netlify/sites.rb
|
114
|
+
- lib/netlify/snippet.rb
|
115
|
+
- lib/netlify/snippets.rb
|
116
|
+
- lib/netlify/submission.rb
|
117
|
+
- lib/netlify/submissions.rb
|
118
|
+
- lib/netlify/user.rb
|
119
|
+
- lib/netlify/users.rb
|
120
|
+
- lib/netlify/version.rb
|
121
|
+
- test/client_test.rb
|
122
|
+
- test/files/site-dir.zip
|
123
|
+
- test/files/site-dir/index.html
|
124
|
+
- test/multipass_test.rb
|
125
|
+
- test/sites_test.rb
|
126
|
+
- test/test_helper.rb
|
127
|
+
homepage: https://www.netlify.com
|
128
|
+
licenses: []
|
129
|
+
metadata: {}
|
130
|
+
post_install_message:
|
131
|
+
rdoc_options: []
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
requirements: []
|
145
|
+
rubyforge_project:
|
146
|
+
rubygems_version: 2.2.2
|
147
|
+
signing_key:
|
148
|
+
specification_version: 4
|
149
|
+
summary: API Client for Netlify
|
150
|
+
test_files:
|
151
|
+
- test/client_test.rb
|
152
|
+
- test/files/site-dir.zip
|
153
|
+
- test/files/site-dir/index.html
|
154
|
+
- test/multipass_test.rb
|
155
|
+
- test/sites_test.rb
|
156
|
+
- test/test_helper.rb
|