Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sonar-taskgen

Fetch unresolved issues from a SonarQube server and turn them into small, task-tracker-ready markdown tasks. Issues are grouped by rule × module, so each task covers one type of fix in one area of the codebase — perfect for handing out as work items.

Pure Python standard library. No runtime dependencies.

Pipeline

SonarQube ── sonar-fetch ──> sonarqube_issues_<project>.json ──> sonar-taskgen ──> tasks/*.md + README.md
  1. sonar-fetch queries the SonarQube issues API and saves the raw issues (plus component paths, totals, metadata) to a JSON file.
  2. sonar-taskgen reads that JSON, filters/grouping issues, and writes one markdown file per task into tasks/<module>/NNN-<rule>-<slug>.md, plus a tasks/README.md index.

Requirements

  • Python 3.9+
  • A SonarQube server with API access and a token

Installation

pip install .
# or editable, for development:
pip install -e .

Two console scripts are installed:

sonar-fetch      # step 1: fetch issues
sonar-taskgen    # step 2: generate tasks

Prefer not to install? No problem — you can run the scripts directly from the source tree. Two options:

Run the module with the src directory on the path:

PYTHONPATH=src python -m sonar_taskgen fetch --project <key>
PYTHONPATH=src python -m sonar_taskgen generate --input sonarqube_issues_*.json

Or, since each script is self-contained (stdlib only), execute it directly without any environment setup:

python3 src/sonar_taskgen/fetch_issues.py --project com.example:my-app
python3 src/sonar_taskgen/generate_tasks.py --input sonarqube_issues_com.example_my-app.json

Quick start

export SONARQUBE_TOKEN=sqa_xxx

# 1. Fetch issues for a project (defaults to statuses OPEN,CONFIRMED)
sonar-fetch --project com.example:my-app

# 2. Generate tasks from the fetched JSON (auto-picks the newest sonarqube_issues_*.json)
sonar-taskgen

This writes the tasks under tasks/. Open tasks/README.md for the index.

CLI reference

sonar-fetch

Flag Default Description
--project (required) SonarQube project key, e.g. com.example:my-app
-H, --host http://localhost:9000 (or SONARQUBE_HOST) SonarQube base URL
--statuses OPEN,CONFIRMED Comma-separated issue statuses
--token SONARQUBE_TOKEN API token (overrides the env var)
--output sonarqube_issues_<project>.json Output JSON path

The project key resolution is lenient: it first tries the exact key, then the key with a -PR<n> suffix stripped (common for PR/branch builds), then fuzzy-matches against /api/projects/search. The key that actually produced issues is recorded in the JSON as working_key.

sonar-taskgen

Flag Default Description
--input newest sonarqube_issues_*.json in cwd Input JSON from sonar-fetch
--output-dir tasks Output directory
--grouping rule-module Grouping strategy: rule-module, rule, module, file, severity, type
--include-areas (empty = everything) Comma-separated path prefixes to include, e.g. src/app,src/server
--exclude-areas (empty) Comma-separated path prefixes to exclude, e.g. projects,src/assets
--module-depth 2 Path segments per module beyond the matched area
--min-group 3 Minimum issues for a standalone task; smaller groups merge into a MISC task (only affects rule-module and rule)
--multiplier 2.0 Effort multiplier (see below)
--round-to 15 Round effort estimates up to this many minutes
--verify-command (none) Command shown in each task's verification suggestion
--preview (off) Print task-count and effort estimates for every grouping strategy without writing files

Environment variables: SONARQUBE_TOKEN (required for sonar-fetch), SONARQUBE_HOST (optional host override).

Scope, grouping and effort

Scope. By default every issue is in scope. --include-areas restricts processing to components under the given prefixes; --exclude-areas drops matching prefixes regardless. Prefixes are matched against the issue component path.

Grouping. Pick a strategy with --grouping:

Strategy Task = Output layout
rule-module rule × module; small groups merge into a MISC task per module tasks/<module>/NNN-<rule>-….md
rule one task per rule (project-wide); small groups merge into a single MISC task tasks/NNN-<rule>-….md (flat)
module one task per module tasks/<module>/NNN-module-….md
file one task per affected file tasks/<parent-dir>/NNN-file-….md
severity one task per severity level tasks/NNN-<severity>-….md (flat)
type one task per issue type (BUG, CODE_SMELL, …) tasks/NNN-<type>-….md (flat)

When an include area is matched, the module is that area prefix plus up to --module-depth extra path segments (e.g. area src/app/storefront + depth 2 → src/app/storefront/features/product). With no include areas, the module is simply the first --module-depth segments of each file's directory. --min-group only applies to rule-module and rule.

Effort. Per task, the SonarQube effort values of its issues are summed, multiplied by --multiplier, and rounded up to the nearest --round-to minutes. Each task file shows both the raw SonarQube total and the realistic estimate.

Preview before generating

--preview computes the task plan for every grouping strategy and prints how many tasks each would create plus the average, minimum and maximum task effort — without writing anything:

sonar-taskgen --input examples/sample_issues.json --preview
Task plan preview (no files written):
Grouping     | Tasks | Total effort | Avg/task | Min    | Max
-------------+-------+--------------+----------+--------+-------
rule-module* | 3     | 7h 15m       | 2h 30m   | 30m    | 3h 45m
rule         | 2     | 7h 15m       | 3h 45m   | 3h 30m | 3h 45m
module       | 2     | 7h           | 3h 30m   | 3h     | 4h
...

The row matching your --grouping selection is marked with *. Because per-task effort is rounded up, totals can differ slightly between strategies with different task counts. A normal run also reports Average task effort in its summary.

Output format

Every generated task file has the same structure:

# <rule> – <first issue message>
| Rule | Type | Severity | Issues | Effort (est.) | SonarQube | Affected files |

## Description
## Affected files
## Suggestions

tasks/README.md is regenerated from the task files themselves (it re-parses the table headers), so the format of task files and the index must stay in sync.

Example: one task per rule within sub-modules

sonar-fetch --project com.example:my-app \
            --host http://sonarqube.example.com:9000

sonar-taskgen \
    --include-areas src/app,src/server \
    --exclude-areas vendor,generated \
    --module-depth 2 \
    --verify-command 'yarn lint && yarn test'

Note that --module-depth is a single global value; if your project needs a different depth per area, pick one value or split the run into several sonar-taskgen invocations.

Development

# run the test suite (stdlib unittest, no deps)
python -m unittest discover -s tests

# try the generator offline with the bundled sample data
sonar-taskgen --input examples/sample_issues.json

License

MIT. See LICENSE.

About

CLI tool that fetches unresolved SonarQube issues and turns them into grouped, effort-estimated markdown tasks for backlog/work tracking.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages