@manojkmfsi/monodog 1.1.6 → 1.1.8
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +12 -0
- package/package.json +1 -1
- package/src/config/swagger-config.ts +0 -344
- package/src/config-loader.ts +0 -97
- package/src/constants/index.ts +0 -13
- package/src/constants/middleware.ts +0 -83
- package/src/constants/port.ts +0 -20
- package/src/constants/security.ts +0 -78
- package/src/controllers/commit-controller.ts +0 -31
- package/src/controllers/config-controller.ts +0 -42
- package/src/controllers/health-controller.ts +0 -24
- package/src/controllers/package-controller.ts +0 -67
- package/src/get-db-url.ts +0 -9
- package/src/index.ts +0 -9
- package/src/middleware/dashboard-startup.ts +0 -161
- package/src/middleware/error-handler.ts +0 -50
- package/src/middleware/index.ts +0 -20
- package/src/middleware/logger.ts +0 -65
- package/src/middleware/security.ts +0 -90
- package/src/middleware/server-startup.ts +0 -153
- package/src/middleware/swagger-middleware.ts +0 -58
- package/src/repositories/commit-repository.ts +0 -108
- package/src/repositories/dependency-repository.ts +0 -110
- package/src/repositories/index.ts +0 -10
- package/src/repositories/package-health-repository.ts +0 -75
- package/src/repositories/package-repository.ts +0 -142
- package/src/repositories/prisma-client.ts +0 -25
- package/src/routes/commit-routes.ts +0 -10
- package/src/routes/config-routes.ts +0 -14
- package/src/routes/health-routes.ts +0 -14
- package/src/routes/package-routes.ts +0 -22
- package/src/serve.ts +0 -41
- package/src/services/commit-service.ts +0 -44
- package/src/services/config-service.ts +0 -391
- package/src/services/git-service.ts +0 -140
- package/src/services/health-service.ts +0 -162
- package/src/services/package-service.ts +0 -228
- package/src/setup.ts +0 -78
- package/src/types/ci.ts +0 -122
- package/src/types/config.ts +0 -22
- package/src/types/database.ts +0 -67
- package/src/types/git.ts +0 -33
- package/src/types/health.ts +0 -11
- package/src/types/index.ts +0 -23
- package/src/types/package.ts +0 -39
- package/src/types/scanner.ts +0 -31
- package/src/types/swagger-jsdoc.d.ts +0 -15
- package/src/utils/ci-status.ts +0 -535
- package/src/utils/db-utils.ts +0 -92
- package/src/utils/health-utils.ts +0 -67
- package/src/utils/monorepo-scanner.ts +0 -576
- package/src/utils/utilities.ts +0 -427
package/src/utils/ci-status.ts
DELETED
|
@@ -1,535 +0,0 @@
|
|
|
1
|
-
import { AppLogger } from '../middleware/logger';
|
|
2
|
-
import type { PackageInfo } from './utilities';
|
|
3
|
-
import type {
|
|
4
|
-
CIProvider,
|
|
5
|
-
CIBuild,
|
|
6
|
-
CIBuildStep,
|
|
7
|
-
CIArtifact,
|
|
8
|
-
CICoverage,
|
|
9
|
-
CITestResults,
|
|
10
|
-
CITestSuite,
|
|
11
|
-
CITest,
|
|
12
|
-
CIPackageStatus,
|
|
13
|
-
CIMonorepoStatus,
|
|
14
|
-
} from '../types';
|
|
15
|
-
|
|
16
|
-
export class CIStatusManager {
|
|
17
|
-
private providers: Map<string, CIProvider> = new Map();
|
|
18
|
-
private cache: Map<string, any> = new Map();
|
|
19
|
-
private cacheExpiry = 2 * 60 * 1000; // 2 minutes
|
|
20
|
-
|
|
21
|
-
constructor() {
|
|
22
|
-
this.initializeDefaultProviders();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Initialize default CI providers
|
|
27
|
-
*/
|
|
28
|
-
private initializeDefaultProviders(): void {
|
|
29
|
-
// GitHub Actions
|
|
30
|
-
this.addProvider({
|
|
31
|
-
name: 'GitHub Actions',
|
|
32
|
-
type: 'github',
|
|
33
|
-
baseUrl: 'https://api.github.com',
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
// GitLab CI
|
|
37
|
-
this.addProvider({
|
|
38
|
-
name: 'GitLab CI',
|
|
39
|
-
type: 'gitlab',
|
|
40
|
-
baseUrl: 'https://gitlab.com/api/v4',
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// CircleCI
|
|
44
|
-
this.addProvider({
|
|
45
|
-
name: 'CircleCI',
|
|
46
|
-
type: 'circleci',
|
|
47
|
-
baseUrl: 'https://circleci.com/api/v2',
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Add a CI provider
|
|
53
|
-
*/
|
|
54
|
-
addProvider(provider: CIProvider): void {
|
|
55
|
-
this.providers.set(provider.name, provider);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Remove a CI provider
|
|
60
|
-
*/
|
|
61
|
-
removeProvider(name: string): void {
|
|
62
|
-
this.providers.delete(name);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Get all registered providers
|
|
67
|
-
*/
|
|
68
|
-
getProviders(): CIProvider[] {
|
|
69
|
-
return Array.from(this.providers.values());
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Fetch CI status for a specific package
|
|
74
|
-
*/
|
|
75
|
-
async getPackageStatus(
|
|
76
|
-
packageName: string,
|
|
77
|
-
providerName?: string
|
|
78
|
-
): Promise<CIPackageStatus | null> {
|
|
79
|
-
const cacheKey = `package-status-${packageName}-${providerName || 'all'}`;
|
|
80
|
-
const cached = this.getFromCache(cacheKey);
|
|
81
|
-
if (cached) {
|
|
82
|
-
return cached;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
let builds: CIBuild[] = [];
|
|
87
|
-
|
|
88
|
-
if (providerName) {
|
|
89
|
-
const provider = this.providers.get(providerName);
|
|
90
|
-
if (provider) {
|
|
91
|
-
builds = await this.fetchBuildsFromProvider(provider, packageName);
|
|
92
|
-
}
|
|
93
|
-
} else {
|
|
94
|
-
// Fetch from all providers
|
|
95
|
-
for (const provider of this.providers.values()) {
|
|
96
|
-
const providerBuilds = await this.fetchBuildsFromProvider(
|
|
97
|
-
provider,
|
|
98
|
-
packageName
|
|
99
|
-
);
|
|
100
|
-
builds.push(...providerBuilds);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (builds.length === 0) {
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Sort builds by start time (newest first)
|
|
109
|
-
builds.sort((a, b) => b.startTime.getTime() - a.startTime.getTime());
|
|
110
|
-
|
|
111
|
-
const lastBuild = builds[0];
|
|
112
|
-
const buildHistory = builds.slice(0, 10); // Last 10 builds
|
|
113
|
-
const successRate = this.calculateSuccessRate(builds);
|
|
114
|
-
const averageDuration = this.calculateAverageDuration(builds);
|
|
115
|
-
const isHealthy = this.determinePackageHealth(builds);
|
|
116
|
-
const issues = this.identifyIssues(builds);
|
|
117
|
-
|
|
118
|
-
const status: CIPackageStatus = {
|
|
119
|
-
packageName,
|
|
120
|
-
lastBuild,
|
|
121
|
-
buildHistory,
|
|
122
|
-
successRate,
|
|
123
|
-
averageDuration,
|
|
124
|
-
lastCommit: lastBuild.commit,
|
|
125
|
-
lastCommitDate: lastBuild.startTime,
|
|
126
|
-
branch: lastBuild.branch,
|
|
127
|
-
isHealthy,
|
|
128
|
-
issues,
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
this.setCache(cacheKey, status);
|
|
132
|
-
return status;
|
|
133
|
-
} catch (error) {
|
|
134
|
-
AppLogger.error(`Error fetching CI status for ${packageName}`, error as Error);
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Get overall monorepo CI status
|
|
141
|
-
*/
|
|
142
|
-
async getMonorepoStatus(packages: PackageInfo[]): Promise<CIMonorepoStatus> {
|
|
143
|
-
const cacheKey = 'monorepo-ci-status';
|
|
144
|
-
const cached = this.getFromCache(cacheKey);
|
|
145
|
-
if (cached) {
|
|
146
|
-
return cached;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const packageStatuses: CIPackageStatus[] = [];
|
|
150
|
-
const allBuilds: CIBuild[] = [];
|
|
151
|
-
let totalTests = 0;
|
|
152
|
-
let passedTests = 0;
|
|
153
|
-
let failedTests = 0;
|
|
154
|
-
const packageCoverage: Record<string, number> = {};
|
|
155
|
-
|
|
156
|
-
// Get status for each package
|
|
157
|
-
for (const pkg of packages) {
|
|
158
|
-
const status = await this.getPackageStatus(pkg.name);
|
|
159
|
-
if (status) {
|
|
160
|
-
packageStatuses.push(status);
|
|
161
|
-
allBuilds.push(...status.buildHistory);
|
|
162
|
-
|
|
163
|
-
// Aggregate test results
|
|
164
|
-
if (status.lastBuild?.tests) {
|
|
165
|
-
totalTests += status.lastBuild.tests.total;
|
|
166
|
-
passedTests += status.lastBuild.tests.passed;
|
|
167
|
-
failedTests += status.lastBuild.tests.failed;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Aggregate coverage
|
|
171
|
-
if (status.lastBuild?.coverage) {
|
|
172
|
-
packageCoverage[pkg.name] = status.lastBuild.coverage.percentage;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Calculate overall metrics
|
|
178
|
-
const totalPackages = packages.length;
|
|
179
|
-
const healthyPackages = packageStatuses.filter(s => s.isHealthy).length;
|
|
180
|
-
const warningPackages = packageStatuses.filter(
|
|
181
|
-
s => !s.isHealthy && s.issues.length < 3
|
|
182
|
-
).length;
|
|
183
|
-
const errorPackages = packageStatuses.filter(
|
|
184
|
-
s => !s.isHealthy && s.issues.length >= 3
|
|
185
|
-
).length;
|
|
186
|
-
const overallHealth = (healthyPackages / totalPackages) * 100;
|
|
187
|
-
|
|
188
|
-
// Sort builds by time
|
|
189
|
-
allBuilds.sort((a, b) => b.startTime.getTime() - a.startTime.getTime());
|
|
190
|
-
const recentBuilds = allBuilds.slice(0, 20);
|
|
191
|
-
const failedBuilds = allBuilds.filter(b => b.status === 'failed');
|
|
192
|
-
|
|
193
|
-
// Calculate overall coverage
|
|
194
|
-
const coverageValues = Object.values(packageCoverage);
|
|
195
|
-
const overallCoverage =
|
|
196
|
-
coverageValues.length > 0
|
|
197
|
-
? coverageValues.reduce((sum, val) => sum + val, 0) /
|
|
198
|
-
coverageValues.length
|
|
199
|
-
: 0;
|
|
200
|
-
|
|
201
|
-
const status: CIMonorepoStatus = {
|
|
202
|
-
totalPackages,
|
|
203
|
-
healthyPackages,
|
|
204
|
-
warningPackages,
|
|
205
|
-
errorPackages,
|
|
206
|
-
overallHealth,
|
|
207
|
-
packages: packageStatuses,
|
|
208
|
-
recentBuilds,
|
|
209
|
-
failedBuilds,
|
|
210
|
-
coverage: {
|
|
211
|
-
overall: overallCoverage,
|
|
212
|
-
packages: packageCoverage,
|
|
213
|
-
},
|
|
214
|
-
tests: {
|
|
215
|
-
total: totalTests,
|
|
216
|
-
passed: passedTests,
|
|
217
|
-
failed: failedTests,
|
|
218
|
-
successRate: totalTests > 0 ? (passedTests / totalTests) * 100 : 0,
|
|
219
|
-
},
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
this.setCache(cacheKey, status);
|
|
223
|
-
return status;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Fetch builds from a specific CI provider
|
|
228
|
-
*/
|
|
229
|
-
private async fetchBuildsFromProvider(
|
|
230
|
-
_provider: CIProvider,
|
|
231
|
-
packageName: string
|
|
232
|
-
): Promise<CIBuild[]> {
|
|
233
|
-
// This is a mock implementation
|
|
234
|
-
// In a real implementation, you would make API calls to the CI provider
|
|
235
|
-
|
|
236
|
-
const mockBuilds: CIBuild[] = [
|
|
237
|
-
{
|
|
238
|
-
id: `build-${Date.now()}-1`,
|
|
239
|
-
status: 'success',
|
|
240
|
-
branch: 'main',
|
|
241
|
-
commit: 'abc1234',
|
|
242
|
-
commitMessage: `feat: update ${packageName}`,
|
|
243
|
-
author: 'developer@example.com',
|
|
244
|
-
startTime: new Date(Date.now() - 1000 * 60 * 30), // 30 minutes ago
|
|
245
|
-
endTime: new Date(Date.now() - 1000 * 60 * 25), // 25 minutes ago
|
|
246
|
-
duration: 5 * 60 * 1000, // 5 minutes
|
|
247
|
-
url: `https://ci.example.com/builds/build-${Date.now()}-1`,
|
|
248
|
-
packageName,
|
|
249
|
-
workflowName: 'Build and Test',
|
|
250
|
-
jobName: 'test',
|
|
251
|
-
steps: [
|
|
252
|
-
{
|
|
253
|
-
name: 'Install dependencies',
|
|
254
|
-
status: 'success',
|
|
255
|
-
duration: 30000,
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
name: 'Run tests',
|
|
259
|
-
status: 'success',
|
|
260
|
-
duration: 120000,
|
|
261
|
-
},
|
|
262
|
-
{
|
|
263
|
-
name: 'Build package',
|
|
264
|
-
status: 'success',
|
|
265
|
-
duration: 60000,
|
|
266
|
-
},
|
|
267
|
-
],
|
|
268
|
-
coverage: {
|
|
269
|
-
percentage: 85,
|
|
270
|
-
lines: 1000,
|
|
271
|
-
functions: 50,
|
|
272
|
-
branches: 200,
|
|
273
|
-
statements: 1200,
|
|
274
|
-
},
|
|
275
|
-
tests: {
|
|
276
|
-
total: 150,
|
|
277
|
-
passed: 145,
|
|
278
|
-
failed: 0,
|
|
279
|
-
skipped: 5,
|
|
280
|
-
duration: 120000,
|
|
281
|
-
suites: [
|
|
282
|
-
{
|
|
283
|
-
name: 'Unit Tests',
|
|
284
|
-
status: 'pass',
|
|
285
|
-
tests: [],
|
|
286
|
-
duration: 80000,
|
|
287
|
-
},
|
|
288
|
-
{
|
|
289
|
-
name: 'Integration Tests',
|
|
290
|
-
status: 'pass',
|
|
291
|
-
tests: [],
|
|
292
|
-
duration: 40000,
|
|
293
|
-
},
|
|
294
|
-
],
|
|
295
|
-
},
|
|
296
|
-
},
|
|
297
|
-
{
|
|
298
|
-
id: `build-${Date.now()}-2`,
|
|
299
|
-
status: 'failed',
|
|
300
|
-
branch: 'feature/new-feature',
|
|
301
|
-
commit: 'def5678',
|
|
302
|
-
commitMessage: `fix: resolve issue in ${packageName}`,
|
|
303
|
-
author: 'developer@example.com',
|
|
304
|
-
startTime: new Date(Date.now() - 1000 * 60 * 60 * 2), // 2 hours ago
|
|
305
|
-
endTime: new Date(Date.now() - 1000 * 60 * 60 * 1.5), // 1.5 hours ago
|
|
306
|
-
duration: 30 * 60 * 1000, // 30 minutes
|
|
307
|
-
url: `https://ci.example.com/builds/build-${Date.now()}-2`,
|
|
308
|
-
packageName,
|
|
309
|
-
workflowName: 'Build and Test',
|
|
310
|
-
jobName: 'test',
|
|
311
|
-
steps: [
|
|
312
|
-
{
|
|
313
|
-
name: 'Install dependencies',
|
|
314
|
-
status: 'success',
|
|
315
|
-
duration: 30000,
|
|
316
|
-
},
|
|
317
|
-
{
|
|
318
|
-
name: 'Run tests',
|
|
319
|
-
status: 'failed',
|
|
320
|
-
duration: 120000,
|
|
321
|
-
error: 'Test suite failed with 3 failing tests',
|
|
322
|
-
},
|
|
323
|
-
],
|
|
324
|
-
tests: {
|
|
325
|
-
total: 150,
|
|
326
|
-
passed: 147,
|
|
327
|
-
failed: 3,
|
|
328
|
-
skipped: 0,
|
|
329
|
-
duration: 120000,
|
|
330
|
-
suites: [
|
|
331
|
-
{
|
|
332
|
-
name: 'Unit Tests',
|
|
333
|
-
status: 'pass',
|
|
334
|
-
tests: [],
|
|
335
|
-
duration: 80000,
|
|
336
|
-
},
|
|
337
|
-
{
|
|
338
|
-
name: 'Integration Tests',
|
|
339
|
-
status: 'fail',
|
|
340
|
-
tests: [],
|
|
341
|
-
duration: 40000,
|
|
342
|
-
},
|
|
343
|
-
],
|
|
344
|
-
},
|
|
345
|
-
},
|
|
346
|
-
];
|
|
347
|
-
|
|
348
|
-
return mockBuilds;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/**
|
|
352
|
-
* Calculate success rate from builds
|
|
353
|
-
*/
|
|
354
|
-
private calculateSuccessRate(builds: CIBuild[]): number {
|
|
355
|
-
if (builds.length === 0) return 0;
|
|
356
|
-
|
|
357
|
-
const successfulBuilds = builds.filter(b => b.status === 'success').length;
|
|
358
|
-
return (successfulBuilds / builds.length) * 100;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Calculate average build duration
|
|
363
|
-
*/
|
|
364
|
-
private calculateAverageDuration(builds: CIBuild[]): number {
|
|
365
|
-
if (builds.length === 0) return 0;
|
|
366
|
-
|
|
367
|
-
const completedBuilds = builds.filter(b => b.duration !== undefined);
|
|
368
|
-
if (completedBuilds.length === 0) return 0;
|
|
369
|
-
|
|
370
|
-
const totalDuration = completedBuilds.reduce(
|
|
371
|
-
(sum, b) => sum + (b.duration || 0),
|
|
372
|
-
0
|
|
373
|
-
);
|
|
374
|
-
return totalDuration / completedBuilds.length;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Determine if a package is healthy based on CI results
|
|
379
|
-
*/
|
|
380
|
-
private determinePackageHealth(builds: CIBuild[]): boolean {
|
|
381
|
-
if (builds.length === 0) return true;
|
|
382
|
-
|
|
383
|
-
const recentBuilds = builds.slice(0, 5); // Last 5 builds
|
|
384
|
-
const successRate = this.calculateSuccessRate(recentBuilds);
|
|
385
|
-
|
|
386
|
-
return successRate >= 80; // 80% success rate threshold
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
/**
|
|
390
|
-
* Identify issues from build results
|
|
391
|
-
*/
|
|
392
|
-
private identifyIssues(builds: CIBuild[]): string[] {
|
|
393
|
-
const issues: string[] = [];
|
|
394
|
-
|
|
395
|
-
if (builds.length === 0) return issues;
|
|
396
|
-
|
|
397
|
-
const recentBuilds = builds.slice(0, 3); // Last 3 builds
|
|
398
|
-
const successRate = this.calculateSuccessRate(recentBuilds);
|
|
399
|
-
|
|
400
|
-
if (successRate < 50) {
|
|
401
|
-
issues.push('High failure rate in recent builds');
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
const failedBuilds = recentBuilds.filter(b => b.status === 'failed');
|
|
405
|
-
for (const build of failedBuilds) {
|
|
406
|
-
const failedSteps = build.steps.filter(s => s.status === 'failed');
|
|
407
|
-
for (const step of failedSteps) {
|
|
408
|
-
if (step.error) {
|
|
409
|
-
issues.push(`Build step '${step.name}' failed: ${step.error}`);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
// Check for long build times
|
|
415
|
-
const avgDuration = this.calculateAverageDuration(recentBuilds);
|
|
416
|
-
if (avgDuration > 10 * 60 * 1000) {
|
|
417
|
-
// 10 minutes
|
|
418
|
-
issues.push('Builds are taking longer than expected');
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
return issues;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
/**
|
|
425
|
-
* Get cache value if not expired
|
|
426
|
-
*/
|
|
427
|
-
private getFromCache(key: string): any {
|
|
428
|
-
const cached = this.cache.get(key);
|
|
429
|
-
if (cached && Date.now() - cached.timestamp < this.cacheExpiry) {
|
|
430
|
-
return cached.data;
|
|
431
|
-
}
|
|
432
|
-
return null;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/**
|
|
436
|
-
* Set cache value with timestamp
|
|
437
|
-
*/
|
|
438
|
-
private setCache(key: string, data: any): void {
|
|
439
|
-
this.cache.set(key, {
|
|
440
|
-
data,
|
|
441
|
-
timestamp: Date.now(),
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
/**
|
|
446
|
-
* Clear the cache
|
|
447
|
-
*/
|
|
448
|
-
clearCache(): void {
|
|
449
|
-
this.cache.clear();
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
/**
|
|
453
|
-
* Get build logs for a specific build
|
|
454
|
-
*/
|
|
455
|
-
async getBuildLogs(buildId: string, providerName: string): Promise<string> {
|
|
456
|
-
// Mock implementation
|
|
457
|
-
return `Build logs for ${buildId} from ${providerName}\n\nStep 1: Install dependencies\n✓ Dependencies installed successfully\n\nStep 2: Run tests\n✓ All tests passed\n\nStep 3: Build package\n✓ Package built successfully`;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
* Trigger a new build for a package
|
|
462
|
-
*/
|
|
463
|
-
async triggerBuild(
|
|
464
|
-
packageName: string,
|
|
465
|
-
providerName: string,
|
|
466
|
-
branch: string = 'main'
|
|
467
|
-
): Promise<{ success: boolean; buildId?: string; error?: string }> {
|
|
468
|
-
try {
|
|
469
|
-
// Mock implementation
|
|
470
|
-
const buildId = `build-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
471
|
-
|
|
472
|
-
AppLogger.info(
|
|
473
|
-
`Triggering build for ${packageName} on ${branch} via ${providerName}`
|
|
474
|
-
);
|
|
475
|
-
|
|
476
|
-
return {
|
|
477
|
-
success: true,
|
|
478
|
-
buildId,
|
|
479
|
-
};
|
|
480
|
-
} catch (error) {
|
|
481
|
-
return {
|
|
482
|
-
success: false,
|
|
483
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* Get build artifacts
|
|
490
|
-
*/
|
|
491
|
-
async getBuildArtifacts(
|
|
492
|
-
buildId: string,
|
|
493
|
-
_providerName: string
|
|
494
|
-
): Promise<CIArtifact[]> {
|
|
495
|
-
// Mock implementation
|
|
496
|
-
return [
|
|
497
|
-
{
|
|
498
|
-
name: 'coverage-report.html',
|
|
499
|
-
type: 'coverage',
|
|
500
|
-
size: 1024 * 50, // 50KB
|
|
501
|
-
url: `https://ci.example.com/artifacts/${buildId}/coverage-report.html`,
|
|
502
|
-
},
|
|
503
|
-
{
|
|
504
|
-
name: 'test-results.xml',
|
|
505
|
-
type: 'test',
|
|
506
|
-
size: 1024 * 10, // 10KB
|
|
507
|
-
url: `https://ci.example.com/artifacts/${buildId}/test-results.xml`,
|
|
508
|
-
},
|
|
509
|
-
];
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// Export default instance
|
|
514
|
-
export const ciStatusManager = new CIStatusManager();
|
|
515
|
-
|
|
516
|
-
// Export convenience functions
|
|
517
|
-
export async function getPackageCIStatus(
|
|
518
|
-
packageName: string
|
|
519
|
-
): Promise<CIPackageStatus | null> {
|
|
520
|
-
return ciStatusManager.getPackageStatus(packageName);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
export async function getMonorepoCIStatus(
|
|
524
|
-
packages: PackageInfo[]
|
|
525
|
-
): Promise<CIMonorepoStatus> {
|
|
526
|
-
return ciStatusManager.getMonorepoStatus(packages);
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
export async function triggerPackageBuild(
|
|
530
|
-
packageName: string,
|
|
531
|
-
providerName: string,
|
|
532
|
-
branch?: string
|
|
533
|
-
): Promise<{ success: boolean; buildId?: string; error?: string }> {
|
|
534
|
-
return ciStatusManager.triggerBuild(packageName, providerName, branch);
|
|
535
|
-
}
|
package/src/utils/db-utils.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import type { PackageInfo, DependencyInfo, Commit } from '../types';
|
|
2
|
-
import { AppLogger } from '../middleware/logger';
|
|
3
|
-
import { CommitRepository, DependencyRepository, PackageRepository } from '../repositories';
|
|
4
|
-
import { appConfig } from '../config-loader';
|
|
5
|
-
|
|
6
|
-
// Default settings
|
|
7
|
-
const DEFAULT_PORT = 8999;
|
|
8
|
-
const port = appConfig.server.port ?? DEFAULT_PORT; //Default port
|
|
9
|
-
const host = appConfig.server.host ?? 'localhost'; //Default host
|
|
10
|
-
|
|
11
|
-
const API_BASE = `http://${host}:${port}/api`;
|
|
12
|
-
|
|
13
|
-
async function getCommits(path: string): Promise<Commit[]> {
|
|
14
|
-
const res = await fetch(API_BASE + `/commits/` + encodeURIComponent(path));
|
|
15
|
-
if (!res.ok) throw new Error('Failed to fetch commits');
|
|
16
|
-
return (await res.json()) as Commit[];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Get package dependencies
|
|
21
|
-
*/
|
|
22
|
-
function getPackageDependenciesInfo(pkg: PackageInfo): DependencyInfo[] {
|
|
23
|
-
const allDeps: DependencyInfo[] = [];
|
|
24
|
-
Object.keys(pkg.dependencies || {}).forEach(depName => {
|
|
25
|
-
allDeps.push({
|
|
26
|
-
name: depName,
|
|
27
|
-
version: pkg.dependencies[depName],
|
|
28
|
-
type: 'dependency',
|
|
29
|
-
latest: '',
|
|
30
|
-
outdated: false,
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
Object.keys(pkg.devDependencies || {}).forEach(depName => {
|
|
34
|
-
allDeps.push({
|
|
35
|
-
name: depName,
|
|
36
|
-
version: pkg.devDependencies[depName],
|
|
37
|
-
type: 'devDependency',
|
|
38
|
-
latest: '',
|
|
39
|
-
outdated: false,
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
Object.keys(pkg.peerDependencies || {}).forEach(depName => {
|
|
43
|
-
allDeps.push({
|
|
44
|
-
name: depName,
|
|
45
|
-
version: pkg.peerDependencies[depName]!,
|
|
46
|
-
type: 'peerDependency',
|
|
47
|
-
latest: '',
|
|
48
|
-
outdated: false,
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
return allDeps;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Store packages in database using repository pattern
|
|
56
|
-
*/
|
|
57
|
-
async function storePackage(pkg: PackageInfo): Promise<void> {
|
|
58
|
-
try {
|
|
59
|
-
// Create or update package using repository
|
|
60
|
-
await PackageRepository.upsert({
|
|
61
|
-
name: pkg.name,
|
|
62
|
-
version: pkg.version,
|
|
63
|
-
type: pkg.type,
|
|
64
|
-
path: pkg.path,
|
|
65
|
-
description: pkg.description,
|
|
66
|
-
license: pkg.license,
|
|
67
|
-
repository: pkg.repository,
|
|
68
|
-
scripts: pkg.scripts,
|
|
69
|
-
dependencies: pkg.dependencies,
|
|
70
|
-
devDependencies: pkg.devDependencies,
|
|
71
|
-
peerDependencies: pkg.peerDependencies,
|
|
72
|
-
maintainers: pkg.maintainers.join(','),
|
|
73
|
-
status: '',
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// Store commits using repository
|
|
77
|
-
const commits = await getCommits(pkg.path ?? '');
|
|
78
|
-
if (commits.length) {
|
|
79
|
-
await CommitRepository.storeMany(pkg.name, commits);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Store dependencies using repository
|
|
83
|
-
const dependenciesInfo = getPackageDependenciesInfo(pkg);
|
|
84
|
-
if (dependenciesInfo.length) {
|
|
85
|
-
await DependencyRepository.storeMany(pkg.name, dependenciesInfo);
|
|
86
|
-
}
|
|
87
|
-
} catch (error) {
|
|
88
|
-
AppLogger.warn(`Failed to store report for ${pkg.name}`);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export { storePackage };
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import type { PackageHealth } from '../types';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Calculates package health score based on various metrics
|
|
5
|
-
*/
|
|
6
|
-
function calculatePackageHealth(
|
|
7
|
-
buildStatus: PackageHealth['buildStatus'],
|
|
8
|
-
testCoverage: number,
|
|
9
|
-
lintStatus: PackageHealth['lintStatus'],
|
|
10
|
-
securityAudit: PackageHealth['securityAudit']
|
|
11
|
-
): PackageHealth {
|
|
12
|
-
let score = 0;
|
|
13
|
-
|
|
14
|
-
// Build status (30 points)
|
|
15
|
-
switch (buildStatus) {
|
|
16
|
-
case 'success':
|
|
17
|
-
score += 30;
|
|
18
|
-
break;
|
|
19
|
-
case 'running':
|
|
20
|
-
score += 15;
|
|
21
|
-
break;
|
|
22
|
-
case 'failed':
|
|
23
|
-
score += 0;
|
|
24
|
-
break;
|
|
25
|
-
default:
|
|
26
|
-
score += 10;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Test coverage (25 points)
|
|
30
|
-
score += Math.min(25, (testCoverage / 100) * 25);
|
|
31
|
-
|
|
32
|
-
// Lint status (25 points)
|
|
33
|
-
switch (lintStatus) {
|
|
34
|
-
case 'pass':
|
|
35
|
-
score += 25;
|
|
36
|
-
break;
|
|
37
|
-
case 'fail':
|
|
38
|
-
score += 0;
|
|
39
|
-
break;
|
|
40
|
-
default:
|
|
41
|
-
score += 10;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Security audit (20 points)
|
|
45
|
-
switch (securityAudit) {
|
|
46
|
-
case 'pass':
|
|
47
|
-
score += 20;
|
|
48
|
-
break;
|
|
49
|
-
case 'fail':
|
|
50
|
-
score += 0;
|
|
51
|
-
break;
|
|
52
|
-
default:
|
|
53
|
-
score += 10;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
buildStatus,
|
|
58
|
-
testCoverage,
|
|
59
|
-
lintStatus,
|
|
60
|
-
securityAudit,
|
|
61
|
-
overallScore: Math.round(score),
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export {
|
|
66
|
-
calculatePackageHealth,
|
|
67
|
-
};
|