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
2 changes: 1 addition & 1 deletion .github/workflows/sonarqube.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches:
# - main # production, already covered automatically by SonarQube Cloud
- main
- dev
# pull_request: # SonarQube Server Community doesn't support PRs
# types: [opened, synchronize, reopened]
workflow_dispatch:
Expand Down
188 changes: 165 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,166 @@

<table>
<tr>
<td rowspan="3">
<th>SonarQube Cloud <code>main</code></th>
<th>SonarQube Server <code>dev</code> (self-hosted on Azure)</th>
</tr>
<tr>
<td>
<a href="https://sonarcloud.io/summary/new_code?id=fernandotonacoder_chrisert">
<img src="https://sonarcloud.io/images/project_badges/sonarcloud-light.svg" alt="SonarQube Cloud" />
<img src="https://sonarcloud.io/api/project_badges/quality_gate?project=fernandotonacoder_chrisert" alt="Quality gate" />
</a>
</td>
<td>
<a href="https://sonarcloud.io/summary/new_code?id=fernandotonacoder_chrisert">
<img src="https://sonarcloud.io/api/project_badges/measure?project=fernandotonacoder_chrisert&metric=alert_status" alt="Quality Gate Status" />
<a href="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317">
<img src="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/quality_gate?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&token=sqb_29e1338abec328874a7e501928a3f3b3efa8a26c" alt="Quality gate" />
</a>
</td>
</tr>
<!-- Security -->
<tr>
<td>
<a href="https://sonarcloud.io/summary/new_code?id=fernandotonacoder_chrisert">
<img src="https://sonarcloud.io/api/project_badges/measure?project=fernandotonacoder_chrisert&metric=security_rating" alt="Security Rating" />
</a>
</td>
<td>
<a href="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317">
<img src="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/measure?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&metric=software_quality_security_rating&token=sqb_29e1338abec328874a7e501928a3f3b3efa8a26c" alt="Security Rating (dev)" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://sonarcloud.io/summary/new_code?id=fernandotonacoder_chrisert">
<img src="https://sonarcloud.io/api/project_badges/measure?project=fernandotonacoder_chrisert&metric=vulnerabilities" alt="Vulnerabilities" />
</a>
</td>
<td>N/A — free tier limitation</td>
</tr>
<tr>
<td>N/A — free tier limitation</td>
<td>
<a href="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317">
<img src="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/measure?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&metric=software_quality_security_issues&token=sqb_29e1338abec328874a7e501928a3f3b3efa8a26c" alt="Security Issues" />
</a>
</td>
</tr>
<tr>
<td>N/A — free tier limitation</td>
<td>
<a href="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317">
<img src="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/measure?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&metric=security_hotspots&token=sqb_29e1338abec328874a7e501928a3f3b3efa8a26c" alt="Security Hotspots" />
</a>
</td>
</tr>
<!-- Reliability -->
<tr>
<td>
<a href="https://sonarcloud.io/summary/new_code?id=fernandotonacoder_chrisert">
<img src="https://sonarcloud.io/api/project_badges/measure?project=fernandotonacoder_chrisert&metric=reliability_rating" alt="Reliability Rating" />
</a>
</td>
<td>
<a href="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317">
<img src="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/measure?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&metric=software_quality_reliability_rating&token=sqb_29e1338abec328874a7e501928a3f3b3efa8a26c" alt="Reliability Rating (dev)" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://sonarcloud.io/summary/new_code?id=fernandotonacoder_chrisert">
<img src="https://sonarcloud.io/api/project_badges/measure?project=fernandotonacoder_chrisert&metric=bugs" alt="Bugs" />
</a>
</td>
<td>N/A — free tier limitation</td>
</tr>
<tr>
<td>N/A — free tier limitation</td>
<td>
<a href="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317">
<img src="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/measure?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&metric=software_quality_reliability_issues&token=sqb_29e1338abec328874a7e501928a3f3b3efa8a26c" alt="Reliability Issues" />
</a>
</td>
</tr>
<!-- Maintainability -->
<tr>
<td>
<a href="https://sonarcloud.io/summary/new_code?id=fernandotonacoder_chrisert">
<img src="https://sonarcloud.io/api/project_badges/measure?project=fernandotonacoder_chrisert&metric=sqale_rating" alt="Maintainability Rating" />
</a>
</td>
<td>
<a href="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317">
<img src="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/measure?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&metric=software_quality_maintainability_rating&token=sqb_29e1338abec328874a7e501928a3f3b3efa8a26c" alt="Maintainability Rating (dev)" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://sonarcloud.io/summary/new_code?id=fernandotonacoder_chrisert">
<img src="https://sonarcloud.io/api/project_badges/measure?project=fernandotonacoder_chrisert&metric=sqale_index" alt="Technical Debt" />
</a>
</td>
<td>
<a href="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317">
<img src="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/measure?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&metric=software_quality_maintainability_remediation_effort&token=sqb_29e1338abec328874a7e501928a3f3b3efa8a26c" alt="Technical Debt (dev)" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://sonarcloud.io/summary/new_code?id=fernandotonacoder_chrisert">
<img src="https://sonarcloud.io/api/project_badges/measure?project=fernandotonacoder_chrisert&metric=code_smells" alt="Code Smells" />
</a>
</td>
<td>N/A — free tier limitation</td>
</tr>
<tr>
<td>N/A — free tier limitation</td>
<td>
<a href="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317">
<img src="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/measure?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&metric=software_quality_maintainability_issues&token=sqb_29e1338abec328874a7e501928a3f3b3efa8a26c" alt="Maintainability Issues" />
</a>
</td>
</tr>
<!-- Coverage & Duplication -->
<tr>
<td>N/A — free tier limitation</td>
<td>
<a href="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317">
<img src="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/measure?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&metric=coverage&token=sqb_29e1338abec328874a7e501928a3f3b3efa8a26c" alt="Coverage (dev)" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://sonarcloud.io/summary/new_code?id=fernandotonacoder_chrisert">
<img src="https://sonarcloud.io/api/project_badges/measure?project=fernandotonacoder_chrisert&metric=duplicated_lines_density" alt="Duplicated Lines (%)" />
</a>
</td>
<td>
<a href="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317">
<img src="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/measure?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&metric=duplicated_lines_density&token=sqb_29e1338abec328874a7e501928a3f3b3efa8a26c" alt="Duplicated Lines (%) (dev)" />
</a>
</td>
</tr>
<!-- Size -->
<tr>
<td>
<a href="https://sonarcloud.io/summary/new_code?id=fernandotonacoder_chrisert">
<img src="https://sonarcloud.io/api/project_badges/measure?project=fernandotonacoder_chrisert&metric=ncloc" alt="Lines of Code" />
</a>
</td>
<td>
<a href="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317">
<img src="https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/measure?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&metric=ncloc&token=sqb_29e1338abec328874a7e501928a3f3b3efa8a26c" alt="Lines of Code (dev)" />
</a>
</td>
</tr>
</table>

