opencode-sonarqube 2.0.0 → 2.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/index.js +86 -53
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4234,7 +4234,8 @@ async function deriveProjectKey(directory) {
|
|
|
4234
4234
|
return `project-${Date.now()}`;
|
|
4235
4235
|
}
|
|
4236
4236
|
function sanitizeProjectKey(input) {
|
|
4237
|
-
|
|
4237
|
+
const sanitized = input.toLowerCase().replaceAll(/[^a-z0-9-_]/g, "-").replaceAll(/-+/g, "-").replaceAll(/(?:^-)|(?:-$)/g, "").slice(0, 400);
|
|
4238
|
+
return sanitized || "project";
|
|
4238
4239
|
}
|
|
4239
4240
|
var configLogger, DEFAULT_CONFIG;
|
|
4240
4241
|
var init_config = __esm(() => {
|
|
@@ -4244,8 +4245,7 @@ var init_config = __esm(() => {
|
|
|
4244
4245
|
DEFAULT_CONFIG = {
|
|
4245
4246
|
level: "enterprise",
|
|
4246
4247
|
autoAnalyze: true,
|
|
4247
|
-
newCodeDefinition: "previous_version"
|
|
4248
|
-
sources: "src"
|
|
4248
|
+
newCodeDefinition: "previous_version"
|
|
4249
4249
|
};
|
|
4250
4250
|
});
|
|
4251
4251
|
|
|
@@ -4787,7 +4787,10 @@ class SonarQubeClient {
|
|
|
4787
4787
|
return this.request("/api/authentication/validate");
|
|
4788
4788
|
}
|
|
4789
4789
|
async getVersion() {
|
|
4790
|
-
const
|
|
4790
|
+
const url2 = buildUrl(this.baseUrl, "/api/server/version");
|
|
4791
|
+
const response = await fetch(url2, {
|
|
4792
|
+
headers: { Authorization: buildAuthHeader(this.auth) }
|
|
4793
|
+
});
|
|
4791
4794
|
return response.text();
|
|
4792
4795
|
}
|
|
4793
4796
|
async healthCheck() {
|
|
@@ -4987,10 +4990,8 @@ async function loadProjectState(directory) {
|
|
|
4987
4990
|
async function saveProjectState(directory, state) {
|
|
4988
4991
|
const stateDir = getStateDir(directory);
|
|
4989
4992
|
const statePath = getStatePath(directory);
|
|
4990
|
-
const
|
|
4991
|
-
|
|
4992
|
-
await Bun.write(`${stateDir}/.gitkeep`, "");
|
|
4993
|
-
}
|
|
4993
|
+
const { mkdir } = await import("node:fs/promises");
|
|
4994
|
+
await mkdir(stateDir, { recursive: true });
|
|
4994
4995
|
const content = JSON.stringify(state, null, 2);
|
|
4995
4996
|
await Bun.write(statePath, content);
|
|
4996
4997
|
logger5.info("Saved project state", { projectKey: state.projectKey });
|
|
@@ -19419,7 +19420,7 @@ function extractTaskId(output) {
|
|
|
19419
19420
|
return altMatch?.[1];
|
|
19420
19421
|
}
|
|
19421
19422
|
function sanitizeArgValue(value) {
|
|
19422
|
-
return value.replaceAll(/[
|
|
19423
|
+
return value.replaceAll(/[\n\r]/g, "");
|
|
19423
19424
|
}
|
|
19424
19425
|
async function runScanner(config3, state, options, directory) {
|
|
19425
19426
|
const dir = directory ?? process.cwd();
|
|
@@ -19459,7 +19460,7 @@ async function runScanner(config3, state, options, directory) {
|
|
|
19459
19460
|
stderr: "pipe",
|
|
19460
19461
|
env: {
|
|
19461
19462
|
...process.env,
|
|
19462
|
-
NODE_OPTIONS: "--max-old-space-size=4096
|
|
19463
|
+
NODE_OPTIONS: `${process.env["NODE_OPTIONS"] ?? ""} --max-old-space-size=4096`.trim()
|
|
19463
19464
|
}
|
|
19464
19465
|
});
|
|
19465
19466
|
const stdout = await new Response(proc.stdout).text();
|
|
@@ -19600,32 +19601,37 @@ function formatAnalysisResult(result) {
|
|
|
19600
19601
|
init_bootstrap();
|
|
19601
19602
|
init_logger();
|
|
19602
19603
|
var logger7 = new Logger("sonarqube-hooks");
|
|
19603
|
-
var editedFiles = new Set;
|
|
19604
|
-
var lastAnalysisTime = 0;
|
|
19605
19604
|
var ANALYSIS_COOLDOWN_MS = 5 * 60 * 1000;
|
|
19606
|
-
|
|
19605
|
+
function createHookState() {
|
|
19606
|
+
return {
|
|
19607
|
+
editedFiles: new Set,
|
|
19608
|
+
lastAnalysisTime: 0,
|
|
19609
|
+
bootstrapInProgress: false
|
|
19610
|
+
};
|
|
19611
|
+
}
|
|
19612
|
+
var activeState = createHookState();
|
|
19607
19613
|
function isAnalysisEnabled(config3) {
|
|
19608
19614
|
return config3 !== null && config3.level !== "off" && config3.autoAnalyze;
|
|
19609
19615
|
}
|
|
19610
|
-
function isInCooldown() {
|
|
19616
|
+
function isInCooldown(state) {
|
|
19611
19617
|
const now = Date.now();
|
|
19612
|
-
return now - lastAnalysisTime < ANALYSIS_COOLDOWN_MS;
|
|
19618
|
+
return now - state.lastAnalysisTime < ANALYSIS_COOLDOWN_MS;
|
|
19613
19619
|
}
|
|
19614
|
-
async function handleBootstrap(config3, directory) {
|
|
19615
|
-
if (bootstrapInProgress) {
|
|
19620
|
+
async function handleBootstrap(config3, directory, hookState) {
|
|
19621
|
+
if (hookState.bootstrapInProgress) {
|
|
19616
19622
|
logger7.debug("Bootstrap already in progress");
|
|
19617
19623
|
return;
|
|
19618
19624
|
}
|
|
19619
19625
|
logger7.info("First run detected - initializing SonarQube integration");
|
|
19620
|
-
bootstrapInProgress = true;
|
|
19626
|
+
hookState.bootstrapInProgress = true;
|
|
19621
19627
|
try {
|
|
19622
19628
|
const result = await bootstrap({ config: config3, directory });
|
|
19623
|
-
bootstrapInProgress = false;
|
|
19629
|
+
hookState.bootstrapInProgress = false;
|
|
19624
19630
|
return result.success ? formatBootstrapMessage(result) : `**SonarQube Setup Failed**
|
|
19625
19631
|
|
|
19626
19632
|
${result.message}`;
|
|
19627
19633
|
} catch (error45) {
|
|
19628
|
-
bootstrapInProgress = false;
|
|
19634
|
+
hookState.bootstrapInProgress = false;
|
|
19629
19635
|
logger7.error("Bootstrap failed", { error: String(error45) });
|
|
19630
19636
|
const errorMsg = error45 instanceof Error ? error45.message : String(error45);
|
|
19631
19637
|
return `**SonarQube Setup Error**
|
|
@@ -19633,7 +19639,7 @@ ${result.message}`;
|
|
|
19633
19639
|
${errorMsg}`;
|
|
19634
19640
|
}
|
|
19635
19641
|
}
|
|
19636
|
-
async function performAnalysis(config3, state, directory) {
|
|
19642
|
+
async function performAnalysis(config3, state, directory, hookState) {
|
|
19637
19643
|
const projectKey = state.projectKey;
|
|
19638
19644
|
const projectName = config3.projectName ?? projectKey;
|
|
19639
19645
|
const result = await runAnalysis(config3, state, {
|
|
@@ -19642,7 +19648,9 @@ async function performAnalysis(config3, state, directory) {
|
|
|
19642
19648
|
sources: config3.sources,
|
|
19643
19649
|
tests: config3.tests
|
|
19644
19650
|
}, directory);
|
|
19645
|
-
|
|
19651
|
+
if (result.success) {
|
|
19652
|
+
hookState.editedFiles.clear();
|
|
19653
|
+
}
|
|
19646
19654
|
return formatAnalysisOutput(result, config3);
|
|
19647
19655
|
}
|
|
19648
19656
|
function formatAnalysisOutput(result, config3) {
|
|
@@ -19667,7 +19675,7 @@ function formatActionPrompt(result, _config) {
|
|
|
19667
19675
|
|
|
19668
19676
|
**Action Required:** Found ${blockerCount} blocker(s) and ${criticalCount} critical issue(s). Please review and fix these issues before continuing.`;
|
|
19669
19677
|
}
|
|
19670
|
-
function createIdleHook(getConfig, getDirectory) {
|
|
19678
|
+
function createIdleHook(getConfig, getDirectory, hookState = activeState) {
|
|
19671
19679
|
return async function handleSessionIdle() {
|
|
19672
19680
|
const rawConfig = getConfig()?.["sonarqube"];
|
|
19673
19681
|
const config3 = loadConfig(rawConfig);
|
|
@@ -19676,25 +19684,25 @@ function createIdleHook(getConfig, getDirectory) {
|
|
|
19676
19684
|
}
|
|
19677
19685
|
const directory = getDirectory();
|
|
19678
19686
|
if (await needsBootstrap(directory)) {
|
|
19679
|
-
return handleBootstrap(config3, directory);
|
|
19687
|
+
return handleBootstrap(config3, directory, hookState);
|
|
19680
19688
|
}
|
|
19681
|
-
if (isInCooldown()) {
|
|
19689
|
+
if (isInCooldown(hookState)) {
|
|
19682
19690
|
logger7.debug("Skipping auto-analysis (cooldown)");
|
|
19683
19691
|
return;
|
|
19684
19692
|
}
|
|
19685
|
-
if (editedFiles.size === 0) {
|
|
19693
|
+
if (hookState.editedFiles.size === 0) {
|
|
19686
19694
|
logger7.debug("Skipping auto-analysis (no edited files)");
|
|
19687
19695
|
return;
|
|
19688
19696
|
}
|
|
19689
19697
|
logger7.info("Session idle - triggering auto-analysis");
|
|
19690
|
-
lastAnalysisTime = Date.now();
|
|
19698
|
+
hookState.lastAnalysisTime = Date.now();
|
|
19691
19699
|
try {
|
|
19692
19700
|
const state = await getProjectState(directory);
|
|
19693
19701
|
if (!state) {
|
|
19694
19702
|
logger7.warn("No project state found, cannot run analysis");
|
|
19695
19703
|
return;
|
|
19696
19704
|
}
|
|
19697
|
-
return await performAnalysis(config3, state, directory);
|
|
19705
|
+
return await performAnalysis(config3, state, directory, hookState);
|
|
19698
19706
|
} catch (error45) {
|
|
19699
19707
|
logger7.error(`Auto-analysis failed: ${error45}`);
|
|
19700
19708
|
return;
|
|
@@ -19732,22 +19740,26 @@ var IGNORED_FILE_PATTERNS = [
|
|
|
19732
19740
|
function shouldIgnoreFile(filePath) {
|
|
19733
19741
|
return IGNORED_FILE_PATTERNS.some((pattern) => pattern.test(filePath));
|
|
19734
19742
|
}
|
|
19735
|
-
function createFileEditedHook() {
|
|
19743
|
+
function createFileEditedHook(hookState = activeState) {
|
|
19736
19744
|
return function handleFileEdited(input) {
|
|
19737
19745
|
const { filePath } = input;
|
|
19738
19746
|
if (!shouldIgnoreFile(filePath)) {
|
|
19739
|
-
editedFiles.add(filePath);
|
|
19747
|
+
hookState.editedFiles.add(filePath);
|
|
19748
|
+
activeState = hookState;
|
|
19740
19749
|
logger7.debug(`Tracked edited file: ${filePath}`);
|
|
19741
19750
|
}
|
|
19742
19751
|
};
|
|
19743
19752
|
}
|
|
19744
19753
|
function getEditedFiles() {
|
|
19745
|
-
return Array.from(editedFiles);
|
|
19754
|
+
return Array.from(activeState.editedFiles);
|
|
19746
19755
|
}
|
|
19747
19756
|
function createHooks(getConfig, getDirectory) {
|
|
19757
|
+
const hookState = createHookState();
|
|
19758
|
+
activeState = hookState;
|
|
19748
19759
|
return {
|
|
19749
|
-
sessionIdle: createIdleHook(getConfig, getDirectory),
|
|
19750
|
-
fileEdited: createFileEditedHook()
|
|
19760
|
+
sessionIdle: createIdleHook(getConfig, getDirectory, hookState),
|
|
19761
|
+
fileEdited: createFileEditedHook(hookState),
|
|
19762
|
+
getEditedFiles: () => Array.from(hookState.editedFiles)
|
|
19751
19763
|
};
|
|
19752
19764
|
}
|
|
19753
19765
|
|
|
@@ -20495,21 +20507,19 @@ var SonarQubeToolArgsSchema = exports_external2.object({
|
|
|
20495
20507
|
});
|
|
20496
20508
|
async function executeSonarQubeTool(args, context) {
|
|
20497
20509
|
const directory = context.directory ?? process.cwd();
|
|
20498
|
-
const
|
|
20510
|
+
const rawConfig = context.config?.["sonarqube"] ?? context.config;
|
|
20511
|
+
const config3 = loadConfig(rawConfig);
|
|
20499
20512
|
if (!config3) {
|
|
20500
20513
|
return formatError2(ErrorMessages.configurationMissing("SonarQube configuration not found.", [
|
|
20501
|
-
"Set environment variables: SONAR_HOST_URL and
|
|
20514
|
+
"Set environment variables: SONAR_HOST_URL, SONAR_USER, and SONAR_PASSWORD",
|
|
20502
20515
|
"Or create a .sonarqube/config.json file in your project",
|
|
20503
20516
|
"Or add plugin configuration in opencode.json"
|
|
20504
20517
|
]) + `
|
|
20505
20518
|
|
|
20506
20519
|
Required environment variables:
|
|
20507
20520
|
- SONAR_HOST_URL (e.g., https://sonarqube.company.com)
|
|
20508
|
-
-
|
|
20509
|
-
|
|
20510
|
-
Optional:
|
|
20511
|
-
- SONAR_USER
|
|
20512
|
-
- SONAR_PASSWORD`);
|
|
20521
|
+
- SONAR_USER (e.g., admin)
|
|
20522
|
+
- SONAR_PASSWORD (password or token)`);
|
|
20513
20523
|
}
|
|
20514
20524
|
logger10.info(`Executing SonarQube tool: ${args.action}`, { directory });
|
|
20515
20525
|
try {
|
|
@@ -20571,7 +20581,7 @@ ${setupResult.message}`);
|
|
|
20571
20581
|
}
|
|
20572
20582
|
|
|
20573
20583
|
// src/utils/shared-state.ts
|
|
20574
|
-
import { readFileSync, writeFileSync } from "node:fs";
|
|
20584
|
+
import { readFileSync, writeFileSync, renameSync } from "node:fs";
|
|
20575
20585
|
var SHARED_STATE_FILE = "/tmp/sonarqube-plugin-shared-state.json";
|
|
20576
20586
|
var readSharedState = () => {
|
|
20577
20587
|
try {
|
|
@@ -20584,7 +20594,9 @@ var readSharedState = () => {
|
|
|
20584
20594
|
var writeSharedState = (state) => {
|
|
20585
20595
|
try {
|
|
20586
20596
|
state.lastUpdated = new Date().toISOString();
|
|
20587
|
-
|
|
20597
|
+
const tmpFile = `${SHARED_STATE_FILE}.tmp.${process.pid}`;
|
|
20598
|
+
writeFileSync(tmpFile, JSON.stringify(state, null, 2));
|
|
20599
|
+
renameSync(tmpFile, SHARED_STATE_FILE);
|
|
20588
20600
|
} catch {}
|
|
20589
20601
|
};
|
|
20590
20602
|
var mapSessionToDirectory = (sessionId, directory) => {
|
|
@@ -20846,6 +20858,10 @@ var SonarQubePlugin = async ({ client, directory, worktree }) => {
|
|
|
20846
20858
|
safeLog("client.app.log failed (non-fatal)");
|
|
20847
20859
|
}
|
|
20848
20860
|
let pluginConfig;
|
|
20861
|
+
let pluginConfigLoadedAt = 0;
|
|
20862
|
+
const CONFIG_RELOAD_INTERVAL_MS = 60000;
|
|
20863
|
+
const transformCacheMap = new Map;
|
|
20864
|
+
const TRANSFORM_CACHE_TTL_MS = 60000;
|
|
20849
20865
|
let lastAnalysisResult;
|
|
20850
20866
|
const getConfig = () => pluginConfig;
|
|
20851
20867
|
const getDirectory = () => {
|
|
@@ -20856,8 +20872,9 @@ var SonarQubePlugin = async ({ client, directory, worktree }) => {
|
|
|
20856
20872
|
return effectiveDirectory;
|
|
20857
20873
|
};
|
|
20858
20874
|
const loadPluginConfig = async () => {
|
|
20859
|
-
if (pluginConfig)
|
|
20875
|
+
if (pluginConfig && Date.now() - pluginConfigLoadedAt < CONFIG_RELOAD_INTERVAL_MS)
|
|
20860
20876
|
return;
|
|
20877
|
+
pluginConfig = undefined;
|
|
20861
20878
|
const dir = getDirectory();
|
|
20862
20879
|
const sonarConfigPath = `${dir}/.sonarqube/config.json`;
|
|
20863
20880
|
try {
|
|
@@ -20865,16 +20882,18 @@ var SonarQubePlugin = async ({ client, directory, worktree }) => {
|
|
|
20865
20882
|
if (await configFile.exists()) {
|
|
20866
20883
|
const config3 = await configFile.json();
|
|
20867
20884
|
pluginConfig = { sonarqube: config3 };
|
|
20885
|
+
pluginConfigLoadedAt = Date.now();
|
|
20868
20886
|
safeLog(`Config loaded from ${sonarConfigPath}`);
|
|
20869
20887
|
return;
|
|
20870
20888
|
}
|
|
20871
20889
|
} catch {}
|
|
20872
20890
|
pluginConfig = {};
|
|
20891
|
+
pluginConfigLoadedAt = Date.now();
|
|
20873
20892
|
safeLog("Using environment variables for config");
|
|
20874
20893
|
};
|
|
20875
20894
|
const hooks = createHooks(getConfig, getDirectory);
|
|
20876
20895
|
let currentSessionId;
|
|
20877
|
-
|
|
20896
|
+
const initialCheckSessions = new Set;
|
|
20878
20897
|
const buildQualityNotification = (qgStatus, counts, qgFailed) => {
|
|
20879
20898
|
const statusEmoji = qgFailed ? "[FAIL]" : "[WARN]";
|
|
20880
20899
|
const blockerNote = counts.blocker > 0 ? `**Action Required:** There are BLOCKER issues that should be fixed.
|
|
@@ -20887,9 +20906,9 @@ var SonarQubePlugin = async ({ client, directory, worktree }) => {
|
|
|
20887
20906
|
${blockerNote}Use \`sonarqube({ action: "issues" })\` to see details or \`sonarqube({ action: "analyze" })\` to re-analyze.`;
|
|
20888
20907
|
};
|
|
20889
20908
|
const performInitialQualityCheck = async (sessionId) => {
|
|
20890
|
-
if (
|
|
20909
|
+
if (initialCheckSessions.has(sessionId))
|
|
20891
20910
|
return;
|
|
20892
|
-
|
|
20911
|
+
initialCheckSessions.add(sessionId);
|
|
20893
20912
|
try {
|
|
20894
20913
|
await loadPluginConfig();
|
|
20895
20914
|
const sonarConfig = pluginConfig?.["sonarqube"];
|
|
@@ -20936,7 +20955,7 @@ ${blockerNote}Use \`sonarqube({ action: "issues" })\` to see details or \`sonarq
|
|
|
20936
20955
|
});
|
|
20937
20956
|
} catch {}
|
|
20938
20957
|
};
|
|
20939
|
-
const qualityGatePattern = /Quality Gate
|
|
20958
|
+
const qualityGatePattern = /Quality Gate[:\s*]*\[(?:PASS|FAIL)\]\s*(\w+)|\*\*Quality Gate:\s*(\w+)\*\*/;
|
|
20940
20959
|
const issueCountPattern = /Blockers: (\d+), Critical: (\d+), Major: (\d+), Minor: (\d+), Info: (\d+)/;
|
|
20941
20960
|
const parseAnalysisResult = (message) => {
|
|
20942
20961
|
const resultMatch = qualityGatePattern.exec(message);
|
|
@@ -20945,7 +20964,7 @@ ${blockerNote}Use \`sonarqube({ action: "issues" })\` to see details or \`sonarq
|
|
|
20945
20964
|
return;
|
|
20946
20965
|
}
|
|
20947
20966
|
return {
|
|
20948
|
-
qualityGate: resultMatch[2],
|
|
20967
|
+
qualityGate: resultMatch[1] || resultMatch[2],
|
|
20949
20968
|
issues: {
|
|
20950
20969
|
blocker: Number.parseInt(issueMatch[1], 10),
|
|
20951
20970
|
critical: Number.parseInt(issueMatch[2], 10),
|
|
@@ -21004,8 +21023,8 @@ ${blockerNote}Use \`sonarqube({ action: "issues" })\` to see details or \`sonarq
|
|
|
21004
21023
|
if (!config3 || config3.level === "off" || !config3.autoAnalyze) {
|
|
21005
21024
|
return;
|
|
21006
21025
|
}
|
|
21007
|
-
const
|
|
21008
|
-
if (
|
|
21026
|
+
const editedFiles = hooks.getEditedFiles?.() ?? getEditedFiles();
|
|
21027
|
+
if (editedFiles.length === 0) {
|
|
21009
21028
|
return;
|
|
21010
21029
|
}
|
|
21011
21030
|
const message = await hooks.sessionIdle();
|
|
@@ -21016,7 +21035,7 @@ ${blockerNote}Use \`sonarqube({ action: "issues" })\` to see details or \`sonarq
|
|
|
21016
21035
|
if (parsedResult) {
|
|
21017
21036
|
lastAnalysisResult = parsedResult;
|
|
21018
21037
|
}
|
|
21019
|
-
const passed = message.includes("[PASS]");
|
|
21038
|
+
const passed = message.includes("[PASS]") || message.includes("Quality Gate") && message.includes("OK");
|
|
21020
21039
|
await showToast(passed ? "SonarQube: Quality Gate Passed" : "SonarQube: Issues Found", passed ? "success" : "error");
|
|
21021
21040
|
await injectAnalysisResults(message, config3, currentSessionId);
|
|
21022
21041
|
};
|
|
@@ -21115,7 +21134,7 @@ Git operation completed with changes. Consider running:
|
|
|
21115
21134
|
const handleGitPush = async (command, outputData) => {
|
|
21116
21135
|
if (!/git\s+push\b/.test(command))
|
|
21117
21136
|
return;
|
|
21118
|
-
if (outputData?.includes("error") || outputData?.includes("rejected"))
|
|
21137
|
+
if (outputData?.includes("error:") || outputData?.includes("fatal:") || outputData?.includes("rejected"))
|
|
21119
21138
|
return;
|
|
21120
21139
|
await showToast("Code pushed - SonarQube will analyze on server", "info");
|
|
21121
21140
|
};
|
|
@@ -21174,16 +21193,27 @@ Git operation completed with changes. Consider running:
|
|
|
21174
21193
|
safeLog(` effectiveDirectory (fallback): "${effectiveDirectory}"`);
|
|
21175
21194
|
const dir = sessionDir || effectiveDirectory;
|
|
21176
21195
|
safeLog(` FINAL dir used: "${dir}"`);
|
|
21196
|
+
const now = Date.now();
|
|
21197
|
+
const cachedEntry = transformCacheMap.get(dir);
|
|
21198
|
+
if (cachedEntry && now - cachedEntry.timestamp < TRANSFORM_CACHE_TTL_MS) {
|
|
21199
|
+
if (cachedEntry.data) {
|
|
21200
|
+
output.system.push(cachedEntry.data);
|
|
21201
|
+
}
|
|
21202
|
+
return;
|
|
21203
|
+
}
|
|
21177
21204
|
await loadPluginConfig();
|
|
21178
21205
|
const sonarConfig = pluginConfig?.["sonarqube"];
|
|
21179
21206
|
const config3 = loadConfig(sonarConfig);
|
|
21180
21207
|
if (!config3 || config3.level === "off") {
|
|
21181
21208
|
safeLog(` config level is off or null, returning early`);
|
|
21209
|
+
transformCacheMap.set(dir, { data: undefined, timestamp: now });
|
|
21182
21210
|
return;
|
|
21183
21211
|
}
|
|
21184
21212
|
const state = await getProjectState(dir);
|
|
21185
|
-
if (!state?.projectKey)
|
|
21213
|
+
if (!state?.projectKey) {
|
|
21214
|
+
transformCacheMap.set(dir, { data: undefined, timestamp: now });
|
|
21186
21215
|
return;
|
|
21216
|
+
}
|
|
21187
21217
|
const api2 = createSonarQubeAPI(config3, state);
|
|
21188
21218
|
const [qgStatus, counts, newCodeResponse] = await Promise.all([
|
|
21189
21219
|
api2.qualityGate.getStatus(state.projectKey),
|
|
@@ -21199,6 +21229,7 @@ Git operation completed with changes. Consider running:
|
|
|
21199
21229
|
const qgFailed = qgStatus.projectStatus.status !== "OK";
|
|
21200
21230
|
const newCodeIssues = newCodeResponse.paging.total;
|
|
21201
21231
|
if (!hasIssues && !qgFailed && newCodeIssues === 0) {
|
|
21232
|
+
transformCacheMap.set(dir, { data: undefined, timestamp: now });
|
|
21202
21233
|
return;
|
|
21203
21234
|
}
|
|
21204
21235
|
const systemContext = `## SonarQube Code Quality Status
|
|
@@ -21215,6 +21246,7 @@ ${config3.level === "enterprise" ? `This project follows enterprise-level qualit
|
|
|
21215
21246
|
- \`sonarqube({ action: "newissues" })\` - See issues in your recent changes (Clean as You Code)
|
|
21216
21247
|
- \`sonarqube({ action: "worstfiles" })\` - Find files needing most attention
|
|
21217
21248
|
- \`sonarqube({ action: "issues" })\` - See all issues`;
|
|
21249
|
+
transformCacheMap.set(dir, { data: systemContext, timestamp: now });
|
|
21218
21250
|
output.system.push(systemContext);
|
|
21219
21251
|
}, "experimental.chat.system.transform"),
|
|
21220
21252
|
tool: {
|
|
@@ -21273,6 +21305,7 @@ Example usage:
|
|
|
21273
21305
|
if (parsedResult) {
|
|
21274
21306
|
lastAnalysisResult = parsedResult;
|
|
21275
21307
|
}
|
|
21308
|
+
transformCacheMap.clear();
|
|
21276
21309
|
}
|
|
21277
21310
|
return result;
|
|
21278
21311
|
}
|