Skip to content

Commit 38d6dd3

Browse files
feat: generate homepage service data
1 parent ea6ebde commit 38d6dd3

7 files changed

Lines changed: 104 additions & 7 deletions

File tree

.github/workflows/populate.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ jobs:
2020
- name: Populate data snapshots
2121
env:
2222
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23-
run: make populate
23+
run: |
24+
make populate
25+
make service-data
2426
2527
- name: Commit and push changes
2628
run: |
2729
git config user.name "github-actions[bot]"
2830
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
29-
git add data
31+
git add data docs/data
3032
if git diff --cached --quiet; then
3133
echo "No data changes to commit"
3234
exit 0

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ WATCH_USERS_FILE ?= data/watchusers.txt
99
IGNORE_ORGS_FILE ?= data/ignoreorgs.txt
1010
DATE_ARG := $(if $(SNAPSHOT_DATE),--date $(SNAPSHOT_DATE),)
1111

12-
.PHONY: serve populate trending
12+
.PHONY: serve populate trending service-data
1313
serve:
1414
python3 -m http.server $(PORT) --bind $(HOST) --directory $(ROOT)
1515

@@ -18,3 +18,6 @@ populate:
1818

1919
trending:
2020
python3 scripts/trending.py --limit $(TRENDING_LIMIT)
21+
22+
service-data:
23+
python3 scripts/service_data.py

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Il server espone direttamente la cartella `docs/`.
2727
- `data/organizations.csv`: esportazione tabellare dell'ultima fotografia.
2828
- `data/trending.json`: classifica trending corrente.
2929
- `data/trending.csv`: esportazione tabellare della classifica.
30+
- `data/service.json`: metadati di servizio usati dalla home, come conteggio organizzazioni e snapshot.
3031
- `data/YYYY/MM/DD/`: snapshot storici giornalieri.
3132
- `docs/data/`: copia pubblicabile via GitHub Pages.
3233

@@ -133,8 +134,9 @@ Le baseline a 30 giorni usano interpolazione lineare tra le letture disponibili.
133134
1. Aggiornare watchlist, ignorelist o dati sorgente.
134135
2. Eseguire `make populate`.
135136
3. Eseguire `make trending`.
136-
4. Verificare il sito con `make serve`.
137-
5. Committare dati, snapshot e pagine aggiornate.
137+
4. Eseguire `make service-data`.
138+
5. Verificare il sito con `make serve`.
139+
6. Committare dati, snapshot e pagine aggiornate.
138140

139141
## Segnala una organizzazione
140142

data/service.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"organizations_count": 104,
3+
"trending_count": 100,
4+
"snapshots_count": 1,
5+
"latest_snapshot": "2026/05/25",
6+
"generated_at": "2026-05-25T18:06:01.719800+00:00"
7+
}

docs/data/service.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"organizations_count": 104,
3+
"trending_count": 100,
4+
"snapshots_count": 1,
5+
"latest_snapshot": "2026/05/25",
6+
"generated_at": "2026-05-25T18:06:01.719800+00:00"
7+
}

docs/index.html

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ <h1>Organizzazioni italiane su GitHub</h1>
177177
</div>
178178
<aside class="status" aria-label="Stato dataset">
179179
<h2>Stato registro</h2>
180-
<div class="metric"><span>Organizzazioni</span><strong>22</strong></div>
181-
<div class="metric"><span>Snapshot</span><strong>1</strong></div>
180+
<div class="metric"><span>Organizzazioni</span><strong id="organizations-count">104</strong></div>
181+
<div class="metric"><span>Snapshot</span><strong id="snapshots-count">1</strong></div>
182182
</aside>
183183
</section>
184184

@@ -217,5 +217,16 @@ <h2>Snapshot</h2>
217217
<a href="https://alterloop.dev">Creato e mantenuto da Alterloop</a>
218218
</div>
219219
</footer>
220+
221+
<script>
222+
fetch("data/service.json")
223+
.then((response) => response.json())
224+
.then((data) => {
225+
const fmt = new Intl.NumberFormat("it-IT");
226+
document.querySelector("#organizations-count").textContent = fmt.format(data.organizations_count || 0);
227+
document.querySelector("#snapshots-count").textContent = fmt.format(data.snapshots_count || 0);
228+
})
229+
.catch(() => {});
230+
</script>
220231
</body>
221232
</html>

scripts/service_data.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env python3
2+
"""Build small service metadata used by the static site."""
3+
4+
from __future__ import annotations
5+
6+
import datetime as dt
7+
import json
8+
from pathlib import Path
9+
10+
ROOT = Path(__file__).resolve().parents[1]
11+
DATA_DIR = ROOT / "data"
12+
DOCS_DATA_DIR = ROOT / "docs" / "data"
13+
14+
15+
def read_json(path: Path, default):
16+
if not path.exists():
17+
return default
18+
with path.open("r", encoding="utf-8") as handle:
19+
return json.load(handle)
20+
21+
22+
def write_json(path: Path, payload) -> None:
23+
path.parent.mkdir(parents=True, exist_ok=True)
24+
with path.open("w", encoding="utf-8") as handle:
25+
json.dump(payload, handle, ensure_ascii=False, indent=2)
26+
handle.write("\n")
27+
28+
29+
def count_snapshots() -> int:
30+
if not DATA_DIR.exists():
31+
return 0
32+
count = 0
33+
for year_dir in DATA_DIR.iterdir():
34+
if not year_dir.is_dir() or not year_dir.name.isdigit():
35+
continue
36+
for month_dir in year_dir.iterdir():
37+
if not month_dir.is_dir() or not month_dir.name.isdigit():
38+
continue
39+
for day_dir in month_dir.iterdir():
40+
if day_dir.is_dir() and day_dir.name.isdigit() and (day_dir / "organizations.json").exists():
41+
count += 1
42+
return count
43+
44+
45+
def main() -> int:
46+
organizations = read_json(DATA_DIR / "organizations.json", [])
47+
trending = read_json(DATA_DIR / "trending.json", {})
48+
latest = read_json(DATA_DIR / "latest.json", {})
49+
50+
payload = {
51+
"organizations_count": len(organizations) if isinstance(organizations, list) else 0,
52+
"trending_count": len(trending.get("items", [])) if isinstance(trending, dict) else 0,
53+
"snapshots_count": count_snapshots(),
54+
"latest_snapshot": latest.get("snapshot", "") if isinstance(latest, dict) else "",
55+
"generated_at": dt.datetime.now(dt.timezone.utc).isoformat(),
56+
}
57+
58+
write_json(DATA_DIR / "service.json", payload)
59+
write_json(DOCS_DATA_DIR / "service.json", payload)
60+
print(f"Wrote service data for {payload['organizations_count']} organizations")
61+
return 0
62+
63+
64+
if __name__ == "__main__":
65+
raise SystemExit(main())

0 commit comments

Comments
 (0)