---

A high-performance web platform for a construction firm specializing in ETICS insulation. Built to bridge modern frontend development with real-world business needs, focusing on SEO and lead generation.

## 📋 About
Expand All @@ -57,17 +190,17 @@ Optimized for performance and SEO to maximize the company's online visibility. F

## 🚀 Tech Stack

| Category | Technology |
| ------------- | --------------------------------------------------------------------------------------- |
| Framework | React |
| Language | JavaScript |
| Styling | Tailwind CSS |
| UI Components | Shadcn UI |
| Testing | Vitest |
| Code Quality | [SonarQube Cloud](https://sonarcloud.io/project/overview?id=fernandotonacoder_chrisert) |
| Staging | GitHub Pages |
| Production | Netlify |
| Forms | Netlify Forms |
| Category | Technology |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Framework | React |
| Language | JavaScript |
| Styling | Tailwind CSS |
| UI Components | Shadcn UI |
| Testing | Vitest |
| Code Quality | [SonarQube Cloud](https://sonarcloud.io/project/overview?id=fernandotonacoder_chrisert) (`main`) + [SonarQube Server](https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/dashboard?id=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317) (`dev`) |
| Staging | GitHub Pages |
| Production | Netlify |
| Forms | Netlify Forms |

## 🛠️ Getting Started

Expand All @@ -81,13 +214,10 @@ Optimized for performance and SEO to maximize the company's online visibility. F
```bash
# Clone the repository
git clone https://github.com/fernandotonacoder/chrisert.git

# Navigate to the project directory
cd chrisert

# Install dependencies
npm install

# Start the development server
npm run dev
```
Expand All @@ -97,19 +227,14 @@ npm run dev
```bash
# Run development server
npm run dev

# Run dev server accessible from other devices (e.g., mobile)
npm run dev -- --host

# Build for production
npm run build

# Run tests
npm run test

# Run tests with coverage report
npm run test:coverage

# Preview production build
npm run preview
```
Expand All @@ -132,6 +257,17 @@ npm run preview
- **Deployments:** Automatic on push to respective branches
- **Auto-Sync:** After each push to `main`, changes are automatically rebased onto `dev` to keep branches in sync

### Code Quality Strategy

This project uses two SonarQube instances with complementary roles:

| Instance | Branch | Role |
| ------------------------------------------- | ------ | ----------------------------------------------------------------------------------------- |
| **SonarQube Cloud** | `main` | Automatic analysis of production code; decorates PRs with quality feedback before merge |
| **SonarQube Server** (self-hosted on Azure) | `dev` | Continuous analysis of active development; monitors code quality before it reaches `main` |

SonarQube Cloud handles PR decoration automatically via GitHub App. The self-hosted server runs via GitHub Actions on every push to `dev`. See [`docs/sonarqube-admin.md`](docs/sonarqube-admin.md) for administration notes.

### Deployment Controls

- **Manual Triggers:** Both GitHub Pages and Netlify workflows can also be triggered manually via Actions → Run workflow
Expand Down Expand Up @@ -170,7 +306,13 @@ The **source code** of this project is licensed under the [MIT License](LICENSE)
**Fernando Tona**

- GitHub: [@fernandotonacoder](https://github.com/fernandotonacoder)
- LinkedIn: [Fernando Tona](https://www.linkedin.com/in/fernandotona/)
- Website: [fernandotonacoder.github.io](https://fernandotonacoder.github.io/)

---

<div align="center">

_Built with ❤️ for real-world business needs_

</div>
55 changes: 55 additions & 0 deletions docs/sonarqube-admin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# SonarQube Server — Administration Notes

### Administration commands and notes for the SonarQube Server (self-hosted) for this project.

> Instance: `https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net`

---

## Changing the project's main branch via API

SonarQube Community Build does not allow changing the default branch from _main_ to _dev_ through the graphical interface. The REST API must be used instead.

```bash
curl -X POST \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
"https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_branches/rename" \
-d "project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&name=dev"
```

Replace `<ADMIN_TOKEN>` with a User Token generated under **My Account → Security**.

---

## SonarQube Server Badges

SonarQube Server badges require a dedicated badge token. To generate one:

**Project Settings → Badges → Generate a token**

The badge token is different from the analysis token — it is read-only and is used solely to expose metrics publicly.

Badge URL:

```
https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net/api/project_badges/measure?project=fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317&metric=alert_status&token=<BADGE_TOKEN>
```

Available metrics: `alert_status`, `security_rating`, `sqale_rating`, `reliability_rating`, `coverage`, `duplicated_lines_density`

---

## Project Key

```
fernandotonacoder_chrisert_bbc86f72-9ba6-4533-99be-b85658dca317
```

---

## Required GitHub Repository Secrets

| Secret | Description |
| ---------------- | ------------------------------------------------------------------------------------------------ |
| `SONAR_TOKEN` | Project Analysis Token generated under My Account → Security → Project Analysis Token → chrisert |
| `SONAR_HOST_URL` | `https://sonarqube-ft-dpdwb8g8dnhkfbey.swedencentral-01.azurewebsites.net` |
Loading