nvoi 0.1.8 → 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.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -5
  3. data/Gemfile.lock +17 -8
  4. data/Rakefile +1 -1
  5. data/lib/nvoi/cli/config/command.rb +46 -41
  6. data/lib/nvoi/cli/credentials/edit/command.rb +20 -20
  7. data/lib/nvoi/cli/credentials/show/command.rb +1 -1
  8. data/lib/nvoi/cli/db/command.rb +10 -10
  9. data/lib/nvoi/cli/delete/command.rb +2 -2
  10. data/lib/nvoi/cli/deploy/command.rb +2 -2
  11. data/lib/nvoi/cli/deploy/steps/configure_tunnel.rb +2 -2
  12. data/lib/nvoi/cli/deploy/steps/provision_server.rb +1 -1
  13. data/lib/nvoi/cli/deploy/steps/provision_volume.rb +1 -1
  14. data/lib/nvoi/cli/exec/command.rb +3 -3
  15. data/lib/nvoi/cli/logs/command.rb +2 -2
  16. data/lib/nvoi/cli/onboard/command.rb +176 -622
  17. data/lib/nvoi/cli/onboard/steps/app.rb +108 -0
  18. data/lib/nvoi/cli/onboard/steps/app_name.rb +26 -0
  19. data/lib/nvoi/cli/onboard/steps/compute.rb +139 -0
  20. data/lib/nvoi/cli/onboard/steps/database.rb +97 -0
  21. data/lib/nvoi/cli/onboard/steps/domain.rb +48 -0
  22. data/lib/nvoi/cli/onboard/steps/env.rb +67 -0
  23. data/lib/nvoi/cli/onboard/ui.rb +84 -0
  24. data/lib/nvoi/cli/unlock/command.rb +2 -2
  25. data/lib/nvoi/cli.rb +0 -32
  26. data/lib/nvoi/configuration/app_service.rb +54 -0
  27. data/lib/nvoi/configuration/application.rb +44 -0
  28. data/lib/nvoi/configuration/builder.rb +417 -0
  29. data/lib/nvoi/configuration/database.rb +56 -0
  30. data/lib/nvoi/configuration/deploy.rb +15 -0
  31. data/lib/nvoi/{objects/service_spec.rb → configuration/deployment.rb} +4 -3
  32. data/lib/nvoi/{objects/config_override.rb → configuration/override.rb} +4 -4
  33. data/lib/nvoi/configuration/providers.rb +78 -0
  34. data/lib/nvoi/configuration/result.rb +43 -0
  35. data/lib/nvoi/configuration/root.rb +234 -0
  36. data/lib/nvoi/configuration/server.rb +39 -0
  37. data/lib/nvoi/configuration/service.rb +62 -0
  38. data/lib/nvoi/external/cloud/aws.rb +12 -12
  39. data/lib/nvoi/external/cloud/hetzner.rb +7 -7
  40. data/lib/nvoi/external/cloud/scaleway.rb +7 -7
  41. data/lib/nvoi/external/cloud/types.rb +42 -0
  42. data/lib/nvoi/external/database/mysql.rb +1 -1
  43. data/lib/nvoi/external/database/postgres.rb +1 -1
  44. data/lib/nvoi/external/database/provider.rb +1 -1
  45. data/lib/nvoi/external/database/sqlite.rb +1 -1
  46. data/lib/nvoi/external/database/types.rb +55 -0
  47. data/lib/nvoi/external/dns/cloudflare.rb +6 -6
  48. data/lib/nvoi/external/dns/types.rb +24 -0
  49. data/lib/nvoi/utils/config_loader.rb +12 -12
  50. data/lib/nvoi/utils/credential_store.rb +4 -4
  51. data/lib/nvoi/utils/env_resolver.rb +3 -3
  52. data/lib/nvoi/utils/namer.rb +2 -2
  53. data/lib/nvoi/utils/presence.rb +23 -0
  54. data/lib/nvoi/version.rb +1 -1
  55. data/lib/nvoi.rb +2 -17
  56. metadata +95 -58
  57. data/.claude/todo/refactor/00-overview.md +0 -171
  58. data/.claude/todo/refactor/01-objects.md +0 -96
  59. data/.claude/todo/refactor/02-utils.md +0 -143
  60. data/.claude/todo/refactor/03-external-cloud.md +0 -164
  61. data/.claude/todo/refactor/04-external-dns.md +0 -104
  62. data/.claude/todo/refactor/05-external.md +0 -133
  63. data/.claude/todo/refactor/06-cli.md +0 -123
  64. data/.claude/todo/refactor/07-cli-deploy-command.md +0 -177
  65. data/.claude/todo/refactor/08-cli-deploy-steps.md +0 -201
  66. data/.claude/todo/refactor/09-cli-delete-command.md +0 -169
  67. data/.claude/todo/refactor/10-cli-exec-command.md +0 -157
  68. data/.claude/todo/refactor/11-cli-credentials-command.md +0 -190
  69. data/.claude/todo/refactor/12-cli-db-command.md +0 -128
  70. data/.claude/todo/refactor/_target.md +0 -79
  71. data/.claude/todo/refactor-execution/00-entrypoint.md +0 -49
  72. data/.claude/todo/refactor-execution/01-objects.md +0 -42
  73. data/.claude/todo/refactor-execution/02-utils.md +0 -41
  74. data/.claude/todo/refactor-execution/03-external-cloud.md +0 -38
  75. data/.claude/todo/refactor-execution/04-external-dns.md +0 -35
  76. data/.claude/todo/refactor-execution/05-external-other.md +0 -46
  77. data/.claude/todo/refactor-execution/06-cli-deploy.md +0 -45
  78. data/.claude/todo/refactor-execution/07-cli-delete.md +0 -43
  79. data/.claude/todo/refactor-execution/08-cli-exec.md +0 -30
  80. data/.claude/todo/refactor-execution/09-cli-credentials.md +0 -34
  81. data/.claude/todo/refactor-execution/10-cli-db.md +0 -31
  82. data/.claude/todo/refactor-execution/11-cli-router.md +0 -44
  83. data/.claude/todo/refactor-execution/12-cleanup.md +0 -120
  84. data/.claude/todo/refactor-execution/_monitoring-strategy.md +0 -126
  85. data/.claude/todo/scaleway.impl.md +0 -644
  86. data/.claude/todo/scaleway.reference.md +0 -520
  87. data/.claude/todos/buckets.md +0 -41
  88. data/.claude/todos.md +0 -550
  89. data/ingest +0 -0
  90. data/lib/nvoi/config_api/actions/app.rb +0 -53
  91. data/lib/nvoi/config_api/actions/compute_provider.rb +0 -55
  92. data/lib/nvoi/config_api/actions/database.rb +0 -70
  93. data/lib/nvoi/config_api/actions/domain_provider.rb +0 -40
  94. data/lib/nvoi/config_api/actions/env.rb +0 -32
  95. data/lib/nvoi/config_api/actions/init.rb +0 -67
  96. data/lib/nvoi/config_api/actions/secret.rb +0 -32
  97. data/lib/nvoi/config_api/actions/server.rb +0 -66
  98. data/lib/nvoi/config_api/actions/service.rb +0 -52
  99. data/lib/nvoi/config_api/actions/volume.rb +0 -40
  100. data/lib/nvoi/config_api/base.rb +0 -38
  101. data/lib/nvoi/config_api/result.rb +0 -26
  102. data/lib/nvoi/config_api.rb +0 -93
  103. data/lib/nvoi/objects/configuration.rb +0 -483
  104. data/lib/nvoi/objects/database.rb +0 -56
  105. data/lib/nvoi/objects/dns.rb +0 -14
  106. data/lib/nvoi/objects/firewall.rb +0 -11
  107. data/lib/nvoi/objects/network.rb +0 -11
  108. data/lib/nvoi/objects/server.rb +0 -14
  109. data/lib/nvoi/objects/tunnel.rb +0 -14
  110. data/lib/nvoi/objects/volume.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29c741e5b25ff6ab371cd67fa720bbfbe45d2edbb3f59cf060cbe22aadde790e
