Skip to content

Commit 3d38fd6

Browse files
authored
feat: check all remotes for codacy info (#48)
* feat: check all remotes for codacy info * cover all scenarios
1 parent 3c4445c commit 3d38fd6

5 files changed

Lines changed: 83 additions & 73 deletions

File tree

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,7 @@ codacy-vscode-extension-CHANGELOG.txt
2929
!.vscode/tasks.json
3030
!.vscode/settings.json
3131
!.vscode/launch.json
32-
!.vscode/extensions.json
32+
!.vscode/extensions.json
33+
34+
#Ignore cursor AI rules
35+
.cursor/rules/codacy.mdc

package.json

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,6 @@
3939
"icon": "resources/icons/codacy-logo.svg",
4040
"when": "Codacy:RepositoryManagerStateContext == NeedsAuthentication"
4141
},
42-
{
43-
"id": "codacy:mcp",
44-
"name": "Codacy MCP Server",
45-
"when": "Codacy:RepositoryManagerStateContext != NeedsAuthentication && codacy:supportsMCP",
46-
"icon": "$(gear)",
47-
"initialSize": 2
48-
},
4942
{
5043
"id": "codacy:prSummary",
5144
"name": "Pull request",
@@ -73,7 +66,14 @@
7366
"icon": "$(library)",
7467
"when": "Codacy:RepositoryManagerStateContext == NoRepository || Codacy:RepositoryManagerStateContext == NoRemote || Codacy:RepositoryManagerStateContext == Initializing || (Codacy:RepositoryManagerStateContext == Loaded && Codacy:PullRequestStateContext == NoPullRequest)",
7568
"initialSize": 1
76-
}
69+
},
70+
{
71+
"id": "codacy:mcp",
72+
"name": "Codacy MCP Server",
73+
"when": "Codacy:RepositoryManagerStateContext != NeedsAuthentication && codacy:supportsMCP",
74+
"icon": "$(gear)",
75+
"initialSize": 2
76+
}
7777
]
7878
},
7979
"viewsWelcome": [
@@ -82,16 +82,6 @@
8282
"contents": "You have not yet signed in with Codacy\n[Sign in](command:codacy.signIn)",
8383
"when": "Codacy:RepositoryManagerStateContext == NeedsAuthentication"
8484
},
85-
{
86-
"view": "codacy:mcp",
87-
"contents": "Enable your AI Chat to talk to Codacy's Cloud API \n[Add Codacy MCP Server](command:codacy.configureMCP)",
88-
"when": "Codacy:RepositoryManagerStateContext != NeedsAuthentication && codacy:supportsMCP && !codacy:mcpConfigured"
89-
},
90-
{
91-
"view": "codacy:mcp",
92-
"contents": "MCP Server is enabled\n[Reset MCP Server](command:codacy.configureMCP.reset)",
93-
"when": "Codacy:RepositoryManagerStateContext != NeedsAuthentication && codacy:supportsMCP && codacy:mcpConfigured"
94-
},
9585
{
9686
"view": "codacy:statuses",
9787
"contents": "No repositories open.",
@@ -111,7 +101,17 @@
111101
"view": "codacy:statuses",
112102
"contents": "No open pull request found.\n[Try again](command:codacy.pr.load)",
113103
"when": "Codacy:RepositoryManagerStateContext == Loaded && Codacy:PullRequestStateContext == NoPullRequest"
114-
}
104+
},
105+
{
106+
"view": "codacy:mcp",
107+
"contents": "Enable your AI Chat to talk to Codacy's Cloud API \n[Add Codacy MCP Server](command:codacy.configureMCP)",
108+
"when": "Codacy:RepositoryManagerStateContext == Loaded && codacy:supportsMCP && !codacy:mcpConfigured"
109+
},
110+
{
111+
"view": "codacy:mcp",
112+
"contents": "MCP Server is enabled\n[Reset MCP Server](command:codacy.configureMCP.reset)",
113+
"when": "Codacy:RepositoryManagerStateContext == Loaded && codacy:supportsMCP && codacy:mcpConfigured"
114+
}
115115
],
116116
"commands": [
117117
{
@@ -193,23 +193,13 @@
193193
"command": "codacy.configureMCP",
194194
"title": "Configure Codacy MCP Server",
195195
"category": "Codacy commands",
196-
"when": "Codacy:RepositoryManagerStateContext != NeedsAuthentication && codacy:supportsMCP && !codacy:mcpConfigured"
196+
"when": "Codacy:RepositoryManagerStateContext == Loaded && codacy:supportsMCP && !codacy:mcpConfigured"
197197
},
198198
{
199199
"command": "codacy.configureMCP.reset",
200200
"title": "Reset Codacy MCP Server",
201201
"category": "Codacy commands",
202-
"when": "Codacy:RepositoryManagerStateContext != NeedsAuthentication && codacy:supportsMCP && codacy:mcpConfigured"
203-
},
204-
{
205-
"command": "codacy.configureMCP",
206-
"title": "Configure Codacy MCP Server",
207-
"when": "Codacy:RepositoryManagerStateContext != NeedsAuthentication && codacy:supportsMCP && !codacy:mcpConfigured"
208-
},
209-
{
210-
"command": "codacy.configureMCP.reset",
211-
"title": "Reset Codacy MCP Server configuration",
212-
"when": "Codacy:RepositoryManagerStateContext != NeedsAuthentication && codacy:supportsMCP && !codacy:mcpConfigured"
202+
"when": "Codacy:RepositoryManagerStateContext == Loaded && codacy:supportsMCP && codacy:mcpConfigured"
213203
}
214204
],
215205
"menus": {
@@ -228,11 +218,11 @@
228218
},
229219
{
230220
"command": "codacy.configureMCP",
231-
"when": "Codacy:RepositoryManagerStateContext != NeedsAuthentication && codacy:supportsMCP && !codacy:mcpConfigured"
221+
"when": "Codacy:RepositoryManagerStateContext == Loaded && codacy:supportsMCP && !codacy:mcpConfigured"
232222
},
233223
{
234224
"command": "codacy.configureMCP.reset",
235-
"when": "Codacy:RepositoryManagerStateContext != NeedsAuthentication && codacy:supportsMCP && codacy:mcpConfigured"
225+
"when": "Codacy:RepositoryManagerStateContext == Loaded && codacy:supportsMCP && codacy:mcpConfigured"
236226
}
237227
],
238228
"view/title": [

src/commands/configureMCP.ts

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as path from 'path'
44
import * as os from 'os'
55
import { Config } from '../common/config'
66
import { get, set } from 'lodash'
7-
import { parseGitRemote } from '../common/parseGitRemote'
7+
import { Repository } from '../api/client'
88

99
interface Rule {
1010
when: string
@@ -106,20 +106,10 @@ const addRulesToGitignore = (rulesPath: string) => {
106106
vscode.window.showInformationMessage('Created .gitignore and added rules path')
107107
}
108108
}
109-
export async function createRules() {
110-
// Get git info
111-
const git = vscode.extensions.getExtension('vscode.git')?.exports.getAPI(1)
112-
const repo = git?.repositories[0]
113-
let provider, organization, repository
114-
115-
if (repo?.state.remotes[0]?.pushUrl) {
116-
const gitInfo = parseGitRemote(repo.state.remotes[0].pushUrl)
117-
provider = gitInfo.provider
118-
organization = gitInfo.organization
119-
repository = gitInfo.repository
120-
}
109+
export async function createRules(repository: Repository) {
110+
const { provider, owner: organization, name } = repository
121111

122-
const newRules = newRulesTemplate(provider, organization, repository)
112+
const newRules = newRulesTemplate(provider, organization, name)
123113

124114
try {
125115
const { path: rulesPath, format } = getCorrectRulesInfo()
@@ -229,7 +219,7 @@ export function isMCPConfigured(): boolean {
229219
}
230220
}
231221

232-
export async function configureMCP() {
222+
export async function configureMCP(repository: Repository) {
233223
const ideConfig = getCorrectMcpConfig()
234224
try {
235225
const apiToken = Config.apiToken
@@ -278,7 +268,7 @@ export async function configureMCP() {
278268
fs.writeFileSync(filePath, JSON.stringify(modifiedConfig, null, 2))
279269

280270
vscode.window.showInformationMessage('Codacy MCP server added successfully')
281-
await createRules()
271+
await createRules(repository)
282272
} catch (error: unknown) {
283273
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
284274
vscode.window.showErrorMessage(`Failed to configure MCP server: ${errorMessage}`)

src/extension.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,22 +192,30 @@ export async function activate(context: vscode.ExtensionContext) {
192192
// Register configure command
193193
context.subscriptions.push(
194194
vscode.commands.registerCommand('codacy.configureMCP', async () => {
195-
await configureMCP()
196-
updateMCPState()
195+
const repository = repositoryManager.repository
196+
if (repository) {
197+
await configureMCP(repository)
198+
updateMCPState()
199+
}
197200
})
198201
)
199202

200203
// Register reset command
201204
context.subscriptions.push(
202205
vscode.commands.registerCommand('codacy.configureMCP.reset', async () => {
203-
await configureMCP()
204-
updateMCPState()
206+
const repository = repositoryManager.repository
207+
if (repository) {
208+
await configureMCP(repository)
209+
updateMCPState()
210+
}
205211
})
206212
)
207213

208-
if (isMCPConfigured()) {
209-
await createRules()
210-
}
214+
repositoryManager.onDidLoadRepository(async ({ repository }) => {
215+
if (isMCPConfigured()) {
216+
await createRules(repository)
217+
}
218+
})
211219
}
212220

213221
// This method is called when your extension is deactivated

src/git/RepositoryManager.ts

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -85,47 +85,66 @@ export class RepositoryManager implements vscode.Disposable {
8585
if (gitRepository.state.HEAD === undefined) {
8686
this.state = RepositoryManagerState.Initializing
8787
} else {
88-
if (!gitRepository.state.remotes[0]?.pushUrl) {
88+
const remotesWithPushUrl = gitRepository.state.remotes.filter((remote) => remote.pushUrl)
89+
90+
if (remotesWithPushUrl.length === 0) {
8991
this.state = RepositoryManagerState.NoRemote
9092
Logger.error('No remote found')
9193
return
9294
}
9395

94-
const repo = parseGitRemote(gitRepository.state.remotes[0].pushUrl)
96+
let remoteIdx = 0
97+
this._repository = undefined
9598

96-
// load repository information
97-
const { data } = await Api.Analysis.getRepositoryWithAnalysis(
98-
repo.provider,
99-
repo.organization,
100-
repo.repository
101-
)
99+
while (this._repository === undefined && remoteIdx < remotesWithPushUrl.length) {
100+
const repo = parseGitRemote(remotesWithPushUrl[remoteIdx].pushUrl!)
101+
102+
try {
103+
// load repository information
104+
const { data } = await Api.Analysis.getRepositoryWithAnalysis(
105+
repo.provider,
106+
repo.organization,
107+
repo.repository
108+
)
109+
110+
this._repository = data
111+
} catch {
112+
remoteIdx++
113+
}
114+
}
102115

103-
const { data: organization } = await Api.Organization.getOrganization(repo.provider, repo.organization)
116+
if (this._repository === undefined) {
117+
this.state = RepositoryManagerState.NoRepository
118+
Logger.error('No repository found')
119+
return
120+
}
121+
122+
const { name: repository, owner, provider } = this._repository.repository
123+
124+
const { data: organization } = await Api.Organization.getOrganization(provider, owner)
104125
this._organization = organization
105126

106127
// does the repository have coverage data?
107128
const {
108129
data: { hasCoverageOverview },
109-
} = await Api.Repository.listCoverageReports(repo.provider, repo.organization, repo.repository)
130+
} = await Api.Repository.listCoverageReports(provider, owner, repository)
110131

111132
// get all branches
112133
const { data: enabledBranches } = await Api.Repository.listRepositoryBranches(
113-
repo.provider,
114-
repo.organization,
115-
repo.repository,
134+
provider,
135+
owner,
136+
repository,
116137
true
117138
)
118139

119-
this._repository = data
120-
121140
this._expectCoverage = hasCoverageOverview
122141
this._enabledBranches = enabledBranches
123142

124143
this._disposables.push(this._current.state.onDidChange(this.handleStateChange.bind(this)))
125144

126145
this.state = RepositoryManagerState.Loaded
127146

128-
this._onDidLoadRepository.fire(data)
147+
this._onDidLoadRepository.fire(this._repository)
129148

130149
await this.handleBranchChange()
131150
}

0 commit comments

Comments
 (0)