@git.zone/cli 3.2.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/classes.gitzoneconfig.js +1 -1
- package/dist_ts/classes.project.js +1 -1
- package/dist_ts/gitzone.cli.js +1 -1
- package/dist_ts/gitzone.logging.js +1 -1
- package/dist_ts/helpers.changelog.js +1 -1
- package/dist_ts/helpers.climode.js +1 -1
- package/dist_ts/helpers.smartconfig.js +61 -11
- package/dist_ts/helpers.smartconfigmigrations.js +1 -1
- package/dist_ts/helpers.tsdocker.js +1 -1
- package/dist_ts/helpers.workflow.js +1 -1
- package/dist_ts/index.js +1 -1
- package/dist_ts/mod_audit/index.js +1 -1
- package/dist_ts/mod_commit/index.js +1 -1
- package/dist_ts/mod_commit/mod.helpers.js +1 -1
- package/dist_ts/mod_commit/mod.plugins.js +1 -1
- package/dist_ts/mod_commit/mod.ui.js +1 -1
- package/dist_ts/mod_config/classes.commitconfig.js +1 -1
- package/dist_ts/mod_config/classes.releaseconfig.js +1 -1
- package/dist_ts/mod_config/index.js +2 -2
- package/dist_ts/mod_config/mod.plugins.js +1 -1
- package/dist_ts/mod_deprecate/index.js +1 -1
- package/dist_ts/mod_deprecate/mod.plugins.js +1 -1
- package/dist_ts/mod_docker/classes.dockerpruner.js +7 -1
- package/dist_ts/mod_docker/index.js +1 -1
- package/dist_ts/mod_docker/mod.plugins.js +1 -1
- package/dist_ts/mod_format/classes.baseformatter.js +1 -1
- package/dist_ts/mod_format/classes.diffreporter.js +1 -1
- package/dist_ts/mod_format/classes.formatcontext.js +1 -1
- package/dist_ts/mod_format/classes.formatplanner.js +1 -1
- package/dist_ts/mod_format/classes.formatstats.js +1 -1
- package/dist_ts/mod_format/formatters/assets.formatter.js +1 -1
- package/dist_ts/mod_format/formatters/cleanup.formatter.js +1 -1
- package/dist_ts/mod_format/formatters/copy.formatter.js +1 -1
- package/dist_ts/mod_format/formatters/gitignore.formatter.js +1 -1
- package/dist_ts/mod_format/formatters/license.formatter.js +1 -1
- package/dist_ts/mod_format/formatters/packagejson.formatter.js +1 -1
- package/dist_ts/mod_format/formatters/prettier.formatter.js +1 -1
- package/dist_ts/mod_format/formatters/readme.formatter.js +1 -1
- package/dist_ts/mod_format/formatters/smartconfig.formatter.js +1 -1
- package/dist_ts/mod_format/formatters/templates.formatter.js +1 -1
- package/dist_ts/mod_format/formatters/tsconfig.formatter.js +1 -1
- package/dist_ts/mod_format/index.js +1 -1
- package/dist_ts/mod_format/interfaces.format.js +1 -1
- package/dist_ts/mod_format/mod.plugins.js +1 -1
- package/dist_ts/mod_helpers/index.js +1 -1
- package/dist_ts/mod_helpers/mod.plugins.js +1 -1
- package/dist_ts/mod_meta/index.js +1 -1
- package/dist_ts/mod_meta/meta.classes.meta.js +1 -1
- package/dist_ts/mod_meta/meta.interfaces.js +1 -1
- package/dist_ts/mod_meta/meta.plugins.js +1 -1
- package/dist_ts/mod_open/index.js +1 -1
- package/dist_ts/mod_open/mod.plugins.js +1 -1
- package/dist_ts/mod_release/index.js +1 -1
- package/dist_ts/mod_release/mod.plugins.js +1 -1
- package/dist_ts/mod_services/classes.dockercontainer.d.ts +50 -3
- package/dist_ts/mod_services/classes.dockercontainer.js +646 -84
- package/dist_ts/mod_services/classes.globalregistry.d.ts +10 -24
- package/dist_ts/mod_services/classes.globalregistry.js +210 -62
- package/dist_ts/mod_services/classes.globalregistrystore.d.ts +48 -0
- package/dist_ts/mod_services/classes.globalregistrystore.js +156 -0
- package/dist_ts/mod_services/classes.interprocesslock.d.ts +21 -0
- package/dist_ts/mod_services/classes.interprocesslock.js +141 -0
- package/dist_ts/mod_services/classes.serviceconfiguration.d.ts +15 -12
- package/dist_ts/mod_services/classes.serviceconfiguration.js +188 -91
- package/dist_ts/mod_services/classes.servicedatamarker.d.ts +32 -7
- package/dist_ts/mod_services/classes.servicedatamarker.js +145 -49
- package/dist_ts/mod_services/classes.servicemanager.d.ts +70 -28
- package/dist_ts/mod_services/classes.servicemanager.js +995 -421
- package/dist_ts/mod_services/classes.servicenames.d.ts +8 -0
- package/dist_ts/mod_services/classes.servicenames.js +54 -0
- package/dist_ts/mod_services/classes.serviceoptions.js +1 -1
- package/dist_ts/mod_services/classes.servicepruner.d.ts +3 -0
- package/dist_ts/mod_services/classes.servicepruner.js +208 -46
- package/dist_ts/mod_services/helpers.js +1 -1
- package/dist_ts/mod_services/index.d.ts +2 -0
- package/dist_ts/mod_services/index.js +81 -58
- package/dist_ts/mod_services/mod.plugins.js +1 -1
- package/dist_ts/mod_standard/index.js +2 -2
- package/dist_ts/mod_standard/mod.plugins.js +1 -1
- package/dist_ts/mod_start/index.js +1 -1
- package/dist_ts/mod_start/mod.plugins.js +1 -1
- package/dist_ts/mod_template/index.js +1 -1
- package/dist_ts/mod_template/mod.plugins.js +1 -1
- package/dist_ts/mod_tools/classes.packagemanager.js +1 -1
- package/dist_ts/mod_tools/index.js +1 -1
- package/dist_ts/mod_tools/mod.plugins.js +1 -1
- package/dist_ts/paths.js +1 -1
- package/dist_ts/plugins.d.ts +3 -1
- package/dist_ts/plugins.js +4 -2
- package/dist_ts_migration/001.service-selection.d.ts +9 -0
- package/dist_ts_migration/001.service-selection.js +51 -0
- package/dist_ts_migration/002.runtime-config.d.ts +19 -0
- package/dist_ts_migration/002.runtime-config.js +170 -0
- package/dist_ts_migration/003.service-data-marker.d.ts +9 -0
- package/dist_ts_migration/003.service-data-marker.js +156 -0
- package/dist_ts_migration/004.global-registry.d.ts +13 -0
- package/dist_ts_migration/004.global-registry.js +165 -0
- package/dist_ts_migration/index.d.ts +11 -0
- package/dist_ts_migration/index.js +59 -0
- package/package.json +6 -3
- package/readme.hints.md +102 -25
- package/readme.md +123 -28
- package/readme.plan.md +29 -16
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/helpers.smartconfig.ts +63 -10
- package/ts/mod_config/index.ts +1 -1
- package/ts/mod_docker/classes.dockerpruner.ts +6 -0
- package/ts/mod_services/classes.dockercontainer.ts +912 -96
- package/ts/mod_services/classes.globalregistry.ts +290 -89
- package/ts/mod_services/classes.globalregistrystore.ts +279 -0
- package/ts/mod_services/classes.interprocesslock.ts +189 -0
- package/ts/mod_services/classes.serviceconfiguration.ts +215 -108
- package/ts/mod_services/classes.servicedatamarker.ts +210 -52
- package/ts/mod_services/classes.servicemanager.ts +1332 -512
- package/ts/mod_services/classes.servicenames.ts +76 -0
- package/ts/mod_services/classes.servicepruner.ts +310 -52
- package/ts/mod_services/index.ts +89 -62
- package/ts/mod_standard/index.ts +1 -1
- package/ts/plugins.ts +4 -0
- package/ts_migration/001.service-selection.ts +77 -0
- package/ts_migration/002.runtime-config.ts +218 -0
- package/ts_migration/003.service-data-marker.ts +216 -0
- package/ts_migration/004.global-registry.ts +272 -0
- package/ts_migration/index.ts +83 -0
|
@@ -1,28 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
containers: {
|
|
5
|
-
mongo?: string;
|
|
6
|
-
minio?: string;
|
|
7
|
-
elasticsearch?: string;
|
|
8
|
-
};
|
|
9
|
-
ports: {
|
|
10
|
-
mongo?: number;
|
|
11
|
-
s3?: number;
|
|
12
|
-
s3Console?: number;
|
|
13
|
-
elasticsearch?: number;
|
|
14
|
-
};
|
|
15
|
-
enabledServices: string[];
|
|
16
|
-
lastActive: number;
|
|
17
|
-
}
|
|
18
|
-
export interface IGlobalRegistryData {
|
|
19
|
-
projects: {
|
|
20
|
-
[projectPath: string]: IRegisteredProject;
|
|
21
|
-
};
|
|
22
|
-
}
|
|
1
|
+
import { type IRegisteredProject } from './classes.globalregistrystore.js';
|
|
2
|
+
export { assertCanonicalGlobalRegistryData } from './classes.globalregistrystore.js';
|
|
3
|
+
export type { IGlobalRegistryData, IRegisteredProject, } from './classes.globalregistrystore.js';
|
|
23
4
|
export declare class GlobalRegistry {
|
|
24
5
|
private static instance;
|
|
25
|
-
private
|
|
6
|
+
private store;
|
|
26
7
|
private docker;
|
|
27
8
|
private constructor();
|
|
28
9
|
/**
|
|
@@ -36,7 +17,7 @@ export declare class GlobalRegistry {
|
|
|
36
17
|
/**
|
|
37
18
|
* Remove a project from the registry
|
|
38
19
|
*/
|
|
39
|
-
unregisterProject(
|
|
20
|
+
unregisterProject(projectPathArg: string, expectedProjectArg: IRegisteredProject): Promise<void>;
|
|
40
21
|
/**
|
|
41
22
|
* Update the lastActive timestamp for a project
|
|
42
23
|
*/
|
|
@@ -47,6 +28,7 @@ export declare class GlobalRegistry {
|
|
|
47
28
|
getAllProjects(): Promise<{
|
|
48
29
|
[path: string]: IRegisteredProject;
|
|
49
30
|
}>;
|
|
31
|
+
private readCanonicalData;
|
|
50
32
|
/**
|
|
51
33
|
* Check if a project is registered
|
|
52
34
|
*/
|
|
@@ -60,6 +42,7 @@ export declare class GlobalRegistry {
|
|
|
60
42
|
containers: Array<{
|
|
61
43
|
name: string;
|
|
62
44
|
status: string;
|
|
45
|
+
ownership?: 'owned' | 'conflict';
|
|
63
46
|
}>;
|
|
64
47
|
lastActive: number;
|
|
65
48
|
}>>;
|
|
@@ -70,6 +53,8 @@ export declare class GlobalRegistry {
|
|
|
70
53
|
stopped: string[];
|
|
71
54
|
failed: string[];
|
|
72
55
|
}>;
|
|
56
|
+
private inspectRegisteredContainer;
|
|
57
|
+
private exactContainerExists;
|
|
73
58
|
/**
|
|
74
59
|
* Cheap staleness summary for a non-blocking hint after ordinary commands.
|
|
75
60
|
*
|
|
@@ -90,4 +75,5 @@ export declare class GlobalRegistry {
|
|
|
90
75
|
reason: string;
|
|
91
76
|
}>;
|
|
92
77
|
}>;
|
|
78
|
+
private withProjectServiceLocks;
|
|
93
79
|
}
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import * as plugins from '../plugins.js';
|
|
2
2
|
import { DockerContainer } from './classes.dockercontainer.js';
|
|
3
3
|
import { logger } from '../gitzone.logging.js';
|
|
4
|
+
import { getServiceContainerLabels, getServiceDataDirectory, hasExactServiceContainerLabels, serviceNames, } from './classes.servicedatamarker.js';
|
|
5
|
+
import { withServiceDataOperationLock } from './classes.interprocesslock.js';
|
|
6
|
+
import { GlobalRegistryStore, assertCanonicalGlobalRegistryData, } from './classes.globalregistrystore.js';
|
|
7
|
+
export { assertCanonicalGlobalRegistryData } from './classes.globalregistrystore.js';
|
|
8
|
+
const registryServiceNames = {
|
|
9
|
+
mongo: 'mongodb',
|
|
10
|
+
objectstorage: 'objectstorage',
|
|
11
|
+
elasticsearch: 'elasticsearch',
|
|
12
|
+
};
|
|
4
13
|
export class GlobalRegistry {
|
|
5
14
|
static instance = null;
|
|
6
|
-
|
|
15
|
+
store;
|
|
7
16
|
docker;
|
|
8
|
-
constructor() {
|
|
9
|
-
this.
|
|
10
|
-
typeArg: 'userHomeDir',
|
|
11
|
-
identityArg: 'gitzone-services',
|
|
12
|
-
});
|
|
17
|
+
constructor(storeArg = new GlobalRegistryStore()) {
|
|
18
|
+
this.store = storeArg;
|
|
13
19
|
this.docker = new DockerContainer();
|
|
14
20
|
}
|
|
15
21
|
/**
|
|
@@ -25,49 +31,82 @@ export class GlobalRegistry {
|
|
|
25
31
|
* Register or update a project in the global registry
|
|
26
32
|
*/
|
|
27
33
|
async registerProject(data) {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
...
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
const projectPath = plugins.path.resolve(data.projectPath);
|
|
35
|
+
await this.store.transact((rawData) => {
|
|
36
|
+
const allData = assertCanonicalGlobalRegistryData(rawData);
|
|
37
|
+
const projects = { ...allData.projects };
|
|
38
|
+
const existingLegacy = projects[projectPath]?.legacy;
|
|
39
|
+
projects[projectPath] = {
|
|
40
|
+
...data,
|
|
41
|
+
projectPath,
|
|
42
|
+
...(existingLegacy ? { legacy: existingLegacy } : {}),
|
|
43
|
+
lastActive: Date.now(),
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
result: undefined,
|
|
47
|
+
writeData: { schemaVersion: 2, projects },
|
|
48
|
+
};
|
|
49
|
+
});
|
|
35
50
|
}
|
|
36
51
|
/**
|
|
37
52
|
* Remove a project from the registry
|
|
38
53
|
*/
|
|
39
|
-
async unregisterProject(
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
async unregisterProject(projectPathArg, expectedProjectArg) {
|
|
55
|
+
const projectPath = plugins.path.resolve(projectPathArg);
|
|
56
|
+
await this.store.transact((rawData) => {
|
|
57
|
+
const allData = assertCanonicalGlobalRegistryData(rawData);
|
|
58
|
+
const projects = { ...allData.projects };
|
|
59
|
+
const currentProject = projects[projectPath];
|
|
60
|
+
if (!currentProject) {
|
|
61
|
+
return { result: undefined };
|
|
62
|
+
}
|
|
63
|
+
if (JSON.stringify(currentProject) !== JSON.stringify(expectedProjectArg)) {
|
|
64
|
+
throw new Error(`Refusing to unregister changed global registry entry: ${projectPath}`);
|
|
65
|
+
}
|
|
43
66
|
delete projects[projectPath];
|
|
44
|
-
|
|
45
|
-
|
|
67
|
+
return {
|
|
68
|
+
result: undefined,
|
|
69
|
+
writeData: { schemaVersion: 2, projects },
|
|
70
|
+
};
|
|
71
|
+
});
|
|
46
72
|
}
|
|
47
73
|
/**
|
|
48
74
|
* Update the lastActive timestamp for a project
|
|
49
75
|
*/
|
|
50
76
|
async touchProject(projectPath) {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
projects
|
|
55
|
-
|
|
56
|
-
|
|
77
|
+
const resolvedProjectPath = plugins.path.resolve(projectPath);
|
|
78
|
+
await this.store.transact((rawData) => {
|
|
79
|
+
const allData = assertCanonicalGlobalRegistryData(rawData);
|
|
80
|
+
const projects = { ...allData.projects };
|
|
81
|
+
const existing = projects[resolvedProjectPath];
|
|
82
|
+
if (!existing) {
|
|
83
|
+
return { result: undefined };
|
|
84
|
+
}
|
|
85
|
+
projects[resolvedProjectPath] = {
|
|
86
|
+
...existing,
|
|
87
|
+
lastActive: Date.now(),
|
|
88
|
+
};
|
|
89
|
+
return {
|
|
90
|
+
result: undefined,
|
|
91
|
+
writeData: { schemaVersion: 2, projects },
|
|
92
|
+
};
|
|
93
|
+
});
|
|
57
94
|
}
|
|
58
95
|
/**
|
|
59
96
|
* Get all registered projects
|
|
60
97
|
*/
|
|
61
98
|
async getAllProjects() {
|
|
62
|
-
|
|
63
|
-
|
|
99
|
+
return (await this.readCanonicalData()).projects;
|
|
100
|
+
}
|
|
101
|
+
async readCanonicalData() {
|
|
102
|
+
return this.store.readCanonical();
|
|
64
103
|
}
|
|
65
104
|
/**
|
|
66
105
|
* Check if a project is registered
|
|
67
106
|
*/
|
|
68
107
|
async isRegistered(projectPath) {
|
|
69
108
|
const projects = await this.getAllProjects();
|
|
70
|
-
return !!projects[projectPath];
|
|
109
|
+
return !!projects[plugins.path.resolve(projectPath)];
|
|
71
110
|
}
|
|
72
111
|
/**
|
|
73
112
|
* Get status of all containers across all registered projects
|
|
@@ -77,8 +116,27 @@ export class GlobalRegistry {
|
|
|
77
116
|
const result = [];
|
|
78
117
|
for (const [path, project] of Object.entries(projects)) {
|
|
79
118
|
const containerStatuses = [];
|
|
80
|
-
for (const containerName of Object.
|
|
119
|
+
for (const [serviceKey, containerName] of Object.entries(project.containers)) {
|
|
81
120
|
if (containerName) {
|
|
121
|
+
if (serviceKey === 'objectstorage') {
|
|
122
|
+
const objectStorage = await this.inspectRegisteredContainer(project, containerName);
|
|
123
|
+
if (!objectStorage) {
|
|
124
|
+
containerStatuses.push({ name: containerName, status: 'not_exists' });
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const expectedLabels = getServiceContainerLabels({
|
|
128
|
+
projectPath: project.projectPath,
|
|
129
|
+
service: 'objectstorage',
|
|
130
|
+
dataPath: getServiceDataDirectory(project.projectPath, 'objectstorage'),
|
|
131
|
+
});
|
|
132
|
+
const owned = hasExactServiceContainerLabels(objectStorage.labels, expectedLabels);
|
|
133
|
+
containerStatuses.push({
|
|
134
|
+
name: containerName,
|
|
135
|
+
status: objectStorage.state,
|
|
136
|
+
ownership: owned ? 'owned' : 'conflict',
|
|
137
|
+
});
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
82
140
|
const status = await this.docker.getStatus(containerName);
|
|
83
141
|
containerStatuses.push({ name: containerName, status });
|
|
84
142
|
}
|
|
@@ -100,14 +158,60 @@ export class GlobalRegistry {
|
|
|
100
158
|
const stopped = [];
|
|
101
159
|
const failed = [];
|
|
102
160
|
for (const project of Object.values(projects)) {
|
|
103
|
-
for (const containerName of Object.
|
|
161
|
+
for (const [serviceKey, containerName] of Object.entries(project.containers)) {
|
|
104
162
|
if (containerName) {
|
|
105
|
-
const
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
163
|
+
const service = registryServiceNames[serviceKey];
|
|
164
|
+
if (!service) {
|
|
165
|
+
failed.push(containerName);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
await withServiceDataOperationLock(project.projectPath, service, async () => {
|
|
170
|
+
const currentProjects = await this.getAllProjects();
|
|
171
|
+
const claims = [];
|
|
172
|
+
for (const [registeredPathArg, registeredProjectArg] of Object.entries(currentProjects)) {
|
|
173
|
+
for (const [registeredServiceKeyArg, registeredNameArg] of Object.entries(registeredProjectArg.containers)) {
|
|
174
|
+
const registeredService = registryServiceNames[registeredServiceKeyArg];
|
|
175
|
+
if (registeredService && registeredNameArg === containerName) {
|
|
176
|
+
claims.push({
|
|
177
|
+
projectPath: plugins.path.resolve(registeredPathArg),
|
|
178
|
+
service: registeredService,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const projectPath = plugins.path.resolve(project.projectPath);
|
|
184
|
+
const currentProject = Object.entries(currentProjects).find(([registeredPathArg]) => plugins.path.resolve(registeredPathArg) === projectPath)?.[1];
|
|
185
|
+
if (!currentProject || currentProject.containers[serviceKey] !== containerName) {
|
|
186
|
+
throw new Error('Registry container claim changed before stop');
|
|
187
|
+
}
|
|
188
|
+
const inspection = await this.inspectRegisteredContainer(currentProject, containerName);
|
|
189
|
+
if (!inspection) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const expectedLabels = getServiceContainerLabels({
|
|
193
|
+
projectPath,
|
|
194
|
+
service,
|
|
195
|
+
dataPath: getServiceDataDirectory(projectPath, service),
|
|
196
|
+
});
|
|
197
|
+
const labelOwned = hasExactServiceContainerLabels(inspection.labels, expectedLabels);
|
|
198
|
+
const hasGitZoneLabels = Object.keys(inspection.labels).some((keyArg) => keyArg.startsWith('git.zone.'));
|
|
199
|
+
const registryOwned = service !== 'objectstorage' &&
|
|
200
|
+
!hasGitZoneLabels &&
|
|
201
|
+
claims.length === 1 &&
|
|
202
|
+
claims[0].projectPath === projectPath &&
|
|
203
|
+
claims[0].service === service;
|
|
204
|
+
if (!labelOwned && !registryOwned) {
|
|
205
|
+
throw new Error('Container ownership conflict');
|
|
206
|
+
}
|
|
207
|
+
if (inspection.running) {
|
|
208
|
+
await this.docker.execArgv(['stop', inspection.id], { timeoutMs: 60_000 });
|
|
209
|
+
stopped.push(containerName);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
if (!failed.includes(containerName)) {
|
|
111
215
|
failed.push(containerName);
|
|
112
216
|
}
|
|
113
217
|
}
|
|
@@ -116,6 +220,28 @@ export class GlobalRegistry {
|
|
|
116
220
|
}
|
|
117
221
|
return { stopped, failed };
|
|
118
222
|
}
|
|
223
|
+
async inspectRegisteredContainer(projectArg, containerNameArg) {
|
|
224
|
+
const ids = await this.docker.listIds([`name=^/${containerNameArg}$`]);
|
|
225
|
+
if (ids.length === 0) {
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
const inspections = (await this.docker.inspectMany(ids)).filter((inspection) => inspection.name === containerNameArg);
|
|
229
|
+
if (inspections.length !== 1) {
|
|
230
|
+
throw new Error(`Docker returned ambiguous ObjectStorage identity for ${projectArg.projectPath}.`);
|
|
231
|
+
}
|
|
232
|
+
return inspections[0];
|
|
233
|
+
}
|
|
234
|
+
async exactContainerExists(containerNameArg) {
|
|
235
|
+
const ids = await this.docker.listIds([`name=^/${containerNameArg}$`]);
|
|
236
|
+
if (ids.length === 0) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
const inspections = (await this.docker.inspectMany(ids)).filter((inspection) => inspection.name === containerNameArg);
|
|
240
|
+
if (inspections.length !== 1) {
|
|
241
|
+
throw new Error(`Docker returned ambiguous container identity for ${containerNameArg}.`);
|
|
242
|
+
}
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
119
245
|
/**
|
|
120
246
|
* Cheap staleness summary for a non-blocking hint after ordinary commands.
|
|
121
247
|
*
|
|
@@ -145,35 +271,57 @@ export class GlobalRegistry {
|
|
|
145
271
|
const projects = await this.getAllProjects();
|
|
146
272
|
const removed = [];
|
|
147
273
|
const kept = [];
|
|
148
|
-
for (const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
// Same rule ServicePruner enforces: for containers created before labels
|
|
153
|
-
// existed, this registry entry is the only thing that can still identify
|
|
154
|
-
// them. Dropping it while one exists would hide the container from prune,
|
|
155
|
-
// `stop -g` and `cleanup -g` alike, leaving it running forever under
|
|
156
|
-
// `restart: unless-stopped`.
|
|
157
|
-
const survivingContainers = [];
|
|
158
|
-
for (const containerName of Object.values(project.containers)) {
|
|
159
|
-
if (!containerName) {
|
|
160
|
-
continue;
|
|
274
|
+
for (const projectPath of Object.keys(projects)) {
|
|
275
|
+
await this.withProjectServiceLocks(projectPath, async () => {
|
|
276
|
+
if (await plugins.smartfs.directory(projectPath).exists()) {
|
|
277
|
+
return;
|
|
161
278
|
}
|
|
162
|
-
|
|
163
|
-
|
|
279
|
+
const currentProject = Object.entries(await this.getAllProjects()).find(([registeredPathArg]) => plugins.path.resolve(registeredPathArg) === plugins.path.resolve(projectPath))?.[1];
|
|
280
|
+
if (!currentProject) {
|
|
281
|
+
return;
|
|
164
282
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
283
|
+
if (currentProject.legacy?.minioContainer) {
|
|
284
|
+
kept.push({
|
|
285
|
+
projectPath,
|
|
286
|
+
reason: `preserved legacy MinIO container reference: ${currentProject.legacy.minioContainer}`,
|
|
287
|
+
});
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
// Same rule ServicePruner enforces: for containers created before labels
|
|
291
|
+
// existed, this registry entry is the only thing that can still identify
|
|
292
|
+
// them. Re-read under all service locks so a concurrent start cannot
|
|
293
|
+
// appear between the Docker check and compare-delete.
|
|
294
|
+
const survivingContainers = [];
|
|
295
|
+
for (const containerName of Object.values(currentProject.containers)) {
|
|
296
|
+
if (containerName && (await this.exactContainerExists(containerName))) {
|
|
297
|
+
survivingContainers.push(containerName);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
const labeledIds = await this.docker.listIds([
|
|
301
|
+
`label=git.zone.project-path=${plugins.path.resolve(projectPath)}`,
|
|
302
|
+
]);
|
|
303
|
+
if (labeledIds.length > 0) {
|
|
304
|
+
survivingContainers.push('project-labeled container');
|
|
305
|
+
}
|
|
306
|
+
if (survivingContainers.length > 0) {
|
|
307
|
+
kept.push({
|
|
308
|
+
projectPath,
|
|
309
|
+
reason: `container(s) still exist: ${survivingContainers.join(', ')}`,
|
|
310
|
+
});
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
await this.unregisterProject(projectPath, currentProject);
|
|
314
|
+
removed.push(projectPath);
|
|
315
|
+
});
|
|
175
316
|
}
|
|
176
317
|
return { removed, kept };
|
|
177
318
|
}
|
|
319
|
+
async withProjectServiceLocks(projectPathArg, actionArg, serviceIndexArg = 0) {
|
|
320
|
+
const service = serviceNames[serviceIndexArg];
|
|
321
|
+
if (!service) {
|
|
322
|
+
return actionArg();
|
|
323
|
+
}
|
|
324
|
+
return withServiceDataOperationLock(projectPathArg, service, () => this.withProjectServiceLocks(projectPathArg, actionArg, serviceIndexArg + 1));
|
|
325
|
+
}
|
|
178
326
|
}
|
|
179
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5nbG9iYWxyZWdpc3RyeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL21vZF9zZXJ2aWNlcy9jbGFzc2VzLmdsb2JhbHJlZ2lzdHJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUF3Qi9DLE1BQU0sT0FBTyxjQUFjO0lBQ2pCLE1BQU0sQ0FBQyxRQUFRLEdBQTBCLElBQUksQ0FBQztJQUM5QyxPQUFPLENBQXlEO0lBQ2hFLE1BQU0sQ0FBa0I7SUFFaEM7UUFDRSxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUM7WUFDbkQsT0FBTyxFQUFFLGFBQWE7WUFDdEIsV0FBVyxFQUFFLGtCQUFrQjtTQUNoQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7SUFDdEMsQ0FBQztJQUVEOztPQUVHO0lBQ0ksTUFBTSxDQUFDLFdBQVc7UUFDdkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUM3QixjQUFjLENBQUMsUUFBUSxHQUFHLElBQUksY0FBYyxFQUFFLENBQUM7UUFDakQsQ0FBQztRQUNELE9BQU8sY0FBYyxDQUFDLFFBQVEsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsZUFBZSxDQUFDLElBQTRDO1FBQ3ZFLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUM3QyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQztRQUV4QyxRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcs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
|
|
327
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5nbG9iYWxyZWdpc3RyeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL21vZF9zZXJ2aWNlcy9jbGFzc2VzLmdsb2JhbHJlZ2lzdHJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxlQUFlLEVBQThCLE1BQU0sOEJBQThCLENBQUM7QUFDM0YsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQy9DLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIsdUJBQXVCLEVBQ3ZCLDhCQUE4QixFQUM5QixZQUFZLEdBRWIsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN4QyxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUM3RSxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLGlDQUFpQyxHQUdsQyxNQUFNLGtDQUFrQyxDQUFDO0FBRTFDLE9BQU8sRUFBRSxpQ0FBaUMsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBTXJGLE1BQU0sb0JBQW9CLEdBQWlDO0lBQ3pELEtBQUssRUFBRSxTQUFTO0lBQ2hCLGFBQWEsRUFBRSxlQUFlO0lBQzlCLGFBQWEsRUFBRSxlQUFlO0NBQy9CLENBQUM7QUFFRixNQUFNLE9BQU8sY0FBYztJQUNqQixNQUFNLENBQUMsUUFBUSxHQUEwQixJQUFJLENBQUM7SUFDOUMsS0FBSyxDQUFzQjtJQUMzQixNQUFNLENBQWtCO0lBRWhDLFlBQW9CLFdBQWdDLElBQUksbUJBQW1CLEVBQUU7UUFDM0UsSUFBSSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUM7UUFDdEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO0lBQ3RDLENBQUM7SUFFRDs7T0FFRztJQUNJLE1BQU0sQ0FBQyxXQUFXO1FBQ3ZCLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDN0Is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
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface IRegisteredProject {
|
|
2
|
+
projectPath: string;
|
|
3
|
+
projectName: string;
|
|
4
|
+
containers: {
|
|
5
|
+
mongo?: string;
|
|
6
|
+
objectstorage?: string;
|
|
7
|
+
elasticsearch?: string;
|
|
8
|
+
};
|
|
9
|
+
ports: {
|
|
10
|
+
mongo?: number;
|
|
11
|
+
s3?: number;
|
|
12
|
+
s3Ui?: number;
|
|
13
|
+
elasticsearch?: number;
|
|
14
|
+
};
|
|
15
|
+
legacy?: {
|
|
16
|
+
/** Preserved migration evidence. Never passed to an active lifecycle operation. */
|
|
17
|
+
minioContainer?: string;
|
|
18
|
+
};
|
|
19
|
+
enabledServices: string[];
|
|
20
|
+
lastActive: number;
|
|
21
|
+
}
|
|
22
|
+
export interface IGlobalRegistryData {
|
|
23
|
+
schemaVersion: 2;
|
|
24
|
+
projects: {
|
|
25
|
+
[projectPath: string]: IRegisteredProject;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** Validate the canonical runtime schema after startup migrations have completed. */
|
|
29
|
+
export declare const assertCanonicalGlobalRegistryData: (dataArg: unknown) => IGlobalRegistryData;
|
|
30
|
+
export interface IGlobalRegistryTransactionResult<T> {
|
|
31
|
+
result: T;
|
|
32
|
+
writeData?: IGlobalRegistryData;
|
|
33
|
+
}
|
|
34
|
+
export interface IGlobalRegistryStoreOptions {
|
|
35
|
+
filePath?: string;
|
|
36
|
+
lockTimeoutMs?: number;
|
|
37
|
+
lockPollMs?: number;
|
|
38
|
+
}
|
|
39
|
+
/** Raw, atomically replaced registry storage shared by runtime and migrations. */
|
|
40
|
+
export declare class GlobalRegistryStore {
|
|
41
|
+
readonly filePath: string;
|
|
42
|
+
private readonly lock;
|
|
43
|
+
constructor(optionsArg?: IGlobalRegistryStoreOptions);
|
|
44
|
+
readRaw(): Promise<unknown>;
|
|
45
|
+
readCanonical(): Promise<IGlobalRegistryData>;
|
|
46
|
+
transact<T>(operationArg: (rawDataArg: unknown) => Promise<IGlobalRegistryTransactionResult<T>> | IGlobalRegistryTransactionResult<T>): Promise<T>;
|
|
47
|
+
private writeAtomic;
|
|
48
|
+
}
|