4
- data.tar.gz: dd4af8ac050b8ce0d95ed5a55a69f0e778ad015074df9860e33dce878f026334
3
+ metadata.gz: 3a77df0dc87230df49e67a6fe295594fd678626fe5c56bd1a13cbe3b83297784
4
+ data.tar.gz: ada2bac9b96a448105ecb9c48b1fede481a1bec883c4eadb01dd05a3f0edf64d
5
5
  SHA512:
6
- metadata.gz: 7764ee8e3a9bb39b3059798c49f2e8c8c42c9cd15e69ff0187d7bea84f6b8eea4e36c2d3d4d18db0ba90e3fdf52f4214981311a255e188d84c3c36cbdc6ea3aa
7
- data.tar.gz: 1b4d265fe116bb22967fcdba974cc0aea8d29fffb98f4ed41acc003eba4cd2a8de07218d04eb034e8ee1c37b06831c8334db88c63ba323ee0ef25b898148057e
6
+ metadata.gz: 5d30789748967c1dab8d0bc9069c135e476473168a5066018dc797c88e79cfc2f356cc1f64084cf3713b076c60f22b6d975098a3504534d3c14370129c923d55
7
+ data.tar.gz: cf31ca90acf5cf8a4c851a474d6efa9be23d0857571081b01b653bc631cceb9b2854b530c2ede54960262e5214a4f99f366a692fb6c2d71688dbc418f8fcb9a2
data/Gemfile CHANGED
@@ -7,9 +7,5 @@ gemspec
7
7
  group :development, :test do
