diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml
index adf21d1..90feea9 100644
--- a/.github/workflows/sonarcloud.yml
+++ b/.github/workflows/sonarcloud.yml
@@ -10,44 +10,82 @@ on:
jobs:
sonar:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- - name: Install Rust toolchain
+ - name: Install Rust Toolchain & Components
uses: dtolnay/rust-toolchain@stable
with:
- components: clippy
+ components: clippy, llvm-tools-preview
- name: Install grcov
- run: cargo install grcov
+ run: cargo install grcov --force
- - name: Generate coverage
- run: |
- export CARGO_INCREMENTAL=0
- export RUSTFLAGS="-Cinstrument-coverage"
- export LLVM_PROFILE_FILE="coverage-%p-%m.profraw"
-
- cargo test
+ - name: Run Tests with Coverage Instrumentation
+ env:
+ CARGO_INCREMENTAL: "0"
+ RUSTFLAGS: "-Cinstrument-coverage"
+ LLVM_PROFILE_FILE: "%m.profraw"
+ run: cargo test --all --verbose
- grcov . --binary-path ./target/debug/ \
+ - name: Generate Coverage Report (lcov format)
+ run: |
+ grcov . \
+ --binary-path ./target/debug/deps/ \
-s . \
-t lcov \
--branch \
--ignore-not-existing \
+ --ignore "/*" \
-o lcov.info
+ - name: Convert lcov to SonarCloud Generic Coverage format
+ run: |
+ python3 << 'EOF'
+ import re
+
+ coverage = {}
+ current_file = None
+
+ with open('lcov.info', 'r') as f:
+ for line in f:
+ if line.startswith('SF:'):
+ current_file = line[3:].strip()
+ if current_file not in coverage:
+ coverage[current_file] = []
+ elif line.startswith('DA:') and current_file:
+ parts = line[3:].strip().split(',')
+ if len(parts) >= 2:
+ line_num = parts[0]
+ hits = parts[1]
+ coverage[current_file].append((line_num, hits))
+
+ with open('coverage.xml', 'w') as f:
+ f.write('\n')
+ f.write('\n')
+ for filepath, lines in coverage.items():
+ if lines:
+ f.write(f' \n')
+ for line_num, hits in lines:
+ f.write(f' 0 else "false"}"/>\n')
+ f.write(' \n')
+ f.write('\n')
+ EOF
+
+ - name: Delete profraw files
+ run: find . -name "*.profraw" -type f -delete
+
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@v2
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- args: >
- -Dsonar.projectKey=morutine_backend
+ args: >
+ -Dsonar.projectKey=MORUTINE_backend
-Dsonar.organization=morutine
- -Dsonar.projectBaseDir=.
- -Dsonar.coverageReportPaths=lcov.info
+ -Dsonar.coverageReportPaths=coverage.xml
\ No newline at end of file
diff --git a/morutine-api/src/common/error/error_into_response.rs b/morutine-api/src/common/error/error_into_response.rs
index 70d3d94..410fd31 100644
--- a/morutine-api/src/common/error/error_into_response.rs
+++ b/morutine-api/src/common/error/error_into_response.rs
@@ -18,7 +18,6 @@ impl IntoResponse for AppError {
let body = Json(json!({
"code": reason.code,
"message": reason.message,
- "data": {}
}));
(StatusCode::from_u16(reason.status).unwrap(), body).into_response()
@@ -30,9 +29,7 @@ impl IntoResponse for DatabaseApiError {
fn into_response(self) -> Response {
let app_error: AppError = match self.0 {
DatabaseErrorCode::UniqueViolation(_) => AppError::new(CommonErrorCode::Conflict),
-
DatabaseErrorCode::NotFound => AppError::new(CommonErrorCode::NotFound),
-
_ => AppError::new(CommonErrorCode::InternalServerError),
};
diff --git a/morutine-api/src/common/mod.rs b/morutine-api/src/common/mod.rs
index 52897d3..a91e735 100644
--- a/morutine-api/src/common/mod.rs
+++ b/morutine-api/src/common/mod.rs
@@ -1,2 +1 @@
pub mod error;
-pub mod response;
diff --git a/morutine-api/src/common/response/api_response.rs b/morutine-api/src/common/response/api_response.rs
deleted file mode 100644
index 8c11d15..0000000
--- a/morutine-api/src/common/response/api_response.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-use axum::{Json, http::StatusCode, response::IntoResponse};
-use common::constant::status::*;
-use serde::Serialize;
-
-#[derive(Debug, Serialize)]
-pub struct ApiResponse {
- pub status: u16,
- pub code: &'static str,
- pub message: Option<&'static str>,
- pub data: Option,
-}
-
-impl IntoResponse for ApiResponse {
- fn into_response(self) -> axum::response::Response {
- let status = StatusCode::from_u16(self.status).unwrap_or(StatusCode::OK);
- let body = Json(self);
-
- (status, body).into_response()
- }
-}
-
-impl ApiResponse {
- pub fn success(data: T) -> Self {
- ApiResponse {
- status: OK,
- code: "OK",
- message: None,
- data: Some(data),
- }
- }
-
- pub fn no_content() -> Self {
- ApiResponse {
- status: NO_CONTENT,
- code: "NO_CONTENT",
- message: None,
- data: None,
- }
- }
-}
diff --git a/morutine-api/src/common/response/mod.rs b/morutine-api/src/common/response/mod.rs
deleted file mode 100644
index 4f99ff6..0000000
--- a/morutine-api/src/common/response/mod.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod api_response;
diff --git a/morutine-api/src/domain/system/handlers.rs b/morutine-api/src/domain/system/handlers.rs
index 5152c1d..6a8bb4a 100644
--- a/morutine-api/src/domain/system/handlers.rs
+++ b/morutine-api/src/domain/system/handlers.rs
@@ -1,6 +1,7 @@
-use crate::common::response::api_response::ApiResponse;
+use axum::Json;
use axum::response::IntoResponse;
+use serde_json::json;
pub async fn health_check() -> impl IntoResponse {
- ApiResponse::success("OK")
+ Json(json!({"status": "OK"}))
}