lesavka/scripts/ci/sonarqube_gate.sh

99 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# Run or account for SonarQube analysis in the Atlas quality contract.
set -euo pipefail
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
REPORT_DIR="${ROOT_DIR}/target/sonarqube-gate"
SUMMARY_JSON="${REPORT_DIR}/summary.json"
SUMMARY_TXT="${REPORT_DIR}/summary.txt"
METRICS_FILE="${REPORT_DIR}/metrics.prom"
PUSHGATEWAY_URL=${QUALITY_GATE_PUSHGATEWAY_URL:-}
ENFORCE=${LESAVKA_SONAR_ENFORCE:-0}
mkdir -p "${REPORT_DIR}"
cd "${ROOT_DIR}"
branch=${BRANCH_NAME:-${GIT_BRANCH:-}}
if [[ -z "${branch}" ]]; then
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)
fi
commit=${GIT_COMMIT:-}
if [[ -z "${commit}" ]]; then
commit=$(git rev-parse --short HEAD 2>/dev/null || echo unknown)
fi
status=0
sonar_status=not_applicable
reason='SONARQUBE_HOST_URL, SONARQUBE_TOKEN, or sonar-scanner is unavailable'
if [[ -n "${SONARQUBE_HOST_URL:-}" && -n "${SONARQUBE_TOKEN:-}" ]] && command -v sonar-scanner >/dev/null 2>&1; then
sonar_status=ok
reason='sonar-scanner completed'
if ! sonar-scanner \
-Dsonar.projectKey=lesavka \
-Dsonar.projectName=lesavka \
-Dsonar.sources=client/src,server/src,common/src,testing/src \
-Dsonar.tests=testing/tests \
-Dsonar.host.url="${SONARQUBE_HOST_URL}" \
-Dsonar.token="${SONARQUBE_TOKEN}" \
>"${REPORT_DIR}/sonar-scanner.log" 2>&1; then
sonar_status=failed
reason='sonar-scanner failed; see sonar-scanner.log'
status=1
fi
elif [[ "${ENFORCE}" == "1" ]]; then
sonar_status=failed
status=1
fi
python3 - "${SUMMARY_JSON}" "${SUMMARY_TXT}" "${METRICS_FILE}" "${sonar_status}" "${reason}" "${branch}" "${commit}" <<'PY'
import json
import pathlib
import sys
from datetime import datetime, timezone
summary_path = pathlib.Path(sys.argv[1])
text_path = pathlib.Path(sys.argv[2])
metrics_path = pathlib.Path(sys.argv[3])
sonar_status = sys.argv[4]
reason = sys.argv[5]
branch = sys.argv[6]
commit = sys.argv[7]
def esc(value: str) -> str:
return value.replace('\\', r'\\').replace('\n', r'\n').replace('"', r'\"')
summary = {
'suite': 'lesavka',
'check': 'sonarqube',
'status': sonar_status,
'reason': reason,
'branch': branch,
'commit': commit,
'generated_at': datetime.now(timezone.utc).isoformat(),
}
summary_path.write_text(json.dumps(summary, indent=2, sort_keys=True) + '\n', encoding='utf-8')
text_path.write_text(
f'sonarqube gate report\nstatus: {sonar_status}\nreason: {reason}\nbranch: {branch}\ncommit: {commit}\n',
encoding='utf-8',
)
labels = f'suite="lesavka",branch="{esc(branch)}",commit="{esc(commit)}"'
statuses = {'ok': 0, 'failed': 0, 'not_applicable': 0}
statuses[sonar_status] = 1
metrics = [
'# HELP platform_quality_gate_checks_total Check outcomes from the latest lesavka gate run.',
'# TYPE platform_quality_gate_checks_total gauge',
]
for state, value in statuses.items():
metrics.append(f'platform_quality_gate_checks_total{{{labels},check="sonarqube",status="{state}"}} {value}')
metrics_path.write_text('\n'.join(metrics) + '\n', encoding='utf-8')
print(text_path.read_text(encoding='utf-8'))
PY
if [[ -n "${PUSHGATEWAY_URL}" ]]; then
curl --fail --silent --show-error \
--data-binary @"${METRICS_FILE}" \
"${PUSHGATEWAY_URL%/}/metrics/job/lesavka-sonarqube-gate/suite/lesavka" || status=$?
fi
exit "${status}"