omaship 0.2.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/CHANGELOG.md +36 -0
- data/README.md +20 -8
- data/lib/omaship/api_client.rb +59 -15
- data/lib/omaship/cli.rb +190 -108
- data/lib/omaship/color_picker.rb +129 -0
- data/lib/omaship/version.rb +1 -1
- data/lib/omaship.rb +1 -0
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6cb3e55ca287cec243c7b73d01ecbd5d37b5830fed0707175e3fce4c92168008
|
|
4
|
+
data.tar.gz: 7f38d4db65faaf778be3af3dd13472793f0d6bc396d82d040a20b39e7c770e13
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0f3aba37dd0ab910fb8132e192c9f14dab1678982723c9805d18cd1a2e47e242f5806ce25c847ec38bdb05fa54105f59eec55888c6ad6d8d633e5fe0a6d71636
|
|
7
|
+
data.tar.gz: 50fc535b1dea46931d96d8e17f894e94af3e6b8a035137aa7b5425f4bdbc8a07df23ec386affff5abc5b3641c2eabf6ea5c140a0c1508c738504607e0d0d734d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.0](https://github.com/bloomedai/omaship/compare/omaship/v0.4.0...omaship/v0.5.0) (2026-04-04)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* ✨ enforce cli semver gate ([39952c0](https://github.com/bloomedai/omaship/commit/39952c0e855043acd1f1bcb3c4f963457032de4c))
|
|
9
|
+
* adopt run-first ship flow and terminology ([#381](https://github.com/bloomedai/omaship/issues/381)) ([8bc857f](https://github.com/bloomedai/omaship/commit/8bc857fe3fcec6213f7d9d90fc9e8511411c8b00))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* 🐛 align onboarding cli flow ([611425a](https://github.com/bloomedai/omaship/commit/611425a8d84446312daa33afb0c5ed49e8500e01))
|
|
15
|
+
* 🐛 HTML-escape landing page inputs, prompt injection defense, regenerate on rename ([#353](https://github.com/bloomedai/omaship/issues/353)) ([85822df](https://github.com/bloomedai/omaship/commit/85822dfdc4dba3758ff506b4e08422d9c8be3187))
|
|
16
|
+
* 🐛 move cli ship identity into api ([c331548](https://github.com/bloomedai/omaship/commit/c331548e8953de09524aa780b550bf2100cab502))
|
|
17
|
+
* 🐛 remove cli skip-purpose flag ([b815ff7](https://github.com/bloomedai/omaship/commit/b815ff767430a5301012a1ba44583e305446f1a8))
|
|
18
|
+
* 🐛 support landing ships in cli ([1a2f7fe](https://github.com/bloomedai/omaship/commit/1a2f7fecfa1f1b1ad277e6e007dd7303a1d2420a))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Code Refactoring
|
|
22
|
+
|
|
23
|
+
* ♻️ rename LandingPage to Landingpage ([#337](https://github.com/bloomedai/omaship/issues/337)) ([16e9467](https://github.com/bloomedai/omaship/commit/16e9467dceea8e9a595f4be2edf8b89e9759bdfa))
|
|
24
|
+
|
|
25
|
+
## [0.4.0](https://github.com/bloomedai/omaship/compare/omaship/v0.3.0...omaship/v0.4.0) (2026-03-14)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Features
|
|
29
|
+
|
|
30
|
+
* ✨ redesign onboarding flow with progressive CLI terminal path ([#324](https://github.com/bloomedai/omaship/issues/324)) ([872b145](https://github.com/bloomedai/omaship/commit/872b145a2f72775448375557246b4b31fe194459))
|
|
31
|
+
|
|
32
|
+
## [0.3.0](https://github.com/bloomedai/omaship/compare/omaship/v0.2.2...omaship/v0.3.0) (2026-03-09)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Features
|
|
36
|
+
|
|
37
|
+
* ✨ ship the free landing-page flow end to end ([#290](https://github.com/bloomedai/omaship/issues/290)) ([352c088](https://github.com/bloomedai/omaship/commit/352c088219acff3a24a72cda965d12bf1767af1e))
|
|
38
|
+
|
|
3
39
|
## [0.2.2](https://github.com/bloomedai/omaship/compare/omaship/v0.2.1...omaship/v0.2.2) (2026-03-06)
|
|
4
40
|
|
|
5
41
|
|
data/README.md
CHANGED
|
@@ -18,7 +18,7 @@ brew install omaship
|
|
|
18
18
|
## Quick Start
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
omaship login --token <token>
|
|
21
|
+
omaship login --token <token>
|
|
22
22
|
omaship list
|
|
23
23
|
omaship use <ship-ref>
|
|
24
24
|
omaship info
|
|
@@ -33,7 +33,7 @@ omaship use 17
|
|
|
33
33
|
|
|
34
34
|
## Ship Selection
|
|
35
35
|
|
|
36
|
-
`info
|
|
36
|
+
`info` and `deploy` resolve the target ship in this order:
|
|
37
37
|
|
|
38
38
|
1. `--ship <ship-ref>`
|
|
39
39
|
2. saved default from `omaship use <ship-ref>`
|
|
@@ -51,14 +51,26 @@ Numeric ids are also accepted.
|
|
|
51
51
|
- `omaship use <ship-ref>`
|
|
52
52
|
- `omaship info [--ship <ship-ref>]` (`status` and `ship` are aliases)
|
|
53
53
|
- `omaship new <name>` (requires Full CLI access)
|
|
54
|
-
- `omaship configure --payments <provider> [--ship <ship-ref>]` (requires Full CLI access)
|
|
55
54
|
- `omaship deploy [--ship <ship-ref>]` (requires Full CLI access)
|
|
56
55
|
- `omaship complete <bash|zsh|fish>` (print shell completion script)
|
|
57
56
|
- `omaship logout`
|
|
58
57
|
|
|
59
|
-
##
|
|
58
|
+
## Product Direction
|
|
60
59
|
|
|
61
|
-
|
|
60
|
+
Omaship CLI is evolving to support two complementary use cases:
|
|
61
|
+
|
|
62
|
+
- standalone Omaship users launching and operating ship runs directly
|
|
63
|
+
- Sokrates-orchestrated workflows where Sokrates calls Omaship capabilities
|
|
64
|
+
|
|
65
|
+
Related docs:
|
|
66
|
+
|
|
67
|
+
- [Sokrates × Omaship Vision](../docs/sokrates-omaship-vision.md)
|
|
68
|
+
- [Sokrates Integration Task List](../docs/sokrates-integration-tasklist.md)
|
|
69
|
+
- [Landing Pages Improvement Plan](../docs/landingpages-improvement-plan.md)
|
|
70
|
+
|
|
71
|
+
## Local Development Run Execution
|
|
72
|
+
|
|
73
|
+
When you run `omaship new <name>` against local Omaship development (`OMASHIP_HOST=http://localhost:3000`), the initial run first installs gems from `https://packages.omaship.com`.
|
|
62
74
|
|
|
63
75
|
If that registry endpoint is unavailable, Omaship automatically retries `bundle install` through the local package proxy mirror at `http://build.localhost:3000/packages`.
|
|
64
76
|
|
|
@@ -94,7 +106,7 @@ omaship complete fish > ~/.config/fish/completions/omaship.fish
|
|
|
94
106
|
|
|
95
107
|
## Environment
|
|
96
108
|
|
|
97
|
-
- `OMASHIP_HOST` (default: `
|
|
109
|
+
- `OMASHIP_HOST` (default: `https://omaship.com`)
|
|
98
110
|
- `OMASHIP_TOKEN` (optional alternative for `login`)
|
|
99
111
|
|
|
100
112
|
## Credentials
|
|
@@ -108,14 +120,14 @@ omaship complete fish > ~/.config/fish/completions/omaship.fish
|
|
|
108
120
|
Run from repository root:
|
|
109
121
|
|
|
110
122
|
```bash
|
|
111
|
-
mise exec ruby@4.0.
|
|
123
|
+
mise exec ruby@4.0.2 -- env BUNDLE_GEMFILE=cli/Gemfile bundle exec ruby cli/bin/omaship -h
|
|
112
124
|
```
|
|
113
125
|
|
|
114
126
|
Run all CLI tests:
|
|
115
127
|
|
|
116
128
|
```bash
|
|
117
129
|
cd cli
|
|
118
|
-
mise exec ruby@4.0.
|
|
130
|
+
mise exec ruby@4.0.2 -- bundle exec ruby -Itest -e 'Dir.glob("test/**/*_test.rb").sort.each { |f| require "./#{f}" }'
|
|
119
131
|
```
|
|
120
132
|
|
|
121
133
|
## Release Automation
|
data/lib/omaship/api_client.rb
CHANGED
|
@@ -8,6 +8,7 @@ module Omaship
|
|
|
8
8
|
class UnauthorizedError < Error; end
|
|
9
9
|
class PermissionDeniedError < Error; end
|
|
10
10
|
class NotFoundError < Error; end
|
|
11
|
+
class UpgradeRequiredError < Error; end
|
|
11
12
|
|
|
12
13
|
def initialize(host:, token:)
|
|
13
14
|
@host = host.to_s
|
|
@@ -26,16 +27,15 @@ module Omaship
|
|
|
26
27
|
post_json("/api/v1/cli/ships", { ship: { root_domain: root_domain, visibility: visibility } })
|
|
27
28
|
end
|
|
28
29
|
|
|
29
|
-
def
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
get_json("/api/v1/cli/ships/#{ship_id}/logs")
|
|
30
|
+
def create_landingpage(name:, color_scheme: "mono-dark", purpose_profile: {})
|
|
31
|
+
post_json("/api/v1/cli/ships", {
|
|
32
|
+
ship: { name: name, landingpage: true, color_scheme: color_scheme },
|
|
33
|
+
purpose_profile: purpose_profile
|
|
34
|
+
})
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
def
|
|
38
|
-
|
|
37
|
+
def ship(ship_id:)
|
|
38
|
+
get_json("/api/v1/cli/ships/#{ship_id}")
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def create_deploy(ship_id:)
|
|
@@ -61,11 +61,9 @@ module Omaship
|
|
|
61
61
|
def parse_response(response)
|
|
62
62
|
case response.status
|
|
63
63
|
when 200..299
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
JSON.parse(response.body)
|
|
68
|
-
end
|
|
64
|
+
response_json(response)
|
|
65
|
+
when 426
|
|
66
|
+
raise upgrade_required_error(response)
|
|
69
67
|
when 401
|
|
70
68
|
raise UnauthorizedError, "Unauthorized"
|
|
71
69
|
when 403
|
|
@@ -81,9 +79,55 @@ module Omaship
|
|
|
81
79
|
@connection ||= Faraday.new(url: @host) do |faraday|
|
|
82
80
|
faraday.request :retry, max: 2, interval: 0.1
|
|
83
81
|
faraday.adapter Faraday.default_adapter
|
|
84
|
-
faraday.headers
|
|
85
|
-
faraday.headers["Accept"] = "application/json"
|
|
82
|
+
faraday.headers.update(request_headers)
|
|
86
83
|
end
|
|
87
84
|
end
|
|
85
|
+
|
|
86
|
+
def request_headers
|
|
87
|
+
{
|
|
88
|
+
"Authorization" => "Bearer #{@token}",
|
|
89
|
+
"Accept" => "application/json",
|
|
90
|
+
"X-Omaship-CLI-Version" => Omaship::VERSION
|
|
91
|
+
}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def response_json(response)
|
|
95
|
+
if response.body.to_s.empty?
|
|
96
|
+
{}
|
|
97
|
+
else
|
|
98
|
+
JSON.parse(response.body)
|
|
99
|
+
end
|
|
100
|
+
rescue JSON::ParserError
|
|
101
|
+
{}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def upgrade_required_error(response)
|
|
105
|
+
payload = response_json(response)
|
|
106
|
+
minimum_version = payload["minimum_version"].to_s.strip
|
|
107
|
+
current_version = payload["current_version"].to_s.strip
|
|
108
|
+
upgrade_command = payload["upgrade_command"].to_s.strip
|
|
109
|
+
|
|
110
|
+
message = []
|
|
111
|
+
|
|
112
|
+
if current_version.empty?
|
|
113
|
+
message << "Your CLI is no longer supported."
|
|
114
|
+
else
|
|
115
|
+
message << "CLI #{current_version} is no longer supported."
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
if minimum_version.empty?
|
|
119
|
+
message << "Install the latest version."
|
|
120
|
+
else
|
|
121
|
+
message << "Minimum supported version is #{minimum_version}."
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
if upgrade_command.empty?
|
|
125
|
+
message << "Upgrade your CLI and try again."
|
|
126
|
+
else
|
|
127
|
+
message << "Run `#{upgrade_command}` and try again."
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
UpgradeRequiredError.new(message.join(" "))
|
|
131
|
+
end
|
|
88
132
|
end
|
|
89
133
|
end
|
data/lib/omaship/cli.rb
CHANGED
|
@@ -51,8 +51,8 @@ module Omaship
|
|
|
51
51
|
shell.say " use Set default ship from `omaship list` (for example: `omaship use omaship/acme`)"
|
|
52
52
|
shell.say " info Show details for a ship (aliases: ship, status)"
|
|
53
53
|
shell.say " new Create and provision a new ship"
|
|
54
|
-
shell.say " configure Configure a ship (requires Full CLI access)"
|
|
55
54
|
shell.say " deploy Deploy a ship (requires Full CLI access)"
|
|
55
|
+
shell.say " upgrade Open browser to upgrade your plan"
|
|
56
56
|
shell.say " complete Print shell completion script (bash, zsh, fish)"
|
|
57
57
|
shell.say " logout Remove local CLI credentials"
|
|
58
58
|
shell.say
|
|
@@ -143,8 +143,7 @@ module Omaship
|
|
|
143
143
|
say "Ships:"
|
|
144
144
|
ships.each do |ship|
|
|
145
145
|
marker = default_ship_match?(ship: ship, ship_reference: default_ship_reference) ? "*" : " "
|
|
146
|
-
|
|
147
|
-
say "#{marker} #{ship.fetch("id")} #{ship.fetch("full_name")} #{ship.fetch("status")} #{app_url}"
|
|
146
|
+
say "#{marker} #{ship.fetch("id")} #{ship.fetch("display_name")} #{ship.fetch("status")} #{ship.fetch("primary_url", "-") || "-"}"
|
|
148
147
|
end
|
|
149
148
|
|
|
150
149
|
if !default_ship_reference.empty?
|
|
@@ -161,6 +160,7 @@ module Omaship
|
|
|
161
160
|
|
|
162
161
|
Get available values with `omaship list`.
|
|
163
162
|
Preferred format is full ship name (`org/repo`), for example `omaship/acme`.
|
|
163
|
+
Landing pages can also be selected by root domain, for example `acme.omaship.app`.
|
|
164
164
|
Numeric ship ids from `omaship list` also work.
|
|
165
165
|
|
|
166
166
|
Examples:
|
|
@@ -173,33 +173,38 @@ module Omaship
|
|
|
173
173
|
ship = find_ship_by_reference(token: token, ship_reference: ship_reference)
|
|
174
174
|
persist_default_ship(ship)
|
|
175
175
|
|
|
176
|
-
say "Default ship set to #{ship.fetch("
|
|
176
|
+
say "Default ship set to #{ship.fetch("reference")}."
|
|
177
177
|
end
|
|
178
178
|
end
|
|
179
179
|
|
|
180
180
|
desc "info", "Show ship info"
|
|
181
|
-
method_option :ship, type: :string, desc: "Ship from `omaship list` (preferred: omaship/acme; id also works)"
|
|
181
|
+
method_option :ship, type: :string, desc: "Ship from `omaship list` (preferred: omaship/acme or acme.omaship.app; id also works)"
|
|
182
182
|
def info
|
|
183
183
|
with_api_error_handling(command: :info) do
|
|
184
184
|
token = current_token
|
|
185
185
|
client = build_api_client(token: token)
|
|
186
186
|
resolved_ship = resolve_ship(token: token)
|
|
187
187
|
ship = client.ship(ship_id: resolved_ship.fetch("id")).fetch("ship")
|
|
188
|
-
deploy = client.latest_deploy(ship_id: ship.fetch("id")).fetch("deploy")
|
|
189
188
|
default_ship_reference = credentials.default_ship.to_s.strip
|
|
190
189
|
|
|
191
|
-
say "Ship: #{ship.fetch("
|
|
190
|
+
say "Ship: #{ship.fetch("display_name")}"
|
|
192
191
|
say "ID: #{ship.fetch("id")}"
|
|
193
192
|
say "Status: #{ship.fetch("status")}"
|
|
194
193
|
say "App URL: #{ship["app_url"] || "-"}"
|
|
194
|
+
say "Landing URL: #{ship["landing_url"] || "-"}"
|
|
195
195
|
say "Repo URL: #{ship["repo_url"] || "-"}"
|
|
196
196
|
say "Default Ship: #{default_ship_reference.empty? ? "-" : default_ship_reference}"
|
|
197
|
-
|
|
198
|
-
if
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
197
|
+
|
|
198
|
+
if ship.fetch("deployable")
|
|
199
|
+
deploy = client.latest_deploy(ship_id: ship.fetch("id")).fetch("deploy")
|
|
200
|
+
|
|
201
|
+
say "Last Deploy: #{deploy_status_summary(deploy)}"
|
|
202
|
+
if deploy["run_number"]
|
|
203
|
+
say "Run: ##{deploy.fetch("run_number")}"
|
|
204
|
+
end
|
|
205
|
+
if deploy["started_at"]
|
|
206
|
+
say "Started At: #{deploy.fetch("started_at")}"
|
|
207
|
+
end
|
|
203
208
|
end
|
|
204
209
|
end
|
|
205
210
|
end
|
|
@@ -209,42 +214,19 @@ module Omaship
|
|
|
209
214
|
def new_ship(name)
|
|
210
215
|
with_api_error_handling(command: :new_ship) do
|
|
211
216
|
token = current_token
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
ship = payload.fetch("ship")
|
|
215
|
-
|
|
216
|
-
progress_renderer.step("Setting up your codebase")
|
|
217
|
-
final_ship = poll_until_terminal(ship_id: ship.fetch("id"), token: token)
|
|
217
|
+
auth = fetch_auth(token: token)
|
|
218
|
+
plan = auth.dig("user", "plan") || "free"
|
|
218
219
|
|
|
219
|
-
if
|
|
220
|
-
|
|
220
|
+
if plan == "free"
|
|
221
|
+
create_free_ship(name: name, token: token)
|
|
221
222
|
else
|
|
222
|
-
|
|
223
|
-
raise Thor::Error, message
|
|
223
|
+
create_paid_ship(name: name, token: token)
|
|
224
224
|
end
|
|
225
225
|
end
|
|
226
226
|
end
|
|
227
227
|
|
|
228
|
-
desc "configure --payments PROVIDER", "Configure a ship"
|
|
229
|
-
method_option :payments, type: :string, required: true
|
|
230
|
-
method_option :ship, type: :string, desc: "Ship from `omaship list` (preferred: omaship/acme; id also works)"
|
|
231
|
-
def configure
|
|
232
|
-
with_api_error_handling(command: :configure) do
|
|
233
|
-
payments_provider = options[:payments].to_s.strip.downcase
|
|
234
|
-
|
|
235
|
-
token = current_token
|
|
236
|
-
ship = resolve_ship(token: token)
|
|
237
|
-
build_api_client(token: token).create_configuration(ship_id: ship.fetch("id"), package: payments_provider)
|
|
238
|
-
|
|
239
|
-
progress_renderer.step("Configuration queued.")
|
|
240
|
-
|
|
241
|
-
poll_until_configuration_complete(ship_id: ship.fetch("id"), token: token)
|
|
242
|
-
progress_renderer.step("Configuration applied.")
|
|
243
|
-
end
|
|
244
|
-
end
|
|
245
|
-
|
|
246
228
|
desc "deploy", "Deploy a ship (requires Full CLI access)"
|
|
247
|
-
method_option :ship, type: :string, desc: "Ship from `omaship list` (preferred: omaship/acme; id also works)"
|
|
229
|
+
method_option :ship, type: :string, desc: "Ship from `omaship list` (preferred: omaship/acme or acme.omaship.app; id also works)"
|
|
248
230
|
def deploy
|
|
249
231
|
with_api_error_handling(command: :deploy) do
|
|
250
232
|
token = current_token
|
|
@@ -260,6 +242,17 @@ module Omaship
|
|
|
260
242
|
end
|
|
261
243
|
end
|
|
262
244
|
|
|
245
|
+
desc "upgrade [SHIP]", "Open browser to upgrade your plan"
|
|
246
|
+
def upgrade(ship_name = nil)
|
|
247
|
+
url = "#{resolved_host}/settings/license"
|
|
248
|
+
if ship_name
|
|
249
|
+
url = "#{url}?ship=#{ship_name}"
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
say "Opening #{url}"
|
|
253
|
+
open_browser(url)
|
|
254
|
+
end
|
|
255
|
+
|
|
263
256
|
desc "complete SHELL", "Print shell completion script (bash, zsh, fish)"
|
|
264
257
|
long_desc <<~DESC
|
|
265
258
|
Print a shell completion script to stdout.
|
|
@@ -307,7 +300,7 @@ module Omaship
|
|
|
307
300
|
fi
|
|
308
301
|
|
|
309
302
|
if [[ ${COMP_CWORD} -eq 1 ]]; then
|
|
310
|
-
COMPREPLY=( $(compgen -W "login whoami list use info status ship new
|
|
303
|
+
COMPREPLY=( $(compgen -W "login whoami list use info status ship new deploy upgrade logout complete help" -- "${cur}") )
|
|
311
304
|
return 0
|
|
312
305
|
fi
|
|
313
306
|
|
|
@@ -316,11 +309,6 @@ module Omaship
|
|
|
316
309
|
return 0
|
|
317
310
|
fi
|
|
318
311
|
|
|
319
|
-
if [[ "${prev}" == "--payments" ]]; then
|
|
320
|
-
COMPREPLY=( $(compgen -W "stripe" -- "${cur}") )
|
|
321
|
-
return 0
|
|
322
|
-
fi
|
|
323
|
-
|
|
324
312
|
if [[ "${prev}" == "--ship" ]]; then
|
|
325
313
|
COMPREPLY=( $(compgen -W "$(omaship list 2>/dev/null | awk '/^[* ] [0-9]+ / { print $3 }')" -- "${cur}") )
|
|
326
314
|
return 0
|
|
@@ -347,9 +335,6 @@ module Omaship
|
|
|
347
335
|
new)
|
|
348
336
|
COMPREPLY=( $(compgen -W "--domain --host -h --help" -- "${cur}") )
|
|
349
337
|
;;
|
|
350
|
-
configure)
|
|
351
|
-
COMPREPLY=( $(compgen -W "--payments --ship --host -h --help" -- "${cur}") )
|
|
352
|
-
;;
|
|
353
338
|
complete)
|
|
354
339
|
COMPREPLY=( $(compgen -W "bash zsh fish" -- "${cur}") )
|
|
355
340
|
;;
|
|
@@ -386,8 +371,8 @@ module Omaship
|
|
|
386
371
|
'status:Alias for info'
|
|
387
372
|
'ship:Alias for info'
|
|
388
373
|
'new:Create and provision a new ship'
|
|
389
|
-
'configure:Configure a ship'
|
|
390
374
|
'deploy:Deploy a ship'
|
|
375
|
+
'upgrade:Open browser to upgrade your plan'
|
|
391
376
|
'logout:Remove local CLI credentials'
|
|
392
377
|
'complete:Print shell completion script'
|
|
393
378
|
'help:Describe available commands'
|
|
@@ -419,9 +404,6 @@ module Omaship
|
|
|
419
404
|
new)
|
|
420
405
|
_arguments '--domain[Root domain]:domain:' '--host[API host]:host:' '1:name:'
|
|
421
406
|
;;
|
|
422
|
-
configure)
|
|
423
|
-
_arguments '--payments[Payments provider]:provider:(stripe)' '--ship[Ship from omaship list]:ship:_omaship_ship_refs' '--host[API host]:host:'
|
|
424
|
-
;;
|
|
425
407
|
complete)
|
|
426
408
|
_arguments '1:shell:(bash zsh fish)'
|
|
427
409
|
;;
|
|
@@ -444,19 +426,145 @@ module Omaship
|
|
|
444
426
|
end
|
|
445
427
|
|
|
446
428
|
complete -c omaship -f
|
|
447
|
-
complete -c omaship -n '__fish_use_subcommand' -a 'login whoami list use info status ship new
|
|
429
|
+
complete -c omaship -n '__fish_use_subcommand' -a 'login whoami list use info status ship new deploy upgrade logout complete help'
|
|
448
430
|
complete -c omaship -l host -d 'API host'
|
|
449
431
|
|
|
450
432
|
complete -c omaship -n '__fish_seen_subcommand_from login' -l token -d 'API token from omaship settings'
|
|
451
433
|
complete -c omaship -n '__fish_seen_subcommand_from new' -l domain -d 'Root domain'
|
|
452
|
-
complete -c omaship -n '__fish_seen_subcommand_from configure' -l payments -d 'Payments provider' -a 'stripe'
|
|
453
|
-
complete -c omaship -n '__fish_seen_subcommand_from configure' -l ship -d 'Ship from omaship list' -a '(__fish_omaship_ship_refs)'
|
|
454
434
|
complete -c omaship -n '__fish_seen_subcommand_from info status ship deploy' -l ship -d 'Ship from omaship list' -a '(__fish_omaship_ship_refs)'
|
|
455
435
|
complete -c omaship -n '__fish_seen_subcommand_from use' -f -a '(__fish_omaship_ship_refs)'
|
|
456
436
|
complete -c omaship -n '__fish_seen_subcommand_from complete' -f -a 'bash zsh fish'
|
|
457
437
|
FISH
|
|
458
438
|
end
|
|
459
439
|
|
|
440
|
+
def fetch_auth(token:)
|
|
441
|
+
build_api_client(token: token).authenticate
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
def create_paid_ship(name:, token:)
|
|
445
|
+
root_domain = options[:domain] || "#{name}.com"
|
|
446
|
+
payload = build_api_client(token: token).create_ship(root_domain: root_domain)
|
|
447
|
+
ship = payload.fetch("ship")
|
|
448
|
+
|
|
449
|
+
progress_renderer.step("Setting up your codebase")
|
|
450
|
+
final_ship = poll_until_terminal(ship_id: ship.fetch("id"), token: token)
|
|
451
|
+
|
|
452
|
+
if final_ship.fetch("status") == "live"
|
|
453
|
+
progress_renderer.step("Ready. Customers can sign up and pay at #{final_ship.fetch("root_domain")}")
|
|
454
|
+
else
|
|
455
|
+
message = final_ship["error_message"] || "Provisioning failed"
|
|
456
|
+
raise Thor::Error, message
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
def create_free_ship(name:, token:)
|
|
461
|
+
print_free_banner
|
|
462
|
+
|
|
463
|
+
purpose_profile = {}
|
|
464
|
+
color_scheme = "mono-dark"
|
|
465
|
+
|
|
466
|
+
if ask_purpose_profile?
|
|
467
|
+
purpose_profile = collect_purpose_profile
|
|
468
|
+
end
|
|
469
|
+
color_scheme = pick_color_scheme
|
|
470
|
+
|
|
471
|
+
say
|
|
472
|
+
progress_renderer.step("Creating your landing page...")
|
|
473
|
+
|
|
474
|
+
payload = build_api_client(token: token).create_landingpage(
|
|
475
|
+
name: name,
|
|
476
|
+
color_scheme: color_scheme,
|
|
477
|
+
purpose_profile: purpose_profile
|
|
478
|
+
)
|
|
479
|
+
ship = payload.fetch("ship")
|
|
480
|
+
|
|
481
|
+
if ship["distillation_status"] == "pending"
|
|
482
|
+
progress_renderer.step("Sokrates is distilling your answers...")
|
|
483
|
+
poll_until_distilled(ship_id: ship.fetch("id"), token: token)
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
say
|
|
487
|
+
say "Live at: https://#{ship.fetch("root_domain")}"
|
|
488
|
+
say "Review and refine at: #{resolved_host}/ships/#{ship.fetch("id")}/purpose_profile"
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
def print_free_banner
|
|
492
|
+
lines = [
|
|
493
|
+
"FREE PLAN",
|
|
494
|
+
"",
|
|
495
|
+
"You'll get a static landing page with a waitlist",
|
|
496
|
+
"on *.omaship.app",
|
|
497
|
+
"",
|
|
498
|
+
"Want the full Rails app on your own server?",
|
|
499
|
+
"Run: omaship upgrade"
|
|
500
|
+
]
|
|
501
|
+
width = lines.map(&:length).max + 4
|
|
502
|
+
bar = "+#{"-" * (width + 2)}+"
|
|
503
|
+
|
|
504
|
+
say
|
|
505
|
+
say bar
|
|
506
|
+
lines.each do |line|
|
|
507
|
+
say "| #{line.ljust(width)}|"
|
|
508
|
+
end
|
|
509
|
+
say bar
|
|
510
|
+
say
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
def ask_purpose_profile?
|
|
514
|
+
say "Would you like to create a purpose profile?"
|
|
515
|
+
say "This helps generate better landing page copy. (5 questions, ~2 min)"
|
|
516
|
+
say
|
|
517
|
+
answer = ask("Continue with purpose profile? (Y/n):")
|
|
518
|
+
answer.to_s.strip.downcase != "n"
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def collect_purpose_profile
|
|
522
|
+
say
|
|
523
|
+
say "--- Purpose Profile ---"
|
|
524
|
+
say
|
|
525
|
+
|
|
526
|
+
raw_problem = ask("What problem does your product solve?\n>")
|
|
527
|
+
raw_audience = ask("Who is most affected by this problem?\n>")
|
|
528
|
+
raw_belief = ask("Why is this worth solving? What's your core belief?\n>")
|
|
529
|
+
raw_contribution = ask("What's your contribution to the solution?\n>")
|
|
530
|
+
raw_outcome = ask("What does the world look like when you succeed?\n>")
|
|
531
|
+
|
|
532
|
+
{
|
|
533
|
+
raw_problem: raw_problem,
|
|
534
|
+
raw_audience: raw_audience,
|
|
535
|
+
raw_belief: raw_belief,
|
|
536
|
+
raw_contribution: raw_contribution,
|
|
537
|
+
raw_outcome: raw_outcome
|
|
538
|
+
}.reject { |_k, v| v.to_s.strip.empty? }
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
def pick_color_scheme
|
|
542
|
+
say
|
|
543
|
+
say "--- Color Scheme ---"
|
|
544
|
+
selected = color_picker.pick
|
|
545
|
+
say "Selected: #{selected}"
|
|
546
|
+
selected
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
def color_picker
|
|
550
|
+
@color_picker ||= Omaship::ColorPicker.new
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
def poll_until_distilled(ship_id:, token:)
|
|
554
|
+
client = build_api_client(token: token)
|
|
555
|
+
30.times do
|
|
556
|
+
ship_payload = client.ship(ship_id: ship_id).fetch("ship")
|
|
557
|
+
status = ship_payload["distillation_status"]
|
|
558
|
+
|
|
559
|
+
if status == "complete" || status == "skipped" || status == "none"
|
|
560
|
+
return ship_payload
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
sleep 2
|
|
564
|
+
end
|
|
565
|
+
say "Distillation timed out. You can refine later in the dashboard."
|
|
566
|
+
end
|
|
567
|
+
|
|
460
568
|
def current_token
|
|
461
569
|
value = credentials.token
|
|
462
570
|
if value.to_s.strip.empty?
|
|
@@ -507,7 +615,7 @@ module Omaship
|
|
|
507
615
|
if ship
|
|
508
616
|
ship
|
|
509
617
|
else
|
|
510
|
-
raise Thor::Error, "Unknown ship `#{ship_reference}`. Run `omaship list` and use
|
|
618
|
+
raise Thor::Error, "Unknown ship `#{ship_reference}`. Run `omaship list` and use a ship name or root domain from the list, or the numeric id."
|
|
511
619
|
end
|
|
512
620
|
end
|
|
513
621
|
|
|
@@ -518,11 +626,11 @@ module Omaship
|
|
|
518
626
|
end
|
|
519
627
|
|
|
520
628
|
def default_ship_match?(ship:, ship_reference:)
|
|
521
|
-
ship.fetch("id").to_s == ship_reference || ship.fetch("
|
|
629
|
+
ship.fetch("id").to_s == ship_reference || ship.fetch("reference") == ship_reference
|
|
522
630
|
end
|
|
523
631
|
|
|
524
632
|
def persist_default_ship(ship)
|
|
525
|
-
credentials.write_default_ship(ship.fetch("
|
|
633
|
+
credentials.write_default_ship(ship.fetch("reference"))
|
|
526
634
|
end
|
|
527
635
|
|
|
528
636
|
def resolve_ship_for_deploy(token:)
|
|
@@ -544,7 +652,7 @@ module Omaship
|
|
|
544
652
|
end
|
|
545
653
|
|
|
546
654
|
def multiple_ships_message
|
|
547
|
-
"Multiple ships found. Run `omaship list` and `omaship use <
|
|
655
|
+
"Multiple ships found. Run `omaship list` and `omaship use <ship-from-list>` (or a ship id)."
|
|
548
656
|
end
|
|
549
657
|
|
|
550
658
|
def with_api_error_handling(command:)
|
|
@@ -558,10 +666,10 @@ module Omaship
|
|
|
558
666
|
end
|
|
559
667
|
|
|
560
668
|
def permission_denied_message(command:)
|
|
561
|
-
if
|
|
669
|
+
if current_access_level == "onboarding"
|
|
670
|
+
"This onboarding token only supports `omaship new` while you create your first ship. Create a full-access token in Settings after onboarding to use other CLI commands."
|
|
671
|
+
elsif command == :new_ship
|
|
562
672
|
"`omaship new` requires a full-access token. Create a token with Full CLI access and run `omaship login` again."
|
|
563
|
-
elsif command == :configure
|
|
564
|
-
"`omaship configure` requires a full-access token. Create a token with Full CLI access and run `omaship login` again."
|
|
565
673
|
elsif command == :deploy
|
|
566
674
|
"`omaship deploy` requires a full-access token. Create a token with Full CLI access and run `omaship login` again."
|
|
567
675
|
else
|
|
@@ -569,6 +677,15 @@ module Omaship
|
|
|
569
677
|
end
|
|
570
678
|
end
|
|
571
679
|
|
|
680
|
+
def current_access_level
|
|
681
|
+
token = credentials.token
|
|
682
|
+
return "unknown" if token.to_s.strip.empty?
|
|
683
|
+
|
|
684
|
+
build_api_client(token: token).authenticate.dig("token", "access_level").to_s
|
|
685
|
+
rescue NoMethodError, Omaship::ApiClient::Error
|
|
686
|
+
"unknown"
|
|
687
|
+
end
|
|
688
|
+
|
|
572
689
|
def build_api_client(token:)
|
|
573
690
|
Omaship::ApiClient.new(host: resolved_host, token: token)
|
|
574
691
|
end
|
|
@@ -581,31 +698,10 @@ module Omaship
|
|
|
581
698
|
@progress_renderer ||= Omaship::ProgressRenderer.new(out: $stdout)
|
|
582
699
|
end
|
|
583
700
|
|
|
584
|
-
def emit_logs(log_entries)
|
|
585
|
-
log_entries.each do |entry|
|
|
586
|
-
next unless displayable_log_entry?(entry)
|
|
587
|
-
|
|
588
|
-
message = entry.fetch("message")
|
|
589
|
-
progress_renderer.step(message)
|
|
590
|
-
end
|
|
591
|
-
end
|
|
592
|
-
|
|
593
|
-
def displayable_log_entry?(entry)
|
|
594
|
-
entry.fetch("level", "").to_s != "debug"
|
|
595
|
-
end
|
|
596
|
-
|
|
597
701
|
def poll_until_terminal(ship_id:, token:)
|
|
598
702
|
client = build_api_client(token: token)
|
|
599
|
-
last_log_id = 0
|
|
600
703
|
90.times do
|
|
601
704
|
ship_payload = client.ship(ship_id: ship_id).fetch("ship")
|
|
602
|
-
logs_payload = client.ship_logs(ship_id: ship_id)
|
|
603
|
-
logs = logs_payload.fetch("logs").select { |entry| entry.fetch("id") > last_log_id }
|
|
604
|
-
if logs.any?
|
|
605
|
-
last_log_id = logs.last.fetch("id")
|
|
606
|
-
end
|
|
607
|
-
|
|
608
|
-
emit_logs(logs)
|
|
609
705
|
status = ship_payload.fetch("status")
|
|
610
706
|
if %w[live error].include?(status)
|
|
611
707
|
return ship_payload
|
|
@@ -616,27 +712,6 @@ module Omaship
|
|
|
616
712
|
raise Thor::Error, "Provisioning timed out."
|
|
617
713
|
end
|
|
618
714
|
|
|
619
|
-
def poll_until_configuration_complete(ship_id:, token:)
|
|
620
|
-
client = build_api_client(token: token)
|
|
621
|
-
60.times do
|
|
622
|
-
ship_payload = client.ship(ship_id: ship_id).fetch("ship")
|
|
623
|
-
pending = ship_payload.fetch("package_update_pending")
|
|
624
|
-
if pending
|
|
625
|
-
progress_renderer.step("Applying configuration changes.")
|
|
626
|
-
sleep 2
|
|
627
|
-
else
|
|
628
|
-
error_message = ship_payload["error_message"].to_s.strip
|
|
629
|
-
if error_message.empty?
|
|
630
|
-
return
|
|
631
|
-
end
|
|
632
|
-
|
|
633
|
-
raise Thor::Error, error_message
|
|
634
|
-
end
|
|
635
|
-
end
|
|
636
|
-
|
|
637
|
-
raise Thor::Error, "Configuration timed out."
|
|
638
|
-
end
|
|
639
|
-
|
|
640
715
|
def poll_until_deploy_finished(ship_id:, token:)
|
|
641
716
|
client = build_api_client(token: token)
|
|
642
717
|
last_status = nil
|
|
@@ -686,8 +761,15 @@ module Omaship
|
|
|
686
761
|
end
|
|
687
762
|
end
|
|
688
763
|
|
|
764
|
+
def open_browser(url)
|
|
765
|
+
opener = RUBY_PLATFORM.include?("darwin") ? "open" : "xdg-open"
|
|
766
|
+
system(opener, url)
|
|
767
|
+
rescue Errno::ENOENT
|
|
768
|
+
say "Could not open browser. Visit: #{url}"
|
|
769
|
+
end
|
|
770
|
+
|
|
689
771
|
def resolved_host
|
|
690
|
-
options[:host] || credentials.host || ENV["OMASHIP_HOST"] || "
|
|
772
|
+
options[:host] || credentials.host || ENV["OMASHIP_HOST"] || "https://omaship.com"
|
|
691
773
|
end
|
|
692
774
|
|
|
693
775
|
def existing_credentials_status_message
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
require "io/console"
|
|
2
|
+
|
|
3
|
+
module Omaship
|
|
4
|
+
class ColorPicker
|
|
5
|
+
SCHEMES = [
|
|
6
|
+
{ key: "flexoki-light", bg: "#FFFCF0", primary: "#205EA6", accent: "#AD8301", text: "#100F0F" },
|
|
7
|
+
{ key: "flexoki-dark", bg: "#100F0F", primary: "#4385BE", accent: "#D0A215", text: "#FFFCF0" },
|
|
8
|
+
{ key: "catppuccin-latte", bg: "#EFF1F5", primary: "#8839EF", accent: "#179299", text: "#4C4F69" },
|
|
9
|
+
{ key: "catppuccin-mocha", bg: "#1E1E2E", primary: "#CBA6F7", accent: "#94E2D5", text: "#CDD6F4" },
|
|
10
|
+
{ key: "rosepine-dawn", bg: "#FAF4ED", primary: "#907AA9", accent: "#D7827E", text: "#575279" },
|
|
11
|
+
{ key: "rosepine-moon", bg: "#232136", primary: "#C4A7E7", accent: "#EA9A97", text: "#E0DEF4" },
|
|
12
|
+
{ key: "nord-snow", bg: "#ECEFF4", primary: "#5E81AC", accent: "#88C0D0", text: "#2E3440" },
|
|
13
|
+
{ key: "nord-frost", bg: "#2E3440", primary: "#88C0D0", accent: "#5E81AC", text: "#ECEFF4" },
|
|
14
|
+
{ key: "mono-light", bg: "#FFFFFF", primary: "#18181B", accent: "#71717A", text: "#18181B" },
|
|
15
|
+
{ key: "mono-dark", bg: "#18181B", primary: "#FAFAFA", accent: "#A1A1AA", text: "#FAFAFA" },
|
|
16
|
+
{ key: "solarized-light", bg: "#FDF6E3", primary: "#268BD2", accent: "#2AA198", text: "#657B83" },
|
|
17
|
+
{ key: "solarized-dark", bg: "#002B36", primary: "#268BD2", accent: "#2AA198", text: "#839496" }
|
|
18
|
+
].freeze
|
|
19
|
+
|
|
20
|
+
DEFAULT_INDEX = 9
|
|
21
|
+
|
|
22
|
+
def initialize(out: $stdout, input: $stdin)
|
|
23
|
+
@out = out
|
|
24
|
+
@input = input
|
|
25
|
+
@index = DEFAULT_INDEX
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def pick
|
|
29
|
+
render
|
|
30
|
+
loop do
|
|
31
|
+
key = read_key
|
|
32
|
+
case key
|
|
33
|
+
when :left, "h"
|
|
34
|
+
@index = (@index - 1) % SCHEMES.size
|
|
35
|
+
render
|
|
36
|
+
when :right, "l"
|
|
37
|
+
@index = (@index + 1) % SCHEMES.size
|
|
38
|
+
render
|
|
39
|
+
when :enter, "q"
|
|
40
|
+
@out.print "\e[?25h"
|
|
41
|
+
@out.puts
|
|
42
|
+
return SCHEMES[@index][:key]
|
|
43
|
+
when :ctrl_c
|
|
44
|
+
@out.print "\e[?25h"
|
|
45
|
+
@out.puts
|
|
46
|
+
return SCHEMES[DEFAULT_INDEX][:key]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def render
|
|
54
|
+
scheme = SCHEMES[@index]
|
|
55
|
+
@out.print "\e[?25l"
|
|
56
|
+
@out.print "\r\e[K"
|
|
57
|
+
lines = build_preview(scheme)
|
|
58
|
+
move_up = @rendered_lines || 0
|
|
59
|
+
@out.print "\e[#{move_up}A" if move_up > 0
|
|
60
|
+
lines.each do |line|
|
|
61
|
+
@out.print "\r\e[K#{line}\n"
|
|
62
|
+
end
|
|
63
|
+
@rendered_lines = lines.size
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def build_preview(scheme)
|
|
67
|
+
name = scheme[:key]
|
|
68
|
+
bg_block = color_block(scheme[:bg])
|
|
69
|
+
primary_block = color_block(scheme[:primary])
|
|
70
|
+
accent_block = color_block(scheme[:accent])
|
|
71
|
+
text_block = color_block(scheme[:text])
|
|
72
|
+
|
|
73
|
+
nav = SCHEMES.map.with_index do |s, i|
|
|
74
|
+
if i == @index
|
|
75
|
+
"\e[1m[#{s[:key]}]\e[0m"
|
|
76
|
+
else
|
|
77
|
+
" #{s[:key]} "
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
[
|
|
82
|
+
"",
|
|
83
|
+
" #{left_arrow} #{name} #{right_arrow}",
|
|
84
|
+
"",
|
|
85
|
+
" #{bg_block} bg #{primary_block} primary #{accent_block} accent #{text_block} text",
|
|
86
|
+
"",
|
|
87
|
+
" Use \e[1m<-\e[0m / \e[1m->\e[0m or \e[1mh\e[0m / \e[1ml\e[0m to browse. \e[1mEnter\e[0m to select.",
|
|
88
|
+
""
|
|
89
|
+
]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def left_arrow
|
|
93
|
+
@index > 0 ? "\e[1m<\e[0m" : " "
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def right_arrow
|
|
97
|
+
@index < SCHEMES.size - 1 ? "\e[1m>\e[0m" : " "
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def color_block(hex)
|
|
101
|
+
r, g, b = hex_to_rgb(hex)
|
|
102
|
+
"\e[48;2;#{r};#{g};#{b}m \e[0m"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def hex_to_rgb(hex)
|
|
106
|
+
hex = hex.delete("#")
|
|
107
|
+
[ hex[0..1], hex[2..3], hex[4..5] ].map { |c| c.to_i(16) }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def read_key
|
|
111
|
+
char = @input.raw { @input.getc }
|
|
112
|
+
case char
|
|
113
|
+
when "\r", "\n"
|
|
114
|
+
:enter
|
|
115
|
+
when "\e"
|
|
116
|
+
seq = @input.raw { @input.read_nonblock(2) rescue "" }
|
|
117
|
+
case seq
|
|
118
|
+
when "[D" then :left
|
|
119
|
+
when "[C" then :right
|
|
120
|
+
else :unknown
|
|
121
|
+
end
|
|
122
|
+
when "\x03"
|
|
123
|
+
:ctrl_c
|
|
124
|
+
else
|
|
125
|
+
char
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
data/lib/omaship/version.rb
CHANGED
data/lib/omaship.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: omaship
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Omaship
|
|
@@ -51,8 +51,7 @@ dependencies:
|
|
|
51
51
|
- - ">="
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
53
|
version: '0'
|
|
54
|
-
description: CLI for login, ship provisioning,
|
|
55
|
-
against Omaship.
|
|
54
|
+
description: CLI for login, ship provisioning, and deploy operations against Omaship.
|
|
56
55
|
email:
|
|
57
56
|
- hello@omaship.com
|
|
58
57
|
executables:
|
|
@@ -66,6 +65,7 @@ files:
|
|
|
66
65
|
- lib/omaship.rb
|
|
67
66
|
- lib/omaship/api_client.rb
|
|
68
67
|
- lib/omaship/cli.rb
|
|
68
|
+
- lib/omaship/color_picker.rb
|
|
69
69
|
- lib/omaship/credentials.rb
|
|
70
70
|
- lib/omaship/progress_renderer.rb
|
|
71
71
|
- lib/omaship/ship_detector.rb
|
|
@@ -91,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
91
91
|
- !ruby/object:Gem::Version
|
|
92
92
|
version: '0'
|
|
93
93
|
requirements: []
|
|
94
|
-
rubygems_version: 4.0.
|
|
94
|
+
rubygems_version: 4.0.6
|
|
95
95
|
specification_version: 4
|
|
96
96
|
summary: Omaship command-line interface
|
|
97
97
|
test_files: []
|