8
8
  gem "rubocop-rails-omakase", require: false
9
9
  gem "simplecov", require: false
10
+ gem "minitest-reporters", require: false
10
11
  end
11
-
12
- gem "tty-prompt", "~> 0.23.1"
13
- gem "tty-box", "~> 0.7.0"
14
- gem "tty-spinner", "~> 0.9.3"
15
- gem "tty-table", "~> 0.12.0"
data/Gemfile.lock CHANGED
@@ -1,12 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nvoi (0.1.8)
4
+ nvoi (0.2.0)
5
5
  aws-sdk-ec2 (~> 1.400)
6
6
  faraday (~> 2.7)
7
7
  net-scp (~> 4.0)
8
8
  net-ssh (~> 7.2)
9
+ pastel (~> 0.8)
9
10
  thor (~> 1.3)
11
+ tty-box (~> 0.7)
12
+ tty-prompt (~> 0.23)
13
+ tty-spinner (~> 0.9)
14
+ tty-table (~> 0.12)
10
15
  zeitwerk (~> 2.6)
11
16
 
12
17
  GEM
@@ -27,9 +32,10 @@ GEM
27
32
  uri (>= 0.13.1)
28
33
  addressable (2.8.8)
29
34
  public_suffix (>= 2.0.2, < 8.0)
35
+ ansi (1.5.0)
30
36
  ast (2.4.3)
31
37
  aws-eventstream (1.4.0)
32
- aws-partitions (1.1192.0)
38
+ aws-partitions (1.1194.0)
33
39
  aws-sdk-core (3.239.2)
34
40
  aws-eventstream (~> 1, >= 1.3.0)
35
41
  aws-partitions (~> 1, >= 1.992.0)
@@ -45,6 +51,7 @@ GEM
45
51
  aws-eventstream (~> 1, >= 1.0.2)
46
52
  base64 (0.3.0)
47
53
  bigdecimal (3.3.1)
54
+ builder (3.3.0)
48
55
  concurrent-ruby (1.3.5)
49
56
  connection_pool (3.0.2)
50
57
  crack (1.0.1)
@@ -62,11 +69,16 @@ GEM
62
69
  i18n (1.14.7)
63
70
  concurrent-ruby (~> 1.0)
64
71
  jmespath (1.6.2)
65
- json (2.17.1)
72
+ json (2.18.0)
66
73
  language_server-protocol (3.17.0.5)
67
74
  lint_roller (1.1.0)
68
75
  logger (1.7.0)
69
- minitest (5.26.2)
76
+ minitest (5.27.0)
77
+ minitest-reporters (1.7.1)
78
+ ansi
79
+ builder
80
+ minitest (>= 5.0)
81
+ ruby-progressbar
70
82
  net-http (0.8.0)
71
83
  uri (>= 0.11.1)
72
84
  net-scp (4.1.0)
@@ -177,15 +189,12 @@ PLATFORMS
177
189
  DEPENDENCIES
178
190
  bundler (~> 2.0)
179
191
  minitest (~> 5.20)
