mirror of
https://github.com/ivuorinen/dotfiles.git
synced 2026-02-07 19:50:50 +00:00
feat(scripts): add x-sonarcloud script for LLM-driven issue analysis
Bridges LLM agents with SonarCloud's REST API to fetch and format code quality issues as structured markdown with processing instructions.
This commit is contained in:
623
local/bin/x-sonarcloud
Executable file
623
local/bin/x-sonarcloud
Executable file
@@ -0,0 +1,623 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# x-sonarcloud - Fetch SonarCloud issues for LLM analysis
|
||||
# Copyright (c) 2025 - Licensed under MIT
|
||||
#
|
||||
# Usage:
|
||||
# x-sonarcloud # Auto-detect, all open issues
|
||||
# x-sonarcloud --pr <number> # PR-specific issues
|
||||
# x-sonarcloud --branch <name> # Branch-specific issues
|
||||
# x-sonarcloud --org <org> --project-key <key> # Explicit project
|
||||
# x-sonarcloud --severities BLOCKER,CRITICAL # Filter by severity
|
||||
# x-sonarcloud --types BUG,VULNERABILITY # Filter by type
|
||||
# x-sonarcloud --statuses OPEN,CONFIRMED # Filter by status
|
||||
# x-sonarcloud --resolved # Include resolved issues
|
||||
# x-sonarcloud -h|--help # Show this help
|
||||
#
|
||||
# Examples:
|
||||
# x-sonarcloud # All open issues in project
|
||||
# x-sonarcloud --pr 42 # Issues on PR #42
|
||||
# x-sonarcloud --branch main # Issues on main branch
|
||||
# x-sonarcloud --severities BLOCKER --types BUG # Only blocker bugs
|
||||
#
|
||||
# Requirements:
|
||||
# - curl and jq installed
|
||||
# - SONAR_TOKEN environment variable set
|
||||
# - sonar-project.properties or .sonarlint/connectedMode.json for auto-detection
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors for output (stderr only)
|
||||
readonly RED='\033[0;31m'
|
||||
readonly GREEN='\033[0;32m'
|
||||
readonly YELLOW='\033[1;33m'
|
||||
readonly BLUE='\033[0;34m'
|
||||
readonly NC='\033[0m' # No Color
|
||||
|
||||
# API constants
|
||||
readonly MAX_PAGE_SIZE=500
|
||||
readonly MAX_TOTAL_ISSUES=10000
|
||||
|
||||
# Show usage information
|
||||
show_usage()
|
||||
{
|
||||
sed -n '3,27p' "$0" | sed 's/^# //' | sed 's/^#//'
|
||||
}
|
||||
|
||||
# Log functions
|
||||
log_error()
|
||||
{
|
||||
echo -e "${RED}ERROR:${NC} $1" >&2
|
||||
}
|
||||
log_warn()
|
||||
{
|
||||
echo -e "${YELLOW}WARN:${NC} $1" >&2
|
||||
}
|
||||
log_info()
|
||||
{
|
||||
if [[ "${INFO:-0}" == "1" ]]; then
|
||||
echo -e "${GREEN}INFO:${NC} $1" >&2
|
||||
fi
|
||||
}
|
||||
log_debug()
|
||||
{
|
||||
if [[ "${DEBUG:-0}" == "1" ]]; then
|
||||
echo -e "${BLUE}DEBUG:${NC} $1" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
# Check required dependencies
|
||||
check_dependencies()
|
||||
{
|
||||
local missing=0
|
||||
|
||||
if ! command -v curl &> /dev/null; then
|
||||
log_error "curl is not installed. Install it with your package manager."
|
||||
missing=1
|
||||
fi
|
||||
|
||||
if ! command -v jq &> /dev/null; then
|
||||
log_error "jq is not installed. Install it with your package manager:"
|
||||
log_error " https://jqlang.github.io/jq/download/"
|
||||
missing=1
|
||||
fi
|
||||
|
||||
if [[ "$missing" -eq 1 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check authentication
|
||||
check_auth()
|
||||
{
|
||||
if [[ -z "${SONAR_TOKEN:-}" ]]; then
|
||||
log_error "SONAR_TOKEN environment variable is not set."
|
||||
log_error "Generate a token at: https://sonarcloud.io/account/security"
|
||||
log_error "Then export it: export SONAR_TOKEN=your_token_here"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Detect project from sonar-project.properties
|
||||
detect_project_from_properties()
|
||||
{
|
||||
local props_file="sonar-project.properties"
|
||||
|
||||
if [[ ! -f "$props_file" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local org key
|
||||
org=$(grep -E '^sonar\.organization=' "$props_file" 2> /dev/null | cut -d'=' -f2- || echo "")
|
||||
key=$(grep -E '^sonar\.projectKey=' "$props_file" 2> /dev/null | cut -d'=' -f2- || echo "")
|
||||
|
||||
if [[ -n "$org" && -n "$key" ]]; then
|
||||
log_debug "Detected from sonar-project.properties: org=$org key=$key"
|
||||
echo "$org" "$key" ""
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Detect project from .sonarlint/connectedMode.json
|
||||
detect_project_from_sonarlint()
|
||||
{
|
||||
local sonarlint_file=".sonarlint/connectedMode.json"
|
||||
|
||||
if [[ ! -f "$sonarlint_file" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local org key region
|
||||
org=$(jq -r '.sonarCloudOrganization // empty' "$sonarlint_file" 2> /dev/null || echo "")
|
||||
key=$(jq -r '.projectKey // empty' "$sonarlint_file" 2> /dev/null || echo "")
|
||||
region=$(jq -r '.region // empty' "$sonarlint_file" 2> /dev/null || echo "")
|
||||
|
||||
if [[ -n "$org" && -n "$key" ]]; then
|
||||
log_debug "Detected from .sonarlint/connectedMode.json: org=$org key=$key region=$region"
|
||||
echo "$org" "$key" "$region"
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Orchestrate project detection in priority order
|
||||
detect_project()
|
||||
{
|
||||
local result
|
||||
|
||||
# 1. sonar-project.properties
|
||||
if result=$(detect_project_from_properties); then
|
||||
echo "$result"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 2. .sonarlint/connectedMode.json
|
||||
if result=$(detect_project_from_sonarlint); then
|
||||
echo "$result"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# No config found
|
||||
log_error "Could not auto-detect SonarCloud project configuration."
|
||||
log_error "Provide one of the following:"
|
||||
log_error " 1. sonar-project.properties with sonar.organization and sonar.projectKey"
|
||||
log_error " 2. .sonarlint/connectedMode.json with sonarCloudOrganization and projectKey"
|
||||
log_error " 3. CLI flags: --org <org> --project-key <key>"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Get API base URL (currently same for all regions)
|
||||
get_base_url()
|
||||
{
|
||||
echo "https://sonarcloud.io"
|
||||
}
|
||||
|
||||
# Make an authenticated SonarCloud API request
|
||||
sonar_api_request()
|
||||
{
|
||||
local url="$1"
|
||||
|
||||
log_debug "API request: $url"
|
||||
|
||||
local http_code body response
|
||||
response=$(curl -s -w "\n%{http_code}" \
|
||||
-H "Authorization: Bearer $SONAR_TOKEN" \
|
||||
"$url" 2> /dev/null) || {
|
||||
log_error "curl request failed for: $url"
|
||||
return 1
|
||||
}
|
||||
|
||||
http_code=$(echo "$response" | tail -n1)
|
||||
body=$(echo "$response" | sed '$d')
|
||||
|
||||
case "$http_code" in
|
||||
200)
|
||||
echo "$body"
|
||||
return 0
|
||||
;;
|
||||
401)
|
||||
log_error "Authentication failed (HTTP 401). Check your SONAR_TOKEN."
|
||||
return 1
|
||||
;;
|
||||
403)
|
||||
log_error "Access forbidden (HTTP 403). Token may lack required permissions."
|
||||
return 1
|
||||
;;
|
||||
404)
|
||||
log_error "Not found (HTTP 404). Check organization and project key."
|
||||
return 1
|
||||
;;
|
||||
429)
|
||||
log_error "Rate limited (HTTP 429). Wait before retrying."
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
log_error "API request failed with HTTP $http_code"
|
||||
log_debug "Response body: $body"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Fetch a single page of issues
|
||||
fetch_issues_page()
|
||||
{
|
||||
local base_url="$1"
|
||||
local project_key="$2"
|
||||
local page="$3"
|
||||
local pr_number="${4:-}"
|
||||
local branch="${5:-}"
|
||||
local severities="${6:-}"
|
||||
local types="${7:-}"
|
||||
local statuses="${8:-}"
|
||||
local resolved="${9:-}"
|
||||
|
||||
local url="${base_url}/api/issues/search?componentKeys=${project_key}"
|
||||
url="${url}&p=${page}&ps=${MAX_PAGE_SIZE}"
|
||||
|
||||
if [[ -n "$pr_number" ]]; then
|
||||
url="${url}&pullRequest=${pr_number}"
|
||||
fi
|
||||
|
||||
if [[ -n "$branch" ]]; then
|
||||
url="${url}&branch=${branch}"
|
||||
fi
|
||||
|
||||
if [[ -n "$severities" ]]; then
|
||||
url="${url}&severities=${severities}"
|
||||
fi
|
||||
|
||||
if [[ -n "$types" ]]; then
|
||||
url="${url}&types=${types}"
|
||||
fi
|
||||
|
||||
if [[ -n "$statuses" ]]; then
|
||||
url="${url}&statuses=${statuses}"
|
||||
fi
|
||||
|
||||
if [[ -n "$resolved" ]]; then
|
||||
url="${url}&resolved=${resolved}"
|
||||
fi
|
||||
|
||||
sonar_api_request "$url"
|
||||
}
|
||||
|
||||
# Fetch all issues with pagination
|
||||
fetch_all_issues()
|
||||
{
|
||||
local base_url="$1"
|
||||
local project_key="$2"
|
||||
local pr_number="${3:-}"
|
||||
local branch="${4:-}"
|
||||
local severities="${5:-}"
|
||||
local types="${6:-}"
|
||||
local statuses="${7:-}"
|
||||
local resolved="${8:-}"
|
||||
|
||||
local page=1
|
||||
local all_issues="[]"
|
||||
local total=0
|
||||
|
||||
while true; do
|
||||
log_info "Fetching issues page $page..."
|
||||
|
||||
local response
|
||||
response=$(fetch_issues_page "$base_url" "$project_key" "$page" \
|
||||
"$pr_number" "$branch" "$severities" "$types" "$statuses" "$resolved") || return 1
|
||||
|
||||
local page_issues page_total
|
||||
page_issues=$(echo "$response" | jq '.issues // []' 2> /dev/null || echo "[]")
|
||||
page_total=$(echo "$response" | jq '.total // 0' 2> /dev/null || echo "0")
|
||||
|
||||
local page_count
|
||||
page_count=$(echo "$page_issues" | jq 'length' 2> /dev/null || echo "0")
|
||||
|
||||
log_debug "Page $page: $page_count issues (total available: $page_total)"
|
||||
|
||||
# Merge into accumulated results
|
||||
all_issues=$(echo "$all_issues" "$page_issues" | jq -s '.[0] + .[1]' 2> /dev/null || echo "$all_issues")
|
||||
total=$(echo "$all_issues" | jq 'length' 2> /dev/null || echo "0")
|
||||
|
||||
# Check if we have all issues or hit the cap
|
||||
if [[ "$page_count" -lt "$MAX_PAGE_SIZE" ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
if [[ "$total" -ge "$MAX_TOTAL_ISSUES" ]]; then
|
||||
log_warn "Reached maximum of $MAX_TOTAL_ISSUES issues. Results may be incomplete."
|
||||
break
|
||||
fi
|
||||
|
||||
page=$((page + 1))
|
||||
done
|
||||
|
||||
log_info "Fetched $total issues total"
|
||||
echo "$all_issues"
|
||||
}
|
||||
|
||||
# Format issues grouped by severity then by file
|
||||
format_issues_by_severity()
|
||||
{
|
||||
local issues="$1"
|
||||
local base_url="$2"
|
||||
local org="$3"
|
||||
local project_key="$4"
|
||||
|
||||
echo "$issues" | jq -r --arg base_url "$base_url" --arg org "$org" --arg key "$project_key" '
|
||||
group_by(.severity) | sort_by(-(
|
||||
if .[0].severity == "BLOCKER" then 5
|
||||
elif .[0].severity == "CRITICAL" then 4
|
||||
elif .[0].severity == "MAJOR" then 3
|
||||
elif .[0].severity == "MINOR" then 2
|
||||
elif .[0].severity == "INFO" then 1
|
||||
else 0 end
|
||||
)) | .[] |
|
||||
"### Severity: \(.[0].severity)\n" +
|
||||
(
|
||||
group_by(.component) | .[] |
|
||||
"#### File: \(.[0].component | split(":") | if length > 1 then .[1:] | join(":") else .[0] end)\n" +
|
||||
(
|
||||
[.[] |
|
||||
"##### Issue: \(.message)\n" +
|
||||
"- **Rule:** \(.rule)\n" +
|
||||
"- **Type:** \(.type)\n" +
|
||||
"- **Severity:** \(.severity)\n" +
|
||||
"- **Status:** \(.status)\n" +
|
||||
"- **Line:** \(.line // "N/A")\n" +
|
||||
"- **Effort:** \(.effort // "N/A")\n" +
|
||||
"- **Created:** \(.creationDate // "N/A")\n" +
|
||||
"- **URL:** \($base_url)/project/issues?open=\(.key)&id=\($key)\n"
|
||||
] | join("\n")
|
||||
)
|
||||
)
|
||||
' 2> /dev/null || echo "Error formatting issues."
|
||||
}
|
||||
|
||||
# Format summary counts
|
||||
format_summary()
|
||||
{
|
||||
local issues="$1"
|
||||
|
||||
echo "### By Severity"
|
||||
echo ""
|
||||
echo "$issues" | jq -r '
|
||||
group_by(.severity) | .[] |
|
||||
"- **\(.[0].severity):** \(length)"
|
||||
' 2> /dev/null || echo "- Error computing severity counts"
|
||||
|
||||
echo ""
|
||||
echo "### By Type"
|
||||
echo ""
|
||||
echo "$issues" | jq -r '
|
||||
group_by(.type) | .[] |
|
||||
"- **\(.[0].type):** \(length)"
|
||||
' 2> /dev/null || echo "- Error computing type counts"
|
||||
|
||||
echo ""
|
||||
echo "### Total"
|
||||
echo ""
|
||||
local count
|
||||
count=$(echo "$issues" | jq 'length' 2> /dev/null || echo "0")
|
||||
echo "- **Total issues:** $count"
|
||||
}
|
||||
|
||||
# Format the full markdown output
|
||||
format_output()
|
||||
{
|
||||
local org="$1"
|
||||
local project_key="$2"
|
||||
local mode="$3"
|
||||
local mode_value="$4"
|
||||
local base_url="$5"
|
||||
local issues="$6"
|
||||
|
||||
local issue_count
|
||||
issue_count=$(echo "$issues" | jq 'length' 2> /dev/null || echo "0")
|
||||
|
||||
# Header and LLM instructions
|
||||
cat << 'EOF'
|
||||
# SonarCloud Issues Analysis Report
|
||||
|
||||
## LLM Processing Instructions
|
||||
|
||||
You are analyzing code quality issues from SonarCloud for this project.
|
||||
|
||||
**Your tasks:**
|
||||
1. **Triage**: Review each issue and assess its real impact on the codebase
|
||||
2. **Priority Assessment**: Rank issues by severity and likelihood of causing problems
|
||||
3. **Code Verification**: Check the actual source code to confirm each issue is valid
|
||||
4. **Root Cause Analysis**: Identify why the issue exists and what pattern caused it
|
||||
5. **Implementation Plan**: Create actionable fix tasks grouped by file for efficiency
|
||||
6. **False Positive Detection**: Flag issues that appear to be false positives with reasoning
|
||||
|
||||
**Tools to use:**
|
||||
- `find`, `cat`, `rg` commands and available tools to examine current codebase
|
||||
- `git log` and `git blame` to understand code history and authorship
|
||||
- File system tools to verify mentioned files exist and check current state
|
||||
EOF
|
||||
|
||||
# Project information
|
||||
cat << EOF
|
||||
|
||||
## Project Information
|
||||
|
||||
- **Organization:** $org
|
||||
- **Project Key:** $project_key
|
||||
EOF
|
||||
|
||||
case "$mode" in
|
||||
pr)
|
||||
echo "- **Mode:** Pull Request #$mode_value"
|
||||
echo "- **URL:** ${base_url}/project/issues?pullRequest=${mode_value}&id=${project_key}"
|
||||
;;
|
||||
branch)
|
||||
echo "- **Mode:** Branch \`$mode_value\`"
|
||||
echo "- **URL:** ${base_url}/project/issues?branch=${mode_value}&id=${project_key}"
|
||||
;;
|
||||
*)
|
||||
echo "- **Mode:** Project (all open issues)"
|
||||
echo "- **URL:** ${base_url}/project/issues?id=${project_key}"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "- **Dashboard:** ${base_url}/project/overview?id=${project_key}"
|
||||
|
||||
# Issues section
|
||||
echo ""
|
||||
echo "## Issues ($issue_count total)"
|
||||
echo ""
|
||||
|
||||
if [[ "$issue_count" -eq 0 ]]; then
|
||||
echo "No issues found matching the specified filters."
|
||||
else
|
||||
format_issues_by_severity "$issues" "$base_url" "$org" "$project_key"
|
||||
|
||||
echo ""
|
||||
echo "## Summary"
|
||||
echo ""
|
||||
format_summary "$issues"
|
||||
fi
|
||||
|
||||
# Footer
|
||||
cat << 'EOF'
|
||||
|
||||
## Next Steps for LLM Analysis
|
||||
|
||||
1. **Validate against current code:**
|
||||
- Check if mentioned files and lines still match the reported issues
|
||||
- Verify issues are not already fixed in the current branch
|
||||
- Identify false positives and explain why they are false positives
|
||||
|
||||
2. **Prioritize fixes:**
|
||||
- Address BLOCKER and CRITICAL severity issues first
|
||||
- Group fixes by file to minimize context switching
|
||||
- Consider effort estimates when planning the fix order
|
||||
|
||||
3. **Group by file for implementation:**
|
||||
- Batch changes to the same file together
|
||||
- Consider dependencies between fixes
|
||||
- Plan atomic commits per logical change group
|
||||
|
||||
4. **Track progress:**
|
||||
- Use todo lists and memory tools to track which issues are addressed
|
||||
- Mark false positives with clear reasoning
|
||||
- Verify fixes do not introduce new issues
|
||||
EOF
|
||||
}
|
||||
|
||||
# Main pipeline: fetch and display issues
|
||||
fetch_and_display_issues()
|
||||
{
|
||||
local org="$1"
|
||||
local project_key="$2"
|
||||
local mode="$3"
|
||||
local mode_value="$4"
|
||||
local severities="${5:-}"
|
||||
local types="${6:-}"
|
||||
local statuses="${7:-}"
|
||||
local resolved="${8:-}"
|
||||
|
||||
local base_url
|
||||
base_url=$(get_base_url)
|
||||
|
||||
local pr_number=""
|
||||
local branch=""
|
||||
|
||||
case "$mode" in
|
||||
pr)
|
||||
pr_number="$mode_value"
|
||||
;;
|
||||
branch)
|
||||
branch="$mode_value"
|
||||
;;
|
||||
esac
|
||||
|
||||
log_info "Fetching SonarCloud issues for $project_key (mode: $mode)..."
|
||||
|
||||
local issues
|
||||
issues=$(fetch_all_issues "$base_url" "$project_key" \
|
||||
"$pr_number" "$branch" "$severities" "$types" "$statuses" "$resolved") || {
|
||||
log_error "Failed to fetch issues"
|
||||
return 1
|
||||
}
|
||||
|
||||
format_output "$org" "$project_key" "$mode" "$mode_value" "$base_url" "$issues"
|
||||
}
|
||||
|
||||
# Main function
|
||||
main()
|
||||
{
|
||||
local org=""
|
||||
local project_key=""
|
||||
local mode="project"
|
||||
local mode_value=""
|
||||
local severities=""
|
||||
local types=""
|
||||
local statuses="OPEN,CONFIRMED,REOPENED"
|
||||
local resolved="false"
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
show_usage
|
||||
exit 0
|
||||
;;
|
||||
--pr)
|
||||
mode="pr"
|
||||
mode_value="${2:?Missing PR number after --pr}"
|
||||
shift 2
|
||||
;;
|
||||
--branch)
|
||||
mode="branch"
|
||||
mode_value="${2:?Missing branch name after --branch}"
|
||||
shift 2
|
||||
;;
|
||||
--org)
|
||||
org="${2:?Missing organization after --org}"
|
||||
shift 2
|
||||
;;
|
||||
--project-key)
|
||||
project_key="${2:?Missing project key after --project-key}"
|
||||
shift 2
|
||||
;;
|
||||
--severities)
|
||||
severities="${2:?Missing severities after --severities}"
|
||||
shift 2
|
||||
;;
|
||||
--types)
|
||||
types="${2:?Missing types after --types}"
|
||||
shift 2
|
||||
;;
|
||||
--statuses)
|
||||
statuses="${2:?Missing statuses after --statuses}"
|
||||
shift 2
|
||||
;;
|
||||
--resolved)
|
||||
resolved="true"
|
||||
statuses=""
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown argument: $1"
|
||||
show_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
check_dependencies
|
||||
check_auth
|
||||
|
||||
# Auto-detect project if not specified via CLI
|
||||
if [[ -z "$org" || -z "$project_key" ]]; then
|
||||
local detected
|
||||
detected=$(detect_project) || exit 1
|
||||
# shellcheck disable=SC2034 # region reserved for future per-region base URLs
|
||||
read -r detected_org detected_key detected_region <<< "$detected"
|
||||
|
||||
if [[ -z "$org" ]]; then
|
||||
org="$detected_org"
|
||||
fi
|
||||
if [[ -z "$project_key" ]]; then
|
||||
project_key="$detected_key"
|
||||
fi
|
||||
fi
|
||||
|
||||
log_debug "Organization: $org"
|
||||
log_debug "Project Key: $project_key"
|
||||
log_debug "Mode: $mode"
|
||||
log_debug "Severities: ${severities:-all}"
|
||||
log_debug "Types: ${types:-all}"
|
||||
log_debug "Statuses: ${statuses:-all}"
|
||||
log_debug "Resolved: $resolved"
|
||||
|
||||
fetch_and_display_issues "$org" "$project_key" "$mode" "$mode_value" \
|
||||
"$severities" "$types" "$statuses" "$resolved"
|
||||
}
|
||||
|
||||
# Run main function with all arguments
|
||||
main "$@"
|
||||
46
local/bin/x-sonarcloud.md
Normal file
46
local/bin/x-sonarcloud.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# x-sonarcloud
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-sonarcloud # Auto-detect, all open issues
|
||||
x-sonarcloud --pr <number> # PR-specific issues
|
||||
x-sonarcloud --branch <name> # Branch-specific issues
|
||||
x-sonarcloud --org <org> --project-key <key> # Explicit project
|
||||
x-sonarcloud --severities BLOCKER,CRITICAL # Filter by severity
|
||||
x-sonarcloud --types BUG,VULNERABILITY # Filter by type
|
||||
x-sonarcloud --statuses OPEN,CONFIRMED # Filter by status
|
||||
x-sonarcloud --resolved # Include resolved issues
|
||||
x-sonarcloud -h|--help # Show help
|
||||
```
|
||||
|
||||
Fetches SonarCloud code quality issues via REST API and formats them as
|
||||
structured markdown with LLM processing instructions for automated analysis
|
||||
and triage.
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
x-sonarcloud # All open issues in project
|
||||
x-sonarcloud --pr 42 # Issues on PR #42
|
||||
x-sonarcloud --branch main # Issues on main branch
|
||||
x-sonarcloud --severities BLOCKER --types BUG # Only blocker bugs
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- `curl` and `jq` installed
|
||||
- `SONAR_TOKEN` environment variable set
|
||||
(generate at <https://sonarcloud.io/account/security>)
|
||||
- Project auto-detection via `sonar-project.properties` or
|
||||
`.sonarlint/connectedMode.json`, or explicit `--org`/`--project-key` flags
|
||||
|
||||
## Environment Variables
|
||||
|
||||
- `SONAR_TOKEN` — Bearer token for SonarCloud API authentication (required)
|
||||
- `INFO=1` — Enable informational log messages on stderr
|
||||
- `DEBUG=1` — Enable debug log messages on stderr
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
Reference in New Issue
Block a user