Skip to content
Draft
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
5 changes: 5 additions & 0 deletions .github/workflows/build_jar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ jobs:
java-version: ${{ steps.detect-java.outputs.version }}
cache: maven

- name: Run tests with Maven (pdf-generator)
run: |
set -euo pipefail
mvn -f pdf-generator/pom.xml -B test

- name: Build with Maven (pdf-generator)
run: |
set -euo pipefail
Expand Down
42 changes: 42 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Maven
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.backup
release.properties
.flattened-pom.xml

# Generated reports
*.pdf
sonarqube-report.pdf

# Compiled classes
*.class
*.classpath

# IDE
.idea/
.vscode/
*.iml
*.iws
*.ipr
.project
.settings/
.classpath
*.swp
*.swo
*~
.DS_Store
Thumbs.db

# OS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db

# Logs
*.log
3 changes: 3 additions & 0 deletions .mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
67 changes: 67 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
.PHONY: help build clean run install package test test-verbose quick

# Default target
help:
@echo "sonar-report - Makefile targets"
@echo ""
@echo "Note: Uses Maven wrapper (./mvnw) - no Maven installation needed"
@echo ""
@echo "Targets:"
@echo " build Build the project and generate JAR"
@echo " clean Remove build artifacts"
@echo " package Create distribution JAR (alias: build)"
@echo " run Run the JAR with SonarQube (requires SONAR_URL, SONAR_TOKEN, SONAR_PROJECT)"
@echo " test Run unit tests"
@echo " test-verbose Run tests with detailed output"
@echo " install Install JAR to local Maven repository"
@echo " quick Fast build without tests"
@echo ""
@echo "Environment variables for 'make run':"
@echo " SONAR_URL SonarQube base URL (required)"
@echo " SONAR_TOKEN Authentication token (required)"
@echo " SONAR_PROJECT Project key (required)"
@echo ""
@echo "Example:"
@echo " make build"
@echo " make test"
@echo " make run SONAR_URL='https://sonarqube.example.com' SONAR_TOKEN='squ_token' SONAR_PROJECT='com.example:my-project'"

# Build the project
build: clean
./mvnw -f pdf-generator/pom.xml clean package -DskipTests

# Clean build artifacts
clean:
./mvnw -f pdf-generator/pom.xml clean
rm -f sonarqube-report.pdf

# Alias for build
package: build

# Install JAR to local Maven repository
install:
./mvnw -f pdf-generator/pom.xml install -DskipTests

# Run the application
run: build
@if [ -z "$(SONAR_URL)" ] || [ -z "$(SONAR_TOKEN)" ] || [ -z "$(SONAR_PROJECT)" ]; then \
echo "Error: Required environment variables not set"; \
echo "Usage: make run SONAR_URL='<url>' SONAR_TOKEN='<token>' SONAR_PROJECT='<key>'"; \
exit 1; \
fi
java -jar pdf-generator/target/sonar-report-1.0-jar-with-dependencies.jar \
"$(SONAR_URL)" \
"$(SONAR_TOKEN)" \
"$(SONAR_PROJECT)"

# Run tests (if any)
test:
./mvnw -f pdf-generator/pom.xml test -q

# Run tests with verbose output
test-verbose:
./mvnw -f pdf-generator/pom.xml test

# Quick build without tests
quick:
./mvnw -f pdf-generator/pom.xml package -DskipTests -T 1C
239 changes: 237 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,240 @@
# sonar-report

Usage
A command-line Java tool that connects to a SonarQube instance, retrieves code analysis metrics via its REST API, and generates a formatted PDF report.

java -jar sonar-report-VERSION.jar SonarQubeURL AuthToken SonarProject
The report includes quality ratings (reliability, security, maintainability), test coverage, technical debt, security hotspots, issue breakdowns by type and severity, and per-language code metrics — with an indexed table of contents and hyperlinks back to SonarQube coding rules.

---

## Requirements

- Java 17+
- Access to a SonarQube instance and a valid authentication token

**Note:** Maven is not required — the project includes a Maven wrapper that downloads Maven 3.9.6 automatically on first use.

---

## Architecture

The project is organized with clean separation of concerns:

| Module | Purpose | Lines |
|---|---|---|
| `GenerateSonarReport` | Entry point — command-line argument parsing | ~15 |
| `SonarApiClient` | HTTP transport layer — SonarQube API calls with SSL bypass | ~75 |
| `ReportBuilder` | Report orchestration — fetches data and builds PDF sections | ~510 |
| `PDFReportWriter` | PDF rendering utilities — low-level PDF operations | ~860 |

**Tests:** Unit tests in `src/test/java/com/ods/` using JUnit 5 + Mockito — 31 test cases covering CLI, HTTP, aggregation, and PDF utilities.

**Package:** `com.ods`

The design minimizes coupling: API client is isolated from report logic, HTTP client is built once and reused, and section builders are cohesive private methods within `ReportBuilder`.

---

## Build

### Using Make (Recommended)

```bash
make build
```

All available Make targets:

```bash
make help # Show all available targets
make build # Build and package the JAR
make clean # Remove build artifacts
make test # Run unit tests (quiet)
make test-verbose # Run unit tests (verbose)
make install # Install JAR to local Maven repository
make quick # Fast build without tests
```

### Using Maven Wrapper (Direct)

```bash
cd pdf-generator
../mvnw clean package
```

Or on Windows:

