@andrebuzeli/git-mcp 5.0.0 → 5.0.2
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/dist/providers/github-provider-backup.d.ts +81 -0
- package/dist/providers/github-provider-backup.d.ts.map +1 -0
- package/dist/providers/github-provider-backup.js +1179 -0
- package/dist/providers/github-provider-backup.js.map +1 -0
- package/dist/providers/github-provider-complete.d.ts +1 -0
- package/dist/providers/github-provider-complete.d.ts.map +1 -0
- package/dist/providers/github-provider-complete.js +2 -0
- package/dist/providers/github-provider-complete.js.map +1 -0
- package/dist/providers/github-provider.d.ts +65 -61
- package/dist/providers/github-provider.d.ts.map +1 -1
- package/dist/providers/github-provider.js +154 -1338
- package/dist/providers/github-provider.js.map +1 -1
- package/package.json +2 -2
- package/dist/tools/git-repos.d.ts +0 -19
- package/dist/tools/git-repos.d.ts.map +0 -1
- package/dist/tools/git-repos.js +0 -19
- package/dist/tools/git-repos.js.map +0 -1
|
@@ -0,0 +1,1179 @@
|
|
|
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
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.GitHubProvider = void 0;
|
|
37
|
+
const base_provider_js_1 = require("./base-provider.js");
|
|
38
|
+
/**
|
|
39
|
+
* Provider específico para GitHub
|
|
40
|
+
* Implementa todas as operações VCS usando a API REST do GitHub
|
|
41
|
+
*/
|
|
42
|
+
class GitHubProvider extends base_provider_js_1.BaseVcsProvider {
|
|
43
|
+
constructor(config) {
|
|
44
|
+
super(config);
|
|
45
|
+
}
|
|
46
|
+
getBaseUrl(config) {
|
|
47
|
+
return 'https://api.github.com';
|
|
48
|
+
}
|
|
49
|
+
getHeaders(config) {
|
|
50
|
+
return {
|
|
51
|
+
'Authorization': `Bearer ${config.token}`,
|
|
52
|
+
'Content-Type': 'application/json',
|
|
53
|
+
'Accept': 'application/vnd.github.v3+json',
|
|
54
|
+
'User-Agent': 'Gitea-MCP-MultiProvider/2.3.0'
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// Usando normalizeError padrão do BaseVcsProvider
|
|
58
|
+
normalizeRepository(data) {
|
|
59
|
+
return {
|
|
60
|
+
id: data.id,
|
|
61
|
+
name: data.name,
|
|
62
|
+
full_name: data.full_name,
|
|
63
|
+
description: data.description,
|
|
64
|
+
private: data.private,
|
|
65
|
+
html_url: data.html_url,
|
|
66
|
+
clone_url: data.clone_url,
|
|
67
|
+
default_branch: data.default_branch,
|
|
68
|
+
created_at: data.created_at,
|
|
69
|
+
updated_at: data.updated_at,
|
|
70
|
+
owner: {
|
|
71
|
+
login: data.owner?.login,
|
|
72
|
+
type: data.owner?.type || 'User'
|
|
73
|
+
},
|
|
74
|
+
raw: data
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
normalizeBranch(data) {
|
|
78
|
+
return {
|
|
79
|
+
name: data.name,
|
|
80
|
+
commit: {
|
|
81
|
+
sha: data.commit?.sha,
|
|
82
|
+
url: data.commit?.url
|
|
83
|
+
},
|
|
84
|
+
protected: data.protected,
|
|
85
|
+
raw: data
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
normalizeFile(data) {
|
|
89
|
+
return {
|
|
90
|
+
name: data.name,
|
|
91
|
+
path: data.path,
|
|
92
|
+
sha: data.sha,
|
|
93
|
+
size: data.size,
|
|
94
|
+
url: data.url,
|
|
95
|
+
html_url: data.html_url,
|
|
96
|
+
git_url: data.git_url,
|
|
97
|
+
download_url: data.download_url,
|
|
98
|
+
type: data.type,
|
|
99
|
+
content: data.content,
|
|
100
|
+
encoding: data.encoding,
|
|
101
|
+
raw: data
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
normalizeCommit(data) {
|
|
105
|
+
return {
|
|
106
|
+
sha: data.sha,
|
|
107
|
+
message: data.commit?.message || data.message,
|
|
108
|
+
author: {
|
|
109
|
+
name: data.commit?.author?.name || data.author?.login,
|
|
110
|
+
email: data.commit?.author?.email,
|
|
111
|
+
date: data.commit?.author?.date
|
|
112
|
+
},
|
|
113
|
+
committer: {
|
|
114
|
+
name: data.commit?.committer?.name || data.committer?.login,
|
|
115
|
+
email: data.commit?.committer?.email,
|
|
116
|
+
date: data.commit?.committer?.date
|
|
117
|
+
},
|
|
118
|
+
commit: {
|
|
119
|
+
author: {
|
|
120
|
+
name: data.commit?.author?.name || '',
|
|
121
|
+
email: data.commit?.author?.email || '',
|
|
122
|
+
date: data.commit?.author?.date || ''
|
|
123
|
+
},
|
|
124
|
+
committer: {
|
|
125
|
+
name: data.commit?.committer?.name || '',
|
|
126
|
+
email: data.commit?.committer?.email || '',
|
|
127
|
+
date: data.commit?.committer?.date || ''
|
|
128
|
+
},
|
|
129
|
+
message: data.commit?.message || data.message || ''
|
|
130
|
+
},
|
|
131
|
+
url: data.url,
|
|
132
|
+
html_url: data.html_url,
|
|
133
|
+
raw: data
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
normalizeIssue(data) {
|
|
137
|
+
return {
|
|
138
|
+
id: data.id,
|
|
139
|
+
number: data.number,
|
|
140
|
+
title: data.title,
|
|
141
|
+
body: data.body,
|
|
142
|
+
state: data.state,
|
|
143
|
+
user: {
|
|
144
|
+
login: data.user?.login,
|
|
145
|
+
id: data.user?.id
|
|
146
|
+
},
|
|
147
|
+
assignees: data.assignees?.map((a) => ({
|
|
148
|
+
login: a.login,
|
|
149
|
+
id: a.id
|
|
150
|
+
})),
|
|
151
|
+
labels: data.labels?.map((l) => ({
|
|
152
|
+
name: l.name,
|
|
153
|
+
color: l.color
|
|
154
|
+
})),
|
|
155
|
+
created_at: data.created_at,
|
|
156
|
+
updated_at: data.updated_at,
|
|
157
|
+
closed_at: data.closed_at,
|
|
158
|
+
raw: data
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
normalizePullRequest(data) {
|
|
162
|
+
return {
|
|
163
|
+
id: data.id,
|
|
164
|
+
number: data.number,
|
|
165
|
+
title: data.title,
|
|
166
|
+
body: data.body,
|
|
167
|
+
state: data.state,
|
|
168
|
+
user: {
|
|
169
|
+
login: data.user?.login,
|
|
170
|
+
id: data.user?.id
|
|
171
|
+
},
|
|
172
|
+
head: {
|
|
173
|
+
ref: data.head?.ref,
|
|
174
|
+
sha: data.head?.sha,
|
|
175
|
+
repo: {
|
|
176
|
+
name: data.head?.repo?.name,
|
|
177
|
+
full_name: data.head?.repo?.full_name
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
base: {
|
|
181
|
+
ref: data.base?.ref,
|
|
182
|
+
sha: data.base?.sha,
|
|
183
|
+
repo: {
|
|
184
|
+
name: data.base?.repo?.name,
|
|
185
|
+
full_name: data.base?.repo?.full_name
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
created_at: data.created_at,
|
|
189
|
+
updated_at: data.updated_at,
|
|
190
|
+
closed_at: data.closed_at,
|
|
191
|
+
merged_at: data.merged_at,
|
|
192
|
+
mergeable: data.mergeable,
|
|
193
|
+
raw: data
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
normalizeRelease(data) {
|
|
197
|
+
return {
|
|
198
|
+
id: data.id,
|
|
199
|
+
tag_name: data.tag_name,
|
|
200
|
+
name: data.name,
|
|
201
|
+
body: data.body,
|
|
202
|
+
draft: data.draft,
|
|
203
|
+
prerelease: data.prerelease,
|
|
204
|
+
created_at: data.created_at,
|
|
205
|
+
published_at: data.published_at,
|
|
206
|
+
html_url: data.html_url,
|
|
207
|
+
tarball_url: data.tarball_url,
|
|
208
|
+
zipball_url: data.zipball_url,
|
|
209
|
+
raw: data
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
normalizeTag(data) {
|
|
213
|
+
return {
|
|
214
|
+
name: data.name,
|
|
215
|
+
commit: {
|
|
216
|
+
sha: data.commit?.sha,
|
|
217
|
+
url: data.commit?.url
|
|
218
|
+
},
|
|
219
|
+
zipball_url: data.zipball_url,
|
|
220
|
+
tarball_url: data.tarball_url,
|
|
221
|
+
raw: data
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
normalizeUser(data) {
|
|
225
|
+
return {
|
|
226
|
+
id: data.id,
|
|
227
|
+
login: data.login,
|
|
228
|
+
name: data.name,
|
|
229
|
+
email: data.email,
|
|
230
|
+
avatar_url: data.avatar_url,
|
|
231
|
+
html_url: data.html_url,
|
|
232
|
+
type: data.type,
|
|
233
|
+
raw: data
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
normalizeOrganization(data) {
|
|
237
|
+
return {
|
|
238
|
+
id: data.id,
|
|
239
|
+
login: data.login,
|
|
240
|
+
name: data.name,
|
|
241
|
+
description: data.description,
|
|
242
|
+
avatar_url: data.avatar_url,
|
|
243
|
+
html_url: data.html_url,
|
|
244
|
+
location: data.location,
|
|
245
|
+
website: data.blog,
|
|
246
|
+
public_repos: data.public_repos,
|
|
247
|
+
public_members: data.public_members,
|
|
248
|
+
raw: data
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
normalizeWebhook(data) {
|
|
252
|
+
return {
|
|
253
|
+
id: data.id,
|
|
254
|
+
type: data.type,
|
|
255
|
+
name: data.name,
|
|
256
|
+
active: data.active,
|
|
257
|
+
url: data.config?.url || data.url || '',
|
|
258
|
+
events: data.events,
|
|
259
|
+
config: {
|
|
260
|
+
url: data.config?.url,
|
|
261
|
+
content_type: data.config?.content_type,
|
|
262
|
+
secret: data.config?.secret
|
|
263
|
+
},
|
|
264
|
+
created_at: data.created_at,
|
|
265
|
+
updated_at: data.updated_at,
|
|
266
|
+
raw: data
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
// Implementações específicas do GitHub
|
|
270
|
+
async listRepositories(username, page = 1, limit = 30) {
|
|
271
|
+
const url = username ? `/users/${username}/repos` : '/user/repos';
|
|
272
|
+
const data = await this.get(url, { page, per_page: limit, sort: 'updated' });
|
|
273
|
+
return data.map(repo => this.normalizeRepository(repo));
|
|
274
|
+
}
|
|
275
|
+
async getRepository(owner, repo) {
|
|
276
|
+
const data = await this.get(`/repos/${owner}/${repo}`);
|
|
277
|
+
return this.normalizeRepository(data);
|
|
278
|
+
}
|
|
279
|
+
async createRepository(name, description, privateRepo = false) {
|
|
280
|
+
const data = await this.post('/user/repos', {
|
|
281
|
+
name,
|
|
282
|
+
description,
|
|
283
|
+
private: privateRepo,
|
|
284
|
+
auto_init: true
|
|
285
|
+
});
|
|
286
|
+
return this.normalizeRepository(data);
|
|
287
|
+
}
|
|
288
|
+
async updateRepository(owner, repo, updates) {
|
|
289
|
+
const data = await this.patch(`/repos/${owner}/${repo}`, updates);
|
|
290
|
+
return this.normalizeRepository(data);
|
|
291
|
+
}
|
|
292
|
+
async deleteRepository(owner, repo) {
|
|
293
|
+
await this.delete(`/repos/${owner}/${repo}`);
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
async forkRepository(owner, repo, organization) {
|
|
297
|
+
const payload = organization ? { organization } : {};
|
|
298
|
+
const data = await this.post(`/repos/${owner}/${repo}/forks`, payload);
|
|
299
|
+
return this.normalizeRepository(data);
|
|
300
|
+
}
|
|
301
|
+
async searchRepositories(query, page = 1, limit = 30) {
|
|
302
|
+
const data = await this.get('/search/repositories', {
|
|
303
|
+
q: query,
|
|
304
|
+
page,
|
|
305
|
+
per_page: limit,
|
|
306
|
+
sort: 'stars',
|
|
307
|
+
order: 'desc'
|
|
308
|
+
});
|
|
309
|
+
return data.items.map((repo) => this.normalizeRepository(repo));
|
|
310
|
+
}
|
|
311
|
+
async listBranches(owner, repo, page = 1, limit = 30) {
|
|
312
|
+
const data = await this.get(`/repos/${owner}/${repo}/branches`, { page, per_page: limit });
|
|
313
|
+
return data.map(branch => this.normalizeBranch(branch));
|
|
314
|
+
}
|
|
315
|
+
async getBranch(owner, repo, branch) {
|
|
316
|
+
const data = await this.get(`/repos/${owner}/${repo}/branches/${branch}`);
|
|
317
|
+
return this.normalizeBranch(data);
|
|
318
|
+
}
|
|
319
|
+
async createBranch(owner, repo, branchName, fromBranch) {
|
|
320
|
+
try {
|
|
321
|
+
// Get the source branch to get the commit SHA
|
|
322
|
+
const sourceBranch = await this.getBranch(owner, repo, fromBranch);
|
|
323
|
+
// Create the new branch reference
|
|
324
|
+
const data = await this.post(`/repos/${owner}/${repo}/git/refs`, {
|
|
325
|
+
ref: `refs/heads/${branchName}`,
|
|
326
|
+
sha: sourceBranch.commit.sha
|
|
327
|
+
});
|
|
328
|
+
return this.normalizeBranch({
|
|
329
|
+
name: branchName,
|
|
330
|
+
commit: {
|
|
331
|
+
sha: sourceBranch.commit.sha,
|
|
332
|
+
url: data.object?.url || `https://api.github.com/repos/${owner}/${repo}/git/commits/${sourceBranch.commit.sha}`
|
|
333
|
+
},
|
|
334
|
+
protected: false
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
throw new Error(`Failed to create branch '${branchName}': ${error instanceof Error ? error.message : String(error)}`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
async deleteBranch(owner, repo, branch) {
|
|
342
|
+
try {
|
|
343
|
+
await this.delete(`/repos/${owner}/${repo}/git/refs/heads/${branch}`);
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
throw new Error(`Failed to delete branch '${branch}': ${error instanceof Error ? error.message : String(error)}`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
async getFile(owner, repo, path, ref) {
|
|
351
|
+
const params = ref ? { ref } : {};
|
|
352
|
+
const data = await this.get(`/repos/${owner}/${repo}/contents/${path}`, params);
|
|
353
|
+
return this.normalizeFile(data);
|
|
354
|
+
}
|
|
355
|
+
async createFile(owner, repo, path, content, message, branch) {
|
|
356
|
+
const payload = {
|
|
357
|
+
message,
|
|
358
|
+
content: Buffer.from(content).toString('base64')
|
|
359
|
+
};
|
|
360
|
+
if (branch) {
|
|
361
|
+
payload.branch = branch;
|
|
362
|
+
}
|
|
363
|
+
const data = await this.put(`/repos/${owner}/${repo}/contents/${path}`, payload);
|
|
364
|
+
return this.normalizeFile(data.content);
|
|
365
|
+
}
|
|
366
|
+
async updateFile(owner, repo, path, content, message, sha, branch) {
|
|
367
|
+
const payload = {
|
|
368
|
+
message,
|
|
369
|
+
content: Buffer.from(content).toString('base64'),
|
|
370
|
+
sha
|
|
371
|
+
};
|
|
372
|
+
if (branch) {
|
|
373
|
+
payload.branch = branch;
|
|
374
|
+
}
|
|
375
|
+
const data = await this.put(`/repos/${owner}/${repo}/contents/${path}`, payload);
|
|
376
|
+
return this.normalizeFile(data.content);
|
|
377
|
+
}
|
|
378
|
+
async deleteFile(owner, repo, path, message, sha, branch) {
|
|
379
|
+
const payload = {
|
|
380
|
+
message,
|
|
381
|
+
sha
|
|
382
|
+
};
|
|
383
|
+
if (branch) {
|
|
384
|
+
payload.branch = branch;
|
|
385
|
+
}
|
|
386
|
+
await this.delete(`/repos/${owner}/${repo}/contents/${path}`, { data: payload });
|
|
387
|
+
return true;
|
|
388
|
+
}
|
|
389
|
+
async listFiles(owner, repo, path, ref) {
|
|
390
|
+
const params = ref ? { ref } : {};
|
|
391
|
+
const data = await this.get(`/repos/${owner}/${repo}/contents/${path}`, params);
|
|
392
|
+
return data.map(file => this.normalizeFile(file));
|
|
393
|
+
}
|
|
394
|
+
async uploadProject(owner, repo, projectPath, message, branch) {
|
|
395
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs/promises')));
|
|
396
|
+
const path = await Promise.resolve().then(() => __importStar(require('path')));
|
|
397
|
+
let uploaded = 0;
|
|
398
|
+
const errors = [];
|
|
399
|
+
try {
|
|
400
|
+
// Função recursiva para processar diretórios
|
|
401
|
+
const processDirectory = async (dirPath, relativePath = '') => {
|
|
402
|
+
const items = await fs.readdir(dirPath, { withFileTypes: true });
|
|
403
|
+
for (const item of items) {
|
|
404
|
+
const fullPath = path.join(dirPath, item.name);
|
|
405
|
+
const itemRelativePath = relativePath ? path.join(relativePath, item.name) : item.name;
|
|
406
|
+
// Pular diretórios que não devem ser enviados
|
|
407
|
+
if (item.isDirectory()) {
|
|
408
|
+
if (item.name === 'node_modules' || item.name === '.git' || item.name === 'dist') {
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
await processDirectory(fullPath, itemRelativePath);
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
// Pular arquivos que não devem ser enviados
|
|
415
|
+
if (item.name.endsWith('.log') || item.name.endsWith('.tmp') || item.name.startsWith('.')) {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
try {
|
|
419
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
420
|
+
await this.createFile(owner, repo, itemRelativePath, content, message, branch);
|
|
421
|
+
uploaded++;
|
|
422
|
+
}
|
|
423
|
+
catch (error) {
|
|
424
|
+
errors.push(`Erro ao enviar ${itemRelativePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
await processDirectory(projectPath);
|
|
430
|
+
return { uploaded, errors };
|
|
431
|
+
}
|
|
432
|
+
catch (error) {
|
|
433
|
+
throw new Error(`Falha ao fazer upload do projeto: ${error instanceof Error ? error.message : String(error)}`);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
async listCommits(owner, repo, branch, page = 1, limit = 30) {
|
|
437
|
+
const params = { page, per_page: limit };
|
|
438
|
+
if (branch)
|
|
439
|
+
params.sha = branch;
|
|
440
|
+
const data = await this.get(`/repos/${owner}/${repo}/commits`, params);
|
|
441
|
+
return data.map(commit => this.normalizeCommit(commit));
|
|
442
|
+
}
|
|
443
|
+
async getCommit(owner, repo, sha) {
|
|
444
|
+
const data = await this.get(`/repos/${owner}/${repo}/git/commits/${sha}`);
|
|
445
|
+
return this.normalizeCommit(data);
|
|
446
|
+
}
|
|
447
|
+
async listIssues(owner, repo, state = 'open', page = 1, limit = 30) {
|
|
448
|
+
const data = await this.get(`/repos/${owner}/${repo}/issues`, {
|
|
449
|
+
state,
|
|
450
|
+
page,
|
|
451
|
+
per_page: limit,
|
|
452
|
+
filter: 'all'
|
|
453
|
+
});
|
|
454
|
+
return data.map(issue => this.normalizeIssue(issue));
|
|
455
|
+
}
|
|
456
|
+
async getIssue(owner, repo, issueNumber) {
|
|
457
|
+
const data = await this.get(`/repos/${owner}/${repo}/issues/${issueNumber}`);
|
|
458
|
+
return this.normalizeIssue(data);
|
|
459
|
+
}
|
|
460
|
+
async createIssue(owner, repo, title, body, assignees, labels) {
|
|
461
|
+
const payload = { title };
|
|
462
|
+
if (body)
|
|
463
|
+
payload.body = body;
|
|
464
|
+
if (assignees)
|
|
465
|
+
payload.assignees = assignees;
|
|
466
|
+
if (labels)
|
|
467
|
+
payload.labels = labels;
|
|
468
|
+
const data = await this.post(`/repos/${owner}/${repo}/issues`, payload);
|
|
469
|
+
return this.normalizeIssue(data);
|
|
470
|
+
}
|
|
471
|
+
async updateIssue(owner, repo, issueNumber, updates) {
|
|
472
|
+
const data = await this.patch(`/repos/${owner}/${repo}/issues/${issueNumber}`, updates);
|
|
473
|
+
return this.normalizeIssue(data);
|
|
474
|
+
}
|
|
475
|
+
async closeIssue(owner, repo, issueNumber) {
|
|
476
|
+
return this.updateIssue(owner, repo, issueNumber, { state: 'closed' });
|
|
477
|
+
}
|
|
478
|
+
async listPullRequests(owner, repo, state = 'open', page = 1, limit = 30) {
|
|
479
|
+
const data = await this.get(`/repos/${owner}/${repo}/pulls`, {
|
|
480
|
+
state,
|
|
481
|
+
page,
|
|
482
|
+
per_page: limit,
|
|
483
|
+
sort: 'updated',
|
|
484
|
+
direction: 'desc'
|
|
485
|
+
});
|
|
486
|
+
return data.map(pr => this.normalizePullRequest(pr));
|
|
487
|
+
}
|
|
488
|
+
async getPullRequest(owner, repo, pullNumber) {
|
|
489
|
+
const data = await this.get(`/repos/${owner}/${repo}/pulls/${pullNumber}`);
|
|
490
|
+
return this.normalizePullRequest(data);
|
|
491
|
+
}
|
|
492
|
+
async createPullRequest(owner, repo, title, body, head, base) {
|
|
493
|
+
const data = await this.post(`/repos/${owner}/${repo}/pulls`, {
|
|
494
|
+
title,
|
|
495
|
+
body,
|
|
496
|
+
head,
|
|
497
|
+
base
|
|
498
|
+
});
|
|
499
|
+
return this.normalizePullRequest(data);
|
|
500
|
+
}
|
|
501
|
+
async updatePullRequest(owner, repo, pullNumber, updates) {
|
|
502
|
+
const data = await this.patch(`/repos/${owner}/${repo}/pulls/${pullNumber}`, updates);
|
|
503
|
+
return this.normalizePullRequest(data);
|
|
504
|
+
}
|
|
505
|
+
async mergePullRequest(owner, repo, pullNumber, mergeMethod = 'merge') {
|
|
506
|
+
await this.put(`/repos/${owner}/${repo}/pulls/${pullNumber}/merge`, {
|
|
507
|
+
merge_method: mergeMethod
|
|
508
|
+
});
|
|
509
|
+
return true;
|
|
510
|
+
}
|
|
511
|
+
async listReleases(owner, repo, page = 1, limit = 30) {
|
|
512
|
+
const data = await this.get(`/repos/${owner}/${repo}/releases`, { page, per_page: limit });
|
|
513
|
+
return data.map(release => this.normalizeRelease(release));
|
|
514
|
+
}
|
|
515
|
+
async getRelease(owner, repo, releaseId) {
|
|
516
|
+
const data = await this.get(`/repos/${owner}/${repo}/releases/${releaseId}`);
|
|
517
|
+
return this.normalizeRelease(data);
|
|
518
|
+
}
|
|
519
|
+
async createRelease(owner, repo, releaseData) {
|
|
520
|
+
const data = await this.post(`/repos/${owner}/${repo}/releases`, {
|
|
521
|
+
tag_name: releaseData.tag_name,
|
|
522
|
+
name: releaseData.name || releaseData.tag_name,
|
|
523
|
+
body: releaseData.body || '',
|
|
524
|
+
draft: releaseData.draft || false,
|
|
525
|
+
prerelease: releaseData.prerelease || false,
|
|
526
|
+
target_commitish: releaseData.target_commitish || 'main'
|
|
527
|
+
});
|
|
528
|
+
return this.normalizeRelease(data);
|
|
529
|
+
}
|
|
530
|
+
async updateRelease(owner, repo, releaseId, updates) {
|
|
531
|
+
const data = await this.patch(`/repos/${owner}/${repo}/releases/${releaseId}`, updates);
|
|
532
|
+
return this.normalizeRelease(data);
|
|
533
|
+
}
|
|
534
|
+
async deleteRelease(owner, repo, releaseId) {
|
|
535
|
+
await this.delete(`/repos/${owner}/${repo}/releases/${releaseId}`);
|
|
536
|
+
return true;
|
|
537
|
+
}
|
|
538
|
+
async listTags(owner, repo, page = 1, limit = 30) {
|
|
539
|
+
const data = await this.get(`/repos/${owner}/${repo}/tags`, { page, per_page: limit });
|
|
540
|
+
return data.map(tag => this.normalizeTag(tag));
|
|
541
|
+
}
|
|
542
|
+
async getTag(owner, repo, tag) {
|
|
543
|
+
const data = await this.get(`/repos/${owner}/${repo}/git/refs/tags/${tag}`);
|
|
544
|
+
return this.normalizeTag(data);
|
|
545
|
+
}
|
|
546
|
+
async createTag(owner, repo, tagData) {
|
|
547
|
+
// First create the tag object
|
|
548
|
+
const tagObject = await this.post(`/repos/${owner}/${repo}/git/tags`, {
|
|
549
|
+
tag: tagData.tag_name,
|
|
550
|
+
message: tagData.message || `Tag ${tagData.tag_name}`,
|
|
551
|
+
object: tagData.target,
|
|
552
|
+
type: 'commit'
|
|
553
|
+
});
|
|
554
|
+
// Then create the tag reference
|
|
555
|
+
const tagRef = await this.post(`/repos/${owner}/${repo}/git/refs`, {
|
|
556
|
+
ref: `refs/tags/${tagData.tag_name}`,
|
|
557
|
+
sha: tagObject.sha
|
|
558
|
+
});
|
|
559
|
+
return this.normalizeTag({
|
|
560
|
+
name: tagData.tag_name,
|
|
561
|
+
commit: {
|
|
562
|
+
sha: tagObject.sha,
|
|
563
|
+
url: tagObject.url
|
|
564
|
+
},
|
|
565
|
+
zipball_url: `https://api.github.com/repos/${owner}/${repo}/zipball/${tagData.tag_name}`,
|
|
566
|
+
tarball_url: `https://api.github.com/repos/${owner}/${repo}/tarball/${tagData.tag_name}`,
|
|
567
|
+
...tagObject
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
async deleteTag(owner, repo, tag) {
|
|
571
|
+
await this.delete(`/repos/${owner}/${repo}/git/refs/tags/${tag}`);
|
|
572
|
+
return true;
|
|
573
|
+
}
|
|
574
|
+
async getCurrentUser() {
|
|
575
|
+
const data = await this.get('/user');
|
|
576
|
+
return this.normalizeUser(data);
|
|
577
|
+
}
|
|
578
|
+
async getUser(username) {
|
|
579
|
+
const data = await this.get(`/users/${username}`);
|
|
580
|
+
return this.normalizeUser(data);
|
|
581
|
+
}
|
|
582
|
+
async listUsers(page = 1, limit = 30) {
|
|
583
|
+
const data = await this.get('/users', { since: (page - 1) * limit, per_page: limit });
|
|
584
|
+
return data.map(user => this.normalizeUser(user));
|
|
585
|
+
}
|
|
586
|
+
async searchUsers(query, page = 1, limit = 30) {
|
|
587
|
+
const data = await this.get('/search/users', {
|
|
588
|
+
q: query,
|
|
589
|
+
page,
|
|
590
|
+
per_page: limit,
|
|
591
|
+
sort: 'followers',
|
|
592
|
+
order: 'desc'
|
|
593
|
+
});
|
|
594
|
+
return data.items.map((user) => this.normalizeUser(user));
|
|
595
|
+
}
|
|
596
|
+
async getUserOrganizations(username, page = 1, limit = 30) {
|
|
597
|
+
const data = await this.get(`/users/${username}/orgs`, { page, per_page: limit });
|
|
598
|
+
return data.map((org) => this.normalizeOrganization(org));
|
|
599
|
+
}
|
|
600
|
+
async getUserRepositories(username, page = 1, limit = 30) {
|
|
601
|
+
const data = await this.get(`/users/${username}/repos`, {
|
|
602
|
+
page,
|
|
603
|
+
per_page: limit,
|
|
604
|
+
sort: 'updated',
|
|
605
|
+
direction: 'desc'
|
|
606
|
+
});
|
|
607
|
+
return data.map((repo) => this.normalizeRepository(repo));
|
|
608
|
+
}
|
|
609
|
+
async listWebhooks(owner, repo, page = 1, limit = 30) {
|
|
610
|
+
const data = await this.get(`/repos/${owner}/${repo}/hooks`, { page, per_page: limit });
|
|
611
|
+
return data.map(webhook => this.normalizeWebhook(webhook));
|
|
612
|
+
}
|
|
613
|
+
async getWebhook(owner, repo, webhookId) {
|
|
614
|
+
const data = await this.get(`/repos/${owner}/${repo}/hooks/${webhookId}`);
|
|
615
|
+
return this.normalizeWebhook(data);
|
|
616
|
+
}
|
|
617
|
+
async createWebhook(owner, repo, url, events, secret) {
|
|
618
|
+
const data = await this.post(`/repos/${owner}/${repo}/hooks`, {
|
|
619
|
+
name: 'web',
|
|
620
|
+
active: true,
|
|
621
|
+
events,
|
|
622
|
+
config: {
|
|
623
|
+
url,
|
|
624
|
+
content_type: 'json',
|
|
625
|
+
secret
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
return this.normalizeWebhook(data);
|
|
629
|
+
}
|
|
630
|
+
async updateWebhook(owner, repo, webhookId, updates) {
|
|
631
|
+
const data = await this.patch(`/repos/${owner}/${repo}/hooks/${webhookId}`, updates);
|
|
632
|
+
return this.normalizeWebhook(data);
|
|
633
|
+
}
|
|
634
|
+
async deleteWebhook(owner, repo, webhookId) {
|
|
635
|
+
await this.delete(`/repos/${owner}/${repo}/hooks/${webhookId}`);
|
|
636
|
+
return true;
|
|
637
|
+
}
|
|
638
|
+
async createCommit(owner, repo, message, branch, changes) {
|
|
639
|
+
// Para criar um commit no GitHub, precisamos:
|
|
640
|
+
// 1. Obter o último commit da branch
|
|
641
|
+
// 2. Criar uma nova árvore com as mudanças
|
|
642
|
+
// 3. Criar o commit
|
|
643
|
+
// 4. Atualizar a referência da branch
|
|
644
|
+
try {
|
|
645
|
+
// Obter informações da branch
|
|
646
|
+
const branchData = await this.getBranch(owner, repo, branch);
|
|
647
|
+
// Para simplificar, vamos usar o endpoint de criação de commit direto
|
|
648
|
+
const commitData = {
|
|
649
|
+
message,
|
|
650
|
+
tree: changes?.tree_sha || branchData.commit.sha,
|
|
651
|
+
parents: [branchData.commit.sha]
|
|
652
|
+
};
|
|
653
|
+
const data = await this.post(`/repos/${owner}/${repo}/git/commits`, commitData);
|
|
654
|
+
// Atualizar a referência da branch
|
|
655
|
+
await this.post(`/repos/${owner}/${repo}/git/refs/heads/${branch}`, {
|
|
656
|
+
sha: data.sha,
|
|
657
|
+
force: false
|
|
658
|
+
});
|
|
659
|
+
return this.normalizeCommit(data);
|
|
660
|
+
}
|
|
661
|
+
catch (error) {
|
|
662
|
+
console.error('Erro ao criar commit:', error);
|
|
663
|
+
throw new Error(`Falha ao criar commit: ${error instanceof Error ? error.message : String(error)}`);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
// Implementações básicas para funcionalidades suportadas pelo GitHub
|
|
667
|
+
async listWorkflows(params) {
|
|
668
|
+
const { owner, repo } = params;
|
|
669
|
+
const data = await this.get(`/repos/${owner}/${repo}/actions/workflows`);
|
|
670
|
+
return data;
|
|
671
|
+
}
|
|
672
|
+
async listWorkflowRuns(params) {
|
|
673
|
+
const { owner, repo } = params;
|
|
674
|
+
const data = await this.get(`/repos/${owner}/${repo}/actions/runs`);
|
|
675
|
+
return data;
|
|
676
|
+
}
|
|
677
|
+
async listDeployments(params) {
|
|
678
|
+
const { owner, repo } = params;
|
|
679
|
+
const data = await this.get(`/repos/${owner}/${repo}/deployments`);
|
|
680
|
+
return data;
|
|
681
|
+
}
|
|
682
|
+
async runSecurityScan(params) {
|
|
683
|
+
const { owner, repo } = params;
|
|
684
|
+
// GitHub Security tab - basic implementation
|
|
685
|
+
const data = await this.get(`/repos/${owner}/${repo}`);
|
|
686
|
+
return {
|
|
687
|
+
security: {
|
|
688
|
+
enabled: data.security_and_analysis?.advanced_security?.status === 'enabled',
|
|
689
|
+
secret_scanning: data.security_and_analysis?.secret_scanning?.status === 'enabled',
|
|
690
|
+
dependabot: data.security_and_analysis?.dependabot_security_updates?.status === 'enabled'
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
async getTrafficStats(params) {
|
|
695
|
+
const { owner, repo, metricType } = params;
|
|
696
|
+
let endpoint = '';
|
|
697
|
+
switch (metricType) {
|
|
698
|
+
case 'views':
|
|
699
|
+
endpoint = `/repos/${owner}/${repo}/traffic/views`;
|
|
700
|
+
break;
|
|
701
|
+
case 'clones':
|
|
702
|
+
endpoint = `/repos/${owner}/${repo}/traffic/clones`;
|
|
703
|
+
break;
|
|
704
|
+
case 'popular':
|
|
705
|
+
endpoint = `/repos/${owner}/${repo}/traffic/popular/paths`;
|
|
706
|
+
break;
|
|
707
|
+
case 'referrers':
|
|
708
|
+
endpoint = `/repos/${owner}/${repo}/traffic/popular/referrers`;
|
|
709
|
+
break;
|
|
710
|
+
default:
|
|
711
|
+
endpoint = `/repos/${owner}/${repo}/traffic/views`;
|
|
712
|
+
}
|
|
713
|
+
return await this.get(endpoint);
|
|
714
|
+
error: 'Traffic stats not available',
|
|
715
|
+
message;
|
|
716
|
+
'Repository traffic statistics require special permissions or may not be available for this repository',
|
|
717
|
+
metricType,
|
|
718
|
+
available;
|
|
719
|
+
false;
|
|
720
|
+
}
|
|
721
|
+
;
|
|
722
|
+
}
|
|
723
|
+
exports.GitHubProvider = GitHubProvider;
|
|
724
|
+
async;
|
|
725
|
+
cloneRepository(params, any);
|
|
726
|
+
Promise < any > {
|
|
727
|
+
throw: new Error('Funcionalidade não suportada por este provider: Provider não implementa cloneRepository')
|
|
728
|
+
};
|
|
729
|
+
async;
|
|
730
|
+
archiveRepository(params, any);
|
|
731
|
+
Promise < any > {
|
|
732
|
+
throw: new Error('Funcionalidade não suportada por este provider: Provider não implementa archiveRepository')
|
|
733
|
+
};
|
|
734
|
+
async;
|
|
735
|
+
transferRepository(params, any);
|
|
736
|
+
Promise < any > {
|
|
737
|
+
const: { owner, repo, newOwner } = params,
|
|
738
|
+
const: data = await this.post(`/repos/${owner}/${repo}/transfer`, { new_owner: newOwner }),
|
|
739
|
+
return: data.owner.login === newOwner
|
|
740
|
+
};
|
|
741
|
+
async;
|
|
742
|
+
createFromTemplate(params, any);
|
|
743
|
+
Promise < any > {
|
|
744
|
+
const: { templateOwner, templateRepo, name, ...options } = params,
|
|
745
|
+
const: data = await this.post(`/repos/${templateOwner}/${templateRepo}/generate`, {
|
|
746
|
+
name,
|
|
747
|
+
...options
|
|
748
|
+
}),
|
|
749
|
+
return: this.normalizeRepository(data)
|
|
750
|
+
};
|
|
751
|
+
async;
|
|
752
|
+
mirrorRepository(params, any);
|
|
753
|
+
Promise < any > {
|
|
754
|
+
throw: new Error('Funcionalidade não suportada por este provider: Provider não implementa mirrorRepository')
|
|
755
|
+
};
|
|
756
|
+
// Implementações para analytics e outras funcionalidades
|
|
757
|
+
async;
|
|
758
|
+
analyzeContributors(params, any);
|
|
759
|
+
Promise < any > {
|
|
760
|
+
const: { owner, repo } = params,
|
|
761
|
+
try: {
|
|
762
|
+
const: contributors = await this.get(`/repos/${owner}/${repo}/contributors`),
|
|
763
|
+
return: {
|
|
764
|
+
totalContributors: contributors.length,
|
|
765
|
+
contributors: contributors.map(c => ({
|
|
766
|
+
login: c.login,
|
|
767
|
+
contributions: c.contributions,
|
|
768
|
+
type: c.type
|
|
769
|
+
})),
|
|
770
|
+
period: 'all_time'
|
|
771
|
+
}
|
|
772
|
+
}, catch(error) {
|
|
773
|
+
return {
|
|
774
|
+
error: 'Contributors analysis failed',
|
|
775
|
+
message: 'Could not retrieve contributor information',
|
|
776
|
+
available: false
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
};
|
|
780
|
+
async;
|
|
781
|
+
getActivityStats(params, any);
|
|
782
|
+
Promise < any > {
|
|
783
|
+
const: { owner, repo } = params,
|
|
784
|
+
try: {
|
|
785
|
+
const: commits = await this.get(`/repos/${owner}/${repo}/commits?per_page=100`),
|
|
786
|
+
const: issues = await this.get(`/repos/${owner}/${repo}/issues?state=all&per_page=100`),
|
|
787
|
+
return: {
|
|
788
|
+
recentCommits: commits.length,
|
|
789
|
+
totalIssues: issues.length,
|
|
790
|
+
openIssues: issues.filter(i => i.state === 'open').length,
|
|
791
|
+
closedIssues: issues.filter(i => i.state === 'closed').length,
|
|
792
|
+
activity: commits.length > 10 ? 'high' : commits.length > 5 ? 'medium' : 'low'
|
|
793
|
+
}
|
|
794
|
+
}, catch(error) {
|
|
795
|
+
return {
|
|
796
|
+
error: 'Activity stats failed',
|
|
797
|
+
message: 'Could not retrieve activity information',
|
|
798
|
+
available: false
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
async;
|
|
803
|
+
getRepositoryInsights(params, any);
|
|
804
|
+
Promise < any > {
|
|
805
|
+
const: { owner, repo } = params,
|
|
806
|
+
try: {
|
|
807
|
+
const: repoData = await this.get(`/repos/${owner}/${repo}`),
|
|
808
|
+
return: {
|
|
809
|
+
insights: {
|
|
810
|
+
stars: repoData.stargazers_count,
|
|
811
|
+
forks: repoData.forks_count,
|
|
812
|
+
watchers: repoData.watchers_count,
|
|
813
|
+
language: repoData.language,
|
|
814
|
+
size: repoData.size,
|
|
815
|
+
created: repoData.created_at,
|
|
816
|
+
updated: repoData.updated_at,
|
|
817
|
+
isArchived: repoData.archived,
|
|
818
|
+
isDisabled: repoData.disabled,
|
|
819
|
+
license: repoData.license?.name,
|
|
820
|
+
topics: repoData.topics || []
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
}, catch(error) {
|
|
824
|
+
return {
|
|
825
|
+
error: 'Repository insights failed',
|
|
826
|
+
message: 'Could not retrieve repository insights',
|
|
827
|
+
available: false
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
};
|
|
831
|
+
// Implementações para funcionalidades faltantes
|
|
832
|
+
async;
|
|
833
|
+
createDeployment(params, any);
|
|
834
|
+
Promise < any > {
|
|
835
|
+
const: { owner, repo, ref, environment, description, task, auto_merge, required_contexts, payload } = params,
|
|
836
|
+
try: {
|
|
837
|
+
const: deploymentData, any = {
|
|
838
|
+
ref,
|
|
839
|
+
environment: environment || 'production',
|
|
840
|
+
description: description || 'Deployment created via API',
|
|
841
|
+
auto_merge: auto_merge || false,
|
|
842
|
+
required_contexts: required_contexts || []
|
|
843
|
+
},
|
|
844
|
+
if(task) { }, deploymentData, : .task = task,
|
|
845
|
+
if(payload) { }, deploymentData, : .payload = payload,
|
|
846
|
+
const: data = await this.post(`/repos/${owner}/${repo}/deployments`, deploymentData),
|
|
847
|
+
return: {
|
|
848
|
+
id: data.id,
|
|
849
|
+
ref: data.ref,
|
|
850
|
+
environment: data.environment,
|
|
851
|
+
description: data.description,
|
|
852
|
+
created_at: data.created_at,
|
|
853
|
+
statuses_url: data.statuses_url,
|
|
854
|
+
repository_url: data.repository_url,
|
|
855
|
+
url: data.url
|
|
856
|
+
}
|
|
857
|
+
}, catch(error) {
|
|
858
|
+
throw new Error(`Falha ao criar deployment: ${error instanceof Error ? error.message : String(error)}`);
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
async;
|
|
862
|
+
updateDeploymentStatus(params, any);
|
|
863
|
+
Promise < any > {
|
|
864
|
+
const: { owner, repo, deployment_id, state, log_url, environment_url, description } = params,
|
|
865
|
+
try: {
|
|
866
|
+
const: statusData, any = {
|
|
867
|
+
state,
|
|
868
|
+
log_url: log_url || '',
|
|
869
|
+
environment_url: environment_url || '',
|
|
870
|
+
description: description || `Status updated to ${state}`
|
|
871
|
+
},
|
|
872
|
+
const: data = await this.post(`/repos/${owner}/${repo}/deployments/${deployment_id}/statuses`, statusData),
|
|
873
|
+
return: {
|
|
874
|
+
id: data.id,
|
|
875
|
+
state: data.state,
|
|
876
|
+
description: data.description,
|
|
877
|
+
environment: data.environment,
|
|
878
|
+
target_url: data.target_url,
|
|
879
|
+
log_url: data.log_url,
|
|
880
|
+
environment_url: data.environment_url,
|
|
881
|
+
created_at: data.created_at,
|
|
882
|
+
updated_at: data.updated_at,
|
|
883
|
+
deployment_url: data.deployment_url,
|
|
884
|
+
repository_url: data.repository_url
|
|
885
|
+
}
|
|
886
|
+
}, catch(error) {
|
|
887
|
+
throw new Error(`Falha ao atualizar status do deployment: ${error instanceof Error ? error.message : String(error)}`);
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
async;
|
|
891
|
+
manageSecurityAlerts(params, any);
|
|
892
|
+
Promise < any > {
|
|
893
|
+
const: { owner, repo, action, alert_number, dismiss_reason, dismiss_comment } = params,
|
|
894
|
+
try: {
|
|
895
|
+
if(action) { }
|
|
896
|
+
} === 'dismiss'
|
|
897
|
+
};
|
|
898
|
+
{
|
|
899
|
+
const dismissData = {
|
|
900
|
+
dismissed_reason: dismiss_reason || 'tolerable_risk'
|
|
901
|
+
};
|
|
902
|
+
if (dismiss_comment)
|
|
903
|
+
dismissData.dismissed_comment = dismiss_comment;
|
|
904
|
+
const data = await this.patch(`/repos/${owner}/${repo}/dependabot/alerts/${alert_number}`, dismissData);
|
|
905
|
+
return {
|
|
906
|
+
number: data.number,
|
|
907
|
+
state: data.state,
|
|
908
|
+
dismissed_reason: data.dismissed_reason,
|
|
909
|
+
dismissed_comment: data.dismissed_comment,
|
|
910
|
+
dismissed_at: data.dismissed_at,
|
|
911
|
+
dismissed_by: data.dismissed_by
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
if (action === 'reopen') {
|
|
915
|
+
const data = await this.patch(`/repos/${owner}/${repo}/dependabot/alerts/${alert_number}`, {
|
|
916
|
+
state: 'open'
|
|
917
|
+
});
|
|
918
|
+
return {
|
|
919
|
+
number: data.number,
|
|
920
|
+
state: data.state,
|
|
921
|
+
created_at: data.created_at,
|
|
922
|
+
updated_at: data.updated_at
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
else {
|
|
926
|
+
throw new Error(`Ação não suportada: ${action}`);
|
|
927
|
+
}
|
|
928
|
+
try { }
|
|
929
|
+
catch (error) {
|
|
930
|
+
throw new Error(`Falha ao gerenciar alertas de segurança: ${error instanceof Error ? error.message : String(error)}`);
|
|
931
|
+
}
|
|
932
|
+
async;
|
|
933
|
+
listSecurityVulnerabilities(params, any);
|
|
934
|
+
Promise < any > {
|
|
935
|
+
const: { owner, repo, state, severity, ecosystem, package_name } = params,
|
|
936
|
+
try: {
|
|
937
|
+
const: queryParams, any = {},
|
|
938
|
+
if(state) { }, queryParams, : .state = state,
|
|
939
|
+
if(severity) { }, queryParams, : .severity = severity,
|
|
940
|
+
if(ecosystem) { }, queryParams, : .ecosystem = ecosystem,
|
|
941
|
+
if(package_name) { }, queryParams, : .package = package_name,
|
|
942
|
+
const: data = await this.get(`/repos/${owner}/${repo}/dependabot/alerts`, queryParams),
|
|
943
|
+
return: {
|
|
944
|
+
total_count: data.length,
|
|
945
|
+
vulnerabilities: data.map(alert => ({
|
|
946
|
+
number: alert.number,
|
|
947
|
+
state: alert.state,
|
|
948
|
+
severity: alert.security_advisory?.severity,
|
|
949
|
+
summary: alert.security_advisory?.summary,
|
|
950
|
+
description: alert.security_advisory?.description,
|
|
951
|
+
created_at: alert.created_at,
|
|
952
|
+
updated_at: alert.updated_at,
|
|
953
|
+
dismissed_at: alert.dismissed_at,
|
|
954
|
+
dismissed_reason: alert.dismissed_reason,
|
|
955
|
+
dismissed_comment: alert.dismissed_comment,
|
|
956
|
+
dismissed_by: alert.dismissed_by,
|
|
957
|
+
dependency: {
|
|
958
|
+
package: alert.dependency?.package?.name,
|
|
959
|
+
ecosystem: alert.dependency?.package?.ecosystem,
|
|
960
|
+
manifest_path: alert.dependency?.manifest_path
|
|
961
|
+
}
|
|
962
|
+
}))
|
|
963
|
+
}
|
|
964
|
+
}, catch(error) {
|
|
965
|
+
return {
|
|
966
|
+
total_count: 0,
|
|
967
|
+
vulnerabilities: [],
|
|
968
|
+
note: 'Vulnerabilidades não disponíveis neste provider'
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
async;
|
|
973
|
+
createWorkflow(params, any);
|
|
974
|
+
Promise < any > {
|
|
975
|
+
const: { owner, repo, name, description, workflow_content } = params,
|
|
976
|
+
try: {
|
|
977
|
+
// Criar o arquivo de workflow
|
|
978
|
+
const: workflowPath = `.github/workflows/${name.toLowerCase().replace(/\s+/g, '-')}.yml`,
|
|
979
|
+
const: data = await this.createFile(owner, repo, workflowPath, workflow_content, `Add ${name} workflow`),
|
|
980
|
+
return: {
|
|
981
|
+
id: `workflow-${Date.now()}`,
|
|
982
|
+
name,
|
|
983
|
+
path: workflowPath,
|
|
984
|
+
state: 'active',
|
|
985
|
+
created_at: new Date().toISOString(),
|
|
986
|
+
updated_at: new Date().toISOString(),
|
|
987
|
+
url: data.html_url,
|
|
988
|
+
html_url: data.html_url
|
|
989
|
+
}
|
|
990
|
+
}, catch(error) {
|
|
991
|
+
throw new Error(`Falha ao criar workflow: ${error instanceof Error ? error.message : String(error)}`);
|
|
992
|
+
}
|
|
993
|
+
};
|
|
994
|
+
async;
|
|
995
|
+
triggerWorkflow(params, any);
|
|
996
|
+
Promise < any > {
|
|
997
|
+
const: { owner, repo, workflow_id, ref, inputs } = params,
|
|
998
|
+
try: {
|
|
999
|
+
const: triggerData, any = {
|
|
1000
|
+
ref: ref || 'main'
|
|
1001
|
+
},
|
|
1002
|
+
if(inputs) { }, triggerData, : .inputs = inputs,
|
|
1003
|
+
const: data = await this.post(`/repos/${owner}/${repo}/actions/workflows/${workflow_id}/dispatches`, triggerData),
|
|
1004
|
+
return: {
|
|
1005
|
+
success: true,
|
|
1006
|
+
message: 'Workflow triggered successfully',
|
|
1007
|
+
workflow_id,
|
|
1008
|
+
ref,
|
|
1009
|
+
inputs
|
|
1010
|
+
}
|
|
1011
|
+
}, catch(error) {
|
|
1012
|
+
throw new Error(`Falha ao disparar workflow: ${error instanceof Error ? error.message : String(error)}`);
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
1015
|
+
async;
|
|
1016
|
+
getWorkflowStatus(params, any);
|
|
1017
|
+
Promise < any > {
|
|
1018
|
+
const: { owner, repo, run_id } = params,
|
|
1019
|
+
try: {
|
|
1020
|
+
const: data = await this.get(`/repos/${owner}/${repo}/actions/runs/${run_id}`),
|
|
1021
|
+
return: {
|
|
1022
|
+
id: data.id,
|
|
1023
|
+
name: data.name,
|
|
1024
|
+
status: data.status,
|
|
1025
|
+
conclusion: data.conclusion,
|
|
1026
|
+
workflow_id: data.workflow_id,
|
|
1027
|
+
head_branch: data.head_branch,
|
|
1028
|
+
head_sha: data.head_sha,
|
|
1029
|
+
run_number: data.run_number,
|
|
1030
|
+
event: data.event,
|
|
1031
|
+
created_at: data.created_at,
|
|
1032
|
+
updated_at: data.updated_at,
|
|
1033
|
+
run_started_at: data.run_started_at,
|
|
1034
|
+
jobs_url: data.jobs_url,
|
|
1035
|
+
logs_url: data.logs_url,
|
|
1036
|
+
check_suite_url: data.check_suite_url,
|
|
1037
|
+
artifacts_url: data.artifacts_url,
|
|
1038
|
+
cancel_url: data.cancel_url,
|
|
1039
|
+
rerun_url: data.rerun_url,
|
|
1040
|
+
workflow_url: data.workflow_url,
|
|
1041
|
+
head_commit: data.head_commit,
|
|
1042
|
+
repository: data.repository,
|
|
1043
|
+
head_repository: data.head_repository
|
|
1044
|
+
}
|
|
1045
|
+
}, catch(error) {
|
|
1046
|
+
throw new Error(`Falha ao obter status do workflow: ${error instanceof Error ? error.message : String(error)}`);
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
async;
|
|
1050
|
+
getWorkflowLogs(params, any);
|
|
1051
|
+
Promise < any > {
|
|
1052
|
+
const: { owner, repo, run_id, job_id, step_number } = params,
|
|
1053
|
+
try: {
|
|
1054
|
+
let, endpoint = `/repos/${owner}/${repo}/actions/runs/${run_id}/logs`,
|
|
1055
|
+
if(job_id) {
|
|
1056
|
+
endpoint = `/repos/${owner}/${repo}/actions/jobs/${job_id}/logs`;
|
|
1057
|
+
if (step_number) {
|
|
1058
|
+
endpoint += `?step=${step_number}`;
|
|
1059
|
+
}
|
|
1060
|
+
},
|
|
1061
|
+
const: data = await this.get(endpoint),
|
|
1062
|
+
return: {
|
|
1063
|
+
logs: data,
|
|
1064
|
+
run_id,
|
|
1065
|
+
job_id,
|
|
1066
|
+
step_number,
|
|
1067
|
+
downloaded_at: new Date().toISOString()
|
|
1068
|
+
}
|
|
1069
|
+
}, catch(error) {
|
|
1070
|
+
throw new Error(`Falha ao obter logs do workflow: ${error instanceof Error ? error.message : String(error)}`);
|
|
1071
|
+
}
|
|
1072
|
+
};
|
|
1073
|
+
async;
|
|
1074
|
+
listWorkflowArtifacts(params, any);
|
|
1075
|
+
Promise < any > {
|
|
1076
|
+
const: { owner, repo, run_id } = params,
|
|
1077
|
+
try: {
|
|
1078
|
+
const: data = await this.get(`/repos/${owner}/${repo}/actions/runs/${run_id}/artifacts`),
|
|
1079
|
+
return: {
|
|
1080
|
+
total_count: data.total_count,
|
|
1081
|
+
artifacts: data.artifacts.map((artifact) => ({
|
|
1082
|
+
id: artifact.id,
|
|
1083
|
+
node_id: artifact.node_id,
|
|
1084
|
+
name: artifact.name,
|
|
1085
|
+
size_in_bytes: artifact.size_in_bytes,
|
|
1086
|
+
url: artifact.url,
|
|
1087
|
+
archive_download_url: artifact.archive_download_url,
|
|
1088
|
+
expired: artifact.expired,
|
|
1089
|
+
created_at: artifact.created_at,
|
|
1090
|
+
updated_at: artifact.updated_at,
|
|
1091
|
+
expires_at: artifact.expires_at
|
|
1092
|
+
}))
|
|
1093
|
+
}
|
|
1094
|
+
}, catch(error) {
|
|
1095
|
+
return {
|
|
1096
|
+
total_count: 0,
|
|
1097
|
+
artifacts: [],
|
|
1098
|
+
note: 'Artefatos não disponíveis'
|
|
1099
|
+
};
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
async;
|
|
1103
|
+
downloadArtifact(params, any);
|
|
1104
|
+
Promise < any > {
|
|
1105
|
+
const: { owner, repo, artifact_id, download_path } = params,
|
|
1106
|
+
try: {
|
|
1107
|
+
const: data = await this.get(`/repos/${owner}/${repo}/actions/artifacts/${artifact_id}/zip`),
|
|
1108
|
+
return: {
|
|
1109
|
+
success: true,
|
|
1110
|
+
artifact_id,
|
|
1111
|
+
download_path,
|
|
1112
|
+
downloaded_at: new Date().toISOString(),
|
|
1113
|
+
message: 'Artefato baixado com sucesso'
|
|
1114
|
+
}
|
|
1115
|
+
}, catch(error) {
|
|
1116
|
+
throw new Error(`Falha ao baixar artefato: ${error instanceof Error ? error.message : String(error)}`);
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
1119
|
+
async;
|
|
1120
|
+
listSecrets(params, any);
|
|
1121
|
+
Promise < any > {
|
|
1122
|
+
const: { owner, repo } = params,
|
|
1123
|
+
try: {
|
|
1124
|
+
const: data = await this.get(`/repos/${owner}/${repo}/actions/secrets`),
|
|
1125
|
+
return: {
|
|
1126
|
+
total_count: data.total_count,
|
|
1127
|
+
secrets: data.secrets.map((secret) => ({
|
|
1128
|
+
name: secret.name,
|
|
1129
|
+
created_at: secret.created_at,
|
|
1130
|
+
updated_at: secret.updated_at
|
|
1131
|
+
}))
|
|
1132
|
+
}
|
|
1133
|
+
}, catch(error) {
|
|
1134
|
+
return {
|
|
1135
|
+
total_count: 0,
|
|
1136
|
+
secrets: [],
|
|
1137
|
+
note: 'Secrets não disponíveis'
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
};
|
|
1141
|
+
async;
|
|
1142
|
+
listJobs(params, any);
|
|
1143
|
+
Promise < any > {
|
|
1144
|
+
const: { owner, repo, run_id } = params,
|
|
1145
|
+
try: {
|
|
1146
|
+
const: data = await this.get(`/repos/${owner}/${repo}/actions/runs/${run_id}/jobs`),
|
|
1147
|
+
return: {
|
|
1148
|
+
total_count: data.total_count,
|
|
1149
|
+
jobs: data.jobs.map((job) => ({
|
|
1150
|
+
id: job.id,
|
|
1151
|
+
run_id: job.run_id,
|
|
1152
|
+
run_url: job.run_url,
|
|
1153
|
+
node_id: job.node_id,
|
|
1154
|
+
head_sha: job.head_sha,
|
|
1155
|
+
url: job.url,
|
|
1156
|
+
html_url: job.html_url,
|
|
1157
|
+
status: job.status,
|
|
1158
|
+
conclusion: job.conclusion,
|
|
1159
|
+
started_at: job.started_at,
|
|
1160
|
+
completed_at: job.completed_at,
|
|
1161
|
+
name: job.name,
|
|
1162
|
+
steps: job.steps,
|
|
1163
|
+
check_run_url: job.check_run_url,
|
|
1164
|
+
labels: job.labels,
|
|
1165
|
+
runner_id: job.runner_id,
|
|
1166
|
+
runner_name: job.runner_name,
|
|
1167
|
+
runner_group_id: job.runner_group_id,
|
|
1168
|
+
runner_group_name: job.runner_group_name
|
|
1169
|
+
}))
|
|
1170
|
+
}
|
|
1171
|
+
}, catch(error) {
|
|
1172
|
+
return {
|
|
1173
|
+
total_count: 0,
|
|
1174
|
+
jobs: [],
|
|
1175
|
+
note: 'Jobs não disponíveis'
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
//# sourceMappingURL=github-provider-backup.js.map
|