jatai 1.2.1 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bf8aed477b1220c2ffd5b71fc309ac1f407a51404b43603f9ce08ad7f29f78c
4
- data.tar.gz: 2514d15c7bcdc3460193c286ff6657b27aae26817524b66121cbc96ccc28a03c
3
+ metadata.gz: 7b9131e1a51d23a7120a320f01c24d31b332e636467c048bbfddea25bd49b643
4
+ data.tar.gz: 5306e6ed76d3076ebe707d08f399d9071d63814fe92cd930239a2143113ba87a
5
5
  SHA512:
6
- metadata.gz: 3d6f9195e30feeb5798276c198ffcddcd8ef429bbd65c4bd9444adf50089c0983ee124afe8a8bd72e342b7199248c46477241deb2083f3d7e9caf4438238a963
7
- data.tar.gz: a6d364146dd82c0321773da507e2eea74b40b637601c27b7cabe45d5cea9b4f61d7a007125b38d25fd346a20a00862733db5945c6af97dfcff1d9a88b41cd09b
6
+ metadata.gz: ed82a595b2b854268d89902e495963b548b6b6a0057d9e846aa01345157fe5c02ea76935901aede74a668be8a8c6ed1c9a7f509702fd27e8f45b37cbf2f382c4
7
+ data.tar.gz: 17fb609ef8532e4da8d49c8bd1cb8ada50fc3052772db9b4b625de6f6516fb830ab8de27264c9166c30eff5080b2adb0d07c827bda32c7184682a0488746e235
data/lib/jatai/cli.rb CHANGED
@@ -13,6 +13,7 @@ require "jatai/commands/status"
13
13
  require "jatai/commands/destroy"
14
14
  require "jatai/commands/domains"
15
15
  require "jatai/commands/redis"
16
+ require "jatai/commands/run"
16
17
 
17
18
  module Jatai
18
19
  class CLI < Thor
@@ -41,6 +42,13 @@ module Jatai
41
42
  Commands::Deploy.new.execute(options)
42
43
  end
43
44
 
45
+ # "run" é palavra reservada do Thor — mapeada p/ run_command.
46
+ desc "run COMANDO", "Executar comando one-off no app (pod efêmero do release atual)"
47
+ map "run" => :run_command
48
+ def run_command(*command_parts)
49
+ Commands::Run.new.execute(command_parts)
50
+ end
51
+
44
52
  desc "logs", "Ver logs da aplicação em tempo real"
45
53
  option :tail, type: :numeric, default: 100, desc: "Número de linhas"
46
54
  def logs
@@ -0,0 +1,79 @@
1
+ require "jatai/commands/base"
2
+
3
+ module Jatai
4
+ module Commands
5
+ # jatai run "<comando>" — executa um comando one-off num pod efêmero com a
6
+ # imagem do release atual, streama a saída e retorna o exit code real.
7
+ class Run < Base
8
+ RUN_TIMEOUT = 960 # activeDeadlineSeconds (900) + folga
9
+
10
+ def execute(command_parts)
11
+ require_auth!
12
+ command = Array(command_parts).join(" ").strip
13
+ return error("Informe o comando: jatai run \"bin/rails runner '...'\"") if command.empty?
14
+
15
+ slug = app_slug
16
+ run = api.post("/api/v1/apps/#{slug}/runs", body: { command: command })
17
+ info("Run ##{run["id"]} criado — subindo pod efêmero com o release atual...")
18
+
19
+ status = follow(run["id"])
20
+ finish(slug, run["id"], status)
21
+ rescue Api::Client::ValidationError => e
22
+ error("Erro: #{e.message}")
23
+ exit(1)
24
+ rescue Api::Client::ApiError => e
25
+ error("Erro: #{e.message}")
26
+ exit(1)
27
+ end
28
+
29
+ private
30
+
31
+ def follow(run_id)
32
+ ws = connect_websocket
33
+ ws.on_log { |msg| puts msg["line"] if msg.is_a?(Hash) && msg["line"] }
34
+ ws.wait_for("AppRunChannel",
35
+ params: { run_id: run_id },
36
+ until_status: %w[succeeded failed error],
37
+ timeout: RUN_TIMEOUT)
38
+ rescue Jatai::Websocket::CableClient::ConnectionError
39
+ info("[WebSocket indisponível — aguardando resultado via API...]")
40
+ poll_until_done(run_id)
41
+ ensure
42
+ ws&.disconnect
43
+ end
44
+
45
+ def poll_until_done(run_id)
46
+ (RUN_TIMEOUT / 5).times do
47
+ run = api.get("/api/v1/apps/#{app_slug}/runs/#{run_id}")
48
+ return run["status"] if %w[succeeded failed error].include?(run["status"])
49
+ sleep(5)
50
+ end
51
+ "error"
52
+ end
53
+
54
+ # O socket entrega o status; o exit code vem da API (fonte de verdade).
55
+ def finish(slug, run_id, status)
56
+ run = api.get("/api/v1/apps/#{slug}/runs/#{run_id}")
57
+ exit_code = run["exit_code"]
58
+
59
+ case status
60
+ when "succeeded"
61
+ success("Concluído (exit 0)")
62
+ exit(0)
63
+ when "failed"
64
+ hint = exit_code == 137 ? " — processo morto (SIGKILL), possivelmente falta de memória (OOM)" : ""
65
+ error("Comando terminou com exit #{exit_code}#{hint}")
66
+ exit(exit_code.to_i.clamp(1, 255))
67
+ else
68
+ error("Run falhou na infraestrutura. Tente novamente ou verifique com: jatai status")
69
+ exit(1)
70
+ end
71
+ end
72
+
73
+ def connect_websocket
74
+ require "jatai/websocket/cable_client"
75
+ Jatai::Websocket::CableClient.new.tap(&:connect!)
76
+ end
77
+ end
78
+ end
79
+ end
data/lib/jatai/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Jatai
2
- VERSION = "1.2.1"
2
+ VERSION = "1.3.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jatai
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jataí Cloud
@@ -176,6 +176,7 @@ files:
176
176
  - lib/jatai/commands/logs_export.rb
177
177
  - lib/jatai/commands/logs_search.rb
178
178
  - lib/jatai/commands/redis.rb
179
+ - lib/jatai/commands/run.rb
179
180
  - lib/jatai/commands/scale.rb
180
181
  - lib/jatai/commands/status.rb
181
182
  - lib/jatai/commands/up.rb