@telora/daemon 0.15.12 → 0.15.15
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/build-info.json +2 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -50
- package/dist/config.js.map +1 -1
- package/dist/directive-executor.d.ts +92 -0
- package/dist/directive-executor.d.ts.map +1 -1
- package/dist/directive-executor.js +172 -11
- package/dist/directive-executor.js.map +1 -1
- package/dist/focus-engine.d.ts.map +1 -1
- package/dist/focus-engine.js +0 -43
- package/dist/focus-engine.js.map +1 -1
- package/dist/focus-executor.d.ts.map +1 -1
- package/dist/focus-executor.js +8 -2
- package/dist/focus-executor.js.map +1 -1
- package/dist/focus-lifecycle.d.ts +3 -4
- package/dist/focus-lifecycle.d.ts.map +1 -1
- package/dist/focus-lifecycle.js +6 -79
- package/dist/focus-lifecycle.js.map +1 -1
- package/dist/focus-phase.d.ts +26 -0
- package/dist/focus-phase.d.ts.map +1 -1
- package/dist/focus-phase.js +43 -0
- package/dist/focus-phase.js.map +1 -1
- package/dist/focus-provisioning.d.ts.map +1 -1
- package/dist/focus-provisioning.js +1 -7
- package/dist/focus-provisioning.js.map +1 -1
- package/dist/focus-worktree-state.d.ts.map +1 -1
- package/dist/focus-worktree-state.js +0 -1
- package/dist/focus-worktree-state.js.map +1 -1
- package/dist/listener.d.ts.map +1 -1
- package/dist/listener.js +0 -6
- package/dist/listener.js.map +1 -1
- package/dist/queries/focuses.d.ts +7 -3
- package/dist/queries/focuses.d.ts.map +1 -1
- package/dist/queries/focuses.js +8 -4
- package/dist/queries/focuses.js.map +1 -1
- package/dist/queries/shared.d.ts.map +1 -1
- package/dist/queries/shared.js +0 -3
- package/dist/queries/shared.js.map +1 -1
- package/dist/supabase.d.ts +1 -5
- package/dist/supabase.d.ts.map +1 -1
- package/dist/supabase.js +1 -9
- package/dist/supabase.js.map +1 -1
- package/dist/team-spawner.d.ts.map +1 -1
- package/dist/team-spawner.js +8 -2
- package/dist/team-spawner.js.map +1 -1
- package/dist/types/config.d.ts +0 -10
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/focus.d.ts +11 -2
- package/dist/types/focus.d.ts.map +1 -1
- package/dist/unified-shell-config.d.ts.map +1 -1
- package/dist/unified-shell-config.js +0 -39
- package/dist/unified-shell-config.js.map +1 -1
- package/package.json +1 -1
- package/dist/qa-crash-recovery.d.ts +0 -77
- package/dist/qa-crash-recovery.d.ts.map +0 -1
- package/dist/qa-crash-recovery.js +0 -243
- package/dist/qa-crash-recovery.js.map +0 -1
- package/dist/qa-dev-server.d.ts +0 -73
- package/dist/qa-dev-server.d.ts.map +0 -1
- package/dist/qa-dev-server.js +0 -279
- package/dist/qa-dev-server.js.map +0 -1
- package/dist/qa-orchestrator.d.ts +0 -107
- package/dist/qa-orchestrator.d.ts.map +0 -1
- package/dist/qa-orchestrator.js +0 -518
- package/dist/qa-orchestrator.js.map +0 -1
- package/dist/qa-port-allocator.d.ts +0 -34
- package/dist/qa-port-allocator.d.ts.map +0 -1
- package/dist/qa-port-allocator.js +0 -75
- package/dist/qa-port-allocator.js.map +0 -1
- package/dist/qa-provisioner.d.ts +0 -33
- package/dist/qa-provisioner.d.ts.map +0 -1
- package/dist/qa-provisioner.js +0 -139
- package/dist/qa-provisioner.js.map +0 -1
- package/dist/qa-state.d.ts +0 -118
- package/dist/qa-state.d.ts.map +0 -1
- package/dist/qa-state.js +0 -88
- package/dist/qa-state.js.map +0 -1
- package/dist/queries/qa.d.ts +0 -120
- package/dist/queries/qa.d.ts.map +0 -1
- package/dist/queries/qa.js +0 -118
- package/dist/queries/qa.js.map +0 -1
- package/dist/save-point-restore.d.ts +0 -35
- package/dist/save-point-restore.d.ts.map +0 -1
- package/dist/save-point-restore.js +0 -146
- package/dist/save-point-restore.js.map +0 -1
package/dist/qa-orchestrator.js
DELETED
|
@@ -1,518 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* QA environment orchestration.
|
|
3
|
-
*
|
|
4
|
-
* Called by the daemon poll loop to process pending QA requests.
|
|
5
|
-
* Coordinates provisioning and teardown using the lower-level modules.
|
|
6
|
-
*/
|
|
7
|
-
import { getQaRequests, updateQaStatus, getDeactivatedQaFocuses, getProductQaRequests, updateProductQaStatus, getSavePointQaRequests, updateSavePointQaStatus } from './supabase.js';
|
|
8
|
-
import { symlinkEnvFiles, createQaWorktree, removeQaWorktree } from './qa-provisioner.js';
|
|
9
|
-
import { getDefaultBranch } from './git-branch.js';
|
|
10
|
-
import { getFocusWorktree as getFocusWorktreeImpl } from './focus-worktree-state.js';
|
|
11
|
-
import { allocatePort, buildQaUrl } from './qa-port-allocator.js';
|
|
12
|
-
import { startQaDevServer, stopQaDevServer } from './qa-dev-server.js';
|
|
13
|
-
import { getQaEnvironment, setQaEnvironment, removeQaEnvironment, hasActiveQaEnvironment, getProductQaEnvironment, setProductQaEnvironment, removeProductQaEnvironment, hasActiveProductQaEnvironment, getSavePointQaEnvironment, setSavePointQaEnvironment, removeSavePointQaEnvironment, hasActiveSavePointQaEnvironment, } from './qa-state.js';
|
|
14
|
-
/** Default deps wired to real implementations. */
|
|
15
|
-
const defaultDeps = {
|
|
16
|
-
getQaRequests,
|
|
17
|
-
getDeactivatedQaFocuses,
|
|
18
|
-
updateQaStatus,
|
|
19
|
-
getFocusWorktree: getFocusWorktreeImpl,
|
|
20
|
-
symlinkEnvFiles,
|
|
21
|
-
allocatePort,
|
|
22
|
-
buildQaUrl,
|
|
23
|
-
startQaDevServer,
|
|
24
|
-
stopQaDevServer,
|
|
25
|
-
getQaEnvironment,
|
|
26
|
-
setQaEnvironment,
|
|
27
|
-
removeQaEnvironment,
|
|
28
|
-
hasActiveQaEnvironment,
|
|
29
|
-
};
|
|
30
|
-
/**
|
|
31
|
-
* Check for and process pending QA requests.
|
|
32
|
-
* Called each poll cycle from listener.ts.
|
|
33
|
-
*/
|
|
34
|
-
export async function checkQaRequests(config, deps = defaultDeps) {
|
|
35
|
-
let requests;
|
|
36
|
-
try {
|
|
37
|
-
requests = await deps.getQaRequests(config.productId);
|
|
38
|
-
}
|
|
39
|
-
catch (err) {
|
|
40
|
-
console.warn(`[qa] Failed to fetch QA requests: ${err.message}`);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if (requests.length === 0)
|
|
44
|
-
return;
|
|
45
|
-
for (const req of requests) {
|
|
46
|
-
try {
|
|
47
|
-
if (req.qa_status === 'requested') {
|
|
48
|
-
await handleQaProvision(config, req, deps);
|
|
49
|
-
}
|
|
50
|
-
else if (req.qa_status === 'stop_requested') {
|
|
51
|
-
await handleQaTeardown(config, req, deps);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
catch (err) {
|
|
55
|
-
console.error(`[qa] Error processing QA request for focus ${req.focus_name}: ${err.message}`);
|
|
56
|
-
// Update DB to failed state
|
|
57
|
-
try {
|
|
58
|
-
await deps.updateQaStatus(req.focus_id, {
|
|
59
|
-
qaStatus: 'failed',
|
|
60
|
-
qaError: err.message,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
catch (updateErr) {
|
|
64
|
-
console.warn(`[qa] Failed to update error state: ${updateErr.message}`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Provision a QA environment for a focus.
|
|
71
|
-
*
|
|
72
|
-
* 1. If already active (refresh case), tear down first.
|
|
73
|
-
* 2. Set DB status to 'provisioning'.
|
|
74
|
-
* 3. Allocate a port and create a worktree.
|
|
75
|
-
* 4. Install deps and start the dev server.
|
|
76
|
-
* 5. Update in-memory state and DB to 'ready'.
|
|
77
|
-
*/
|
|
78
|
-
async function handleQaProvision(config, req, deps) {
|
|
79
|
-
const { focus_id: focusId, focus_name: focusName } = req;
|
|
80
|
-
// If already active (refresh), tear down first
|
|
81
|
-
if (deps.hasActiveQaEnvironment(focusId)) {
|
|
82
|
-
console.log(`[qa] Refreshing QA environment for "${focusName}"`);
|
|
83
|
-
await handleQaTeardown(config, req, deps);
|
|
84
|
-
}
|
|
85
|
-
// 1. Set provisioning in DB
|
|
86
|
-
await deps.updateQaStatus(focusId, { qaStatus: 'provisioning' });
|
|
87
|
-
// 2. Allocate port
|
|
88
|
-
const port = await deps.allocatePort(config);
|
|
89
|
-
const url = deps.buildQaUrl(config, port);
|
|
90
|
-
// 3. Look up the persistent focus worktree (QA runs inside it)
|
|
91
|
-
const worktreeInfo = deps.getFocusWorktree(focusId);
|
|
92
|
-
if (!worktreeInfo) {
|
|
93
|
-
throw new Error(`No persistent worktree found for focus "${focusName}" (${focusId})`);
|
|
94
|
-
}
|
|
95
|
-
const worktreePath = worktreeInfo.worktreePath;
|
|
96
|
-
deps.symlinkEnvFiles(config.repoPath, worktreePath);
|
|
97
|
-
// 4. Track in memory (status provisioning, dev server not yet started)
|
|
98
|
-
const state = {
|
|
99
|
-
focusId,
|
|
100
|
-
focusName,
|
|
101
|
-
worktreePath,
|
|
102
|
-
pid: null,
|
|
103
|
-
port,
|
|
104
|
-
url,
|
|
105
|
-
status: 'provisioning',
|
|
106
|
-
createdAt: new Date(),
|
|
107
|
-
lastError: null,
|
|
108
|
-
};
|
|
109
|
-
deps.setQaEnvironment(focusId, state);
|
|
110
|
-
// 5. Start dev server (npm install + npm run dev)
|
|
111
|
-
const result = deps.startQaDevServer({
|
|
112
|
-
config,
|
|
113
|
-
focusId,
|
|
114
|
-
worktreePath,
|
|
115
|
-
port,
|
|
116
|
-
onUnexpectedExit: (error) => {
|
|
117
|
-
console.error(`[qa] Dev server crashed for "${focusName}": ${error}`);
|
|
118
|
-
deps.setQaEnvironment(focusId, { ...state, pid: null, status: 'failed', lastError: error });
|
|
119
|
-
deps.updateQaStatus(focusId, { qaStatus: 'failed', qaError: error }).catch((e) => {
|
|
120
|
-
console.warn(`[qa] Failed to report dev server crash: ${e.message}`);
|
|
121
|
-
});
|
|
122
|
-
},
|
|
123
|
-
});
|
|
124
|
-
// 6. Update state with PID and mark ready
|
|
125
|
-
const readyState = {
|
|
126
|
-
...state,
|
|
127
|
-
pid: result.pid,
|
|
128
|
-
status: 'ready',
|
|
129
|
-
};
|
|
130
|
-
deps.setQaEnvironment(focusId, readyState);
|
|
131
|
-
// 7. Update DB to ready
|
|
132
|
-
await deps.updateQaStatus(focusId, {
|
|
133
|
-
qaStatus: 'ready',
|
|
134
|
-
qaUrl: url,
|
|
135
|
-
qaPort: port,
|
|
136
|
-
qaWorktreePath: worktreePath,
|
|
137
|
-
qaReadyAt: new Date().toISOString(),
|
|
138
|
-
});
|
|
139
|
-
console.log(`[qa] QA environment ready for "${focusName}" at ${url}`);
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Tear down a QA environment for a focus.
|
|
143
|
-
*
|
|
144
|
-
* 1. Kill the dev server process if running.
|
|
145
|
-
* 2. Remove the worktree.
|
|
146
|
-
* 3. Clear in-memory and DB state.
|
|
147
|
-
*/
|
|
148
|
-
async function handleQaTeardown(config, req, deps) {
|
|
149
|
-
const { focus_id: focusId, focus_name: focusName } = req;
|
|
150
|
-
console.log(`[qa] Tearing down QA environment for "${focusName}"`);
|
|
151
|
-
// Kill dev server if running
|
|
152
|
-
const state = deps.getQaEnvironment(focusId);
|
|
153
|
-
if (state?.pid) {
|
|
154
|
-
await deps.stopQaDevServer(state.pid);
|
|
155
|
-
}
|
|
156
|
-
// Worktree is focus-owned -- do NOT remove here.
|
|
157
|
-
// Removal happens via coordinated teardown when the focus is deactivated.
|
|
158
|
-
// Clear in-memory state
|
|
159
|
-
deps.removeQaEnvironment(focusId);
|
|
160
|
-
// Clear DB state
|
|
161
|
-
await deps.updateQaStatus(focusId, {
|
|
162
|
-
qaStatus: null,
|
|
163
|
-
qaUrl: null,
|
|
164
|
-
qaPort: null,
|
|
165
|
-
qaWorktreePath: null,
|
|
166
|
-
qaReadyAt: null,
|
|
167
|
-
qaError: null,
|
|
168
|
-
});
|
|
169
|
-
console.log(`[qa] QA environment torn down for "${focusName}"`);
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Check for focuses that have been deactivated while QA was running.
|
|
173
|
-
* Tears down any QA environment whose focus is no longer in 'active' status.
|
|
174
|
-
* Called each poll cycle from listener.ts.
|
|
175
|
-
*/
|
|
176
|
-
export async function checkQaForDeactivatedFocuses(config, deps = defaultDeps) {
|
|
177
|
-
let deactivated;
|
|
178
|
-
try {
|
|
179
|
-
deactivated = await deps.getDeactivatedQaFocuses(config.productId);
|
|
180
|
-
}
|
|
181
|
-
catch (err) {
|
|
182
|
-
console.warn(`[qa] Failed to fetch deactivated QA focuses: ${err.message}`);
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
if (deactivated.length === 0)
|
|
186
|
-
return;
|
|
187
|
-
for (const focus of deactivated) {
|
|
188
|
-
console.log(`[qa] Focus "${focus.focus_name}" is ${focus.focus_status} but has QA state "${focus.qa_status}" -- tearing down`);
|
|
189
|
-
try {
|
|
190
|
-
await handleQaTeardown(config, {
|
|
191
|
-
focus_id: focus.focus_id,
|
|
192
|
-
focus_name: focus.focus_name,
|
|
193
|
-
qa_status: focus.qa_status,
|
|
194
|
-
product_id: focus.product_id,
|
|
195
|
-
}, deps);
|
|
196
|
-
}
|
|
197
|
-
catch (err) {
|
|
198
|
-
console.error(`[qa] Error tearing down QA for deactivated focus "${focus.focus_name}": ${err.message}`);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
/** Default deps wired to real implementations. */
|
|
203
|
-
const defaultProductDeps = {
|
|
204
|
-
getProductQaRequests,
|
|
205
|
-
updateProductQaStatus,
|
|
206
|
-
createQaWorktree,
|
|
207
|
-
removeQaWorktree,
|
|
208
|
-
symlinkEnvFiles,
|
|
209
|
-
allocatePort,
|
|
210
|
-
buildQaUrl,
|
|
211
|
-
startQaDevServer,
|
|
212
|
-
stopQaDevServer,
|
|
213
|
-
getProductQaEnvironment,
|
|
214
|
-
setProductQaEnvironment,
|
|
215
|
-
removeProductQaEnvironment,
|
|
216
|
-
hasActiveProductQaEnvironment,
|
|
217
|
-
};
|
|
218
|
-
/**
|
|
219
|
-
* Check for and process pending product QA requests.
|
|
220
|
-
* Called each poll cycle from listener.ts.
|
|
221
|
-
*/
|
|
222
|
-
export async function checkProductQaRequests(config, deps = defaultProductDeps) {
|
|
223
|
-
let requests;
|
|
224
|
-
try {
|
|
225
|
-
requests = await deps.getProductQaRequests(config.productId);
|
|
226
|
-
}
|
|
227
|
-
catch (err) {
|
|
228
|
-
console.warn(`[product-qa] Failed to fetch product QA requests: ${err.message}`);
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
if (requests.length === 0)
|
|
232
|
-
return;
|
|
233
|
-
for (const req of requests) {
|
|
234
|
-
try {
|
|
235
|
-
if (req.qa_status === 'requested') {
|
|
236
|
-
await handleProductQaProvision(config, req, deps);
|
|
237
|
-
}
|
|
238
|
-
else if (req.qa_status === 'refresh_requested') {
|
|
239
|
-
await handleProductQaRefresh(config, req, deps);
|
|
240
|
-
}
|
|
241
|
-
else if (req.qa_status === 'stop_requested') {
|
|
242
|
-
await handleProductQaTeardown(config, req, deps);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
catch (err) {
|
|
246
|
-
console.error(`[product-qa] Error processing product QA request for "${req.product_name}": ${err.message}`);
|
|
247
|
-
try {
|
|
248
|
-
await deps.updateProductQaStatus(req.product_id, {
|
|
249
|
-
qaStatus: 'failed',
|
|
250
|
-
qaError: err.message,
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
catch (updateErr) {
|
|
254
|
-
console.warn(`[product-qa] Failed to update error state: ${updateErr.message}`);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Provision a product-level QA environment.
|
|
261
|
-
*
|
|
262
|
-
* Creates a QA worktree on the default branch (main) so the dev server
|
|
263
|
-
* reflects the latest promoted state of the product.
|
|
264
|
-
*/
|
|
265
|
-
async function handleProductQaProvision(config, req, deps) {
|
|
266
|
-
const { product_id: productId, product_name: productName } = req;
|
|
267
|
-
// If already active (refresh), tear down first
|
|
268
|
-
if (deps.hasActiveProductQaEnvironment(productId)) {
|
|
269
|
-
console.log(`[product-qa] Refreshing QA environment for product "${productName}"`);
|
|
270
|
-
await handleProductQaTeardown(config, req, deps);
|
|
271
|
-
}
|
|
272
|
-
// 1. Set provisioning in DB
|
|
273
|
-
await deps.updateProductQaStatus(productId, { qaStatus: 'provisioning' });
|
|
274
|
-
// 2. Allocate port
|
|
275
|
-
const port = await deps.allocatePort(config);
|
|
276
|
-
const url = deps.buildQaUrl(config, port);
|
|
277
|
-
// 3. Create QA worktree on default branch (main)
|
|
278
|
-
const defaultBranch = getDefaultBranch(config.repoPath);
|
|
279
|
-
const worktreePath = deps.createQaWorktree(config, defaultBranch, `product-${productId}`);
|
|
280
|
-
deps.symlinkEnvFiles(config.repoPath, worktreePath);
|
|
281
|
-
// 4. Track in memory
|
|
282
|
-
const state = {
|
|
283
|
-
productId,
|
|
284
|
-
productName,
|
|
285
|
-
worktreePath,
|
|
286
|
-
pid: null,
|
|
287
|
-
port,
|
|
288
|
-
url,
|
|
289
|
-
status: 'provisioning',
|
|
290
|
-
createdAt: new Date(),
|
|
291
|
-
lastError: null,
|
|
292
|
-
};
|
|
293
|
-
deps.setProductQaEnvironment(productId, state);
|
|
294
|
-
// 5. Start dev server in integration worktree
|
|
295
|
-
const result = deps.startQaDevServer({
|
|
296
|
-
config,
|
|
297
|
-
focusId: `product-${productId}`,
|
|
298
|
-
worktreePath,
|
|
299
|
-
port,
|
|
300
|
-
onUnexpectedExit: (error) => {
|
|
301
|
-
console.error(`[product-qa] Dev server crashed for product "${productName}": ${error}`);
|
|
302
|
-
deps.setProductQaEnvironment(productId, { ...state, pid: null, status: 'failed', lastError: error });
|
|
303
|
-
deps.updateProductQaStatus(productId, { qaStatus: 'failed', qaError: error }).catch((e) => {
|
|
304
|
-
console.warn(`[product-qa] Failed to report dev server crash: ${e.message}`);
|
|
305
|
-
});
|
|
306
|
-
},
|
|
307
|
-
});
|
|
308
|
-
// 6. Update state with PID and mark ready
|
|
309
|
-
const readyState = {
|
|
310
|
-
...state,
|
|
311
|
-
pid: result.pid,
|
|
312
|
-
status: 'ready',
|
|
313
|
-
};
|
|
314
|
-
deps.setProductQaEnvironment(productId, readyState);
|
|
315
|
-
// 7. Update DB to ready
|
|
316
|
-
await deps.updateProductQaStatus(productId, {
|
|
317
|
-
qaStatus: 'ready',
|
|
318
|
-
qaUrl: url,
|
|
319
|
-
qaPort: port,
|
|
320
|
-
qaWorktreePath: worktreePath,
|
|
321
|
-
qaReadyAt: new Date().toISOString(),
|
|
322
|
-
});
|
|
323
|
-
console.log(`[product-qa] QA environment ready for product "${productName}" at ${url} (${defaultBranch})`);
|
|
324
|
-
}
|
|
325
|
-
/**
|
|
326
|
-
* Lightweight refresh of a product-level QA environment.
|
|
327
|
-
* Updates the worktree to the latest commit on the default branch
|
|
328
|
-
* without restarting the dev server (Vite picks up changes via HMR).
|
|
329
|
-
*/
|
|
330
|
-
async function handleProductQaRefresh(config, req, deps) {
|
|
331
|
-
const { product_id: productId, product_name: productName } = req;
|
|
332
|
-
const envState = deps.getProductQaEnvironment(productId);
|
|
333
|
-
if (!envState?.worktreePath) {
|
|
334
|
-
console.warn(`[product-qa] No active QA environment to refresh for "${productName}", falling back to full provision`);
|
|
335
|
-
await handleProductQaProvision(config, req, deps);
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
console.log(`[product-qa] Refreshing worktree for product "${productName}"`);
|
|
339
|
-
// Update worktree to latest commit on default branch (detached HEAD checkout)
|
|
340
|
-
const defaultBranch = getDefaultBranch(config.repoPath);
|
|
341
|
-
deps.createQaWorktree(config, defaultBranch, `product-${productId}`);
|
|
342
|
-
// Set back to ready
|
|
343
|
-
await deps.updateProductQaStatus(productId, { qaStatus: 'ready' });
|
|
344
|
-
console.log(`[product-qa] QA worktree refreshed for product "${productName}" (${defaultBranch})`);
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* Tear down a product-level QA environment.
|
|
348
|
-
* Kills the dev server and removes the integration worktree.
|
|
349
|
-
*/
|
|
350
|
-
async function handleProductQaTeardown(config, req, deps) {
|
|
351
|
-
const { product_id: productId, product_name: productName } = req;
|
|
352
|
-
console.log(`[product-qa] Tearing down QA environment for product "${productName}"`);
|
|
353
|
-
// Kill dev server if running
|
|
354
|
-
const state = deps.getProductQaEnvironment(productId);
|
|
355
|
-
if (state?.pid) {
|
|
356
|
-
await deps.stopQaDevServer(state.pid);
|
|
357
|
-
}
|
|
358
|
-
// Remove QA worktree (read-only checkout, no safety commits needed)
|
|
359
|
-
if (state?.worktreePath) {
|
|
360
|
-
deps.removeQaWorktree(config.repoPath, state.worktreePath);
|
|
361
|
-
}
|
|
362
|
-
// Clear in-memory state
|
|
363
|
-
deps.removeProductQaEnvironment(productId);
|
|
364
|
-
// Clear DB state
|
|
365
|
-
await deps.updateProductQaStatus(productId, {
|
|
366
|
-
qaStatus: null,
|
|
367
|
-
qaUrl: null,
|
|
368
|
-
qaPort: null,
|
|
369
|
-
qaWorktreePath: null,
|
|
370
|
-
qaReadyAt: null,
|
|
371
|
-
qaError: null,
|
|
372
|
-
});
|
|
373
|
-
console.log(`[product-qa] QA environment torn down for product "${productName}"`);
|
|
374
|
-
}
|
|
375
|
-
/** Default deps wired to real implementations. */
|
|
376
|
-
const defaultSavePointDeps = {
|
|
377
|
-
getSavePointQaRequests,
|
|
378
|
-
updateSavePointQaStatus,
|
|
379
|
-
symlinkEnvFiles,
|
|
380
|
-
allocatePort,
|
|
381
|
-
buildQaUrl,
|
|
382
|
-
startQaDevServer,
|
|
383
|
-
stopQaDevServer,
|
|
384
|
-
getSavePointQaEnvironment,
|
|
385
|
-
setSavePointQaEnvironment,
|
|
386
|
-
removeSavePointQaEnvironment,
|
|
387
|
-
hasActiveSavePointQaEnvironment,
|
|
388
|
-
};
|
|
389
|
-
/**
|
|
390
|
-
* Check for and process pending save point QA requests.
|
|
391
|
-
* Called each poll cycle from listener.ts.
|
|
392
|
-
*/
|
|
393
|
-
export async function checkSavePointQaRequests(config, deps = defaultSavePointDeps) {
|
|
394
|
-
let requests;
|
|
395
|
-
try {
|
|
396
|
-
requests = await deps.getSavePointQaRequests(config.productId);
|
|
397
|
-
}
|
|
398
|
-
catch (err) {
|
|
399
|
-
console.warn(`[save-point-qa] Failed to fetch save point QA requests: ${err.message}`);
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
if (requests.length === 0)
|
|
403
|
-
return;
|
|
404
|
-
for (const req of requests) {
|
|
405
|
-
try {
|
|
406
|
-
if (req.qa_status === 'requested') {
|
|
407
|
-
await handleSavePointQaProvision(config, req, deps);
|
|
408
|
-
}
|
|
409
|
-
else if (req.qa_status === 'stop_requested') {
|
|
410
|
-
await handleSavePointQaTeardown(config, req, deps);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
catch (err) {
|
|
414
|
-
console.error(`[save-point-qa] Error processing QA request for save point "${req.name}": ${err.message}`);
|
|
415
|
-
try {
|
|
416
|
-
await deps.updateSavePointQaStatus(req.save_point_id, {
|
|
417
|
-
qaStatus: 'failed',
|
|
418
|
-
qaError: err.message,
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
catch (updateErr) {
|
|
422
|
-
console.warn(`[save-point-qa] Failed to update error state: ${updateErr.message}`);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
/**
|
|
428
|
-
* Provision a QA environment for a save point.
|
|
429
|
-
*
|
|
430
|
-
* The worktree already exists (created by MCP view action).
|
|
431
|
-
* We just need to start a dev server in it.
|
|
432
|
-
*/
|
|
433
|
-
async function handleSavePointQaProvision(config, req, deps) {
|
|
434
|
-
const { save_point_id: savePointId, name: spName, worktree_path: worktreePath } = req;
|
|
435
|
-
if (!worktreePath) {
|
|
436
|
-
throw new Error(`Save point "${spName}" has no active worktree -- view it first`);
|
|
437
|
-
}
|
|
438
|
-
// If already active (refresh), tear down first
|
|
439
|
-
if (deps.hasActiveSavePointQaEnvironment(savePointId)) {
|
|
440
|
-
console.log(`[save-point-qa] Refreshing QA environment for "${spName}"`);
|
|
441
|
-
await handleSavePointQaTeardown(config, req, deps);
|
|
442
|
-
}
|
|
443
|
-
// 1. Set provisioning in DB
|
|
444
|
-
await deps.updateSavePointQaStatus(savePointId, { qaStatus: 'provisioning' });
|
|
445
|
-
// 2. Allocate port
|
|
446
|
-
const port = await deps.allocatePort(config);
|
|
447
|
-
const url = deps.buildQaUrl(config, port);
|
|
448
|
-
// 3. Symlink env files into the worktree
|
|
449
|
-
deps.symlinkEnvFiles(config.repoPath, worktreePath);
|
|
450
|
-
// 4. Track in memory
|
|
451
|
-
const state = {
|
|
452
|
-
savePointId,
|
|
453
|
-
name: spName,
|
|
454
|
-
worktreePath,
|
|
455
|
-
pid: null,
|
|
456
|
-
port,
|
|
457
|
-
url,
|
|
458
|
-
status: 'provisioning',
|
|
459
|
-
createdAt: new Date(),
|
|
460
|
-
lastError: null,
|
|
461
|
-
};
|
|
462
|
-
deps.setSavePointQaEnvironment(savePointId, state);
|
|
463
|
-
// 5. Start dev server
|
|
464
|
-
const result = deps.startQaDevServer({
|
|
465
|
-
config,
|
|
466
|
-
focusId: `save-point-${savePointId}`,
|
|
467
|
-
worktreePath,
|
|
468
|
-
port,
|
|
469
|
-
onUnexpectedExit: (error) => {
|
|
470
|
-
console.error(`[save-point-qa] Dev server crashed for "${spName}": ${error}`);
|
|
471
|
-
deps.setSavePointQaEnvironment(savePointId, { ...state, pid: null, status: 'failed', lastError: error });
|
|
472
|
-
deps.updateSavePointQaStatus(savePointId, { qaStatus: 'failed', qaError: error }).catch((e) => {
|
|
473
|
-
console.warn(`[save-point-qa] Failed to report dev server crash: ${e.message}`);
|
|
474
|
-
});
|
|
475
|
-
},
|
|
476
|
-
});
|
|
477
|
-
// 6. Update state with PID and mark ready
|
|
478
|
-
const readyState = {
|
|
479
|
-
...state,
|
|
480
|
-
pid: result.pid,
|
|
481
|
-
status: 'ready',
|
|
482
|
-
};
|
|
483
|
-
deps.setSavePointQaEnvironment(savePointId, readyState);
|
|
484
|
-
// 7. Update DB to ready
|
|
485
|
-
await deps.updateSavePointQaStatus(savePointId, {
|
|
486
|
-
qaStatus: 'ready',
|
|
487
|
-
qaUrl: url,
|
|
488
|
-
qaPort: port,
|
|
489
|
-
qaReadyAt: new Date().toISOString(),
|
|
490
|
-
});
|
|
491
|
-
console.log(`[save-point-qa] QA environment ready for "${spName}" at ${url}`);
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* Tear down a save point QA environment.
|
|
495
|
-
* Kills the dev server but does NOT remove the worktree
|
|
496
|
-
* (that's managed by the MCP close action).
|
|
497
|
-
*/
|
|
498
|
-
async function handleSavePointQaTeardown(config, req, deps) {
|
|
499
|
-
const { save_point_id: savePointId, name: spName } = req;
|
|
500
|
-
console.log(`[save-point-qa] Tearing down QA environment for "${spName}"`);
|
|
501
|
-
// Kill dev server if running
|
|
502
|
-
const state = deps.getSavePointQaEnvironment(savePointId);
|
|
503
|
-
if (state?.pid) {
|
|
504
|
-
await deps.stopQaDevServer(state.pid);
|
|
505
|
-
}
|
|
506
|
-
// Clear in-memory state
|
|
507
|
-
deps.removeSavePointQaEnvironment(savePointId);
|
|
508
|
-
// Clear DB QA state (keep worktree_path -- that's managed by MCP view/close)
|
|
509
|
-
await deps.updateSavePointQaStatus(savePointId, {
|
|
510
|
-
qaStatus: null,
|
|
511
|
-
qaUrl: null,
|
|
512
|
-
qaPort: null,
|
|
513
|
-
qaReadyAt: null,
|
|
514
|
-
qaError: null,
|
|
515
|
-
});
|
|
516
|
-
console.log(`[save-point-qa] QA environment torn down for "${spName}"`);
|
|
517
|
-
}
|
|
518
|
-
//# sourceMappingURL=qa-orchestrator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"qa-orchestrator.js","sourceRoot":"","sources":["../src/qa-orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACrL,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEvE,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,6BAA6B,EAC7B,yBAAyB,EACzB,yBAAyB,EACzB,4BAA4B,EAC5B,+BAA+B,GAChC,MAAM,eAAe,CAAC;AAqCvB,kDAAkD;AAClD,MAAM,WAAW,GAAuB;IACtC,aAAa;IACb,uBAAuB;IACvB,cAAc;IACd,gBAAgB,EAAE,oBAAoB;IACtC,eAAe;IACf,YAAY;IACZ,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,mBAAmB;IACnB,sBAAsB;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAoB,EAAE,OAA2B,WAAW;IAChG,IAAI,QAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,qCAAsC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5E,OAAO;IACT,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAElC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;gBAClC,MAAM,iBAAiB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7C,CAAC;iBAAM,IAAI,GAAG,CAAC,SAAS,KAAK,gBAAgB,EAAE,CAAC;gBAC9C,MAAM,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CACX,8CAA8C,GAAG,CAAC,UAAU,KAAM,GAAa,CAAC,OAAO,EAAE,CAC1F,CAAC;YACF,4BAA4B;YAC5B,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE;oBACtC,QAAQ,EAAE,QAAQ;oBAClB,OAAO,EAAG,GAAa,CAAC,OAAO;iBAChC,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,SAAS,EAAE,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,sCAAuC,SAAmB,CAAC,OAAO,EAAE,CAAC,CAAC;YACrF,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,iBAAiB,CAAC,MAAoB,EAAE,GAAc,EAAE,IAAwB;IAC7F,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC;IAEzD,+CAA+C;IAC/C,IAAI,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,uCAAuC,SAAS,GAAG,CAAC,CAAC;QACjE,MAAM,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED,4BAA4B;IAC5B,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;IAEjE,mBAAmB;IACnB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAE1C,+DAA+D;IAC/D,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACpD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,2CAA2C,SAAS,MAAM,OAAO,GAAG,CAAC,CAAC;IACxF,CAAC;IACD,MAAM,YAAY,GAAG,YAAY,CAAC,YAAY,CAAC;IAC/C,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAEpD,uEAAuE;IACvE,MAAM,KAAK,GAAuB;QAChC,OAAO;QACP,SAAS;QACT,YAAY;QACZ,GAAG,EAAE,IAAI;QACT,IAAI;QACJ,GAAG;QACH,MAAM,EAAE,cAAc;QACtB,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,SAAS,EAAE,IAAI;KAChB,CAAC;IACF,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAEtC,kDAAkD;IAClD,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACnC,MAAM;QACN,OAAO;QACP,YAAY;QACZ,IAAI;QACJ,gBAAgB,EAAE,CAAC,KAAa,EAAE,EAAE;YAClC,OAAO,CAAC,KAAK,CAAC,gCAAgC,SAAS,MAAM,KAAK,EAAE,CAAC,CAAC;YACtE,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YAC5F,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE;gBACxF,OAAO,CAAC,IAAI,CAAC,2CAA4C,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YAClF,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;IAEH,0CAA0C;IAC1C,MAAM,UAAU,GAAuB;QACrC,GAAG,KAAK;QACR,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,MAAM,EAAE,OAAO;KAChB,CAAC;IACF,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAE3C,wBAAwB;IACxB,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QACjC,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,GAAG;QACV,MAAM,EAAE,IAAI;QACZ,cAAc,EAAE,YAAY;QAC5B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,kCAAkC,SAAS,QAAQ,GAAG,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,gBAAgB,CAAC,MAAoB,EAAE,GAAc,EAAE,IAAwB;IAC5F,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC;IAEzD,OAAO,CAAC,GAAG,CAAC,yCAAyC,SAAS,GAAG,CAAC,CAAC;IAEnE,6BAA6B;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,KAAK,EAAE,GAAG,EAAE,CAAC;QACf,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,CAAC;IAED,iDAAiD;IACjD,0EAA0E;IAE1E,wBAAwB;IACxB,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAElC,iBAAiB;IACjB,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QACjC,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,cAAc,EAAE,IAAI;QACpB,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,sCAAsC,SAAS,GAAG,CAAC,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,MAAoB,EACpB,OAA2B,WAAW;IAEtC,IAAI,WAAiC,CAAC;IACtC,IAAI,CAAC;QACH,WAAW,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACrE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,gDAAiD,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACvF,OAAO;IACT,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAErC,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CACT,eAAe,KAAK,CAAC,UAAU,QAAQ,KAAK,CAAC,YAAY,sBAAsB,KAAK,CAAC,SAAS,mBAAmB,CAClH,CAAC;QACF,IAAI,CAAC;YACH,MAAM,gBAAgB,CACpB,MAAM,EACN;gBACE,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;aAC7B,EACD,IAAI,CACL,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CACX,qDAAqD,KAAK,CAAC,UAAU,MAAO,GAAa,CAAC,OAAO,EAAE,CACpG,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AA8BD,kDAAkD;AAClD,MAAM,kBAAkB,GAA8B;IACpD,oBAAoB;IACpB,qBAAqB;IACrB,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;IACf,YAAY;IACZ,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,uBAAuB;IACvB,uBAAuB;IACvB,0BAA0B;IAC1B,6BAA6B;CAC9B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAoB,EACpB,OAAkC,kBAAkB;IAEpD,IAAI,QAA4B,CAAC;IACjC,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,qDAAsD,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5F,OAAO;IACT,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAElC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;gBAClC,MAAM,wBAAwB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YACpD,CAAC;iBAAM,IAAI,GAAG,CAAC,SAAS,KAAK,mBAAmB,EAAE,CAAC;gBACjD,MAAM,sBAAsB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAClD,CAAC;iBAAM,IAAI,GAAG,CAAC,SAAS,KAAK,gBAAgB,EAAE,CAAC;gBAC9C,MAAM,uBAAuB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CACX,yDAAyD,GAAG,CAAC,YAAY,MAAO,GAAa,CAAC,OAAO,EAAE,CACxG,CAAC;YACF,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,UAAU,EAAE;oBAC/C,QAAQ,EAAE,QAAQ;oBAClB,OAAO,EAAG,GAAa,CAAC,OAAO;iBAChC,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,SAAS,EAAE,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,8CAA+C,SAAmB,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7F,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,wBAAwB,CACrC,MAAoB,EACpB,GAAqB,EACrB,IAA+B;IAE/B,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC;IAEjE,+CAA+C;IAC/C,IAAI,IAAI,CAAC,6BAA6B,CAAC,SAAS,CAAC,EAAE,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,uDAAuD,WAAW,GAAG,CAAC,CAAC;QACnF,MAAM,uBAAuB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACnD,CAAC;IAED,4BAA4B;IAC5B,MAAM,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;IAE1E,mBAAmB;IACnB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAE1C,iDAAiD;IACjD,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACxD,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,SAAS,EAAE,CAAC,CAAC;IAC1F,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAEpD,qBAAqB;IACrB,MAAM,KAAK,GAA8B;QACvC,SAAS;QACT,WAAW;QACX,YAAY;QACZ,GAAG,EAAE,IAAI;QACT,IAAI;QACJ,GAAG;QACH,MAAM,EAAE,cAAc;QACtB,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,SAAS,EAAE,IAAI;KAChB,CAAC;IACF,IAAI,CAAC,uBAAuB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAE/C,8CAA8C;IAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACnC,MAAM;QACN,OAAO,EAAE,WAAW,SAAS,EAAE;QAC/B,YAAY;QACZ,IAAI;QACJ,gBAAgB,EAAE,CAAC,KAAa,EAAE,EAAE;YAClC,OAAO,CAAC,KAAK,CAAC,gDAAgD,WAAW,MAAM,KAAK,EAAE,CAAC,CAAC;YACxF,IAAI,CAAC,uBAAuB,CAAC,SAAS,EAAE,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YACrG,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE;gBACjG,OAAO,CAAC,IAAI,CAAC,mDAAoD,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1F,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;IAEH,0CAA0C;IAC1C,MAAM,UAAU,GAA8B;QAC5C,GAAG,KAAK;QACR,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,MAAM,EAAE,OAAO;KAChB,CAAC;IACF,IAAI,CAAC,uBAAuB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAEpD,wBAAwB;IACxB,MAAM,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE;QAC1C,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,GAAG;QACV,MAAM,EAAE,IAAI;QACZ,cAAc,EAAE,YAAY;QAC5B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,kDAAkD,WAAW,QAAQ,GAAG,KAAK,aAAa,GAAG,CAAC,CAAC;AAC7G,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,sBAAsB,CACnC,MAAoB,EACpB,GAAqB,EACrB,IAA+B;IAE/B,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC;IAEjE,MAAM,QAAQ,GAAG,IAAI,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC;IACzD,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC;QAC5B,OAAO,CAAC,IAAI,CAAC,yDAAyD,WAAW,mCAAmC,CAAC,CAAC;QACtH,MAAM,wBAAwB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,iDAAiD,WAAW,GAAG,CAAC,CAAC;IAE7E,8EAA8E;IAC9E,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,SAAS,EAAE,CAAC,CAAC;IAErE,oBAAoB;IACpB,MAAM,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAEnE,OAAO,CAAC,GAAG,CAAC,mDAAmD,WAAW,MAAM,aAAa,GAAG,CAAC,CAAC;AACpG,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,uBAAuB,CACpC,MAAoB,EACpB,GAAqB,EACrB,IAA+B;IAE/B,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC;IAEjE,OAAO,CAAC,GAAG,CAAC,yDAAyD,WAAW,GAAG,CAAC,CAAC;IAErF,6BAA6B;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC;IACtD,IAAI,KAAK,EAAE,GAAG,EAAE,CAAC;QACf,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,CAAC;IAED,oEAAoE;IACpE,IAAI,KAAK,EAAE,YAAY,EAAE,CAAC;QACxB,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAC7D,CAAC;IAED,wBAAwB;IACxB,IAAI,CAAC,0BAA0B,CAAC,SAAS,CAAC,CAAC;IAE3C,iBAAiB;IACjB,MAAM,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE;QAC1C,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,cAAc,EAAE,IAAI;QACpB,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,sDAAsD,WAAW,GAAG,CAAC,CAAC;AACpF,CAAC;AA+BD,kDAAkD;AAClD,MAAM,oBAAoB,GAAgC;IACxD,sBAAsB;IACtB,uBAAuB;IACvB,eAAe;IACf,YAAY;IACZ,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,yBAAyB;IACzB,yBAAyB;IACzB,4BAA4B;IAC5B,+BAA+B;CAChC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAoB,EACpB,OAAoC,oBAAoB;IAExD,IAAI,QAA8B,CAAC;IACnC,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACjE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,2DAA4D,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAClG,OAAO;IACT,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAElC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;gBAClC,MAAM,0BAA0B,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YACtD,CAAC;iBAAM,IAAI,GAAG,CAAC,SAAS,KAAK,gBAAgB,EAAE,CAAC;gBAC9C,MAAM,yBAAyB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CACX,+DAA+D,GAAG,CAAC,IAAI,MAAO,GAAa,CAAC,OAAO,EAAE,CACtG,CAAC;YACF,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,aAAa,EAAE;oBACpD,QAAQ,EAAE,QAAQ;oBAClB,OAAO,EAAG,GAAa,CAAC,OAAO;iBAChC,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,SAAS,EAAE,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,iDAAkD,SAAmB,CAAC,OAAO,EAAE,CAAC,CAAC;YAChG,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,0BAA0B,CACvC,MAAoB,EACpB,GAAuB,EACvB,IAAiC;IAEjC,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,GAAG,CAAC;IAEtF,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,eAAe,MAAM,2CAA2C,CAAC,CAAC;IACpF,CAAC;IAED,+CAA+C;IAC/C,IAAI,IAAI,CAAC,+BAA+B,CAAC,WAAW,CAAC,EAAE,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,kDAAkD,MAAM,GAAG,CAAC,CAAC;QACzE,MAAM,yBAAyB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACrD,CAAC;IAED,4BAA4B;IAC5B,MAAM,IAAI,CAAC,uBAAuB,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;IAE9E,mBAAmB;IACnB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAE1C,yCAAyC;IACzC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAEpD,qBAAqB;IACrB,MAAM,KAAK,GAAgC;QACzC,WAAW;QACX,IAAI,EAAE,MAAM;QACZ,YAAY;QACZ,GAAG,EAAE,IAAI;QACT,IAAI;QACJ,GAAG;QACH,MAAM,EAAE,cAAc;QACtB,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,SAAS,EAAE,IAAI;KAChB,CAAC;IACF,IAAI,CAAC,yBAAyB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAEnD,sBAAsB;IACtB,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACnC,MAAM;QACN,OAAO,EAAE,cAAc,WAAW,EAAE;QACpC,YAAY;QACZ,IAAI;QACJ,gBAAgB,EAAE,CAAC,KAAa,EAAE,EAAE;YAClC,OAAO,CAAC,KAAK,CAAC,2CAA2C,MAAM,MAAM,KAAK,EAAE,CAAC,CAAC;YAC9E,IAAI,CAAC,yBAAyB,CAAC,WAAW,EAAE,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YACzG,IAAI,CAAC,uBAAuB,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE;gBACrG,OAAO,CAAC,IAAI,CAAC,sDAAuD,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7F,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;IAEH,0CAA0C;IAC1C,MAAM,UAAU,GAAgC;QAC9C,GAAG,KAAK;QACR,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,MAAM,EAAE,OAAO;KAChB,CAAC;IACF,IAAI,CAAC,yBAAyB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAExD,wBAAwB;IACxB,MAAM,IAAI,CAAC,uBAAuB,CAAC,WAAW,EAAE;QAC9C,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,GAAG;QACV,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,6CAA6C,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC;AAChF,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,yBAAyB,CACtC,MAAoB,EACpB,GAAuB,EACvB,IAAiC;IAEjC,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IAEzD,OAAO,CAAC,GAAG,CAAC,oDAAoD,MAAM,GAAG,CAAC,CAAC;IAE3E,6BAA6B;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,yBAAyB,CAAC,WAAW,CAAC,CAAC;IAC1D,IAAI,KAAK,EAAE,GAAG,EAAE,CAAC;QACf,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,CAAC;IAED,wBAAwB;IACxB,IAAI,CAAC,4BAA4B,CAAC,WAAW,CAAC,CAAC;IAE/C,6EAA6E;IAC7E,MAAM,IAAI,CAAC,uBAAuB,CAAC,WAAW,EAAE;QAC9C,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,iDAAiD,MAAM,GAAG,CAAC,CAAC;AAC1E,CAAC"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* QA environment port allocation and URL construction.
|
|
3
|
-
*
|
|
4
|
-
* Allocates ports from the configured range for QA dev servers,
|
|
5
|
-
* checking both in-memory state and OS-level availability.
|
|
6
|
-
*/
|
|
7
|
-
import type { DaemonConfig } from './types.js';
|
|
8
|
-
/**
|
|
9
|
-
* Allocate an available port from the configured QA port range.
|
|
10
|
-
*
|
|
11
|
-
* 1. Collects ports already in use by active QA environments (in-memory).
|
|
12
|
-
* 2. Iterates through [qaPortRangeStart, qaPortRangeEnd].
|
|
13
|
-
* 3. For each port not already allocated, verifies OS-level availability.
|
|
14
|
-
* 4. Returns the first available port.
|
|
15
|
-
*
|
|
16
|
-
* @throws Error if no port is available in the configured range.
|
|
17
|
-
*/
|
|
18
|
-
export declare function allocatePort(config: DaemonConfig): Promise<number>;
|
|
19
|
-
/**
|
|
20
|
-
* Release a port allocation.
|
|
21
|
-
*
|
|
22
|
-
* Currently a no-op: ports are tracked in qa-state.ts via QaEnvironmentState.
|
|
23
|
-
* When removeQaEnvironment() is called, the port is implicitly released.
|
|
24
|
-
* This is a placeholder for future explicit port reservation tracking.
|
|
25
|
-
*/
|
|
26
|
-
export declare function releasePort(_port: number): void;
|
|
27
|
-
/**
|
|
28
|
-
* Build the full QA URL for a given port using the configured host.
|
|
29
|
-
*
|
|
30
|
-
* Uses qaHost from config, which is either an auto-detected LAN IP
|
|
31
|
-
* or an explicitly configured hostname.
|
|
32
|
-
*/
|
|
33
|
-
export declare function buildQaUrl(config: DaemonConfig, port: number): string;
|
|
34
|
-
//# sourceMappingURL=qa-port-allocator.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"qa-port-allocator.d.ts","sourceRoot":"","sources":["../src/qa-port-allocator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAkB/C;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBxE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAG/C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErE"}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* QA environment port allocation and URL construction.
|
|
3
|
-
*
|
|
4
|
-
* Allocates ports from the configured range for QA dev servers,
|
|
5
|
-
* checking both in-memory state and OS-level availability.
|
|
6
|
-
*/
|
|
7
|
-
import { createServer } from 'node:net';
|
|
8
|
-
import { getActiveQaEnvironments } from './qa-state.js';
|
|
9
|
-
/**
|
|
10
|
-
* Check whether a port is available by briefly binding to it.
|
|
11
|
-
* Returns true if the port can be bound, false if it is in use.
|
|
12
|
-
*/
|
|
13
|
-
function isPortAvailable(port) {
|
|
14
|
-
return new Promise((resolve) => {
|
|
15
|
-
const server = createServer();
|
|
16
|
-
server.once('error', () => resolve(false));
|
|
17
|
-
server.once('listening', () => {
|
|
18
|
-
server.close(() => resolve(true));
|
|
19
|
-
});
|
|
20
|
-
server.listen(port, '0.0.0.0');
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Allocate an available port from the configured QA port range.
|
|
25
|
-
*
|
|
26
|
-
* 1. Collects ports already in use by active QA environments (in-memory).
|
|
27
|
-
* 2. Iterates through [qaPortRangeStart, qaPortRangeEnd].
|
|
28
|
-
* 3. For each port not already allocated, verifies OS-level availability.
|
|
29
|
-
* 4. Returns the first available port.
|
|
30
|
-
*
|
|
31
|
-
* @throws Error if no port is available in the configured range.
|
|
32
|
-
*/
|
|
33
|
-
export async function allocatePort(config) {
|
|
34
|
-
const { qaPortRangeStart: start, qaPortRangeEnd: end } = config;
|
|
35
|
-
// Collect ports already allocated to active QA environments
|
|
36
|
-
const activeEnvironments = getActiveQaEnvironments();
|
|
37
|
-
const allocatedPorts = new Set();
|
|
38
|
-
for (const env of activeEnvironments.values()) {
|
|
39
|
-
allocatedPorts.add(env.port);
|
|
40
|
-
}
|
|
41
|
-
// Iterate through the range looking for an available port
|
|
42
|
-
for (let port = start; port <= end; port++) {
|
|
43
|
-
// Skip ports already tracked in memory
|
|
44
|
-
if (allocatedPorts.has(port)) {
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
// Verify the port is actually free at the OS level
|
|
48
|
-
const available = await isPortAvailable(port);
|
|
49
|
-
if (available) {
|
|
50
|
-
return port;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
throw new Error(`No available port in range ${start}-${end}`);
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Release a port allocation.
|
|
57
|
-
*
|
|
58
|
-
* Currently a no-op: ports are tracked in qa-state.ts via QaEnvironmentState.
|
|
59
|
-
* When removeQaEnvironment() is called, the port is implicitly released.
|
|
60
|
-
* This is a placeholder for future explicit port reservation tracking.
|
|
61
|
-
*/
|
|
62
|
-
export function releasePort(_port) {
|
|
63
|
-
// Port is released implicitly when QA environment state is removed.
|
|
64
|
-
// This is a placeholder for future explicit port reservation tracking.
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Build the full QA URL for a given port using the configured host.
|
|
68
|
-
*
|
|
69
|
-
* Uses qaHost from config, which is either an auto-detected LAN IP
|
|
70
|
-
* or an explicitly configured hostname.
|
|
71
|
-
*/
|
|
72
|
-
export function buildQaUrl(config, port) {
|
|
73
|
-
return `http://${config.qaHost}:${port}`;
|
|
74
|
-
}
|
|
75
|
-
//# sourceMappingURL=qa-port-allocator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"qa-port-allocator.js","sourceRoot":"","sources":["../src/qa-port-allocator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD;;;GAGG;AACH,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAoB;IACrD,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;IAEhE,4DAA4D;IAC5D,MAAM,kBAAkB,GAAG,uBAAuB,EAAE,CAAC;IACrD,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9C,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,0DAA0D;IAC1D,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC;QAC3C,uCAAuC;QACvC,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,mDAAmD;QACnD,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,8BAA8B,KAAK,IAAI,GAAG,EAAE,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,oEAAoE;IACpE,uEAAuE;AACzE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,MAAoB,EAAE,IAAY;IAC3D,OAAO,UAAU,MAAM,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;AAC3C,CAAC"}
|