192
+ minitest-reporters
180
193
  nvoi!
181
194
  rake (~> 13.0)
182
195
  rubocop (~> 1.57)
183
196
  rubocop-rails-omakase
184
197
  simplecov
185
- tty-box (~> 0.7.0)
186
- tty-prompt (~> 0.23.1)
187
- tty-spinner (~> 0.9.3)
188
- tty-table (~> 0.12.0)
189
198
  webmock (~> 3.19)
190
199
 
191
200
  BUNDLED WITH
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require "rubocop/rake_task"
7
7
  Rake::TestTask.new(:test) do |t|
8
8
  t.libs << "test"
9
9
  t.libs << "lib"
10
- t.test_files = FileList["test/**/*_test.rb", "test/**/test_*.rb"]
10
+ t.test_files = FileList["test/**/*_test.rb"]
11
11
  t.warning = false
12
12
  end
13
13
 
@@ -4,7 +4,7 @@ module Nvoi
4
4
  class Cli
5
5
  module Config
6
6
  # Command helper for all config operations
7
- # Uses CredentialStore for crypto, ConfigApi for transformations
7
+ # Uses CredentialStore for crypto, Configuration::Builder for transformations
8
8
  class Command
9
9
  def initialize(options)
10
10
  @options = options
@@ -13,7 +13,7 @@ module Nvoi
13
13
 
14
14
  # Initialize new config
15
15
  def init(name, environment)
16
- result = ConfigApi.init(name:, environment:)
16
+ result = Configuration::Builder.init(name:, environment:)
17
17
 
18
18
  if result.failure?
19
19
  error("Failed to initialize: #{result.error_message}")
@@ -40,118 +40,118 @@ module Nvoi
40
40
 
41
41
  # Domain provider
42
42
  def domain_set(provider, api_token:, account_id:)
43
- with_config do |data|
44
- ConfigApi.set_domain_provider(data, provider:, api_token:, account_id:)
43
+ with_config do |builder|
44
+ builder.domain_provider(provider, api_token:, account_id:)
45
45
  end
46
46
  end
47
47
 
48
48
  def domain_rm
49
- with_config do |data|
50
- ConfigApi.delete_domain_provider(data)
49
+ with_config do |builder|
50
+ builder.remove_domain_provider
51
51
  end
52
52
  end
53
53
 
54
54
  # Compute provider
55
55
  def provider_set(provider, **opts)
56
- with_config do |data|
57
- ConfigApi.set_compute_provider(data, provider:, **opts)
56
+ with_config do |builder|
57
+ builder.compute_provider(provider, **opts)
58
58
  end
59
59
  end
60
60
 
61
61
  def provider_rm
62
- with_config do |data|
63
- ConfigApi.delete_compute_provider(data)
62
+ with_config do |builder|
63
+ builder.remove_compute_provider
64
64
  end
65
65
  end
66
66
 
67
67
  # Server
68
68
  def server_set(name, master: false, type: nil, location: nil, count: 1)
69
- with_config do |data|
70
- ConfigApi.set_server(data, name:, master:, type:, location:, count:)
69
+ with_config do |builder|
70
+ builder.server(name, master:, type:, location:, count:)
71
71
  end
72
72
  end
73
73
 
74
74
  def server_rm(name)
75
- with_config do |data|
76
- ConfigApi.delete_server(data, name:)
75
+ with_config do |builder|
76
+ builder.remove_server(name)
77
77
  end
78
78
  end
79
79
 
80
80
  # Volume
81
81
  def volume_set(server, name, size: 10)
82
- with_config do |data|
83
- ConfigApi.set_volume(data, server:, name:, size:)
82
+ with_config do |builder|
83
+ builder.volume(server, name, size:)
84
84
  end
85
85
  end
86
86
 
87
87
  def volume_rm(server, name)
88
- with_config do |data|
89
- ConfigApi.delete_volume(data, server:, name:)
88
+ with_config do |builder|
89
+ builder.remove_volume(server, name)
90
90
  end
91
91
  end
92
92
 
93
93
  # App
94
94
  def app_set(name, servers:, **opts)
95
- with_config do |data|
96
- ConfigApi.set_app(data, name:, servers:, **opts)
95
+ with_config do |builder|
96
+ builder.app_entry(name, servers:, **opts)
97
97
  end
