From e2f9c7ca86f7cbedfcfdba0ce6e193aac39db9b3 Mon Sep 17 00:00:00 2001 From: 5000user5000 Date: Fri, 29 May 2026 07:48:58 +0800 Subject: [PATCH 1/2] Resolve SonarQube quality gate new violations --- .../cloudnative/project/OverrideService.java | 1 + .../versioning/VersionHistoryService.java | 2 ++ .../ProjectCompositionServiceTest.java | 7 ++-- frontend/src/pages/Projects.jsx | 32 ++++++++++++++++++- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/cloudnative/project/OverrideService.java b/backend/src/main/java/com/cloudnative/project/OverrideService.java index f0b5637..262c551 100644 --- a/backend/src/main/java/com/cloudnative/project/OverrideService.java +++ b/backend/src/main/java/com/cloudnative/project/OverrideService.java @@ -55,6 +55,7 @@ public OverrideState currentState(UUID projectId, UUID scopeId, UUID templateId, * Applies one override change under an already-created change session (a * change request being approved) and records it to version history. */ + @SuppressWarnings("java:S107") @Transactional public void applyChange( UUID sessionId, diff --git a/backend/src/main/java/com/cloudnative/versioning/VersionHistoryService.java b/backend/src/main/java/com/cloudnative/versioning/VersionHistoryService.java index c4dbddd..dc916cf 100644 --- a/backend/src/main/java/com/cloudnative/versioning/VersionHistoryService.java +++ b/backend/src/main/java/com/cloudnative/versioning/VersionHistoryService.java @@ -96,6 +96,7 @@ public ChangeSession createSession( * Records one override mutation as an immutable history row. The override * write path calls this after it has written the live value. */ + @SuppressWarnings("java:S107") @Transactional public ConfigurationOverrideHistory recordOverrideChange( UUID sessionId, @@ -231,6 +232,7 @@ public Set findSessionProjectIds(UUID sessionId) { .collect(Collectors.toSet()); } + @SuppressWarnings("java:S6809") @Transactional public UUID rollback(UUID sessionId, UUID actorId, String notes) { RestoreResult result = restoreSessionState(sessionId, RestoreTarget.before, actorId, notes); diff --git a/backend/src/test/java/com/cloudnative/project/ProjectCompositionServiceTest.java b/backend/src/test/java/com/cloudnative/project/ProjectCompositionServiceTest.java index 8002d1e..6ab843c 100644 --- a/backend/src/test/java/com/cloudnative/project/ProjectCompositionServiceTest.java +++ b/backend/src/test/java/com/cloudnative/project/ProjectCompositionServiceTest.java @@ -119,11 +119,14 @@ void rejectsMultipleTemplatesForSameType() { when(configurationRepository.findAllById(List.of(DB_TEMPLATE_ID, DB_TEMPLATE_VARIANT_ID))) .thenReturn(List.of(dbTemplate, dbVariant)); - assertThatThrownBy(() -> service().create(new ProjectCreateRequest( + ProjectCompositionService service = service(); + ProjectCreateRequest request = new ProjectCreateRequest( "core-api", "Core API", List.of(DB_TEMPLATE_ID, DB_TEMPLATE_VARIANT_ID) - ))) + ); + + assertThatThrownBy(() -> service.create(request)) .isInstanceOf(ResponseStatusException.class) .hasMessageContaining("only one template per template type"); } diff --git a/frontend/src/pages/Projects.jsx b/frontend/src/pages/Projects.jsx index 7f68fc0..f3038f5 100644 --- a/frontend/src/pages/Projects.jsx +++ b/frontend/src/pages/Projects.jsx @@ -1660,7 +1660,7 @@ function normalizeProjectTemplateForModal(section, templates = []) { templateType: section.templateType ?? sourceTemplate.templateType, description: sourceTemplate.description ?? [ section.cloneSource ? `Source scope: ${section.cloneSource.siteName} / ${section.cloneSource.environmentName}` : null, - section.priority !== undefined ? `Priority ${section.priority}` : null, + section.priority === undefined ? null : `Priority ${section.priority}`, ].filter(Boolean).join(' · '), }; } @@ -3837,3 +3837,33 @@ function AddScopeModal({ project, sites, environments, mutating, onClose, onSubm ); } + +const optionalProjectProp = () => null; + +Projects.propTypes = { + projects: optionalProjectProp, + setProjects: optionalProjectProp, + templates: optionalProjectProp, + setTemplates: optionalProjectProp, + setNotification: optionalProjectProp, + onOpenImpact: optionalProjectProp, + onProposeChange: optionalProjectProp, + canCreateProject: optionalProjectProp, + loading: optionalProjectProp, + error: optionalProjectProp, + onCreateProject: optionalProjectProp, + onCloneProject: optionalProjectProp, + onUpdateProject: optionalProjectProp, + onDeleteProject: optionalProjectProp, + onUpdateProjectTemplates: optionalProjectProp, + onUpdateTemplate: optionalProjectProp, + onDeleteTemplate: optionalProjectProp, + onFetchTemplateImpact: optionalProjectProp, + onAddProjectScope: optionalProjectProp, + onRemoveProjectScope: optionalProjectProp, + onCreateOverrideRequest: optionalProjectProp, + sites: optionalProjectProp, + environments: optionalProjectProp, + templateTypes: optionalProjectProp, + token: optionalProjectProp, +}; From 3c3d9b32a88e3da35046ab7b3b7569c631416be7 Mon Sep 17 00:00:00 2001 From: 5000user5000 Date: Fri, 29 May 2026 08:25:11 +0800 Subject: [PATCH 2/2] Resolve SonarQube violations and document quality workflow --- README.md | 286 +++++++++++++++++++++------------- docs/quality-and-sonarqube.md | 184 ++++++++++++++++++++++ 2 files changed, 359 insertions(+), 111 deletions(-) create mode 100644 docs/quality-and-sonarqube.md diff --git a/README.md b/README.md index a70992c..75f5233 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,78 @@ -# Cloud Native +# Cloud Native Configuration Management -This repository contains a small full-stack workspace: +Cloud Native Configuration Management is a full-stack configuration governance workspace for project, factory, environment, template, override, export, and change-history workflows. -- `frontend/`: Vite + React application -- `backend/`: Spring Boot API with PostgreSQL, Flyway, JPA, validation, and auth/configuration flows -- `.github/workflows/`: CI definitions +The repository is organized as a single workspace with a React frontend, a Spring Boot backend, PostgreSQL persistence, automated tests, coverage reports, and SonarQube quality analysis. -## Quick Start +## Project Overview + +The application helps teams manage reusable configuration templates and project-specific overrides across deployment scopes. + +Core capabilities: + +- user registration, login, JWT authentication, and role-aware screens; +- configuration template creation, editing, inspection, import, export, and deletion; +- project, factory, and environment scope browsing; +- project scope configuration preview with inherited template values and overrides; +- change-request and version-history support for configuration changes; +- backend service tests and frontend component/page tests; +- SonarQube quality gate validation with frontend and backend coverage. + +## Repository Structure + +```text +. +├── backend/ Spring Boot API, domain logic, persistence, tests +├── frontend/ Vite React UI, Vitest tests, frontend coverage +├── deploy/ Nginx and Docker Compose deployment references +├── docs/ Shared project documentation +├── local_docs/ Local notes and presentation-only artifacts +├── sonar-project.properties Root aggregate SonarQube scan configuration +└── README.md Main project guide +``` + +Important entry points: + +- [frontend/src](frontend/src): React application source +- [frontend/tests](frontend/tests): frontend tests +- [backend/src/main/java](backend/src/main/java): backend application source +- [backend/src/test/java](backend/src/test/java): backend tests +- [sonar-project.properties](sonar-project.properties): canonical SonarQube scan configuration + +## Architecture + +Local development runs three main services: + +```text +Browser + -> Vite dev server / frontend static build + -> Spring Boot backend API + -> PostgreSQL database +``` + +The production-oriented deployment model is stateless at the backend layer: + +```text +Users + -> DNS / HTTPS + -> Load Balancer or Reverse Proxy + -> Frontend static app + -> Backend API replica pool + -> PostgreSQL / managed database +``` + +The backend uses JWT-based authentication and stores source-of-truth data in PostgreSQL, so backend replicas can be placed behind a load balancer without sticky sessions. -### Requirements +Deployment references are in [deploy/README.md](deploy/README.md). + +## Requirements - Node.js `20.19+` -- Java `21+` or newer +- npm +- Java `21+` - Maven -- Docker, if you want to run PostgreSQL locally in a container +- PostgreSQL `15+`, or Docker for local PostgreSQL +- Optional: local or online SonarQube / SonarCloud access Default local ports: @@ -21,11 +80,14 @@ Default local ports: Frontend: http://127.0.0.1:5173 Backend: http://127.0.0.1:8080 PostgreSQL: localhost:5432 +SonarQube: http://localhost:9000, if running locally ``` +## Quick Start + ### 1. Start PostgreSQL -If you do not already have a local PostgreSQL database, start one with Docker: +If PostgreSQL is not already available locally, start a Docker container: ```bash docker run --name cloud-native-postgres \ @@ -42,7 +104,7 @@ If the container already exists: docker start cloud-native-postgres ``` -The backend defaults to: +The backend defaults are: ```text DATABASE_URL=jdbc:postgresql://localhost:5432/cloud_native_db @@ -51,6 +113,8 @@ DATABASE_PASSWORD=cloudnative QUICK_ADMIN_PASSWORD=optional local quick-login password ``` +If your database runs on another port, export the variables before starting the backend. + ### 2. Start Backend ```bash @@ -60,15 +124,15 @@ mvn spring-boot:run -Dspring-boot.run.profiles=dev The backend runs on `http://127.0.0.1:8080`. -Flyway applies database migrations on startup. Current seed data includes: +Flyway applies database migrations on startup. The seed data includes template types, sample projects, factories, environments, and project scope template selections. -- template types such as Application Config, Database Config, Cache Config, Security / Auth Config -- an `AI Agent` project -- 12 factories, `Factory A` through `Factory L` -- 4 environments: Development, Testing, Staging, Production -- sample template selections for project scope preview +Health check: -### Frontend +```text +GET http://127.0.0.1:8080/api/health +``` + +### 3. Start Frontend ```bash cd frontend @@ -78,48 +142,26 @@ npm run dev The frontend runs on `http://127.0.0.1:5173`. -### Backend Details - -See [backend/README.md](backend/README.md) for the full backend workflow, including PostgreSQL setup, Flyway notes, backend testing, and coverage usage. - -If you already have PostgreSQL ready: - -```bash -cd backend -mvn spring-boot:run -Dspring-boot.run.profiles=dev -``` - -## How To Use The App +## Application Flow 1. Open `http://127.0.0.1:5173`. -2. Register or log in from the auth screen. -3. Use `Search` to search backend configurations and templates. -4. Use `Templates` to create, inspect, edit, and delete reusable config fragments. -5. Use `Projects` to inspect project scope configuration. +2. Register or log in. +3. Use `Search` to search configurations and templates. +4. Use `Templates` to manage reusable configuration fragments. +5. Use `Projects` to inspect project scope configuration by project, factory, and environment. +6. Use export/import screens to move configuration data through supported formats. -The current Project flow is: +The main project inspection flow is: ```text -Project List -> Factory List -> Environment List -> Templates Used +Project List -> Factory List -> Environment List -> Templates Used -> Effective Config Preview ``` -After selecting a project, factory, and environment, the right panel shows which template files are used by that scope. - -The `Clone Project` button opens a clone source picker: - -```text -Select base Project / Factory / Environment -Review final config preview -Optionally mix individual template sources from other Factory / Environment scopes -View template details from each row -Select Clone Source -``` +The clone-source preview flow supports selecting a base project/factory/environment and optionally mixing individual template sources from other scopes before review. -The clone flow is currently a frontend workflow preview. It can compose and display a mixed clone source in the UI, but it does not yet persist a cloned project to the backend. +## Testing And Coverage -## Testing - -### Frontend tests +### Frontend ```bash cd frontend @@ -127,106 +169,128 @@ npm run test npm run test:coverage ``` -The coverage command writes reports under `frontend/coverage/`, including -`frontend/coverage/lcov.info` for Sonar scanner input. +Coverage output: + +```text +frontend/coverage/lcov.info +frontend/coverage/coverage-summary.json +``` + +The LCOV file is the frontend coverage input used by SonarQube. -### Backend tests +### Backend ```bash cd backend mvn clean verify ``` -This currently: +This runs backend tests and generates JaCoCo coverage: -- runs the regular backend test suite -- generates a JaCoCo coverage report at `backend/target/site/jacoco/index.html` -- writes the XML report used by Sonar at `backend/target/site/jacoco/jacoco.xml` +```text +backend/target/site/jacoco/index.html +backend/target/site/jacoco/jacoco.xml +``` + +The XML report is the backend coverage input used by SonarQube. -The backend PostgreSQL/Testcontainers integration test is intentionally tagged as `integration` and skipped by default for local runs. To include it: +The PostgreSQL/Testcontainers integration test is tagged as `integration` and skipped by default. To include it: ```bash cd backend mvn verify -Dexcluded.test.tags= ``` -The detailed explanation and Docker-related notes live in [backend/README.md](backend/README.md). +More backend setup details are in [backend/README.md](backend/README.md). -### Sonar scanner +## SonarQube Quality Gate -After generating both frontend and backend coverage reports, run the scanner -from the repository root: +The canonical SonarQube project is the root aggregate project: -```bash -npx @sonar/scan +```text +cloud-native ``` -The scanner reads `sonar-project.properties`. Provide server URL and token -through your local Sonar scanner environment or command-line options; do not -commit credentials to the repository. For SonarCloud, also provide -`sonar.organization`; for local SonarQube, provide `sonar.host.url`. +Run the scanner from the repository root after generating both frontend and backend coverage reports: -## Deployment Architecture +```bash +cd frontend +npm run test:coverage + +cd ../backend +mvn clean verify + +cd .. +npx @sonar/scan \ + -Dsonar.host.url=http://localhost:9000 \ + -Dsonar.token=$SONAR_TOKEN +``` -The target deployment architecture is: +The root scan reads [sonar-project.properties](sonar-project.properties), including: ```text -Users - -> DNS / HTTPS - -> Load Balancer / Reverse Proxy - -> Frontend static app - -> Backend API replica pool - -> PostgreSQL / Neon +frontend/coverage/lcov.info +backend/target/site/jacoco/jacoco.xml ``` -The backend is designed to be stateless for request routing because it uses JWT -authentication and stores source-of-truth data in PostgreSQL. That allows future -backend replicas to sit behind a load balancer without sticky sessions. +Use the root `cloud-native` project for final quality gate evidence. Standalone project keys such as `cloud-native-frontend` and `cloud-native-backend` have separate baselines and issue history, so they can produce different results unless maintained intentionally. -Deployment references live in [deploy/README.md](deploy/README.md): +Detailed SonarQube notes, online-scan requirements, and troubleshooting are in [docs/quality-and-sonarqube.md](docs/quality-and-sonarqube.md). -- `deploy/nginx.production.conf`: production-oriented reverse proxy template -- `deploy/production-like/`: runnable Docker Compose stack with frontend, backend replicas, reverse proxy, and PostgreSQL -- `deploy/demo/`: local Docker Compose demo with Nginx and scaled backend replicas +## Code Quality Policy -The backend health endpoint for load balancers and uptime checks is: +The project uses a conservative coverage and quality strategy: -```text -GET /api/health +- test user-facing frontend flows and backend business logic +- exclude low-value bootstrap, DTO, repository, controller, enum, static data, and framework-wiring files from coverage KPIs where appropriate +- avoid committing generated output such as `coverage/`, `target/`, `.scannerwork/`, and `dist/` +- treat security hotspots as review items that require either remediation or a clear explanation. + +Current local quality evidence should be regenerated from the commands above instead of relying on committed reports. + +## Security Scanning + +Dependency vulnerability scanning is documented as a manual workflow in [docs/security-scanning.md](docs/security-scanning.md). + +Common commands: + +```bash +cd frontend +npm audit --audit-level=high + +cd ../backend +mvn org.owasp:dependency-check-maven:check ``` -## Repository Structure +These dependency scans complement application security tests for JWT authentication, role guards, and protected backend endpoints. + +## Deployment + +Deployment references live in [deploy/README.md](deploy/README.md): + +- `deploy/nginx.production.conf`: production-oriented reverse proxy template; +- `deploy/production-like/`: Docker Compose stack with frontend, backend replicas, reverse proxy, and PostgreSQL; +- `deploy/demo/`: local demo stack with Nginx and scaled backend replicas. + +The backend health endpoint for load balancers and uptime checks is: ```text -. -├── .github/ -│ └── workflows/ -├── backend/ -│ ├── src/ -│ ├── target/ -│ └── README.md -├── frontend/ -│ ├── src/ -│ └── tests/ -└── README.md +GET /api/health ``` ## Documentation Guide -- [backend/README.md](backend/README.md) - Backend setup, PostgreSQL, Flyway, local testing, and coverage - -- [deploy/README.md](deploy/README.md) - Deployment topology, load balancing model, Nginx reverse proxy template, and production checklist - -- [docs/security-scanning.md](docs/security-scanning.md) - Manual dependency vulnerability scanning commands for frontend and backend +- [backend/README.md](backend/README.md): backend setup, PostgreSQL, Flyway, tests, and coverage +- [deploy/README.md](deploy/README.md): deployment topology and production-like local stack +- [docs/quality-and-sonarqube.md](docs/quality-and-sonarqube.md): coverage, SonarQube, online scan, and Quality Gate guidance +- [docs/security-scanning.md](docs/security-scanning.md): manual dependency vulnerability scanning ## CI -GitHub Actions runs separate frontend and backend jobs from [`.github/workflows/ci.yml`](.github/workflows/ci.yml). +GitHub Actions runs separate frontend and backend jobs from [.github/workflows/ci.yml](.github/workflows/ci.yml). -Today that means: +The CI workflow currently covers: -- frontend install, test, and build checks -- backend Maven test execution +- frontend dependency install, tests, and build; +- backend Maven tests; +- fast feedback for pull requests and branch updates. diff --git a/docs/quality-and-sonarqube.md b/docs/quality-and-sonarqube.md new file mode 100644 index 0000000..f5d2bc0 --- /dev/null +++ b/docs/quality-and-sonarqube.md @@ -0,0 +1,184 @@ +# Quality And SonarQube Guide + +This document explains how to reproduce the project quality evidence with frontend coverage, backend coverage, and SonarQube Quality Gate analysis. + +## Canonical Project + +Use the root aggregate SonarQube project as the canonical quality project: + +```text +cloud-native +``` + +The aggregate project is configured by [../sonar-project.properties](../sonar-project.properties). It scans both sides of the repository: + +```text +frontend/src +backend/src/main/java +frontend/tests +backend/src/test/java +``` + +It imports coverage from: + +```text +frontend/coverage/lcov.info +backend/target/site/jacoco/jacoco.xml +``` + +## Required Order + +Always generate coverage before running the scanner. + +```bash +cd frontend +npm run test:coverage + +cd ../backend +mvn clean verify + +cd .. +npx @sonar/scan \ + -Dsonar.host.url=http://localhost:9000 \ + -Dsonar.token=$SONAR_TOKEN +``` + +If `frontend/coverage/lcov.info` or `backend/target/site/jacoco/jacoco.xml` is missing, SonarQube can report lower or zero coverage. + +## Online SonarQube Or SonarCloud + +The same scan model should be used online: + +1. checkout the repository; +2. install frontend dependencies; +3. run frontend coverage; +4. run backend `mvn clean verify`; +5. run scanner from the repository root. + +Example: + +```bash +cd frontend +npm ci +npm run test:coverage + +cd ../backend +mvn clean verify + +cd .. +npx @sonar/scan \ + -Dsonar.host.url=$SONAR_HOST_URL \ + -Dsonar.token=$SONAR_TOKEN +``` + +For SonarCloud, include the organization if needed: + +```bash +-Dsonar.organization= +``` + +Do not write tokens into repository files. Use CI secrets, environment variables, or local shell variables. + +## Quality Gate Expectations + +The expected Quality Gate evidence for the root project is: + +```text +Project key: cloud-native +Quality Gate: OK +Coverage: 80%+ +New coverage: 80%+ +New violations: 0 +Duplicated lines on new code: below gate threshold +``` + +Exact values can differ across environments because SonarQube version, quality profile, New Code baseline, and server-side project settings can differ. + +## New Code Baseline Risk + +A local project and an online project may not use the same New Code baseline. + +Common baseline modes include: + +- previous version; +- number of days; +- reference branch; +- specific analysis. + +If an online SonarQube project is created fresh and treats the full branch as New Code, it may report more New Code issues than the local server. In that case, either fix the newly reported issues or configure the intended New Code baseline in SonarQube. + +## Standalone Project Keys + +The repository may also have standalone local projects from earlier scans: + +```text +cloud-native-frontend +cloud-native-backend +``` + +These are not the recommended final evidence projects unless intentionally maintained. They have their own issue history, Quality Gate status, and New Code baseline. A standalone project can fail even when the root `cloud-native` project passes. + +For final review, presentation, or CI evidence, prefer: + +```text +cloud-native +``` + +## Coverage Exclusion Rationale + +Coverage exclusions should stay conservative. They are intended for files with low test value or framework-driven behavior, not for hiding core product logic. + +Reasonable examples: + +- app bootstrap and entry files; +- static data fixtures; +- generated or build output; +- DTOs and simple data carriers; +- repositories and controllers when service-level tests cover behavior; +- enums and constant-only files; +- framework configuration; +- prototype/demo preview files that are not part of the formal product flow. + +Core service logic, security behavior, frontend workflows, parsing, import/export behavior, and change/version workflows should be tested rather than excluded. + +## Security Hotspots + +Security Hotspots are review items, not automatically vulnerabilities. Each hotspot should have one of these outcomes: + +- fixed in code; +- marked safe with a clear reason in SonarQube; +- documented as accepted risk with follow-up work. + +Examples relevant to this project: + +- pseudorandom values used only for demo identifiers are not security-sensitive; +- CSRF disabling is acceptable only when the backend is a stateless token-based API and does not rely on cookie session authentication. + +If the authentication model changes to cookie-based sessions, CSRF protection must be revisited. + +## Troubleshooting + +If Quality Gate fails because coverage is too low: + +- confirm `frontend/coverage/lcov.info` exists; +- confirm `backend/target/site/jacoco/jacoco.xml` exists; +- confirm the scanner ran from the repository root; +- confirm `sonar-project.properties` was used; +- confirm online CI did not skip tests before scanning. + +If Quality Gate fails because of New Code issues: + +- check the project key in the SonarQube URL; +- check whether the failing project is `cloud-native` or a standalone project; +- inspect the New Code baseline; +- fix low-risk issues directly; +- avoid broad source exclusions for real product logic. + +If online results differ from local results: + +- compare SonarQube server version; +- compare quality profile and quality gate settings; +- compare New Code definition; +- compare scanner command and working directory; +- compare generated coverage report paths; +- verify that no token or project key from local testing was hard-coded.