@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 CHANGED
@@ -1,5 +1,69 @@
1
1
  # @manojkmfsi/monoapp
2
2
 
3
+ ## 1.1.30
4
+
5
+ ### Patch Changes
6
+
7
+ - [`f27db43`](https://github.com/manojkmfsi/monodog/commit/f27db43277895381dbf239ffd57ebb17e7fd6e13) - sasasasasasasas
8
+
9
+ ## 1.1.29
10
+
11
+ ### Patch Changes
12
+
13
+ - [`8600e0c`](https://github.com/manojkmfsi/monodog/commit/8600e0c636f76c8b9dcc8fbf7a2617d355f2d0e5) - fsfyfhfhfjjh,m
14
+
15
+ - [`188bcf2`](https://github.com/manojkmfsi/monodog/commit/188bcf2ab06b5fe58b2cea5915a7751cba3a68d2) - cxzcxvxcbvcbnb,m
16
+
17
+ - [`cfb03da`](https://github.com/manojkmfsi/monodog/commit/cfb03da50efd0b829bf4a8b4c5c2ae68c4d1a4ce) - mkjmnmnmnmnnmnm
18
+
19
+ - [`d95b183`](https://github.com/manojkmfsi/monodog/commit/d95b183ea3aa3a60f153d40d1db4049565ecaffa) - m nm nm nm nm mn nm mmm nm mn mm
20
+
21
+ - [`8abe3fb`](https://github.com/manojkmfsi/monodog/commit/8abe3fb09b2608696e6960ac0fdb8e0a9112dfa7) - xzdfdguiulmn cxdtyj
22
+
23
+ - [`9add854`](https://github.com/manojkmfsi/monodog/commit/9add854171041d38161916c2ce5ed34af471614a) - hbmjnbmm,n,,m,
24
+
25
+ - [`5f9b61e`](https://github.com/manojkmfsi/monodog/commit/5f9b61e73c8d1c460dac445aa9c5ae52ed053883) - cxgfhgjmnmnm,k,m
26
+
27
+ - [`bde7bfb`](https://github.com/manojkmfsi/monodog/commit/bde7bfb74376917ab590c8f0d831c3aa0a9e0482) - vnmn,nkjlkn,mnm,
28
+
29
+ - [`e67b026`](https://github.com/manojkmfsi/monodog/commit/e67b02689d82fb4cae0ca917fdb829c3d23d3b9d) - drkjk,,kjudscxvxvvvvnm
30
+
31
+ - [`6b78e09`](https://github.com/manojkmfsi/monodog/commit/6b78e09e6e090ece45485b0e43b1b6e5a537e4eb) - fcdgcbvnkmkllml.m.
32
+
33
+ - [`1a74552`](https://github.com/manojkmfsi/monodog/commit/1a74552277f8deaef831649ad424ea41c77fd467) - nhuyfgxbvnbmklm, .,nmkn,
34
+
35
+ - [`fe566fd`](https://github.com/manojkmfsi/monodog/commit/fe566fdb7041ce079e8afe78ebdb4b477f0cae44) - fghjvvnvnbn
36
+
37
+ - [`79566ae`](https://github.com/manojkmfsi/monodog/commit/79566ae23e3f30a03482134f35b5491e289d2775) - adssdxvcvbcbvcxvcbvcb
38
+
39
+ - [`804ddf2`](https://github.com/manojkmfsi/monodog/commit/804ddf22cf845aa2c980bff9488a04e251be119a) - fxcbcvcxcbvnbvnb
40
+
41
+ - [`07e1878`](https://github.com/manojkmfsi/monodog/commit/07e18786e6f3d8dad57f90822af93bd578c9c3ae) - bvcghmjnm,nmnmhkjhn,mn
42
+
43
+ - [`faa4e0c`](https://github.com/manojkmfsi/monodog/commit/faa4e0cb48e0b1f8eae6aa93f104924452076b94) - mnmmmmnmnmn,mn,mnmn,
44
+
45
+ - [`4ed3483`](https://github.com/manojkmfsi/monodog/commit/4ed34834edea9c6789ffbf93c1354f9752b59b8b) - n,mnmnmnmn,mnm,,m
46
+
47
+ - [`dd47e0b`](https://github.com/manojkmfsi/monodog/commit/dd47e0b8480f14a78b958f3ff68d3b41082f3465) - mnn,mn,mn,n,mn,,
48
+
49
+ - [`621bee1`](https://github.com/manojkmfsi/monodog/commit/621bee11b6194ee56fd90c130a4b3c83b386831a) - kmmnmmn,n,m,m, n,m
50
+
51
+ - [`ec7e1b0`](https://github.com/manojkmfsi/monodog/commit/ec7e1b0817ae540ece67576fbceb7486dcadc48f) - mnm,n,n,mn,mn,m,m,m,
52
+
53
+ - [`411523b`](https://github.com/manojkmfsi/monodog/commit/411523b813a96fcfd46c3e459bcd887c255fd2e7) - mnmn,mn,mn,m.,m.,m.,m,m.,
54
+
55
+ - [`ec19a7c`](https://github.com/manojkmfsi/monodog/commit/ec19a7ccff425f7319c24d0506a147fcfdd0e9ca) - vbcbvbnvnmbnmbnmnm
56
+
57
+ - [`6818670`](https://github.com/manojkmfsi/monodog/commit/6818670424be6bdb98e1fd2e04f1fe985638e67e) - cxxvcvcbvbnvnbvnmnm
58
+
59
+ - [`10eac2e`](https://github.com/manojkmfsi/monodog/commit/10eac2ee72753474d4ec0d9ba2ba3ebdd4639c96) - sdhgjhkjhkjjkkkjn
60
+
61
+ - [`4c924c9`](https://github.com/manojkmfsi/monodog/commit/4c924c918f93cbd54c1c752060a6bdaab45e987d) - wdassdsfddfsdffdgfdsgfsgfg
62
+
63
+ - [`a9e5e26`](https://github.com/manojkmfsi/monodog/commit/a9e5e2680f49c448c49e3a1c414d5c2533a5e9cf) - nnknknnnknkn,,mnm,
64
+
65
+ - [`d559595`](https://github.com/manojkmfsi/monodog/commit/d559595e3b56371a102a21244d0d6c5696541bd3) - dsdsmnd,mns,mnd,msnd,msn,md
66
+
3
67
  ## 1.1.28
4
68
 
5
69
  ### Patch Changes
package/check-db.js ADDED
@@ -0,0 +1,58 @@
1
+ const { PrismaClient } = require('@prisma/client');
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+
5
+ // Load config similar to the app
6
+ let databasePath = 'file:./monodog.db'; // default
7
+
8
+ // Try to read monodog-config.json
9
+ try {
10
+ const configPath = path.join(__dirname, 'monodog-config.json');
11
+ if (fs.existsSync(configPath)) {
12
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
13
+ databasePath = config.database?.path || databasePath;
14
+ }
15
+ } catch (e) {
16
+ console.warn('Could not read config:', e.message);
17
+ }
18
+
19
+ console.log(`Database URL: ${databasePath}\n`);
20
+
21
+ async function checkDatabase() {
22
+ const prisma = new PrismaClient({
23
+ datasources: {
24
+ db: {
25
+ url: databasePath,
26
+ },
27
+ },
28
+ });
29
+
30
+ try {
31
+ console.log('=== Database Status ===\n');
32
+
33
+ // Check ReleasePipeline count
34
+ const pipelineCount = await prisma.releasePipeline.count();
35
+ console.log(`Total pipelines in database: ${pipelineCount}\n`);
36
+
37
+ if (pipelineCount > 0) {
38
+ const pipelines = await prisma.releasePipeline.findMany({
39
+ take: 5,
40
+ orderBy: { createdAt: 'desc' },
41
+ });
42
+ console.log('Latest pipelines:');
43
+ pipelines.forEach(p => {
44
+ console.log(` - ${p.packageName} v${p.releaseVersion} (${p.currentStatus})`);
45
+ console.log(` Triggered by: ${p.triggeredBy} at ${p.triggeredAt}`);
46
+ console.log(` Owner/Repo: ${p.owner}/${p.repo}`);
47
+ console.log('');
48
+ });
49
+ }
50
+
51
+ process.exit(0);
52
+ } catch (error) {
53
+ console.error('Error:', error.message);
54
+ process.exit(1);
55
+ }
56
+ }
57
+
58
+ checkDatabase();
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * This script creates a test session by directly calling the auth middleware's storeSession function
5
+ * It simulates what happens after a successful GitHub OAuth login
6
+ */
7
+
8
+ const { storeSession } = require('./dist/middleware/auth-middleware');
9
+
10
+ // Create a mock session
11
+ const mockSession = {
12
+ accessToken: 'gho_test_token_' + Math.random().toString(36).substr(2, 9),
13
+ expiresIn: 3600,
14
+ expiresAt: Date.now() + 24 * 60 * 60 * 1000,
15
+ user: {
16
+ id: 12345,
17
+ login: 'testuser',
18
+ name: 'Test User',
19
+ email: 'test@example.com',
20
+ avatar_url: 'https://avatars.githubusercontent.com/u/12345?v=4',
21
+ public_repos: 5,
22
+ followers: 10,
23
+ following: 5,
24
+ },
25
+ scopes: ['repo', 'read:user'],
26
+ permission: {
27
+ permission: 'maintain',
28
+ role: 'Maintainer',
29
+ userId: 12345,
30
+ username: 'testuser',
31
+ owner: 'manojkmfsi',
32
+ repo: 'MonoDog',
33
+ cachedAt: Date.now(),
34
+ ttl: 3600000,
35
+ },
36
+ };
37
+
38
+ try {
39
+ const token = storeSession(mockSession);
40
+ console.log('✅ Test session created successfully!');
41
+ console.log(`\nSession Token: ${token}`);
42
+ console.log(`User: ${mockSession.user.login}`);
43
+ console.log(`Permission: ${mockSession.permission.permission}`);
44
+ console.log(`Expires at: ${new Date(mockSession.expiresAt).toISOString()}`);
45
+ console.log(`\nYou can use this token in API requests:`);
46
+ console.log(`curl -H "Authorization: Bearer ${token}" http://localhost:8999/api/publish/trigger`);
47
+ } catch (error) {
48
+ console.error('❌ Failed to create session:', error.message);
49
+ process.exit(1);
50
+ }
package/dev-server.pid ADDED
@@ -0,0 +1 @@
1
+ 22401
@@ -0,0 +1,329 @@
1
+ "use strict";
2
+ /**
3
+ * Pipeline Controller
4
+ * Handles HTTP requests and responses for pipeline operations
5
+ * Delegates business logic to pipeline service
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.getRecentPipelines = getRecentPipelines;
42
+ exports.updatePipelineStatus = updatePipelineStatus;
43
+ exports.listAvailableWorkflows = listAvailableWorkflows;
44
+ exports.getWorkflowRuns = getWorkflowRuns;
45
+ exports.getWorkflowRunWithJobs = getWorkflowRunWithJobs;
46
+ exports.getJobLogs = getJobLogs;
47
+ exports.triggerWorkflow = triggerWorkflow;
48
+ exports.getPipelineAuditLogs = getPipelineAuditLogs;
49
+ exports.cancelWorkflowRun = cancelWorkflowRun;
50
+ exports.rerunWorkflow = rerunWorkflow;
51
+ const logger_1 = require("../middleware/logger");
52
+ const pipelineService = __importStar(require("../services/pipeline-service"));
53
+ const githubActionsService = __importStar(require("../services/github-actions-service"));
54
+ /**
55
+ * Get recent pipelines for the dashboard
56
+ * GET /api/pipelines
57
+ */
58
+ async function getRecentPipelines(req, res) {
59
+ try {
60
+ if (!req.user) {
61
+ return res.status(401).json({ error: 'Unauthorized' });
62
+ }
63
+ const limit = Math.min(parseInt(req.query.limit) || 20, 100);
64
+ const offset = parseInt(req.query.offset) || 0;
65
+ const pipelines = await pipelineService.getRecentPipelines(limit, offset);
66
+ res.json(pipelines);
67
+ }
68
+ catch (error) {
69
+ logger_1.AppLogger.error(`Error getting pipelines: ${error}`);
70
+ res.status(500).json({ error: 'Failed to get pipelines' });
71
+ }
72
+ }
73
+ /**
74
+ * Update pipeline status based on latest workflow run
75
+ * PUT /api/pipelines/:pipelineId/status
76
+ */
77
+ async function updatePipelineStatus(req, res) {
78
+ try {
79
+ if (!req.user) {
80
+ return res.status(401).json({ error: 'Unauthorized' });
81
+ }
82
+ const { pipelineId } = req.params;
83
+ const { currentStatus, currentConclusion, lastRunId } = req.body;
84
+ if (!currentStatus) {
85
+ return res.status(400).json({ error: 'currentStatus is required' });
86
+ }
87
+ const updatedPipeline = await pipelineService.updatePipelineStatus(pipelineId, currentStatus, currentConclusion || null, lastRunId ? String(lastRunId) : undefined);
88
+ res.json({
89
+ success: true,
90
+ pipeline: updatedPipeline,
91
+ });
92
+ }
93
+ catch (error) {
94
+ logger_1.AppLogger.error(`Error updating pipeline status: ${error}`);
95
+ res.status(500).json({ error: 'Failed to update pipeline status' });
96
+ }
97
+ }
98
+ /**
99
+ * Get available workflows in a repository
100
+ * GET /api/workflows/:owner/:repo/available
101
+ */
102
+ async function listAvailableWorkflows(req, res) {
103
+ try {
104
+ if (!req.user || !req.accessToken) {
105
+ return res.status(401).json({ error: 'Unauthorized' });
106
+ }
107
+ const { owner, repo } = req.params;
108
+ const result = await githubActionsService.listWorkflows(owner, repo, req.accessToken);
109
+ res.json(result);
110
+ }
111
+ catch (error) {
112
+ logger_1.AppLogger.error(`Error listing workflows: ${error}`);
113
+ res.status(500).json({ error: 'Failed to list workflows' });
114
+ }
115
+ }
116
+ /**
117
+ * Get workflow runs for a repository
118
+ * GET /api/workflows/:owner/:repo
119
+ */
120
+ async function getWorkflowRuns(req, res) {
121
+ try {
122
+ if (!req.user || !req.accessToken) {
123
+ return res.status(401).json({ error: 'Unauthorized' });
124
+ }
125
+ const { owner, repo } = req.params;
126
+ const workflowId = req.query.workflow_id;
127
+ const workflowPath = req.query.workflow_path;
128
+ const status = req.query.status;
129
+ const page = parseInt(req.query.page) || 1;
130
+ const per_page = parseInt(req.query.per_page) || 30;
131
+ logger_1.AppLogger.info(`GET /workflows/${owner}/${repo}: workflowId=${workflowId}, workflowPath=${workflowPath}, status=${status}, page=${page}, per_page=${per_page}`);
132
+ const result = await githubActionsService.getWorkflowRuns(owner, repo, req.accessToken, {
133
+ workflowId,
134
+ workflowPath,
135
+ status,
136
+ page,
137
+ per_page,
138
+ });
139
+ logger_1.AppLogger.info(`GET /workflows/${owner}/${repo}: Returned ${result.runs.length} runs (total: ${result.totalCount})`);
140
+ res.json(result);
141
+ }
142
+ catch (error) {
143
+ logger_1.AppLogger.error(`Error getting workflows: ${error}`);
144
+ res.status(500).json({ error: 'Failed to get workflows' });
145
+ }
146
+ }
147
+ /**
148
+ * Get specific workflow run with jobs
149
+ * GET /api/workflows/:owner/:repo/runs/:runId
150
+ */
151
+ async function getWorkflowRunWithJobs(req, res) {
152
+ try {
153
+ if (!req.user || !req.accessToken) {
154
+ return res.status(401).json({ error: 'Unauthorized' });
155
+ }
156
+ const { owner, repo, runId } = req.params;
157
+ const page = parseInt(req.query.page) || 1;
158
+ // Get run details
159
+ const { run, rateLimit: runRateLimit } = await githubActionsService.getWorkflowRun(owner, repo, parseInt(runId), req.accessToken);
160
+ // Get jobs
161
+ const { jobs, totalCount, rateLimit: jobsRateLimit } = await githubActionsService.getWorkflowRunJobs(owner, repo, parseInt(runId), req.accessToken, page);
162
+ // Transform jobs to match frontend expectations
163
+ const transformedJobs = jobs.map((job) => ({
164
+ id: job.id,
165
+ gitHubJobId: job.id,
166
+ name: job.name,
167
+ status: job.status,
168
+ conclusion: job.conclusion || null,
169
+ htmlUrl: job.html_url,
170
+ startedAt: job.started_at,
171
+ completedAt: job.completed_at,
172
+ }));
173
+ res.json({
174
+ run,
175
+ jobs: transformedJobs,
176
+ pagination: {
177
+ page,
178
+ totalCount,
179
+ pageSize: transformedJobs.length,
180
+ },
181
+ rateLimit: {
182
+ limit: runRateLimit?.limit,
183
+ remaining: runRateLimit?.remaining,
184
+ reset: runRateLimit?.reset,
185
+ },
186
+ });
187
+ }
188
+ catch (error) {
189
+ logger_1.AppLogger.error(`Error getting workflow run: ${error}`);
190
+ res.status(500).json({ error: 'Failed to get workflow run' });
191
+ }
192
+ }
193
+ /**
194
+ * Get job logs
195
+ * GET /api/workflows/:owner/:repo/jobs/:jobId/logs
196
+ */
197
+ async function getJobLogs(req, res) {
198
+ try {
199
+ if (!req.user || !req.accessToken) {
200
+ return res.status(401).json({ error: 'Unauthorized' });
201
+ }
202
+ const { owner, repo, jobId } = req.params;
203
+ logger_1.AppLogger.info(`[LOGS] Fetching job logs: owner=${owner}, repo=${repo}, jobId=${jobId}, user=${req.user?.login}`);
204
+ const { logs, rateLimit } = await githubActionsService.getJobLogs(owner, repo, parseInt(jobId), req.accessToken);
205
+ logger_1.AppLogger.info(`[LOGS] Successfully fetched ${logs.length} characters of logs`);
206
+ res.json({
207
+ logs: logs || '',
208
+ rateLimit,
209
+ meta: {
210
+ size: logs.length,
211
+ isEmpty: !logs || logs.trim().length === 0,
212
+ },
213
+ });
214
+ }
215
+ catch (error) {
216
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
217
+ logger_1.AppLogger.error(`[LOGS ERROR] Failed to fetch job logs: ${errorMsg}`);
218
+ res.status(500).json({
219
+ error: 'Failed to get job logs',
220
+ details: errorMsg,
221
+ jobId: req.params.jobId,
222
+ });
223
+ }
224
+ }
225
+ /**
226
+ * Trigger a workflow run
227
+ * POST /api/workflows/:owner/:repo/trigger
228
+ */
229
+ async function triggerWorkflow(req, res) {
230
+ try {
231
+ if (!req.user || !req.accessToken) {
232
+ return res.status(401).json({ error: 'Unauthorized' });
233
+ }
234
+ const { owner, repo } = req.params;
235
+ const { pipelineId, workflowId, ref, inputs } = req.body;
236
+ if (!workflowId || !ref) {
237
+ return res.status(400).json({
238
+ error: 'Missing required fields: workflowId, ref',
239
+ });
240
+ }
241
+ const result = await githubActionsService.triggerWorkflow(req.accessToken, {
242
+ owner,
243
+ repo,
244
+ workflow: workflowId,
245
+ ref,
246
+ inputs,
247
+ });
248
+ if (pipelineId) {
249
+ await pipelineService.createAuditLog(pipelineId, req.user.id, req.user.login, 'trigger', 'workflow', String(workflowId), `Trigger workflow`, {}, result.response.success ? 'success' : 'failure');
250
+ }
251
+ res.json({
252
+ success: result.response.success,
253
+ message: result.response.message,
254
+ rateLimit: result.rateLimit,
255
+ });
256
+ }
257
+ catch (error) {
258
+ logger_1.AppLogger.error(`Error triggering workflow: ${error}`);
259
+ res.status(500).json({ error: 'Failed to trigger workflow' });
260
+ }
261
+ }
262
+ /**
263
+ * Get pipeline audit logs
264
+ * GET /api/pipelines/:pipelineId/audit
265
+ */
266
+ async function getPipelineAuditLogs(req, res) {
267
+ try {
268
+ if (!req.user) {
269
+ return res.status(401).json({ error: 'Unauthorized' });
270
+ }
271
+ const { pipelineId } = req.params;
272
+ const limit = Math.min(parseInt(req.query.limit) || 50, 500);
273
+ const offset = parseInt(req.query.offset) || 0;
274
+ const logs = await pipelineService.getPipelineAuditLogs(pipelineId, limit, offset);
275
+ res.json({
276
+ success: true,
277
+ logs,
278
+ count: logs.length,
279
+ });
280
+ }
281
+ catch (error) {
282
+ logger_1.AppLogger.error(`Error getting audit logs: ${error}`);
283
+ res.status(500).json({ error: 'Failed to get audit logs' });
284
+ }
285
+ }
286
+ /**
287
+ * Cancel a workflow run
288
+ * POST /api/workflows/:owner/:repo/runs/:runId/cancel
289
+ */
290
+ async function cancelWorkflowRun(req, res) {
291
+ try {
292
+ if (!req.user || !req.accessToken) {
293
+ return res.status(401).json({ error: 'Unauthorized' });
294
+ }
295
+ const { owner, repo, runId } = req.params;
296
+ const { pipelineId } = req.body;
297
+ const { success, rateLimit } = await githubActionsService.cancelWorkflowRun(owner, repo, parseInt(runId), req.accessToken);
298
+ if (pipelineId) {
299
+ await pipelineService.createAuditLog(pipelineId, req.user.id, req.user.login, 'cancel', 'workflow_run', String(runId), `Cancel workflow run ${runId}`, {}, success ? 'success' : 'failure');
300
+ }
301
+ res.json({ success, rateLimit });
302
+ }
303
+ catch (error) {
304
+ logger_1.AppLogger.error(`Error cancelling workflow: ${error}`);
305
+ res.status(500).json({ error: 'Failed to cancel workflow' });
306
+ }
307
+ }
308
+ /**
309
+ * Rerun a workflow
310
+ * POST /api/workflows/:owner/:repo/runs/:runId/rerun
311
+ */
312
+ async function rerunWorkflow(req, res) {
313
+ try {
314
+ if (!req.user || !req.accessToken) {
315
+ return res.status(401).json({ error: 'Unauthorized' });
316
+ }
317
+ const { owner, repo, runId } = req.params;
318
+ const { failedOnly = false, pipelineId } = req.body;
319
+ const { success, rateLimit } = await githubActionsService.rerunWorkflow(owner, repo, parseInt(runId), req.accessToken, failedOnly);
320
+ if (pipelineId) {
321
+ await pipelineService.createAuditLog(pipelineId, req.user.id, req.user.login, 'rerun', 'workflow_run', String(runId), `Rerun workflow ${failedOnly ? '(failed jobs only)' : ''}`, { failedOnly }, success ? 'success' : 'failure');
322
+ }
323
+ res.json({ success, rateLimit });
324
+ }
325
+ catch (error) {
326
+ logger_1.AppLogger.error(`Error rerunning workflow: ${error}`);
327
+ res.status(500).json({ error: 'Failed to rerun workflow' });
328
+ }
329
+ }