@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.
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.getPublishPackages = getPublishPackages;
4
37
  exports.getPublishChangesets = getPublishChangesets;
@@ -7,8 +40,10 @@ exports.createChangeset = createChangeset;
7
40
  exports.checkPublishStatus = checkPublishStatus;
8
41
  exports.triggerPublish = triggerPublish;
9
42
  const logger_1 = require("../middleware/logger");
10
- const auth_middleware_1 = require("../middleware/auth-middleware");
11
43
  const changeset_service_1 = require("../services/changeset-service");
44
+ const pipelineService = __importStar(require("../services/pipeline-service"));
45
+ const utilities_1 = require("../utils/utilities");
46
+ const github_actions_service_1 = require("../services/github-actions-service");
12
47
  /**
13
48
  * Get all workspace packages
14
49
  */
@@ -75,14 +110,13 @@ async function previewPublish(req, res) {
75
110
  // Calculate new versions
76
111
  const newVersions = (0, changeset_service_1.calculateNewVersions)(selectedPackages, bumps || []);
77
112
  // Check if working tree is clean
78
- const isClean = true; //await isWorkingTreeClean(rootPath);
113
+ const isClean = await (0, changeset_service_1.isWorkingTreeClean)(rootPath);
79
114
  // Get existing changesets
80
115
  const changesets = await (0, changeset_service_1.getExistingChangesets)(rootPath);
81
116
  // Perform validation checks
82
117
  const errors = [];
83
118
  const warnings = [];
84
119
  // Get authenticated user
85
- const session = (0, auth_middleware_1.getSessionFromRequest)(req);
86
120
  const authUser = req.user;
87
121
  const userPermission = req.permission.permission || 'read';
88
122
  // Check 1: Working tree clean
@@ -215,7 +249,7 @@ async function checkPublishStatus(req, res) {
215
249
  try {
216
250
  const rootPath = req.app.locals.rootPath;
217
251
  // Check if working tree is clean
218
- const isClean = true; //await isWorkingTreeClean(rootPath);
252
+ const isClean = await (0, changeset_service_1.isWorkingTreeClean)(rootPath);
219
253
  // Get existing changesets
220
254
  const changesets = await (0, changeset_service_1.getExistingChangesets)(rootPath);
221
255
  res.json({
@@ -244,6 +278,8 @@ async function triggerPublish(req, res) {
244
278
  const rootPath = req.app.locals.rootPath;
245
279
  const authUser = req.user;
246
280
  const userPermission = req.permission.permission || 'read';
281
+ const { packages: selectedPackages } = req.body;
282
+ const selectedPackageNames = selectedPackages?.map((pkg) => pkg.name) || [];
247
283
  // Check permissions
248
284
  const permissionHierarchy = {
249
285
  admin: 4,
@@ -264,7 +300,7 @@ async function triggerPublish(req, res) {
264
300
  return;
265
301
  }
266
302
  // Check if working tree is clean
267
- const isClean = true; //await isWorkingTreeClean(rootPath);
303
+ const isClean = await (0, changeset_service_1.isWorkingTreeClean)(rootPath);
268
304
  if (!isClean) {
269
305
  res.status(400).json({
270
306
  success: false,
@@ -284,8 +320,8 @@ async function triggerPublish(req, res) {
284
320
  return;
285
321
  }
286
322
  logger_1.AppLogger.info(`Triggering publish for user: ${authUser?.login} (permission: ${userPermission})`);
287
- // Trigger publish pipeline with user context
288
- const result = await (0, changeset_service_1.triggerPublishPipeline)(rootPath, authUser?.login);
323
+ // Trigger publish pipeline with user context and package info
324
+ const result = await (0, changeset_service_1.triggerPublishPipeline)(rootPath, authUser?.login, selectedPackages);
289
325
  if (!result.success) {
290
326
  res.status(500).json({
291
327
  success: false,
@@ -294,6 +330,82 @@ async function triggerPublish(req, res) {
294
330
  });
295
331
  return;
296
332
  }
333
+ // Create pipeline records in database for each package
334
+ logger_1.AppLogger.info(`Checking if should create pipelines: selectedPackageNames=${JSON.stringify(selectedPackageNames)}, isArray=${Array.isArray(selectedPackageNames)}`);
335
+ if (selectedPackages && Array.isArray(selectedPackages)) {
336
+ logger_1.AppLogger.info(`Creating pipelines for ${selectedPackages.length} packages`);
337
+ try {
338
+ const repoInfo = await (0, utilities_1.getRepositoryInfoFromGit)();
339
+ if (!repoInfo) {
340
+ logger_1.AppLogger.warn('Could not extract repository info from git remote - permission fetch skipped');
341
+ }
342
+ else {
343
+ const { owner, repo } = repoInfo;
344
+ const timestamp = new Date().toISOString();
345
+ logger_1.AppLogger.info(`Extracted GitHub: owner=${owner}, repo=${repo}`);
346
+ // Fetch the actual workflow ID from GitHub
347
+ const accessToken = req.accessToken;
348
+ let realWorkflowId = '1'; // Fallback to '1' if fetch fails
349
+ let workflowPath = 'release.yml'; // Default path for reference
350
+ if (accessToken) {
351
+ try {
352
+ logger_1.AppLogger.info(`Fetching workflows for ${owner}/${repo}`);
353
+ const workflowsResponse = await (0, github_actions_service_1.listWorkflows)(owner, repo, accessToken);
354
+ // Find the main deployment/release workflow (could be named "Release", "Deployment Workflow", etc.)
355
+ const releaseWorkflow = workflowsResponse.workflows.find((workflow) => workflow.name === 'Release' ||
356
+ workflow.name === 'Deployment Workflow' ||
357
+ workflow.name.toLowerCase().includes('release') ||
358
+ workflow.name.toLowerCase().includes('deployment'));
359
+ if (releaseWorkflow) {
360
+ realWorkflowId = String(releaseWorkflow.id);
361
+ workflowPath = String(releaseWorkflow.path);
362
+ logger_1.AppLogger.info(`Found Release workflow with ID: ${realWorkflowId} (name: ${releaseWorkflow.name})`);
363
+ }
364
+ else {
365
+ logger_1.AppLogger.warn(`Release workflow not found. Available workflows: ${workflowsResponse.workflows.map(w => `${w.name}(${w.id})`).join(', ')}`);
366
+ }
367
+ }
368
+ catch (workflowFetchError) {
369
+ logger_1.AppLogger.warn(`Failed to fetch workflows: ${workflowFetchError}. Using fallback ID 1`);
370
+ }
371
+ }
372
+ else {
373
+ logger_1.AppLogger.warn('No access token available to fetch workflows');
374
+ }
375
+ for (const pkg of selectedPackages) {
376
+ try {
377
+ logger_1.AppLogger.info(`Creating pipeline for package: ${pkg.name}`);
378
+ await pipelineService.createOrUpdatePipeline({
379
+ releaseVersion: pkg.newVersion,
380
+ packageName: pkg.name,
381
+ owner,
382
+ repo,
383
+ workflowId: realWorkflowId,
384
+ workflowName: 'Release',
385
+ workflowPath: workflowPath,
386
+ triggerType: 'manual',
387
+ triggeredBy: authUser?.login || 'unknown',
388
+ triggeredAt: timestamp,
389
+ currentStatus: 'queued',
390
+ currentConclusion: null,
391
+ lastRunId: undefined,
392
+ });
393
+ logger_1.AppLogger.info(`Created pipeline record for package: ${pkg.name}`);
394
+ }
395
+ catch (pipelineError) {
396
+ logger_1.AppLogger.warn(`Failed to create pipeline for ${pkg.name}: ${pipelineError}`);
397
+ // Don't fail the whole request if pipeline creation fails
398
+ }
399
+ }
400
+ }
401
+ }
402
+ catch (configError) {
403
+ logger_1.AppLogger.error(`Failed to read package.json for pipeline creation: ${configError}`);
404
+ }
405
+ }
406
+ else {
407
+ logger_1.AppLogger.warn(`Skipping pipeline creation: selectedPackageNames is ${selectedPackageNames}`);
408
+ }
297
409
  res.json({
298
410
  success: true,
299
411
  message: 'Publishing workflow initiated',
@@ -96,6 +96,7 @@ function authenticationMiddleware(req, res, next) {
96
96
  login: session.user.login,
97
97
  id: session.user.id,
98
98
  };
99
+ req.accessToken = session.accessToken;
99
100
  // Attach permission from session (if available)
100
101
  if (session.permission) {
101
102
  req.permission = session.permission;
@@ -21,6 +21,7 @@ const config_routes_1 = __importDefault(require("../routes/config-routes"));
21
21
  const auth_routes_1 = __importDefault(require("../routes/auth-routes"));
22
22
  const permission_routes_1 = __importDefault(require("../routes/permission-routes"));
23
23
  const publish_routes_1 = __importDefault(require("../routes/publish-routes"));
24
+ const pipeline_routes_1 = require("../routes/pipeline-routes");
24
25
  const constants_1 = require("../constants");
25
26
  const auth_middleware_1 = require("./auth-middleware");
26
27
  const permission_service_1 = require("../services/permission-service");
@@ -58,6 +59,9 @@ function createApp(rootPath) {
58
59
  (0, auth_middleware_1.initializeAuthentication)();
59
60
  // Start permission cache cleanup
60
61
  (0, permission_service_1.startCacheCleanup)();
62
+ // Create a router for pipeline routes
63
+ const router = express_1.default.Router();
64
+ (0, pipeline_routes_1.setupPipelineRoutes)(router);
61
65
  // Routes
62
66
  app.use('/api/auth', auth_routes_1.default);
63
67
  app.use('/api/permissions', permission_routes_1.default);
@@ -66,6 +70,7 @@ function createApp(rootPath) {
66
70
  app.use('/api/health/', health_routes_1.default);
67
71
  app.use('/api/config/', config_routes_1.default);
68
72
  app.use('/api/publish', publish_routes_1.default);
73
+ app.use('/api', router); // Pipeline routes
69
74
  // 404 handler
70
75
  app.use('*', error_handler_1.notFoundHandler);
71
76
  // Global error handler (must be last)
@@ -118,6 +123,20 @@ function startServer(rootPath) {
118
123
  'POST /api/publish/preview',
119
124
  'POST /api/publish/changesets',
120
125
  'POST /api/publish/trigger',
126
+ // Pipeline endpoints
127
+ 'GET /api/pipelines',
128
+ 'GET /api/pipelines/:pipelineId',
129
+ 'GET /api/pipelines/package/:owner/:repo/:packageName',
130
+ 'PUT /api/pipelines/:pipelineId/status',
131
+ 'GET /api/workflows/:owner/:repo',
132
+ 'GET /api/workflows/:owner/:repo/runs',
133
+ 'GET /api/runs/:runId/jobs',
134
+ 'GET /api/jobs/:jobId/logs',
135
+ 'POST /api/workflows/:workflowId/trigger',
136
+ 'POST /api/workflows/:workflowId/dispatch',
137
+ 'GET /api/audit-logs',
138
+ 'GET /api/metrics',
139
+ 'GET /api/rate-limit',
121
140
  ],
122
141
  });
123
142
  });
@@ -190,6 +190,8 @@ router.get('/callback', async (req, res) => {
190
190
  permission: permission ? {
191
191
  level: permission.permission,
192
192
  role: permission.role,
193
+ owner: permission.owner,
194
+ repo: permission.repo,
193
195
  } : null,
194
196
  });
195
197
  }
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /**
3
+ * GitHub Actions and Release Pipeline Routes
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.setupPipelineRoutes = setupPipelineRoutes;
7
+ const auth_middleware_1 = require("../middleware/auth-middleware");
8
+ const pipeline_controller_1 = require("../controllers/pipeline-controller");
9
+ function setupPipelineRoutes(router) {
10
+ /**
11
+ * GET /api/pipelines
12
+ * Get recent pipelines for the dashboard
13
+ */
14
+ router.get('/pipelines', auth_middleware_1.authenticationMiddleware, pipeline_controller_1.getRecentPipelines);
15
+ /**
16
+ * PUT /api/pipelines/:pipelineId/status
17
+ * Update pipeline status based on latest workflow run
18
+ */
19
+ router.put('/pipelines/:pipelineId/status', auth_middleware_1.authenticationMiddleware, pipeline_controller_1.updatePipelineStatus);
20
+ /**
21
+ * GET /api/workflows/:owner/:repo/available
22
+ * List available workflows in a repository
23
+ */
24
+ router.get('/workflows/:owner/:repo/available', auth_middleware_1.authenticationMiddleware, pipeline_controller_1.listAvailableWorkflows);
25
+ /**
26
+ * GET /api/workflows/:owner/:repo
27
+ * Get workflow runs for a repository
28
+ */
29
+ router.get('/workflows/:owner/:repo', auth_middleware_1.authenticationMiddleware, pipeline_controller_1.getWorkflowRuns);
30
+ /**
31
+ * GET /api/workflows/:owner/:repo/runs/:runId
32
+ * Get specific workflow run with jobs
33
+ */
34
+ router.get('/workflows/:owner/:repo/runs/:runId', auth_middleware_1.authenticationMiddleware, pipeline_controller_1.getWorkflowRunWithJobs);
35
+ /**
36
+ * GET /api/workflows/:owner/:repo/jobs/:jobId/logs
37
+ * Get logs for a job
38
+ */
39
+ router.get('/workflows/:owner/:repo/jobs/:jobId/logs', auth_middleware_1.authenticationMiddleware, pipeline_controller_1.getJobLogs);
40
+ /**
41
+ * POST /api/workflows/:owner/:repo/trigger
42
+ * Trigger a workflow
43
+ */
44
+ router.post('/workflows/:owner/:repo/trigger', auth_middleware_1.authenticationMiddleware, pipeline_controller_1.triggerWorkflow);
45
+ /**
46
+ * POST /api/workflows/:owner/:repo/runs/:runId/cancel
47
+ * Cancel a workflow run
48
+ */
49
+ router.post('/workflows/:owner/:repo/runs/:runId/cancel', auth_middleware_1.authenticationMiddleware, pipeline_controller_1.cancelWorkflowRun);
50
+ /**
51
+ * POST /api/workflows/:owner/:repo/runs/:runId/rerun
52
+ * Re-run a workflow
53
+ */
54
+ router.post('/workflows/:owner/:repo/runs/:runId/rerun', auth_middleware_1.authenticationMiddleware, pipeline_controller_1.rerunWorkflow);
55
+ /**
56
+ * GET /api/pipelines/:pipelineId/audit-logs
57
+ * Get audit logs for a pipeline
58
+ */
59
+ router.get('/pipelines/:pipelineId/audit-logs', auth_middleware_1.authenticationMiddleware, pipeline_controller_1.getPipelineAuditLogs);
60
+ /**
61
+ * GET /api/rate-limit
62
+ * Get GitHub API rate limit information
63
+ */
64
+ // router.get('/rate-limit', authenticationMiddleware, async (req: Request, res: Response) => {
65
+ // try {
66
+ // if (!req.user || !req.accessToken) {
67
+ // return res.status(401).json({ error: 'Unauthorized' });
68
+ // }
69
+ // const rateLimit = await githubActionsService.getRateLimit(req.accessToken);
70
+ // res.json(rateLimit);
71
+ // } catch (error) {
72
+ // AppLogger.error(`Error getting rate limit: ${error}`);
73
+ // res.status(500).json({ error: 'Failed to get rate limit' });
74
+ // }
75
+ // });
76
+ }
@@ -173,6 +173,7 @@ async function generateChangeset(rootPath, packages, bumps, summary, createdBy)
173
173
  * Check if working tree is clean
174
174
  */
175
175
  async function isWorkingTreeClean(rootPath) {
176
+ return true; // For testing purposes, we assume it's always clean. Replace with actual git status check in production.
176
177
  try {
177
178
  const { stdout } = await execPromise('git status --porcelain', {
178
179
  cwd: rootPath,
@@ -186,20 +187,9 @@ async function isWorkingTreeClean(rootPath) {
186
187
  /**
187
188
  * Trigger CI pipeline for publishing
188
189
  */
189
- async function triggerPublishPipeline(rootPath, publishedBy) {
190
+ async function triggerPublishPipeline(rootPath, publishedBy, selectedPackages) {
190
191
  try {
191
192
  logger_1.AppLogger.info(`Publishing workflow triggered by user: ${publishedBy || 'unknown'}`);
192
- // Check if publish workflow exists
193
- const publishWorkflowPath = path_1.default.join(rootPath, '.github', 'workflows', 'release.yml');
194
- try {
195
- await promises_1.default.stat(publishWorkflowPath);
196
- }
197
- catch {
198
- return {
199
- success: false,
200
- message: 'Publish workflow not configured',
201
- };
202
- }
203
193
  // Commit the changeset if there are any changes
204
194
  try {
205
195
  const { stdout: status } = await execPromise('git status --porcelain', {
@@ -235,7 +225,6 @@ async function triggerPublishPipeline(rootPath, publishedBy) {
235
225
  message: 'Publishing workflow initiated',
236
226
  result: {
237
227
  timestamp: new Date().toISOString(),
238
- workflowPath: publishWorkflowPath,
239
228
  },
240
229
  };
241
230
  }