Repository navigation
99 lines (94 loc) · 5.11 KB
/
Copy pathci.yml
File metadata and controls
99 lines (94 loc) · 5.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
- run: uv python install 3.13
- run: uv sync --group dev
- run: uv run ruff check src tests
- run: uv run ruff format src tests --check
- run: uv run pytest --cov --cov-report=term-missing
# ── SMOKE DELLA NIGHTLY ────────────────────────────────────────────────────
# Esegue gli STESSI script che la nightly invoca, su OGNI push/PR. Scopo:
# qualunque modifica di codice che rompa uno script della nightly diventa
# rosso QUI (a costo zero di notte), non alle 4 del mattino. È il pilastro
# "nessuna modifica di codice romperà la nightly" del fix definitivo.
# Regola di progetto: ogni nuovo step aggiunto a nightly.yml DEVE essere
# aggiunto qui nello stesso PR. Vedi CLAUDE.md §"CRITICAL: Nightly must never break".
smoke:
name: Nightly scripts smoke test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
- run: uv python install 3.13
- run: uv sync --group dev
# 1) Import-check di OGNI script invocato dalla nightly, inclusi quelli di
# rete che qui non possiamo eseguire (fetch_indicepa, recover/finalize,
# enrich). Esegue il top-level del modulo (import + def) SENZA lanciare
# il main(): intercetta sia errori di sintassi sia errori di import
# (es. una funzione rinominata in mail_sovereignty usata da uno script).
# È la rete di sicurezza per "nessuna modifica di codice romperà la nightly".
- name: Import-check every nightly script (syntax + imports, no main)
run: |
uv run python - <<'PY'
import importlib.util, pathlib, signal, sys
scripts = """
fetch_indicepa fetch_istat_comuni strip_to_it enrich_from_aoo_uo recover_it_unknowns finalize_it_unknowns
cleanup_invalid_mx_attributions backfill_mx_discovery geocode_istruzione aggregate_istruzione_per_comune
enrich_geo compute_confidence report_confidence report_anomalies report_it_by_cluster build_frontend
build_public_dataset build_stats build_kpi build_report build_sitemap build_entity_pages historicize build_dcat
""".split()
# Guardia: un import non deve fare I/O. Se un modulo "appende" (es. rete a
# livello di modulo) lo facciamo fallire in 30s invece di bloccare la CI.
def _on_timeout(signum, frame):
raise TimeoutError("import >30s (I/O a livello di modulo?)")
signal.signal(signal.SIGALRM, _on_timeout)
failed = []
for name in scripts:
p = pathlib.Path("scripts") / f"{name}.py"
spec = importlib.util.spec_from_file_location(f"_smoke_{name}", p)
mod = importlib.util.module_from_spec(spec)
signal.alarm(30)
try:
spec.loader.exec_module(mod) # top-level only; __name__ != "__main__"
print("OK ", name)
except Exception as e: # noqa: BLE001
failed.append(name); print("FAIL", name, "->", repr(e))
finally:
signal.alarm(0)
if failed:
print(f"\n{len(failed)} script non importabili: {failed}", file=sys.stderr)
sys.exit(1)
PY
# 2) Esecuzione REALE della coda deterministica della pipeline sul data.json
# committato (nessuna rete): se una modifica rompe a RUNTIME uno di
# questi script, il job va rosso PRIMA del merge. Stesso ordine della
# nightly. historicize/build_dcat sono inclusi così che, quando li
# riattiveremo nella nightly, siano già provati verdi in CI.
- name: Run deterministic pipeline tail on committed data.json
run: |
uv run python3 scripts/strip_to_it.py --keep IT
uv run python3 scripts/enrich_geo.py --country IT
uv run python3 scripts/compute_confidence.py --country IT
uv run python3 scripts/report_confidence.py --country IT
uv run python3 scripts/report_anomalies.py --country IT
uv run python3 scripts/report_it_by_cluster.py
uv run validate || true # il quality gate è un SEGNALE, non deve bloccare la CI
uv run python3 scripts/build_frontend.py
uv run python3 scripts/build_public_dataset.py
uv run python3 scripts/build_stats.py --country IT
uv run python3 scripts/build_kpi.py --country IT
uv run python3 scripts/build_report.py --country IT
# SEO pages (#15): subset for speed — exercises entity/hub/category/alias
# rendering + sitemap-index + integrity assertions without 48k files.
uv run python3 scripts/build_entity_pages.py --country IT --limit 300
uv run python3 scripts/historicize.py --run-id ci-smoke --git-sha "${GITHUB_SHA}" --pipeline-version ci-smoke
uv run python3 scripts/build_dcat.py