opencode-sonarqube 1.2.16 → 1.2.18

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.
Files changed (2) hide show
  1. package/dist/index.js +191 -161
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3999,10 +3999,10 @@ function numberToRating(num) {
3999
3999
  const ratings = ["A", "B", "C", "D", "E"];
4000
4000
  return ratings[num - 1] ?? "?";
4001
4001
  }
4002
- function SonarQubeError(message, code, statusCode) {
4002
+ function SonarQubeError(message, code2, statusCode) {
4003
4003
  const error45 = new Error(message);
4004
4004
  error45.name = "SonarQubeError";
4005
- error45.code = code;
4005
+ error45.code = code2;
4006
4006
  error45.statusCode = statusCode;
4007
4007
  return error45;
4008
4008
  }
@@ -4110,18 +4110,18 @@ var init_types2 = __esm(() => {
4110
4110
  });
4111
4111
 
4112
4112
  // src/utils/state.ts
4113
- function getStatePath(directory) {
4114
- return `${directory}/${STATE_DIR}/${STATE_FILE}`;
4113
+ function getStatePath(directory2) {
4114
+ return `${directory2}/${STATE_DIR}/${STATE_FILE}`;
4115
4115
  }
4116
- function getStateDir(directory) {
4117
- return `${directory}/${STATE_DIR}`;
4116
+ function getStateDir(directory2) {
4117
+ return `${directory2}/${STATE_DIR}`;
4118
4118
  }
4119
- async function hasProjectState(directory) {
4120
- const statePath = getStatePath(directory);
4119
+ async function hasProjectState(directory2) {
4120
+ const statePath = getStatePath(directory2);
4121
4121
  return Bun.file(statePath).exists();
4122
4122
  }
4123
- async function loadProjectState(directory) {
4124
- const statePath = getStatePath(directory);
4123
+ async function loadProjectState(directory2) {
4124
+ const statePath = getStatePath(directory2);
4125
4125
  const exists = await Bun.file(statePath).exists();
4126
4126
  if (!exists) {
4127
4127
  return null;
@@ -4139,9 +4139,9 @@ async function loadProjectState(directory) {
4139
4139
  return null;
4140
4140
  }
4141
4141
  }
4142
- async function saveProjectState(directory, state) {
4143
- const stateDir = getStateDir(directory);
4144
- const statePath = getStatePath(directory);
4142
+ async function saveProjectState(directory2, state) {
4143
+ const stateDir = getStateDir(directory2);
4144
+ const statePath = getStatePath(directory2);
4145
4145
  const dirExists = await Bun.file(stateDir).exists();
4146
4146
  if (!dirExists) {
4147
4147
  await Bun.write(`${stateDir}/.gitkeep`, "");
@@ -4161,8 +4161,8 @@ function createInitialState(options) {
4161
4161
  setupComplete: true
4162
4162
  };
4163
4163
  }
4164
- async function ensureGitignore(directory) {
4165
- const gitignorePath = `${directory}/.gitignore`;
4164
+ async function ensureGitignore(directory2) {
4165
+ const gitignorePath = `${directory2}/.gitignore`;
4166
4166
  const entry = ".sonarqube/";
4167
4167
  const exists = await Bun.file(gitignorePath).exists();
4168
4168
  if (!exists) {
@@ -16567,15 +16567,15 @@ function loadConfig(rawConfig) {
16567
16567
  configLogger.info("<<< loadConfig success", { url: result.data.url, level: result.data.level });
16568
16568
  return result.data;
16569
16569
  }
16570
- async function deriveProjectKey(directory) {
16570
+ async function deriveProjectKey(directory2) {
16571
16571
  try {
16572
- const packageJsonPath = `${directory}/package.json`;
16572
+ const packageJsonPath = `${directory2}/package.json`;
16573
16573
  const packageJson = await Bun.file(packageJsonPath).json();
16574
16574
  if (packageJson.name) {
16575
16575
  return packageJson.name;
16576
16576
  }
16577
16577
  } catch {}
16578
- const dirName = directory.split("/").pop();
16578
+ const dirName = directory2.split("/").pop();
16579
16579
  if (dirName && dirName.length > 0) {
16580
16580
  return dirName;
16581
16581
  }
@@ -16678,22 +16678,22 @@ var logger = new Logger("opencode-sonarqube");
16678
16678
 
16679
16679
  // src/scanner/config.ts
16680
16680
  var logger2 = new Logger("scanner-config");
16681
- async function checkProjectFiles(directory) {
16681
+ async function checkProjectFiles(directory2) {
16682
16682
  const checks3 = await Promise.all([
16683
- Bun.file(`${directory}/package.json`).exists(),
16684
- Bun.file(`${directory}/tsconfig.json`).exists(),
16685
- Bun.file(`${directory}/requirements.txt`).exists(),
16686
- Bun.file(`${directory}/pyproject.toml`).exists(),
16687
- Bun.file(`${directory}/pom.xml`).exists(),
16688
- Bun.file(`${directory}/build.gradle`).exists(),
16689
- Bun.file(`${directory}/go.mod`).exists(),
16690
- Bun.file(`${directory}/Cargo.toml`).exists(),
16691
- Bun.file(`${directory}/composer.json`).exists(),
16692
- Bun.file(`${directory}/Gemfile`).exists(),
16693
- Bun.file(`${directory}/package-lock.json`).exists(),
16694
- Bun.file(`${directory}/yarn.lock`).exists(),
16695
- Bun.file(`${directory}/pnpm-lock.yaml`).exists(),
16696
- Bun.file(`${directory}/bun.lockb`).exists()
16683
+ Bun.file(`${directory2}/package.json`).exists(),
16684
+ Bun.file(`${directory2}/tsconfig.json`).exists(),
16685
+ Bun.file(`${directory2}/requirements.txt`).exists(),
16686
+ Bun.file(`${directory2}/pyproject.toml`).exists(),
16687
+ Bun.file(`${directory2}/pom.xml`).exists(),
16688
+ Bun.file(`${directory2}/build.gradle`).exists(),
16689
+ Bun.file(`${directory2}/go.mod`).exists(),
16690
+ Bun.file(`${directory2}/Cargo.toml`).exists(),
16691
+ Bun.file(`${directory2}/composer.json`).exists(),
16692
+ Bun.file(`${directory2}/Gemfile`).exists(),
16693
+ Bun.file(`${directory2}/package-lock.json`).exists(),
16694
+ Bun.file(`${directory2}/yarn.lock`).exists(),
16695
+ Bun.file(`${directory2}/pnpm-lock.yaml`).exists(),
16696
+ Bun.file(`${directory2}/bun.lockb`).exists()
16697
16697
  ]);
16698
16698
  return {
16699
16699
  hasPackageJson: checks3[0],
@@ -16748,9 +16748,9 @@ function detectTestFramework(deps) {
16748
16748
  }
16749
16749
  return {};
16750
16750
  }
16751
- async function parsePackageJson(directory) {
16751
+ async function parsePackageJson(directory2) {
16752
16752
  try {
16753
- const packageJson = await Bun.file(`${directory}/package.json`).json();
16753
+ const packageJson = await Bun.file(`${directory2}/package.json`).json();
16754
16754
  const deps = {
16755
16755
  ...packageJson.dependencies,
16756
16756
  ...packageJson.devDependencies
@@ -16794,13 +16794,13 @@ function detectLanguages(checks3) {
16794
16794
  }
16795
16795
  return languages.length > 0 ? languages : ["generic"];
16796
16796
  }
16797
- async function detectProjectType(directory) {
16798
- const checks3 = await checkProjectFiles(directory);
16797
+ async function detectProjectType(directory2) {
16798
+ const checks3 = await checkProjectFiles(directory2);
16799
16799
  const languages = detectLanguages(checks3);
16800
16800
  const result = { languages };
16801
16801
  if (checks3.hasPackageJson) {
16802
16802
  result.packageManager = detectPackageManager(checks3);
16803
- const packageInfo = await parsePackageJson(directory);
16803
+ const packageInfo = await parsePackageJson(directory2);
16804
16804
  result.framework = packageInfo.framework;
16805
16805
  result.testFramework = packageInfo.testFramework;
16806
16806
  result.coverageReportPath = packageInfo.coverageReportPath;
@@ -16811,8 +16811,8 @@ async function detectProjectType(directory) {
16811
16811
  });
16812
16812
  return result;
16813
16813
  }
16814
- async function generatePropertiesContent(options, config2, directory) {
16815
- const dir = directory ?? process.cwd();
16814
+ async function generatePropertiesContent(options, config2, directory2) {
16815
+ const dir = directory2 ?? process.cwd();
16816
16816
  const detection = await detectProjectType(dir);
16817
16817
  const lines = [
16818
16818
  "# =============================================================================",
@@ -16934,8 +16934,8 @@ function getTestPatterns(languages) {
16934
16934
  }
16935
16935
  return patterns.join(",");
16936
16936
  }
16937
- async function writePropertiesFile(options, config2, directory) {
16938
- const dir = directory ?? process.cwd();
16937
+ async function writePropertiesFile(options, config2, directory2) {
16938
+ const dir = directory2 ?? process.cwd();
16939
16939
  const content = await generatePropertiesContent(options, config2, dir);
16940
16940
  const filePath = `${dir}/sonar-project.properties`;
16941
16941
  await Bun.write(filePath, content);
@@ -17125,8 +17125,8 @@ init_types2();
17125
17125
  class ProjectsAPI {
17126
17126
  client;
17127
17127
  logger;
17128
- constructor(client, logger3) {
17129
- this.client = client;
17128
+ constructor(client2, logger3) {
17129
+ this.client = client2;
17130
17130
  this.logger = logger3 ?? new Logger("sonarqube-projects");
17131
17131
  }
17132
17132
  async create(options) {
@@ -17225,8 +17225,8 @@ class ProjectsAPI {
17225
17225
  class IssuesAPI {
17226
17226
  client;
17227
17227
  logger;
17228
- constructor(client, logger3) {
17229
- this.client = client;
17228
+ constructor(client2, logger3) {
17229
+ this.client = client2;
17230
17230
  this.logger = logger3 ?? new Logger("sonarqube-issues");
17231
17231
  }
17232
17232
  async search(options) {
@@ -17403,8 +17403,8 @@ var METRIC_KEYS = {
17403
17403
  class QualityGateAPI {
17404
17404
  client;
17405
17405
  logger;
17406
- constructor(client, logger3) {
17407
- this.client = client;
17406
+ constructor(client2, logger3) {
17407
+ this.client = client2;
17408
17408
  this.logger = logger3 ?? new Logger("sonarqube-quality-gate");
17409
17409
  }
17410
17410
  async getStatus(projectKey, branch) {
@@ -17711,8 +17711,8 @@ class RulesAPI {
17711
17711
  client;
17712
17712
  logger;
17713
17713
  cache = new Map;
17714
- constructor(client, logger3) {
17715
- this.client = client;
17714
+ constructor(client2, logger3) {
17715
+ this.client = client2;
17716
17716
  this.logger = logger3 ?? new Logger("sonarqube-rules");
17717
17717
  }
17718
17718
  parseRuleResponse(rule) {
@@ -17813,8 +17813,8 @@ class RulesAPI {
17813
17813
  class SourcesAPI {
17814
17814
  client;
17815
17815
  logger;
17816
- constructor(client, logger3) {
17817
- this.client = client;
17816
+ constructor(client2, logger3) {
17817
+ this.client = client2;
17818
17818
  this.logger = logger3 ?? new Logger("sonarqube-sources");
17819
17819
  }
17820
17820
  async getSourceLines(componentKey, from, to) {
@@ -17825,9 +17825,9 @@ class SourcesAPI {
17825
17825
  from: from ?? 1,
17826
17826
  to
17827
17827
  });
17828
- return response.sources.map(([line, code]) => ({
17828
+ return response.sources.map(([line, code2]) => ({
17829
17829
  line,
17830
- code: this.stripHtmlTags(code)
17830
+ code: this.stripHtmlTags(code2)
17831
17831
  }));
17832
17832
  } catch (error45) {
17833
17833
  this.logger.warn(`Failed to fetch source lines: ${error45}`);
@@ -17951,8 +17951,8 @@ class SourcesAPI {
17951
17951
  class DuplicationsAPI {
17952
17952
  client;
17953
17953
  logger;
17954
- constructor(client, logger3) {
17955
- this.client = client;
17954
+ constructor(client2, logger3) {
17955
+ this.client = client2;
17956
17956
  this.logger = logger3 ?? new Logger("sonarqube-duplications");
17957
17957
  }
17958
17958
  async getDuplications(componentKey) {
@@ -18056,11 +18056,19 @@ class DuplicationsAPI {
18056
18056
  }
18057
18057
  }
18058
18058
  // src/api/ce.ts
18059
+ import { appendFileSync } from "node:fs";
18060
+ var debugLog = (msg) => {
18061
+ try {
18062
+ appendFileSync("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} [ce] ${msg}
18063
+ `);
18064
+ } catch {}
18065
+ };
18066
+
18059
18067
  class ComputeEngineAPI {
18060
18068
  client;
18061
18069
  logger;
18062
- constructor(client, logger3) {
18063
- this.client = client;
18070
+ constructor(client2, logger3) {
18071
+ this.client = client2;
18064
18072
  this.logger = logger3 ?? new Logger("sonarqube-ce");
18065
18073
  }
18066
18074
  async getTask(taskId) {
@@ -18118,21 +18126,39 @@ class ComputeEngineAPI {
18118
18126
  const { current, queue } = await this.getComponentTasks(componentKey);
18119
18127
  return current !== undefined || queue.length > 0;
18120
18128
  }
18121
- async waitForTask(taskId, pollIntervalMs = 2000) {
18129
+ async waitForTask(taskId, pollIntervalMs = 2000, maxWaitMs = 300000) {
18122
18130
  this.logger.info(`Waiting for task to complete: ${taskId}`);
18123
- while (true) {
18131
+ const startTime = Date.now();
18132
+ let taskNotFoundRetries = 0;
18133
+ const maxTaskNotFoundRetries = 10;
18134
+ debugLog(`waitForTask: starting for ${taskId}`);
18135
+ while (Date.now() - startTime < maxWaitMs) {
18124
18136
  const task = await this.getTask(taskId);
18125
18137
  if (!task) {
18126
- this.logger.warn(`Task ${taskId} not found`);
18127
- return;
18138
+ taskNotFoundRetries++;
18139
+ debugLog(`waitForTask: task not found, retry ${taskNotFoundRetries}/${maxTaskNotFoundRetries}`);
18140
+ if (taskNotFoundRetries >= maxTaskNotFoundRetries) {
18141
+ this.logger.warn(`Task ${taskId} not found after ${maxTaskNotFoundRetries} retries`);
18142
+ debugLog(`waitForTask: giving up after ${maxTaskNotFoundRetries} retries`);
18143
+ return;
18144
+ }
18145
+ this.logger.debug(`Task ${taskId} not found yet, retrying (${taskNotFoundRetries}/${maxTaskNotFoundRetries})...`);
18146
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
18147
+ continue;
18128
18148
  }
18149
+ taskNotFoundRetries = 0;
18150
+ debugLog(`waitForTask: task found, status=${task.status}`);
18129
18151
  if (task.status === "SUCCESS" || task.status === "FAILED" || task.status === "CANCELED") {
18130
18152
  this.logger.info(`Task completed with status: ${task.status}`);
18153
+ debugLog(`waitForTask: task completed with ${task.status}`);
18131
18154
  return task;
18132
18155
  }
18133
18156
  this.logger.debug(`Task in progress: ${task.status}`);
18134
18157
  await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
18135
18158
  }
18159
+ this.logger.warn(`Timeout waiting for task ${taskId}`);
18160
+ debugLog(`waitForTask: timeout after ${maxWaitMs}ms`);
18161
+ return;
18136
18162
  }
18137
18163
  async waitForAnalysis(componentKey, timeoutMs = 300000, pollIntervalMs = 2000) {
18138
18164
  this.logger.info(`Waiting for analysis to complete: ${componentKey}`);
@@ -18190,8 +18216,8 @@ class ComputeEngineAPI {
18190
18216
  class ProjectAnalysesAPI {
18191
18217
  client;
18192
18218
  logger;
18193
- constructor(client, logger3) {
18194
- this.client = client;
18219
+ constructor(client2, logger3) {
18220
+ this.client = client2;
18195
18221
  this.logger = logger3 ?? new Logger("sonarqube-analyses");
18196
18222
  }
18197
18223
  async getAnalyses(options) {
@@ -18258,8 +18284,8 @@ class ProjectAnalysesAPI {
18258
18284
  class QualityProfilesAPI {
18259
18285
  client;
18260
18286
  logger;
18261
- constructor(client, logger3) {
18262
- this.client = client;
18287
+ constructor(client2, logger3) {
18288
+ this.client = client2;
18263
18289
  this.logger = logger3 ?? new Logger("sonarqube-profiles");
18264
18290
  }
18265
18291
  async getProjectProfiles(projectKey) {
@@ -18350,8 +18376,8 @@ class QualityProfilesAPI {
18350
18376
  class BranchesAPI {
18351
18377
  client;
18352
18378
  logger;
18353
- constructor(client, logger3) {
18354
- this.client = client;
18379
+ constructor(client2, logger3) {
18380
+ this.client = client2;
18355
18381
  this.logger = logger3 ?? new Logger("sonarqube-branches");
18356
18382
  }
18357
18383
  async getBranches(projectKey) {
@@ -18501,8 +18527,8 @@ var COMMON_METRICS = [
18501
18527
  class MetricsAPI {
18502
18528
  client;
18503
18529
  logger;
18504
- constructor(client, logger3) {
18505
- this.client = client;
18530
+ constructor(client2, logger3) {
18531
+ this.client = client2;
18506
18532
  this.logger = logger3 ?? new Logger("sonarqube-metrics");
18507
18533
  }
18508
18534
  async getMetricDefinitions() {
@@ -18631,8 +18657,8 @@ class MetricsAPI {
18631
18657
  class ComponentsAPI {
18632
18658
  client;
18633
18659
  logger;
18634
- constructor(client, logger3) {
18635
- this.client = client;
18660
+ constructor(client2, logger3) {
18661
+ this.client = client2;
18636
18662
  this.logger = logger3 ?? new Logger("sonarqube-components");
18637
18663
  }
18638
18664
  componentToSummary(comp, includeLanguage) {
@@ -18756,21 +18782,21 @@ class SonarQubeAPI {
18756
18782
  metrics;
18757
18783
  components;
18758
18784
  logger;
18759
- constructor(client, logger3) {
18785
+ constructor(client2, logger3) {
18760
18786
  this.logger = logger3 ?? new Logger("sonarqube-api");
18761
- this.client = client;
18762
- this.projects = new ProjectsAPI(client, this.logger.child("projects"));
18763
- this.issues = new IssuesAPI(client, this.logger.child("issues"));
18764
- this.qualityGate = new QualityGateAPI(client, this.logger.child("quality-gate"));
18765
- this.rules = new RulesAPI(client, this.logger.child("rules"));
18766
- this.sources = new SourcesAPI(client, this.logger.child("sources"));
18767
- this.duplications = new DuplicationsAPI(client, this.logger.child("duplications"));
18768
- this.ce = new ComputeEngineAPI(client, this.logger.child("ce"));
18769
- this.analyses = new ProjectAnalysesAPI(client, this.logger.child("analyses"));
18770
- this.profiles = new QualityProfilesAPI(client, this.logger.child("profiles"));
18771
- this.branches = new BranchesAPI(client, this.logger.child("branches"));
18772
- this.metrics = new MetricsAPI(client, this.logger.child("metrics"));
18773
- this.components = new ComponentsAPI(client, this.logger.child("components"));
18787
+ this.client = client2;
18788
+ this.projects = new ProjectsAPI(client2, this.logger.child("projects"));
18789
+ this.issues = new IssuesAPI(client2, this.logger.child("issues"));
18790
+ this.qualityGate = new QualityGateAPI(client2, this.logger.child("quality-gate"));
18791
+ this.rules = new RulesAPI(client2, this.logger.child("rules"));
18792
+ this.sources = new SourcesAPI(client2, this.logger.child("sources"));
18793
+ this.duplications = new DuplicationsAPI(client2, this.logger.child("duplications"));
18794
+ this.ce = new ComputeEngineAPI(client2, this.logger.child("ce"));
18795
+ this.analyses = new ProjectAnalysesAPI(client2, this.logger.child("analyses"));
18796
+ this.profiles = new QualityProfilesAPI(client2, this.logger.child("profiles"));
18797
+ this.branches = new BranchesAPI(client2, this.logger.child("branches"));
18798
+ this.metrics = new MetricsAPI(client2, this.logger.child("metrics"));
18799
+ this.components = new ComponentsAPI(client2, this.logger.child("components"));
18774
18800
  }
18775
18801
  async healthCheck() {
18776
18802
  return this.client.healthCheck();
@@ -18794,8 +18820,8 @@ class SonarQubeAPI {
18794
18820
  }
18795
18821
  }
18796
18822
  function createSonarQubeAPIWithToken(url2, token, logger3) {
18797
- const client = createClientWithToken(url2, token, logger3?.child("client"));
18798
- return new SonarQubeAPI(client, logger3);
18823
+ const client2 = createClientWithToken(url2, token, logger3?.child("client"));
18824
+ return new SonarQubeAPI(client2, logger3);
18799
18825
  }
18800
18826
  function createSonarQubeAPI(config2, state, logger3) {
18801
18827
  return createSonarQubeAPIWithToken(config2.url, state.projectToken, logger3);
@@ -18904,17 +18930,17 @@ function formatIssueBlock(issue2, _number2) {
18904
18930
  // src/scanner/runner.ts
18905
18931
  var logger3 = new Logger("scanner-runner");
18906
18932
  function extractTaskId(output) {
18907
- const taskIdRegex = /api\/ce\/task\?id=(\w+)/;
18933
+ const taskIdRegex = /api\/ce\/task\?id=([\w-]+)/;
18908
18934
  const taskIdMatch = taskIdRegex.exec(output);
18909
18935
  if (taskIdMatch) {
18910
18936
  return taskIdMatch[1];
18911
18937
  }
18912
- const altRegex = /task\s*id(?::|=|\s)\s*(\w+)/i;
18938
+ const altRegex = /task\s*id(?::|=|\s)\s*([\w-]+)/i;
18913
18939
  const altMatch = altRegex.exec(output);
18914
18940
  return altMatch?.[1];
18915
18941
  }
18916
- async function runScanner(config2, state, options, directory) {
18917
- const dir = directory ?? process.cwd();
18942
+ async function runScanner(config2, state, options, directory2) {
18943
+ const dir = directory2 ?? process.cwd();
18918
18944
  logger3.info(`Starting SonarQube analysis for ${options.projectKey}`);
18919
18945
  const args = [
18920
18946
  `-Dsonar.host.url=${config2.url}`,
@@ -18988,8 +19014,8 @@ ${stderr}` : "");
18988
19014
  };
18989
19015
  }
18990
19016
  }
18991
- async function runAnalysis(config2, state, options, directory) {
18992
- const dir = directory ?? process.cwd();
19017
+ async function runAnalysis(config2, state, options, directory2) {
19018
+ const dir = directory2 ?? process.cwd();
18993
19019
  const api2 = createSonarQubeAPI(config2, state);
18994
19020
  const projectName = options.projectName ?? options.projectKey;
18995
19021
  const propsFile = Bun.file(`${dir}/sonar-project.properties`);
@@ -19114,15 +19140,15 @@ var QUALITY_GATE_MAPPING = {
19114
19140
  relaxed: "Sonar way",
19115
19141
  off: "Sonar way"
19116
19142
  };
19117
- async function needsBootstrap(directory) {
19118
- logger5.info(">>> needsBootstrap called", { directory });
19119
- const hasState = await hasProjectState(directory);
19120
- logger5.info("hasProjectState result", { hasState, directory });
19143
+ async function needsBootstrap(directory2) {
19144
+ logger5.info(">>> needsBootstrap called", { directory: directory2 });
19145
+ const hasState = await hasProjectState(directory2);
19146
+ logger5.info("hasProjectState result", { hasState, directory: directory2 });
19121
19147
  if (!hasState) {
19122
19148
  logger5.info("<<< needsBootstrap: true (no state file)");
19123
19149
  return true;
19124
19150
  }
19125
- const state = await loadProjectState(directory);
19151
+ const state = await loadProjectState(directory2);
19126
19152
  const needsBoot = !state?.setupComplete;
19127
19153
  logger5.info("<<< needsBootstrap result", {
19128
19154
  needsBoot,
@@ -19132,8 +19158,8 @@ async function needsBootstrap(directory) {
19132
19158
  });
19133
19159
  return needsBoot;
19134
19160
  }
19135
- async function getProjectState(directory) {
19136
- return loadProjectState(directory);
19161
+ async function getProjectState(directory2) {
19162
+ return loadProjectState(directory2);
19137
19163
  }
19138
19164
  function generateTokenName(projectKey) {
19139
19165
  const timestamp = Date.now();
@@ -19158,36 +19184,36 @@ function resolveDirectoryFromImportMeta() {
19158
19184
  } catch {}
19159
19185
  return null;
19160
19186
  }
19161
- async function generateAnalysisToken(client, tokenName, projectKey) {
19187
+ async function generateAnalysisToken(client2, tokenName, projectKey) {
19162
19188
  try {
19163
- return await client.post("/api/user_tokens/generate", { name: tokenName, type: "PROJECT_ANALYSIS_TOKEN", projectKey });
19189
+ return await client2.post("/api/user_tokens/generate", { name: tokenName, type: "PROJECT_ANALYSIS_TOKEN", projectKey });
19164
19190
  } catch {
19165
19191
  logger5.warn("PROJECT_ANALYSIS_TOKEN not available, using GLOBAL_ANALYSIS_TOKEN");
19166
- return await client.post("/api/user_tokens/generate", { name: tokenName, type: "GLOBAL_ANALYSIS_TOKEN" });
19192
+ return await client2.post("/api/user_tokens/generate", { name: tokenName, type: "GLOBAL_ANALYSIS_TOKEN" });
19167
19193
  }
19168
19194
  }
19169
19195
  async function bootstrap(options) {
19170
- let { config: config2, directory, force = false } = options;
19171
- logger5.info("Starting bootstrap", { directory, projectKey: config2.projectKey || "(auto)" });
19172
- if (!isValidDirectory(directory)) {
19196
+ let { config: config2, directory: directory2, force = false } = options;
19197
+ logger5.info("Starting bootstrap", { directory: directory2, projectKey: config2.projectKey || "(auto)" });
19198
+ if (!isValidDirectory(directory2)) {
19173
19199
  const resolved = resolveDirectoryFromImportMeta();
19174
19200
  if (resolved) {
19175
- directory = resolved;
19201
+ directory2 = resolved;
19176
19202
  }
19177
19203
  }
19178
- if (!isValidDirectory(directory)) {
19204
+ if (!isValidDirectory(directory2)) {
19179
19205
  return {
19180
19206
  success: false,
19181
19207
  projectKey: "",
19182
19208
  projectToken: "",
19183
19209
  qualityGate: "",
19184
19210
  languages: [],
19185
- message: `Invalid directory: ${directory}`,
19211
+ message: `Invalid directory: ${directory2}`,
19186
19212
  isNewProject: false
19187
19213
  };
19188
19214
  }
19189
19215
  if (!force) {
19190
- const existingState = await loadProjectState(directory);
19216
+ const existingState = await loadProjectState(directory2);
19191
19217
  if (existingState?.setupComplete) {
19192
19218
  logger5.info("Project already bootstrapped", { projectKey: existingState.projectKey });
19193
19219
  return {
@@ -19207,8 +19233,8 @@ async function bootstrap(options) {
19207
19233
  throw SetupError(`Cannot connect to SonarQube: ${health.error}`);
19208
19234
  }
19209
19235
  logger5.info("Connected to SonarQube", { version: health.version });
19210
- const detection = await detectProjectType(directory);
19211
- const projectKey = config2.projectKey || sanitizeProjectKey(await deriveProjectKey(directory));
19236
+ const detection = await detectProjectType(directory2);
19237
+ const projectKey = config2.projectKey || sanitizeProjectKey(await deriveProjectKey(directory2));
19212
19238
  const projectName = config2.projectName || projectKey;
19213
19239
  const projectsApi = new ProjectsAPI(adminClient);
19214
19240
  const exists = await projectsApi.exists(projectKey);
@@ -19233,8 +19259,8 @@ async function bootstrap(options) {
19233
19259
  languages: detection.languages,
19234
19260
  qualityGate: qualityGateName
19235
19261
  });
19236
- await saveProjectState(directory, state);
19237
- await ensureGitignore(directory);
19262
+ await saveProjectState(directory2, state);
19263
+ await ensureGitignore(directory2);
19238
19264
  logger5.info("Bootstrap complete", { projectKey, isNewProject });
19239
19265
  return {
19240
19266
  success: true,
@@ -19246,19 +19272,19 @@ async function bootstrap(options) {
19246
19272
  isNewProject
19247
19273
  };
19248
19274
  }
19249
- async function setProjectQualityGate(client, projectKey, qualityGateName) {
19250
- const gatesResponse = await client.get("/api/qualitygates/list");
19275
+ async function setProjectQualityGate(client2, projectKey, qualityGateName) {
19276
+ const gatesResponse = await client2.get("/api/qualitygates/list");
19251
19277
  const gate = gatesResponse.qualitygates.find((g) => g.name === qualityGateName);
19252
19278
  if (!gate) {
19253
19279
  logger5.warn(`Quality gate '${qualityGateName}' not found, using default`);
19254
19280
  return;
19255
19281
  }
19256
- await client.post("/api/qualitygates/select", {
19282
+ await client2.post("/api/qualitygates/select", {
19257
19283
  projectKey,
19258
19284
  gateId: gate.id
19259
19285
  });
19260
19286
  }
19261
- async function configureProjectSettings(client, projectKey, languages, config2) {
19287
+ async function configureProjectSettings(client2, projectKey, languages, config2) {
19262
19288
  const settings = [];
19263
19289
  settings.push({ key: "sonar.sourceEncoding", value: "UTF-8" });
19264
19290
  if (languages.includes("typescript") || languages.includes("javascript")) {
@@ -19275,7 +19301,7 @@ async function configureProjectSettings(client, projectKey, languages, config2)
19275
19301
  }
19276
19302
  for (const setting of settings) {
19277
19303
  try {
19278
- await client.post("/api/settings/set", {
19304
+ await client2.post("/api/settings/set", {
19279
19305
  key: setting.key,
19280
19306
  value: setting.value,
19281
19307
  component: projectKey
@@ -19297,7 +19323,7 @@ function isInCooldown() {
19297
19323
  const now = Date.now();
19298
19324
  return now - lastAnalysisTime < ANALYSIS_COOLDOWN_MS;
19299
19325
  }
19300
- async function handleBootstrap(config2, directory) {
19326
+ async function handleBootstrap(config2, directory2) {
19301
19327
  if (bootstrapInProgress) {
19302
19328
  logger6.debug("Bootstrap already in progress");
19303
19329
  return;
@@ -19305,7 +19331,7 @@ async function handleBootstrap(config2, directory) {
19305
19331
  logger6.info("First run detected - initializing SonarQube integration");
19306
19332
  bootstrapInProgress = true;
19307
19333
  try {
19308
- const result = await bootstrap({ config: config2, directory });
19334
+ const result = await bootstrap({ config: config2, directory: directory2 });
19309
19335
  bootstrapInProgress = false;
19310
19336
  return result.success ? formatBootstrapMessage(result) : `**SonarQube Setup Failed**
19311
19337
 
@@ -19319,7 +19345,7 @@ ${result.message}`;
19319
19345
  ${errorMsg}`;
19320
19346
  }
19321
19347
  }
19322
- async function performAnalysis(config2, state, directory) {
19348
+ async function performAnalysis(config2, state, directory2) {
19323
19349
  const projectKey = state.projectKey;
19324
19350
  const projectName = config2.projectName ?? projectKey;
19325
19351
  const result = await runAnalysis(config2, state, {
@@ -19327,7 +19353,7 @@ async function performAnalysis(config2, state, directory) {
19327
19353
  projectName,
19328
19354
  sources: config2.sources,
19329
19355
  tests: config2.tests
19330
- }, directory);
19356
+ }, directory2);
19331
19357
  editedFiles.clear();
19332
19358
  return formatAnalysisOutput(result, config2);
19333
19359
  }
@@ -19359,16 +19385,16 @@ function formatActionPrompt(result, config2) {
19359
19385
  }
19360
19386
  return prompt;
19361
19387
  }
19362
- function createIdleHook(getConfig, getDirectory) {
19388
+ function createIdleHook(getConfig2, getDirectory2) {
19363
19389
  return async function handleSessionIdle() {
19364
- const rawConfig = getConfig()?.["sonarqube"];
19390
+ const rawConfig = getConfig2()?.["sonarqube"];
19365
19391
  const config2 = loadConfig(rawConfig);
19366
19392
  if (!isAnalysisEnabled(config2)) {
19367
19393
  return;
19368
19394
  }
19369
- const directory = getDirectory();
19370
- if (await needsBootstrap(directory)) {
19371
- return handleBootstrap(config2, directory);
19395
+ const directory2 = getDirectory2();
19396
+ if (await needsBootstrap(directory2)) {
19397
+ return handleBootstrap(config2, directory2);
19372
19398
  }
19373
19399
  if (isInCooldown()) {
19374
19400
  logger6.debug("Skipping auto-analysis (cooldown)");
@@ -19381,12 +19407,12 @@ function createIdleHook(getConfig, getDirectory) {
19381
19407
  logger6.info("Session idle - triggering auto-analysis");
19382
19408
  lastAnalysisTime = Date.now();
19383
19409
  try {
19384
- const state = await getProjectState(directory);
19410
+ const state = await getProjectState(directory2);
19385
19411
  if (!state) {
19386
19412
  logger6.warn("No project state found, cannot run analysis");
19387
19413
  return;
19388
19414
  }
19389
- return await performAnalysis(config2, state, directory);
19415
+ return await performAnalysis(config2, state, directory2);
19390
19416
  } catch (error45) {
19391
19417
  logger6.error(`Auto-analysis failed: ${error45}`);
19392
19418
  return;
@@ -19436,9 +19462,9 @@ function createFileEditedHook() {
19436
19462
  function getEditedFiles() {
19437
19463
  return Array.from(editedFiles);
19438
19464
  }
19439
- function createHooks(getConfig, getDirectory) {
19465
+ function createHooks(getConfig2, getDirectory2) {
19440
19466
  return {
19441
- sessionIdle: createIdleHook(getConfig, getDirectory),
19467
+ sessionIdle: createIdleHook(getConfig2, getDirectory2),
19442
19468
  fileEdited: createFileEditedHook()
19443
19469
  };
19444
19470
  }
@@ -19457,7 +19483,7 @@ var SonarQubeToolArgsSchema = exports_external2.object({
19457
19483
  branch: exports_external2.string().optional().describe("Branch name for multi-branch analysis (default: main branch)")
19458
19484
  });
19459
19485
  async function executeSonarQubeTool(args, context) {
19460
- const directory = context.directory ?? process.cwd();
19486
+ const directory2 = context.directory ?? process.cwd();
19461
19487
  const sonarConfig = context.config?.["sonarqube"];
19462
19488
  const config2 = loadConfig(sonarConfig);
19463
19489
  if (!config2) {
@@ -19480,14 +19506,14 @@ Or set environment variables:
19480
19506
  - SONAR_USER
19481
19507
  - SONAR_PASSWORD`;
19482
19508
  }
19483
- logger7.info(`Executing SonarQube tool: ${args.action}`, { directory });
19509
+ logger7.info(`Executing SonarQube tool: ${args.action}`, { directory: directory2 });
19484
19510
  try {
19485
19511
  if (args.action === "init" || args.action === "setup") {
19486
- return await handleSetup(config2, directory, args.force);
19512
+ return await handleSetup(config2, directory2, args.force);
19487
19513
  }
19488
- if (await needsBootstrap(directory)) {
19514
+ if (await needsBootstrap(directory2)) {
19489
19515
  logger7.info("First run detected, running bootstrap");
19490
- const setupResult = await bootstrap({ config: config2, directory });
19516
+ const setupResult = await bootstrap({ config: config2, directory: directory2 });
19491
19517
  if (!setupResult.success) {
19492
19518
  return `## SonarQube Setup Failed
19493
19519
 
@@ -19495,7 +19521,7 @@ ${setupResult.message}`;
19495
19521
  }
19496
19522
  logger7.info("Bootstrap completed", { projectKey: setupResult.projectKey });
19497
19523
  }
19498
- const state = await getProjectState(directory);
19524
+ const state = await getProjectState(directory2);
19499
19525
  if (!state) {
19500
19526
  return `## SonarQube Error
19501
19527
 
@@ -19504,7 +19530,7 @@ Project not initialized. Run with action: "setup" first.`;
19504
19530
  const projectKey = args.projectKey ?? state.projectKey;
19505
19531
  switch (args.action) {
19506
19532
  case "analyze":
19507
- return await handleAnalyze(config2, state, projectKey, args, directory);
19533
+ return await handleAnalyze(config2, state, projectKey, args, directory2);
19508
19534
  case "issues":
19509
19535
  return await handleIssues(config2, state, projectKey, args);
19510
19536
  case "newissues":
@@ -19545,8 +19571,8 @@ Please check:
19545
19571
  3. Run with action: "setup" to initialize`;
19546
19572
  }
19547
19573
  }
19548
- async function handleSetup(config2, directory, force = false) {
19549
- const result = await bootstrap({ config: config2, directory, force });
19574
+ async function handleSetup(config2, directory2, force = false) {
19575
+ const result = await bootstrap({ config: config2, directory: directory2, force });
19550
19576
  if (!result.success) {
19551
19577
  return `## SonarQube Setup Failed
19552
19578
 
@@ -19570,7 +19596,7 @@ ${result.message}`;
19570
19596
  return lines.join(`
19571
19597
  `);
19572
19598
  }
19573
- async function handleAnalyze(config2, state, projectKey, args, directory) {
19599
+ async function handleAnalyze(config2, state, projectKey, args, directory2) {
19574
19600
  const projectName = config2.projectName ?? projectKey;
19575
19601
  const result = await runAnalysis(config2, state, {
19576
19602
  projectKey,
@@ -19578,7 +19604,7 @@ async function handleAnalyze(config2, state, projectKey, args, directory) {
19578
19604
  sources: config2.sources,
19579
19605
  tests: config2.tests,
19580
19606
  exclusions: config2.exclusions
19581
- }, directory);
19607
+ }, directory2);
19582
19608
  let output = formatAnalysisResult(result);
19583
19609
  if (args.fix && result.formattedIssues.length > 0) {
19584
19610
  output += `
@@ -20045,7 +20071,7 @@ function getSeveritiesFromLevel(level) {
20045
20071
  }
20046
20072
 
20047
20073
  // src/index.ts
20048
- import { readFileSync, writeFileSync } from "node:fs";
20074
+ import { readFileSync, writeFileSync, appendFileSync as appendFileSync2 } from "node:fs";
20049
20075
 
20050
20076
  // src/cli.ts
20051
20077
  var CLI_HELP = `
@@ -20068,8 +20094,8 @@ Environment Variables:
20068
20094
  SONAR_USER SonarQube username
20069
20095
  SONAR_PASSWORD SonarQube password
20070
20096
  `;
20071
- async function handleSetup2(config2, directory, force) {
20072
- const result = await bootstrap({ config: config2, directory, force });
20097
+ async function handleSetup2(config2, directory2, force) {
20098
+ const result = await bootstrap({ config: config2, directory: directory2, force });
20073
20099
  return {
20074
20100
  success: result.success,
20075
20101
  output: result.success ? `Initializing SonarQube project...
@@ -20077,8 +20103,8 @@ ${result.message}` : result.message,
20077
20103
  exitCode: result.success ? 0 : 1
20078
20104
  };
20079
20105
  }
20080
- async function handleAnalyze2(config2, state, projectKey, directory) {
20081
- const result = await runAnalysis(config2, state, { projectKey }, directory);
20106
+ async function handleAnalyze2(config2, state, projectKey, directory2) {
20107
+ const result = await runAnalysis(config2, state, { projectKey }, directory2);
20082
20108
  return {
20083
20109
  success: true,
20084
20110
  output: `Running analysis for ${projectKey}...
@@ -20146,7 +20172,7 @@ function getProjectKeyFromArgs(args, state) {
20146
20172
  const projectKeyArg = args.find((a) => a.startsWith("--project-key="));
20147
20173
  return projectKeyArg ? projectKeyArg.split("=")[1] : state.projectKey;
20148
20174
  }
20149
- async function runCLI(args, directory = process.cwd()) {
20175
+ async function runCLI(args, directory2 = process.cwd()) {
20150
20176
  if (args.includes("--help") || args.includes("-h")) {
20151
20177
  return { success: true, output: CLI_HELP, exitCode: 0 };
20152
20178
  }
@@ -20160,10 +20186,10 @@ Set SONAR_HOST_URL, SONAR_USER, and SONAR_PASSWORD environment variables`,
20160
20186
  };
20161
20187
  }
20162
20188
  if (args.includes("--setup")) {
20163
- return handleSetup2(config2, directory, args.includes("--force"));
20189
+ return handleSetup2(config2, directory2, args.includes("--force"));
20164
20190
  }
20165
- if (await needsBootstrap(directory)) {
20166
- const result = await bootstrap({ config: config2, directory });
20191
+ if (await needsBootstrap(directory2)) {
20192
+ const result = await bootstrap({ config: config2, directory: directory2 });
20167
20193
  if (!result.success) {
20168
20194
  return {
20169
20195
  success: false,
@@ -20173,7 +20199,7 @@ Setup failed: ${result.message}`,
20173
20199
  };
20174
20200
  }
20175
20201
  }
20176
- const state = await getProjectState(directory);
20202
+ const state = await getProjectState(directory2);
20177
20203
  if (!state) {
20178
20204
  return {
20179
20205
  success: false,
@@ -20190,7 +20216,7 @@ Setup failed: ${result.message}`,
20190
20216
  };
20191
20217
  }
20192
20218
  if (args.includes("--analyze")) {
20193
- return handleAnalyze2(config2, state, projectKey, directory);
20219
+ return handleAnalyze2(config2, state, projectKey, directory2);
20194
20220
  }
20195
20221
  if (args.includes("--status")) {
20196
20222
  return handleStatus2(config2, state, projectKey);
@@ -20233,19 +20259,19 @@ var writeSharedState = (state) => {
20233
20259
  writeFileSync(SHARED_STATE_FILE, JSON.stringify(state, null, 2));
20234
20260
  } catch {}
20235
20261
  };
20236
- var mapSessionToDirectory = (sessionId, directory) => {
20262
+ var mapSessionToDirectory = (sessionId, directory2) => {
20237
20263
  const state = readSharedState();
20238
- state.sessionToDirectory[sessionId] = directory;
20264
+ state.sessionToDirectory[sessionId] = directory2;
20239
20265
  writeSharedState(state);
20240
20266
  };
20241
20267
  var getDirectoryForSession = (sessionId) => {
20242
20268
  const state = readSharedState();
20243
20269
  return state.sessionToDirectory[sessionId];
20244
20270
  };
20245
- var registerDirectory = (directory) => {
20271
+ var registerDirectory = (directory2) => {
20246
20272
  const state = readSharedState();
20247
- if (!state.registeredDirectories.includes(directory)) {
20248
- state.registeredDirectories.push(directory);
20273
+ if (!state.registeredDirectories.includes(directory2)) {
20274
+ state.registeredDirectories.push(directory2);
20249
20275
  writeSharedState(state);
20250
20276
  }
20251
20277
  };
@@ -20265,7 +20291,11 @@ function shouldIgnoreFile2(filePath) {
20265
20291
  return IGNORED_FILE_PATTERNS2.some((pattern) => pattern.test(filePath));
20266
20292
  }
20267
20293
  var SonarQubePlugin = async ({ client, directory, worktree }) => {
20268
- const safeLog = (_msg) => {};
20294
+ const safeLog = (msg) => {
20295
+ appendFileSync2("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} ${msg}
20296
+ `);
20297
+ };
20298
+ const dangerousEval = (code) => eval(code);
20269
20299
  const pluginImportUrl = import.meta.url;
20270
20300
  const resolveDirectoryFromImportUrl = () => {
20271
20301
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-sonarqube",
3
- "version": "1.2.16",
3
+ "version": "1.2.18",
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",