```cmd
cd pdf-generator
..\mvnw.cmd clean package
```

The output JAR is placed at:

```
pdf-generator/target/sonar-report-1.0-jar-with-dependencies.jar
```

Pre-built JARs are also attached to each [GitHub Release](../../releases).

---

## Testing

### Running Tests

#### Using Make (Recommended)

```bash
make test # Run tests (quiet output)
make test-verbose # Run tests with detailed output
```

#### Using Maven Wrapper (Direct)

```bash
cd pdf-generator
../mvnw test
```

### Test Structure

The project includes comprehensive unit tests covering all major components:

| Test Class | Module | Coverage |
|---|---|---|
| `GenerateSonarReportTest` | CLI argument parsing | 5 test cases |
| `ReportBuilderTest` | Report data aggregation | 13 test cases |
| `PDFReportWriterTest` | PDF utilities | 7 test cases |
| `SonarApiClientTest` | HTTP API transport | 6 test cases |
| **Total** | — | **31 test cases** |

### Test Details

**GenerateSonarReportTest** — Validates command-line argument parsing:
- All known flags (`--sonar-url`, `--token`, `--project`, `--branch`, `--output`)
- Empty arguments, dangling flags, non-flag arguments
- Duplicate flag handling

**ReportBuilderTest** — Tests data transformation utilities:
- `extractComponent()` — file path extraction from component identifiers
- `ratingToLetter()` — quality rating conversion (A–E)
- `minsToDaysHoursMins()` — technical debt time formatting
- `groupHotspotsByRule()` — aggregates security hotspots by rule key
- `groupIssuesByRule()` — aggregates code issues by rule key

**PDFReportWriterTest** — Tests PDF rendering utilities:
- `getCurrentGMTTimeFormatted()` — GMT timestamp formatting with regex validation
- `splitBySlash()` — path component splitting (handles slashes at end)

**SonarApiClientTest** — Tests HTTP API transport with mocked responses:
- Successful 200 responses return parsed JSON
- Error responses (401, 404) throw `IOException`
- URL encoding of special characters in project keys
- Branch parameter handling (with/without/blank)

### Test Framework

- **Framework:** JUnit 5 (Jupiter)
- **Mocking:** Mockito 5.11.0
- **Compiler:** Java 17+

All tests are run during the standard Maven build via the Maven Surefire plugin.

---

## Usage

### Using Make

```bash
make run SONAR_URL='https://sonarqube.example.com' SONAR_TOKEN='squ_abc123yourtoken' SONAR_PROJECT='com.example:my-project'
```

### Using Java Directly

```bash
java -jar sonar-report-1.0-jar-with-dependencies.jar \
--sonar-url <url> \
--token <token> \
--project <key> \
[--branch <branch>] \
[--output <file.pdf>]
```

### Arguments

| Flag | Required | Description |
|---|---|---|
| `--sonar-url` | Yes | Base URL of your SonarQube server, e.g. `https://sonarqube.example.com` |
| `--token` | Yes | SonarQube user token (Bearer authentication) |
| `--project` | Yes | The project key as shown in SonarQube, e.g. `com.example:my-project` |
| `--branch` | No | Branch to analyze (default: SonarQube project default branch) |
| `--output` | No | Output PDF filename (default: `sonarqube-report.pdf`) |

### Example

```bash
java -jar sonar-report-1.0-jar-with-dependencies.jar \
--sonar-url "https://sonarqube.example.com" \
--token "squ_abc123yourtoken" \
--project "com.example:my-project" \
--branch "main"
```

With a custom output filename:

```bash
java -jar sonar-report-1.0-jar-with-dependencies.jar \
--sonar-url "https://sonarqube.example.com" \
--token "squ_abc123yourtoken" \
--project "com.example:my-project" \
--branch "develop" \
--output "my-project-report.pdf"
```

The report is written to the specified file (or `sonarqube-report.pdf` by default) in the current working directory.

---

## Report Contents

The generated PDF contains:

- Project name, version, and quality gate status
- Quality ratings: Reliability, Security, Maintainability (grades A–E)
- Code coverage, complexity, duplication, and comment density
- Technical debt (formatted as days/hours/minutes)
- Security hotspots and vulnerabilities
- Open issues grouped by type and severity, linked to coding rules
- Metrics broken down by programming language
- Auto-generated table of contents with page bookmarks

---

## Notes

- The tool accepts self-signed TLS certificates, making it suitable for internal SonarQube deployments.
- Paginated API results (hotspots, issues) are fully iterated — no result cap at 500.
- All arguments are passed as named flags (`--sonar-url`, `--token`, `--project`, `--output`); no environment variables or config files are required.
- **Test Coverage:** Comprehensive unit tests (31 test cases) validate CLI parsing, API transport, data aggregation, and PDF utilities.
- **Bug fix:** Tests section now fetches correct metrics (was incorrectly reusing Metrics URL).
- **Performance:** HTTP client is built once and reused across all API calls.

---

## CI/CD

Two GitHub Actions workflows are included:

| Workflow | Trigger | Purpose |
|---|---|---|
| `build_jar.yml` | Push, PR, Release | Builds the uber-JAR and attaches it to releases |
| `check_calls.yml` | Push, PR | Validates all SonarQube API endpoints used by the tool |

The JAR artifact is named after the branch, PR number, or release tag automatically.

---

## License

See [LICENSE](LICENSE).
Loading
Loading