@andrebuzeli/git-mcp 10.0.9 → 11.0.0
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/README.md +34 -428
- package/bin/git-mcp.js +21 -0
- package/docs/TOOLS.md +110 -0
- package/mcp.json.template +12 -0
- package/package.json +9 -76
- package/src/local/git.js +14 -0
- package/src/providers/gitea.js +13 -0
- package/src/providers/github.js +13 -0
- package/src/server.js +63 -0
- package/src/tools/git-actions.js +19 -0
- package/src/tools/git-activity.js +28 -0
- package/src/tools/git-admin.js +20 -0
- package/src/tools/git-checks.js +14 -0
- package/src/tools/git-commits.js +34 -0
- package/src/tools/git-contents.js +30 -0
- package/src/tools/git-deployments.js +21 -0
- package/src/tools/git-gists.js +15 -0
- package/src/tools/git-gitdata.js +19 -0
- package/src/tools/git-issues-prs.js +44 -0
- package/src/tools/git-issues.js +12 -0
- package/src/tools/git-local.js +66 -0
- package/src/tools/git-meta.js +19 -0
- package/src/tools/git-misc.js +21 -0
- package/src/tools/git-orgs.js +26 -0
- package/src/tools/git-packages.js +12 -0
- package/src/tools/git-raw.js +14 -0
- package/src/tools/git-releases.js +17 -0
- package/src/tools/git-remote.js +29 -0
- package/src/tools/git-repos.js +60 -0
- package/src/tools/git-search.js +18 -0
- package/src/tools/git-sync.js +40 -0
- package/src/tools/git-user.js +26 -0
- package/src/tools/schema.js +3 -0
- package/src/utils/fs.js +29 -0
- package/src/utils/project.js +7 -0
- package/tests/errors.js +26 -0
- package/tests/full_suite.js +98 -0
- package/tests/run.js +50 -0
- package/LICENSE +0 -21
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -224
- package/dist/prompts/gitPrompts.d.ts +0 -93
- package/dist/prompts/gitPrompts.js +0 -177
- package/dist/providers/giteaProvider.d.ts +0 -3
- package/dist/providers/giteaProvider.js +0 -6
- package/dist/providers/githubProvider.d.ts +0 -2
- package/dist/providers/githubProvider.js +0 -4
- package/dist/providers/providerManager.d.ts +0 -11
- package/dist/providers/providerManager.js +0 -49
- package/dist/resources/toolsGuide.d.ts +0 -12
- package/dist/resources/toolsGuide.js +0 -1713
- package/dist/scripts/test_e2e.d.ts +0 -1
- package/dist/scripts/test_e2e.js +0 -199
- package/dist/scripts/test_exhaustive.d.ts +0 -1
- package/dist/scripts/test_exhaustive.js +0 -275
- package/dist/scripts/test_gitea_creation.d.ts +0 -1
- package/dist/scripts/test_gitea_creation.js +0 -116
- package/dist/scripts/verify_setup.d.ts +0 -1
- package/dist/scripts/verify_setup.js +0 -61
- package/dist/server.d.ts +0 -9
- package/dist/server.js +0 -73
- package/dist/tools/gitAnalytics.d.ts +0 -35
- package/dist/tools/gitAnalytics.js +0 -220
- package/dist/tools/gitArchive.d.ts +0 -119
- package/dist/tools/gitArchive.js +0 -150
- package/dist/tools/gitBackup.d.ts +0 -116
- package/dist/tools/gitBackup.js +0 -156
- package/dist/tools/gitBranches.d.ts +0 -54
- package/dist/tools/gitBranches.js +0 -282
- package/dist/tools/gitChangelog.d.ts +0 -37
- package/dist/tools/gitChangelog.js +0 -67
- package/dist/tools/gitConfig.d.ts +0 -97
- package/dist/tools/gitConfig.js +0 -125
- package/dist/tools/gitFiles.d.ts +0 -129
- package/dist/tools/gitFiles.js +0 -213
- package/dist/tools/gitFix.d.ts +0 -4
- package/dist/tools/gitFix.js +0 -159
- package/dist/tools/gitFix.tool.d.ts +0 -31
- package/dist/tools/gitFix.tool.js +0 -92
- package/dist/tools/gitHistory.d.ts +0 -41
- package/dist/tools/gitHistory.js +0 -349
- package/dist/tools/gitIgnore.d.ts +0 -214
- package/dist/tools/gitIgnore.js +0 -338
- package/dist/tools/gitIssues.d.ts +0 -80
- package/dist/tools/gitIssues.js +0 -363
- package/dist/tools/gitLog.d.ts +0 -30
- package/dist/tools/gitLog.js +0 -46
- package/dist/tools/gitMonitor.d.ts +0 -30
- package/dist/tools/gitMonitor.js +0 -284
- package/dist/tools/gitPackages.d.ts +0 -180
- package/dist/tools/gitPackages.js +0 -214
- package/dist/tools/gitPulls.d.ts +0 -66
- package/dist/tools/gitPulls.js +0 -347
- package/dist/tools/gitPush.d.ts +0 -40
- package/dist/tools/gitPush.js +0 -59
- package/dist/tools/gitRelease.d.ts +0 -49
- package/dist/tools/gitRelease.js +0 -359
- package/dist/tools/gitRemote.d.ts +0 -47
- package/dist/tools/gitRemote.js +0 -111
- package/dist/tools/gitReset.d.ts +0 -57
- package/dist/tools/gitReset.js +0 -79
- package/dist/tools/gitStash.d.ts +0 -61
- package/dist/tools/gitStash.js +0 -80
- package/dist/tools/gitSync.d.ts +0 -34
- package/dist/tools/gitSync.js +0 -182
- package/dist/tools/gitTags.d.ts +0 -45
- package/dist/tools/gitTags.js +0 -251
- package/dist/tools/gitUpdate.d.ts +0 -60
- package/dist/tools/gitUpdate.js +0 -474
- package/dist/tools/gitUpload.d.ts +0 -35
- package/dist/tools/gitUpload.js +0 -385
- package/dist/tools/gitWorkflow.d.ts +0 -117
- package/dist/tools/gitWorkflow.js +0 -472
- package/dist/types.d.ts +0 -20
- package/dist/types.js +0 -1
- package/dist/utils/agentHelpers.d.ts +0 -11
- package/dist/utils/agentHelpers.js +0 -41
- package/dist/utils/apiHelpers.d.ts +0 -29
- package/dist/utils/apiHelpers.js +0 -125
- package/dist/utils/cache.d.ts +0 -96
- package/dist/utils/cache.js +0 -208
- package/dist/utils/contextDetector.d.ts +0 -0
- package/dist/utils/contextDetector.js +0 -1
- package/dist/utils/errors.d.ts +0 -13
- package/dist/utils/errors.js +0 -17
- package/dist/utils/gitAdapter.d.ts +0 -224
- package/dist/utils/gitAdapter.js +0 -1162
- package/dist/utils/logger.d.ts +0 -45
- package/dist/utils/logger.js +0 -140
- package/dist/utils/rateLimiter.d.ts +0 -113
- package/dist/utils/rateLimiter.js +0 -257
- package/dist/utils/repoHelpers.d.ts +0 -44
- package/dist/utils/repoHelpers.js +0 -122
- package/dist/utils/safetyController.d.ts +0 -1
- package/dist/utils/safetyController.js +0 -12
- package/dist/utils/validation.d.ts +0 -115
- package/dist/utils/validation.js +0 -270
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Gitea } from '../providers/gitea.js'
|
|
2
|
+
import { Github } from '../providers/github.js'
|
|
3
|
+
import { makeSchema } from './schema.js'
|
|
4
|
+
|
|
5
|
+
export class GitOrgsTool {
|
|
6
|
+
constructor(env) { this.gitea = new Gitea(env.GITEA_URL, env.GITEA_TOKEN); this.github = new Github(env.GITHUB_TOKEN) }
|
|
7
|
+
async handle(action, projectPath, args) {
|
|
8
|
+
if (action === 'create') return await this.gitea.request('POST', '/orgs', { username: args?.org_name, visibility: args?.visibility || 'public' })
|
|
9
|
+
if (action === 'list') { const r = await Promise.allSettled([ this.gitea.request('GET', '/orgs'), this.github.request('GET', '/user/orgs') ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
10
|
+
if (action === 'get') { const r = await Promise.allSettled([ this.gitea.request('GET', `/orgs/${args?.org_name}`), this.github.request('GET', `/orgs/${args?.org_name}`) ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
11
|
+
if (action === 'members') return await this.gitea.request('GET', `/orgs/${args?.org_name}/members`)
|
|
12
|
+
if (action === 'public_members') return await this.gitea.request('GET', `/orgs/${args?.org_name}/public_members`)
|
|
13
|
+
if (action === 'repos') return await this.gitea.request('GET', `/orgs/${args?.org_name}/repos`)
|
|
14
|
+
if (action === 'activities') return await this.gitea.request('GET', `/orgs/${args?.org_name}/activities/feeds`)
|
|
15
|
+
if (action === 'hooks') return await this.gitea.request('GET', `/orgs/${args?.org_name}/hooks`)
|
|
16
|
+
if (action === 'team-create') return await this.gitea.request('POST', `/orgs/${args?.org_name}/teams`, { name: args?.name || 'Team', permission: args?.permission || 'read' })
|
|
17
|
+
if (action === 'team-get') return await this.gitea.request('GET', `/api/v1/teams/${args?.team_id}`)
|
|
18
|
+
if (action === 'team-members') return await this.gitea.request('GET', `/teams/${args?.team_id}/members`)
|
|
19
|
+
if (action === 'team-repos') return await this.gitea.request('GET', `/teams/${args?.team_id}/repos`)
|
|
20
|
+
if (action === 'labels') return await this.gitea.request('GET', `/orgs/${args?.org_name}/labels`)
|
|
21
|
+
if (action === 'delete') return await this.gitea.request('DELETE', `/orgs/${args?.org_name}`)
|
|
22
|
+
return { error: 'ação inválida' }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getSchema() { return makeSchema({ name: 'git-orgs', description: 'Organizações e times (Gitea)', actions: { create: { description: 'Criar organização' }, list: { description: 'Listar organizações' }, get: { description: 'Obter organização' }, members: { description: 'Membros' }, public_members: { description: 'Membros públicos' }, repos: { description: 'Repositórios' }, activities: { description: 'Atividades' }, hooks: { description: 'Hooks' }, 'team-create': { description: 'Criar time' }, 'team-get': { description: 'Obter time' }, 'team-members': { description: 'Membros do time' }, 'team-repos': { description: 'Repos do time' }, labels: { description: 'Labels da org' }, delete: { description: 'Excluir organização' } } }) }
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Gitea } from '../providers/gitea.js'
|
|
2
|
+
import { makeSchema } from './schema.js'
|
|
3
|
+
|
|
4
|
+
export class GitPackagesTool {
|
|
5
|
+
constructor(env) { this.gitea = new Gitea(env.GITEA_URL, env.GITEA_TOKEN) }
|
|
6
|
+
async handle(action, projectPath, args) {
|
|
7
|
+
if (action === 'list') { const me = await this.gitea.me(); return await this.gitea.request('GET', `/packages/${me.login}`) }
|
|
8
|
+
return { error: 'ação inválida' }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getSchema() { return makeSchema({ name: 'git-packages', description: 'Pacotes (Gitea)', actions: { list: { description: 'Listar pacotes do usuário' } } }) }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Gitea } from '../providers/gitea.js'
|
|
2
|
+
import { deriveProjectName } from '../utils/project.js'
|
|
3
|
+
import { makeSchema } from './schema.js'
|
|
4
|
+
|
|
5
|
+
export class GitRawTool {
|
|
6
|
+
constructor(env) { this.gitea = new Gitea(env.GITEA_URL, env.GITEA_TOKEN) }
|
|
7
|
+
async handle(action, projectPath, args) {
|
|
8
|
+
const me = await this.gitea.me(); const name = deriveProjectName(projectPath); const repo = `${me.login}/${name}`
|
|
9
|
+
if (action === 'get') return await this.gitea.request('GET', `/repos/${repo}/raw/${args?.path || 'test.txt'}`)
|
|
10
|
+
return { error: 'ação inválida' }
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getSchema() { return makeSchema({ name: 'git-raw', description: 'Conteúdo bruto (Gitea)', actions: { get: { description: 'Obter arquivo bruto' } } }) }
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Gitea } from '../providers/gitea.js'
|
|
2
|
+
import { Github } from '../providers/github.js'
|
|
3
|
+
import { deriveProjectName } from '../utils/project.js'
|
|
4
|
+
import { makeSchema } from './schema.js'
|
|
5
|
+
|
|
6
|
+
export class GitReleasesTool {
|
|
7
|
+
constructor(env) { this.providers = { gitea: new Gitea(env.GITEA_URL, env.GITEA_TOKEN), github: new Github(env.GITHUB_TOKEN) } }
|
|
8
|
+
async handle(action, projectPath, args) {
|
|
9
|
+
const name = deriveProjectName(projectPath)
|
|
10
|
+
if (action === 'create') { const tag = args?.tag || 'v1.0.0'; const title = args?.title || tag; const body = args?.body || ''; const r = await Promise.allSettled([ this.providers.gitea.createRelease(name, tag, title, body), this.providers.github.createRelease(name, tag, title, body) ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
11
|
+
return { error: 'ação inválida' }
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getSchema() {
|
|
16
|
+
return makeSchema({ name: 'git-releases', description: 'Gerenciar releases', actions: { create: { description: 'Criar release (tag/title/body)' } } })
|
|
17
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Gitea } from '../providers/gitea.js'
|
|
2
|
+
import { Github } from '../providers/github.js'
|
|
3
|
+
import { deriveProjectName } from '../utils/project.js'
|
|
4
|
+
import fs from 'fs'
|
|
5
|
+
import git from 'isomorphic-git'
|
|
6
|
+
import { makeSchema } from './schema.js'
|
|
7
|
+
|
|
8
|
+
export class GitRemoteTool {
|
|
9
|
+
constructor(env) { this.env = env; this.providers = { gitea: new Gitea(env.GITEA_URL, env.GITEA_TOKEN), github: new Github(env.GITHUB_TOKEN) } }
|
|
10
|
+
async handle(action, projectPath, args) {
|
|
11
|
+
const name = deriveProjectName(projectPath)
|
|
12
|
+
if (action === 'createRepo') { const r = await Promise.allSettled([ this.providers.gitea.createRepo(name, false, true), this.providers.github.createRepo(name, false, true) ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
13
|
+
if (action === 'deleteRepo') { const r = await Promise.allSettled([ this.providers.gitea.deleteRepo(name), this.providers.github.deleteRepo(name) ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
14
|
+
if (action === 'ensureRemotes') { const urls = await Promise.all([ this.providers.gitea.repoHttpsUrl(name), this.providers.github.repoHttpsUrl(name) ]); try { await git.addRemote({ fs, dir: projectPath, remote: 'origin-gitea', url: urls[0] }) } catch {} ; try { await git.addRemote({ fs, dir: projectPath, remote: 'origin-github', url: urls[1] }) } catch {} ; return { gitea: urls[0], github: urls[1] } }
|
|
15
|
+
return { error: 'ação inválida' }
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getSchema() {
|
|
20
|
+
return makeSchema({
|
|
21
|
+
name: 'git-remote',
|
|
22
|
+
description: 'Operações remotas simultâneas Gitea/GitHub (repos/remotes)',
|
|
23
|
+
actions: {
|
|
24
|
+
createRepo: { description: 'Criar repositório nos provedores' },
|
|
25
|
+
deleteRepo: { description: 'Excluir repositório nos provedores' },
|
|
26
|
+
ensureRemotes: { description: 'Garantir remotes origin-gitea/github' }
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Gitea } from '../providers/gitea.js'
|
|
2
|
+
import { Github } from '../providers/github.js'
|
|
3
|
+
import { deriveProjectName } from '../utils/project.js'
|
|
4
|
+
import { makeSchema } from './schema.js'
|
|
5
|
+
|
|
6
|
+
export class GitReposTool {
|
|
7
|
+
constructor(env) { this.providers = { gitea: new Gitea(env.GITEA_URL, env.GITEA_TOKEN), github: new Github(env.GITHUB_TOKEN) } }
|
|
8
|
+
async handle(action, projectPath, args) {
|
|
9
|
+
const name = deriveProjectName(projectPath)
|
|
10
|
+
const meG = await this.providers.gitea.me(); const meH = await this.providers.github.me()
|
|
11
|
+
const repoFullG = `${meG.login}/${name}`
|
|
12
|
+
const repoFullH = `${meH.login}/${name}`
|
|
13
|
+
const par = async (fnG, fnH) => { const r = await Promise.allSettled([ fnG(), fnH() ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
14
|
+
|
|
15
|
+
if (action === 'get') return await par(() => this.providers.gitea.request('GET', `/repos/${repoFullG}`), () => this.providers.github.request('GET', `/repos/${repoFullH}`))
|
|
16
|
+
if (action === 'patch') return await par(() => this.providers.gitea.request('PATCH', `/repos/${repoFullG}`, { description: args?.description || 'Updated' }), () => this.providers.github.request('PATCH', `/repos/${repoFullH}`, { description: args?.description || 'Updated' }))
|
|
17
|
+
if (action === 'languages') return await par(() => this.providers.gitea.request('GET', `/repos/${repoFullG}/languages`), () => this.providers.github.request('GET', `/repos/${repoFullH}/languages`))
|
|
18
|
+
if (action === 'tags') return await par(() => this.providers.gitea.request('GET', `/repos/${repoFullG}/tags`), () => this.providers.github.request('GET', `/repos/${repoFullH}/tags`))
|
|
19
|
+
if (action === 'topics-get') return await par(() => this.providers.gitea.request('GET', `/repos/${repoFullG}/topics`), () => this.providers.github.request('GET', `/repos/${repoFullH}/topics`))
|
|
20
|
+
if (action === 'topics-put') return await par(() => this.providers.gitea.request('PUT', `/repos/${repoFullG}/topics`, { topics: args?.topics || ['test'] }), () => this.providers.github.request('PUT', `/repos/${repoFullH}/topics`, { names: args?.topics || ['test'] }))
|
|
21
|
+
if (action === 'collaborators') return await par(() => this.providers.gitea.request('GET', `/repos/${repoFullG}/collaborators`), () => this.providers.github.request('GET', `/repos/${repoFullH}/collaborators`))
|
|
22
|
+
if (action === 'subscribers') return await par(() => this.providers.gitea.request('GET', `/repos/${repoFullG}/subscribers`), () => this.providers.github.request('GET', `/repos/${repoFullH}/subscribers`))
|
|
23
|
+
if (action === 'subscription-get') return await par(() => this.providers.gitea.request('GET', `/repos/${repoFullG}/subscription`), () => this.providers.github.request('GET', `/repos/${repoFullH}/subscription`))
|
|
24
|
+
if (action === 'subscription-put') return await par(() => this.providers.gitea.request('PUT', `/repos/${repoFullG}/subscription`, { subscribed: true }), () => this.providers.github.request('PUT', `/repos/${repoFullH}/subscription`, { subscribed: true }))
|
|
25
|
+
if (action === 'subscription-delete') return await par(() => this.providers.gitea.request('DELETE', `/repos/${repoFullG}/subscription`), () => this.providers.github.request('DELETE', `/repos/${repoFullH}/subscription`))
|
|
26
|
+
if (action === 'stargazers') return await par(() => this.providers.gitea.request('GET', `/repos/${repoFullG}/stargazers`), () => this.providers.github.request('GET', `/repos/${repoFullH}/stargazers`))
|
|
27
|
+
if (action === 'forks-get') return await par(() => this.providers.gitea.request('GET', `/repos/${repoFullG}/forks`), () => this.providers.github.request('GET', `/repos/${repoFullH}/forks`))
|
|
28
|
+
if (action === 'forks-post') return await par(() => this.providers.gitea.request('POST', `/repos/${repoFullG}/forks`), () => this.providers.github.request('POST', `/repos/${repoFullH}/forks`))
|
|
29
|
+
if (action === 'activities') return await par(() => this.providers.gitea.request('GET', `/repos/${repoFullG}/activities/feeds`), () => this.providers.github.request('GET', `/repos/${repoFullH}/events`))
|
|
30
|
+
if (action === 'hooks') return await par(() => this.providers.gitea.request('GET', `/repos/${repoFullG}/hooks`), () => this.providers.github.request('GET', `/repos/${repoFullH}/hooks`))
|
|
31
|
+
if (action === 'keys') return await par(() => this.providers.gitea.request('GET', `/repos/${repoFullG}/keys`), () => this.providers.github.request('GET', `/repos/${repoFullH}/keys`))
|
|
32
|
+
return { error: 'ação inválida' }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function getSchema() {
|
|
37
|
+
return makeSchema({
|
|
38
|
+
name: 'git-repos',
|
|
39
|
+
description: 'Metadados e relações de repositórios',
|
|
40
|
+
actions: {
|
|
41
|
+
get: { description: 'Obter repositório' },
|
|
42
|
+
patch: { description: 'Atualizar descrição' },
|
|
43
|
+
languages: { description: 'Listar linguagens' },
|
|
44
|
+
tags: { description: 'Listar tags' },
|
|
45
|
+
'topics-get': { description: 'Obter tópicos' },
|
|
46
|
+
'topics-put': { description: 'Definir tópicos' },
|
|
47
|
+
collaborators: { description: 'Listar colaboradores' },
|
|
48
|
+
subscribers: { description: 'Listar assinantes' },
|
|
49
|
+
'subscription-get': { description: 'Obter assinatura' },
|
|
50
|
+
'subscription-put': { description: 'Assinar repo' },
|
|
51
|
+
'subscription-delete': { description: 'Cancelar assinatura' },
|
|
52
|
+
stargazers: { description: 'Listar estrelas' },
|
|
53
|
+
'forks-get': { description: 'Listar forks' },
|
|
54
|
+
'forks-post': { description: 'Criar fork' },
|
|
55
|
+
activities: { description: 'Feed de atividades' },
|
|
56
|
+
hooks: { description: 'Hooks do repo' },
|
|
57
|
+
keys: { description: 'Chaves do repo' }
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Gitea } from '../providers/gitea.js'
|
|
2
|
+
import { Github } from '../providers/github.js'
|
|
3
|
+
import { makeSchema } from './schema.js'
|
|
4
|
+
|
|
5
|
+
export class GitSearchTool {
|
|
6
|
+
constructor(env) { this.gitea = new Gitea(env.GITEA_URL, env.GITEA_TOKEN); this.github = new Github(env.GITHUB_TOKEN) }
|
|
7
|
+
async handle(action, projectPath, args) {
|
|
8
|
+
if (action === 'repos') { const q = args?.q || 'user:defunkt'; return await this.github.request('GET', `/search/repositories?q=${encodeURIComponent(q)}`) }
|
|
9
|
+
if (action === 'users') { const q = args?.q || 'tom'; return await this.github.request('GET', `/search/users?q=${encodeURIComponent(q)}`) }
|
|
10
|
+
if (action === 'issues') { const q = args?.q || 'type:issue+user:defunkt'; return await this.github.request('GET', `/search/issues?q=${encodeURIComponent(q)}`) }
|
|
11
|
+
if (action === 'repos-gitea') return await this.gitea.request('GET', '/repos/search')
|
|
12
|
+
return { error: 'ação inválida' }
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getSchema() {
|
|
17
|
+
return makeSchema({ name: 'git-search', description: 'Busca em GitHub/Gitea', actions: { repos: { description: 'Buscar repositórios (GitHub)' }, users: { description: 'Buscar usuários (GitHub)' }, issues: { description: 'Buscar issues (GitHub)' }, 'repos-gitea': { description: 'Buscar repositórios (Gitea)' } } })
|
|
18
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { deriveProjectName } from '../utils/project.js'
|
|
2
|
+
import { GitLocalTool } from './git-local.js'
|
|
3
|
+
import { GitRemoteTool } from './git-remote.js'
|
|
4
|
+
import { listFilesRecursive, toProjectRelative, readBase64 } from '../utils/fs.js'
|
|
5
|
+
import { Gitea } from '../providers/gitea.js'
|
|
6
|
+
import { Github } from '../providers/github.js'
|
|
7
|
+
import { makeSchema } from './schema.js'
|
|
8
|
+
|
|
9
|
+
export class GitSyncTool {
|
|
10
|
+
constructor(env) { this.env = env; this.local = new GitLocalTool(); this.remote = new GitRemoteTool(env) }
|
|
11
|
+
async handle(action, projectPath, args) {
|
|
12
|
+
if (action === 'mirror') {
|
|
13
|
+
await this.remote.handle('createRepo', projectPath, args)
|
|
14
|
+
const rem = await this.remote.handle('ensureRemotes', projectPath, args)
|
|
15
|
+
try { await this.local.handle('push', projectPath, { remote: 'origin-gitea', branch: args?.branch || 'master' }, this.env) } catch {}
|
|
16
|
+
try { await this.local.handle('push', projectPath, { remote: 'origin-github', branch: args?.branch || 'master' }, this.env) } catch {}
|
|
17
|
+
// Fallback por API: subir todos arquivos via contents
|
|
18
|
+
const files = listFilesRecursive(projectPath)
|
|
19
|
+
const gitea = new Gitea(this.env.GITEA_URL, this.env.GITEA_TOKEN)
|
|
20
|
+
const github = new Github(this.env.GITHUB_TOKEN)
|
|
21
|
+
const name = deriveProjectName(projectPath)
|
|
22
|
+
for (const f of files) {
|
|
23
|
+
const rel = toProjectRelative(projectPath, f)
|
|
24
|
+
const content = readBase64(f)
|
|
25
|
+
try { await gitea.putContent(name, rel, content, 'mcp sync', args?.branch || 'master') } catch {}
|
|
26
|
+
try { await github.putContent(name, rel, content, 'mcp sync', args?.branch || 'master') } catch {}
|
|
27
|
+
}
|
|
28
|
+
return { ok: true }
|
|
29
|
+
}
|
|
30
|
+
return { error: 'ação inválida' }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getSchema() {
|
|
35
|
+
return makeSchema({
|
|
36
|
+
name: 'git-sync',
|
|
37
|
+
description: 'Espelhamento e sincronização completa entre provedores',
|
|
38
|
+
actions: { mirror: { description: 'Push e fallback via Contents API' } }
|
|
39
|
+
})
|
|
40
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Gitea } from '../providers/gitea.js'
|
|
2
|
+
import { Github } from '../providers/github.js'
|
|
3
|
+
import { makeSchema } from './schema.js'
|
|
4
|
+
|
|
5
|
+
export class GitUserTool {
|
|
6
|
+
constructor(env) { this.gitea = new Gitea(env.GITEA_URL, env.GITEA_TOKEN); this.github = new Github(env.GITHUB_TOKEN) }
|
|
7
|
+
async handle(action, projectPath, args) {
|
|
8
|
+
if (action === 'me') { const r = await Promise.allSettled([ this.gitea.request('GET', '/user'), this.github.request('GET', '/user') ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
9
|
+
if (action === 'users-search') return await this.gitea.request('GET', '/users/search')
|
|
10
|
+
if (action === 'user-get') return await this.gitea.request('GET', `/users/${args?.username}`)
|
|
11
|
+
if (action === 'heatmap') return await this.gitea.request('GET', `/users/${args?.username}/heatmap`)
|
|
12
|
+
if (action === 'followers') { const r = await Promise.allSettled([ this.gitea.request('GET', `/users/${args?.username}/followers`), this.github.request('GET', '/user/followers') ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
13
|
+
if (action === 'following') { const r = await Promise.allSettled([ this.gitea.request('GET', `/users/${args?.username}/following`), this.github.request('GET', '/user/following') ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
14
|
+
if (action === 'keys') { const r = await Promise.allSettled([ this.gitea.request('GET', `/users/${args?.username}/keys`), this.github.request('GET', '/user/keys') ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
15
|
+
if (action === 'gpg_keys') { const r = await Promise.allSettled([ this.gitea.request('GET', `/users/${args?.username}/gpg_keys`), this.github.request('GET', '/user/gpg_keys') ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
16
|
+
if (action === 'oauth2-apps') return await this.gitea.request('GET', '/user/applications/oauth2')
|
|
17
|
+
if (action === 'emails') { const r = await Promise.allSettled([ this.gitea.request('GET', '/user/emails'), this.github.request('GET', '/user/emails') ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
18
|
+
if (action === 'starred') { const r = await Promise.allSettled([ this.gitea.request('GET', '/user/starred'), this.github.request('GET', '/user/starred') ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
19
|
+
if (action === 'subscriptions') { const r = await Promise.allSettled([ this.gitea.request('GET', '/user/subscriptions'), this.github.request('GET', '/user/subscriptions') ]); return r.map(x => x.status === 'fulfilled' ? x.value : { error: x.reason?.message }) }
|
|
20
|
+
if (action === 'stopwatches') return await this.gitea.request('GET', '/user/stopwatches')
|
|
21
|
+
if (action === 'settings') return await this.gitea.request('GET', '/user/settings')
|
|
22
|
+
return { error: 'ação inválida' }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getSchema() { return makeSchema({ name: 'git-user', description: 'Perfil e dados de usuário (Gitea/GitHub)', actions: { me: { description: 'Dados do usuário autenticado' }, 'users-search': { description: 'Buscar usuários (Gitea)' }, 'user-get': { description: 'Obter usuário (Gitea)' }, heatmap: { description: 'Heatmap (Gitea)' }, followers: { description: 'Seguidores' }, following: { description: 'Seguindo' }, keys: { description: 'Chaves SSH' }, gpg_keys: { description: 'Chaves GPG' }, 'oauth2-apps': { description: 'Apps OAuth2 (Gitea)' }, emails: { description: 'Emails' }, starred: { description: 'Repos estrelados' }, subscriptions: { description: 'Assinaturas' }, stopwatches: { description: 'Cronômetros (Gitea)' }, settings: { description: 'Configurações (Gitea)' } } }) }
|
package/src/utils/fs.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
4
|
+
export function listFilesRecursive(dir) {
|
|
5
|
+
const out = []
|
|
6
|
+
function walk(d) {
|
|
7
|
+
const entries = fs.readdirSync(d, { withFileTypes: true })
|
|
8
|
+
for (const e of entries) {
|
|
9
|
+
const p = path.join(d, e.name)
|
|
10
|
+
if (e.isDirectory()) {
|
|
11
|
+
if (e.name === '.git') continue
|
|
12
|
+
walk(p)
|
|
13
|
+
} else {
|
|
14
|
+
out.push(p)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
walk(dir)
|
|
19
|
+
return out
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function toProjectRelative(dir, filePath) {
|
|
23
|
+
return path.relative(dir, filePath).split(path.sep).join('/')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function readBase64(filePath) {
|
|
27
|
+
const buf = fs.readFileSync(filePath)
|
|
28
|
+
return buf.toString('base64')
|
|
29
|
+
}
|
package/tests/errors.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { callOnce } from '../src/server.js'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
const projectPath = process.env.TEST_PROJECT || 'Z:/MCP/GIT MCP/temp_git_mcp_test'
|
|
4
|
+
|
|
5
|
+
async function main() {
|
|
6
|
+
if (!fs.existsSync(projectPath)) fs.mkdirSync(projectPath, { recursive: true })
|
|
7
|
+
fs.writeFileSync(projectPath + '/err.txt', 'X')
|
|
8
|
+
const wrap = async (name, fn) => { try { const r = await fn(); console.log(name + ': OK' + (r?.fallback ? ' (fallback)' : '')) } catch (e) { console.log(name + ': ERR ' + e?.message) } }
|
|
9
|
+
|
|
10
|
+
// Missing remote -> ensureRemotes then push
|
|
11
|
+
await wrap('ensureRemotes', () => callOnce({ tool: 'git-remote', action: 'ensureRemotes', projectPath }))
|
|
12
|
+
await wrap('push-fallback', () => callOnce({ tool: 'git-local', action: 'push', projectPath, args: { branch: 'master' } }))
|
|
13
|
+
|
|
14
|
+
// Issue labels with nonexistent label -> autocreate and apply
|
|
15
|
+
await wrap('labels-create', () => callOnce({ tool: 'git-issues-prs', action: 'labels-create', projectPath, args: { name: 'bug', color: 'ff0000' } }))
|
|
16
|
+
const issue = await callOnce({ tool: 'git-issues-prs', action: 'issue-create', projectPath, args: { title: 'Err Issue', body: 'B' } })
|
|
17
|
+
const num = Array.isArray(issue) ? (issue[1]?.number) : issue?.number
|
|
18
|
+
await wrap('issue-labels-autocorrect', () => callOnce({ tool: 'git-issues-prs', action: 'issue-labels', projectPath, args: { number: num, labels: ['bug'] } }))
|
|
19
|
+
|
|
20
|
+
// PR head inexistente -> autocorreção criando branch/arquivo e reabrindo
|
|
21
|
+
await wrap('pr-create-autocorrect', () => callOnce({ tool: 'git-issues-prs', action: 'pr-create', projectPath, args: { title: 'PR Err', head: 'feature-branch', base: 'main' } }))
|
|
22
|
+
|
|
23
|
+
console.log('ERROR TESTS DONE')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
main().catch(e => { console.error(e); process.exit(1) })
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { callOnce } from '../src/server.js'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
|
|
4
|
+
function log(name, res) { const ok = typeof res === 'object' && res !== null && res.ok === false ? false : true; console.log(`${name}: ${ok ? 'OK' : 'ERR'}`) }
|
|
5
|
+
|
|
6
|
+
async function main() {
|
|
7
|
+
const projectPath = process.env.TEST_PROJECT || 'Z:/MCP/GIT MCP/temp_git_mcp_test_full'
|
|
8
|
+
if (!fs.existsSync(projectPath)) fs.mkdirSync(projectPath, { recursive: true })
|
|
9
|
+
fs.writeFileSync(projectPath + '/README.md', '# Full Suite')
|
|
10
|
+
fs.writeFileSync(projectPath + '/file.txt', 'content')
|
|
11
|
+
|
|
12
|
+
await callOnce({ tool: 'git-local', action: 'init', projectPath })
|
|
13
|
+
await callOnce({ tool: 'git-local', action: 'add', projectPath, args: { patterns: ['README.md', 'file.txt'] } })
|
|
14
|
+
await callOnce({ tool: 'git-local', action: 'commit', projectPath, args: { message: 'init' } })
|
|
15
|
+
|
|
16
|
+
log('git-remote.createRepo', await callOnce({ tool: 'git-remote', action: 'createRepo', projectPath }))
|
|
17
|
+
const rem = await callOnce({ tool: 'git-remote', action: 'ensureRemotes', projectPath })
|
|
18
|
+
log('git-remote.ensureRemotes', rem)
|
|
19
|
+
|
|
20
|
+
// Full mirror (push then contents fallback)
|
|
21
|
+
log('git-sync.mirror', await callOnce({ tool: 'git-sync', action: 'mirror', projectPath, args: { branch: 'master' } }))
|
|
22
|
+
|
|
23
|
+
// Repos metadata
|
|
24
|
+
log('git-repos.get', await callOnce({ tool: 'git-repos', action: 'get', projectPath }))
|
|
25
|
+
log('git-repos.patch', await callOnce({ tool: 'git-repos', action: 'patch', projectPath, args: { description: 'Updated by full suite' } }))
|
|
26
|
+
log('git-repos.languages', await callOnce({ tool: 'git-repos', action: 'languages', projectPath }))
|
|
27
|
+
log('git-repos.tags', await callOnce({ tool: 'git-repos', action: 'tags', projectPath }))
|
|
28
|
+
log('git-repos.topics-put', await callOnce({ tool: 'git-repos', action: 'topics-put', projectPath, args: { topics: ['mcp','git'] } }))
|
|
29
|
+
log('git-repos.subscription-get', await callOnce({ tool: 'git-repos', action: 'subscription-get', projectPath }))
|
|
30
|
+
log('git-repos.subscription-put', await callOnce({ tool: 'git-repos', action: 'subscription-put', projectPath }))
|
|
31
|
+
log('git-repos.subscription-delete', await callOnce({ tool: 'git-repos', action: 'subscription-delete', projectPath }))
|
|
32
|
+
|
|
33
|
+
// Contents
|
|
34
|
+
log('git-contents.create', await callOnce({ tool: 'git-contents', action: 'create', projectPath, args: { path: 'api.txt', content: Buffer.from('hello').toString('base64'), message: 'add api', branch: 'master' } }))
|
|
35
|
+
log('git-contents.get', await callOnce({ tool: 'git-contents', action: 'get', projectPath, args: { path: 'api.txt' } }))
|
|
36
|
+
|
|
37
|
+
// Commits & branches
|
|
38
|
+
log('git-commits.branches', await callOnce({ tool: 'git-commits', action: 'branches', projectPath }))
|
|
39
|
+
log('git-commits.create-branch', await callOnce({ tool: 'git-commits', action: 'create-branch', projectPath, args: { name: 'dev', from: 'master' } }))
|
|
40
|
+
log('git-commits.branch-protections', await callOnce({ tool: 'git-commits', action: 'branch-protections', projectPath }))
|
|
41
|
+
const refs = await callOnce({ tool: 'git-commits', action: 'refs', projectPath })
|
|
42
|
+
log('git-commits.refs', refs)
|
|
43
|
+
let sha
|
|
44
|
+
try { const ghRefs = Array.isArray(refs) ? refs[1] : refs; if (Array.isArray(ghRefs)) { const head = ghRefs.find(r => r?.ref?.endsWith('master') || r?.ref?.endsWith('main')); sha = head?.object?.sha } } catch {}
|
|
45
|
+
|
|
46
|
+
// Issues & PRs & labels & milestones
|
|
47
|
+
log('git-issues-prs.labels-create', await callOnce({ tool: 'git-issues-prs', action: 'labels-create', projectPath, args: { name: 'bug', color: 'ff0000' } }))
|
|
48
|
+
const issue = await callOnce({ tool: 'git-issues-prs', action: 'issue-create', projectPath, args: { title: 'Issue Full', body: 'Body' } })
|
|
49
|
+
log('git-issues-prs.issue-create', issue)
|
|
50
|
+
const issueNum = Array.isArray(issue) ? (issue[1]?.number || issue[0]?.number) : issue?.number
|
|
51
|
+
if (issueNum) {
|
|
52
|
+
log('git-issues-prs.issue-comment', await callOnce({ tool: 'git-issues-prs', action: 'issue-comment', projectPath, args: { number: issueNum, comment: 'Comment' } }))
|
|
53
|
+
log('git-issues-prs.issue-labels', await callOnce({ tool: 'git-issues-prs', action: 'issue-labels', projectPath, args: { number: issueNum, labels: ['bug'] } }))
|
|
54
|
+
}
|
|
55
|
+
log('git-issues-prs.milestones-create', await callOnce({ tool: 'git-issues-prs', action: 'milestones-create', projectPath, args: { title: 'v1.0' } }))
|
|
56
|
+
log('git-issues-prs.pr-create', await callOnce({ tool: 'git-issues-prs', action: 'pr-create', projectPath, args: { title: 'PR Full', head: 'dev', base: 'master' } }))
|
|
57
|
+
|
|
58
|
+
// Releases
|
|
59
|
+
log('git-releases.create', await callOnce({ tool: 'git-releases', action: 'create', projectPath, args: { tag: 'v1.0.0', title: 'v1.0.0', body: 'Desc' } }))
|
|
60
|
+
|
|
61
|
+
// Actions (GitHub)
|
|
62
|
+
log('git-actions.workflows', await callOnce({ tool: 'git-actions', action: 'workflows', projectPath }))
|
|
63
|
+
log('git-actions.runs', await callOnce({ tool: 'git-actions', action: 'runs', projectPath }))
|
|
64
|
+
|
|
65
|
+
// Activity
|
|
66
|
+
log('git-activity.notifications-get', await callOnce({ tool: 'git-activity', action: 'notifications-get', projectPath }))
|
|
67
|
+
log('git-activity.events', await callOnce({ tool: 'git-activity', action: 'events', projectPath }))
|
|
68
|
+
|
|
69
|
+
// Search
|
|
70
|
+
log('git-search.repos', await callOnce({ tool: 'git-search', action: 'repos', projectPath }))
|
|
71
|
+
log('git-search.users', await callOnce({ tool: 'git-search', action: 'users', projectPath }))
|
|
72
|
+
|
|
73
|
+
// Git Data (GitHub)
|
|
74
|
+
if (sha) {
|
|
75
|
+
log('git-checks.status', await callOnce({ tool: 'git-checks', action: 'status', projectPath, args: { sha, state: 'success', context: 'full-suite' } }))
|
|
76
|
+
log('git-deployments.create', await callOnce({ tool: 'git-deployments', action: 'create', projectPath }))
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Misc
|
|
80
|
+
log('git-misc.version', await callOnce({ tool: 'git-misc', action: 'version', projectPath }))
|
|
81
|
+
log('git-misc.markdown', await callOnce({ tool: 'git-misc', action: 'markdown', projectPath, args: { text: '# Hello' } }))
|
|
82
|
+
|
|
83
|
+
// Gists (GitHub)
|
|
84
|
+
const gist = await callOnce({ tool: 'git-gists', action: 'create', projectPath, args: { description: 'Full', public: false, files: { 't.txt': { content: 'x' } } } })
|
|
85
|
+
log('git-gists.create', gist)
|
|
86
|
+
const gid = gist?.id || gist?.[0]?.id || gist?.[1]?.id
|
|
87
|
+
if (gid) {
|
|
88
|
+
log('git-gists.star', await callOnce({ tool: 'git-gists', action: 'star', projectPath, args: { id: gid } }))
|
|
89
|
+
log('git-gists.delete', await callOnce({ tool: 'git-gists', action: 'delete', projectPath, args: { id: gid } }))
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Packages (Gitea)
|
|
93
|
+
log('git-packages.list', await callOnce({ tool: 'git-packages', action: 'list', projectPath }))
|
|
94
|
+
|
|
95
|
+
console.log('FULL SUITE DONE')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
main().catch(e => { console.error(e); process.exit(1) })
|
package/tests/run.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { callOnce } from '../src/server.js'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
const projectPath = process.env.TEST_PROJECT || 'Z:/MCP/GIT MCP/temp_git_mcp_test'
|
|
4
|
+
|
|
5
|
+
async function main() {
|
|
6
|
+
if (!fs.existsSync(projectPath)) fs.mkdirSync(projectPath, { recursive: true })
|
|
7
|
+
fs.writeFileSync(projectPath + '/README.md', 'Test')
|
|
8
|
+
const log = (name, res) => { console.log(name + ': ' + (res && res.ok === false ? 'ERR' : 'OK')) }
|
|
9
|
+
|
|
10
|
+
await callOnce({ tool: 'git-local', action: 'init', projectPath })
|
|
11
|
+
await callOnce({ tool: 'git-local', action: 'add', projectPath, args: { patterns: ['README.md'] } })
|
|
12
|
+
await callOnce({ tool: 'git-local', action: 'commit', projectPath, args: { message: 'init' } })
|
|
13
|
+
|
|
14
|
+
log('git-remote.createRepo', await callOnce({ tool: 'git-remote', action: 'createRepo', projectPath }))
|
|
15
|
+
const remotes = await callOnce({ tool: 'git-remote', action: 'ensureRemotes', projectPath })
|
|
16
|
+
log('git-remote.ensureRemotes', remotes)
|
|
17
|
+
await callOnce({ tool: 'git-local', action: 'addRemote', projectPath, args: { name: 'origin-gitea', url: remotes.gitea } })
|
|
18
|
+
await callOnce({ tool: 'git-local', action: 'addRemote', projectPath, args: { name: 'origin-github', url: remotes.github } })
|
|
19
|
+
|
|
20
|
+
log('git-local.push(github)', await callOnce({ tool: 'git-local', action: 'push', projectPath, args: { url: remotes.github, branch: 'master' } }))
|
|
21
|
+
|
|
22
|
+
const calls = [
|
|
23
|
+
{ tool: 'git-repos', action: 'get' },
|
|
24
|
+
{ tool: 'git-repos', action: 'languages' },
|
|
25
|
+
{ tool: 'git-repos', action: 'tags' },
|
|
26
|
+
{ tool: 'git-repos', action: 'topics-put', args: { topics: ['test'] } },
|
|
27
|
+
{ tool: 'git-contents', action: 'create', args: { path: 'test.txt', content: Buffer.from('Hello').toString('base64'), message: 'Add file', branch: 'master' } },
|
|
28
|
+
{ tool: 'git-contents', action: 'get', args: { path: 'test.txt' } },
|
|
29
|
+
{ tool: 'git-commits', action: 'branches' },
|
|
30
|
+
{ tool: 'git-commits', action: 'create-branch', args: { name: 'dev', from: 'main' } },
|
|
31
|
+
{ tool: 'git-issues-prs', action: 'labels-create', args: { name: 'bug', color: 'ff0000' } },
|
|
32
|
+
{ tool: 'git-issues-prs', action: 'issue-create', args: { title: 'Test Issue', body: 'Body' } },
|
|
33
|
+
{ tool: 'git-releases', action: 'create', args: { tag: 'v1.0.0', title: 'v1.0.0', body: 'Release' } },
|
|
34
|
+
{ tool: 'git-actions', action: 'workflows' },
|
|
35
|
+
{ tool: 'git-activity', action: 'notifications-get' },
|
|
36
|
+
{ tool: 'git-search', action: 'repos-gitea' },
|
|
37
|
+
{ tool: 'git-misc', action: 'version' }
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
for (const c of calls) {
|
|
41
|
+
const res = await callOnce({ tool: c.tool, action: c.action, projectPath, args: c.args })
|
|
42
|
+
log(`${c.tool}.${c.action}`, res)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Mirror fallback via contents
|
|
46
|
+
await callOnce({ tool: 'git-sync', action: 'mirror', projectPath, args: { branch: 'master' } })
|
|
47
|
+
console.log('DONE')
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
main().catch(e => { console.error(e); process.exit(1) })
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 Andre Buzeli
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/dist/index.d.ts
DELETED