Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 0 additions & 39 deletions .cursor/rules/sonar-issue-fix.mdc

This file was deleted.

54 changes: 54 additions & 0 deletions .cursor/rules/sonarflow-autofix.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# sonarflow-autofix (SAFE)

Purpose: Provide guidance only. Do not modify files or run commands.

Operating principles:

- Only offer advice, suggestions, documentation links, and example snippets for each Sonar issue.
- Never edit files, stage changes, or commit. Never run shell commands.
- Do not auto-fetch issues. If issues are missing, ask the user to run: `sonar:fetch`.
- Keep suggestions minimal, focused, and ordered by priority below.

Priorities (highest first):

- S3776,S3358,S4165 > S1874,S6551,S6660 > S6759,S4325,S6479,S6478 > S125,S1135.

Guidelines:

- Only touch the code conceptually related to the issue; avoid broad refactors.
- Prefer early returns, readable control flow; avoid nested ternaries.
- Maintain or improve types; avoid `any` and non-null assertions.
- Issues are found in `.sonarflow/issues.json` (user-provided).

Patterns and examples:

- S6759: prefer readonly props.
Example:
```ts
// before
const C: React.FC<{ p: T }> = ({ p }) => {}
// after
const C: React.FC<Readonly<{ p: T }>> = ({ p }) => {}
```
- S4325: remove unsafe casts/non-null assertions; introduce guards/narrowings.
- S6660: replace nested `else if` chains with early returns.
- S6479: use stable IDs for React keys, not indices.
- S6478: hoist nested component definitions out of parents.
- S6551: avoid implicit object stringification; use `JSON.stringify` or specific fields.
- S125: delete commented-out code blocks.
- S3358: replace nested ternaries with `if/else`.
- S3776: extract helpers, flatten branches, deduplicate logic.
- S4165: remove redundant reassignments.
- S1135: resolve TODOs or link a tracked ticket.

Process (advisory only):

1. For the current file/issue, suggest a minimal, targeted change.
2. Provide a short rationale (1–2 lines) and a small code example or diff snippet.
3. If risky, propose an alternative safer approach.
4. Ask the user to review and apply.

Pitfalls:

- Do not resolve TODOs that are intentionally pending (external dependency or requirement clarification).

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ build

