nvoi 0.1.8 → 0.2.1
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/Gemfile +1 -5
- data/Gemfile.lock +17 -8
- data/Rakefile +1 -1
- data/_TODO-rails-example.md +816 -0
- data/_TODO-rails-optimization.md +433 -0
- data/doc/config-schema.yaml +12 -0
- data/examples/apex-wildcard/deploy.yml +1 -0
- data/examples/golang-postgres-multi/deploy.yml +1 -0
- data/examples/postgres-multi/deploy.yml +1 -0
- data/examples/postgres-single/deploy.yml +1 -0
- data/examples/rails-single/deploy.yml +1 -0
- data/lib/nvoi/cli/config/command.rb +46 -41
- data/lib/nvoi/cli/credentials/edit/command.rb +24 -20
- data/lib/nvoi/cli/credentials/show/command.rb +1 -1
- data/lib/nvoi/cli/db/command.rb +10 -10
- data/lib/nvoi/cli/delete/command.rb +2 -2
- data/lib/nvoi/cli/deploy/command.rb +2 -2
- data/lib/nvoi/cli/deploy/steps/build_image.rb +2 -1
- data/lib/nvoi/cli/deploy/steps/configure_tunnel.rb +2 -2
- data/lib/nvoi/cli/deploy/steps/deploy_service.rb +7 -4
- data/lib/nvoi/cli/deploy/steps/provision_server.rb +1 -1
- data/lib/nvoi/cli/deploy/steps/provision_volume.rb +1 -1
- data/lib/nvoi/cli/exec/command.rb +3 -3
- data/lib/nvoi/cli/logs/command.rb +2 -2
- data/lib/nvoi/cli/onboard/command.rb +176 -622
- data/lib/nvoi/cli/onboard/steps/app.rb +108 -0
- data/lib/nvoi/cli/onboard/steps/app_name.rb +26 -0
- data/lib/nvoi/cli/onboard/steps/compute.rb +186 -0
- data/lib/nvoi/cli/onboard/steps/database.rb +97 -0
- data/lib/nvoi/cli/onboard/steps/domain.rb +48 -0
- data/lib/nvoi/cli/onboard/steps/env.rb +67 -0
- data/lib/nvoi/cli/onboard/ui.rb +84 -0
- data/lib/nvoi/cli/unlock/command.rb +2 -2
- data/lib/nvoi/cli.rb +2 -33
- data/lib/nvoi/configuration/app_service.rb +54 -0
- data/lib/nvoi/configuration/application.rb +44 -0
- data/lib/nvoi/configuration/builder.rb +420 -0
- data/lib/nvoi/configuration/database.rb +56 -0
- data/lib/nvoi/configuration/deploy.rb +15 -0
- data/lib/nvoi/{objects/service_spec.rb → configuration/deployment.rb} +4 -3
- data/lib/nvoi/{objects/config_override.rb → configuration/override.rb} +4 -4
- data/lib/nvoi/configuration/providers.rb +81 -0
- data/lib/nvoi/configuration/result.rb +43 -0
- data/lib/nvoi/configuration/root.rb +252 -0
- data/lib/nvoi/configuration/server.rb +39 -0
- data/lib/nvoi/configuration/service.rb +51 -0
- data/lib/nvoi/configuration/ssh_key.rb +16 -0
- data/lib/nvoi/external/cloud/aws.rb +26 -16
- data/lib/nvoi/external/cloud/hetzner.rb +40 -25
- data/lib/nvoi/external/cloud/scaleway.rb +10 -8
- data/lib/nvoi/external/cloud/types.rb +42 -0
- data/lib/nvoi/external/database/mysql.rb +1 -1
- data/lib/nvoi/external/database/postgres.rb +1 -1
- data/lib/nvoi/external/database/provider.rb +1 -1
- data/lib/nvoi/external/database/sqlite.rb +1 -1
- data/lib/nvoi/external/database/types.rb +55 -0
- data/lib/nvoi/external/dns/cloudflare.rb +11 -11
- data/lib/nvoi/external/dns/types.rb +24 -0
- data/lib/nvoi/utils/config_loader.rb +12 -12
- data/lib/nvoi/utils/credential_store.rb +4 -4
- data/lib/nvoi/utils/env_resolver.rb +3 -3
- data/lib/nvoi/utils/namer.rb +8 -3
- data/lib/nvoi/utils/presence.rb +23 -0
- data/lib/nvoi/version.rb +1 -1
- data/lib/nvoi.rb +2 -17
- metadata +98 -59
- data/.claude/todo/refactor/00-overview.md +0 -171
- data/.claude/todo/refactor/01-objects.md +0 -96
- data/.claude/todo/refactor/02-utils.md +0 -143
- data/.claude/todo/refactor/03-external-cloud.md +0 -164
- data/.claude/todo/refactor/04-external-dns.md +0 -104
- data/.claude/todo/refactor/05-external.md +0 -133
- data/.claude/todo/refactor/06-cli.md +0 -123
- data/.claude/todo/refactor/07-cli-deploy-command.md +0 -177
- data/.claude/todo/refactor/08-cli-deploy-steps.md +0 -201
- data/.claude/todo/refactor/09-cli-delete-command.md +0 -169
- data/.claude/todo/refactor/10-cli-exec-command.md +0 -157
- data/.claude/todo/refactor/11-cli-credentials-command.md +0 -190
- data/.claude/todo/refactor/12-cli-db-command.md +0 -128
- data/.claude/todo/refactor/_target.md +0 -79
- data/.claude/todo/refactor-execution/00-entrypoint.md +0 -49
- data/.claude/todo/refactor-execution/01-objects.md +0 -42
- data/.claude/todo/refactor-execution/02-utils.md +0 -41
- data/.claude/todo/refactor-execution/03-external-cloud.md +0 -38
- data/.claude/todo/refactor-execution/04-external-dns.md +0 -35
- data/.claude/todo/refactor-execution/05-external-other.md +0 -46
- data/.claude/todo/refactor-execution/06-cli-deploy.md +0 -45
- data/.claude/todo/refactor-execution/07-cli-delete.md +0 -43
- data/.claude/todo/refactor-execution/08-cli-exec.md +0 -30
- data/.claude/todo/refactor-execution/09-cli-credentials.md +0 -34
- data/.claude/todo/refactor-execution/10-cli-db.md +0 -31
- data/.claude/todo/refactor-execution/11-cli-router.md +0 -44
- data/.claude/todo/refactor-execution/12-cleanup.md +0 -120
- data/.claude/todo/refactor-execution/_monitoring-strategy.md +0 -126
- data/.claude/todo/scaleway.impl.md +0 -644
- data/.claude/todo/scaleway.reference.md +0 -520
- data/.claude/todos/buckets.md +0 -41
- data/.claude/todos.md +0 -550
- data/Makefile +0 -26
- data/ingest +0 -0
- data/lib/nvoi/config_api/actions/app.rb +0 -53
- data/lib/nvoi/config_api/actions/compute_provider.rb +0 -55
- data/lib/nvoi/config_api/actions/database.rb +0 -70
- data/lib/nvoi/config_api/actions/domain_provider.rb +0 -40
- data/lib/nvoi/config_api/actions/env.rb +0 -32
- data/lib/nvoi/config_api/actions/init.rb +0 -67
- data/lib/nvoi/config_api/actions/secret.rb +0 -32
- data/lib/nvoi/config_api/actions/server.rb +0 -66
- data/lib/nvoi/config_api/actions/service.rb +0 -52
- data/lib/nvoi/config_api/actions/volume.rb +0 -40
- data/lib/nvoi/config_api/base.rb +0 -38
- data/lib/nvoi/config_api/result.rb +0 -26
- data/lib/nvoi/config_api.rb +0 -93
- data/lib/nvoi/objects/configuration.rb +0 -483
- data/lib/nvoi/objects/database.rb +0 -56
- data/lib/nvoi/objects/dns.rb +0 -14
- data/lib/nvoi/objects/firewall.rb +0 -11
- data/lib/nvoi/objects/network.rb +0 -11
- data/lib/nvoi/objects/server.rb +0 -14
- data/lib/nvoi/objects/tunnel.rb +0 -14
- data/lib/nvoi/objects/volume.rb +0 -17
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
# NVOI Gem - Rails Optimization TODO
|
|
2
|
+
|
|
3
|
+
Changes needed in the `nvoi` gem to support **optional** dashboard integration.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Modes
|
|
8
|
+
|
|
9
|
+
### Standalone Mode (default)
|
|
10
|
+
|
|
11
|
+
No `callback_url` in config. Gem works exactly as today:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
nvoi deploy
|
|
15
|
+
↓
|
|
16
|
+
logs to stdout
|
|
17
|
+
↓
|
|
18
|
+
done
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Dashboard Mode (optional)
|
|
22
|
+
|
|
23
|
+
When `callback_url` is set in config:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
nvoi deploy
|
|
27
|
+
↓
|
|
28
|
+
logs to stdout AND POSTs to callback_url
|
|
29
|
+
↓
|
|
30
|
+
Rails dashboard receives logs in real-time
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**The gem remains 100% standalone.** Dashboard integration is opt-in via config.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Architecture (Dashboard Mode)
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
CI (GitHub Actions, GitLab CI, etc.)
|
|
41
|
+
↓
|
|
42
|
+
gem install nvoi && nvoi deploy
|
|
43
|
+
↓
|
|
44
|
+
gem decrypts deploy.enc with DEPLOY_KEY
|
|
45
|
+
↓
|
|
46
|
+
gem POSTs logs to callback_url (signed with DEPLOY_KEY)
|
|
47
|
+
↓
|
|
48
|
+
Rails receives, stores, broadcasts via Turbo
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**One key, two purposes (when dashboard enabled):**
|
|
52
|
+
|
|
53
|
+
1. Decrypt `deploy.enc`
|
|
54
|
+
2. HMAC-sign API callbacks to Rails
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 1. Callback Configuration
|
|
59
|
+
|
|
60
|
+
Add optional callback URL to deploy config schema:
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
# lib/nvoi/configuration/deploy.rb
|
|
64
|
+
class Deploy
|
|
65
|
+
# Existing fields...
|
|
66
|
+
|
|
67
|
+
# New: callback URL for log streaming
|
|
68
|
+
def callback_url
|
|
69
|
+
@data["callback_url"]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def callback_enabled?
|
|
73
|
+
callback_url.present?
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Config example:
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
# In decrypted deploy config
|
|
82
|
+
callback_url: "https://myapp.com/api/deploys"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 2. HTTP Logger Adapter
|
|
88
|
+
|
|
89
|
+
New adapter that POSTs logs to Rails:
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
# lib/nvoi/adapters/logger/http.rb
|
|
93
|
+
module Nvoi
|
|
94
|
+
module Adapters
|
|
95
|
+
module Logger
|
|
96
|
+
class Http < Base
|
|
97
|
+
def initialize(url:, key:, deploy_id:, fallback: nil)
|
|
98
|
+
@url = url
|
|
99
|
+
@key = key
|
|
100
|
+
@deploy_id = deploy_id
|
|
101
|
+
@fallback = fallback || Stdout.new
|
|
102
|
+
@buffer = []
|
|
103
|
+
@flush_thread = start_flush_thread
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def info(message, *args)
|
|
107
|
+
log(:info, format_message(message, args))
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def success(message, *args)
|
|
111
|
+
log(:success, format_message(message, args))
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def error(message, *args)
|
|
115
|
+
log(:error, format_message(message, args))
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def warning(message, *args)
|
|
119
|
+
log(:warning, format_message(message, args))
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def step(message, *args)
|
|
123
|
+
log(:step, format_message(message, args))
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def ok(message, *args)
|
|
127
|
+
log(:ok, format_message(message, args))
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def flush
|
|
131
|
+
return if @buffer.empty?
|
|
132
|
+
|
|
133
|
+
logs = @buffer.dup
|
|
134
|
+
@buffer.clear
|
|
135
|
+
|
|
136
|
+
send_logs(logs)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def close
|
|
140
|
+
@flush_thread&.kill
|
|
141
|
+
flush
|
|
142
|
+
send_status(:completed)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def fail!(error_message)
|
|
146
|
+
flush
|
|
147
|
+
send_status(:failed, error: error_message)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
private
|
|
151
|
+
|
|
152
|
+
def log(level, message)
|
|
153
|
+
@fallback&.public_send(level, message)
|
|
154
|
+
|
|
155
|
+
@buffer << {
|
|
156
|
+
level: level,
|
|
157
|
+
message: message,
|
|
158
|
+
logged_at: Time.now.iso8601(3)
|
|
159
|
+
}
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def start_flush_thread
|
|
163
|
+
Thread.new do
|
|
164
|
+
loop do
|
|
165
|
+
sleep 1
|
|
166
|
+
flush
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def send_logs(logs)
|
|
172
|
+
payload = { logs: logs }
|
|
173
|
+
post("#{@url}/#{@deploy_id}/logs", payload)
|
|
174
|
+
rescue => e
|
|
175
|
+
@fallback&.warning("Callback failed: #{e.message}")
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def send_status(status, error: nil)
|
|
179
|
+
payload = { status: status, error: error }
|
|
180
|
+
post("#{@url}/#{@deploy_id}/status", payload)
|
|
181
|
+
rescue => e
|
|
182
|
+
@fallback&.warning("Status callback failed: #{e.message}")
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def post(url, payload)
|
|
186
|
+
body = payload.to_json
|
|
187
|
+
signature = sign(body)
|
|
188
|
+
|
|
189
|
+
uri = URI(url)
|
|
190
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
191
|
+
http.use_ssl = uri.scheme == "https"
|
|
192
|
+
|
|
193
|
+
request = Net::HTTP::Post.new(uri.path)
|
|
194
|
+
request["Content-Type"] = "application/json"
|
|
195
|
+
request["X-Nvoi-Signature"] = signature
|
|
196
|
+
request["X-Nvoi-Deploy-Id"] = @deploy_id
|
|
197
|
+
request.body = body
|
|
198
|
+
|
|
199
|
+
response = http.request(request)
|
|
200
|
+
|
|
201
|
+
unless response.is_a?(Net::HTTPSuccess)
|
|
202
|
+
raise "HTTP #{response.code}: #{response.body}"
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def sign(body)
|
|
207
|
+
"sha256=" + OpenSSL::HMAC.hexdigest("SHA256", @key, body)
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## 3. CLI Integration
|
|
218
|
+
|
|
219
|
+
Update deploy command to use HTTP logger when callback configured:
|
|
220
|
+
|
|
221
|
+
```ruby
|
|
222
|
+
# lib/nvoi/cli/deploy/command.rb
|
|
223
|
+
def run
|
|
224
|
+
@log = build_logger
|
|
225
|
+
|
|
226
|
+
# ... existing deploy logic ...
|
|
227
|
+
|
|
228
|
+
@log.close # flush remaining logs + send completed status
|
|
229
|
+
rescue => e
|
|
230
|
+
@log.fail!(e.message)
|
|
231
|
+
raise
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
private
|
|
235
|
+
|
|
236
|
+
def build_logger
|
|
237
|
+
if @config.callback_enabled?
|
|
238
|
+
deploy_id = ENV["NVOI_DEPLOY_ID"] || ENV["GITHUB_RUN_ID"] || SecureRandom.uuid
|
|
239
|
+
|
|
240
|
+
Adapters::Logger::Http.new(
|
|
241
|
+
url: @config.callback_url,
|
|
242
|
+
key: load_deploy_key,
|
|
243
|
+
deploy_id: deploy_id,
|
|
244
|
+
fallback: Utils::Logger.new # still print to stdout
|
|
245
|
+
)
|
|
246
|
+
else
|
|
247
|
+
Utils::Logger.new
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def load_deploy_key
|
|
252
|
+
key_path = resolve_key_path
|
|
253
|
+
File.read(key_path).strip
|
|
254
|
+
end
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## 4. Status Callbacks
|
|
260
|
+
|
|
261
|
+
Send deploy lifecycle events:
|
|
262
|
+
|
|
263
|
+
```ruby
|
|
264
|
+
# Callback payloads:
|
|
265
|
+
|
|
266
|
+
# POST /api/deploys/:id/logs
|
|
267
|
+
{
|
|
268
|
+
"logs": [
|
|
269
|
+
{ "level": "info", "message": "Starting deploy...", "logged_at": "2024-01-15T10:30:00.123Z" },
|
|
270
|
+
{ "level": "success", "message": "Server provisioned", "logged_at": "2024-01-15T10:30:05.456Z" }
|
|
271
|
+
]
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
# POST /api/deploys/:id/status
|
|
275
|
+
{
|
|
276
|
+
"status": "started",
|
|
277
|
+
"git_sha": "abc123",
|
|
278
|
+
"git_ref": "main",
|
|
279
|
+
"ci_provider": "github_actions",
|
|
280
|
+
"ci_run_url": "https://github.com/user/repo/actions/runs/12345"
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
# POST /api/deploys/:id/status (on complete)
|
|
284
|
+
{
|
|
285
|
+
"status": "completed",
|
|
286
|
+
"tunnels": [
|
|
287
|
+
{ "service_name": "web", "hostname": "www.example.com" }
|
|
288
|
+
],
|
|
289
|
+
"duration_seconds": 120
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
# POST /api/deploys/:id/status (on failure)
|
|
293
|
+
{
|
|
294
|
+
"status": "failed",
|
|
295
|
+
"error": "SSH connection failed"
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## 5. Delete Command Callbacks
|
|
302
|
+
|
|
303
|
+
Same pattern for delete:
|
|
304
|
+
|
|
305
|
+
```ruby
|
|
306
|
+
# lib/nvoi/cli/delete/command.rb
|
|
307
|
+
def run
|
|
308
|
+
@log = build_logger
|
|
309
|
+
send_status(:started)
|
|
310
|
+
|
|
311
|
+
# ... existing delete logic ...
|
|
312
|
+
|
|
313
|
+
send_status(:completed)
|
|
314
|
+
@log.close
|
|
315
|
+
rescue => e
|
|
316
|
+
send_status(:failed, error: e.message)
|
|
317
|
+
@log.close
|
|
318
|
+
raise
|
|
319
|
+
end
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## 6. Environment Variables
|
|
325
|
+
|
|
326
|
+
CI provides context:
|
|
327
|
+
|
|
328
|
+
| Variable | Source | Purpose |
|
|
329
|
+
| ------------------- | --------------------------- | ------------------------ |
|
|
330
|
+
| `NVOI_DEPLOY_ID` | Set by CI or auto-generated | Unique deploy identifier |
|
|
331
|
+
| `GITHUB_RUN_ID` | GitHub Actions | Fallback deploy ID |
|
|
332
|
+
| `GITHUB_SHA` | GitHub Actions | Git commit SHA |
|
|
333
|
+
| `GITHUB_REF_NAME` | GitHub Actions | Branch name |
|
|
334
|
+
| `GITHUB_SERVER_URL` | GitHub Actions | Build CI run URL |
|
|
335
|
+
| `GITHUB_REPOSITORY` | GitHub Actions | repo owner/name |
|
|
336
|
+
| `GITHUB_RUN_ID` | GitHub Actions | Run ID for URL |
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## 7. File Structure
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
lib/nvoi/
|
|
344
|
+
adapters/
|
|
345
|
+
logger/
|
|
346
|
+
base.rb
|
|
347
|
+
http.rb # NEW
|
|
348
|
+
stdout.rb # renamed from utils/logger.rb
|
|
349
|
+
null.rb
|
|
350
|
+
cli/
|
|
351
|
+
deploy/
|
|
352
|
+
command.rb # MODIFIED - use callback logger
|
|
353
|
+
delete/
|
|
354
|
+
command.rb # MODIFIED - use callback logger
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## 8. Onboard Wizard Enhancement
|
|
360
|
+
|
|
361
|
+
Add callback URL step:
|
|
362
|
+
|
|
363
|
+
```ruby
|
|
364
|
+
# lib/nvoi/cli/onboard/steps/callback_step.rb
|
|
365
|
+
class CallbackStep
|
|
366
|
+
def run(state)
|
|
367
|
+
use_callback = prompt.yes?("Stream deploy logs to a dashboard?")
|
|
368
|
+
return state unless use_callback
|
|
369
|
+
|
|
370
|
+
url = prompt.ask("Callback URL:", required: true)
|
|
371
|
+
|
|
372
|
+
state.merge(callback_url: url)
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## 9. Testing
|
|
380
|
+
|
|
381
|
+
```ruby
|
|
382
|
+
# test/nvoi/adapters/logger/http_test.rb
|
|
383
|
+
class HttpLoggerTest < Minitest::Test
|
|
384
|
+
def setup
|
|
385
|
+
@url = "https://example.com/api/deploys"
|
|
386
|
+
@key = "test-key-123"
|
|
387
|
+
@deploy_id = "run-456"
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def test_signs_requests_with_hmac
|
|
391
|
+
stub_request(:post, "#{@url}/#{@deploy_id}/logs")
|
|
392
|
+
.with { |req|
|
|
393
|
+
signature = req.headers["X-Nvoi-Signature"]
|
|
394
|
+
expected = "sha256=" + OpenSSL::HMAC.hexdigest("SHA256", @key, req.body)
|
|
395
|
+
signature == expected
|
|
396
|
+
}
|
|
397
|
+
.to_return(status: 200)
|
|
398
|
+
|
|
399
|
+
logger = Nvoi::Adapters::Logger::Http.new(
|
|
400
|
+
url: @url, key: @key, deploy_id: @deploy_id
|
|
401
|
+
)
|
|
402
|
+
logger.info("test")
|
|
403
|
+
logger.flush
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def test_buffers_and_flushes
|
|
407
|
+
stub = stub_request(:post, "#{@url}/#{@deploy_id}/logs")
|
|
408
|
+
.to_return(status: 200)
|
|
409
|
+
|
|
410
|
+
logger = Nvoi::Adapters::Logger::Http.new(
|
|
411
|
+
url: @url, key: @key, deploy_id: @deploy_id
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
logger.info("one")
|
|
415
|
+
logger.info("two")
|
|
416
|
+
logger.flush
|
|
417
|
+
|
|
418
|
+
assert_requested(stub, times: 1)
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## 10. Migration Path
|
|
426
|
+
|
|
427
|
+
1. Add HTTP logger adapter (non-breaking)
|
|
428
|
+
2. Add callback_url config option (non-breaking)
|
|
429
|
+
3. Update CLI to use callback logger when configured (non-breaking)
|
|
430
|
+
4. Update onboard wizard (non-breaking)
|
|
431
|
+
5. Release as 0.3.0
|
|
432
|
+
|
|
433
|
+
No breaking changes for existing CLI users.
|
data/doc/config-schema.yaml
CHANGED
|
@@ -127,6 +127,7 @@ components:
|
|
|
127
127
|
description: Hetzner Cloud provider configuration
|
|
128
128
|
required:
|
|
129
129
|
- api_token
|
|
130
|
+
- architecture
|
|
130
131
|
properties:
|
|
131
132
|
api_token:
|
|
132
133
|
type: string
|
|
@@ -141,6 +142,11 @@ components:
|
|
|
141
142
|
description: Default datacenter location
|
|
142
143
|
enum: [fsn1, nbg1, hel1, ash, hil]
|
|
143
144
|
example: fsn1
|
|
145
|
+
architecture:
|
|
146
|
+
type: string
|
|
147
|
+
description: CPU architecture for Docker builds
|
|
148
|
+
enum: [x86, arm64]
|
|
149
|
+
example: x86
|
|
144
150
|
|
|
145
151
|
AWSConfig:
|
|
146
152
|
type: object
|
|
@@ -149,6 +155,7 @@ components:
|
|
|
149
155
|
- access_key_id
|
|
150
156
|
- secret_access_key
|
|
151
157
|
- region
|
|
158
|
+
- architecture
|
|
152
159
|
properties:
|
|
153
160
|
access_key_id:
|
|
154
161
|
type: string
|
|
@@ -164,6 +171,11 @@ components:
|
|
|
164
171
|
type: string
|
|
165
172
|
description: Default EC2 instance type
|
|
166
173
|
example: t3.medium
|
|
174
|
+
architecture:
|
|
175
|
+
type: string
|
|
176
|
+
description: CPU architecture for Docker builds
|
|
177
|
+
enum: [x86, arm64]
|
|
178
|
+
example: x86
|
|
167
179
|
|
|
168
180
|
ServerConfig:
|
|
169
181
|
type: object
|
|
@@ -13,6 +13,7 @@ application:
|
|
|
13
13
|
api_token: $HETZNER_API_TOKEN
|
|
14
14
|
server_type: cx22 # Default for all servers
|
|
15
15
|
server_location: nbg1
|
|
16
|
+
architecture: x86
|
|
16
17
|
|
|
17
18
|
# Multi-instance server configuration: 3 servers total
|
|
18
19
|
# 1 master (K3s control plane) + 2 workers (app + database)
|