98
98
  end
99
99
 
100
100
  def app_rm(name)
101
- with_config do |data|
102
- ConfigApi.delete_app(data, name:)
101
+ with_config do |builder|
102
+ builder.remove_app(name)
103
103
  end
104
104
  end
105
105
 
106
106
  # Database
107
107
  def database_set(servers:, adapter:, **opts)
108
- with_config do |data|
109
- ConfigApi.set_database(data, servers:, adapter:, **opts)
108
+ with_config do |builder|
109
+ builder.database(servers:, adapter:, **opts)
110
110
  end
111
111
  end
112
112
 
113
113
  def database_rm
114
- with_config do |data|
115
- ConfigApi.delete_database(data)
114
+ with_config do |builder|
115
+ builder.remove_database
116
116
  end
117
117
  end
118
118
 
119
119
  # Service
120
120
  def service_set(name, servers:, image:, **opts)
121
- with_config do |data|
122
- ConfigApi.set_service(data, name:, servers:, image:, **opts)
121
+ with_config do |builder|
122
+ builder.service(name, servers:, image:, **opts)
123
123
  end
124
124
  end
125
125
 
126
126
  def service_rm(name)
127
- with_config do |data|
128
- ConfigApi.delete_service(data, name:)
127
+ with_config do |builder|
128
+ builder.remove_service(name)
129
129
  end
130
130
  end
131
131
 
132
132
  # Secret
133
133
  def secret_set(key_name, value)
134
- with_config do |data|
135
- ConfigApi.set_secret(data, key: key_name, value:)
134
+ with_config do |builder|
135
+ builder.secret(key_name, value)
136
136
  end
137
137
  end
138
138
 
139
139
  def secret_rm(key_name)
140
- with_config do |data|
141
- ConfigApi.delete_secret(data, key: key_name)
140
+ with_config do |builder|
141
+ builder.remove_secret(key_name)
142
142
  end
143
143
  end
144
144
 
145
145
  # Env
146
146
  def env_set(key_name, value)
147
- with_config do |data|
148
- ConfigApi.set_env(data, key: key_name, value:)
147
+ with_config do |builder|
148
+ builder.env(key_name, value)
149
149
  end
150
150
  end
151
151
 
152
152
  def env_rm(key_name)
153
- with_config do |data|
154
- ConfigApi.delete_env(data, key: key_name)
153
+ with_config do |builder|
154
+ builder.remove_env(key_name)
155
155
  end
156
156
  end
157
157
 
@@ -174,20 +174,25 @@ module Nvoi
174
174
  yaml = store.read
175
175
  data = YAML.safe_load(yaml, permitted_classes: [Symbol])
176
176
 
177
- # Transform
178
- result = yield(data)
177
+ # Transform using Builder
178
+ builder = Configuration::Builder.from_hash(data)
179
+ result = yield(builder)
179
180
 
180
181
  if result.failure?
181
182
  error("#{result.error_type}: #{result.error_message}")
182
183
  else
183
184
  # Serialize and write
184
- store.write(YAML.dump(result.data))
185
+ store.write(builder.to_yaml)
185
186
  success("Config updated")
186
187
  end
187
188
  rescue Errors::CredentialError => e
188
189
  error(e.message)
189
190
  rescue Errors::DecryptionError => e
190
191
  error("Decryption failed: #{e.message}")
192
+ rescue ArgumentError => e
193
+ error("invalid_args: #{e.message}")
194
+ rescue Errors::ConfigValidationError => e
195
+ error("validation_error: #{e.message}")
191
196
  end
192
197
 
193
198
  def update_gitignore
@@ -151,7 +151,7 @@ module Nvoi
151
151
 
152
152
  def resolve_working_dir
153
153
  wd = @options[:dir]
154
- if wd.nil? || wd.empty? || wd == "."
154
+ if wd.blank? || wd == "."
155
155
  Dir.pwd
156
156
  else
157
157
  File.expand_path(wd)
@@ -160,7 +160,7 @@ module Nvoi
160
160
 
161
161
  def resolve_enc_path(working_dir)
162
162
  enc_path = @options[:credentials]