.cursor/mcp.json
.sonarflowrc.json
.sonarflow/
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [0.3.0-beta.5](https://github.com/bitrockteam/sonarflow/compare/v0.3.0-beta.4...v0.3.0-beta.5) (2025-11-10)


### Chores

* update schema version to v0.3.0-beta.5 ([ccc515a](https://github.com/bitrockteam/sonarflow/commit/ccc515ae5b43c3bfee3403dd39c58eb9e352f4f6))

## [0.3.0-beta.4](https://github.com/bitrockteam/sonarflow/compare/v0.3.0-beta.3...v0.3.0-beta.4) (2025-11-10)


### Chores

* update file paths and configurations for Sonarflow integration ([ba97c3e](https://github.com/bitrockteam/sonarflow/commit/ba97c3ef53b7f2e6f05110c550a919a544f806d7))
* update schema version to v0.3.0-beta.4 ([fad91c7](https://github.com/bitrockteam/sonarflow/commit/fad91c77d31728e3f564066a999f25b0eea38fab))

## [0.3.0-beta.2](https://github.com/bitrockteam/sonarflow/compare/v0.3.0-beta.1...v0.3.0-beta.2) (2025-11-01)


Expand Down
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ npx @bitrockteam/sonarflow fetch my-branch https://sonarcloud.io/project/issues?
```

- Auto PR detection tries provider API first (GitHub or Bitbucket), then falls back to extracting from branch naming patterns.
- Issues are saved to `.sonar/issues.json`.
- Issues are saved to `.sonarflow/issues.json`.

#### Initialize Configuration

Expand Down Expand Up @@ -206,7 +206,7 @@ npx @bitrockteam/sonarflow@latest <command>
1. Detects the current git branch or uses provided branch name
2. Attempts to find associated PR using GitHub or Bitbucket API, or branch name pattern matching
3. Fetches SonarQube issues for the PR or branch
4. Saves issues to `.sonar/issues.json`
4. Saves issues to `.sonarflow/issues.json`
5. Displays a summary of fetched issues


Expand All @@ -219,21 +219,21 @@ npx @bitrockteam/sonarflow@latest <command>

## Output Files

- `.sonar/issues.json` - Fetched SonarQube issues in JSON format
- `.sonarflow/issues.json` - Fetched SonarQube issues in JSON format
- `.sonarflowrc.json` - Project configuration
- `.cursor/rules/sonar-issue-fix.mdc` - Cursor AI rules (if selected)
- `.vscode/sonar-issue-fix.md` - VSCode rules (if selected)
- `.windsurf/rules/sonar-issue-fix.mdc` - Windsurf rules (if selected)
- `.rules/sonar-issue-fix.md` - Generic rules (if selected "other")
- `.cursor/rules/sonarflow-autofix.mdc` - Cursor AI rules (if selected)
- `.vscode/sonarflow-autofix.md` - VSCode rules (if selected)
- `.windsurf/rules/sonarflow-autofix.mdc` - Windsurf rules (if selected)
- `.rules/sonarflow-autofix.md` - Generic rules (if selected "other")

## AI Editor Integration

The tool creates specific rules for your chosen AI editor to help with automated SonarQube issue fixing:

- **Cursor**: Creates `.cursor/rules/sonar-issue-fix.mdc`
- **VSCode with Copilot**: Creates `.vscode/sonar-issue-fix.md`
- **Windsurf**: Creates `.windsurf/rules/sonar-issue-fix.mdc`
- **Other**: Creates `.rules/sonar-issue-fix.md`
- **Cursor**: Creates `.cursor/rules/sonarflow-autofix.mdc`
- **VSCode with Copilot**: Creates `.vscode/sonarflow-autofix.md`
- **Windsurf**: Creates `.windsurf/rules/sonarflow-autofix.mdc`
- **Other**: Creates `.rules/sonarflow-autofix.md`

These rules provide patterns and priorities for fixing common SonarQube issues.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bitrockteam/sonarflow",
"version": "0.3.0-beta.3",
"version": "0.3.0-beta.5",
"description": "CLI utility for fetching SonarQube issues and integrating with Bitbucket/GitHub PR workflows",
"main": "dist/cli.js",
"bin": {
Expand Down
12 changes: 9 additions & 3 deletions schemas/sonarflowrc.schema.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://raw.githubusercontent.com/bitrockteam/sonarflow/v0.3.0-beta.3/schemas/sonarflowrc.schema.json",
"$id": "https://raw.githubusercontent.com/bitrockteam/sonarflow/v0.3.0-beta.5/schemas/sonarflowrc.schema.json",
"title": "Sonarflow Configuration Schema",
"description": "Schema for .sonarflowrc.json configuration file",
"type": "object",
Expand All @@ -11,7 +11,8 @@
"sonarProjectKey",
"sonarMode",
"aiEditor",
"rulesFlavor"
"rulesFlavor",
"rulePath"
],
"properties": {
"$schema": {
Expand Down Expand Up @@ -91,9 +92,14 @@
],
"description": "Rules flavor for AI code generation"
},
"rulePath": {
"type": "string",
"description": "Path to the rule file (relative to project root)",
"minLength": 1
},
"outputPath": {
"type": "string",
"description": "Output path for sonar issues (default: '.sonar/')"
"description": "Output path for sonar issues (default: '.sonarflow/')"
}
},
"allOf": [
Expand Down
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ program

program
.command("fetch")
.description("Fetch Sonar issues and save to .sonar/issues.json")
.description("Fetch Sonar issues and save to .sonarflow/issues.json")
.allowExcessArguments(true)
.action(() => {
runNodeScript("./versioning/index.js", process.argv.slice(3));
Expand Down
41 changes: 30 additions & 11 deletions src/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface InitAnswers {

aiEditor: "cursor" | "copilot (vscode)" | "windsurf" | "other";
rulesFlavor: "safe" | "vibe-coder" | "yolo";
rulePath: string;
}

interface Config {
Expand All @@ -54,6 +55,7 @@ interface Config {

aiEditor: "cursor" | "copilot (vscode)" | "windsurf" | "other";
rulesFlavor: "safe" | "vibe-coder" | "yolo";
rulePath: string;
}

const runInit = async (): Promise<void> => {
Expand Down Expand Up @@ -134,6 +136,21 @@ const runInit = async (): Promise<void> => {
? defaultRepoName.split("/")[0]
: undefined;

const getDefaultRulePath = (
editor: "cursor" | "copilot (vscode)" | "windsurf" | "other"
): string => {
if (editor === "cursor") {
return ".cursor/rules/sonarflow-autofix.mdc";
}
if (editor === "copilot (vscode)") {
return ".vscode/sonarflow-autofix.md";
}
if (editor === "windsurf") {
return ".windsurf/rules/sonarflow-autofix.mdc";
}
return ".rules/sonarflow-autofix.md";
};

let answers: InitAnswers;
try {
const repoName = await input({
Expand Down Expand Up @@ -244,6 +261,16 @@ const runInit = async (): Promise<void> => {
default: "safe",
});

const defaultRulePath = getDefaultRulePath(aiEditor);
const rulePath = await input({
message: "Rule path:",
default: defaultRulePath,
validate: (val: string) => {
const trimmed = (val ?? "").trim();
return trimmed ? true : "Rule path is required";
},
});

answers = {
repoName,
gitProvider,
Expand All @@ -255,6 +282,7 @@ const runInit = async (): Promise<void> => {
sonarMode,
sonarBaseUrl,
rulesFlavor,
rulePath: rulePath.trim(),
};
} catch (error) {
// Handle graceful exit on SIGINT (Ctrl+C)
Expand Down Expand Up @@ -297,6 +325,7 @@ const runInit = async (): Promise<void> => {
// automation
aiEditor: answers.aiEditor,
rulesFlavor: answers.rulesFlavor,
rulePath: answers.rulePath,
};

const configSpinner = ora({
Expand Down Expand Up @@ -352,17 +381,7 @@ const runInit = async (): Promise<void> => {
}
const ruleContent = await fs.readFile(templateRulePath, "utf8");

const editor = answers.aiEditor;
let targetRulePath: string;
if (editor === "cursor") {
targetRulePath = path.join(process.cwd(), ".cursor/rules/sonar-issue-fix.mdc");
} else if (editor === "copilot (vscode)") {
targetRulePath = path.join(process.cwd(), ".vscode/sonar-issue-fix.md");
} else if (editor === "windsurf") {
targetRulePath = path.join(process.cwd(), ".windsurf/rules/sonar-issue-fix.mdc");
} else {
targetRulePath = path.join(process.cwd(), ".rules/sonar-issue-fix.md");
}
const targetRulePath = path.join(process.cwd(), answers.rulePath);

await fs.ensureDir(path.dirname(targetRulePath));
await fs.writeFile(targetRulePath, ruleContent, "utf8");
Expand Down
Loading