Skip to content

Commit fa8c160

Browse files
alerizzoCopilot
andauthored
clean: improve overall UX (#86)
* clean: improve overall UX * Update src/extension.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix copilots suggestion * PR review improvements * go to cli specific settings --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent d421691 commit fa8c160

5 files changed

Lines changed: 105 additions & 42 deletions

File tree

package.json

Lines changed: 63 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -45,26 +45,12 @@
4545
"codacy-main": [
4646
{
4747
"id": "codacy:statuses",
48-
"name": "Status",
48+
"name": "Codacy Cloud",
4949
"icon": "$(library)",
5050
"when": "!codacy:hasProject || Codacy:RepositoryManagerStateContext == NeedsAuthentication ||Codacy:RepositoryManagerStateContext == NoRepository || Codacy:RepositoryManagerStateContext == NoRemote || Codacy:RepositoryManagerStateContext == Initializing || (Codacy:RepositoryManagerStateContext == Loaded && Codacy:PullRequestStateContext == NoPullRequest)",
5151
"initialSize": 1,
5252
"collapsed": false
5353
},
54-
{
55-
"id": "codacy:cli",
56-
"name": "Codacy CLI",
57-
"when": "codacy:hasProject && ((!codacy:cliInstalled && codacy:canInstallCLI) || codacy:windowsDetected)",
58-
"icon": "$(gear)",
59-
"initialSize": 2
60-
},
61-
{
62-
"id": "codacy:mcp",
63-
"name": "Codacy MCP Server",
64-
"when": "codacy:hasProject && codacy:supportsMCP",
65-
"icon": "$(gear)",
66-
"initialSize": 2
67-
},
6854
{
6955
"id": "codacy:prSummary",
7056
"name": "Pull request",
@@ -86,12 +72,28 @@
8672
"icon": "$(bug)",
8773
"initialSize": 3
8874
},
75+
{
76+
"id": "codacy:mcp",
77+
"name": "AI Guardrails",
78+
"when": "codacy:hasProject && codacy:supportsMCP",
79+
"icon": "$(gear)",
80+
"initialSize": 2
81+
},
82+
{
83+
"id": "codacy:cli",
84+
"name": "Local Analysis",
85+
"when": "codacy:hasProject && ((!codacy:cliInstalled && codacy:canInstallCLI) || codacy:windowsDetected)",
86+
"icon": "$(gear)",
87+
"initialSize": 2
88+
},
8989
{
9090
"id": "codacy:support",
9191
"name": "Chat with us",
9292
"icon": "$(question)",
93-
"collapsed": false
93+
"collapsed": false,
94+
"initialSize": 1
9495
}
96+
9597
]
9698
},
9799
"viewsWelcome": [
@@ -101,18 +103,18 @@
101103
},
102104
{
103105
"view": "codacy:statuses",
104-
"contents": "You are not connected to Codacy.\n[Connect to Codacy](command:codacy.signIn)",
106+
"contents": "You are not connected to Codacy. Connect to Codacy to customize your rules and scan every PR before it gets merged.\n[Connect to Codacy](command:codacy.signIn)\n\nGet access to all features: coverage, DAST, SCA scanning, and more. [Learn more about Codacy](https://www.codacy.com/)",
105107
"when": "codacy:hasProject && Codacy:RepositoryManagerStateContext == NeedsAuthentication"
106108
},
107109
{
108110
"view": "codacy:statuses",
109-
"contents": "There is no project opened. Open a project to use Codacy extension.",
111+
"contents": "No project is open. Open a project to use the Codacy extension.",
110112
"when": "!codacy:hasProject"
111113
},
112114
{
113115
"view": "codacy:statuses",
114116
"contents": "This project isn't a Git repository. To connect it to Codacy, initialize a Git repository first.",
115-
"when": "!codacy:isGitRepository && codacy:hasProject"
117+
"when": "!codacy:isGitRepository && codacy:hasProject && Codacy:RepositoryManagerStateContext != NeedsAuthentication"
116118
},
117119
{
118120
"view": "codacy:statuses",
@@ -135,29 +137,59 @@
135137
"when": "codacy:hasProject && codacy:isGitRepository && Codacy:RepositoryManagerStateContext == Loaded && Codacy:PullRequestStateContext == NoPullRequest"
136138
},
137139
{
138-
"view": "codacy:cli",
139-
"contents": "Install Codacy CLI to analyze your code locally\n[Install Codacy CLI](command:codacy.installCLI)",
140-
"when": "!codacy:cliInstalled && codacy:canInstallCLI && !codacy:cliInstalling "
140+
"view": "codacy:mcp",
141+
"contents": "Control your AI generated code with [Codacy Guardrails](https://www.codacy.com/guardrails/).\n[Install Guardrails](command:codacy.configureGuardrails)\n\nGets everything set up by installing Codacy CLI, setting up Codacy MCP Server, and adding the necessary agent rules files.\n\nYou can also choose to [only install the MCP Server](command:codacy.configureMCP)",
142+
"when": "codacy:supportsMCP && !codacy:mcpConfigured && !codacy:cliInstalled && codacy:canInstallCLI && !codacy:cliInstalling"
141143
},
142144
{
143-
"view": "codacy:cli",
144-
"contents": "Codacy CLI is only available on Windows via WSL. Make sure you install the WSL extension and start a WSL window.",
145-
"when": "codacy:windowsDetected"
145+
"view": "codacy:mcp",
146+
"contents": "Set up Codacy MCP Server to get access to Codacy information from your agent.\n[Install MCP Server](command:codacy.configureMCP)\n\nTo control your AI generated code with [Codacy Guardrails](https://www.codacy.com/guardrails/), you need to be able to install the Codacy CLI (macOS, Linus, or Windows via WSL).",
147+
"when": "codacy:supportsMCP && !codacy:mcpConfigured && !codacy:canInstallCLI"
146148
},
147149
{
148-
"view": "codacy:cli",
149-
"contents": "$(loading~spin) Installing Codacy CLI...",
150-
"when": "!codacy:cliInstalled && codacy:canInstallCLI && codacy:cliInstalling"
150+
"view": "codacy:mcp",
151+
"contents": "Control your AI generated code with [Codacy Guardrails](https://www.codacy.com/guardrails/). Install the missing components to get started.",
152+
"when": "(codacy:supportsMCP && !codacy:mcpConfigured && codacy:cliInstalled) || (!codacy:cliInstalled && codacy:canInstallCLI && !codacy:cliInstalling && codacy:mcpConfigured)"
151153
},
152154
{
153155
"view": "codacy:mcp",
154-
"contents": "Enable your AI Agent to interact with Codacy Guardrails \n[Add Codacy MCP Server](command:codacy.configureMCP)",
155-
"when": "codacy:supportsMCP && !codacy:mcpConfigured"
156+
"contents": "Control your AI generated code with [Codacy Guardrails](https://www.codacy.com/guardrails/).",
157+
"when": "codacy:supportsMCP && codacy:mcpConfigured && codacy:canInstallCLI && codacy:cliInstalled"
156158
},
157159
{
158160
"view": "codacy:mcp",
159-
"contents": "Codacy Guardrails MCP Server is enabled\n[Reset MCP Server](command:codacy.configureMCP.reset)",
161+
"contents": "$(check) Codacy MCP Server is set up. [Reset MCP Server](command:codacy.configureMCP.reset)",
160162
"when": "codacy:supportsMCP && codacy:mcpConfigured"
163+
},
164+
{
165+
"view": "codacy:mcp",
166+
"contents": "$(warning) MCP Server not found. [Install MCP Server](command:codacy.configureMCP)",
167+
"when": "codacy:supportsMCP && !codacy:mcpConfigured && codacy:cliInstalled && !codacy:cliInstalling"
168+
},
169+
{
170+
"view": "codacy:mcp",
171+
"contents": "$(check) Codacy CLI is installed. [Go to settings](command:workbench.action.openSettings?%22@ext:codacy-app.codacy%20cli%22).",
172+
"when": "codacy:canInstallCLI && codacy:cliInstalled"
173+
},
174+
{
175+
"view": "codacy:mcp",
176+
"contents": "$(warning) Codacy CLI not found. [Install CLI](command:codacy.installCLI)",
177+
"when": "codacy:supportsMCP && codacy:mcpConfigured && !codacy:cliInstalled && codacy:canInstallCLI && !codacy:cliInstalling"
178+
},
179+
{
180+
"view": "codacy:cli",
181+
"contents": "Install Codacy CLI to analyze your code locally and get instant feedback as you type.\n[Install Codacy CLI](command:codacy.installCLI)\n\nSets everything up in your IDE so you're ready to go, including any dependencies you need (like Node, Python, or Java). Customize how it works in the [extension settings](command:workbench.action.openSettings?%22@ext:codacy-app.codacy%20cli%22).",
182+
"when": "!codacy:cliInstalled && codacy:canInstallCLI && !codacy:cliInstalling"
183+
},
184+
{
185+
"view": "codacy:cli",
186+
"contents": "Codacy CLI is only available on Windows via WSL. Make sure you install the WSL extension and start a WSL window.",
187+
"when": "codacy:windowsDetected"
188+
},
189+
{
190+
"view": "codacy:cli",
191+
"contents": "$(loading~spin) Installing Codacy CLI...",
192+
"when": "!codacy:cliInstalled && codacy:canInstallCLI && codacy:cliInstalling"
161193
}
162194
],
163195
"commands": [
@@ -326,10 +358,6 @@
326358
"type": "object",
327359
"title": "Codacy",
328360
"properties": {
329-
"codacy.apiToken": {
330-
"type": "string",
331-
"description": "API Personal Token"
332-
},
333361
"codacy.guardrails.analyzeGeneratedCode": {
334362
"type": "string",
335363
"title": "Automatically analyze generated code with Codacy Guardrails",

src/commands/configureMCP.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,11 @@ export function isMCPConfigured(): boolean {
254254
}
255255
}
256256

257+
export async function configureGuardrails(repository?: Repository) {
258+
await installCodacyCLI(repository)
259+
await configureMCP(repository)
260+
}
261+
257262
export async function configureMCP(repository?: Repository) {
258263
const generateRules = vscode.workspace.getConfiguration().get('codacy.guardrails.rulesFile')
259264
const ideConfig = getCorrectMcpConfig()
@@ -305,9 +310,14 @@ export async function configureMCP(repository?: Repository) {
305310
if (generateRules === 'enabled') {
306311
await createRules(repository)
307312
}
308-
await installCodacyCLI(repository)
309313
} catch (error: unknown) {
310314
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
311315
vscode.window.showErrorMessage(`Failed to configure MCP server: ${errorMessage}`)
312316
}
313317
}
318+
319+
export async function updateMCPConfig(repository?: Repository) {
320+
if (isMCPConfigured()) {
321+
await configureMCP(repository)
322+
}
323+
}

src/commands/installAnalysisCLI.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const execAsync = (command: string) => {
1717
const workspacePath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || ''
1818
const cliVersion = vscode.workspace.getConfiguration().get('codacy.cli.cliVersion')
1919

20-
return new Promise((resolve, reject) => {
20+
return new Promise<{ stdout: string; stderr: string }>((resolve, reject) => {
2121
exec(
2222
`${cliVersion ? `CODACY_CLI_V2_VERSION=${cliVersion}` : ''} ${command}`,
2323
{

src/extension.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ import { Account } from './codacy/Account'
1818
import Telemetry from './common/telemetry'
1919
import { decorateWithCoverage } from './views/coverage'
2020
import { APIState, Repository as GitRepository } from './git/git'
21-
import { configureMCP, createRules, isMCPConfigured } from './commands/configureMCP'
21+
import {
22+
configureGuardrails,
23+
configureMCP,
24+
createRules,
25+
isMCPConfigured,
26+
updateMCPConfig,
27+
} from './commands/configureMCP'
2228
import { installCodacyCLI, isCLIInstalled, updateCodacyCLI } from './commands/installAnalysisCLI'
2329

2430
/**
@@ -31,6 +37,7 @@ const registerCommands = async (context: vscode.ExtensionContext, repositoryMana
3137
'codacy.signOut': () => {
3238
Config.storeApiToken(undefined)
3339
Account.clear()
40+
repositoryManager.clear()
3441
},
3542
'codacy.pr.load': () => repositoryManager.loadPullRequest(),
3643
'codacy.pr.refresh': () => repositoryManager.pullRequest?.refresh(),
@@ -180,6 +187,11 @@ export async function activate(context: vscode.ExtensionContext) {
180187
if (gitProvider?.repositories.length) {
181188
repositoryManager.open(gitProvider.repositories[0])
182189
}
190+
191+
Logger.appendLine('Updating MCP config')
192+
193+
// Update MCP config now that we have a token and perhaps a repository
194+
updateMCPConfig(repositoryManager.repository)
183195
})
184196
)
185197

@@ -221,15 +233,16 @@ export async function activate(context: vscode.ExtensionContext) {
221233
const updateCLIState = async () => {
222234
const cliInstalled = await isCLIInstalled()
223235
vscode.commands.executeCommand('setContext', 'codacy:cliInstalled', cliInstalled)
236+
237+
return cliInstalled
224238
}
225239

226-
const cliInstalled = await isCLIInstalled()
240+
const cliInstalled = await updateCLIState()
227241
const analysisMode = vscode.workspace.getConfiguration().get('codacy.cli.analysisMode')
228242
const cliVersion = vscode.workspace.getConfiguration().get('codacy.cli.cliVersion')
229243
// When the user doesn't have a specific version, update the CLI to the latest version
230244
if (!cliVersion && cliInstalled && analysisMode !== 'disabled') {
231245
await updateCodacyCLI(repositoryManager.repository)
232-
await updateCLIState()
233246
// If it is not installed, don't do anything. On the next usage of the CLI it will be installed with the most recent version
234247
}
235248

@@ -269,7 +282,7 @@ export async function activate(context: vscode.ExtensionContext) {
269282
// Update initially
270283
updateMCPState()
271284

272-
// Register configure command
285+
// Register MCP Only command
273286
context.subscriptions.push(
274287
vscode.commands.registerCommand('codacy.configureMCP', async () => {
275288
const repository = repositoryManager.repository
@@ -278,6 +291,16 @@ export async function activate(context: vscode.ExtensionContext) {
278291
})
279292
)
280293

294+
// Register Guardrails command
295+
context.subscriptions.push(
296+
vscode.commands.registerCommand('codacy.configureGuardrails', async () => {
297+
const repository = repositoryManager.repository
298+
await configureGuardrails(repository)
299+
updateMCPState()
300+
await updateCLIState()
301+
})
302+
)
303+
281304
// Register reset command
282305
context.subscriptions.push(
283306
vscode.commands.registerCommand('codacy.configureMCP.reset', async () => {

src/views/ProblemsDiagnosticCollection.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,9 @@ export class ProblemsDiagnosticCollection implements vscode.Disposable {
186186
if (this._isAnalysisRunning) return
187187

188188
// Check for the presence of the .codacy/codacy.yaml file to know if the CLI is initialized
189-
const codacyConfigPath = path.join(this._repositoryManager.rootUri?.fsPath || '', '.codacy', 'codacy.yaml')
189+
const workspacePath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || ''
190+
const codacyConfigPath = path.join(workspacePath, '.codacy', 'codacy.yaml')
191+
190192
const codacyConfigExists =
191193
(await vscode.workspace.fs.stat(vscode.Uri.file(codacyConfigPath)).then(() => true)) || false
192194

0 commit comments

Comments
 (0)