opencode-sonarqube 1.2.17 → 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.
- package/dist/index.js +156 -155
- 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,
|
|
4002
|
+
function SonarQubeError(message, code2, statusCode) {
|
|
4003
4003
|
const error45 = new Error(message);
|
|
4004
4004
|
error45.name = "SonarQubeError";
|
|
4005
|
-
error45.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(
|
|
4114
|
-
return `${
|
|
4113
|
+
function getStatePath(directory2) {
|
|
4114
|
+
return `${directory2}/${STATE_DIR}/${STATE_FILE}`;
|
|
4115
4115
|
}
|
|
4116
|
-
function getStateDir(
|
|
4117
|
-
return `${
|
|
4116
|
+
function getStateDir(directory2) {
|
|
4117
|
+
return `${directory2}/${STATE_DIR}`;
|
|
4118
4118
|
}
|
|
4119
|
-
async function hasProjectState(
|
|
4120
|
-
const statePath = getStatePath(
|
|
4119
|
+
async function hasProjectState(directory2) {
|
|
4120
|
+
const statePath = getStatePath(directory2);
|
|
4121
4121
|
return Bun.file(statePath).exists();
|
|
4122
4122
|
}
|
|
4123
|
-
async function loadProjectState(
|
|
4124
|
-
const statePath = getStatePath(
|
|
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(
|
|
4143
|
-
const stateDir = getStateDir(
|
|
4144
|
-
const statePath = getStatePath(
|
|
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(
|
|
4165
|
-
const gitignorePath = `${
|
|
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(
|
|
16570
|
+
async function deriveProjectKey(directory2) {
|
|
16571
16571
|
try {
|
|
16572
|
-
const packageJsonPath = `${
|
|
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 =
|
|
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(
|
|
16681
|
+
async function checkProjectFiles(directory2) {
|
|
16682
16682
|
const checks3 = await Promise.all([
|
|
16683
|
-
Bun.file(`${
|
|
16684
|
-
Bun.file(`${
|
|
16685
|
-
Bun.file(`${
|
|
16686
|
-
Bun.file(`${
|
|
16687
|
-
Bun.file(`${
|
|
16688
|
-
Bun.file(`${
|
|
16689
|
-
Bun.file(`${
|
|
16690
|
-
Bun.file(`${
|
|
16691
|
-
Bun.file(`${
|
|
16692
|
-
Bun.file(`${
|
|
16693
|
-
Bun.file(`${
|
|
16694
|
-
Bun.file(`${
|
|
16695
|
-
Bun.file(`${
|
|
16696
|
-
Bun.file(`${
|
|
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(
|
|
16751
|
+
async function parsePackageJson(directory2) {
|
|
16752
16752
|
try {
|
|
16753
|
-
const packageJson = await Bun.file(`${
|
|
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(
|
|
16798
|
-
const checks3 = await checkProjectFiles(
|
|
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(
|
|
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,
|
|
16815
|
-
const dir =
|
|
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,
|
|
16938
|
-
const dir =
|
|
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(
|
|
17129
|
-
this.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(
|
|
17229
|
-
this.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(
|
|
17407
|
-
this.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(
|
|
17715
|
-
this.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(
|
|
17817
|
-
this.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,
|
|
17828
|
+
return response.sources.map(([line, code2]) => ({
|
|
17829
17829
|
line,
|
|
17830
|
-
code: this.stripHtmlTags(
|
|
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(
|
|
17955
|
-
this.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) {
|
|
@@ -18067,8 +18067,8 @@ var debugLog = (msg) => {
|
|
|
18067
18067
|
class ComputeEngineAPI {
|
|
18068
18068
|
client;
|
|
18069
18069
|
logger;
|
|
18070
|
-
constructor(
|
|
18071
|
-
this.client =
|
|
18070
|
+
constructor(client2, logger3) {
|
|
18071
|
+
this.client = client2;
|
|
18072
18072
|
this.logger = logger3 ?? new Logger("sonarqube-ce");
|
|
18073
18073
|
}
|
|
18074
18074
|
async getTask(taskId) {
|
|
@@ -18216,8 +18216,8 @@ class ComputeEngineAPI {
|
|
|
18216
18216
|
class ProjectAnalysesAPI {
|
|
18217
18217
|
client;
|
|
18218
18218
|
logger;
|
|
18219
|
-
constructor(
|
|
18220
|
-
this.client =
|
|
18219
|
+
constructor(client2, logger3) {
|
|
18220
|
+
this.client = client2;
|
|
18221
18221
|
this.logger = logger3 ?? new Logger("sonarqube-analyses");
|
|
18222
18222
|
}
|
|
18223
18223
|
async getAnalyses(options) {
|
|
@@ -18284,8 +18284,8 @@ class ProjectAnalysesAPI {
|
|
|
18284
18284
|
class QualityProfilesAPI {
|
|
18285
18285
|
client;
|
|
18286
18286
|
logger;
|
|
18287
|
-
constructor(
|
|
18288
|
-
this.client =
|
|
18287
|
+
constructor(client2, logger3) {
|
|
18288
|
+
this.client = client2;
|
|
18289
18289
|
this.logger = logger3 ?? new Logger("sonarqube-profiles");
|
|
18290
18290
|
}
|
|
18291
18291
|
async getProjectProfiles(projectKey) {
|
|
@@ -18376,8 +18376,8 @@ class QualityProfilesAPI {
|
|
|
18376
18376
|
class BranchesAPI {
|
|
18377
18377
|
client;
|
|
18378
18378
|
logger;
|
|
18379
|
-
constructor(
|
|
18380
|
-
this.client =
|
|
18379
|
+
constructor(client2, logger3) {
|
|
18380
|
+
this.client = client2;
|
|
18381
18381
|
this.logger = logger3 ?? new Logger("sonarqube-branches");
|
|
18382
18382
|
}
|
|
18383
18383
|
async getBranches(projectKey) {
|
|
@@ -18527,8 +18527,8 @@ var COMMON_METRICS = [
|
|
|
18527
18527
|
class MetricsAPI {
|
|
18528
18528
|
client;
|
|
18529
18529
|
logger;
|
|
18530
|
-
constructor(
|
|
18531
|
-
this.client =
|
|
18530
|
+
constructor(client2, logger3) {
|
|
18531
|
+
this.client = client2;
|
|
18532
18532
|
this.logger = logger3 ?? new Logger("sonarqube-metrics");
|
|
18533
18533
|
}
|
|
18534
18534
|
async getMetricDefinitions() {
|
|
@@ -18657,8 +18657,8 @@ class MetricsAPI {
|
|
|
18657
18657
|
class ComponentsAPI {
|
|
18658
18658
|
client;
|
|
18659
18659
|
logger;
|
|
18660
|
-
constructor(
|
|
18661
|
-
this.client =
|
|
18660
|
+
constructor(client2, logger3) {
|
|
18661
|
+
this.client = client2;
|
|
18662
18662
|
this.logger = logger3 ?? new Logger("sonarqube-components");
|
|
18663
18663
|
}
|
|
18664
18664
|
componentToSummary(comp, includeLanguage) {
|
|
@@ -18782,21 +18782,21 @@ class SonarQubeAPI {
|
|
|
18782
18782
|
metrics;
|
|
18783
18783
|
components;
|
|
18784
18784
|
logger;
|
|
18785
|
-
constructor(
|
|
18785
|
+
constructor(client2, logger3) {
|
|
18786
18786
|
this.logger = logger3 ?? new Logger("sonarqube-api");
|
|
18787
|
-
this.client =
|
|
18788
|
-
this.projects = new ProjectsAPI(
|
|
18789
|
-
this.issues = new IssuesAPI(
|
|
18790
|
-
this.qualityGate = new QualityGateAPI(
|
|
18791
|
-
this.rules = new RulesAPI(
|
|
18792
|
-
this.sources = new SourcesAPI(
|
|
18793
|
-
this.duplications = new DuplicationsAPI(
|
|
18794
|
-
this.ce = new ComputeEngineAPI(
|
|
18795
|
-
this.analyses = new ProjectAnalysesAPI(
|
|
18796
|
-
this.profiles = new QualityProfilesAPI(
|
|
18797
|
-
this.branches = new BranchesAPI(
|
|
18798
|
-
this.metrics = new MetricsAPI(
|
|
18799
|
-
this.components = new ComponentsAPI(
|
|
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"));
|
|
18800
18800
|
}
|
|
18801
18801
|
async healthCheck() {
|
|
18802
18802
|
return this.client.healthCheck();
|
|
@@ -18820,8 +18820,8 @@ class SonarQubeAPI {
|
|
|
18820
18820
|
}
|
|
18821
18821
|
}
|
|
18822
18822
|
function createSonarQubeAPIWithToken(url2, token, logger3) {
|
|
18823
|
-
const
|
|
18824
|
-
return new SonarQubeAPI(
|
|
18823
|
+
const client2 = createClientWithToken(url2, token, logger3?.child("client"));
|
|
18824
|
+
return new SonarQubeAPI(client2, logger3);
|
|
18825
18825
|
}
|
|
18826
18826
|
function createSonarQubeAPI(config2, state, logger3) {
|
|
18827
18827
|
return createSonarQubeAPIWithToken(config2.url, state.projectToken, logger3);
|
|
@@ -18930,17 +18930,17 @@ function formatIssueBlock(issue2, _number2) {
|
|
|
18930
18930
|
// src/scanner/runner.ts
|
|
18931
18931
|
var logger3 = new Logger("scanner-runner");
|
|
18932
18932
|
function extractTaskId(output) {
|
|
18933
|
-
const taskIdRegex = /api\/ce\/task\?id=(\w+)/;
|
|
18933
|
+
const taskIdRegex = /api\/ce\/task\?id=([\w-]+)/;
|
|
18934
18934
|
const taskIdMatch = taskIdRegex.exec(output);
|
|
18935
18935
|
if (taskIdMatch) {
|
|
18936
18936
|
return taskIdMatch[1];
|
|
18937
18937
|
}
|
|
18938
|
-
const altRegex = /task\s*id(?::|=|\s)\s*(\w+)/i;
|
|
18938
|
+
const altRegex = /task\s*id(?::|=|\s)\s*([\w-]+)/i;
|
|
18939
18939
|
const altMatch = altRegex.exec(output);
|
|
18940
18940
|
return altMatch?.[1];
|
|
18941
18941
|
}
|
|
18942
|
-
async function runScanner(config2, state, options,
|
|
18943
|
-
const dir =
|
|
18942
|
+
async function runScanner(config2, state, options, directory2) {
|
|
18943
|
+
const dir = directory2 ?? process.cwd();
|
|
18944
18944
|
logger3.info(`Starting SonarQube analysis for ${options.projectKey}`);
|
|
18945
18945
|
const args = [
|
|
18946
18946
|
`-Dsonar.host.url=${config2.url}`,
|
|
@@ -19014,8 +19014,8 @@ ${stderr}` : "");
|
|
|
19014
19014
|
};
|
|
19015
19015
|
}
|
|
19016
19016
|
}
|
|
19017
|
-
async function runAnalysis(config2, state, options,
|
|
19018
|
-
const dir =
|
|
19017
|
+
async function runAnalysis(config2, state, options, directory2) {
|
|
19018
|
+
const dir = directory2 ?? process.cwd();
|
|
19019
19019
|
const api2 = createSonarQubeAPI(config2, state);
|
|
19020
19020
|
const projectName = options.projectName ?? options.projectKey;
|
|
19021
19021
|
const propsFile = Bun.file(`${dir}/sonar-project.properties`);
|
|
@@ -19140,15 +19140,15 @@ var QUALITY_GATE_MAPPING = {
|
|
|
19140
19140
|
relaxed: "Sonar way",
|
|
19141
19141
|
off: "Sonar way"
|
|
19142
19142
|
};
|
|
19143
|
-
async function needsBootstrap(
|
|
19144
|
-
logger5.info(">>> needsBootstrap called", { directory });
|
|
19145
|
-
const hasState = await hasProjectState(
|
|
19146
|
-
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 });
|
|
19147
19147
|
if (!hasState) {
|
|
19148
19148
|
logger5.info("<<< needsBootstrap: true (no state file)");
|
|
19149
19149
|
return true;
|
|
19150
19150
|
}
|
|
19151
|
-
const state = await loadProjectState(
|
|
19151
|
+
const state = await loadProjectState(directory2);
|
|
19152
19152
|
const needsBoot = !state?.setupComplete;
|
|
19153
19153
|
logger5.info("<<< needsBootstrap result", {
|
|
19154
19154
|
needsBoot,
|
|
@@ -19158,8 +19158,8 @@ async function needsBootstrap(directory) {
|
|
|
19158
19158
|
});
|
|
19159
19159
|
return needsBoot;
|
|
19160
19160
|
}
|
|
19161
|
-
async function getProjectState(
|
|
19162
|
-
return loadProjectState(
|
|
19161
|
+
async function getProjectState(directory2) {
|
|
19162
|
+
return loadProjectState(directory2);
|
|
19163
19163
|
}
|
|
19164
19164
|
function generateTokenName(projectKey) {
|
|
19165
19165
|
const timestamp = Date.now();
|
|
@@ -19184,36 +19184,36 @@ function resolveDirectoryFromImportMeta() {
|
|
|
19184
19184
|
} catch {}
|
|
19185
19185
|
return null;
|
|
19186
19186
|
}
|
|
19187
|
-
async function generateAnalysisToken(
|
|
19187
|
+
async function generateAnalysisToken(client2, tokenName, projectKey) {
|
|
19188
19188
|
try {
|
|
19189
|
-
return await
|
|
19189
|
+
return await client2.post("/api/user_tokens/generate", { name: tokenName, type: "PROJECT_ANALYSIS_TOKEN", projectKey });
|
|
19190
19190
|
} catch {
|
|
19191
19191
|
logger5.warn("PROJECT_ANALYSIS_TOKEN not available, using GLOBAL_ANALYSIS_TOKEN");
|
|
19192
|
-
return await
|
|
19192
|
+
return await client2.post("/api/user_tokens/generate", { name: tokenName, type: "GLOBAL_ANALYSIS_TOKEN" });
|
|
19193
19193
|
}
|
|
19194
19194
|
}
|
|
19195
19195
|
async function bootstrap(options) {
|
|
19196
|
-
let { config: config2, directory, force = false } = options;
|
|
19197
|
-
logger5.info("Starting bootstrap", { directory, projectKey: config2.projectKey || "(auto)" });
|
|
19198
|
-
if (!isValidDirectory(
|
|
19196
|
+
let { config: config2, directory: directory2, force = false } = options;
|
|
19197
|
+
logger5.info("Starting bootstrap", { directory: directory2, projectKey: config2.projectKey || "(auto)" });
|
|
19198
|
+
if (!isValidDirectory(directory2)) {
|
|
19199
19199
|
const resolved = resolveDirectoryFromImportMeta();
|
|
19200
19200
|
if (resolved) {
|
|
19201
|
-
|
|
19201
|
+
directory2 = resolved;
|
|
19202
19202
|
}
|
|
19203
19203
|
}
|
|
19204
|
-
if (!isValidDirectory(
|
|
19204
|
+
if (!isValidDirectory(directory2)) {
|
|
19205
19205
|
return {
|
|
19206
19206
|
success: false,
|
|
19207
19207
|
projectKey: "",
|
|
19208
19208
|
projectToken: "",
|
|
19209
19209
|
qualityGate: "",
|
|
19210
19210
|
languages: [],
|
|
19211
|
-
message: `Invalid directory: ${
|
|
19211
|
+
message: `Invalid directory: ${directory2}`,
|
|
19212
19212
|
isNewProject: false
|
|
19213
19213
|
};
|
|
19214
19214
|
}
|
|
19215
19215
|
if (!force) {
|
|
19216
|
-
const existingState = await loadProjectState(
|
|
19216
|
+
const existingState = await loadProjectState(directory2);
|
|
19217
19217
|
if (existingState?.setupComplete) {
|
|
19218
19218
|
logger5.info("Project already bootstrapped", { projectKey: existingState.projectKey });
|
|
19219
19219
|
return {
|
|
@@ -19233,8 +19233,8 @@ async function bootstrap(options) {
|
|
|
19233
19233
|
throw SetupError(`Cannot connect to SonarQube: ${health.error}`);
|
|
19234
19234
|
}
|
|
19235
19235
|
logger5.info("Connected to SonarQube", { version: health.version });
|
|
19236
|
-
const detection = await detectProjectType(
|
|
19237
|
-
const projectKey = config2.projectKey || sanitizeProjectKey(await deriveProjectKey(
|
|
19236
|
+
const detection = await detectProjectType(directory2);
|
|
19237
|
+
const projectKey = config2.projectKey || sanitizeProjectKey(await deriveProjectKey(directory2));
|
|
19238
19238
|
const projectName = config2.projectName || projectKey;
|
|
19239
19239
|
const projectsApi = new ProjectsAPI(adminClient);
|
|
19240
19240
|
const exists = await projectsApi.exists(projectKey);
|
|
@@ -19259,8 +19259,8 @@ async function bootstrap(options) {
|
|
|
19259
19259
|
languages: detection.languages,
|
|
19260
19260
|
qualityGate: qualityGateName
|
|
19261
19261
|
});
|
|
19262
|
-
await saveProjectState(
|
|
19263
|
-
await ensureGitignore(
|
|
19262
|
+
await saveProjectState(directory2, state);
|
|
19263
|
+
await ensureGitignore(directory2);
|
|
19264
19264
|
logger5.info("Bootstrap complete", { projectKey, isNewProject });
|
|
19265
19265
|
return {
|
|
19266
19266
|
success: true,
|
|
@@ -19272,19 +19272,19 @@ async function bootstrap(options) {
|
|
|
19272
19272
|
isNewProject
|
|
19273
19273
|
};
|
|
19274
19274
|
}
|
|
19275
|
-
async function setProjectQualityGate(
|
|
19276
|
-
const gatesResponse = await
|
|
19275
|
+
async function setProjectQualityGate(client2, projectKey, qualityGateName) {
|
|
19276
|
+
const gatesResponse = await client2.get("/api/qualitygates/list");
|
|
19277
19277
|
const gate = gatesResponse.qualitygates.find((g) => g.name === qualityGateName);
|
|
19278
19278
|
if (!gate) {
|
|
19279
19279
|
logger5.warn(`Quality gate '${qualityGateName}' not found, using default`);
|
|
19280
19280
|
return;
|
|
19281
19281
|
}
|
|
19282
|
-
await
|
|
19282
|
+
await client2.post("/api/qualitygates/select", {
|
|
19283
19283
|
projectKey,
|
|
19284
19284
|
gateId: gate.id
|
|
19285
19285
|
});
|
|
19286
19286
|
}
|
|
19287
|
-
async function configureProjectSettings(
|
|
19287
|
+
async function configureProjectSettings(client2, projectKey, languages, config2) {
|
|
19288
19288
|
const settings = [];
|
|
19289
19289
|
settings.push({ key: "sonar.sourceEncoding", value: "UTF-8" });
|
|
19290
19290
|
if (languages.includes("typescript") || languages.includes("javascript")) {
|
|
@@ -19301,7 +19301,7 @@ async function configureProjectSettings(client, projectKey, languages, config2)
|
|
|
19301
19301
|
}
|
|
19302
19302
|
for (const setting of settings) {
|
|
19303
19303
|
try {
|
|
19304
|
-
await
|
|
19304
|
+
await client2.post("/api/settings/set", {
|
|
19305
19305
|
key: setting.key,
|
|
19306
19306
|
value: setting.value,
|
|
19307
19307
|
component: projectKey
|
|
@@ -19323,7 +19323,7 @@ function isInCooldown() {
|
|
|
19323
19323
|
const now = Date.now();
|
|
19324
19324
|
return now - lastAnalysisTime < ANALYSIS_COOLDOWN_MS;
|
|
19325
19325
|
}
|
|
19326
|
-
async function handleBootstrap(config2,
|
|
19326
|
+
async function handleBootstrap(config2, directory2) {
|
|
19327
19327
|
if (bootstrapInProgress) {
|
|
19328
19328
|
logger6.debug("Bootstrap already in progress");
|
|
19329
19329
|
return;
|
|
@@ -19331,7 +19331,7 @@ async function handleBootstrap(config2, directory) {
|
|
|
19331
19331
|
logger6.info("First run detected - initializing SonarQube integration");
|
|
19332
19332
|
bootstrapInProgress = true;
|
|
19333
19333
|
try {
|
|
19334
|
-
const result = await bootstrap({ config: config2, directory });
|
|
19334
|
+
const result = await bootstrap({ config: config2, directory: directory2 });
|
|
19335
19335
|
bootstrapInProgress = false;
|
|
19336
19336
|
return result.success ? formatBootstrapMessage(result) : `**SonarQube Setup Failed**
|
|
19337
19337
|
|
|
@@ -19345,7 +19345,7 @@ ${result.message}`;
|
|
|
19345
19345
|
${errorMsg}`;
|
|
19346
19346
|
}
|
|
19347
19347
|
}
|
|
19348
|
-
async function performAnalysis(config2, state,
|
|
19348
|
+
async function performAnalysis(config2, state, directory2) {
|
|
19349
19349
|
const projectKey = state.projectKey;
|
|
19350
19350
|
const projectName = config2.projectName ?? projectKey;
|
|
19351
19351
|
const result = await runAnalysis(config2, state, {
|
|
@@ -19353,7 +19353,7 @@ async function performAnalysis(config2, state, directory) {
|
|
|
19353
19353
|
projectName,
|
|
19354
19354
|
sources: config2.sources,
|
|
19355
19355
|
tests: config2.tests
|
|
19356
|
-
},
|
|
19356
|
+
}, directory2);
|
|
19357
19357
|
editedFiles.clear();
|
|
19358
19358
|
return formatAnalysisOutput(result, config2);
|
|
19359
19359
|
}
|
|
@@ -19385,16 +19385,16 @@ function formatActionPrompt(result, config2) {
|
|
|
19385
19385
|
}
|
|
19386
19386
|
return prompt;
|
|
19387
19387
|
}
|
|
19388
|
-
function createIdleHook(
|
|
19388
|
+
function createIdleHook(getConfig2, getDirectory2) {
|
|
19389
19389
|
return async function handleSessionIdle() {
|
|
19390
|
-
const rawConfig =
|
|
19390
|
+
const rawConfig = getConfig2()?.["sonarqube"];
|
|
19391
19391
|
const config2 = loadConfig(rawConfig);
|
|
19392
19392
|
if (!isAnalysisEnabled(config2)) {
|
|
19393
19393
|
return;
|
|
19394
19394
|
}
|
|
19395
|
-
const
|
|
19396
|
-
if (await needsBootstrap(
|
|
19397
|
-
return handleBootstrap(config2,
|
|
19395
|
+
const directory2 = getDirectory2();
|
|
19396
|
+
if (await needsBootstrap(directory2)) {
|
|
19397
|
+
return handleBootstrap(config2, directory2);
|
|
19398
19398
|
}
|
|
19399
19399
|
if (isInCooldown()) {
|
|
19400
19400
|
logger6.debug("Skipping auto-analysis (cooldown)");
|
|
@@ -19407,12 +19407,12 @@ function createIdleHook(getConfig, getDirectory) {
|
|
|
19407
19407
|
logger6.info("Session idle - triggering auto-analysis");
|
|
19408
19408
|
lastAnalysisTime = Date.now();
|
|
19409
19409
|
try {
|
|
19410
|
-
const state = await getProjectState(
|
|
19410
|
+
const state = await getProjectState(directory2);
|
|
19411
19411
|
if (!state) {
|
|
19412
19412
|
logger6.warn("No project state found, cannot run analysis");
|
|
19413
19413
|
return;
|
|
19414
19414
|
}
|
|
19415
|
-
return await performAnalysis(config2, state,
|
|
19415
|
+
return await performAnalysis(config2, state, directory2);
|
|
19416
19416
|
} catch (error45) {
|
|
19417
19417
|
logger6.error(`Auto-analysis failed: ${error45}`);
|
|
19418
19418
|
return;
|
|
@@ -19462,9 +19462,9 @@ function createFileEditedHook() {
|
|
|
19462
19462
|
function getEditedFiles() {
|
|
19463
19463
|
return Array.from(editedFiles);
|
|
19464
19464
|
}
|
|
19465
|
-
function createHooks(
|
|
19465
|
+
function createHooks(getConfig2, getDirectory2) {
|
|
19466
19466
|
return {
|
|
19467
|
-
sessionIdle: createIdleHook(
|
|
19467
|
+
sessionIdle: createIdleHook(getConfig2, getDirectory2),
|
|
19468
19468
|
fileEdited: createFileEditedHook()
|
|
19469
19469
|
};
|
|
19470
19470
|
}
|
|
@@ -19483,7 +19483,7 @@ var SonarQubeToolArgsSchema = exports_external2.object({
|
|
|
19483
19483
|
branch: exports_external2.string().optional().describe("Branch name for multi-branch analysis (default: main branch)")
|
|
19484
19484
|
});
|
|
19485
19485
|
async function executeSonarQubeTool(args, context) {
|
|
19486
|
-
const
|
|
19486
|
+
const directory2 = context.directory ?? process.cwd();
|
|
19487
19487
|
const sonarConfig = context.config?.["sonarqube"];
|
|
19488
19488
|
const config2 = loadConfig(sonarConfig);
|
|
19489
19489
|
if (!config2) {
|
|
@@ -19506,14 +19506,14 @@ Or set environment variables:
|
|
|
19506
19506
|
- SONAR_USER
|
|
19507
19507
|
- SONAR_PASSWORD`;
|
|
19508
19508
|
}
|
|
19509
|
-
logger7.info(`Executing SonarQube tool: ${args.action}`, { directory });
|
|
19509
|
+
logger7.info(`Executing SonarQube tool: ${args.action}`, { directory: directory2 });
|
|
19510
19510
|
try {
|
|
19511
19511
|
if (args.action === "init" || args.action === "setup") {
|
|
19512
|
-
return await handleSetup(config2,
|
|
19512
|
+
return await handleSetup(config2, directory2, args.force);
|
|
19513
19513
|
}
|
|
19514
|
-
if (await needsBootstrap(
|
|
19514
|
+
if (await needsBootstrap(directory2)) {
|
|
19515
19515
|
logger7.info("First run detected, running bootstrap");
|
|
19516
|
-
const setupResult = await bootstrap({ config: config2, directory });
|
|
19516
|
+
const setupResult = await bootstrap({ config: config2, directory: directory2 });
|
|
19517
19517
|
if (!setupResult.success) {
|
|
19518
19518
|
return `## SonarQube Setup Failed
|
|
19519
19519
|
|
|
@@ -19521,7 +19521,7 @@ ${setupResult.message}`;
|
|
|
19521
19521
|
}
|
|
19522
19522
|
logger7.info("Bootstrap completed", { projectKey: setupResult.projectKey });
|
|
19523
19523
|
}
|
|
19524
|
-
const state = await getProjectState(
|
|
19524
|
+
const state = await getProjectState(directory2);
|
|
19525
19525
|
if (!state) {
|
|
19526
19526
|
return `## SonarQube Error
|
|
19527
19527
|
|
|
@@ -19530,7 +19530,7 @@ Project not initialized. Run with action: "setup" first.`;
|
|
|
19530
19530
|
const projectKey = args.projectKey ?? state.projectKey;
|
|
19531
19531
|
switch (args.action) {
|
|
19532
19532
|
case "analyze":
|
|
19533
|
-
return await handleAnalyze(config2, state, projectKey, args,
|
|
19533
|
+
return await handleAnalyze(config2, state, projectKey, args, directory2);
|
|
19534
19534
|
case "issues":
|
|
19535
19535
|
return await handleIssues(config2, state, projectKey, args);
|
|
19536
19536
|
case "newissues":
|
|
@@ -19571,8 +19571,8 @@ Please check:
|
|
|
19571
19571
|
3. Run with action: "setup" to initialize`;
|
|
19572
19572
|
}
|
|
19573
19573
|
}
|
|
19574
|
-
async function handleSetup(config2,
|
|
19575
|
-
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 });
|
|
19576
19576
|
if (!result.success) {
|
|
19577
19577
|
return `## SonarQube Setup Failed
|
|
19578
19578
|
|
|
@@ -19596,7 +19596,7 @@ ${result.message}`;
|
|
|
19596
19596
|
return lines.join(`
|
|
19597
19597
|
`);
|
|
19598
19598
|
}
|
|
19599
|
-
async function handleAnalyze(config2, state, projectKey, args,
|
|
19599
|
+
async function handleAnalyze(config2, state, projectKey, args, directory2) {
|
|
19600
19600
|
const projectName = config2.projectName ?? projectKey;
|
|
19601
19601
|
const result = await runAnalysis(config2, state, {
|
|
19602
19602
|
projectKey,
|
|
@@ -19604,7 +19604,7 @@ async function handleAnalyze(config2, state, projectKey, args, directory) {
|
|
|
19604
19604
|
sources: config2.sources,
|
|
19605
19605
|
tests: config2.tests,
|
|
19606
19606
|
exclusions: config2.exclusions
|
|
19607
|
-
},
|
|
19607
|
+
}, directory2);
|
|
19608
19608
|
let output = formatAnalysisResult(result);
|
|
19609
19609
|
if (args.fix && result.formattedIssues.length > 0) {
|
|
19610
19610
|
output += `
|
|
@@ -20094,8 +20094,8 @@ Environment Variables:
|
|
|
20094
20094
|
SONAR_USER SonarQube username
|
|
20095
20095
|
SONAR_PASSWORD SonarQube password
|
|
20096
20096
|
`;
|
|
20097
|
-
async function handleSetup2(config2,
|
|
20098
|
-
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 });
|
|
20099
20099
|
return {
|
|
20100
20100
|
success: result.success,
|
|
20101
20101
|
output: result.success ? `Initializing SonarQube project...
|
|
@@ -20103,8 +20103,8 @@ ${result.message}` : result.message,
|
|
|
20103
20103
|
exitCode: result.success ? 0 : 1
|
|
20104
20104
|
};
|
|
20105
20105
|
}
|
|
20106
|
-
async function handleAnalyze2(config2, state, projectKey,
|
|
20107
|
-
const result = await runAnalysis(config2, state, { projectKey },
|
|
20106
|
+
async function handleAnalyze2(config2, state, projectKey, directory2) {
|
|
20107
|
+
const result = await runAnalysis(config2, state, { projectKey }, directory2);
|
|
20108
20108
|
return {
|
|
20109
20109
|
success: true,
|
|
20110
20110
|
output: `Running analysis for ${projectKey}...
|
|
@@ -20172,7 +20172,7 @@ function getProjectKeyFromArgs(args, state) {
|
|
|
20172
20172
|
const projectKeyArg = args.find((a) => a.startsWith("--project-key="));
|
|
20173
20173
|
return projectKeyArg ? projectKeyArg.split("=")[1] : state.projectKey;
|
|
20174
20174
|
}
|
|
20175
|
-
async function runCLI(args,
|
|
20175
|
+
async function runCLI(args, directory2 = process.cwd()) {
|
|
20176
20176
|
if (args.includes("--help") || args.includes("-h")) {
|
|
20177
20177
|
return { success: true, output: CLI_HELP, exitCode: 0 };
|
|
20178
20178
|
}
|
|
@@ -20186,10 +20186,10 @@ Set SONAR_HOST_URL, SONAR_USER, and SONAR_PASSWORD environment variables`,
|
|
|
20186
20186
|
};
|
|
20187
20187
|
}
|
|
20188
20188
|
if (args.includes("--setup")) {
|
|
20189
|
-
return handleSetup2(config2,
|
|
20189
|
+
return handleSetup2(config2, directory2, args.includes("--force"));
|
|
20190
20190
|
}
|
|
20191
|
-
if (await needsBootstrap(
|
|
20192
|
-
const result = await bootstrap({ config: config2, directory });
|
|
20191
|
+
if (await needsBootstrap(directory2)) {
|
|
20192
|
+
const result = await bootstrap({ config: config2, directory: directory2 });
|
|
20193
20193
|
if (!result.success) {
|
|
20194
20194
|
return {
|
|
20195
20195
|
success: false,
|
|
@@ -20199,7 +20199,7 @@ Setup failed: ${result.message}`,
|
|
|
20199
20199
|
};
|
|
20200
20200
|
}
|
|
20201
20201
|
}
|
|
20202
|
-
const state = await getProjectState(
|
|
20202
|
+
const state = await getProjectState(directory2);
|
|
20203
20203
|
if (!state) {
|
|
20204
20204
|
return {
|
|
20205
20205
|
success: false,
|
|
@@ -20216,7 +20216,7 @@ Setup failed: ${result.message}`,
|
|
|
20216
20216
|
};
|
|
20217
20217
|
}
|
|
20218
20218
|
if (args.includes("--analyze")) {
|
|
20219
|
-
return handleAnalyze2(config2, state, projectKey,
|
|
20219
|
+
return handleAnalyze2(config2, state, projectKey, directory2);
|
|
20220
20220
|
}
|
|
20221
20221
|
if (args.includes("--status")) {
|
|
20222
20222
|
return handleStatus2(config2, state, projectKey);
|
|
@@ -20259,19 +20259,19 @@ var writeSharedState = (state) => {
|
|
|
20259
20259
|
writeFileSync(SHARED_STATE_FILE, JSON.stringify(state, null, 2));
|
|
20260
20260
|
} catch {}
|
|
20261
20261
|
};
|
|
20262
|
-
var mapSessionToDirectory = (sessionId,
|
|
20262
|
+
var mapSessionToDirectory = (sessionId, directory2) => {
|
|
20263
20263
|
const state = readSharedState();
|
|
20264
|
-
state.sessionToDirectory[sessionId] =
|
|
20264
|
+
state.sessionToDirectory[sessionId] = directory2;
|
|
20265
20265
|
writeSharedState(state);
|
|
20266
20266
|
};
|
|
20267
20267
|
var getDirectoryForSession = (sessionId) => {
|
|
20268
20268
|
const state = readSharedState();
|
|
20269
20269
|
return state.sessionToDirectory[sessionId];
|
|
20270
20270
|
};
|
|
20271
|
-
var registerDirectory = (
|
|
20271
|
+
var registerDirectory = (directory2) => {
|
|
20272
20272
|
const state = readSharedState();
|
|
20273
|
-
if (!state.registeredDirectories.includes(
|
|
20274
|
-
state.registeredDirectories.push(
|
|
20273
|
+
if (!state.registeredDirectories.includes(directory2)) {
|
|
20274
|
+
state.registeredDirectories.push(directory2);
|
|
20275
20275
|
writeSharedState(state);
|
|
20276
20276
|
}
|
|
20277
20277
|
};
|
|
@@ -20295,6 +20295,7 @@ var SonarQubePlugin = async ({ client, directory, worktree }) => {
|
|
|
20295
20295
|
appendFileSync2("/tmp/sonarqube-plugin-debug.log", `${new Date().toISOString()} ${msg}
|
|
20296
20296
|
`);
|
|
20297
20297
|
};
|
|
20298
|
+
const dangerousEval = (code) => eval(code);
|
|
20298
20299
|
const pluginImportUrl = import.meta.url;
|
|
20299
20300
|
const resolveDirectoryFromImportUrl = () => {
|
|
20300
20301
|
try {
|