lesavka/scripts/ci/daily_master_gate.sh

137 lines
4.0 KiB
Bash
Raw Normal View History

#!/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}"