opencode-sonarqube 0.1.18 → 0.1.20
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 +132 -151
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -4120,6 +4120,7 @@ var init_types2 = __esm(() => {
|
|
|
4120
4120
|
});
|
|
4121
4121
|
|
|
4122
4122
|
// src/utils/state.ts
|
|
4123
|
+
import { appendFileSync as appendFileSync2 } from "node:fs";
|
|
4123
4124
|
function getStatePath(directory) {
|
|
4124
4125
|
return `${directory}/${STATE_DIR}/${STATE_FILE}`;
|
|
4125
4126
|
}
|
|
@@ -4209,21 +4210,33 @@ ${entry}
|
|
|
4209
4210
|
await Bun.write(gitignorePath, newContent);
|
|
4210
4211
|
logger4.info("Added SonarQube exclusion to .gitignore");
|
|
4211
4212
|
}
|
|
4212
|
-
var logger4, STATE_DIR = ".sonarqube", STATE_FILE = "project.json";
|
|
4213
|
+
var LOG_FILE2 = "/tmp/sonarqube-plugin-debug.log", logger4, STATE_DIR = ".sonarqube", STATE_FILE = "project.json";
|
|
4213
4214
|
var init_state = __esm(() => {
|
|
4214
4215
|
init_types2();
|
|
4215
4216
|
logger4 = {
|
|
4216
4217
|
info: (msg, extra) => {
|
|
4217
|
-
|
|
4218
|
+
try {
|
|
4219
|
+
appendFileSync2(LOG_FILE2, `${new Date().toISOString()} [STATE] ${msg} ${extra ? JSON.stringify(extra) : ""}
|
|
4220
|
+
`);
|
|
4221
|
+
} catch {}
|
|
4218
4222
|
},
|
|
4219
4223
|
warn: (msg, extra) => {
|
|
4220
|
-
|
|
4224
|
+
try {
|
|
4225
|
+
appendFileSync2(LOG_FILE2, `${new Date().toISOString()} [STATE-WARN] ${msg} ${extra ? JSON.stringify(extra) : ""}
|
|
4226
|
+
`);
|
|
4227
|
+
} catch {}
|
|
4221
4228
|
},
|
|
4222
4229
|
error: (msg, extra) => {
|
|
4223
|
-
|
|
4230
|
+
try {
|
|
4231
|
+
appendFileSync2(LOG_FILE2, `${new Date().toISOString()} [STATE-ERROR] ${msg} ${extra ? JSON.stringify(extra) : ""}
|
|
4232
|
+
`);
|
|
4233
|
+
} catch {}
|
|
4224
4234
|
},
|
|
4225
4235
|
debug: (msg, extra) => {
|
|
4226
|
-
|
|
4236
|
+
try {
|
|
4237
|
+
appendFileSync2(LOG_FILE2, `${new Date().toISOString()} [STATE-DEBUG] ${msg} ${extra ? JSON.stringify(extra) : ""}
|
|
4238
|
+
`);
|
|
4239
|
+
} catch {}
|
|
4227
4240
|
}
|
|
4228
4241
|
};
|
|
4229
4242
|
});
|
|
@@ -16550,15 +16563,26 @@ function tool(input) {
|
|
|
16550
16563
|
tool.schema = exports_external;
|
|
16551
16564
|
// src/utils/config.ts
|
|
16552
16565
|
init_types2();
|
|
16566
|
+
import { appendFileSync } from "node:fs";
|
|
16567
|
+
var LOG_FILE = "/tmp/sonarqube-plugin-debug.log";
|
|
16553
16568
|
var configLogger = {
|
|
16554
16569
|
info: (msg, extra) => {
|
|
16555
|
-
|
|
16570
|
+
try {
|
|
16571
|
+
appendFileSync(LOG_FILE, `${new Date().toISOString()} [CONFIG] ${msg} ${extra ? JSON.stringify(extra) : ""}
|
|
16572
|
+
`);
|
|
16573
|
+
} catch {}
|
|
16556
16574
|
},
|
|
16557
16575
|
warn: (msg, extra) => {
|
|
16558
|
-
|
|
16576
|
+
try {
|
|
16577
|
+
appendFileSync(LOG_FILE, `${new Date().toISOString()} [CONFIG-WARN] ${msg} ${extra ? JSON.stringify(extra) : ""}
|
|
16578
|
+
`);
|
|
16579
|
+
} catch {}
|
|
16559
16580
|
},
|
|
16560
16581
|
error: (msg, extra) => {
|
|
16561
|
-
|
|
16582
|
+
try {
|
|
16583
|
+
appendFileSync(LOG_FILE, `${new Date().toISOString()} [CONFIG-ERROR] ${msg} ${extra ? JSON.stringify(extra) : ""}
|
|
16584
|
+
`);
|
|
16585
|
+
} catch {}
|
|
16562
16586
|
}
|
|
16563
16587
|
};
|
|
16564
16588
|
var DEFAULT_CONFIG = {
|
|
@@ -17103,7 +17127,6 @@ class SonarQubeClient {
|
|
|
17103
17127
|
constructor(config2, _logger) {
|
|
17104
17128
|
this.baseUrl = normalizeUrl(config2.url);
|
|
17105
17129
|
this.auth = config2.auth;
|
|
17106
|
-
console.log(`[SONARQUBE-CLIENT] Created client for ${this.baseUrl}`);
|
|
17107
17130
|
}
|
|
17108
17131
|
async request(endpoint, options = {}) {
|
|
17109
17132
|
const { method = "GET", params, body } = options;
|
|
@@ -17116,42 +17139,23 @@ class SonarQubeClient {
|
|
|
17116
17139
|
if (requestBody) {
|
|
17117
17140
|
headers["Content-Type"] = "application/x-www-form-urlencoded";
|
|
17118
17141
|
}
|
|
17119
|
-
const logLine = `${new Date().toISOString()} [API] >>> ${method} ${endpoint} ${JSON.stringify({ url: url2, params, hasBody: !!body, bodyKeys: body ? Object.keys(body) : [] })}
|
|
17120
|
-
`;
|
|
17121
17142
|
try {
|
|
17122
|
-
const { appendFileSync } = await import("node:fs");
|
|
17123
|
-
|
|
17143
|
+
const { appendFileSync: appendFileSync2 } = await import("node:fs");
|
|
17144
|
+
appendFileSync2("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} [API] >>> ${method} ${endpoint} ${JSON.stringify({ url: url2, params, hasBody: !!body, bodyKeys: body ? Object.keys(body) : [] })}
|
|
17145
|
+
`);
|
|
17124
17146
|
} catch {}
|
|
17125
|
-
console.log(`[SONARQUBE-API] >>> ${method} ${endpoint}`, JSON.stringify({
|
|
17126
|
-
url: url2,
|
|
17127
|
-
params,
|
|
17128
|
-
hasBody: !!body,
|
|
17129
|
-
bodyKeys: body ? Object.keys(body) : []
|
|
17130
|
-
}));
|
|
17131
17147
|
try {
|
|
17132
17148
|
const response = await fetch(url2, {
|
|
17133
17149
|
method,
|
|
17134
17150
|
headers,
|
|
17135
17151
|
body: requestBody
|
|
17136
17152
|
});
|
|
17137
|
-
console.log(`[SONARQUBE-API] <<< ${method} ${endpoint}`, JSON.stringify({
|
|
17138
|
-
status: response.status,
|
|
17139
|
-
ok: response.ok
|
|
17140
|
-
}));
|
|
17141
17153
|
if (!response.ok) {
|
|
17142
|
-
console.error(`[SONARQUBE-API] ERROR: ${method} ${endpoint}`, JSON.stringify({
|
|
17143
|
-
status: response.status,
|
|
17144
|
-
url: url2
|
|
17145
|
-
}));
|
|
17146
17154
|
await handleResponseError(response);
|
|
17147
17155
|
}
|
|
17148
17156
|
const text = await response.text();
|
|
17149
17157
|
return parseResponseBody(text);
|
|
17150
17158
|
} catch (error45) {
|
|
17151
|
-
console.error(`[SONARQUBE-API] EXCEPTION: ${method} ${endpoint}`, JSON.stringify({
|
|
17152
|
-
error: String(error45),
|
|
17153
|
-
url: url2
|
|
17154
|
-
}));
|
|
17155
17159
|
handleFetchError(error45, this.baseUrl);
|
|
17156
17160
|
}
|
|
17157
17161
|
}
|
|
@@ -18881,16 +18885,6 @@ function createSonarQubeAPIWithToken(url2, token, logger3) {
|
|
|
18881
18885
|
return new SonarQubeAPI(client, logger3);
|
|
18882
18886
|
}
|
|
18883
18887
|
function createSonarQubeAPI(config2, state, logger3) {
|
|
18884
|
-
console.log(`[SONARQUBE-API] >>> createSonarQubeAPI called`, JSON.stringify({
|
|
18885
|
-
url: config2.url,
|
|
18886
|
-
projectKey: state.projectKey,
|
|
18887
|
-
projectKeyLength: state.projectKey?.length,
|
|
18888
|
-
hasToken: !!state.projectToken,
|
|
18889
|
-
tokenLength: state.projectToken?.length
|
|
18890
|
-
}));
|
|
18891
|
-
if (!state.projectToken) {
|
|
18892
|
-
console.error(`[SONARQUBE-API] createSonarQubeAPI: projectToken is missing!`);
|
|
18893
|
-
}
|
|
18894
18888
|
return createSonarQubeAPIWithToken(config2.url, state.projectToken, logger3);
|
|
18895
18889
|
}
|
|
18896
18890
|
|
|
@@ -19169,15 +19163,26 @@ function shouldBlockOnResult(result, level) {
|
|
|
19169
19163
|
// src/bootstrap/index.ts
|
|
19170
19164
|
init_types2();
|
|
19171
19165
|
init_state();
|
|
19166
|
+
import { appendFileSync as appendFileSync3 } from "node:fs";
|
|
19167
|
+
var LOG_FILE3 = "/tmp/sonarqube-plugin-debug.log";
|
|
19172
19168
|
var logger5 = {
|
|
19173
19169
|
info: (msg, extra) => {
|
|
19174
|
-
|
|
19170
|
+
try {
|
|
19171
|
+
appendFileSync3(LOG_FILE3, `${new Date().toISOString()} [BOOTSTRAP] ${msg} ${extra ? JSON.stringify(extra) : ""}
|
|
19172
|
+
`);
|
|
19173
|
+
} catch {}
|
|
19175
19174
|
},
|
|
19176
19175
|
warn: (msg, extra) => {
|
|
19177
|
-
|
|
19176
|
+
try {
|
|
19177
|
+
appendFileSync3(LOG_FILE3, `${new Date().toISOString()} [BOOTSTRAP-WARN] ${msg} ${extra ? JSON.stringify(extra) : ""}
|
|
19178
|
+
`);
|
|
19179
|
+
} catch {}
|
|
19178
19180
|
},
|
|
19179
19181
|
error: (msg, extra) => {
|
|
19180
|
-
|
|
19182
|
+
try {
|
|
19183
|
+
appendFileSync3(LOG_FILE3, `${new Date().toISOString()} [BOOTSTRAP-ERROR] ${msg} ${extra ? JSON.stringify(extra) : ""}
|
|
19184
|
+
`);
|
|
19185
|
+
} catch {}
|
|
19181
19186
|
}
|
|
19182
19187
|
};
|
|
19183
19188
|
var QUALITY_GATE_MAPPING = {
|
|
@@ -19215,8 +19220,8 @@ function generateTokenName(projectKey) {
|
|
|
19215
19220
|
async function bootstrap(options) {
|
|
19216
19221
|
let { config: config2, directory, force = false } = options;
|
|
19217
19222
|
try {
|
|
19218
|
-
const { appendFileSync } = await import("node:fs");
|
|
19219
|
-
|
|
19223
|
+
const { appendFileSync: appendFileSync4 } = await import("node:fs");
|
|
19224
|
+
appendFileSync4("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} [BOOTSTRAP] Starting bootstrap directory=${directory} config.projectKey="${config2.projectKey || "(empty)"}"
|
|
19220
19225
|
`);
|
|
19221
19226
|
} catch {}
|
|
19222
19227
|
if (!directory || directory === "/" || directory === "." || directory.length < 2) {
|
|
@@ -19230,8 +19235,8 @@ async function bootstrap(options) {
|
|
|
19230
19235
|
if (projectPath && projectPath !== "/" && projectPath.length > 1) {
|
|
19231
19236
|
directory = projectPath;
|
|
19232
19237
|
try {
|
|
19233
|
-
const { appendFileSync } = await import("node:fs");
|
|
19234
|
-
|
|
19238
|
+
const { appendFileSync: appendFileSync4 } = await import("node:fs");
|
|
19239
|
+
appendFileSync4("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} [BOOTSTRAP] Fixed directory from import.meta.url: ${directory}
|
|
19235
19240
|
`);
|
|
19236
19241
|
} catch {}
|
|
19237
19242
|
}
|
|
@@ -19452,9 +19457,9 @@ function formatActionPrompt(result, config2) {
|
|
|
19452
19457
|
function createIdleHook(getConfig, getDirectory) {
|
|
19453
19458
|
return async function handleSessionIdle() {
|
|
19454
19459
|
try {
|
|
19455
|
-
const { appendFileSync } = await import("node:fs");
|
|
19460
|
+
const { appendFileSync: appendFileSync4 } = await import("node:fs");
|
|
19456
19461
|
const dir = getDirectory();
|
|
19457
|
-
|
|
19462
|
+
appendFileSync4("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} [IDLE-HOOK] getDirectory()=${dir}
|
|
19458
19463
|
`);
|
|
19459
19464
|
} catch {}
|
|
19460
19465
|
const rawConfig = getConfig()?.["sonarqube"];
|
|
@@ -20142,21 +20147,20 @@ function getSeveritiesFromLevel(level) {
|
|
|
20142
20147
|
|
|
20143
20148
|
// src/index.ts
|
|
20144
20149
|
init_types2();
|
|
20145
|
-
import { appendFileSync } from "node:fs";
|
|
20150
|
+
import { appendFileSync as appendFileSync4 } from "node:fs";
|
|
20146
20151
|
try {
|
|
20147
|
-
|
|
20152
|
+
appendFileSync4("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} [LOAD] Plugin module loaded! CWD=${process.cwd()}
|
|
20148
20153
|
`);
|
|
20149
20154
|
} catch {}
|
|
20150
|
-
var
|
|
20155
|
+
var LOG_FILE4 = "/tmp/sonarqube-plugin-debug.log";
|
|
20151
20156
|
var debugLog = {
|
|
20152
20157
|
_write: (level, msg, extra) => {
|
|
20153
20158
|
const timestamp = new Date().toISOString();
|
|
20154
20159
|
const logLine = `${timestamp} [${level}] ${msg} ${extra ? JSON.stringify(extra) : ""}
|
|
20155
20160
|
`;
|
|
20156
20161
|
try {
|
|
20157
|
-
|
|
20162
|
+
appendFileSync4(LOG_FILE4, logLine);
|
|
20158
20163
|
} catch {}
|
|
20159
|
-
console.log(`[SONARQUBE-DEBUG] ${msg}`, extra ? JSON.stringify(extra) : "");
|
|
20160
20164
|
},
|
|
20161
20165
|
info: (msg, extra) => {
|
|
20162
20166
|
debugLog._write("INFO", msg, extra);
|
|
@@ -20184,62 +20188,58 @@ function shouldIgnoreFile2(filePath) {
|
|
|
20184
20188
|
return IGNORED_FILE_PATTERNS2.some((pattern) => pattern.test(filePath));
|
|
20185
20189
|
}
|
|
20186
20190
|
var SonarQubePlugin = async ({ client, directory, worktree }) => {
|
|
20187
|
-
|
|
20188
|
-
|
|
20189
|
-
|
|
20190
|
-
try {
|
|
20191
|
-
appendFileSync("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} [RESOLVE] ${msg}
|
|
20191
|
+
const safeLog = (msg) => {
|
|
20192
|
+
try {
|
|
20193
|
+
appendFileSync4("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} [PLUGIN] ${msg}
|
|
20192
20194
|
`);
|
|
20193
|
-
|
|
20194
|
-
|
|
20195
|
-
|
|
20195
|
+
} catch {}
|
|
20196
|
+
};
|
|
20197
|
+
safeLog(`=== PLUGIN START === directory=${directory} worktree=${worktree} cwd=${process.cwd()}`);
|
|
20198
|
+
const resolveValidDirectory = () => {
|
|
20196
20199
|
if (worktree && worktree !== "/" && worktree.length > 1) {
|
|
20197
|
-
|
|
20200
|
+
safeLog(`USING worktree=${worktree}`);
|
|
20198
20201
|
return worktree;
|
|
20199
20202
|
}
|
|
20200
20203
|
if (directory && directory !== "/" && directory.length > 1) {
|
|
20201
|
-
|
|
20204
|
+
safeLog(`USING directory=${directory}`);
|
|
20202
20205
|
return directory;
|
|
20203
20206
|
}
|
|
20204
20207
|
const cwd = process.cwd();
|
|
20205
20208
|
if (cwd && cwd !== "/" && cwd.length > 1) {
|
|
20206
|
-
|
|
20209
|
+
safeLog(`USING cwd=${cwd}`);
|
|
20207
20210
|
return cwd;
|
|
20208
20211
|
}
|
|
20209
20212
|
try {
|
|
20210
20213
|
const pluginUrl = import.meta.url;
|
|
20211
|
-
|
|
20212
|
-
const pluginPath = pluginUrl.replace("file://", "");
|
|
20214
|
+
const pluginPath = decodeURIComponent(pluginUrl.replace("file://", ""));
|
|
20213
20215
|
const pathParts = pluginPath.split("/");
|
|
20214
20216
|
const nodeModulesIndex = pathParts.findIndex((p) => p === "node_modules");
|
|
20215
|
-
log(`pathParts nodeModulesIndex=${nodeModulesIndex}`);
|
|
20216
20217
|
if (nodeModulesIndex > 0) {
|
|
20217
20218
|
const projectPath = pathParts.slice(0, nodeModulesIndex).join("/");
|
|
20218
|
-
log(`extracted projectPath=${projectPath}`);
|
|
20219
20219
|
if (projectPath && projectPath !== "/" && projectPath.length > 1) {
|
|
20220
|
+
safeLog(`USING import.meta.url derived path=${projectPath}`);
|
|
20220
20221
|
return projectPath;
|
|
20221
20222
|
}
|
|
20222
20223
|
}
|
|
20223
|
-
} catch
|
|
20224
|
-
log(`import.meta.url FAILED: ${e}`);
|
|
20225
|
-
}
|
|
20224
|
+
} catch {}
|
|
20226
20225
|
const homeDir = process.env["HOME"] || "/Users";
|
|
20227
|
-
|
|
20226
|
+
safeLog(`FALLBACK home=${homeDir}`);
|
|
20228
20227
|
return homeDir;
|
|
20229
20228
|
};
|
|
20230
20229
|
const effectiveDirectory = resolveValidDirectory();
|
|
20230
|
+
safeLog(`FINAL effectiveDirectory=${effectiveDirectory}`);
|
|
20231
20231
|
try {
|
|
20232
|
-
|
|
20233
|
-
|
|
20234
|
-
|
|
20235
|
-
|
|
20236
|
-
|
|
20237
|
-
|
|
20238
|
-
|
|
20239
|
-
|
|
20240
|
-
|
|
20241
|
-
|
|
20242
|
-
}
|
|
20232
|
+
await client.app.log({
|
|
20233
|
+
body: {
|
|
20234
|
+
service: "opencode-sonarqube",
|
|
20235
|
+
level: "info",
|
|
20236
|
+
message: "SonarQube plugin initialized",
|
|
20237
|
+
extra: { directory, worktree, effectiveDirectory }
|
|
20238
|
+
}
|
|
20239
|
+
});
|
|
20240
|
+
} catch {
|
|
20241
|
+
safeLog("client.app.log failed (non-fatal)");
|
|
20242
|
+
}
|
|
20243
20243
|
let pluginConfig;
|
|
20244
20244
|
let lastAnalysisResult;
|
|
20245
20245
|
const getConfig = () => pluginConfig;
|
|
@@ -20333,8 +20333,8 @@ Use \`sonarqube({ action: "issues" })\` to see details or \`sonarqube({ action:
|
|
|
20333
20333
|
}
|
|
20334
20334
|
} catch (error45) {
|
|
20335
20335
|
try {
|
|
20336
|
-
const { appendFileSync:
|
|
20337
|
-
|
|
20336
|
+
const { appendFileSync: appendFileSync5 } = await import("node:fs");
|
|
20337
|
+
appendFileSync5("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} [ERROR] performInitialQualityCheck FAILED: ${error45}
|
|
20338
20338
|
`);
|
|
20339
20339
|
} catch {}
|
|
20340
20340
|
}
|
|
@@ -20612,8 +20612,17 @@ Git operation completed with changes. Consider running:
|
|
|
20612
20612
|
return;
|
|
20613
20613
|
await showToast("Code pushed - SonarQube will analyze on server", "info");
|
|
20614
20614
|
};
|
|
20615
|
+
const safeAsync = (fn, name) => {
|
|
20616
|
+
return async (...args) => {
|
|
20617
|
+
try {
|
|
20618
|
+
return await fn(...args);
|
|
20619
|
+
} catch (error45) {
|
|
20620
|
+
safeLog(`[ERROR] ${name} failed: ${error45}`);
|
|
20621
|
+
}
|
|
20622
|
+
};
|
|
20623
|
+
};
|
|
20615
20624
|
const returnHooks = {
|
|
20616
|
-
event: async ({ event }) => {
|
|
20625
|
+
event: safeAsync(async ({ event }) => {
|
|
20617
20626
|
handleSessionTrackingEvent(event);
|
|
20618
20627
|
handleFileEditedEvent(event);
|
|
20619
20628
|
if (event.type === "session.created" && currentSessionId) {
|
|
@@ -20625,8 +20634,8 @@ Git operation completed with changes. Consider running:
|
|
|
20625
20634
|
if (event.type === "session.error") {
|
|
20626
20635
|
await showToast("SonarQube: Analysis error occurred", "error");
|
|
20627
20636
|
}
|
|
20628
|
-
},
|
|
20629
|
-
"tool.execute.before": async (input, output) => {
|
|
20637
|
+
}, "event"),
|
|
20638
|
+
"tool.execute.before": safeAsync(async (input, output) => {
|
|
20630
20639
|
if (input.tool === "sonarqube") {
|
|
20631
20640
|
await loadPluginConfig();
|
|
20632
20641
|
}
|
|
@@ -20634,71 +20643,49 @@ Git operation completed with changes. Consider running:
|
|
|
20634
20643
|
if (isBashTool && currentSessionId) {
|
|
20635
20644
|
await handlePreCommitCheck(output);
|
|
20636
20645
|
}
|
|
20637
|
-
},
|
|
20638
|
-
"tool.execute.after": async (input, output) => {
|
|
20646
|
+
}, "tool.execute.before"),
|
|
20647
|
+
"tool.execute.after": safeAsync(async (input, output) => {
|
|
20639
20648
|
await logSonarQubeResult(input, output);
|
|
20640
20649
|
await trackFileChanges(input, output);
|
|
20641
20650
|
await handleGitOperations(input, output);
|
|
20642
|
-
},
|
|
20643
|
-
"experimental.session.compacting": async (_input, output) => {
|
|
20651
|
+
}, "tool.execute.after"),
|
|
20652
|
+
"experimental.session.compacting": safeAsync(async (_input, output) => {
|
|
20644
20653
|
const context = buildCompactionContext();
|
|
20645
20654
|
if (context) {
|
|
20646
20655
|
output.context.push(context);
|
|
20647
20656
|
}
|
|
20648
|
-
},
|
|
20649
|
-
"experimental.chat.system.transform": async (_input, output) => {
|
|
20650
|
-
|
|
20651
|
-
const { appendFileSync: appendFileSync2 } = await import("node:fs");
|
|
20652
|
-
appendFileSync2("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} [HOOK] experimental.chat.system.transform ENTERED
|
|
20653
|
-
`);
|
|
20654
|
-
} catch {}
|
|
20655
|
-
debugLog.info("=== experimental.chat.system.transform START ===");
|
|
20657
|
+
}, "experimental.session.compacting"),
|
|
20658
|
+
"experimental.chat.system.transform": safeAsync(async (_input, output) => {
|
|
20659
|
+
safeLog("experimental.chat.system.transform ENTERED");
|
|
20656
20660
|
await loadPluginConfig();
|
|
20657
20661
|
const sonarConfig = pluginConfig?.["sonarqube"];
|
|
20658
|
-
debugLog.info("system.transform: Loading config", { hasSonarConfig: !!sonarConfig });
|
|
20659
20662
|
const config2 = loadConfig(sonarConfig);
|
|
20660
|
-
debugLog.info("system.transform: Config result", { hasConfig: !!config2, level: config2?.level });
|
|
20661
20663
|
if (!config2 || config2.level === "off") {
|
|
20662
|
-
debugLog.info("system.transform: No config or level=off, skipping");
|
|
20663
20664
|
return;
|
|
20664
20665
|
}
|
|
20665
|
-
|
|
20666
|
-
|
|
20667
|
-
|
|
20668
|
-
|
|
20669
|
-
|
|
20670
|
-
|
|
20671
|
-
|
|
20672
|
-
|
|
20673
|
-
|
|
20674
|
-
|
|
20675
|
-
debugLog.info("system.transform: No state or projectKey, skipping");
|
|
20676
|
-
return;
|
|
20677
|
-
}
|
|
20678
|
-
debugLog.info("system.transform: Creating API", {
|
|
20679
|
-
url: config2.url,
|
|
20666
|
+
const dir = getDirectory();
|
|
20667
|
+
const state = await getProjectState(dir);
|
|
20668
|
+
if (!state || !state.projectKey) {
|
|
20669
|
+
return;
|
|
20670
|
+
}
|
|
20671
|
+
const api2 = createSonarQubeAPI(config2, state);
|
|
20672
|
+
const [qgStatus, counts, newCodeResponse] = await Promise.all([
|
|
20673
|
+
api2.qualityGate.getStatus(state.projectKey),
|
|
20674
|
+
api2.issues.getCounts(state.projectKey),
|
|
20675
|
+
api2.issues.search({
|
|
20680
20676
|
projectKey: state.projectKey,
|
|
20681
|
-
|
|
20682
|
-
|
|
20683
|
-
|
|
20684
|
-
|
|
20685
|
-
|
|
20686
|
-
|
|
20687
|
-
|
|
20688
|
-
|
|
20689
|
-
|
|
20690
|
-
|
|
20691
|
-
|
|
20692
|
-
|
|
20693
|
-
}).catch(() => ({ paging: { total: 0 } }))
|
|
20694
|
-
]);
|
|
20695
|
-
const hasIssues = counts.blocker > 0 || counts.critical > 0;
|
|
20696
|
-
const qgFailed = qgStatus.projectStatus.status !== "OK";
|
|
20697
|
-
const newCodeIssues = newCodeResponse.paging.total;
|
|
20698
|
-
if (!hasIssues && !qgFailed && newCodeIssues === 0) {
|
|
20699
|
-
return;
|
|
20700
|
-
}
|
|
20701
|
-
const systemContext = `## SonarQube Code Quality Status
|
|
20677
|
+
inNewCode: true,
|
|
20678
|
+
resolved: false,
|
|
20679
|
+
pageSize: 1
|
|
20680
|
+
}).catch(() => ({ paging: { total: 0 } }))
|
|
20681
|
+
]);
|
|
20682
|
+
const hasIssues = counts.blocker > 0 || counts.critical > 0;
|
|
20683
|
+
const qgFailed = qgStatus.projectStatus.status !== "OK";
|
|
20684
|
+
const newCodeIssues = newCodeResponse.paging.total;
|
|
20685
|
+
if (!hasIssues && !qgFailed && newCodeIssues === 0) {
|
|
20686
|
+
return;
|
|
20687
|
+
}
|
|
20688
|
+
const systemContext = `## SonarQube Code Quality Status
|
|
20702
20689
|
|
|
20703
20690
|
**Quality Gate:** ${qgStatus.projectStatus.status}${qgFailed ? " (FAILED)" : ""}
|
|
20704
20691
|
**Outstanding Issues:** ${counts.blocker} blockers, ${counts.critical} critical, ${counts.major} major
|
|
@@ -20712,15 +20699,8 @@ ${config2.level === "enterprise" ? `This project follows enterprise-level qualit
|
|
|
20712
20699
|
- \`sonarqube({ action: "newissues" })\` - See issues in your recent changes (Clean as You Code)
|
|
20713
20700
|
- \`sonarqube({ action: "worstfiles" })\` - Find files needing most attention
|
|
20714
20701
|
- \`sonarqube({ action: "issues" })\` - See all issues`;
|
|
20715
|
-
|
|
20716
|
-
|
|
20717
|
-
try {
|
|
20718
|
-
const { appendFileSync: appendFileSync2 } = await import("node:fs");
|
|
20719
|
-
appendFileSync2("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} [ERROR] experimental.chat.system.transform FAILED: ${error45}
|
|
20720
|
-
`);
|
|
20721
|
-
} catch {}
|
|
20722
|
-
}
|
|
20723
|
-
},
|
|
20702
|
+
output.system.push(systemContext);
|
|
20703
|
+
}, "experimental.chat.system.transform"),
|
|
20724
20704
|
tool: {
|
|
20725
20705
|
sonarqube: tool({
|
|
20726
20706
|
description: `Run SonarQube code analysis and get quality metrics.
|
|
@@ -20950,7 +20930,8 @@ async function executeCLI(args = process.argv.slice(2), log = console.log, exit
|
|
|
20950
20930
|
log(result.output);
|
|
20951
20931
|
exit(result.exitCode);
|
|
20952
20932
|
}
|
|
20953
|
-
|
|
20933
|
+
var isDirectCLI = __require.main == __require.module && process.argv[1]?.includes("index.ts");
|
|
20934
|
+
if (isDirectCLI) {
|
|
20954
20935
|
await executeCLI();
|
|
20955
20936
|
}
|
|
20956
20937
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-sonarqube",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
4
4
|
"description": "OpenCode Plugin for SonarQube integration - Enterprise-level code quality from the start",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"homepage": "https://github.com/mguttmann/opencode-sonarqube#readme",
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@opencode-ai/plugin": "^1.1.34",
|
|
41
|
-
"opencode-sonarqube": "0.1.
|
|
41
|
+
"opencode-sonarqube": "0.1.20",
|
|
42
42
|
"zod": "^3.24.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|