@rulebricks/cli 2.0.1 → 2.0.2
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.
- package/benchmarks/README.md +98 -0
- package/benchmarks/Test Flow.rbf +4088 -0
- package/benchmarks/benchmark-flow.json +26 -0
- package/benchmarks/lib/payload.js +101 -0
- package/benchmarks/lib/report.js +929 -0
- package/benchmarks/qps-test.js +136 -0
- package/benchmarks/run-qps-test.sh +115 -0
- package/benchmarks/run-throughput-test.sh +123 -0
- package/benchmarks/throughput-report.html +632 -0
- package/benchmarks/throughput-results.json +298 -0
- package/benchmarks/throughput-test.js +159 -0
- package/dist/commands/deploy.js +12 -1
- package/dist/components/Wizard/steps/BenchmarkSteps.js +2 -2
- package/package.json +5 -3
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
{
|
|
2
|
+
"root_group": {
|
|
3
|
+
"name": "",
|
|
4
|
+
"path": "",
|
|
5
|
+
"id": "d41d8cd98f00b204e9800998ecf8427e",
|
|
6
|
+
"groups": [],
|
|
7
|
+
"checks": [
|
|
8
|
+
{
|
|
9
|
+
"name": "status is 200",
|
|
10
|
+
"path": "::status is 200",
|
|
11
|
+
"id": "6210a8cd14cd70477eba5c5e4cb3fb5f",
|
|
12
|
+
"passes": 24000,
|
|
13
|
+
"fails": 0
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "valid response",
|
|
17
|
+
"path": "::valid response",
|
|
18
|
+
"id": "74e6940490a7b557672e61f02e36f4e8",
|
|
19
|
+
"passes": 24000,
|
|
20
|
+
"fails": 0
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "no error in response",
|
|
24
|
+
"path": "::no error in response",
|
|
25
|
+
"id": "04d657588d6c66446d4937ecba2292a2",
|
|
26
|
+
"passes": 24000,
|
|
27
|
+
"fails": 0
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
"options": {
|
|
32
|
+
"summaryTrendStats": [
|
|
33
|
+
"avg",
|
|
34
|
+
"min",
|
|
35
|
+
"med",
|
|
36
|
+
"max",
|
|
37
|
+
"p(90)",
|
|
38
|
+
"p(95)"
|
|
39
|
+
],
|
|
40
|
+
"summaryTimeUnit": "",
|
|
41
|
+
"noColor": false
|
|
42
|
+
},
|
|
43
|
+
"state": {
|
|
44
|
+
"isStdOutTTY": true,
|
|
45
|
+
"isStdErrTTY": true,
|
|
46
|
+
"testRunDurationMs": 300227.96
|
|
47
|
+
},
|
|
48
|
+
"metrics": {
|
|
49
|
+
"request_duration": {
|
|
50
|
+
"type": "trend",
|
|
51
|
+
"contains": "default",
|
|
52
|
+
"values": {
|
|
53
|
+
"p(95)": 318,
|
|
54
|
+
"avg": 207.51141666666666,
|
|
55
|
+
"min": 98,
|
|
56
|
+
"med": 195,
|
|
57
|
+
"max": 1305,
|
|
58
|
+
"p(90)": 285
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"http_req_sending": {
|
|
62
|
+
"values": {
|
|
63
|
+
"p(90)": 0.443,
|
|
64
|
+
"p(95)": 0.575,
|
|
65
|
+
"avg": 0.3505282157261422,
|
|
66
|
+
"min": 0.029,
|
|
67
|
+
"med": 0.265,
|
|
68
|
+
"max": 197.681
|
|
69
|
+
},
|
|
70
|
+
"type": "trend",
|
|
71
|
+
"contains": "time"
|
|
72
|
+
},
|
|
73
|
+
"http_req_failed": {
|
|
74
|
+
"type": "rate",
|
|
75
|
+
"contains": "default",
|
|
76
|
+
"values": {
|
|
77
|
+
"rate": 0,
|
|
78
|
+
"passes": 0,
|
|
79
|
+
"fails": 30001
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"checks": {
|
|
83
|
+
"type": "rate",
|
|
84
|
+
"contains": "default",
|
|
85
|
+
"values": {
|
|
86
|
+
"rate": 1,
|
|
87
|
+
"passes": 72000,
|
|
88
|
+
"fails": 0
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"successes": {
|
|
92
|
+
"type": "rate",
|
|
93
|
+
"contains": "default",
|
|
94
|
+
"values": {
|
|
95
|
+
"rate": 1,
|
|
96
|
+
"passes": 24000,
|
|
97
|
+
"fails": 0
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"http_req_blocked": {
|
|
101
|
+
"contains": "time",
|
|
102
|
+
"values": {
|
|
103
|
+
"med": 0.001,
|
|
104
|
+
"max": 446.733,
|
|
105
|
+
"p(90)": 0.001,
|
|
106
|
+
"p(95)": 0.002,
|
|
107
|
+
"avg": 1.6850438318703274,
|
|
108
|
+
"min": 0
|
|
109
|
+
},
|
|
110
|
+
"type": "trend"
|
|
111
|
+
},
|
|
112
|
+
"http_req_receiving": {
|
|
113
|
+
"type": "trend",
|
|
114
|
+
"contains": "time",
|
|
115
|
+
"values": {
|
|
116
|
+
"avg": 2.110890670310989,
|
|
117
|
+
"min": 0.019,
|
|
118
|
+
"med": 0.203,
|
|
119
|
+
"max": 206.634,
|
|
120
|
+
"p(90)": 3.99,
|
|
121
|
+
"p(95)": 5.81
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"http_req_duration": {
|
|
125
|
+
"values": {
|
|
126
|
+
"avg": 204.29118289390323,
|
|
127
|
+
"min": 97.82,
|
|
128
|
+
"med": 193.159,
|
|
129
|
+
"max": 990.433,
|
|
130
|
+
"p(90)": 283.411,
|
|
131
|
+
"p(95)": 316.351
|
|
132
|
+
},
|
|
133
|
+
"type": "trend",
|
|
134
|
+
"contains": "time"
|
|
135
|
+
},
|
|
136
|
+
"vus_max": {
|
|
137
|
+
"type": "gauge",
|
|
138
|
+
"contains": "default",
|
|
139
|
+
"values": {
|
|
140
|
+
"value": 200,
|
|
141
|
+
"min": 200,
|
|
142
|
+
"max": 200
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
"errors{phase:measurement}": {
|
|
146
|
+
"values": {
|
|
147
|
+
"rate": 0,
|
|
148
|
+
"passes": 0,
|
|
149
|
+
"fails": 24000
|
|
150
|
+
},
|
|
151
|
+
"thresholds": {
|
|
152
|
+
"rate<0.05": {
|
|
153
|
+
"ok": true
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
"type": "rate",
|
|
157
|
+
"contains": "default"
|
|
158
|
+
},
|
|
159
|
+
"http_reqs": {
|
|
160
|
+
"contains": "default",
|
|
161
|
+
"values": {
|
|
162
|
+
"count": 30001,
|
|
163
|
+
"rate": 99.9274018315949
|
|
164
|
+
},
|
|
165
|
+
"type": "counter"
|
|
166
|
+
},
|
|
167
|
+
"data_received": {
|
|
168
|
+
"type": "counter",
|
|
169
|
+
"contains": "data",
|
|
170
|
+
"values": {
|
|
171
|
+
"count": 409778192,
|
|
172
|
+
"rate": 1364890.172121211
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
"iterations": {
|
|
176
|
+
"type": "counter",
|
|
177
|
+
"contains": "default",
|
|
178
|
+
"values": {
|
|
179
|
+
"count": 30001,
|
|
180
|
+
"rate": 99.9274018315949
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
"data_sent": {
|
|
184
|
+
"type": "counter",
|
|
185
|
+
"contains": "data",
|
|
186
|
+
"values": {
|
|
187
|
+
"count": 104185619,
|
|
188
|
+
"rate": 347021.7064393336
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
"http_req_tls_handshaking": {
|
|
192
|
+
"type": "trend",
|
|
193
|
+
"contains": "time",
|
|
194
|
+
"values": {
|
|
195
|
+
"avg": 0.9106618112729572,
|
|
196
|
+
"min": 0,
|
|
197
|
+
"med": 0,
|
|
198
|
+
"max": 306.889,
|
|
199
|
+
"p(90)": 0,
|
|
200
|
+
"p(95)": 0
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
"http_req_waiting": {
|
|
204
|
+
"contains": "time",
|
|
205
|
+
"values": {
|
|
206
|
+
"p(90)": 280.835,
|
|
207
|
+
"p(95)": 313.283,
|
|
208
|
+
"avg": 201.82976400786623,
|
|
209
|
+
"min": 94.379,
|
|
210
|
+
"med": 190.745,
|
|
211
|
+
"max": 933.167
|
|
212
|
+
},
|
|
213
|
+
"type": "trend"
|
|
214
|
+
},
|
|
215
|
+
"iteration_duration": {
|
|
216
|
+
"type": "trend",
|
|
217
|
+
"contains": "time",
|
|
218
|
+
"values": {
|
|
219
|
+
"p(95)": 324.982625,
|
|
220
|
+
"avg": 209.38244802586436,
|
|
221
|
+
"min": 100.226958,
|
|
222
|
+
"med": 196.689375,
|
|
223
|
+
"max": 1306.521125,
|
|
224
|
+
"p(90)": 288.073125
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
"errors": {
|
|
228
|
+
"type": "rate",
|
|
229
|
+
"contains": "default",
|
|
230
|
+
"values": {
|
|
231
|
+
"rate": 0,
|
|
232
|
+
"passes": 0,
|
|
233
|
+
"fails": 24000
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
"http_req_duration{phase:measurement}": {
|
|
237
|
+
"type": "trend",
|
|
238
|
+
"contains": "time",
|
|
239
|
+
"values": {
|
|
240
|
+
"p(95)": 316.0782,
|
|
241
|
+
"avg": 205.77155337500048,
|
|
242
|
+
"min": 97.82,
|
|
243
|
+
"med": 194.721,
|
|
244
|
+
"max": 990.433,
|
|
245
|
+
"p(90)": 283.5602
|
|
246
|
+
},
|
|
247
|
+
"thresholds": {
|
|
248
|
+
"p(95)<2000": {
|
|
249
|
+
"ok": true
|
|
250
|
+
},
|
|
251
|
+
"p(99)<5000": {
|
|
252
|
+
"ok": true
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
"http_req_connecting": {
|
|
257
|
+
"type": "trend",
|
|
258
|
+
"contains": "time",
|
|
259
|
+
"values": {
|
|
260
|
+
"avg": 0.7645731142295258,
|
|
261
|
+
"min": 0,
|
|
262
|
+
"med": 0,
|
|
263
|
+
"max": 257.371,
|
|
264
|
+
"p(90)": 0,
|
|
265
|
+
"p(95)": 0
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
"http_req_duration{expected_response:true}": {
|
|
269
|
+
"contains": "time",
|
|
270
|
+
"values": {
|
|
271
|
+
"avg": 204.29118289390323,
|
|
272
|
+
"min": 97.82,
|
|
273
|
+
"med": 193.159,
|
|
274
|
+
"max": 990.433,
|
|
275
|
+
"p(90)": 283.411,
|
|
276
|
+
"p(95)": 316.351
|
|
277
|
+
},
|
|
278
|
+
"type": "trend"
|
|
279
|
+
},
|
|
280
|
+
"vus": {
|
|
281
|
+
"type": "gauge",
|
|
282
|
+
"contains": "default",
|
|
283
|
+
"values": {
|
|
284
|
+
"max": 71,
|
|
285
|
+
"value": 21,
|
|
286
|
+
"min": 13
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
"total_payloads": {
|
|
290
|
+
"contains": "default",
|
|
291
|
+
"values": {
|
|
292
|
+
"count": 1200000,
|
|
293
|
+
"rate": 3996.9628411690906
|
|
294
|
+
},
|
|
295
|
+
"type": "counter"
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Throughput (Solutions Per Second) Benchmark Test
|
|
3
|
+
*
|
|
4
|
+
* Measures rule engine capacity by sending bulk payload requests at a constant rate.
|
|
5
|
+
* This test helps you understand:
|
|
6
|
+
* - How many rule evaluations your deployment can process per second
|
|
7
|
+
* - Maximum throughput for batch workloads
|
|
8
|
+
* - Engine performance under sustained load
|
|
9
|
+
*
|
|
10
|
+
* Test Structure:
|
|
11
|
+
* - 1 minute warm-up phase (allows cluster to scale, excluded from results)
|
|
12
|
+
* - 4 minutes measurement phase (steady-state performance)
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* k6 run -e API_URL=https://your-instance.com/api/v1/flows/flow_id \
|
|
16
|
+
* -e API_KEY=your-api-key \
|
|
17
|
+
* throughput-test.js
|
|
18
|
+
*
|
|
19
|
+
* Optional environment variables:
|
|
20
|
+
* TEST_DURATION - Measurement duration after warm-up (default: 4m)
|
|
21
|
+
* TARGET_RPS - Target bulk requests per second (default: 100)
|
|
22
|
+
* BULK_SIZE - Number of payloads per request (default: 50)
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { check } from "k6";
|
|
26
|
+
import http from "k6/http";
|
|
27
|
+
import { Counter, Rate, Trend } from "k6/metrics";
|
|
28
|
+
import {
|
|
29
|
+
generateBulkPayload,
|
|
30
|
+
getConfig,
|
|
31
|
+
createRequestParams,
|
|
32
|
+
} from "./lib/payload.js";
|
|
33
|
+
import {
|
|
34
|
+
generateThroughputReport,
|
|
35
|
+
generateThroughputConsoleSummary,
|
|
36
|
+
} from "./lib/report.js";
|
|
37
|
+
|
|
38
|
+
// Load configuration
|
|
39
|
+
const config = getConfig({
|
|
40
|
+
testDuration: "4m",
|
|
41
|
+
targetRps: 100,
|
|
42
|
+
bulkSize: 50,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Custom metrics (only for measurement phase)
|
|
46
|
+
const errorRate = new Rate("errors");
|
|
47
|
+
const successRate = new Rate("successes");
|
|
48
|
+
const requestDuration = new Trend("request_duration");
|
|
49
|
+
const droppedRequests = new Counter("dropped_requests");
|
|
50
|
+
const totalPayloads = new Counter("total_payloads");
|
|
51
|
+
const failedPayloads = new Counter("failed_payloads");
|
|
52
|
+
|
|
53
|
+
// k6 options with warm-up and measurement phases
|
|
54
|
+
export const options = {
|
|
55
|
+
scenarios: {
|
|
56
|
+
// Warm-up phase: 1 minute to let cluster scale
|
|
57
|
+
warm_up: {
|
|
58
|
+
executor: "constant-arrival-rate",
|
|
59
|
+
rate: config.targetRps,
|
|
60
|
+
timeUnit: "1s",
|
|
61
|
+
duration: "1m",
|
|
62
|
+
preAllocatedVUs: Math.min(config.targetRps, 100),
|
|
63
|
+
maxVUs: Math.min(config.targetRps * 3, 500),
|
|
64
|
+
exec: "warmUp",
|
|
65
|
+
tags: { phase: "warmup" },
|
|
66
|
+
},
|
|
67
|
+
// Measurement phase: actual test after warm-up
|
|
68
|
+
throughput_test: {
|
|
69
|
+
executor: "constant-arrival-rate",
|
|
70
|
+
rate: config.targetRps,
|
|
71
|
+
timeUnit: "1s",
|
|
72
|
+
duration: config.testDuration,
|
|
73
|
+
preAllocatedVUs: Math.min(config.targetRps, 100),
|
|
74
|
+
maxVUs: Math.min(config.targetRps * 3, 500),
|
|
75
|
+
startTime: "1m", // Start after warm-up
|
|
76
|
+
exec: "measureTest",
|
|
77
|
+
tags: { phase: "measurement" },
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
thresholds: {
|
|
81
|
+
// Only apply thresholds to measurement phase
|
|
82
|
+
"http_req_duration{phase:measurement}": ["p(95)<2000", "p(99)<5000"],
|
|
83
|
+
"errors{phase:measurement}": ["rate<0.05"],
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Request parameters (longer timeout for bulk requests)
|
|
88
|
+
const params = createRequestParams(config.apiKey, "30s");
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Warm-up function - same as test but metrics tagged differently
|
|
92
|
+
*/
|
|
93
|
+
export function warmUp() {
|
|
94
|
+
const bulkPayload = generateBulkPayload(config.bulkSize);
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
http.post(config.apiUrl, JSON.stringify(bulkPayload), params);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
// Ignore errors during warm-up
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Measurement test function - sends bulk requests
|
|
105
|
+
*/
|
|
106
|
+
export function measureTest() {
|
|
107
|
+
const bulkPayload = generateBulkPayload(config.bulkSize);
|
|
108
|
+
const start = Date.now();
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const response = http.post(
|
|
112
|
+
config.apiUrl,
|
|
113
|
+
JSON.stringify(bulkPayload),
|
|
114
|
+
params
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const duration = Date.now() - start;
|
|
118
|
+
requestDuration.add(duration);
|
|
119
|
+
|
|
120
|
+
const success = check(response, {
|
|
121
|
+
"status is 200": (r) => r.status === 200,
|
|
122
|
+
"valid response": (r) => r.body && r.body.length > 0,
|
|
123
|
+
"no error in response": (r) => {
|
|
124
|
+
try {
|
|
125
|
+
const body = JSON.parse(r.body);
|
|
126
|
+
return !body.error;
|
|
127
|
+
} catch (e) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
errorRate.add(!success);
|
|
134
|
+
successRate.add(success);
|
|
135
|
+
totalPayloads.add(config.bulkSize);
|
|
136
|
+
|
|
137
|
+
if (!success) {
|
|
138
|
+
droppedRequests.add(1);
|
|
139
|
+
failedPayloads.add(config.bulkSize);
|
|
140
|
+
}
|
|
141
|
+
} catch (error) {
|
|
142
|
+
errorRate.add(1);
|
|
143
|
+
successRate.add(0);
|
|
144
|
+
droppedRequests.add(1);
|
|
145
|
+
totalPayloads.add(config.bulkSize);
|
|
146
|
+
failedPayloads.add(config.bulkSize);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Generate summary report
|
|
152
|
+
*/
|
|
153
|
+
export function handleSummary(data) {
|
|
154
|
+
return {
|
|
155
|
+
stdout: generateThroughputConsoleSummary(data, config),
|
|
156
|
+
"throughput-report.html": generateThroughputReport(data, config),
|
|
157
|
+
"throughput-results.json": JSON.stringify(data, null, 2),
|
|
158
|
+
};
|
|
159
|
+
}
|
package/dist/commands/deploy.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useEffect, useCallback, useRef } from "react";
|
|
3
3
|
import { Box, Text, useApp, useInput } from "ink";
|
|
4
|
+
import { platform } from "os";
|
|
4
5
|
import { BorderBox, Spinner, StatusLine, ThemeProvider, useTheme, Logo, } from "../components/common/index.js";
|
|
5
6
|
import { DNSWaitScreen } from "../components/DNSWaitScreen.js";
|
|
6
7
|
import { loadDeploymentConfig, loadDeploymentState, saveDeploymentState, updateDeploymentStatus, } from "../lib/config.js";
|
|
@@ -360,7 +361,7 @@ function DeployCommandInner({ name, skipInfra, skipDns, version, }) {
|
|
|
360
361
|
// Complete screen
|
|
361
362
|
if (step === "complete") {
|
|
362
363
|
const tlsSkipped = status.helmUpgradeTls === "skipped" && !useExternalDns;
|
|
363
|
-
return (_jsx(BorderBox, { title: "Deployment Complete", children: _jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { color: colors.success, bold: true, children: "\u2713 Rulebricks deployed successfully!" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { children: ["URL:", " ", _jsxs(Text, { color: colors.accent, children: ["https://", config?.domain, "/auth/signup"] })] }), useExternalDns && (_jsx(Text, { color: colors.muted, children: "DNS records will be created automatically by external-dns" })), tlsSkipped && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: colors.warning, children: ["\u26A0 TLS not configured. Run `rulebricks deploy ", name, "` again after DNS setup."] }) }))] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Next steps:" }), _jsxs(Text, { color: colors.muted, children: [" ", "\u2022 Visit the URL to complete initial setup"] }), _jsxs(Text, { color: colors.muted, children: [" ", "\u2022 Run `rulebricks status ", name, "` to check deployment health"] }), tlsSkipped && (_jsxs(Text, { color: colors.muted, children: [" ", "\u2022 Configure DNS and re-run deploy for TLS"] }))] })] }) }));
|
|
364
|
+
return (_jsx(BorderBox, { title: "Deployment Complete", children: _jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { color: colors.success, bold: true, children: "\u2713 Rulebricks deployed successfully!" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { children: ["URL:", " ", _jsxs(Text, { color: colors.accent, children: ["https://", config?.domain, "/auth/signup"] })] }), useExternalDns && (_jsx(Text, { color: colors.muted, children: "DNS records will be created automatically by external-dns" })), tlsSkipped && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: colors.warning, children: ["\u26A0 TLS not configured. Run `rulebricks deploy ", name, "` again after DNS setup."] }) }))] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Next steps:" }), _jsxs(Text, { color: colors.muted, children: [" ", "\u2022 Visit the URL to complete initial setup"] }), _jsxs(Text, { color: colors.muted, children: [" ", "\u2022 Run `rulebricks status ", name, "` to check deployment health"] }), tlsSkipped && (_jsxs(Text, { color: colors.muted, children: [" ", "\u2022 Configure DNS and re-run deploy for TLS"] }))] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: colors.muted, dimColor: true, children: "Tip: If the URL isn't accessible yet, your local DNS may need time to propagate." }), _jsxs(Text, { color: colors.muted, dimColor: true, children: ["Flush DNS cache: ", getDnsFlushCommand()] })] })] }) }));
|
|
364
365
|
}
|
|
365
366
|
// Progress screen
|
|
366
367
|
const helmInstallLabel = useExternalDns
|
|
@@ -376,6 +377,16 @@ function DeployCommandInner({ name, skipInfra, skipDns, version, }) {
|
|
|
376
377
|
? "Applying infrastructure"
|
|
377
378
|
: undefined }), _jsx(StatusLine, { status: status.kubeconfig, label: "Kubernetes configuration" }), _jsx(StatusLine, { status: status.helmInstall, label: helmInstallLabel }), !useExternalDns && (_jsxs(_Fragment, { children: [_jsx(StatusLine, { status: status.dnsConfig, label: "DNS configuration" }), _jsx(StatusLine, { status: status.helmUpgradeTls, label: "TLS configuration" })] })), step !== "dns-wait" && (_jsx(Box, { marginTop: 1, children: _jsx(Spinner, { label: getStepLabel(step, useExternalDns) }) }))] }) }));
|
|
378
379
|
}
|
|
380
|
+
function getDnsFlushCommand() {
|
|
381
|
+
switch (platform()) {
|
|
382
|
+
case "darwin":
|
|
383
|
+
return "sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder";
|
|
384
|
+
case "win32":
|
|
385
|
+
return "ipconfig /flushdns";
|
|
386
|
+
default:
|
|
387
|
+
return "sudo systemd-resolve --flush-caches";
|
|
388
|
+
}
|
|
389
|
+
}
|
|
379
390
|
function getStepLabel(step, useExternalDns) {
|
|
380
391
|
switch (step) {
|
|
381
392
|
case "loading":
|
|
@@ -175,7 +175,7 @@ export function TestModeStep({ onComplete, onBack, state }) {
|
|
|
175
175
|
...defaults,
|
|
176
176
|
});
|
|
177
177
|
};
|
|
178
|
-
return (_jsxs(BorderBox, { title: "Test Mode", children: [_jsx(Box, { flexDirection: "column", marginY: 1, children: _jsx(Text, { children: "Select the type of benchmark to run:" }) }), _jsx(SelectInput, { items: items, onSelect: handleSelect, itemComponent: ({ isSelected, label }) => {
|
|
178
|
+
return (_jsxs(BorderBox, { title: "Test Mode", children: [_jsx(Box, { flexDirection: "column", marginY: 1, children: _jsx(Text, { children: "Select the type of benchmark to run:" }) }), _jsx(SelectInput, { items: items, onSelect: handleSelect, indicatorComponent: () => null, itemComponent: ({ isSelected, label }) => {
|
|
179
179
|
const item = items.find((i) => i.label === label);
|
|
180
180
|
return (_jsxs(Box, { flexDirection: "column", marginY: isSelected ? 1 : 0, children: [_jsxs(Text, { color: isSelected ? colors.accent : undefined, bold: isSelected, children: [isSelected ? "❯ " : " ", label] }), isSelected && item && (_jsxs(Text, { color: colors.muted, dimColor: true, children: [" ", item.description] }))] }));
|
|
181
181
|
} }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.muted, dimColor: true, children: "Esc to go back \u2022 Enter to select" }) })] }));
|
|
@@ -262,7 +262,7 @@ export function PresetsStep({ onComplete, onBack, state }) {
|
|
|
262
262
|
if (customMode) {
|
|
263
263
|
return (_jsxs(BorderBox, { title: "Custom Configuration", children: [_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { children: "Configure your custom benchmark parameters:" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Box, { children: [_jsxs(Text, { color: activeField === "rps" ? colors.accent : undefined, children: [activeField === "rps" ? "❯ " : " ", "Target RPS:", " "] }), activeField === "rps" ? (_jsx(TextInput, { value: customRps, onChange: setCustomRps, onSubmit: handleCustomSubmit, placeholder: "e.g., 500" })) : (_jsx(Text, { children: customRps }))] }), _jsxs(Box, { children: [_jsxs(Text, { color: activeField === "duration" ? colors.accent : undefined, children: [activeField === "duration" ? "❯ " : " ", "Duration:", " "] }), activeField === "duration" ? (_jsx(TextInput, { value: customDuration, onChange: setCustomDuration, onSubmit: handleCustomSubmit, placeholder: "e.g., 4m" })) : (_jsx(Text, { children: customDuration }))] }), state.testMode === "throughput" && (_jsxs(Box, { children: [_jsxs(Text, { color: activeField === "bulkSize" ? colors.accent : undefined, children: [activeField === "bulkSize" ? "❯ " : " ", "Bulk Size:", " "] }), activeField === "bulkSize" ? (_jsx(TextInput, { value: customBulkSize, onChange: setCustomBulkSize, onSubmit: handleCustomSubmit, placeholder: "e.g., 50" })) : (_jsx(Text, { children: customBulkSize }))] }))] })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.muted, dimColor: true, children: "Tab to switch fields \u2022 Esc to go back \u2022 Enter to continue" }) })] }));
|
|
264
264
|
}
|
|
265
|
-
return (_jsxs(BorderBox, { title: "Test Presets", children: [_jsx(Box, { flexDirection: "column", marginY: 1, children: _jsxs(Text, { children: ["Select a preset for your ", state.testMode.toUpperCase(), " test:"] }) }), _jsx(SelectInput, { items: items, onSelect: handleSelect, itemComponent: ({ isSelected, label }) => {
|
|
265
|
+
return (_jsxs(BorderBox, { title: "Test Presets", children: [_jsx(Box, { flexDirection: "column", marginY: 1, children: _jsxs(Text, { children: ["Select a preset for your ", state.testMode.toUpperCase(), " test:"] }) }), _jsx(SelectInput, { items: items, onSelect: handleSelect, indicatorComponent: () => null, itemComponent: ({ isSelected, label }) => {
|
|
266
266
|
const item = items.find((i) => i.label === label);
|
|
267
267
|
return (_jsxs(Box, { flexDirection: "column", marginY: isSelected ? 1 : 0, children: [_jsxs(Text, { color: isSelected ? colors.accent : undefined, bold: isSelected, children: [isSelected ? "❯ " : " ", label] }), isSelected && item && (_jsxs(Text, { color: colors.muted, dimColor: true, children: [" ", item.description] }))] }));
|
|
268
268
|
} }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.muted, dimColor: true, children: "Esc to go back \u2022 Enter to select" }) })] }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulebricks/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "CLI for deploying and managing private Rulebricks instances",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -59,7 +59,8 @@
|
|
|
59
59
|
"pkg": {
|
|
60
60
|
"scripts": "dist/**/*.js",
|
|
61
61
|
"assets": [
|
|
62
|
-
"terraform/**/*"
|
|
62
|
+
"terraform/**/*",
|
|
63
|
+
"benchmarks/**/*"
|
|
63
64
|
],
|
|
64
65
|
"targets": [
|
|
65
66
|
"node20-linux-x64",
|
|
@@ -73,6 +74,7 @@
|
|
|
73
74
|
"files": [
|
|
74
75
|
"dist",
|
|
75
76
|
"terraform",
|
|
76
|
-
"templates"
|
|
77
|
+
"templates",
|
|
78
|
+
"benchmarks"
|
|
77
79
|
]
|
|
78
80
|
}
|