Skip to content

Refactor API endpoints and fix product reducer import path #1582

Refactor API endpoints and fix product reducer import path

Refactor API endpoints and fix product reducer import path #1582

Workflow file for this run

# SonarQube Analysis Pipeline
# Runs code quality and security analysis on every PR and push to main branches
name: SonarQube Analysis
on:
push:
branches: ['develop', 'master']
pull_request:
branches: ['develop', 'master']
workflow_dispatch:
inputs:
branch:
description: 'Branch to analyze (must be develop or master)'
required: false
default: 'develop'
type: choice
options:
- develop
- master
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
# SonarQube Community Build 25.x requires the scanner to run on Java 17+
JAVA_VERSION: '21'
NODE_VERSION: '18.x'
SONAR_HOST_URL: 'https://sonarqube.datainn.io'
jobs:
sonarqube:
name: Build and Analyze
runs-on: k3s-simpleaccounts-runners
timeout-minutes: 45
permissions:
contents: read
pull-requests: read
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
with:
fetch-depth: 0 # Full history for accurate blame information
- name: Determine whether to run SonarQube
id: sonar
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN || secrets.SONARQUBE_TOKEN }}
run: |
if [ "${{ github.event_name }}" = "pull_request" ] && [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then
echo "run=false" >> "$GITHUB_OUTPUT"
echo "::notice::Fork PR detected; SonarQube analysis is skipped because GitHub Actions secrets are not available to forks."
exit 0
fi
if [ "${{ github.event_name }}" = "pull_request" ] && [ -z "$SONAR_TOKEN" ]; then
echo "run=false" >> "$GITHUB_OUTPUT"
echo "::notice::SONAR_TOKEN is not available in this PR context (e.g., Dependabot); skipping SonarQube analysis."
exit 0
fi
echo "run=true" >> "$GITHUB_OUTPUT"
- name: Set up JDK
if: steps.sonar.outputs.run == 'true'
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: 'temurin'
cache: maven
- name: Set up Node.js
if: steps.sonar.outputs.run == 'true'
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Cache SonarQube packages
if: steps.sonar.outputs.run == 'true'
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Maven packages
if: steps.sonar.outputs.run == 'true'
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v4
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Cache Node dependencies
if: steps.sonar.outputs.run == 'true'
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v4
with:
path: |
node_modules
apps/frontend/node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- name: Install Node dependencies
if: steps.sonar.outputs.run == 'true'
run: |
npm ci --legacy-peer-deps
cd apps/frontend && npm ci --legacy-peer-deps
# Frontend: Test and Generate Coverage (don't fail on thresholds, just report to SonarQube)
- name: Test Frontend with Coverage
if: steps.sonar.outputs.run == 'true'
working-directory: apps/frontend
run: npm test -- --coverage --watchAll=false --coverageThreshold='{}' || true
env:
CI: true
NODE_OPTIONS: --openssl-legacy-provider
# Backend: Build, Test, and Analyze with SonarQube
- name: Build and Test Backend
if: steps.sonar.outputs.run == 'true'
working-directory: apps/backend
env:
SPRING_PROFILES_ACTIVE: test
run: ./mvnw -B test -Dspring.profiles.active=test || true
continue-on-error: true
- name: Generate Coverage Report
if: steps.sonar.outputs.run == 'true'
working-directory: apps/backend
run: ./mvnw jacoco:report || true
continue-on-error: true
# Import SSL certificate and run SonarQube Analysis
- name: Import SonarQube SSL Certificate
if: steps.sonar.outputs.run == 'true'
continue-on-error: true
run: |
SONAR_HOST=$(echo "${{ secrets.SONAR_HOST_URL || env.SONAR_HOST_URL }}" | sed -E 's#^https?://##;s#/.*##')
if [ -z "$SONAR_HOST" ]; then
echo "::warning::Unable to resolve SonarQube host from SONAR_HOST_URL."
exit 0
fi
# Fetch and import the SSL certificate (non-blocking)
echo | openssl s_client -servername "$SONAR_HOST" \
-connect "$SONAR_HOST:443" 2>/dev/null | \
openssl x509 -out /tmp/sonar.crt || echo "::warning::Could not fetch SSL certificate"
if [ -f /tmp/sonar.crt ]; then
sudo keytool -import -trustcacerts -keystore $JAVA_HOME/lib/security/cacerts \
-storepass changeit -noprompt -alias sonarqube -file /tmp/sonar.crt || true
fi
# Run SonarQube Analysis (Community Edition - no branch/PR support)
- name: Run SonarQube Analysis
if: steps.sonar.outputs.run == 'true'
continue-on-error: true
working-directory: apps/backend
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN || secrets.SONARQUBE_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL || env.SONAR_HOST_URL }}
run: |
if [ -z "$SONAR_TOKEN" ]; then
echo "::warning::SONAR_TOKEN is not set (configure repo secret SONAR_TOKEN)."
exit 0
fi
if [ -z "$SONAR_HOST_URL" ]; then
echo "::warning::SONAR_HOST_URL is not set (configure repo secret SONAR_HOST_URL or workflow env)."
exit 0
fi
mvn -B org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \
-Dsonar.projectKey=SimpleAccounts_SimpleAccounts-UAE_f0046086-4810-411a-9ca7-6017268b2eb9 \
-Dsonar.projectName="SimpleAccounts-UAE" \
-Dsonar.host.url="$SONAR_HOST_URL" \
-Dsonar.token=$SONAR_TOKEN \
-Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml \
-Dsonar.javascript.lcov.reportPaths=../../apps/frontend/coverage/lcov.info \
-Dsonar.scanner.skipJreProvisioning=true \
-Dsonar.scanner.os=linux \
-Dsonar.scanner.arch=x64 \
-Dsonar.scanner.truststorePath=${JAVA_HOME}/lib/security/cacerts \
-Dsonar.scanner.truststorePassword=changeit \
-Dsonar.qualitygate.wait=true \
-Dsonar.qualitygate.timeout=300 \
-DskipTests=true
# Check Quality Gate status - fails the workflow if quality gate fails
- name: Check Quality Gate Status
if: steps.sonar.outputs.run == 'true' && always()
continue-on-error: true
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN || secrets.SONARQUBE_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL || env.SONAR_HOST_URL }}
run: |
echo "Checking Quality Gate status..."
sleep 15
if [ -z "$SONAR_TOKEN" ]; then
echo "::warning::SONAR_TOKEN is not set (configure repo secret SONAR_TOKEN)."
exit 0
fi
if [ -z "$SONAR_HOST_URL" ]; then
echo "::warning::SONAR_HOST_URL is not set (configure repo secret SONAR_HOST_URL or workflow env)."
exit 0
fi
PROJECT_KEY="SimpleAccounts_SimpleAccounts-UAE_f0046086-4810-411a-9ca7-6017268b2eb9"
API_URL="$SONAR_HOST_URL/api/qualitygates/project_status?projectKey=${PROJECT_KEY}"
DASHBOARD_URL="$SONAR_HOST_URL/dashboard?id=${PROJECT_KEY}"
# Add retry logic to handle transient network/SSL issues
RESPONSE=$(curl -sS --retry 5 --retry-delay 5 --retry-connrefused --connect-timeout 30 --max-time 60 -u "$SONAR_TOKEN:" "$API_URL" 2>&1) #gitleaks:allow
STATUS=$(echo "$RESPONSE" | jq -r '.projectStatus.status // empty' 2>/dev/null)
echo "Quality Gate Status: $STATUS"
echo "Dashboard: $DASHBOARD_URL"
if [ -z "$STATUS" ]; then
echo ""
echo "::warning::Unable to determine Quality Gate status from SonarQube response (connection issue)."
echo "$RESPONSE"
exit 0
fi
if [ "$STATUS" != "OK" ]; then
echo ""
echo "::error::Quality Gate FAILED!"
echo "Failed conditions:"
echo "$RESPONSE" | jq -r '.projectStatus.conditions[] | select(.status != "OK") | " - \(.metricKey): \(.actualValue) (threshold: \(.errorThreshold))"'
exit 1
fi
echo "::notice::Quality Gate PASSED!"