@manojkmfsi/monodog 1.1.28 → 1.1.30
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/CHANGELOG.md +64 -0
- package/check-db.js +58 -0
- package/create-test-session.js +50 -0
- package/dev-server.pid +1 -0
- package/dist/controllers/pipeline-controller.js +329 -0
- package/dist/controllers/publish-controller.js +119 -7
- package/dist/middleware/auth-middleware.js +1 -0
- package/dist/middleware/server-startup.js +19 -0
- package/dist/routes/auth-routes.js +2 -0
- package/dist/routes/pipeline-routes.js +76 -0
- package/dist/services/changeset-service.js +2 -13
- package/dist/services/github-actions-service.js +552 -0
- package/dist/services/pipeline-service.js +356 -0
- package/dist/types/github-actions.js +6 -0
- package/monodog-dashboard/dist/assets/index-6NrFUGfK.js +15 -0
- package/monodog-dashboard/dist/assets/index-6NrFUGfK.js.map +1 -0
- package/monodog-dashboard/dist/assets/index-DcvKt8qx.css +1 -0
- package/monodog-dashboard/dist/index.html +2 -2
- package/package.json +2 -2
- package/prisma/migrations/{20260118042615_init_database → 20260224091033_init_db}/migration.sql +58 -0
- package/prisma/schema/pipeline-audit-log.prisma +22 -0
- package/prisma/schema/release-pipeline.prisma +25 -0
- package/monodog-dashboard/dist/assets/index-7G3SCgcz.css +0 -1
- package/monodog-dashboard/dist/assets/index-BMoE990p.js +0 -13
- package/monodog-dashboard/dist/assets/index-BMoE990p.js.map +0 -1
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pipeline Management Service
|
|
4
|
+
* Handles pipeline tracking, storage, and real-time updates
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.createOrUpdatePipeline = createOrUpdatePipeline;
|
|
41
|
+
exports.updatePipelineStatus = updatePipelineStatus;
|
|
42
|
+
exports.createAuditLog = createAuditLog;
|
|
43
|
+
exports.getPipelineAuditLogs = getPipelineAuditLogs;
|
|
44
|
+
exports.getRecentPipelines = getRecentPipelines;
|
|
45
|
+
exports.deleteOldPipelines = deleteOldPipelines;
|
|
46
|
+
const PrismaPkg = __importStar(require("@prisma/client"));
|
|
47
|
+
const PrismaClient = PrismaPkg.PrismaClient || PrismaPkg.default || PrismaPkg;
|
|
48
|
+
const logger_1 = require("../middleware/logger");
|
|
49
|
+
const prisma = new PrismaClient();
|
|
50
|
+
/**
|
|
51
|
+
* Create or update a release pipeline
|
|
52
|
+
*/
|
|
53
|
+
async function createOrUpdatePipeline(pipeline) {
|
|
54
|
+
try {
|
|
55
|
+
// Check if pipeline already exists for this release
|
|
56
|
+
const existing = await prisma.releasePipeline.findFirst({
|
|
57
|
+
where: {
|
|
58
|
+
releaseVersion: pipeline.releaseVersion,
|
|
59
|
+
packageName: pipeline.packageName,
|
|
60
|
+
owner: pipeline.owner,
|
|
61
|
+
repo: pipeline.repo,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
let result;
|
|
65
|
+
if (existing) {
|
|
66
|
+
result = await prisma.releasePipeline.update({
|
|
67
|
+
where: { id: existing.id },
|
|
68
|
+
data: {
|
|
69
|
+
currentStatus: pipeline.currentStatus,
|
|
70
|
+
currentConclusion: pipeline.currentConclusion,
|
|
71
|
+
lastRunId: pipeline.lastRunId ? String(pipeline.lastRunId) : null,
|
|
72
|
+
triggeredAt: pipeline.triggeredAt,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
result = await prisma.releasePipeline.create({
|
|
78
|
+
data: {
|
|
79
|
+
releaseVersion: pipeline.releaseVersion,
|
|
80
|
+
packageName: pipeline.packageName,
|
|
81
|
+
owner: pipeline.owner,
|
|
82
|
+
repo: pipeline.repo,
|
|
83
|
+
workflowId: pipeline.workflowId,
|
|
84
|
+
workflowName: pipeline.workflowName,
|
|
85
|
+
workflowPath: pipeline.workflowPath,
|
|
86
|
+
triggerType: pipeline.triggerType,
|
|
87
|
+
triggeredBy: pipeline.triggeredBy,
|
|
88
|
+
triggeredAt: pipeline.triggeredAt,
|
|
89
|
+
currentStatus: pipeline.currentStatus,
|
|
90
|
+
currentConclusion: pipeline.currentConclusion,
|
|
91
|
+
lastRunId: pipeline.lastRunId ? String(pipeline.lastRunId) : null,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
id: result.id,
|
|
97
|
+
releaseVersion: result.releaseVersion,
|
|
98
|
+
packageName: result.packageName,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
logger_1.AppLogger.error(`Failed to create/update pipeline: ${error}`);
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Update pipeline status and conclusion based on workflow run
|
|
108
|
+
*/
|
|
109
|
+
async function updatePipelineStatus(pipelineId, currentStatus, currentConclusion, lastRunId) {
|
|
110
|
+
try {
|
|
111
|
+
const result = await prisma.releasePipeline.update({
|
|
112
|
+
where: { id: pipelineId },
|
|
113
|
+
data: {
|
|
114
|
+
currentStatus,
|
|
115
|
+
currentConclusion,
|
|
116
|
+
...(lastRunId && { lastRunId: String(lastRunId) }),
|
|
117
|
+
updatedAt: new Date(),
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
logger_1.AppLogger.info(`Updated pipeline ${pipelineId}: status=${currentStatus}, conclusion=${currentConclusion}`);
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
logger_1.AppLogger.error(`Failed to update pipeline status: ${error}`);
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Store workflow run in database
|
|
130
|
+
*/
|
|
131
|
+
// export async function storeWorkflowRun(
|
|
132
|
+
// pipelineId: string,
|
|
133
|
+
// run: any // WorkflowRun type
|
|
134
|
+
// ): Promise<string> {
|
|
135
|
+
// try {
|
|
136
|
+
// const result = await prisma.workflowRun.upsert({
|
|
137
|
+
// where: { gitHubRunId: run.id },
|
|
138
|
+
// update: {
|
|
139
|
+
// status: run.status,
|
|
140
|
+
// conclusion: run.conclusion,
|
|
141
|
+
// updatedAt: new Date(run.updated_at),
|
|
142
|
+
// },
|
|
143
|
+
// create: {
|
|
144
|
+
// gitHubRunId: run.id,
|
|
145
|
+
// gitHubNodeId: run.node_id,
|
|
146
|
+
// name: run.name,
|
|
147
|
+
// displayTitle: run.display_title,
|
|
148
|
+
// runNumber: run.run_number,
|
|
149
|
+
// event: run.event,
|
|
150
|
+
// status: run.status,
|
|
151
|
+
// conclusion: run.conclusion,
|
|
152
|
+
// htmlUrl: run.html_url,
|
|
153
|
+
// workflowId: run.workflow_id,
|
|
154
|
+
// workflowPath: run.path,
|
|
155
|
+
// headBranch: run.head_branch,
|
|
156
|
+
// headSha: run.head_sha,
|
|
157
|
+
// createdAt: new Date(run.created_at),
|
|
158
|
+
// updatedAt: new Date(run.updated_at),
|
|
159
|
+
// runStartedAt: run.run_started_at ? new Date(run.run_started_at) : null,
|
|
160
|
+
// pipelineId,
|
|
161
|
+
// actor: run.actor?.login || 'unknown',
|
|
162
|
+
// triggeringActor: run.triggering_actor?.login,
|
|
163
|
+
// },
|
|
164
|
+
// });
|
|
165
|
+
// return result.id;
|
|
166
|
+
// } catch (error) {
|
|
167
|
+
// AppLogger.error(`Failed to store workflow run: ${error}`);
|
|
168
|
+
// throw error;
|
|
169
|
+
// }
|
|
170
|
+
// }
|
|
171
|
+
/**
|
|
172
|
+
* Store workflow jobs for a run
|
|
173
|
+
*/
|
|
174
|
+
// export async function storeWorkflowJobs(
|
|
175
|
+
// workflowRunId: string,
|
|
176
|
+
// jobs: any[] // WorkflowJob[]
|
|
177
|
+
// ): Promise<string[]> {
|
|
178
|
+
// try {
|
|
179
|
+
// const createdJobIds: string[] = [];
|
|
180
|
+
// for (const job of jobs) {
|
|
181
|
+
// const result = await prisma.workflowJob.upsert({
|
|
182
|
+
// where: { gitHubJobId: job.id },
|
|
183
|
+
// update: {
|
|
184
|
+
// status: job.status,
|
|
185
|
+
// conclusion: job.conclusion,
|
|
186
|
+
// },
|
|
187
|
+
// create: {
|
|
188
|
+
// gitHubJobId: job.id,
|
|
189
|
+
// gitHubNodeId: job.node_id,
|
|
190
|
+
// name: job.name,
|
|
191
|
+
// runUrl: job.run_url,
|
|
192
|
+
// htmlUrl: job.html_url,
|
|
193
|
+
// status: job.status,
|
|
194
|
+
// conclusion: job.conclusion,
|
|
195
|
+
// headSha: job.head_sha,
|
|
196
|
+
// startedAt: job.started_at ? new Date(job.started_at) : null,
|
|
197
|
+
// completedAt: job.completed_at ? new Date(job.completed_at) : null,
|
|
198
|
+
// runnerId: job.runner_id,
|
|
199
|
+
// runnerName: job.runner_name,
|
|
200
|
+
// runnerGroupId: job.runner_group_id,
|
|
201
|
+
// runnerGroupName: job.runner_group_name,
|
|
202
|
+
// runId: workflowRunId,
|
|
203
|
+
// labels: JSON.stringify(job.labels || []),
|
|
204
|
+
// },
|
|
205
|
+
// });
|
|
206
|
+
// createdJobIds.push(result.id);
|
|
207
|
+
// // Store steps
|
|
208
|
+
// if (job.steps && Array.isArray(job.steps)) {
|
|
209
|
+
// for (const step of job.steps) {
|
|
210
|
+
// await prisma.workflowStep.upsert({
|
|
211
|
+
// where: {
|
|
212
|
+
// id: `${result.id}-${step.number}`,
|
|
213
|
+
// },
|
|
214
|
+
// update: {
|
|
215
|
+
// status: step.status,
|
|
216
|
+
// conclusion: step.conclusion,
|
|
217
|
+
// },
|
|
218
|
+
// create: {
|
|
219
|
+
// id: `${result.id}-${step.number}`,
|
|
220
|
+
// name: step.name,
|
|
221
|
+
// stepNumber: step.number,
|
|
222
|
+
// status: step.status,
|
|
223
|
+
// conclusion: step.conclusion,
|
|
224
|
+
// startedAt: step.started_at ? new Date(step.started_at) : null,
|
|
225
|
+
// completedAt: step.completed_at
|
|
226
|
+
// ? new Date(step.completed_at)
|
|
227
|
+
// : null,
|
|
228
|
+
// jobId: result.id,
|
|
229
|
+
// },
|
|
230
|
+
// });
|
|
231
|
+
// }
|
|
232
|
+
// }
|
|
233
|
+
// }
|
|
234
|
+
// return createdJobIds;
|
|
235
|
+
// } catch (error) {
|
|
236
|
+
// AppLogger.error(`Failed to store workflow jobs: ${error}`);
|
|
237
|
+
// throw error;
|
|
238
|
+
// }
|
|
239
|
+
// }
|
|
240
|
+
/**
|
|
241
|
+
* Store job logs
|
|
242
|
+
*/
|
|
243
|
+
// export async function storeJobLogs(
|
|
244
|
+
// jobId: string,
|
|
245
|
+
// logs: any, // JobLogs
|
|
246
|
+
// rawLogUrl: string
|
|
247
|
+
// ): Promise<void> {
|
|
248
|
+
// try {
|
|
249
|
+
// await prisma.jobLog.upsert({
|
|
250
|
+
// where: { jobId },
|
|
251
|
+
// update: {
|
|
252
|
+
// logLines: JSON.stringify(logs.steps.flatMap((s: any) => s.logs)),
|
|
253
|
+
// updatedAt: new Date(),
|
|
254
|
+
// },
|
|
255
|
+
// create: {
|
|
256
|
+
// jobId,
|
|
257
|
+
// logLines: JSON.stringify(logs.steps.flatMap((s: any) => s.logs)),
|
|
258
|
+
// rawLogUrl,
|
|
259
|
+
// totalLines: logs.steps.reduce(
|
|
260
|
+
// (sum: number, s: any) => sum + (s.logs?.length || 0),
|
|
261
|
+
// 0
|
|
262
|
+
// ),
|
|
263
|
+
// hasPreviousLogs: logs.hasPreviousLogs,
|
|
264
|
+
// hasMoreLogs: logs.hasMoreLogs,
|
|
265
|
+
// },
|
|
266
|
+
// });
|
|
267
|
+
// } catch (error) {
|
|
268
|
+
// AppLogger.error(`Failed to store job logs: ${error}`);
|
|
269
|
+
// throw error;
|
|
270
|
+
// }
|
|
271
|
+
// }
|
|
272
|
+
/**
|
|
273
|
+
* Create audit log entry
|
|
274
|
+
*/
|
|
275
|
+
async function createAuditLog(pipelineId, userId, username, action, resourceType, resourceId, resourceName, details = {}, status = 'success', errorMessage) {
|
|
276
|
+
try {
|
|
277
|
+
await prisma.pipelineAuditLog.create({
|
|
278
|
+
data: {
|
|
279
|
+
pipelineId,
|
|
280
|
+
userId,
|
|
281
|
+
username,
|
|
282
|
+
action,
|
|
283
|
+
resourceType,
|
|
284
|
+
resourceId,
|
|
285
|
+
resourceName,
|
|
286
|
+
details: JSON.stringify(details),
|
|
287
|
+
status,
|
|
288
|
+
errorMessage,
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
logger_1.AppLogger.error(`Failed to create audit log: ${error}`);
|
|
294
|
+
throw error;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Get audit logs for a pipeline
|
|
299
|
+
*/
|
|
300
|
+
async function getPipelineAuditLogs(pipelineId, limit = 50, offset = 0) {
|
|
301
|
+
try {
|
|
302
|
+
return await prisma.pipelineAuditLog.findMany({
|
|
303
|
+
where: { pipelineId },
|
|
304
|
+
orderBy: { timestamp: 'desc' },
|
|
305
|
+
take: limit,
|
|
306
|
+
skip: offset,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
logger_1.AppLogger.error(`Failed to get audit logs: ${error}`);
|
|
311
|
+
throw error;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Get recent pipelines for dashboard
|
|
316
|
+
*/
|
|
317
|
+
async function getRecentPipelines(limit = 20, offset = 0) {
|
|
318
|
+
try {
|
|
319
|
+
const pipelines = await prisma.releasePipeline.findMany({
|
|
320
|
+
orderBy: { triggeredAt: 'desc' },
|
|
321
|
+
take: limit,
|
|
322
|
+
skip: offset
|
|
323
|
+
});
|
|
324
|
+
// Enrich with workflowPath if not already set (should be set in database now)
|
|
325
|
+
return pipelines.map((p) => ({
|
|
326
|
+
...p,
|
|
327
|
+
workflowPath: p.workflowPath || 'release.yml',
|
|
328
|
+
}));
|
|
329
|
+
}
|
|
330
|
+
catch (error) {
|
|
331
|
+
logger_1.AppLogger.error(`Failed to get recent pipelines: ${error}`);
|
|
332
|
+
throw error;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Delete old pipelines (cleanup)
|
|
337
|
+
*/
|
|
338
|
+
async function deleteOldPipelines(daysOld = 90) {
|
|
339
|
+
try {
|
|
340
|
+
const cutoffDate = new Date();
|
|
341
|
+
cutoffDate.setDate(cutoffDate.getDate() - daysOld);
|
|
342
|
+
const result = await prisma.releasePipeline.deleteMany({
|
|
343
|
+
where: {
|
|
344
|
+
createdAt: {
|
|
345
|
+
lt: cutoffDate,
|
|
346
|
+
},
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
logger_1.AppLogger.info(`Deleted ${result.count} old pipelines`);
|
|
350
|
+
return result.count;
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
logger_1.AppLogger.error(`Failed to delete old pipelines: ${error}`);
|
|
354
|
+
throw error;
|
|
355
|
+
}
|
|
356
|
+
}
|