163
- return File.join(working_dir, DEFAULT_ENCRYPTED_FILE) if enc_path.nil? || enc_path.empty?
163
+ return File.join(working_dir, DEFAULT_ENCRYPTED_FILE) if enc_path.blank?
164
164
 
165
165
  enc_path
166
166
  end
@@ -184,18 +184,18 @@ module Nvoi
184
184
  return "application section is required" unless app.is_a?(Hash)
185
185
 
186
186
  # Application name
187
- return "application.name is required" if app["name"].nil? || app["name"].to_s.empty?
187
+ return "application.name is required" if app["name"].blank?
188
188
 
189
189
  # Environment
190
- return "application.environment is required" if app["environment"].nil? || app["environment"].to_s.empty?
190
+ return "application.environment is required" if app["environment"].blank?
191
191
 
192
192
  # Domain provider
193
193
  domain_provider = app["domain_provider"]
194
194
  return "application.domain_provider.cloudflare is required" unless domain_provider&.dig("cloudflare")
195
195
 
196
196
  cf = domain_provider["cloudflare"]
197
- return "application.domain_provider.cloudflare.api_token is required" if cf["api_token"].nil? || cf["api_token"].to_s.empty?
198
- return "application.domain_provider.cloudflare.account_id is required" if cf["account_id"].nil? || cf["account_id"].to_s.empty?
197
+ return "application.domain_provider.cloudflare.api_token is required" if cf["api_token"].blank?
198
+ return "application.domain_provider.cloudflare.account_id is required" if cf["account_id"].blank?
199
199
 
200
200
  # Compute provider
201
201
  compute_provider = app["compute_provider"]
@@ -203,22 +203,22 @@ module Nvoi
203
203
  return "compute_provider (hetzner, aws, or scaleway) is required" unless has_compute
204
204
 
205
205
  if (h = compute_provider&.dig("hetzner"))
206
- return "application.compute_provider.hetzner.api_token is required" if h["api_token"].nil? || h["api_token"].to_s.empty?
207
- return "application.compute_provider.hetzner.server_type is required" if h["server_type"].nil? || h["server_type"].to_s.empty?
208
- return "application.compute_provider.hetzner.server_location is required" if h["server_location"].nil? || h["server_location"].to_s.empty?
206
+ return "application.compute_provider.hetzner.api_token is required" if h["api_token"].blank?
207
+ return "application.compute_provider.hetzner.server_type is required" if h["server_type"].blank?
208
+ return "application.compute_provider.hetzner.server_location is required" if h["server_location"].blank?
209
209
  end
210
210
 
211
211
  if (a = compute_provider&.dig("aws"))
212
- return "application.compute_provider.aws.access_key_id is required" if a["access_key_id"].nil? || a["access_key_id"].to_s.empty?
213
- return "application.compute_provider.aws.secret_access_key is required" if a["secret_access_key"].nil? || a["secret_access_key"].to_s.empty?
214
- return "application.compute_provider.aws.region is required" if a["region"].nil? || a["region"].to_s.empty?
215
- return "application.compute_provider.aws.instance_type is required" if a["instance_type"].nil? || a["instance_type"].to_s.empty?
212
+ return "application.compute_provider.aws.access_key_id is required" if a["access_key_id"].blank?
213
+ return "application.compute_provider.aws.secret_access_key is required" if a["secret_access_key"].blank?
214
+ return "application.compute_provider.aws.region is required" if a["region"].blank?
215
+ return "application.compute_provider.aws.instance_type is required" if a["instance_type"].blank?
216
216
  end
217
217
 
218
218
  if (s = compute_provider&.dig("scaleway"))
219
- return "application.compute_provider.scaleway.secret_key is required" if s["secret_key"].nil? || s["secret_key"].to_s.empty?
220
- return "application.compute_provider.scaleway.project_id is required" if s["project_id"].nil? || s["project_id"].to_s.empty?
221
- return "application.compute_provider.scaleway.server_type is required" if s["server_type"].nil? || s["server_type"].to_s.empty?
219
+ return "application.compute_provider.scaleway.secret_key is required" if s["secret_key"].blank?
220
+ return "application.compute_provider.scaleway.project_id is required" if s["project_id"].blank?
221
+ return "application.compute_provider.scaleway.server_type is required" if s["server_type"].blank?
222
222
  end
223
223
 
224
224
  # Servers (if any services defined)
