#!/usr/bin/env bash # Run the safe daily gate for the current primary branch. set -euo pipefail ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) REPORT_DIR="${ROOT_DIR}/target/daily-master-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:-} PUSHGATEWAY_JOB=${LESAVKA_DAILY_GATE_PUSHGATEWAY_JOB:-lesavka-daily-master-gate} 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 build_url=${BUILD_URL:-} is_primary_branch=0 case "${branch}" in master|main|origin/master|origin/main|*/master|*/main) is_primary_branch=1 ;; esac status=0 outcome=ok detail="ran safe platform quality gate" start_seconds=$(date +%s) if [[ "${is_primary_branch}" != "1" && "${LESAVKA_DAILY_ALLOW_NON_PRIMARY:-0}" != "1" ]]; then outcome=skipped detail="daily gate only evaluates master/main by default" else set +e LESAVKA_CI_PROFILE=daily scripts/ci/platform_quality_gate.sh status=$? set -e if [[ "${status}" -ne 0 ]]; then outcome=failed detail="safe platform quality gate failed" fi fi duration_seconds=$(($(date +%s) - start_seconds)) python3 - \ "${SUMMARY_JSON}" \ "${SUMMARY_TXT}" \ "${METRICS_FILE}" \ "${branch}" \ "${commit}" \ "${build_url}" \ "${outcome}" \ "${status}" \ "${duration_seconds}" \ "${detail}" <<'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]) branch = sys.argv[4] commit = sys.argv[5] build_url = sys.argv[6] outcome = sys.argv[7] status = int(sys.argv[8]) duration_seconds = int(sys.argv[9]) detail = sys.argv[10] def esc(value: str) -> str: return value.replace('\\', r'\\').replace('\n', r'\n').replace('"', r'\"') summary = { 'suite': 'lesavka', 'profile': 'daily', 'branch': branch, 'commit': commit, 'build_url': build_url, 'outcome': outcome, 'exit_code': status, 'duration_seconds': duration_seconds, 'detail': detail, '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( '\n'.join([ f'lesavka daily gate: {outcome}', f'branch: {branch}', f'commit: {commit}', f'duration: {duration_seconds}s', f'detail: {detail}', ]) + '\n', encoding='utf-8', ) labels = f'suite="lesavka",profile="daily",branch="{esc(branch)}",commit="{esc(commit)}"' ok = 1 if outcome == 'ok' else 0 failed = 1 if outcome == 'failed' else 0 skipped = 1 if outcome == 'skipped' else 0 metrics_path.write_text( '\n'.join([ '# HELP lesavka_ci_profile_last_run_success Whether the latest Lesavka CI profile run succeeded.', '# TYPE lesavka_ci_profile_last_run_success gauge', f'lesavka_ci_profile_last_run_success{{{labels}}} {ok}', '# HELP lesavka_ci_profile_duration_seconds Duration of the latest Lesavka CI profile run.', '# TYPE lesavka_ci_profile_duration_seconds gauge', f'lesavka_ci_profile_duration_seconds{{{labels}}} {duration_seconds}', '# HELP lesavka_ci_profile_runs Current profile run outcome.', '# TYPE lesavka_ci_profile_runs gauge', f'lesavka_ci_profile_runs{{{labels},status="ok"}} {ok}', f'lesavka_ci_profile_runs{{{labels},status="failed"}} {failed}', f'lesavka_ci_profile_runs{{{labels},status="skipped"}} {skipped}', ]) + '\n', encoding='utf-8', ) PY if [[ -n "${PUSHGATEWAY_URL}" ]]; then curl --fail --silent --show-error \ --data-binary @"${METRICS_FILE}" \ "${PUSHGATEWAY_URL%/}/metrics/job/${PUSHGATEWAY_JOB}/suite/lesavka" || status=$? fi exit "${status}"