render_api 0.0.1 → 0.2.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 +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +83 -1
- data/lib/render_api/camelise.rb +28 -0
- data/lib/render_api/client.rb +18 -3
- data/lib/render_api/clients/deploys.rb +7 -1
- data/lib/render_api/clients/domains.rb +39 -0
- data/lib/render_api/clients/jobs.rb +30 -0
- data/lib/render_api/clients/owners.rb +17 -0
- data/lib/render_api/clients/services.rb +58 -1
- data/lib/render_api/data_object.rb +52 -0
- data/lib/render_api/endpoint.rb +42 -3
- data/lib/render_api/response.rb +38 -0
- data/lib/render_api.rb +2 -1
- metadata +9 -78
- data/.rspec +0 -3
- data/Gemfile +0 -5
- data/Rakefile +0 -3
- data/spec/features/deploys_spec.rb +0 -68
- data/spec/features/services_spec.rb +0 -55
- data/spec/spec_helper.rb +0 -11
- data/spec/support/webmock.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f0ff1114203638708526d13f86bb2af21cac8e58da59ebb62b2fa8cb2b568e5
|
4
|
+
data.tar.gz: a301e13c6f5dae3f3e245120e60947065eaf7e6203a271651a655bf84b519c65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75666c35848e92149a4c10fd19e24307593a663f40cdc61461e2a22e24fea04d0e5c7c35e3d9e01464a8fa04f21ba46de2a83c8606f24b027afe9b30c346981c
|
7
|
+
data.tar.gz: d142dab2c7903d506ea87d5a7b295cc4ce3147f30f2b1bd9b4a854e42b7747ef2807d402becb48413c9ba48e6db3e3fef14a9da5f57dac6c454fdebc1af66a0d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.2.0] - 2025-07-30
|
4
|
+
|
5
|
+
- Add support for service restart endpoint (Barry Hess).
|
6
|
+
- Updated syntax for latest Rubocop preferences.
|
7
|
+
- Updated tested Ruby versions to 3.1-3.4 (dropping official support for 2.7, 3.0).
|
8
|
+
|
9
|
+
## [0.1.0] - 2022-05-29
|
10
|
+
|
11
|
+
- Ensure POST data is sent as JSON with camelCased keys (David Mauskop).
|
12
|
+
- Add support for job endpoints (David Mauskop).
|
13
|
+
- Add support for domain endpoints.
|
14
|
+
- Add support for all remaining service endpoints.
|
15
|
+
|
3
16
|
## [0.0.1] - 2021-12-12
|
4
17
|
|
5
18
|
- Initial release
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
A Ruby interface for [the render.com API](https://render.com/docs/api).
|
4
4
|
|
5
|
-
|
5
|
+
At this point in time all known API endpoints are supported.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -22,11 +22,93 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
+
Returned response objects can be enumerated upon when a list of records are returned, and also can provide rate-limit details via `rate_limit`, `rate_limit_remaining`, and `rate_limit_reset` methods.
|
26
|
+
|
27
|
+
The response objects respond to underscored versions of the attribute names - e.g. a service responds to `auto_deploy` with the value from the underlying hash for the key `autoDeploy`. Timestamp strings are automatically converted to Time objects, and nested hashes are also provided as these utility objects.
|
28
|
+
|
29
|
+
Also: when the response objects are from a list, they respond to `cursor`, for use with pagination.
|
30
|
+
|
31
|
+
### Creating a client
|
32
|
+
|
25
33
|
```ruby
|
26
34
|
client = RenderAPI.client(api_key)
|
35
|
+
```
|
36
|
+
|
37
|
+
### Services
|
38
|
+
|
39
|
+
```ruby
|
27
40
|
client.services.list(limit: nil, cursor: nil, filters: nil)
|
41
|
+
client.services.find(service_id)
|
42
|
+
```
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
services = client.services.list(limit: 20)
|
46
|
+
|
47
|
+
puts services.rate_limit, services.rate_limit_remaining
|
48
|
+
|
49
|
+
services.each do |service|
|
50
|
+
puts service.id
|
51
|
+
puts service.cursor
|
52
|
+
puts service.service_details.build_command
|
53
|
+
end
|
54
|
+
|
55
|
+
# https://api-docs.render.com/reference/create-service
|
56
|
+
client.services.create(name: "my-new-service", ...)
|
57
|
+
# https://api-docs.render.com/reference/update-service
|
58
|
+
client.services.update(service_id, name: "my-new-service", ...)
|
59
|
+
client.services.restart(service_id)
|
60
|
+
client.services.delete(service_id)
|
61
|
+
|
62
|
+
client.services.suspend(service_id)
|
63
|
+
client.services.resume(service_id)
|
64
|
+
client.services.scale(service_id, num_instances: 5)
|
65
|
+
|
66
|
+
client.services.list_headers(service_id, limit: nil, cursor: nil, filters: nil)
|
67
|
+
client.services.list_routes(service_id, limit: nil, cursor: nil, filters: nil)
|
68
|
+
client.services.list_variables(service_id, limit: nil, cursor: nil)
|
69
|
+
# Note that updating variables requires all variables to be provided.
|
70
|
+
# https://api-docs.render.com/reference/update-env-vars-for-service
|
71
|
+
# (i.e. a full update, not a partial update)
|
72
|
+
client.services.update_variables(
|
73
|
+
service_id,
|
74
|
+
[
|
75
|
+
{ key: "RAILS_ENV", value: "production" },
|
76
|
+
{ key: "RAILS_SESSION_SECRET", generate_value: "yes" }
|
77
|
+
]
|
78
|
+
)
|
79
|
+
```
|
80
|
+
|
81
|
+
### Deploys
|
82
|
+
|
83
|
+
```ruby
|
28
84
|
client.deploys.list(service_id, limit: nil, cursor: nil, filters: nil)
|
29
85
|
client.deploys.create(service_id, clear_cache: "do_not_clear")
|
86
|
+
client.deploys.find(service_id, deploy_id)
|
87
|
+
```
|
88
|
+
|
89
|
+
### Domains
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
client.domains.list(service_id, limit: nil, cursor: nil, filters: nil)
|
93
|
+
client.domains.create(service_id, name: "example.com")
|
94
|
+
client.domains.find(service_id, domain_id)
|
95
|
+
client.domains.verify(service_id, domain_id)
|
96
|
+
client.domains.delete(service_id, domain_id)
|
97
|
+
```
|
98
|
+
|
99
|
+
## Owners
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
client.owners.list(limit: nil, cursor: nil, filters: nil)
|
103
|
+
client.owners.find(owner_id)
|
104
|
+
```
|
105
|
+
|
106
|
+
## Jobs
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
client.jobs.list(service_id, limit: nil, cursor: nil, filters: nil)
|
110
|
+
client.jobs.create(service_id, start_command: "whoami")
|
111
|
+
client.jobs.find(service_id, job_id)
|
30
112
|
```
|
31
113
|
|
32
114
|
## Development
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RenderAPI
|
4
|
+
# Borrowed from awrence:
|
5
|
+
# https://github.com/technicalpanda/awrence/blob/main/lib/awrence/methods.rb
|
6
|
+
class Camelise
|
7
|
+
def self.call(...)
|
8
|
+
new.call(...)
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(string, first_upper: false)
|
12
|
+
if first_upper
|
13
|
+
string = gsubbed(string, /(?:^|_)([^_\s]+)/)
|
14
|
+
gsubbed(string, %r{/([^/]*)}, "::")
|
15
|
+
else
|
16
|
+
parts = string.split("_", 2)
|
17
|
+
parts[0] << call(parts[1], first_upper: true) if parts.size > 1
|
18
|
+
parts[0] || ""
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def gsubbed(string, pattern, extra = "")
|
25
|
+
string.gsub(pattern) { extra + Regexp.last_match(1).capitalize }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/render_api/client.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "
|
4
|
-
require_relative "
|
5
|
-
require_relative "
|
3
|
+
require_relative "clients/deploys"
|
4
|
+
require_relative "clients/domains"
|
5
|
+
require_relative "clients/jobs"
|
6
|
+
require_relative "clients/owners"
|
7
|
+
require_relative "clients/services"
|
8
|
+
require_relative "endpoint"
|
6
9
|
|
7
10
|
module RenderAPI
|
8
11
|
class Client
|
@@ -14,6 +17,18 @@ module RenderAPI
|
|
14
17
|
@deploys ||= Clients::Deploys.new(endpoint)
|
15
18
|
end
|
16
19
|
|
20
|
+
def domains
|
21
|
+
@domains ||= Clients::Domains.new(endpoint)
|
22
|
+
end
|
23
|
+
|
24
|
+
def jobs
|
25
|
+
@jobs ||= Clients::Jobs.new(endpoint)
|
26
|
+
end
|
27
|
+
|
28
|
+
def owners
|
29
|
+
@owners ||= Clients::Owners.new(endpoint)
|
30
|
+
end
|
31
|
+
|
17
32
|
def services
|
18
33
|
@services ||= Clients::Services.new(endpoint)
|
19
34
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "
|
3
|
+
require_relative "base"
|
4
4
|
|
5
5
|
module RenderAPI
|
6
6
|
module Clients
|
@@ -14,6 +14,12 @@ module RenderAPI
|
|
14
14
|
)
|
15
15
|
end
|
16
16
|
|
17
|
+
def find(service_id, deploy_id)
|
18
|
+
endpoint.get(
|
19
|
+
"/services/#{service_id}/deploys/#{deploy_id}"
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
17
23
|
def list(service_id, ...)
|
18
24
|
endpoint.get(
|
19
25
|
"/services/#{service_id}/deploys", params: list_parameters(...)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module RenderAPI
|
6
|
+
module Clients
|
7
|
+
class Domains < Base
|
8
|
+
def create(service_id, name:)
|
9
|
+
endpoint.post(
|
10
|
+
"/services/#{service_id}/custom-domains", body: { name: name }
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def delete(service_id, domain_id)
|
15
|
+
endpoint.delete(
|
16
|
+
"/services/#{service_id}/custom-domains/#{domain_id}"
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def find(service_id, domain_id)
|
21
|
+
endpoint.get(
|
22
|
+
"/services/#{service_id}/custom-domains/#{domain_id}"
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def list(service_id, ...)
|
27
|
+
endpoint.get(
|
28
|
+
"/services/#{service_id}/custom-domains", params: list_parameters(...)
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def verify(service_id, domain_id)
|
33
|
+
endpoint.post(
|
34
|
+
"/services/#{service_id}/custom-domains/#{domain_id}/verify"
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module RenderAPI
|
6
|
+
module Clients
|
7
|
+
class Jobs < Base
|
8
|
+
def create(service_id, start_command:, plan_id: nil)
|
9
|
+
body = { startCommand: start_command }
|
10
|
+
body[:plan_id] = plan_id unless plan_id.nil?
|
11
|
+
|
12
|
+
endpoint.post(
|
13
|
+
"/services/#{service_id}/jobs", body: body
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def find(service_id, job_id)
|
18
|
+
endpoint.get(
|
19
|
+
"/services/#{service_id}/jobs/#{job_id}"
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def list(service_id, ...)
|
24
|
+
endpoint.get(
|
25
|
+
"/services/#{service_id}/jobs", params: list_parameters(...)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module RenderAPI
|
6
|
+
module Clients
|
7
|
+
class Owners < Base
|
8
|
+
def find(owner_id)
|
9
|
+
endpoint.get("/owners/#{owner_id}")
|
10
|
+
end
|
11
|
+
|
12
|
+
def list(...)
|
13
|
+
endpoint.get("/owners", params: list_parameters(...))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,13 +1,70 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "
|
3
|
+
require_relative "base"
|
4
4
|
|
5
5
|
module RenderAPI
|
6
6
|
module Clients
|
7
7
|
class Services < Base
|
8
|
+
def create(**payload)
|
9
|
+
endpoint.post("/services", body: payload)
|
10
|
+
end
|
11
|
+
|
12
|
+
def delete(service_id)
|
13
|
+
endpoint.delete("/services/#{service_id}")
|
14
|
+
end
|
15
|
+
|
16
|
+
def find(service_id)
|
17
|
+
endpoint.get("/services/#{service_id}")
|
18
|
+
end
|
19
|
+
|
8
20
|
def list(...)
|
9
21
|
endpoint.get("/services", params: list_parameters(...))
|
10
22
|
end
|
23
|
+
|
24
|
+
def list_headers(service_id, ...)
|
25
|
+
endpoint.get(
|
26
|
+
"/services/#{service_id}/headers", params: list_parameters(...)
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def list_routes(service_id, ...)
|
31
|
+
endpoint.get(
|
32
|
+
"/services/#{service_id}/routes", params: list_parameters(...)
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def list_variables(service_id, ...)
|
37
|
+
endpoint.get(
|
38
|
+
"/services/#{service_id}/env-vars", params: list_parameters(...)
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def resume(service_id)
|
43
|
+
endpoint.post("/services/#{service_id}/resume")
|
44
|
+
end
|
45
|
+
|
46
|
+
def restart(service_id)
|
47
|
+
endpoint.post("/services/#{service_id}/restart")
|
48
|
+
end
|
49
|
+
|
50
|
+
def scale(service_id, num_instances:)
|
51
|
+
endpoint.post(
|
52
|
+
"/services/#{service_id}/scale",
|
53
|
+
body: { num_instances: num_instances }
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
def suspend(service_id)
|
58
|
+
endpoint.post("/services/#{service_id}/suspend")
|
59
|
+
end
|
60
|
+
|
61
|
+
def update(service_id, **payload)
|
62
|
+
endpoint.patch("/services/#{service_id}", body: payload)
|
63
|
+
end
|
64
|
+
|
65
|
+
def update_variables(service_id, payloads)
|
66
|
+
endpoint.put("/services/#{service_id}/env-vars", body: payloads)
|
67
|
+
end
|
11
68
|
end
|
12
69
|
end
|
13
70
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "camelise"
|
4
|
+
|
5
|
+
module RenderAPI
|
6
|
+
class DataObject
|
7
|
+
TIME_PATTERN = /\A\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d+Z\z/.freeze
|
8
|
+
|
9
|
+
attr_reader :cursor
|
10
|
+
|
11
|
+
def initialize(data)
|
12
|
+
if data["cursor"]
|
13
|
+
@cursor = data.delete("cursor")
|
14
|
+
@data = data.values.first
|
15
|
+
else
|
16
|
+
@data = data
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_h
|
21
|
+
data
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :data
|
27
|
+
|
28
|
+
def method_missing(name, *args, **kwargs, &block)
|
29
|
+
return super unless respond_to_missing?(name, false)
|
30
|
+
raise ArgumentError if args.any? || kwargs.any? || block
|
31
|
+
|
32
|
+
translate(data[Camelise.call(name.to_s)])
|
33
|
+
end
|
34
|
+
|
35
|
+
def respond_to_missing?(name, _include_all)
|
36
|
+
data.key?(Camelise.call(name.to_s))
|
37
|
+
end
|
38
|
+
|
39
|
+
def translate(object)
|
40
|
+
case object
|
41
|
+
when Hash
|
42
|
+
self.class.new(object)
|
43
|
+
when Array
|
44
|
+
object.collect { |item| translate(item) }
|
45
|
+
when String
|
46
|
+
object[TIME_PATTERN] ? Time.parse(object) : object
|
47
|
+
else
|
48
|
+
object
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/render_api/endpoint.rb
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
require "http"
|
4
4
|
|
5
|
-
require_relative "
|
5
|
+
require_relative "camelise"
|
6
|
+
require_relative "response"
|
6
7
|
|
7
8
|
module RenderAPI
|
8
9
|
class Endpoint
|
@@ -17,22 +18,60 @@ module RenderAPI
|
|
17
18
|
request(:get, path, params: params)
|
18
19
|
end
|
19
20
|
|
21
|
+
def patch(path, body: nil)
|
22
|
+
request(:patch, path, body: camelise(body))
|
23
|
+
end
|
24
|
+
|
20
25
|
def post(path, body: nil)
|
21
|
-
request(:post, path, body: body)
|
26
|
+
request(:post, path, body: camelise(body))
|
27
|
+
end
|
28
|
+
|
29
|
+
def put(path, body: nil)
|
30
|
+
request(:put, path, body: camelise(body))
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete(path)
|
34
|
+
request(:delete, path)
|
22
35
|
end
|
23
36
|
|
24
37
|
private
|
25
38
|
|
26
39
|
attr_reader :api_key
|
27
40
|
|
41
|
+
def camelise(object)
|
42
|
+
case object
|
43
|
+
when Hash
|
44
|
+
object
|
45
|
+
.transform_keys { |key| Camelise.call(key.to_s) }
|
46
|
+
.transform_values { |value| camelise(value) }
|
47
|
+
when Array
|
48
|
+
object.collect { |item| camelise(item) }
|
49
|
+
else
|
50
|
+
object
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def handle_error(response)
|
55
|
+
raise RequestError, response.body.to_s
|
56
|
+
end
|
57
|
+
|
28
58
|
def http
|
29
59
|
HTTP
|
30
60
|
.auth("Bearer #{api_key}")
|
31
61
|
.headers("Accept" => "application/json")
|
62
|
+
.headers("Content-Type" => "application/json")
|
32
63
|
end
|
33
64
|
|
34
65
|
def request(verb, path, body: nil, params: nil)
|
35
|
-
|
66
|
+
response = http.request(verb, url_for(path), json: body, params: params)
|
67
|
+
handle_error(response) unless response.status.success?
|
68
|
+
|
69
|
+
case response.status.code
|
70
|
+
when 202, 204
|
71
|
+
true
|
72
|
+
else
|
73
|
+
Response.new(response)
|
74
|
+
end
|
36
75
|
end
|
37
76
|
|
38
77
|
def url_for(path)
|
data/lib/render_api/response.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "data_object"
|
4
|
+
|
3
5
|
module RenderAPI
|
4
6
|
class Response
|
7
|
+
include Enumerable
|
8
|
+
|
5
9
|
def initialize(http_response)
|
6
10
|
@http_response = http_response
|
7
11
|
end
|
@@ -10,10 +14,18 @@ module RenderAPI
|
|
10
14
|
@data ||= http_response.parse(:json)
|
11
15
|
end
|
12
16
|
|
17
|
+
def each(&block)
|
18
|
+
data_objects.each(&block)
|
19
|
+
end
|
20
|
+
|
13
21
|
def headers
|
14
22
|
@headers ||= http_response.headers.to_h
|
15
23
|
end
|
16
24
|
|
25
|
+
def length
|
26
|
+
data_objects.length
|
27
|
+
end
|
28
|
+
|
17
29
|
def rate_limit
|
18
30
|
headers["Ratelimit-Limit"].to_i
|
19
31
|
end
|
@@ -29,5 +41,31 @@ module RenderAPI
|
|
29
41
|
private
|
30
42
|
|
31
43
|
attr_reader :http_response
|
44
|
+
|
45
|
+
def data_object(hash)
|
46
|
+
DataObject.new(hash)
|
47
|
+
end
|
48
|
+
|
49
|
+
def data_objects
|
50
|
+
@data_objects ||=
|
51
|
+
case data
|
52
|
+
when Array
|
53
|
+
data.collect { |hash| data_object(hash) }
|
54
|
+
else
|
55
|
+
[data_object(data)]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def method_missing(name, *args, **kwargs, &block)
|
60
|
+
return super unless respond_to_missing?(name, false)
|
61
|
+
|
62
|
+
data_objects.first.public_send(name, *args, **kwargs, &block)
|
63
|
+
end
|
64
|
+
|
65
|
+
def respond_to_missing?(name, include_all)
|
66
|
+
return false if data.is_a?(Array)
|
67
|
+
|
68
|
+
data_objects.first.respond_to?(name, include_all)
|
69
|
+
end
|
32
70
|
end
|
33
71
|
end
|
data/lib/render_api.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "
|
3
|
+
require_relative "render_api/client"
|
4
4
|
|
5
5
|
module RenderAPI
|
6
6
|
Error = Class.new(StandardError)
|
7
|
+
RequestError = Class.new(Error)
|
7
8
|
|
8
9
|
def self.client(api_key)
|
9
10
|
RenderAPI::Client.new(api_key)
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: render_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Allan
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: http
|
@@ -24,86 +23,27 @@ dependencies:
|
|
24
23
|
- - ">="
|
25
24
|
- !ruby/object:Gem::Version
|
26
25
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rake
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :development
|
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: rspec
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
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: rubocop
|
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:
|
84
26
|
email:
|
85
27
|
- pat@freelancing-gods.com
|
86
28
|
executables: []
|
87
29
|
extensions: []
|
88
30
|
extra_rdoc_files: []
|
89
31
|
files:
|
90
|
-
- ".rspec"
|
91
32
|
- CHANGELOG.md
|
92
|
-
- Gemfile
|
93
33
|
- LICENSE.txt
|
94
34
|
- README.md
|
95
|
-
- Rakefile
|
96
35
|
- lib/render_api.rb
|
36
|
+
- lib/render_api/camelise.rb
|
97
37
|
- lib/render_api/client.rb
|
98
38
|
- lib/render_api/clients/base.rb
|
99
39
|
- lib/render_api/clients/deploys.rb
|
40
|
+
- lib/render_api/clients/domains.rb
|
41
|
+
- lib/render_api/clients/jobs.rb
|
42
|
+
- lib/render_api/clients/owners.rb
|
100
43
|
- lib/render_api/clients/services.rb
|
44
|
+
- lib/render_api/data_object.rb
|
101
45
|
- lib/render_api/endpoint.rb
|
102
46
|
- lib/render_api/response.rb
|
103
|
-
- spec/features/deploys_spec.rb
|
104
|
-
- spec/features/services_spec.rb
|
105
|
-
- spec/spec_helper.rb
|
106
|
-
- spec/support/webmock.rb
|
107
47
|
homepage: https://github.com/pat/render_api
|
108
48
|
licenses:
|
109
49
|
- MIT
|
@@ -112,7 +52,6 @@ metadata:
|
|
112
52
|
source_code_uri: https://github.com/pat/render_api
|
113
53
|
changelog_uri: https://github.com/pat/render_api/blob/main/CHANGELOG.md
|
114
54
|
rubygems_mfa_required: 'true'
|
115
|
-
post_install_message:
|
116
55
|
rdoc_options: []
|
117
56
|
require_paths:
|
118
57
|
- lib
|
@@ -127,15 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
127
66
|
- !ruby/object:Gem::Version
|
128
67
|
version: '0'
|
129
68
|
requirements: []
|
130
|
-
rubygems_version: 3.
|
131
|
-
signing_key:
|
69
|
+
rubygems_version: 3.6.9
|
132
70
|
specification_version: 4
|
133
71
|
summary: Ruby interface for the render.com API.
|
134
|
-
test_files:
|
135
|
-
- spec/features/deploys_spec.rb
|
136
|
-
- spec/features/services_spec.rb
|
137
|
-
- spec/spec_helper.rb
|
138
|
-
- spec/support/webmock.rb
|
139
|
-
- ".rspec"
|
140
|
-
- Gemfile
|
141
|
-
- Rakefile
|
72
|
+
test_files: []
|
data/.rspec
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe "Deploys" do
|
4
|
-
let(:client) { RenderAPI.client "test-api-key" }
|
5
|
-
let(:service_id) { "random-string" }
|
6
|
-
|
7
|
-
subject { client.deploys }
|
8
|
-
|
9
|
-
describe "create" do
|
10
|
-
before :each do
|
11
|
-
stub_request(
|
12
|
-
:post, "https://api.render.com/v1/services/#{service_id}/deploys"
|
13
|
-
).to_return_json(
|
14
|
-
body: {
|
15
|
-
"id" => "new-deploy",
|
16
|
-
"commit" => {
|
17
|
-
"id" => "string",
|
18
|
-
"message" => "string",
|
19
|
-
"createdAt" => "2021-12-12T08:34:38.327Z"
|
20
|
-
},
|
21
|
-
"status" => "created",
|
22
|
-
"finishedAt" => "2021-12-12T08:34:38.327Z",
|
23
|
-
"createdAt" => "2021-12-12T08:34:38.327Z",
|
24
|
-
"updatedAt" => "2021-12-12T08:34:38.327Z"
|
25
|
-
}
|
26
|
-
)
|
27
|
-
end
|
28
|
-
|
29
|
-
it "returns the new deploy details" do
|
30
|
-
response = subject.create(service_id)
|
31
|
-
|
32
|
-
expect(response.data["id"]).to eq("new-deploy")
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe "list" do
|
37
|
-
before :each do
|
38
|
-
stub_request(
|
39
|
-
:get, "https://api.render.com/v1/services/#{service_id}/deploys"
|
40
|
-
).to_return_json(
|
41
|
-
body: [
|
42
|
-
{
|
43
|
-
"deploy" => {
|
44
|
-
"id" => "my-deploy",
|
45
|
-
"commit" => {
|
46
|
-
"id" => "string",
|
47
|
-
"message" => "string",
|
48
|
-
"createdAt" => "2021-12-12T08:31:33.669Z"
|
49
|
-
},
|
50
|
-
"status" => "created",
|
51
|
-
"finishedAt" => "2021-12-12T08:31:33.670Z",
|
52
|
-
"createdAt" => "2021-12-12T08:31:33.670Z",
|
53
|
-
"updatedAt" => "2021-12-12T08:31:33.670Z"
|
54
|
-
},
|
55
|
-
"cursor" => "string"
|
56
|
-
}
|
57
|
-
]
|
58
|
-
)
|
59
|
-
end
|
60
|
-
|
61
|
-
it "returns deploy data" do
|
62
|
-
response = subject.list(service_id)
|
63
|
-
|
64
|
-
expect(response.data.length).to eq(1)
|
65
|
-
expect(response.data.first["deploy"]["id"]).to eq("my-deploy")
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe "Services" do
|
4
|
-
let(:client) { RenderAPI.client "test-api-key" }
|
5
|
-
|
6
|
-
subject { client.services }
|
7
|
-
|
8
|
-
describe "list" do
|
9
|
-
before :each do
|
10
|
-
stub_request(
|
11
|
-
:get, "https://api.render.com/v1/services"
|
12
|
-
).to_return_json(
|
13
|
-
body: [
|
14
|
-
{
|
15
|
-
"service" => {
|
16
|
-
"id" => "string",
|
17
|
-
"autoDeploy" => "yes",
|
18
|
-
"branch" => "string",
|
19
|
-
"createdAt" => "2021-12-12T08:02:47.138Z",
|
20
|
-
"name" => "my-service",
|
21
|
-
"notifyOnFail" => "default",
|
22
|
-
"ownerId" => "string",
|
23
|
-
"repo" => "string",
|
24
|
-
"slug" => "string",
|
25
|
-
"suspended" => "suspended",
|
26
|
-
"suspenders" => [
|
27
|
-
"admin"
|
28
|
-
],
|
29
|
-
"type" => "static_site",
|
30
|
-
"updatedAt" => "2021-12-12T08:02:47.138Z",
|
31
|
-
"serviceDetails" => {
|
32
|
-
"buildCommand" => "string",
|
33
|
-
"parentServer" => {
|
34
|
-
"id" => "string",
|
35
|
-
"name" => "string"
|
36
|
-
},
|
37
|
-
"publishPath" => "string",
|
38
|
-
"pullRequestPreviewsEnabled" => "yes",
|
39
|
-
"url" => "string"
|
40
|
-
}
|
41
|
-
},
|
42
|
-
"cursor" => "string"
|
43
|
-
}
|
44
|
-
]
|
45
|
-
)
|
46
|
-
end
|
47
|
-
|
48
|
-
it "returns service data" do
|
49
|
-
response = subject.list
|
50
|
-
|
51
|
-
expect(response.data.length).to eq(1)
|
52
|
-
expect(response.data.first["service"]["name"]).to eq("my-service")
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
data/spec/spec_helper.rb
DELETED
data/spec/support/webmock.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "delegate"
|
4
|
-
require "webmock/rspec"
|
5
|
-
|
6
|
-
module WebmockJSONHelpers
|
7
|
-
def stub_request(method, uri)
|
8
|
-
RequestStub.new(super)
|
9
|
-
end
|
10
|
-
|
11
|
-
def a_request(method, uri)
|
12
|
-
RequestPattern.new(super)
|
13
|
-
end
|
14
|
-
|
15
|
-
class RequestStub < SimpleDelegator
|
16
|
-
def to_return_json(*response_hashes, &block)
|
17
|
-
typed_hashes = response_hashes.map do |hash|
|
18
|
-
typed = hash.dup
|
19
|
-
|
20
|
-
typed[:headers] ||= {}
|
21
|
-
typed[:headers]["Content-Type"] = "application/json"
|
22
|
-
|
23
|
-
typed[:body] = JSON.dump(hash[:body] || {})
|
24
|
-
|
25
|
-
typed
|
26
|
-
end
|
27
|
-
|
28
|
-
to_return(*typed_hashes, &block)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class RequestPattern < SimpleDelegator
|
33
|
-
def with_json_body
|
34
|
-
with do |request|
|
35
|
-
yield JSON.parse(request.body)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
RSpec.configure do |config|
|
42
|
-
config.include WebmockJSONHelpers
|
43
|
-
end
|