@@ -236,7 +236,7 @@ module Nvoi
236
236
  app_services.each do |service_name, svc|
237
237
  next unless svc
238
238
 
239
- return "app.#{service_name}.servers is required" if svc["servers"].nil? || svc["servers"].empty?
239
+ return "app.#{service_name}.servers is required" if svc["servers"].to_a.empty?
240
240
 
241
241
  svc["servers"].each do |ref|
242
242
  return "app.#{service_name} references undefined server: #{ref}" unless defined_servers.include?(ref)
@@ -245,7 +245,7 @@ module Nvoi
245
245
 
246
246
  # Validate database
247
247
  if database
248
- return "database.servers is required" if database["servers"].nil? || database["servers"].empty?
248
+ return "database.servers is required" if database["servers"].to_a.empty?
249
249
 
250
250
  database["servers"].each do |ref|
251
251
  return "database references undefined server: #{ref}" unless defined_servers.include?(ref)
@@ -268,10 +268,10 @@ module Nvoi
268
268
  adapter = db["adapter"]&.downcase
269
269
  url = db["url"]
270
270
 
271
- return "database.adapter is required" if adapter.nil? || adapter.empty?
271
+ return "database.adapter is required" if adapter.blank?
272
272
 
273
273
  # URL takes precedence - if provided, no secrets needed
274
- has_url = url && !url.to_s.empty?
274
+ has_url = !url.blank?
275
275
 
276
276
  case adapter
277
277
  when "postgres", "postgresql"
@@ -22,7 +22,7 @@ module Nvoi
22
22
 
23
23
  def resolve_working_dir
24
24
  wd = @options[:dir]
25
- if wd.nil? || wd.empty? || wd == "."
25
+ if wd.blank? || wd == "."
26
26
  Dir.pwd
27
27
  else
28
28
  File.expand_path(wd)
@@ -60,7 +60,7 @@ module Nvoi
60
60
  result = ssh.execute("test -f #{metadata_file} && cat #{metadata_file} || echo '{}'")
61
61
 
62
62
  begin
63
- metadata = Objects::Database::BranchMetadata.from_json(result)
63
+ metadata = External::Database::Types::BranchMetadata.from_json(result)
64
64
  branches = metadata.branches
65
65
  rescue JSON::ParserError
66
66
  branches = []
@@ -185,9 +185,9 @@ module Nvoi
185
185
 
186
186
  def apply_branch_override
187
187
  branch = @options[:branch]
188
- return if branch.nil? || branch.empty?
188
+ return if branch.blank?
189
189
 
190
- override = Objects::ConfigOverride.new(branch:)
190
+ override = Configuration::Override.new(branch:)
191
191
  override.apply(@config)
192
192
  end
193
193
 
@@ -204,12 +204,12 @@ module Nvoi
204
204
 
205
205
  def build_dump_options
206
206
  if @db_provider.is_a?(External::Database::Sqlite)
