brasa 0.4.2 → 0.5.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/lib/brasa/commands/deploy.rb +43 -21
- data/lib/brasa/commands/up.rb +76 -42
- data/lib/brasa/version.rb +1 -1
- data/lib/brasa/websocket/cable_client.rb +123 -0
- metadata +16 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3618063ca02e720d10a6a270976219d508a078ff13917d3de2fc9f81d9ab8e73
|
|
4
|
+
data.tar.gz: 781b40094dfc2baef08fc091d266cb79acd984dfabed6d3f54b9f68e2616c6c7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: edbd4b233d795fd78006f054791743985f6a1513c90d37951313739d92a3e1c945cdf5254d7981941400575a23d26e891cb0c991554216419710001912214b22
|
|
7
|
+
data.tar.gz: c7db4110649d9378c0eb9d5351a15da213a716ca0037612c56632d00ea3cca2bb10e5188d43f1a709bb8dcec35cd2ff874d89f1b5bc0129e2371a08069a0cef0
|
|
@@ -5,7 +5,8 @@ module Brasa
|
|
|
5
5
|
module Commands
|
|
6
6
|
class Deploy < Base
|
|
7
7
|
POLL_INTERVAL = 5
|
|
8
|
-
|
|
8
|
+
DEPLOY_TIMEOUT = 1800
|
|
9
|
+
DEPLOY_MAX_POLLS = 360
|
|
9
10
|
|
|
10
11
|
def execute(options = {})
|
|
11
12
|
require_auth!
|
|
@@ -13,18 +14,16 @@ module Brasa
|
|
|
13
14
|
|
|
14
15
|
info("Empacotando código...")
|
|
15
16
|
archive_path = SourcePacker.pack
|
|
16
|
-
|
|
17
17
|
size_kb = File.size(archive_path) / 1024
|
|
18
18
|
info("Enviando #{size_kb}KB para o servidor...")
|
|
19
19
|
|
|
20
|
-
deploy = api.upload(
|
|
21
|
-
"/api/v1/apps/#{slug}/deploys",
|
|
20
|
+
deploy = api.upload("/api/v1/apps/#{slug}/deploys",
|
|
22
21
|
file_path: archive_path,
|
|
23
|
-
params: { branch: options["branch"] || project_config[:branch] || "main" }
|
|
24
|
-
)
|
|
25
|
-
info("
|
|
22
|
+
params: { branch: options["branch"] || project_config[:branch] || "main" })
|
|
23
|
+
info("Deploy ##{deploy["id"]} criado.")
|
|
24
|
+
info(" Na fila...")
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
wait_for_deploy_complete(slug, deploy["id"])
|
|
28
27
|
rescue Api::Client::ApiError => e
|
|
29
28
|
error("Erro: #{e.message}")
|
|
30
29
|
ensure
|
|
@@ -33,24 +32,51 @@ module Brasa
|
|
|
33
32
|
|
|
34
33
|
private
|
|
35
34
|
|
|
36
|
-
def
|
|
35
|
+
def wait_for_deploy_complete(slug, deploy_id)
|
|
36
|
+
ws = connect_websocket
|
|
37
|
+
started = Time.now
|
|
38
|
+
|
|
39
|
+
ws.on_log { |msg| print msg["line"] + "\n" if msg["line"] }
|
|
40
|
+
ws.subscribe("DeployLogChannel", deploy_id: deploy_id)
|
|
41
|
+
|
|
42
|
+
status = ws.wait_for("DeployStatusChannel",
|
|
43
|
+
params: { deploy_id: deploy_id },
|
|
44
|
+
until_status: %w[live failed],
|
|
45
|
+
timeout: DEPLOY_TIMEOUT)
|
|
46
|
+
|
|
47
|
+
elapsed = (Time.now - started).to_i
|
|
48
|
+
if status == "live"
|
|
49
|
+
success("\nDeploy concluído com sucesso! (#{elapsed}s)")
|
|
50
|
+
else
|
|
51
|
+
error("\nDeploy falhou.")
|
|
52
|
+
end
|
|
53
|
+
rescue Websocket::CableClient::ConnectionError => e
|
|
54
|
+
$stderr.puts "\n [WebSocket indisponível: #{e.message}. Usando polling...]"
|
|
55
|
+
wait_for_deploy_polling(slug, deploy_id)
|
|
56
|
+
ensure
|
|
57
|
+
ws&.disconnect
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def connect_websocket
|
|
61
|
+
require "brasa/websocket/cable_client"
|
|
62
|
+
Websocket::CableClient.new.tap(&:connect!)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def wait_for_deploy_polling(slug, deploy_id)
|
|
37
66
|
started = Time.now
|
|
38
67
|
last_status = nil
|
|
39
68
|
DEPLOY_MAX_POLLS.times do |i|
|
|
40
69
|
deploy = api.get("/api/v1/apps/#{slug}/deploys/#{deploy_id}")
|
|
41
|
-
|
|
42
70
|
case deploy["status"]
|
|
43
71
|
when "live"
|
|
44
|
-
|
|
45
|
-
success("\nDeploy concluído com sucesso! (#{elapsed}s)")
|
|
72
|
+
success("\nDeploy concluído com sucesso! (#{(Time.now - started).to_i}s)")
|
|
46
73
|
return
|
|
47
74
|
when "failed"
|
|
48
75
|
error("\nDeploy falhou.")
|
|
49
76
|
return
|
|
50
77
|
end
|
|
51
|
-
|
|
52
78
|
if deploy["status"] != last_status
|
|
53
|
-
print "\n #{status_label(deploy["status"])}"
|
|
79
|
+
print "\n #{status_label(deploy["status"])}"
|
|
54
80
|
last_status = deploy["status"]
|
|
55
81
|
end
|
|
56
82
|
print "."
|
|
@@ -60,21 +86,17 @@ module Brasa
|
|
|
60
86
|
print "!"
|
|
61
87
|
sleep(POLL_INTERVAL)
|
|
62
88
|
end
|
|
63
|
-
|
|
64
|
-
error("\nTimeout aguardando deploy (#{elapsed}s). O processo pode ainda estar rodando — verifique com: brasa status")
|
|
89
|
+
error("\nTimeout (#{(Time.now - started).to_i}s). Verifique com: brasa status")
|
|
65
90
|
end
|
|
66
91
|
|
|
67
92
|
def status_label(status)
|
|
68
|
-
{ "queued" => "Na fila...",
|
|
69
|
-
"building" => "Construindo imagem...",
|
|
93
|
+
{ "queued" => "Na fila...", "building" => "Construindo imagem...",
|
|
70
94
|
"deploying" => "Deployando..." }[status] || status
|
|
71
95
|
end
|
|
72
96
|
|
|
73
97
|
def show_elapsed(started)
|
|
74
98
|
elapsed = (Time.now - started).to_i
|
|
75
|
-
|
|
76
|
-
sec = elapsed % 60
|
|
77
|
-
print " (#{min}m#{sec}s)"
|
|
99
|
+
print " (#{elapsed / 60}m#{elapsed % 60}s)"
|
|
78
100
|
end
|
|
79
101
|
end
|
|
80
102
|
end
|
data/lib/brasa/commands/up.rb
CHANGED
|
@@ -5,8 +5,10 @@ module Brasa
|
|
|
5
5
|
module Commands
|
|
6
6
|
class Up < Base
|
|
7
7
|
POLL_INTERVAL = 5
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
PROVISION_TIMEOUT = 1200
|
|
9
|
+
DEPLOY_TIMEOUT = 1800
|
|
10
|
+
PROVISION_MAX_POLLS = 240
|
|
11
|
+
DEPLOY_MAX_POLLS = 360
|
|
10
12
|
|
|
11
13
|
def execute(options = {})
|
|
12
14
|
require_auth!
|
|
@@ -19,7 +21,8 @@ module Brasa
|
|
|
19
21
|
info("Iniciando deploy...")
|
|
20
22
|
else
|
|
21
23
|
info("Provisionando infraestrutura...")
|
|
22
|
-
|
|
24
|
+
trigger_provision(slug) if %w[pending error].include?(@app["status"])
|
|
25
|
+
unless wait_for_provisioning(@app["id"], slug)
|
|
23
26
|
return
|
|
24
27
|
end
|
|
25
28
|
success("Infraestrutura provisionada!")
|
|
@@ -27,8 +30,9 @@ module Brasa
|
|
|
27
30
|
end
|
|
28
31
|
|
|
29
32
|
deploy = trigger_deploy(slug)
|
|
33
|
+
info(" Na fila...")
|
|
30
34
|
|
|
31
|
-
if
|
|
35
|
+
if wait_for_deploy_complete(slug, deploy["id"])
|
|
32
36
|
subdomain = @app["subdomain"] || slug
|
|
33
37
|
success("Deploy concluído! App disponível em https://#{subdomain}.usebrasa.com.br")
|
|
34
38
|
end
|
|
@@ -50,23 +54,22 @@ module Brasa
|
|
|
50
54
|
create_app(config)
|
|
51
55
|
end
|
|
52
56
|
|
|
57
|
+
def trigger_provision(slug)
|
|
58
|
+
api.post("/api/v1/apps/#{slug}/provision")
|
|
59
|
+
rescue Api::Client::ApiError
|
|
60
|
+
end
|
|
61
|
+
|
|
53
62
|
def ensure_repo_url(slug)
|
|
54
63
|
repo = detect_git_remote
|
|
55
64
|
return unless repo
|
|
56
|
-
|
|
57
65
|
api.patch("/api/v1/apps/#{slug}", body: { app: { repo_url: repo } })
|
|
58
66
|
rescue Api::Client::ApiError
|
|
59
|
-
# Não bloquear o fluxo se falhar ao atualizar repo
|
|
60
67
|
end
|
|
61
68
|
|
|
62
69
|
def create_app(config)
|
|
63
70
|
app_params = {
|
|
64
|
-
name: config[:app],
|
|
65
|
-
|
|
66
|
-
preset: config[:preset],
|
|
67
|
-
region: config[:region],
|
|
68
|
-
repo_url: detect_git_remote,
|
|
69
|
-
repo_branch: config[:branch]
|
|
71
|
+
name: config[:app], stack: config[:stack], preset: config[:preset],
|
|
72
|
+
region: config[:region], repo_url: detect_git_remote, repo_branch: config[:branch]
|
|
70
73
|
}
|
|
71
74
|
app_params[:database_engine] = config[:database_engine] if config[:database_engine]
|
|
72
75
|
api.post("/api/v1/apps", body: { app: app_params })
|
|
@@ -77,13 +80,8 @@ module Brasa
|
|
|
77
80
|
archive_path = SourcePacker.pack
|
|
78
81
|
size_kb = File.size(archive_path) / 1024
|
|
79
82
|
info("Enviando #{size_kb}KB para o servidor...")
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
"/api/v1/apps/#{slug}/deploys",
|
|
83
|
-
file_path: archive_path,
|
|
84
|
-
params: { branch: project_config[:branch] || "main" }
|
|
85
|
-
)
|
|
86
|
-
deploy
|
|
83
|
+
api.upload("/api/v1/apps/#{slug}/deploys", file_path: archive_path,
|
|
84
|
+
params: { branch: project_config[:branch] || "main" })
|
|
87
85
|
ensure
|
|
88
86
|
FileUtils.rm_f(archive_path) if archive_path
|
|
89
87
|
end
|
|
@@ -93,18 +91,63 @@ module Brasa
|
|
|
93
91
|
remote.empty? ? nil : remote
|
|
94
92
|
end
|
|
95
93
|
|
|
96
|
-
|
|
94
|
+
# ── WebSocket methods ──
|
|
95
|
+
|
|
96
|
+
def wait_for_provisioning(app_id, slug)
|
|
97
|
+
ws = connect_websocket
|
|
98
|
+
status = ws.wait_for("ProvisionStatusChannel",
|
|
99
|
+
params: { app_id: app_id },
|
|
100
|
+
until_status: %w[active error],
|
|
101
|
+
timeout: PROVISION_TIMEOUT)
|
|
102
|
+
|
|
103
|
+
status == "active" ? true : (error("\nErro no provisionamento."); false)
|
|
104
|
+
rescue Websocket::CableClient::ConnectionError => e
|
|
105
|
+
warn_fallback(e)
|
|
106
|
+
wait_for_provisioning_polling(slug)
|
|
107
|
+
ensure
|
|
108
|
+
ws&.disconnect
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def wait_for_deploy_complete(slug, deploy_id)
|
|
112
|
+
ws = connect_websocket
|
|
113
|
+
started = Time.now
|
|
114
|
+
|
|
115
|
+
ws.on_log { |msg| print msg["line"] + "\n" if msg["line"] }
|
|
116
|
+
ws.subscribe("DeployLogChannel", deploy_id: deploy_id)
|
|
117
|
+
|
|
118
|
+
status = ws.wait_for("DeployStatusChannel",
|
|
119
|
+
params: { deploy_id: deploy_id },
|
|
120
|
+
until_status: %w[live failed],
|
|
121
|
+
timeout: DEPLOY_TIMEOUT)
|
|
122
|
+
|
|
123
|
+
status == "live" ? true : (error("\nDeploy falhou."); false)
|
|
124
|
+
rescue Websocket::CableClient::ConnectionError => e
|
|
125
|
+
warn_fallback(e)
|
|
126
|
+
wait_for_deploy_polling(slug, deploy_id)
|
|
127
|
+
ensure
|
|
128
|
+
ws&.disconnect
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def connect_websocket
|
|
132
|
+
require "brasa/websocket/cable_client"
|
|
133
|
+
Websocket::CableClient.new.tap(&:connect!)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def warn_fallback(err)
|
|
137
|
+
$stderr.puts "\n [WebSocket indisponível: #{err.message}. Usando polling...]"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# ── Fallback polling ──
|
|
141
|
+
|
|
142
|
+
def wait_for_provisioning_polling(slug)
|
|
97
143
|
started = Time.now
|
|
98
144
|
last_status = nil
|
|
99
145
|
PROVISION_MAX_POLLS.times do |i|
|
|
100
146
|
app = api.get("/api/v1/apps/#{slug}")
|
|
101
147
|
return true if app["status"] == "active"
|
|
102
|
-
if app["status"] == "error"
|
|
103
|
-
error("\nErro no provisionamento.")
|
|
104
|
-
return false
|
|
105
|
-
end
|
|
148
|
+
return (error("\nErro no provisionamento."); false) if app["status"] == "error"
|
|
106
149
|
if app["status"] != last_status
|
|
107
|
-
print "\n #{status_label(app["status"])}"
|
|
150
|
+
print "\n #{status_label(app["status"])}"
|
|
108
151
|
last_status = app["status"]
|
|
109
152
|
end
|
|
110
153
|
print "."
|
|
@@ -114,23 +157,19 @@ module Brasa
|
|
|
114
157
|
print "!"
|
|
115
158
|
sleep(POLL_INTERVAL)
|
|
116
159
|
end
|
|
117
|
-
|
|
118
|
-
error("\nTimeout aguardando provisionamento (#{elapsed}s). O processo pode ainda estar rodando no servidor — verifique com: brasa status")
|
|
160
|
+
error("\nTimeout (#{(Time.now - started).to_i}s). Verifique com: brasa status")
|
|
119
161
|
false
|
|
120
162
|
end
|
|
121
163
|
|
|
122
|
-
def
|
|
164
|
+
def wait_for_deploy_polling(slug, deploy_id)
|
|
123
165
|
started = Time.now
|
|
124
166
|
last_status = nil
|
|
125
167
|
DEPLOY_MAX_POLLS.times do |i|
|
|
126
168
|
deploy = api.get("/api/v1/apps/#{slug}/deploys/#{deploy_id}")
|
|
127
169
|
return true if deploy["status"] == "live"
|
|
128
|
-
if deploy["status"] == "failed"
|
|
129
|
-
error("\nDeploy falhou.")
|
|
130
|
-
return false
|
|
131
|
-
end
|
|
170
|
+
return (error("\nDeploy falhou."); false) if deploy["status"] == "failed"
|
|
132
171
|
if deploy["status"] != last_status
|
|
133
|
-
print "\n #{status_label(deploy["status"])}"
|
|
172
|
+
print "\n #{status_label(deploy["status"])}"
|
|
134
173
|
last_status = deploy["status"]
|
|
135
174
|
end
|
|
136
175
|
print "."
|
|
@@ -140,24 +179,19 @@ module Brasa
|
|
|
140
179
|
print "!"
|
|
141
180
|
sleep(POLL_INTERVAL)
|
|
142
181
|
end
|
|
143
|
-
|
|
144
|
-
error("\nTimeout aguardando deploy (#{elapsed}s). O processo pode ainda estar rodando no servidor — verifique com: brasa status")
|
|
182
|
+
error("\nTimeout (#{(Time.now - started).to_i}s). Verifique com: brasa status")
|
|
145
183
|
false
|
|
146
184
|
end
|
|
147
185
|
|
|
148
186
|
def status_label(status)
|
|
149
|
-
{ "pending" => "Aguardando...",
|
|
150
|
-
"
|
|
151
|
-
"queued" => "Na fila...",
|
|
152
|
-
"building" => "Construindo imagem...",
|
|
187
|
+
{ "pending" => "Aguardando...", "provisioning" => "Provisionando VM...",
|
|
188
|
+
"queued" => "Na fila...", "building" => "Construindo imagem...",
|
|
153
189
|
"deploying" => "Deployando..." }[status] || status
|
|
154
190
|
end
|
|
155
191
|
|
|
156
192
|
def show_elapsed(started)
|
|
157
193
|
elapsed = (Time.now - started).to_i
|
|
158
|
-
|
|
159
|
-
sec = elapsed % 60
|
|
160
|
-
print " (#{min}m#{sec}s)"
|
|
194
|
+
print " (#{elapsed / 60}m#{elapsed % 60}s)"
|
|
161
195
|
end
|
|
162
196
|
end
|
|
163
197
|
end
|
data/lib/brasa/version.rb
CHANGED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
require "websocket-client-simple"
|
|
2
|
+
require "json"
|
|
3
|
+
|
|
4
|
+
module Brasa
|
|
5
|
+
module Websocket
|
|
6
|
+
class CableClient
|
|
7
|
+
class ConnectionError < StandardError; end
|
|
8
|
+
|
|
9
|
+
RECONNECT_DELAYS = [1, 3, 10].freeze
|
|
10
|
+
|
|
11
|
+
def initialize(api_url: nil, token: nil)
|
|
12
|
+
@api_url = api_url || Brasa::Config.api_url
|
|
13
|
+
@token = token || Brasa::Config.token
|
|
14
|
+
@subscriptions = {}
|
|
15
|
+
@connected = false
|
|
16
|
+
@log_callback = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def connect!
|
|
20
|
+
raise ConnectionError, "No token. Run `brasa login`." unless @token
|
|
21
|
+
|
|
22
|
+
ws_url = @api_url.sub(%r{^https?://}, "wss://").chomp("/") + "/cable"
|
|
23
|
+
@ws = WebSocket::Client::Simple.connect(ws_url, headers: {
|
|
24
|
+
"Authorization" => "Bearer #{@token}",
|
|
25
|
+
"Origin" => @api_url
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
setup_handlers
|
|
29
|
+
wait_for_welcome
|
|
30
|
+
self
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def subscribe(channel, params = {}, &callback)
|
|
34
|
+
identifier = { channel: channel }.merge(params).to_json
|
|
35
|
+
@subscriptions[identifier] = callback
|
|
36
|
+
send_command("subscribe", identifier)
|
|
37
|
+
identifier
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def wait_for(channel, params: {}, until_status: [], timeout: 1800)
|
|
41
|
+
result = nil
|
|
42
|
+
identifier = subscribe(channel, params) do |msg|
|
|
43
|
+
status = msg["status"]
|
|
44
|
+
result = status if until_status.include?(status)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
deadline = Time.now + timeout
|
|
48
|
+
loop do
|
|
49
|
+
return result if result
|
|
50
|
+
raise ConnectionError, "Timeout (#{timeout}s)" if Time.now > deadline
|
|
51
|
+
raise ConnectionError, "Connection lost" unless @connected
|
|
52
|
+
sleep 0.2
|
|
53
|
+
end
|
|
54
|
+
ensure
|
|
55
|
+
send_command("unsubscribe", identifier) if identifier && @connected
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def on_log(&block)
|
|
59
|
+
@log_callback = block
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def disconnect
|
|
63
|
+
@ws&.close
|
|
64
|
+
@connected = false
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def setup_handlers
|
|
70
|
+
client = self
|
|
71
|
+
|
|
72
|
+
@ws.on :message do |msg|
|
|
73
|
+
data = JSON.parse(msg.data) rescue next
|
|
74
|
+
client.send(:handle_message, data)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
@ws.on :close do |_|
|
|
78
|
+
client.instance_variable_set(:@connected, false)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
@ws.on :error do |_|
|
|
82
|
+
client.instance_variable_set(:@connected, false)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def handle_message(data)
|
|
87
|
+
case data["type"]
|
|
88
|
+
when "welcome"
|
|
89
|
+
@connected = true
|
|
90
|
+
when "ping"
|
|
91
|
+
# keepalive — noop
|
|
92
|
+
when "confirm_subscription"
|
|
93
|
+
# confirmed
|
|
94
|
+
when "reject_subscription"
|
|
95
|
+
raise ConnectionError, "Subscription rejected"
|
|
96
|
+
else
|
|
97
|
+
identifier = data["identifier"]
|
|
98
|
+
message = data["message"]
|
|
99
|
+
return unless message
|
|
100
|
+
|
|
101
|
+
callback = @subscriptions[identifier]
|
|
102
|
+
callback&.call(message)
|
|
103
|
+
|
|
104
|
+
@log_callback&.call(message) if message["line"]
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def wait_for_welcome
|
|
109
|
+
deadline = Time.now + 10
|
|
110
|
+
loop do
|
|
111
|
+
return if @connected
|
|
112
|
+
raise ConnectionError, "WebSocket connection timeout" if Time.now > deadline
|
|
113
|
+
sleep 0.1
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def send_command(command, identifier)
|
|
118
|
+
return unless @ws&.open?
|
|
119
|
+
@ws.send({ command: command, identifier: identifier }.to_json)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: brasa
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brasa
|
|
@@ -107,6 +107,20 @@ dependencies:
|
|
|
107
107
|
- - "~>"
|
|
108
108
|
- !ruby/object:Gem::Version
|
|
109
109
|
version: '0.8'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: websocket-client-simple
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '0.8'
|
|
117
|
+
type: :runtime
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '0.8'
|
|
110
124
|
- !ruby/object:Gem::Dependency
|
|
111
125
|
name: rspec
|
|
112
126
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -168,6 +182,7 @@ files:
|
|
|
168
182
|
- lib/brasa/config.rb
|
|
169
183
|
- lib/brasa/source_packer.rb
|
|
170
184
|
- lib/brasa/version.rb
|
|
185
|
+
- lib/brasa/websocket/cable_client.rb
|
|
171
186
|
homepage: https://usebrasa.com.br
|
|
172
187
|
licenses:
|
|
173
188
|
- MIT
|