@lenne.tech/cli 1.37.2 → 1.38.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.
|
@@ -26,7 +26,12 @@ const workspace_integration_1 = require("../../lib/workspace-integration");
|
|
|
26
26
|
* `lt ticket stop --keep-db` are never touched.
|
|
27
27
|
* 2. STALE SHARD TEST DATABASES (`<base>-test-<n>` from `lt dev test --shard`)
|
|
28
28
|
* when no test session is running — they are reset on every run anyway.
|
|
29
|
-
* 3.
|
|
29
|
+
* 3. ORPHANED SMOKE-TEST DATABASES (global): the `/lt-dev:fullstack:smoke-test`
|
|
30
|
+
* throwaway projects use the reserved `lt-smoke-test` slug; their DBs are
|
|
31
|
+
* ephemeral by convention. Leftovers (e.g. a blocked drop during the run's
|
|
32
|
+
* cleanup) would be REUSED by the next run's stack and leak state between
|
|
33
|
+
* test runs — swept here whenever no live smoke-test run is registered.
|
|
34
|
+
* 4. DEAD REGISTRY ENTRIES (all projects): path no longer exists → the entry and
|
|
30
35
|
* its reserved ports are reclaimed. Databases of dead MAIN projects are NEVER
|
|
31
36
|
* dropped (a deleted folder is not consent to destroy data).
|
|
32
37
|
*
|
|
@@ -51,8 +56,12 @@ const PruneCommand = {
|
|
|
51
56
|
const mainLayout = (0, dev_project_1.resolveLayout)(mainRepoRoot, filesystem);
|
|
52
57
|
const slug = (0, dev_identity_1.buildIdentity)(mainRepoRoot).slug;
|
|
53
58
|
const projectDevDb = (0, dev_project_1.deriveDbName)(mainLayout.apiDir, slug);
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
// Always observe — the smoke-test sweep is GLOBAL (reserved prefix), so it
|
|
60
|
+
// must work from any project, even one without an own API (e.g. the CLI
|
|
61
|
+
// repo itself). mongosh against the local default URI needs no project
|
|
62
|
+
// driver; the api dir merely improves the driver fallback when present.
|
|
63
|
+
const observed = (0, dev_ticket_1.listDatabaseNames)(undefined, [mainLayout.apiDir, mainRepoRoot].filter(Boolean));
|
|
64
|
+
if (observed === null) {
|
|
56
65
|
warning('Could not list databases (mongosh missing or MongoDB unreachable) — only the registry is pruned.');
|
|
57
66
|
}
|
|
58
67
|
const plan = (0, dev_prune_1.collectDevPrunePlan)({
|
|
@@ -62,9 +71,9 @@ const PruneCommand = {
|
|
|
62
71
|
projectDevDb,
|
|
63
72
|
slug,
|
|
64
73
|
});
|
|
65
|
-
const dbTargets = [...new Set([...plan.orphan.targets, ...plan.shardTargets])];
|
|
74
|
+
const dbTargets = [...new Set([...plan.orphan.targets, ...plan.shardTargets, ...plan.smokeTargets])];
|
|
66
75
|
if (dbTargets.length === 0 && plan.registryPrune.length === 0) {
|
|
67
|
-
success('Nothing to prune — no orphaned ticket DBs, no stale shard DBs, no dead registry entries.');
|
|
76
|
+
success('Nothing to prune — no orphaned ticket DBs, no stale shard DBs, no smoke-test DBs, no dead registry entries.');
|
|
68
77
|
if (plan.orphan.protected.length > 0) {
|
|
69
78
|
info(colors.dim(` kept (registry keptDbs / referenced): ${plan.orphan.protected.join(', ')}`));
|
|
70
79
|
}
|
|
@@ -80,6 +89,10 @@ const PruneCommand = {
|
|
|
80
89
|
info(colors.bold('Stale shard test databases (no test session running):'));
|
|
81
90
|
plan.shardTargets.forEach((db) => info(colors.dim(` • ${db}`)));
|
|
82
91
|
}
|
|
92
|
+
if (plan.smokeTargets.length > 0) {
|
|
93
|
+
info(colors.bold('Orphaned smoke-test databases (reserved lt-smoke-test prefix, no live run):'));
|
|
94
|
+
plan.smokeTargets.forEach((db) => info(colors.dim(` • ${db}`)));
|
|
95
|
+
}
|
|
83
96
|
if (plan.orphan.protected.length > 0) {
|
|
84
97
|
info(colors.dim(`Kept (recorded via --keep-db or still referenced): ${plan.orphan.protected.join(', ')}`));
|
|
85
98
|
}
|
package/build/commands/dev/up.js
CHANGED
|
@@ -454,11 +454,13 @@ const UpCommand = {
|
|
|
454
454
|
const plan = (0, dev_prune_1.collectDevPrunePlan)({
|
|
455
455
|
loadRegistry: dev_state_1.loadRegistry,
|
|
456
456
|
mainRepoRoot,
|
|
457
|
-
|
|
457
|
+
// Always observe (not only with an own api dir): the smoke-test sweep is
|
|
458
|
+
// global, and mongosh against the local default URI needs no project driver.
|
|
459
|
+
observedDbNames: (0, dev_ticket_1.listDatabaseNames)(undefined, [mainLayout.apiDir, mainRepoRoot].filter(Boolean)),
|
|
458
460
|
projectDevDb: (0, dev_project_1.deriveDbName)(mainLayout.apiDir, baseSlug),
|
|
459
461
|
slug: baseSlug,
|
|
460
462
|
});
|
|
461
|
-
const dbTargets = [...new Set([...plan.orphan.targets, ...plan.shardTargets])];
|
|
463
|
+
const dbTargets = [...new Set([...plan.orphan.targets, ...plan.shardTargets, ...plan.smokeTargets])];
|
|
462
464
|
if (dbTargets.length > 0) {
|
|
463
465
|
const { dropped, reason } = (0, dev_ticket_1.dropDatabases)(dbTargets, undefined, [mainLayout.apiDir, mainRepoRoot]);
|
|
464
466
|
if (dropped.length > 0) {
|
package/build/lib/dev-prune.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SMOKE_TEST_DB_PREFIX = void 0;
|
|
3
4
|
exports.collectDevPrunePlan = collectDevPrunePlan;
|
|
4
5
|
exports.listLiveTicketIds = listLiveTicketIds;
|
|
5
6
|
exports.listPastTicketIds = listPastTicketIds;
|
|
6
7
|
exports.planOrphanTicketDbSweep = planOrphanTicketDbSweep;
|
|
7
8
|
exports.planRegistryPrune = planRegistryPrune;
|
|
9
|
+
exports.planSmokeTestDbSweep = planSmokeTestDbSweep;
|
|
8
10
|
exports.planStaleShardDbSweep = planStaleShardDbSweep;
|
|
9
11
|
/**
|
|
10
12
|
* Garbage collection for `lt dev` / `lt ticket` leftovers.
|
|
@@ -44,6 +46,13 @@ const dev_project_1 = require("./dev-project");
|
|
|
44
46
|
const dev_ticket_1 = require("./dev-ticket");
|
|
45
47
|
/** Branch prefix `lt ticket start` creates worktrees on. */
|
|
46
48
|
const TICKET_BRANCH_PREFIX = 'feat/';
|
|
49
|
+
/**
|
|
50
|
+
* Slug convention of the lt-dev fullstack smoke test (`/lt-dev:fullstack:smoke-test`).
|
|
51
|
+
* Its throwaway projects are named `lt-smoke-test`, so every database under this
|
|
52
|
+
* prefix is ephemeral BY CONVENTION — reserve the prefix for smoke-test runs and
|
|
53
|
+
* never name a real project like this.
|
|
54
|
+
*/
|
|
55
|
+
exports.SMOKE_TEST_DB_PREFIX = 'lt-smoke-test';
|
|
47
56
|
/**
|
|
48
57
|
* Collect the full prune plan for one project. Reads the registry and the Mongo
|
|
49
58
|
* database listing; performs NO destructive action.
|
|
@@ -66,6 +75,7 @@ function collectDevPrunePlan(args) {
|
|
|
66
75
|
projectDevDb,
|
|
67
76
|
projectRoot: mainRepoRoot,
|
|
68
77
|
}),
|
|
78
|
+
smokeTargets: planSmokeTestDbSweep({ observedDbNames, registry }),
|
|
69
79
|
};
|
|
70
80
|
}
|
|
71
81
|
/** Ticket ids that still have a live environment (worktree and/or live registry entry). */
|
|
@@ -182,6 +192,47 @@ function planRegistryPrune(registry) {
|
|
|
182
192
|
.filter(([, entry]) => entry.path && !(0, fs_1.existsSync)(entry.path))
|
|
183
193
|
.map(([key]) => key);
|
|
184
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Orphaned smoke-test databases. The `/lt-dev:fullstack:smoke-test` command
|
|
197
|
+
* scaffolds throwaway projects under the reserved {@link SMOKE_TEST_DB_PREFIX}
|
|
198
|
+
* slug; their databases (`lt-smoke-test-local`, `lt-smoke-test-test`, ticket
|
|
199
|
+
* variants, …) are ephemeral by convention. When the run's cleanup could not
|
|
200
|
+
* drop them (e.g. a blocking policy hook) they linger and — worse — get
|
|
201
|
+
* REUSED by the next run's stack, leaking state between test runs (observed:
|
|
202
|
+
* a previous run's user made a fresh sign-up probe fail with
|
|
203
|
+
* "Email already registered").
|
|
204
|
+
*
|
|
205
|
+
* Fail-closed gates, in line with the rest of this module:
|
|
206
|
+
* - No server listing → empty plan.
|
|
207
|
+
* - A LIVE registry entry under the prefix (path exists ⇒ a smoke test is
|
|
208
|
+
* running right now) → empty plan; never pull the DB out from under an
|
|
209
|
+
* active run.
|
|
210
|
+
* - Names recorded as kept (`keptDbs`) or referenced by any live entry's
|
|
211
|
+
* `dbName` are never touched.
|
|
212
|
+
*/
|
|
213
|
+
function planSmokeTestDbSweep(args) {
|
|
214
|
+
var _a;
|
|
215
|
+
const { observedDbNames, registry } = args;
|
|
216
|
+
if (!observedDbNames || observedDbNames.length === 0)
|
|
217
|
+
return [];
|
|
218
|
+
const entries = Object.entries(registry.projects);
|
|
219
|
+
const smokeRunLive = entries.some(([key, entry]) => (key === exports.SMOKE_TEST_DB_PREFIX || key.startsWith(`${exports.SMOKE_TEST_DB_PREFIX}-`)) &&
|
|
220
|
+
entry.path &&
|
|
221
|
+
(0, fs_1.existsSync)(entry.path));
|
|
222
|
+
if (smokeRunLive)
|
|
223
|
+
return [];
|
|
224
|
+
const protectedNames = new Set();
|
|
225
|
+
for (const [, entry] of entries) {
|
|
226
|
+
if (entry.dbName && entry.path && (0, fs_1.existsSync)(entry.path)) {
|
|
227
|
+
protectedNames.add(entry.dbName);
|
|
228
|
+
protectedNames.add((0, dev_project_1.deriveTestDbName)(entry.dbName));
|
|
229
|
+
}
|
|
230
|
+
for (const kept of (_a = entry.keptDbs) !== null && _a !== void 0 ? _a : []) {
|
|
231
|
+
protectedNames.add(kept);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return observedDbNames.filter((name) => (name === exports.SMOKE_TEST_DB_PREFIX || name.startsWith(`${exports.SMOKE_TEST_DB_PREFIX}-`)) && !protectedNames.has(name));
|
|
235
|
+
}
|
|
185
236
|
/**
|
|
186
237
|
* Stale sharded-test databases of the project itself (`<base>-test-<n>` from
|
|
187
238
|
* `lt dev test --shard`). They are ephemeral by definition — every shard run
|