207
- Objects::Database::DumpOptions.new(
207
+ External::Database::Types::DumpOptions.new(
208
208
  host_path: @creds.host_path,
209
209
  database: @creds.database
210
210
  )
211
211
  else
212
- Objects::Database::DumpOptions.new(
212
+ External::Database::Types::DumpOptions.new(
213
213
  pod_name: @config.namer.database_pod_name,
214
214
  database: @creds.database,
215
215
  user: @creds.user,
@@ -222,12 +222,12 @@ module Nvoi
222
222
  sanitized_name = sanitize_db_name(new_db_name)
223
223
 
224
224
  if @db_provider.is_a?(External::Database::Sqlite)
225
- Objects::Database::RestoreOptions.new(
225
+ External::Database::Types::RestoreOptions.new(
226
226
  host_path: @creds.host_path,
227
227
  database: sanitized_name
228
228
  )
229
229
  else
230
- Objects::Database::RestoreOptions.new(
230
+ External::Database::Types::RestoreOptions.new(
231
231
  pod_name: @config.namer.database_pod_name,
232
232
  database: sanitized_name,
233
233
  user: @creds.user,
@@ -255,12 +255,12 @@ module Nvoi
255
255
  result = ssh.execute("test -f #{metadata_file} && cat #{metadata_file} || echo '{}'")
256
256
 
257
257
  metadata = begin
258
- Objects::Database::BranchMetadata.from_json(result)
258
+ External::Database::Types::BranchMetadata.from_json(result)
259
259
  rescue JSON::ParserError
260
- Objects::Database::BranchMetadata.new
260
+ External::Database::Types::BranchMetadata.new
261
261
  end
262
262
 
263
- metadata.branches << Objects::Database::Branch.new(
263
+ metadata.branches << External::Database::Types::Branch.new(
264
264
  id: branch_id,
265
265
  created_at: Time.now.iso8601,
266
266
  size:,
@@ -64,9 +64,9 @@ module Nvoi
64
64
 
65
65
  def apply_branch_override
66
66
  branch = @options[:branch]
67
- return if branch.nil? || branch.empty?
67
+ return if branch.blank?
68
68
 
69
- override = Objects::ConfigOverride.new(branch:)
69
+ override = Configuration::Override.new(branch:)
70
70
  override.apply(@config)
71
71
  end
72
72
  end
@@ -65,9 +65,9 @@ module Nvoi
65
65
 
66
66
  def apply_branch_override
67
67
  branch = @options[:branch]
68
- return if branch.nil? || branch.empty?
68
+ return if branch.blank?
69
69
 
70
- override = Objects::ConfigOverride.new(branch:)
70
+ override = Configuration::Override.new(branch:)
71
71
  override.apply(@config)
72
72
  end
73
73
 
@@ -43,7 +43,7 @@ module Nvoi
43
43
 
44
44
  tunnel = setup_tunnel(tunnel_name, hostnames, service_url, service_config.domain)
45
45
 
46
- Objects::Tunnel::Info.new(
46
+ External::Dns::Types::Tunnel::Info.new(
47
47
  service_name:,
48
48
  hostname: primary_hostname,
49
49
  tunnel_id: tunnel.tunnel_id,
@@ -90,7 +90,7 @@ module Nvoi
90
90
 
91
91
  @log.success "Tunnel configured: %s", tunnel_name
92
92
 
93
- Objects::Tunnel::Info.new(
93
+ External::Dns::Types::Tunnel::Info.new(
94
94
  tunnel_id: tunnel.id,
95
95
  tunnel_token: token
96
96
  )
@@ -71,7 +71,7 @@ module Nvoi
71
71
  # Create cloud-init user data
72
72
  user_data = generate_user_data
73
73
 
74
- opts = Objects::Server::CreateOptions.new(
74
+ opts = External::Cloud::Types::Server::CreateOptions.new(
75
75
  name:,
76
76
  type: server_type,
77
77
  image:,
@@ -66,7 +66,7 @@ module Nvoi
66
66
  raise Errors::VolumeError, "server not found: #{vol_config[:server_name]}" unless server
67
67
 
68
68
  # Create volume
69
- opts = Objects::Volume::CreateOptions.new(
69
+ opts = External::Cloud::Types::Volume::CreateOptions.new(
70
70
  name: vol_config[:name],
71
71
  size: vol_config[:size],
72
72
  server_id: server.id
@@ -55,9 +55,9 @@ module Nvoi
55
55
 
56
56
  def apply_branch_override
57
57
  branch = @options[:branch]
58
- return if branch.nil? || branch.empty?
58
+ return if branch.blank?
59
59
 
60
- override = Objects::ConfigOverride.new(branch:)
60
+ override = Configuration::Override.new(branch:)
61
61
  override.apply(@config)
62
62
  end
63
63
 
@@ -132,7 +132,7 @@ module Nvoi
132
132
  end
133
133
 
134
134
  def resolve_server_name(name)
135
- return @config.server_name if name.nil? || name.empty? || name == "main"
135
+ return @config.server_name if name.blank? || name == "main"
136
136
 
137
137
  parts = name.split("-")
138
138
  if parts.length >= 2
@@ -55,9 +55,9 @@ module Nvoi
55
55
 
56
56
  def apply_branch_override
57
57
  branch = @options[:branch]
58
- return if branch.nil? || branch.empty?
58
+ return if branch.blank?
59
59
 
60
- override = Objects::ConfigOverride.new(branch:)
60
+ override = Configuration::Override.new(branch:)
61
61
  override.apply(@config)
62
62
  end
63
63
  end