wokku-cli 0.5.2 → 0.6.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 +12 -0
- data/README.md +2 -8
- data/lib/wokku/commands/addons.rb +20 -2
- data/lib/wokku/commands/databases.rb +17 -1
- data/lib/wokku/version.rb +1 -1
- data/lib/wokku.rb +13 -0
- metadata +1 -4
- data/lib/wokku/commands/buildpacks.rb +0 -50
- data/lib/wokku/commands/do.rb +0 -32
- data/lib/wokku/commands/storage.rb +0 -31
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7ca5f8ef74b0d7c4991fde4d09e2fe741bd2925152b20a1337ca34b20f4a54cd
|
|
4
|
+
data.tar.gz: 661e85e21edc58b048532701bc32f5e9ef062d5fc610898d9d18718d051b39b5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 73e67bb05dbbba4f756a0fc69312d8bebd626d826779a5496404363786b45121046a0cc4e669a635d51e527932d19bfb92aa70bdc376b1df7b864fc75a3f404b
|
|
7
|
+
data.tar.gz: b08a864fce04de1fc2435c0aa071d4ce343aee48214b963f4cc3859c67e14fef3a08250631ab343aaee155ab1c5406613f990f2fc30fd5cc79f5cfe0454bd0d9
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0 — 2026-07-30
|
|
4
|
+
|
|
5
|
+
### Removed
|
|
6
|
+
|
|
7
|
+
- Removed `do`, `buildpacks`, `storage`, and log-drain commands — the underlying wokku-cloud endpoints were retired when the platform moved off Dokku (Track B). `wokku logs` is unchanged.
|
|
8
|
+
|
|
9
|
+
## 0.5.3 — 2026-06-26
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- `databases:create` and `addons:shared:enable` no longer report success optimistically. The CLI used to print "Created"/"Enabled" on any 2xx — including a `202 Accepted` ("queued") — so a database or shared engine that was still provisioning, or that failed afterward, looked done. Both commands now poll until the resource is actually `running` (then "Created"/"ready"), `error` (a clear failure + nonzero exit), or a timeout ("still provisioning — check `wokku addons APP` / `databases:info`"). Poll cadence is tunable via `WOKKU_POLL_ATTEMPTS`/`WOKKU_POLL_INTERVAL`.
|
|
14
|
+
|
|
3
15
|
## 0.5.2 — 2026-06-06
|
|
4
16
|
|
|
5
17
|
### Changed
|
data/README.md
CHANGED
|
@@ -28,7 +28,7 @@ wokku logs myapp -f
|
|
|
28
28
|
|
|
29
29
|
## Commands
|
|
30
30
|
|
|
31
|
-
Run `wokku --help` for the full list. ~
|
|
31
|
+
Run `wokku --help` for the full list. ~30 first-class commands today, grouped:
|
|
32
32
|
|
|
33
33
|
- **Apps:** `apps`, `apps:create`, `apps:destroy`, `apps:info`, `apps:transfer`
|
|
34
34
|
- **Process:** `ps`, `ps:start/stop/restart/scale/rebuild`, `redeploy`
|
|
@@ -39,13 +39,7 @@ Run `wokku --help` for the full list. ~39 first-class commands today, grouped:
|
|
|
39
39
|
- **Servers:** `servers`, `servers:info`, `servers:default` (multi-Dokku-host installs)
|
|
40
40
|
- **Teams:** `teams`, `teams:members`, `teams:invite`, `teams:remove`
|
|
41
41
|
- **Logs:** `wokku logs APP --follow [--tail N]`
|
|
42
|
-
- **Run
|
|
43
|
-
|
|
44
|
-
### Parity with Dokku
|
|
45
|
-
|
|
46
|
-
`wokku do` is the bridge for the ~110 Dokku subcommands not yet first-classed here. Anything `dokku <something> APP` does, `wokku do APP -- <something>` does too — same exit code, same stdout.
|
|
47
|
-
|
|
48
|
-
If you find yourself running the same `wokku do` invocation repeatedly, open an issue — that's the queue for promoting commands to first-class status.
|
|
42
|
+
- **Run:** `wokku run APP -- COMMAND` (one-off in a fresh container)
|
|
49
43
|
|
|
50
44
|
## Global flags
|
|
51
45
|
|
|
@@ -40,8 +40,26 @@ end
|
|
|
40
40
|
register "addons:shared:enable", "Enable a shared engine on an app (usage: wokku addons:shared:enable APP ENGINE). ENGINE: postgres|redis|memcached|rabbitmq|meilisearch" do
|
|
41
41
|
id = ARGV.shift || abort("Usage: wokku addons:shared:enable APP ENGINE")
|
|
42
42
|
engine = ARGV.shift || abort("Missing engine")
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
api(:post, "/apps/#{id}/addons/shared", { engine: engine })
|
|
44
|
+
|
|
45
|
+
attempts = (ENV["WOKKU_POLL_ATTEMPTS"] || "30").to_i
|
|
46
|
+
interval = (ENV["WOKKU_POLL_INTERVAL"] || "2").to_f
|
|
47
|
+
|
|
48
|
+
Wokku::Output.status "Enabling shared #{engine} on #{id} — provisioning…" unless Wokku.quiet
|
|
49
|
+
final = poll_until("/apps/#{id}/addons", attempts: attempts, interval: interval) do |list|
|
|
50
|
+
row = Array(list).find { |a| a["service_type"] == engine && a["shared"] }
|
|
51
|
+
row && %w[running error].include?(row["status"])
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
row = Array(final).find { |a| a["service_type"] == engine && a["shared"] }
|
|
55
|
+
case row && row["status"]
|
|
56
|
+
when "running"
|
|
57
|
+
Wokku::Output.status "Shared #{engine} ready on #{id}."
|
|
58
|
+
when "error"
|
|
59
|
+
abort "Shared #{engine} failed to provision on #{id}. See the dashboard or re-run to retry."
|
|
60
|
+
else
|
|
61
|
+
Wokku::Output.status "Shared #{engine} still provisioning on #{id}. Check: wokku addons #{id}"
|
|
62
|
+
end
|
|
45
63
|
end
|
|
46
64
|
|
|
47
65
|
register "addons:shared:disable", "Disable a shared engine on an app (usage: wokku addons:shared:disable APP ENGINE)" do
|
|
@@ -32,7 +32,23 @@ register "databases:create", "Create a database (usage: wokku databases:create N
|
|
|
32
32
|
abort "Missing --type (postgres, mysql, redis, mongo)" unless type
|
|
33
33
|
server = resolve_server(explicit: server)
|
|
34
34
|
data = api(:post, "/databases", { name: name, service_type: type, server_id: server })
|
|
35
|
-
|
|
35
|
+
|
|
36
|
+
if data["status"] != "running"
|
|
37
|
+
attempts = (ENV["WOKKU_POLL_ATTEMPTS"] || "15").to_i
|
|
38
|
+
interval = (ENV["WOKKU_POLL_INTERVAL"] || "2").to_f
|
|
39
|
+
data = poll_until("/databases/#{data['name']}", attempts: attempts, interval: interval) do |d|
|
|
40
|
+
%w[running error].include?(d["status"])
|
|
41
|
+
end || { "name" => name, "service_type" => type, "status" => "creating" }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
case data["status"]
|
|
45
|
+
when "running"
|
|
46
|
+
Wokku::Output.status "Created #{data['service_type']} database: #{data['name']}"
|
|
47
|
+
when "error"
|
|
48
|
+
abort "Database '#{data['name']}' failed to provision."
|
|
49
|
+
else
|
|
50
|
+
Wokku::Output.status "Database '#{data['name']}' is still provisioning. Check: wokku databases:info #{data['name']}"
|
|
51
|
+
end
|
|
36
52
|
end
|
|
37
53
|
|
|
38
54
|
register "databases:destroy", "Destroy a database (usage: wokku databases:destroy NAME)" do
|
data/lib/wokku/version.rb
CHANGED
data/lib/wokku.rb
CHANGED
|
@@ -80,6 +80,19 @@ rescue Wokku::ApiClient::NotAuthenticated, Wokku::ApiClient::Timeout,
|
|
|
80
80
|
abort e.message
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
+
# Poll GET <path> until the block returns truthy (returns that data) or the
|
|
84
|
+
# attempt budget is exhausted (returns nil). interval is injectable so specs
|
|
85
|
+
# can run with no real sleep.
|
|
86
|
+
def poll_until(path, attempts: 30, interval: 2)
|
|
87
|
+
attempts.times do |i|
|
|
88
|
+
data = api(:get, path)
|
|
89
|
+
return data if yield(data)
|
|
90
|
+
|
|
91
|
+
sleep(interval) if interval.positive? && i < attempts - 1
|
|
92
|
+
end
|
|
93
|
+
nil
|
|
94
|
+
end
|
|
95
|
+
|
|
83
96
|
def load_config = Wokku::Config.load
|
|
84
97
|
def save_config(data) = Wokku::Config.save(data)
|
|
85
98
|
def api_url = Wokku::Config.api_url
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: wokku-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Johannes Dwicahyo
|
|
@@ -46,7 +46,6 @@ files:
|
|
|
46
46
|
- lib/wokku/commands/apps_lifecycle.rb
|
|
47
47
|
- lib/wokku/commands/auth.rb
|
|
48
48
|
- lib/wokku/commands/billing.rb
|
|
49
|
-
- lib/wokku/commands/buildpacks.rb
|
|
50
49
|
- lib/wokku/commands/cdn.rb
|
|
51
50
|
- lib/wokku/commands/certs.rb
|
|
52
51
|
- lib/wokku/commands/checks.rb
|
|
@@ -55,7 +54,6 @@ files:
|
|
|
55
54
|
- lib/wokku/commands/databases.rb
|
|
56
55
|
- lib/wokku/commands/db_monitor.rb
|
|
57
56
|
- lib/wokku/commands/dev.rb
|
|
58
|
-
- lib/wokku/commands/do.rb
|
|
59
57
|
- lib/wokku/commands/domains.rb
|
|
60
58
|
- lib/wokku/commands/github.rb
|
|
61
59
|
- lib/wokku/commands/https.rb
|
|
@@ -72,7 +70,6 @@ files:
|
|
|
72
70
|
- lib/wokku/commands/servers.rb
|
|
73
71
|
- lib/wokku/commands/shell.rb
|
|
74
72
|
- lib/wokku/commands/ssh_keys.rb
|
|
75
|
-
- lib/wokku/commands/storage.rb
|
|
76
73
|
- lib/wokku/commands/teams.rb
|
|
77
74
|
- lib/wokku/commands/templates.rb
|
|
78
75
|
- lib/wokku/commands/tunnel.rb
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# --- Buildpacks ---
|
|
4
|
-
register "buildpacks", "List buildpacks (usage: wokku buildpacks APP)" do
|
|
5
|
-
id = ARGV.shift || abort("Usage: wokku buildpacks APP")
|
|
6
|
-
data = api(:get, "/apps/#{id}/buildpacks")
|
|
7
|
-
Wokku::Output.render(data) do |d|
|
|
8
|
-
list = d.is_a?(Hash) ? Array(d["buildpacks"]) : Array(d)
|
|
9
|
-
if list.empty?
|
|
10
|
-
puts "(no buildpacks configured — auto-detected from source)"
|
|
11
|
-
else
|
|
12
|
-
list.each_with_index { |url, i| puts "#{i + 1}. #{url}" }
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
register "buildpacks:add", "Append a buildpack (usage: wokku buildpacks:add APP URL [--index N])" do
|
|
18
|
-
id = ARGV.shift || abort("Usage: wokku buildpacks:add APP URL [--index N]")
|
|
19
|
-
url = ARGV.shift || abort("Missing buildpack URL")
|
|
20
|
-
index = nil
|
|
21
|
-
while arg = ARGV.shift
|
|
22
|
-
index = ARGV.shift if arg == "--index"
|
|
23
|
-
end
|
|
24
|
-
body = { url: url }
|
|
25
|
-
body[:index] = index if index
|
|
26
|
-
api(:post, "/apps/#{id}/buildpacks", body)
|
|
27
|
-
Wokku::Output.status "Added buildpack: #{url}"
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
register "buildpacks:remove", "Remove a buildpack (usage: wokku buildpacks:remove APP URL)" do
|
|
31
|
-
id = ARGV.shift || abort("Usage: wokku buildpacks:remove APP URL")
|
|
32
|
-
url = ARGV.shift || abort("Missing buildpack URL")
|
|
33
|
-
api(:delete, "/apps/#{id}/buildpacks", { url: url })
|
|
34
|
-
Wokku::Output.status "Removed buildpack: #{url}"
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
register "buildpacks:clear", "Remove every buildpack (usage: wokku buildpacks:clear APP)" do
|
|
38
|
-
id = ARGV.shift || abort("Usage: wokku buildpacks:clear APP")
|
|
39
|
-
api(:delete, "/apps/#{id}/buildpacks")
|
|
40
|
-
Wokku::Output.status "All buildpacks removed."
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
register "buildpacks:set", "Replace the buildpack stack in order (usage: wokku buildpacks:set APP URL [URL...])" do
|
|
44
|
-
id = ARGV.shift || abort("Usage: wokku buildpacks:set APP URL [URL...]")
|
|
45
|
-
urls = ARGV.dup
|
|
46
|
-
ARGV.clear
|
|
47
|
-
abort "No buildpack URLs given." if urls.empty?
|
|
48
|
-
api(:put, "/apps/#{id}/buildpacks", { urls: urls })
|
|
49
|
-
Wokku::Output.status "Buildpacks set: #{urls.join(', ')}"
|
|
50
|
-
end
|
data/lib/wokku/commands/do.rb
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# --- Raw dokku passthrough ---
|
|
4
|
-
register "do", "Run any dokku command (usage: wokku do APP -- DOKKU_ARGS | wokku do --server N -- DOKKU_ARGS)" do
|
|
5
|
-
app = nil
|
|
6
|
-
server = nil
|
|
7
|
-
force = false
|
|
8
|
-
while ARGV.any? && ARGV.first != "--"
|
|
9
|
-
arg = ARGV.shift
|
|
10
|
-
case arg
|
|
11
|
-
when "--server"
|
|
12
|
-
server = ARGV.shift
|
|
13
|
-
abort "--server requires a server ID" if server.nil? || server == "--"
|
|
14
|
-
when "--force" then force = true
|
|
15
|
-
else app ||= arg
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
abort "Missing `--` separator. Example: wokku do myapp -- ps:list" unless ARGV.first == "--"
|
|
20
|
-
ARGV.shift # drop the --
|
|
21
|
-
args = ARGV.dup
|
|
22
|
-
ARGV.clear
|
|
23
|
-
abort "Missing dokku command. Example: wokku do myapp -- ps:list" if args.empty?
|
|
24
|
-
abort "Pass either APP or --server N, not both" if app && server
|
|
25
|
-
abort "Pass APP or --server N before --" if app.nil? && server.nil?
|
|
26
|
-
|
|
27
|
-
path = app ? "/apps/#{app}/dokku" : "/servers/#{server}/dokku"
|
|
28
|
-
data = api(:post, path, { args: args, force: force })
|
|
29
|
-
$stdout.write(data["stdout"]) if data["stdout"] && !data["stdout"].empty?
|
|
30
|
-
$stderr.write(data["stderr"]) if data["stderr"] && !data["stderr"].empty?
|
|
31
|
-
exit (data["exit_code"] || 0).to_i
|
|
32
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# --- Storage (host-bind volumes) ---
|
|
4
|
-
register "storage", "List storage mounts (usage: wokku storage APP)" do
|
|
5
|
-
id = ARGV.shift || abort("Usage: wokku storage APP")
|
|
6
|
-
data = api(:get, "/apps/#{id}/storage")
|
|
7
|
-
Wokku::Output.render(data) do |d|
|
|
8
|
-
list = d.is_a?(Hash) ? Array(d["mounts"]) : Array(d)
|
|
9
|
-
if list.empty?
|
|
10
|
-
puts "(no mounts configured)"
|
|
11
|
-
else
|
|
12
|
-
list.each { |m| puts m }
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
register "storage:mount", "Add a host-bind mount (usage: wokku storage:mount APP HOST_PATH:CONTAINER_PATH)" do
|
|
18
|
-
id = ARGV.shift || abort("Usage: wokku storage:mount APP HOST_PATH:CONTAINER_PATH")
|
|
19
|
-
spec = ARGV.shift || abort("Missing HOST_PATH:CONTAINER_PATH")
|
|
20
|
-
abort "Mount must be HOST_PATH:CONTAINER_PATH" unless spec.include?(":")
|
|
21
|
-
api(:post, "/apps/#{id}/storage", { mount: spec })
|
|
22
|
-
Wokku::Output.status "Mounted: #{spec}"
|
|
23
|
-
Wokku::Output.status "Restart the app to pick up the mount: wokku ps:restart #{id}"
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
register "storage:unmount", "Remove a host-bind mount (usage: wokku storage:unmount APP HOST_PATH:CONTAINER_PATH)" do
|
|
27
|
-
id = ARGV.shift || abort("Usage: wokku storage:unmount APP HOST_PATH:CONTAINER_PATH")
|
|
28
|
-
spec = ARGV.shift || abort("Missing HOST_PATH:CONTAINER_PATH")
|
|
29
|
-
api(:delete, "/apps/#{id}/storage", { mount: spec })
|
|
30
|
-
Wokku::Output.status "Unmounted: #{spec}"
|
|
31
|
-
end
|