@serve.zone/gitops 2.13.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.
- package/.smartconfig.json +114 -0
- package/binary/gitops.ts +4 -0
- package/changelog.md +185 -0
- package/cli.child.js +4 -0
- package/cli.js +4 -0
- package/cli.ts.js +5 -0
- package/deno.json +10 -0
- package/dist_serve/bundle.js +36362 -0
- package/dist_serve/index.html +33 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/cache/classes.cache.cleaner.d.ts +23 -0
- package/dist_ts/cache/classes.cache.cleaner.js +61 -0
- package/dist_ts/cache/classes.cached.document.d.ts +30 -0
- package/dist_ts/cache/classes.cached.document.js +101 -0
- package/dist_ts/cache/classes.cachedb.d.ts +22 -0
- package/dist_ts/cache/classes.cachedb.js +58 -0
- package/dist_ts/cache/classes.secrets.scan.service.d.ts +51 -0
- package/dist_ts/cache/classes.secrets.scan.service.js +237 -0
- package/dist_ts/cache/documents/classes.cached.project.d.ts +13 -0
- package/dist_ts/cache/documents/classes.cached.project.js +101 -0
- package/dist_ts/cache/documents/classes.cached.secret.d.ts +24 -0
- package/dist_ts/cache/documents/classes.cached.secret.js +158 -0
- package/dist_ts/cache/documents/index.d.ts +2 -0
- package/dist_ts/cache/documents/index.js +3 -0
- package/dist_ts/cache/index.d.ts +7 -0
- package/dist_ts/cache/index.js +6 -0
- package/dist_ts/classes/actionlog.d.ts +19 -0
- package/dist_ts/classes/actionlog.js +44 -0
- package/dist_ts/classes/connectionmanager.d.ts +57 -0
- package/dist_ts/classes/connectionmanager.js +247 -0
- package/dist_ts/classes/gitopsapp.d.ts +30 -0
- package/dist_ts/classes/gitopsapp.js +101 -0
- package/dist_ts/classes/jobmanager.d.ts +47 -0
- package/dist_ts/classes/jobmanager.js +301 -0
- package/dist_ts/classes/jobrunners/autobookstackdocs.runner.d.ts +29 -0
- package/dist_ts/classes/jobrunners/autobookstackdocs.runner.js +361 -0
- package/dist_ts/classes/jobrunners/base.jobrunner.d.ts +14 -0
- package/dist_ts/classes/jobrunners/base.jobrunner.js +3 -0
- package/dist_ts/classes/jobrunners/index.d.ts +5 -0
- package/dist_ts/classes/jobrunners/index.js +14 -0
- package/dist_ts/classes/managedsecrets.manager.d.ts +47 -0
- package/dist_ts/classes/managedsecrets.manager.js +247 -0
- package/dist_ts/classes/syncmanager.d.ts +189 -0
- package/dist_ts/classes/syncmanager.js +1787 -0
- package/dist_ts/index.d.ts +6 -0
- package/dist_ts/index.js +32 -0
- package/dist_ts/logging.d.ts +49 -0
- package/dist_ts/logging.js +134 -0
- package/dist_ts/opsserver/classes.opsserver.d.ts +25 -0
- package/dist_ts/opsserver/classes.opsserver.js +70 -0
- package/dist_ts/opsserver/handlers/actionlog.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/actionlog.handler.js +24 -0
- package/dist_ts/opsserver/handlers/actions.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/actions.handler.js +38 -0
- package/dist_ts/opsserver/handlers/admin.handler.d.ts +19 -0
- package/dist_ts/opsserver/handlers/admin.handler.js +96 -0
- package/dist_ts/opsserver/handlers/connections.handler.d.ts +10 -0
- package/dist_ts/opsserver/handlers/connections.handler.js +109 -0
- package/dist_ts/opsserver/handlers/groups.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/groups.handler.js +24 -0
- package/dist_ts/opsserver/handlers/index.d.ts +13 -0
- package/dist_ts/opsserver/handlers/index.js +14 -0
- package/dist_ts/opsserver/handlers/jobs.handler.d.ts +16 -0
- package/dist_ts/opsserver/handlers/jobs.handler.js +146 -0
- package/dist_ts/opsserver/handlers/logs.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/logs.handler.js +21 -0
- package/dist_ts/opsserver/handlers/managedsecrets.handler.d.ts +11 -0
- package/dist_ts/opsserver/handlers/managedsecrets.handler.js +110 -0
- package/dist_ts/opsserver/handlers/pipelines.handler.d.ts +31 -0
- package/dist_ts/opsserver/handlers/pipelines.handler.js +204 -0
- package/dist_ts/opsserver/handlers/projects.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/projects.handler.js +24 -0
- package/dist_ts/opsserver/handlers/secrets.handler.d.ts +10 -0
- package/dist_ts/opsserver/handlers/secrets.handler.js +171 -0
- package/dist_ts/opsserver/handlers/sync.handler.d.ts +16 -0
- package/dist_ts/opsserver/handlers/sync.handler.js +166 -0
- package/dist_ts/opsserver/handlers/webhook.handler.d.ts +7 -0
- package/dist_ts/opsserver/handlers/webhook.handler.js +55 -0
- package/dist_ts/opsserver/helpers/guards.d.ts +5 -0
- package/dist_ts/opsserver/helpers/guards.js +12 -0
- package/dist_ts/opsserver/index.d.ts +1 -0
- package/dist_ts/opsserver/index.js +2 -0
- package/dist_ts/paths.d.ts +9 -0
- package/dist_ts/paths.js +13 -0
- package/dist_ts/plugins.d.ts +25 -0
- package/dist_ts/plugins.js +32 -0
- package/dist_ts/providers/classes.baseprovider.d.ts +51 -0
- package/dist_ts/providers/classes.baseprovider.js +17 -0
- package/dist_ts/providers/classes.giteaprovider.d.ts +40 -0
- package/dist_ts/providers/classes.giteaprovider.js +224 -0
- package/dist_ts/providers/classes.gitlabprovider.d.ts +39 -0
- package/dist_ts/providers/classes.gitlabprovider.js +207 -0
- package/dist_ts/providers/index.d.ts +3 -0
- package/dist_ts/providers/index.js +4 -0
- package/dist_ts/storage/classes.storagemanager.d.ts +33 -0
- package/dist_ts/storage/classes.storagemanager.js +135 -0
- package/dist_ts/storage/index.d.ts +2 -0
- package/dist_ts/storage/index.js +2 -0
- package/dist_ts/timers.d.ts +4 -0
- package/dist_ts/timers.js +24 -0
- package/dist_ts_bundled/bundle.d.ts +4 -0
- package/dist_ts_bundled/bundle.js +12 -0
- package/dist_ts_interfaces/data/actionlog.d.ts +12 -0
- package/dist_ts_interfaces/data/actionlog.js +2 -0
- package/dist_ts_interfaces/data/branch.d.ts +8 -0
- package/dist_ts_interfaces/data/branch.js +2 -0
- package/dist_ts_interfaces/data/connection.d.ts +12 -0
- package/dist_ts_interfaces/data/connection.js +2 -0
- package/dist_ts_interfaces/data/group.d.ts +10 -0
- package/dist_ts_interfaces/data/group.js +2 -0
- package/dist_ts_interfaces/data/identity.d.ts +7 -0
- package/dist_ts_interfaces/data/identity.js +2 -0
- package/dist_ts_interfaces/data/index.d.ts +11 -0
- package/dist_ts_interfaces/data/index.js +12 -0
- package/dist_ts_interfaces/data/job.d.ts +37 -0
- package/dist_ts_interfaces/data/job.js +2 -0
- package/dist_ts_interfaces/data/managedsecret.d.ts +37 -0
- package/dist_ts_interfaces/data/managedsecret.js +2 -0
- package/dist_ts_interfaces/data/pipeline.d.ts +22 -0
- package/dist_ts_interfaces/data/pipeline.js +2 -0
- package/dist_ts_interfaces/data/project.d.ts +12 -0
- package/dist_ts_interfaces/data/project.js +2 -0
- package/dist_ts_interfaces/data/secret.d.ts +11 -0
- package/dist_ts_interfaces/data/secret.js +2 -0
- package/dist_ts_interfaces/data/sync.d.ts +34 -0
- package/dist_ts_interfaces/data/sync.js +2 -0
- package/dist_ts_interfaces/index.d.ts +5 -0
- package/dist_ts_interfaces/index.js +8 -0
- package/dist_ts_interfaces/plugins.d.ts +2 -0
- package/dist_ts_interfaces/plugins.js +4 -0
- package/dist_ts_interfaces/requests/actionlog.d.ts +15 -0
- package/dist_ts_interfaces/requests/actionlog.js +3 -0
- package/dist_ts_interfaces/requests/actions.d.ts +31 -0
- package/dist_ts_interfaces/requests/actions.js +3 -0
- package/dist_ts_interfaces/requests/admin.d.ts +31 -0
- package/dist_ts_interfaces/requests/admin.js +3 -0
- package/dist_ts_interfaces/requests/connections.d.ts +71 -0
- package/dist_ts_interfaces/requests/connections.js +3 -0
- package/dist_ts_interfaces/requests/groups.d.ts +14 -0
- package/dist_ts_interfaces/requests/groups.js +3 -0
- package/dist_ts_interfaces/requests/index.d.ts +13 -0
- package/dist_ts_interfaces/requests/index.js +14 -0
- package/dist_ts_interfaces/requests/jobs.d.ts +86 -0
- package/dist_ts_interfaces/requests/jobs.js +3 -0
- package/dist_ts_interfaces/requests/logs.d.ts +14 -0
- package/dist_ts_interfaces/requests/logs.js +3 -0
- package/dist_ts_interfaces/requests/managedsecrets.d.ts +84 -0
- package/dist_ts_interfaces/requests/managedsecrets.js +3 -0
- package/dist_ts_interfaces/requests/pipelines.d.ts +55 -0
- package/dist_ts_interfaces/requests/pipelines.js +3 -0
- package/dist_ts_interfaces/requests/projects.d.ts +14 -0
- package/dist_ts_interfaces/requests/projects.js +3 -0
- package/dist_ts_interfaces/requests/secrets.d.ts +72 -0
- package/dist_ts_interfaces/requests/secrets.js +3 -0
- package/dist_ts_interfaces/requests/sync.d.ts +120 -0
- package/dist_ts_interfaces/requests/sync.js +3 -0
- package/dist_ts_interfaces/requests/webhook.d.ts +13 -0
- package/dist_ts_interfaces/requests/webhook.js +3 -0
- package/license +21 -0
- package/package.json +81 -0
- package/readme.md +177 -0
- package/readme.todo.md +3 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/cache/classes.cache.cleaner.ts +69 -0
- package/ts/cache/classes.cached.document.ts +57 -0
- package/ts/cache/classes.cachedb.ts +72 -0
- package/ts/cache/classes.secrets.scan.service.ts +267 -0
- package/ts/cache/documents/classes.cached.project.ts +32 -0
- package/ts/cache/documents/classes.cached.secret.ts +81 -0
- package/ts/cache/documents/index.ts +2 -0
- package/ts/cache/index.ts +7 -0
- package/ts/classes/actionlog.ts +57 -0
- package/ts/classes/connectionmanager.ts +263 -0
- package/ts/classes/gitopsapp.ts +128 -0
- package/ts/classes/jobmanager.ts +337 -0
- package/ts/classes/jobrunners/autobookstackdocs.runner.ts +435 -0
- package/ts/classes/jobrunners/base.jobrunner.ts +16 -0
- package/ts/classes/jobrunners/index.ts +17 -0
- package/ts/classes/managedsecrets.manager.ts +322 -0
- package/ts/classes/syncmanager.ts +2117 -0
- package/ts/index.ts +37 -0
- package/ts/logging.ts +162 -0
- package/ts/opsserver/classes.opsserver.ts +86 -0
- package/ts/opsserver/handlers/actionlog.handler.ts +30 -0
- package/ts/opsserver/handlers/actions.handler.ts +50 -0
- package/ts/opsserver/handlers/admin.handler.ts +122 -0
- package/ts/opsserver/handlers/connections.handler.ts +162 -0
- package/ts/opsserver/handlers/groups.handler.ts +32 -0
- package/ts/opsserver/handlers/index.ts +13 -0
- package/ts/opsserver/handlers/jobs.handler.ts +189 -0
- package/ts/opsserver/handlers/logs.handler.ts +29 -0
- package/ts/opsserver/handlers/managedsecrets.handler.ts +158 -0
- package/ts/opsserver/handlers/pipelines.handler.ts +281 -0
- package/ts/opsserver/handlers/projects.handler.ts +32 -0
- package/ts/opsserver/handlers/secrets.handler.ts +224 -0
- package/ts/opsserver/handlers/sync.handler.ts +224 -0
- package/ts/opsserver/handlers/webhook.handler.ts +62 -0
- package/ts/opsserver/helpers/guards.ts +16 -0
- package/ts/opsserver/index.ts +1 -0
- package/ts/paths.ts +19 -0
- package/ts/plugins.ts +38 -0
- package/ts/providers/classes.baseprovider.ts +99 -0
- package/ts/providers/classes.giteaprovider.ts +279 -0
- package/ts/providers/classes.gitlabprovider.ts +265 -0
- package/ts/providers/index.ts +3 -0
- package/ts/storage/classes.storagemanager.ts +144 -0
- package/ts/storage/index.ts +2 -0
- package/ts/timers.ts +34 -0
- package/ts_interfaces/data/actionlog.ts +13 -0
- package/ts_interfaces/data/branch.ts +9 -0
- package/ts_interfaces/data/connection.ts +13 -0
- package/ts_interfaces/data/group.ts +10 -0
- package/ts_interfaces/data/identity.ts +7 -0
- package/ts_interfaces/data/index.ts +11 -0
- package/ts_interfaces/data/job.ts +42 -0
- package/ts_interfaces/data/managedsecret.ts +41 -0
- package/ts_interfaces/data/pipeline.ts +32 -0
- package/ts_interfaces/data/project.ts +12 -0
- package/ts_interfaces/data/secret.ts +11 -0
- package/ts_interfaces/data/sync.ts +37 -0
- package/ts_interfaces/index.ts +9 -0
- package/ts_interfaces/plugins.ts +6 -0
- package/ts_interfaces/requests/actionlog.ts +19 -0
- package/ts_interfaces/requests/actions.ts +39 -0
- package/ts_interfaces/requests/admin.ts +43 -0
- package/ts_interfaces/requests/connections.ts +95 -0
- package/ts_interfaces/requests/groups.ts +18 -0
- package/ts_interfaces/requests/index.ts +13 -0
- package/ts_interfaces/requests/jobs.ts +118 -0
- package/ts_interfaces/requests/logs.ts +18 -0
- package/ts_interfaces/requests/managedsecrets.ts +112 -0
- package/ts_interfaces/requests/pipelines.ts +71 -0
- package/ts_interfaces/requests/projects.ts +18 -0
- package/ts_interfaces/requests/secrets.ts +92 -0
- package/ts_interfaces/requests/sync.ts +157 -0
- package/ts_interfaces/requests/webhook.ts +18 -0
- package/ts_web/00_commitinfo_data.ts +8 -0
- package/ts_web/appstate.ts +1251 -0
- package/ts_web/elements/gitops-dashboard.ts +350 -0
- package/ts_web/elements/index.ts +10 -0
- package/ts_web/elements/shared/css.ts +29 -0
- package/ts_web/elements/shared/index.ts +1 -0
- package/ts_web/elements/views/actionlog/index.ts +101 -0
- package/ts_web/elements/views/actions/index.ts +209 -0
- package/ts_web/elements/views/buildlog/index.ts +196 -0
- package/ts_web/elements/views/connections/index.ts +260 -0
- package/ts_web/elements/views/groups/index.ts +134 -0
- package/ts_web/elements/views/jobs/index.ts +424 -0
- package/ts_web/elements/views/managedsecrets/index.ts +502 -0
- package/ts_web/elements/views/overview/index.ts +86 -0
- package/ts_web/elements/views/pipelines/index.ts +561 -0
- package/ts_web/elements/views/projects/index.ts +149 -0
- package/ts_web/elements/views/secrets/index.ts +310 -0
- package/ts_web/elements/views/sync/index.ts +512 -0
- package/ts_web/index.ts +7 -0
- package/ts_web/plugins.ts +15 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { AdminHandler } from './admin.handler.js';
|
|
2
|
+
export { ConnectionsHandler } from './connections.handler.js';
|
|
3
|
+
export { ProjectsHandler } from './projects.handler.js';
|
|
4
|
+
export { GroupsHandler } from './groups.handler.js';
|
|
5
|
+
export { SecretsHandler } from './secrets.handler.js';
|
|
6
|
+
export { PipelinesHandler } from './pipelines.handler.js';
|
|
7
|
+
export { LogsHandler } from './logs.handler.js';
|
|
8
|
+
export { WebhookHandler } from './webhook.handler.js';
|
|
9
|
+
export { ActionsHandler } from './actions.handler.js';
|
|
10
|
+
export { ActionLogHandler } from './actionlog.handler.js';
|
|
11
|
+
export { SyncHandler } from './sync.handler.js';
|
|
12
|
+
export { ManagedSecretsHandler } from './managedsecrets.handler.js';
|
|
13
|
+
export { JobsHandler } from './jobs.handler.js';
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
|
+
import * as interfaces from '../../../ts_interfaces/index.js';
|
|
4
|
+
import { requireValidIdentity } from '../helpers/guards.js';
|
|
5
|
+
import { logger } from '../../logging.js';
|
|
6
|
+
|
|
7
|
+
export class JobsHandler {
|
|
8
|
+
public typedrouter = new plugins.typedrequest.TypedRouter();
|
|
9
|
+
|
|
10
|
+
constructor(private opsServerRef: OpsServer) {
|
|
11
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
12
|
+
this.registerHandlers();
|
|
13
|
+
this.setupBroadcast();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Wire the logger's job broadcast function to push log entries
|
|
18
|
+
* to all connected frontends via TypedSocket.
|
|
19
|
+
*/
|
|
20
|
+
private setupBroadcast(): void {
|
|
21
|
+
logger.setJobBroadcastFn((entry) => {
|
|
22
|
+
try {
|
|
23
|
+
const typedsocket = this.opsServerRef.server?.typedserver?.typedsocket;
|
|
24
|
+
if (!typedsocket) return;
|
|
25
|
+
typedsocket.findAllTargetConnectionsByTag('jobLogClient').then((connections) => {
|
|
26
|
+
for (const conn of connections) {
|
|
27
|
+
typedsocket
|
|
28
|
+
.createTypedRequest<interfaces.requests.IReq_PushJobLog>('pushJobLog', conn)
|
|
29
|
+
.fire({ entry })
|
|
30
|
+
.catch(() => {});
|
|
31
|
+
}
|
|
32
|
+
}).catch(() => {});
|
|
33
|
+
} catch {
|
|
34
|
+
// Server may not be ready yet — ignore
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private get jobManager() {
|
|
40
|
+
return this.opsServerRef.gitopsAppRef.jobManager;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private get actionLog() {
|
|
44
|
+
return this.opsServerRef.gitopsAppRef.actionLog;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private registerHandlers(): void {
|
|
48
|
+
// Get all jobs
|
|
49
|
+
this.typedrouter.addTypedHandler(
|
|
50
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetJobs>(
|
|
51
|
+
'getJobs',
|
|
52
|
+
async (dataArg) => {
|
|
53
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
54
|
+
return { jobs: this.jobManager.getJobs() };
|
|
55
|
+
},
|
|
56
|
+
),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
// Create job
|
|
60
|
+
this.typedrouter.addTypedHandler(
|
|
61
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateJob>(
|
|
62
|
+
'createJob',
|
|
63
|
+
async (dataArg) => {
|
|
64
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
65
|
+
const job = await this.jobManager.createJob({
|
|
66
|
+
name: dataArg.name,
|
|
67
|
+
jobType: dataArg.jobType,
|
|
68
|
+
intervalMinutes: dataArg.intervalMinutes,
|
|
69
|
+
autoBookstackDocsConfig: dataArg.autoBookstackDocsConfig,
|
|
70
|
+
});
|
|
71
|
+
this.actionLog.append({
|
|
72
|
+
actionType: 'create',
|
|
73
|
+
entityType: 'job',
|
|
74
|
+
entityId: job.id,
|
|
75
|
+
entityName: job.name,
|
|
76
|
+
details: `Created ${job.jobType} job`,
|
|
77
|
+
username: dataArg.identity.username,
|
|
78
|
+
});
|
|
79
|
+
return { job };
|
|
80
|
+
},
|
|
81
|
+
),
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// Update job
|
|
85
|
+
this.typedrouter.addTypedHandler(
|
|
86
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateJob>(
|
|
87
|
+
'updateJob',
|
|
88
|
+
async (dataArg) => {
|
|
89
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
90
|
+
const job = await this.jobManager.updateJob(dataArg.jobId, {
|
|
91
|
+
name: dataArg.name,
|
|
92
|
+
intervalMinutes: dataArg.intervalMinutes,
|
|
93
|
+
autoBookstackDocsConfig: dataArg.autoBookstackDocsConfig,
|
|
94
|
+
});
|
|
95
|
+
this.actionLog.append({
|
|
96
|
+
actionType: 'update',
|
|
97
|
+
entityType: 'job',
|
|
98
|
+
entityId: job.id,
|
|
99
|
+
entityName: job.name,
|
|
100
|
+
details: 'Updated job configuration',
|
|
101
|
+
username: dataArg.identity.username,
|
|
102
|
+
});
|
|
103
|
+
return { job };
|
|
104
|
+
},
|
|
105
|
+
),
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// Delete job
|
|
109
|
+
this.typedrouter.addTypedHandler(
|
|
110
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteJob>(
|
|
111
|
+
'deleteJob',
|
|
112
|
+
async (dataArg) => {
|
|
113
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
114
|
+
const job = this.jobManager.getJob(dataArg.jobId);
|
|
115
|
+
await this.jobManager.deleteJob(dataArg.jobId);
|
|
116
|
+
this.actionLog.append({
|
|
117
|
+
actionType: 'delete',
|
|
118
|
+
entityType: 'job',
|
|
119
|
+
entityId: dataArg.jobId,
|
|
120
|
+
entityName: job?.name || dataArg.jobId,
|
|
121
|
+
details: 'Deleted job',
|
|
122
|
+
username: dataArg.identity.username,
|
|
123
|
+
});
|
|
124
|
+
return { ok: true };
|
|
125
|
+
},
|
|
126
|
+
),
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
// Pause/resume job
|
|
130
|
+
this.typedrouter.addTypedHandler(
|
|
131
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_PauseJob>(
|
|
132
|
+
'pauseJob',
|
|
133
|
+
async (dataArg) => {
|
|
134
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
135
|
+
const job = await this.jobManager.pauseJob(dataArg.jobId, dataArg.paused);
|
|
136
|
+
this.actionLog.append({
|
|
137
|
+
actionType: dataArg.paused ? 'pause' : 'resume',
|
|
138
|
+
entityType: 'job',
|
|
139
|
+
entityId: job.id,
|
|
140
|
+
entityName: job.name,
|
|
141
|
+
details: dataArg.paused ? 'Paused job' : 'Resumed job',
|
|
142
|
+
username: dataArg.identity.username,
|
|
143
|
+
});
|
|
144
|
+
return { job };
|
|
145
|
+
},
|
|
146
|
+
),
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
// Trigger job manually
|
|
150
|
+
this.typedrouter.addTypedHandler(
|
|
151
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_TriggerJob>(
|
|
152
|
+
'triggerJob',
|
|
153
|
+
async (dataArg) => {
|
|
154
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
155
|
+
const job = this.jobManager.getJob(dataArg.jobId);
|
|
156
|
+
if (!job) {
|
|
157
|
+
return { ok: false, message: `Job not found: ${dataArg.jobId}` };
|
|
158
|
+
}
|
|
159
|
+
if (this.jobManager.isJobRunning(dataArg.jobId)) {
|
|
160
|
+
return { ok: false, message: 'Job is already running' };
|
|
161
|
+
}
|
|
162
|
+
// Fire-and-forget
|
|
163
|
+
this.jobManager.executeJob(dataArg.jobId, true).catch(() => {});
|
|
164
|
+
this.actionLog.append({
|
|
165
|
+
actionType: 'run',
|
|
166
|
+
entityType: 'job',
|
|
167
|
+
entityId: job.id,
|
|
168
|
+
entityName: job.name,
|
|
169
|
+
details: 'Manually triggered job execution',
|
|
170
|
+
username: dataArg.identity.username,
|
|
171
|
+
});
|
|
172
|
+
return { ok: true, message: 'Job triggered' };
|
|
173
|
+
},
|
|
174
|
+
),
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
// Get job logs
|
|
178
|
+
this.typedrouter.addTypedHandler(
|
|
179
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetJobLogs>(
|
|
180
|
+
'getJobLogs',
|
|
181
|
+
async (dataArg) => {
|
|
182
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
183
|
+
const logs = logger.getJobLogs(dataArg.limit || 200);
|
|
184
|
+
return { logs };
|
|
185
|
+
},
|
|
186
|
+
),
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
|
+
import * as interfaces from '../../../ts_interfaces/index.js';
|
|
4
|
+
import { requireValidIdentity } from '../helpers/guards.js';
|
|
5
|
+
|
|
6
|
+
export class LogsHandler {
|
|
7
|
+
public typedrouter = new plugins.typedrequest.TypedRouter();
|
|
8
|
+
|
|
9
|
+
constructor(private opsServerRef: OpsServer) {
|
|
10
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
11
|
+
this.registerHandlers();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private registerHandlers(): void {
|
|
15
|
+
this.typedrouter.addTypedHandler(
|
|
16
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetJobLog>(
|
|
17
|
+
'getJobLog',
|
|
18
|
+
async (dataArg) => {
|
|
19
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
20
|
+
const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
|
|
21
|
+
dataArg.connectionId,
|
|
22
|
+
);
|
|
23
|
+
const log = await provider.getJobLog(dataArg.projectId, dataArg.jobId);
|
|
24
|
+
return { log };
|
|
25
|
+
},
|
|
26
|
+
),
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
|
+
import * as interfaces from '../../../ts_interfaces/index.js';
|
|
4
|
+
import { requireValidIdentity } from '../helpers/guards.js';
|
|
5
|
+
|
|
6
|
+
export class ManagedSecretsHandler {
|
|
7
|
+
public typedrouter = new plugins.typedrequest.TypedRouter();
|
|
8
|
+
|
|
9
|
+
constructor(private opsServerRef: OpsServer) {
|
|
10
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
11
|
+
this.registerHandlers();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private get actionLog() {
|
|
15
|
+
return this.opsServerRef.gitopsAppRef.actionLog;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private get manager() {
|
|
19
|
+
return this.opsServerRef.gitopsAppRef.managedSecretsManager;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private registerHandlers(): void {
|
|
23
|
+
// List all managed secrets
|
|
24
|
+
this.typedrouter.addTypedHandler(
|
|
25
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetManagedSecrets>(
|
|
26
|
+
'getManagedSecrets',
|
|
27
|
+
async (dataArg) => {
|
|
28
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
29
|
+
const managedSecrets = await this.manager.getAll();
|
|
30
|
+
return { managedSecrets };
|
|
31
|
+
},
|
|
32
|
+
),
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
// Get single managed secret
|
|
36
|
+
this.typedrouter.addTypedHandler(
|
|
37
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetManagedSecret>(
|
|
38
|
+
'getManagedSecret',
|
|
39
|
+
async (dataArg) => {
|
|
40
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
41
|
+
const managedSecret = await this.manager.getById(dataArg.managedSecretId);
|
|
42
|
+
if (!managedSecret) throw new Error(`Managed secret not found: ${dataArg.managedSecretId}`);
|
|
43
|
+
return { managedSecret };
|
|
44
|
+
},
|
|
45
|
+
),
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Create managed secret
|
|
49
|
+
this.typedrouter.addTypedHandler(
|
|
50
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateManagedSecret>(
|
|
51
|
+
'createManagedSecret',
|
|
52
|
+
async (dataArg) => {
|
|
53
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
54
|
+
const result = await this.manager.create(
|
|
55
|
+
dataArg.key,
|
|
56
|
+
dataArg.value,
|
|
57
|
+
dataArg.description,
|
|
58
|
+
dataArg.targets,
|
|
59
|
+
);
|
|
60
|
+
this.actionLog.append({
|
|
61
|
+
actionType: 'create',
|
|
62
|
+
entityType: 'managed-secret',
|
|
63
|
+
entityId: result.managedSecret.id,
|
|
64
|
+
entityName: `GITOPS_${dataArg.key}`,
|
|
65
|
+
details: `Created managed secret "${dataArg.key}" with ${dataArg.targets.length} target(s)`,
|
|
66
|
+
username: dataArg.identity.username,
|
|
67
|
+
});
|
|
68
|
+
return result;
|
|
69
|
+
},
|
|
70
|
+
),
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
// Update managed secret
|
|
74
|
+
this.typedrouter.addTypedHandler(
|
|
75
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateManagedSecret>(
|
|
76
|
+
'updateManagedSecret',
|
|
77
|
+
async (dataArg) => {
|
|
78
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
79
|
+
const result = await this.manager.update(dataArg.managedSecretId, {
|
|
80
|
+
value: dataArg.value,
|
|
81
|
+
description: dataArg.description,
|
|
82
|
+
targets: dataArg.targets,
|
|
83
|
+
});
|
|
84
|
+
this.actionLog.append({
|
|
85
|
+
actionType: 'update',
|
|
86
|
+
entityType: 'managed-secret',
|
|
87
|
+
entityId: dataArg.managedSecretId,
|
|
88
|
+
entityName: `GITOPS_${result.managedSecret.key}`,
|
|
89
|
+
details: `Updated managed secret "${result.managedSecret.key}"`,
|
|
90
|
+
username: dataArg.identity.username,
|
|
91
|
+
});
|
|
92
|
+
return result;
|
|
93
|
+
},
|
|
94
|
+
),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
// Delete managed secret
|
|
98
|
+
this.typedrouter.addTypedHandler(
|
|
99
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteManagedSecret>(
|
|
100
|
+
'deleteManagedSecret',
|
|
101
|
+
async (dataArg) => {
|
|
102
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
103
|
+
const secret = await this.manager.getById(dataArg.managedSecretId);
|
|
104
|
+
const result = await this.manager.delete(dataArg.managedSecretId);
|
|
105
|
+
this.actionLog.append({
|
|
106
|
+
actionType: 'delete',
|
|
107
|
+
entityType: 'managed-secret',
|
|
108
|
+
entityId: dataArg.managedSecretId,
|
|
109
|
+
entityName: secret ? `GITOPS_${secret.key}` : dataArg.managedSecretId,
|
|
110
|
+
details: `Deleted managed secret${secret ? ` "${secret.key}"` : ''}`,
|
|
111
|
+
username: dataArg.identity.username,
|
|
112
|
+
});
|
|
113
|
+
return result;
|
|
114
|
+
},
|
|
115
|
+
),
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// Push single managed secret
|
|
119
|
+
this.typedrouter.addTypedHandler(
|
|
120
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_PushManagedSecret>(
|
|
121
|
+
'pushManagedSecret',
|
|
122
|
+
async (dataArg) => {
|
|
123
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
124
|
+
const result = await this.manager.pushOne(dataArg.managedSecretId);
|
|
125
|
+
this.actionLog.append({
|
|
126
|
+
actionType: 'push',
|
|
127
|
+
entityType: 'managed-secret',
|
|
128
|
+
entityId: dataArg.managedSecretId,
|
|
129
|
+
entityName: `GITOPS_${result.managedSecret.key}`,
|
|
130
|
+
details: `Pushed managed secret "${result.managedSecret.key}" to ${result.pushResults.length} target(s)`,
|
|
131
|
+
username: dataArg.identity.username,
|
|
132
|
+
});
|
|
133
|
+
return result;
|
|
134
|
+
},
|
|
135
|
+
),
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
// Push all managed secrets
|
|
139
|
+
this.typedrouter.addTypedHandler(
|
|
140
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_PushAllManagedSecrets>(
|
|
141
|
+
'pushAllManagedSecrets',
|
|
142
|
+
async (dataArg) => {
|
|
143
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
144
|
+
const results = await this.manager.pushAll();
|
|
145
|
+
this.actionLog.append({
|
|
146
|
+
actionType: 'push',
|
|
147
|
+
entityType: 'managed-secret',
|
|
148
|
+
entityId: 'all',
|
|
149
|
+
entityName: 'All managed secrets',
|
|
150
|
+
details: `Pushed ${results.length} managed secret(s) to their targets`,
|
|
151
|
+
username: dataArg.identity.username,
|
|
152
|
+
});
|
|
153
|
+
return { results };
|
|
154
|
+
},
|
|
155
|
+
),
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
|
+
import * as interfaces from '../../../ts_interfaces/index.js';
|
|
4
|
+
import { requireValidIdentity } from '../helpers/guards.js';
|
|
5
|
+
import type { BaseProvider } from '../../providers/classes.baseprovider.js';
|
|
6
|
+
|
|
7
|
+
const TIME_RANGE_MS: Record<string, number> = {
|
|
8
|
+
'1h': 60 * 60 * 1000,
|
|
9
|
+
'6h': 6 * 60 * 60 * 1000,
|
|
10
|
+
'1d': 24 * 60 * 60 * 1000,
|
|
11
|
+
'3d': 3 * 24 * 60 * 60 * 1000,
|
|
12
|
+
'7d': 7 * 24 * 60 * 60 * 1000,
|
|
13
|
+
'30d': 30 * 24 * 60 * 60 * 1000,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const STATUS_PRIORITY: Record<string, number> = {
|
|
17
|
+
running: 0,
|
|
18
|
+
pending: 1,
|
|
19
|
+
waiting: 2,
|
|
20
|
+
manual: 3,
|
|
21
|
+
failed: 4,
|
|
22
|
+
canceled: 5,
|
|
23
|
+
success: 6,
|
|
24
|
+
skipped: 7,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export class PipelinesHandler {
|
|
28
|
+
public typedrouter = new plugins.typedrequest.TypedRouter();
|
|
29
|
+
|
|
30
|
+
constructor(private opsServerRef: OpsServer) {
|
|
31
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
32
|
+
this.registerHandlers();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private get actionLog() {
|
|
36
|
+
return this.opsServerRef.gitopsAppRef.actionLog;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private registerHandlers(): void {
|
|
40
|
+
// Get pipelines — supports view modes
|
|
41
|
+
this.typedrouter.addTypedHandler(
|
|
42
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetPipelines>(
|
|
43
|
+
'getPipelines',
|
|
44
|
+
async (dataArg) => {
|
|
45
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
46
|
+
const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
|
|
47
|
+
dataArg.connectionId,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const viewMode = dataArg.viewMode || 'project';
|
|
51
|
+
const timeRange = dataArg.timeRange || '1d';
|
|
52
|
+
const sortBy = dataArg.sortBy || 'created';
|
|
53
|
+
|
|
54
|
+
let pipelines: interfaces.data.IPipeline[];
|
|
55
|
+
|
|
56
|
+
if (viewMode === 'project') {
|
|
57
|
+
if (!dataArg.projectId) return { pipelines: [] };
|
|
58
|
+
pipelines = await provider.getPipelines(dataArg.projectId, {
|
|
59
|
+
page: dataArg.page,
|
|
60
|
+
status: dataArg.status,
|
|
61
|
+
});
|
|
62
|
+
pipelines = this.filterByTimeRange(pipelines, timeRange);
|
|
63
|
+
} else if (viewMode === 'current') {
|
|
64
|
+
pipelines = await this.fetchCurrentPipelines(provider, timeRange);
|
|
65
|
+
} else if (viewMode === 'group') {
|
|
66
|
+
if (!dataArg.groupId) return { pipelines: [] };
|
|
67
|
+
pipelines = await this.fetchGroupPipelines(provider, dataArg.groupId, timeRange);
|
|
68
|
+
} else if (viewMode === 'error') {
|
|
69
|
+
pipelines = await this.fetchErrorPipelines(provider, timeRange);
|
|
70
|
+
} else {
|
|
71
|
+
pipelines = [];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return { pipelines: this.sortPipelines(pipelines, sortBy).slice(0, 200) };
|
|
75
|
+
},
|
|
76
|
+
),
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
// Get pipeline jobs
|
|
80
|
+
this.typedrouter.addTypedHandler(
|
|
81
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetPipelineJobs>(
|
|
82
|
+
'getPipelineJobs',
|
|
83
|
+
async (dataArg) => {
|
|
84
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
85
|
+
const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
|
|
86
|
+
dataArg.connectionId,
|
|
87
|
+
);
|
|
88
|
+
const jobs = await provider.getPipelineJobs(dataArg.projectId, dataArg.pipelineId);
|
|
89
|
+
return { jobs };
|
|
90
|
+
},
|
|
91
|
+
),
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
// Retry pipeline
|
|
95
|
+
this.typedrouter.addTypedHandler(
|
|
96
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_RetryPipeline>(
|
|
97
|
+
'retryPipeline',
|
|
98
|
+
async (dataArg) => {
|
|
99
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
100
|
+
const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
|
|
101
|
+
dataArg.connectionId,
|
|
102
|
+
);
|
|
103
|
+
await provider.retryPipeline(dataArg.projectId, dataArg.pipelineId);
|
|
104
|
+
this.actionLog.append({
|
|
105
|
+
actionType: 'update',
|
|
106
|
+
entityType: 'pipeline',
|
|
107
|
+
entityId: dataArg.pipelineId,
|
|
108
|
+
entityName: `Pipeline #${dataArg.pipelineId}`,
|
|
109
|
+
details: `Retried pipeline #${dataArg.pipelineId} in project ${dataArg.projectId}`,
|
|
110
|
+
username: dataArg.identity.username,
|
|
111
|
+
});
|
|
112
|
+
return { ok: true };
|
|
113
|
+
},
|
|
114
|
+
),
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// Cancel pipeline
|
|
118
|
+
this.typedrouter.addTypedHandler(
|
|
119
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CancelPipeline>(
|
|
120
|
+
'cancelPipeline',
|
|
121
|
+
async (dataArg) => {
|
|
122
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
123
|
+
const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
|
|
124
|
+
dataArg.connectionId,
|
|
125
|
+
);
|
|
126
|
+
await provider.cancelPipeline(dataArg.projectId, dataArg.pipelineId);
|
|
127
|
+
this.actionLog.append({
|
|
128
|
+
actionType: 'delete',
|
|
129
|
+
entityType: 'pipeline',
|
|
130
|
+
entityId: dataArg.pipelineId,
|
|
131
|
+
entityName: `Pipeline #${dataArg.pipelineId}`,
|
|
132
|
+
details: `Cancelled pipeline #${dataArg.pipelineId} in project ${dataArg.projectId}`,
|
|
133
|
+
username: dataArg.identity.username,
|
|
134
|
+
});
|
|
135
|
+
return { ok: true };
|
|
136
|
+
},
|
|
137
|
+
),
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
// View mode helpers
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Current mode: running/pending always shown, plus recent pipelines within timeRange.
|
|
147
|
+
* Fetches a generous page of recent pipelines per project (100), then splits into
|
|
148
|
+
* active (running/pending/waiting) and the rest. Active are always shown; the rest
|
|
149
|
+
* is filtered by timeRange.
|
|
150
|
+
*/
|
|
151
|
+
private async fetchCurrentPipelines(
|
|
152
|
+
provider: BaseProvider,
|
|
153
|
+
timeRange: string,
|
|
154
|
+
): Promise<interfaces.data.IPipeline[]> {
|
|
155
|
+
const projects = await provider.getProjects();
|
|
156
|
+
const allPipelines = await this.fetchAggregatedPipelines(provider, projects, { perPage: 100 });
|
|
157
|
+
|
|
158
|
+
// Running/pending pipelines are always shown regardless of time
|
|
159
|
+
const active = allPipelines.filter(
|
|
160
|
+
(p) => p.status === 'running' || p.status === 'pending' || p.status === 'waiting',
|
|
161
|
+
);
|
|
162
|
+
const rest = allPipelines.filter(
|
|
163
|
+
(p) => p.status !== 'running' && p.status !== 'pending' && p.status !== 'waiting',
|
|
164
|
+
);
|
|
165
|
+
const filteredRest = this.filterByTimeRange(rest, timeRange);
|
|
166
|
+
|
|
167
|
+
// Deduplicate (active pipelines may also appear in filtered rest)
|
|
168
|
+
const activeIds = new Set(active.map((p) => `${p.connectionId}:${p.projectId}:${p.id}`));
|
|
169
|
+
const uniqueRest = filteredRest.filter(
|
|
170
|
+
(p) => !activeIds.has(`${p.connectionId}:${p.projectId}:${p.id}`),
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
return [...active, ...uniqueRest];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Group mode: pipelines from all projects in a group
|
|
178
|
+
*/
|
|
179
|
+
private async fetchGroupPipelines(
|
|
180
|
+
provider: BaseProvider,
|
|
181
|
+
groupId: string,
|
|
182
|
+
timeRange: string,
|
|
183
|
+
): Promise<interfaces.data.IPipeline[]> {
|
|
184
|
+
const projects = await provider.getGroupProjects(groupId);
|
|
185
|
+
const allPipelines = await this.fetchAggregatedPipelines(provider, projects);
|
|
186
|
+
return this.filterByTimeRange(allPipelines, timeRange);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Error mode: only failed pipelines
|
|
191
|
+
*/
|
|
192
|
+
private async fetchErrorPipelines(
|
|
193
|
+
provider: BaseProvider,
|
|
194
|
+
timeRange: string,
|
|
195
|
+
): Promise<interfaces.data.IPipeline[]> {
|
|
196
|
+
const projects = await provider.getProjects();
|
|
197
|
+
const allPipelines = await this.fetchAggregatedPipelines(provider, projects, { status: 'failed' });
|
|
198
|
+
return this.filterByTimeRange(allPipelines, timeRange);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Fetch pipelines from multiple projects in parallel (batched)
|
|
203
|
+
*/
|
|
204
|
+
private async fetchAggregatedPipelines(
|
|
205
|
+
provider: BaseProvider,
|
|
206
|
+
projects: interfaces.data.IProject[],
|
|
207
|
+
opts?: { status?: string; perPage?: number },
|
|
208
|
+
): Promise<interfaces.data.IPipeline[]> {
|
|
209
|
+
const BATCH_SIZE = 10;
|
|
210
|
+
const perPage = opts?.perPage || 50;
|
|
211
|
+
const allPipelines: interfaces.data.IPipeline[] = [];
|
|
212
|
+
|
|
213
|
+
for (let i = 0; i < projects.length; i += BATCH_SIZE) {
|
|
214
|
+
const batch = projects.slice(i, i + BATCH_SIZE);
|
|
215
|
+
const results = await Promise.allSettled(
|
|
216
|
+
batch.map(async (project) => {
|
|
217
|
+
const pipelines = await provider.getPipelines(project.id, {
|
|
218
|
+
perPage,
|
|
219
|
+
status: opts?.status,
|
|
220
|
+
});
|
|
221
|
+
// Enrich with proper project name
|
|
222
|
+
return pipelines.map((p) => ({
|
|
223
|
+
...p,
|
|
224
|
+
projectName: project.fullPath || project.name || p.projectId,
|
|
225
|
+
}));
|
|
226
|
+
}),
|
|
227
|
+
);
|
|
228
|
+
for (let j = 0; j < results.length; j++) {
|
|
229
|
+
const result = results[j];
|
|
230
|
+
if (result.status === 'fulfilled') {
|
|
231
|
+
allPipelines.push(...result.value);
|
|
232
|
+
} else {
|
|
233
|
+
const projectId = batch[j]?.id || 'unknown';
|
|
234
|
+
console.warn(`[PipelinesHandler] Failed to fetch pipelines for project ${projectId}: ${result.reason}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return allPipelines;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
// Filtering and sorting
|
|
244
|
+
// ---------------------------------------------------------------------------
|
|
245
|
+
|
|
246
|
+
private filterByTimeRange(
|
|
247
|
+
pipelines: interfaces.data.IPipeline[],
|
|
248
|
+
timeRange: string,
|
|
249
|
+
): interfaces.data.IPipeline[] {
|
|
250
|
+
const cutoffMs = TIME_RANGE_MS[timeRange] || TIME_RANGE_MS['1d'];
|
|
251
|
+
const cutoff = Date.now() - cutoffMs;
|
|
252
|
+
return pipelines.filter((p) => {
|
|
253
|
+
if (!p.createdAt) return false;
|
|
254
|
+
return new Date(p.createdAt).getTime() >= cutoff;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private sortPipelines(
|
|
259
|
+
pipelines: interfaces.data.IPipeline[],
|
|
260
|
+
sortBy: string,
|
|
261
|
+
): interfaces.data.IPipeline[] {
|
|
262
|
+
const sorted = [...pipelines];
|
|
263
|
+
switch (sortBy) {
|
|
264
|
+
case 'duration':
|
|
265
|
+
sorted.sort((a, b) => (b.duration || 0) - (a.duration || 0));
|
|
266
|
+
break;
|
|
267
|
+
case 'status':
|
|
268
|
+
sorted.sort(
|
|
269
|
+
(a, b) => (STATUS_PRIORITY[a.status] ?? 99) - (STATUS_PRIORITY[b.status] ?? 99),
|
|
270
|
+
);
|
|
271
|
+
break;
|
|
272
|
+
case 'created':
|
|
273
|
+
default:
|
|
274
|
+
sorted.sort(
|
|
275
|
+
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
|
|
276
|
+
);
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
return sorted;
|
|
280
|
+
}
|
|
281
|
+
}
|