Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/data_correction.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ body:
id: location_id
attributes:
label: Identificativo del record
description: location_id oppure legacy_uuid.
description: location_id del record corrente.
placeholder: IT-COM-058091
validations:
required: true
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/missing-coordinate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body:
id: location_id
attributes:
label: Identificativo
description: "`location_id` o `legacy_uuid`."
description: "`location_id` del record corrente."
validations:
required: true
- type: input
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/wrong-locality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body:
id: location_id
attributes:
label: Identificativo
description: "`location_id` o `legacy_uuid` del record."
description: "`location_id` del record corrente."
placeholder: IT-LOC-e6b0bc3e-1acf-5509-8923-238575fc9025
validations:
required: true
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/wrong-postal-code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body:
id: location_id
attributes:
label: Identificativo
description: "`location_id` o `legacy_uuid`."
description: "`location_id` del record corrente."
validations:
required: true
- type: input
Expand Down
17 changes: 15 additions & 2 deletions .github/workflows/data-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,19 @@ jobs:
- name: Lint Python sources and tests
run: ruff check scripts tests

- name: Type-check the validation boundary
- name: Type-check all maintained Python scripts
run: mypy

- name: Enforce validator test coverage
- name: Enforce maintained-script test coverage
run: |
coverage run -m unittest discover -s tests
coverage run --append scripts/build_dataset.py
coverage run --append scripts/build_pages.py
coverage run --append scripts/build_release.py
coverage run --append scripts/validate_release.py
coverage run --append scripts/build_geography.py --check
coverage report
coverage xml

python-compatibility:
name: Python ${{ matrix.python-version }}
Expand Down Expand Up @@ -109,9 +115,15 @@ jobs:
- name: Test Pages search and map logic
run: node --test tests/pages_core.test.mjs

- name: Verify committed geographic base
run: python scripts/build_geography.py --check

- name: Build deterministic GitHub Pages site
run: python scripts/build_pages.py

- name: Validate Pages accessibility, links and budgets
run: python scripts/validate_site.py dist/pages

- name: Build versioned release assets
run: python scripts/build_release.py

Expand All @@ -135,6 +147,7 @@ jobs:
reports/release-diff.json
reports/build-metadata.json
reports/legacy-comparison.json
reports/reconciliation-backlog.json
reports/export-manifest.json
reports/determinism.json
reports/quality-validation.json
8 changes: 8 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
- "data/italian_locations.csv"
- "project.json"
- "scripts/build_pages.py"
- "scripts/build_geography.py"
- "scripts/project_metadata.py"
- "site/**"
- "tests/pages_core.test.mjs"
Expand All @@ -21,6 +22,7 @@ on:
- "data/italian_locations.csv"
- "project.json"
- "scripts/build_pages.py"
- "scripts/build_geography.py"
- "scripts/project_metadata.py"
- "site/**"
- "tests/pages_core.test.mjs"
Expand Down Expand Up @@ -61,9 +63,15 @@ jobs:
- name: Test deterministic Pages build
run: python -m unittest discover -s tests -p "test_pages.py" -v

- name: Verify committed geographic base
run: python scripts/build_geography.py --check

- name: Build GitHub Pages artifact
run: python scripts/build_pages.py --output _site

- name: Validate accessibility, local links and performance budgets
run: python scripts/validate_site.py _site

- name: Configure GitHub Pages
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0

Expand Down
42 changes: 40 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,18 @@ jobs:
- name: Check out tagged commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false

- name: Require tagged commit to be integrated in the default branch
env:
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
run: |
git fetch --no-tags origin "${DEFAULT_BRANCH}"
git merge-base --is-ancestor \
"${GITHUB_SHA}" \
"origin/${DEFAULT_BRANCH}"

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
Expand Down Expand Up @@ -104,7 +114,7 @@ jobs:
! gh release view "${GITHUB_REF_NAME}"
--repo "${GITHUB_REPOSITORY}"

- name: Create GitHub release
- name: Create draft GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: |
Expand All @@ -113,18 +123,20 @@ jobs:
gh release create "${GITHUB_REF_NAME}" \
--repo "${GITHUB_REPOSITORY}" \
--verify-tag \
--draft \
--prerelease \
--title "Italian Cities ${GITHUB_REF_NAME}" \
--notes-file "release/${GITHUB_REF_NAME}.md"
else
gh release create "${GITHUB_REF_NAME}" \
--repo "${GITHUB_REPOSITORY}" \
--verify-tag \
--draft \
--title "Italian Cities ${GITHUB_REF_NAME}" \
--notes-file "release/${GITHUB_REF_NAME}.md"
fi

- name: Upload immutable release assets
- name: Upload release assets to the draft
env:
GH_TOKEN: ${{ github.token }}
run: |
Expand All @@ -139,3 +151,29 @@ jobs:
"dist/${GITHUB_REF_NAME}/italian_locations.sql" \
"dist/${GITHUB_REF_NAME}/SHA256SUMS" \
--repo "${GITHUB_REPOSITORY}"

- name: Verify draft assets before publication
env:
GH_TOKEN: ${{ github.token }}
run: |
expected_assets="$(
find "dist/${GITHUB_REF_NAME}" -maxdepth 1 -type f \
-exec basename {} \; |
LC_ALL=C sort
)"
published_assets="$(
gh release view "${GITHUB_REF_NAME}" \
--repo "${GITHUB_REPOSITORY}" \
--json assets \
--jq '.assets[].name' |
LC_ALL=C sort
)"
test "${expected_assets}" = "${published_assets}"

- name: Publish the complete release
env:
GH_TOKEN: ${{ github.token }}
run: >-
gh release edit "${GITHUB_REF_NAME}"
--repo "${GITHUB_REPOSITORY}"
--draft=false
68 changes: 68 additions & 0 deletions .github/workflows/source-freshness.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: Source freshness

on:
schedule:
- cron: "17 6 * * 1"
workflow_dispatch:

permissions:
contents: read
issues: write

jobs:
check:
name: Check canonical upstream sources
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
cache: pip

- name: Install runtime dependencies
run: python -m pip install -r requirements.txt

- name: Compare declared snapshots with upstream artifacts
run: >-
python scripts/update_sources.py
--check
--report "${RUNNER_TEMP}/source-freshness.json"

- name: Preserve freshness evidence
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: source-freshness
path: ${{ runner.temp }}/source-freshness.json
retention-days: 30

- name: Open one tracking issue when an update is available
env:
GH_TOKEN: ${{ github.token }}
REPORT: ${{ runner.temp }}/source-freshness.json
run: |
updates="$(python -c 'import json, os; print(", ".join(json.load(open(os.environ["REPORT"]))["updates_available"]))')"
if [ -z "${updates}" ]; then
exit 0
fi
existing="$(
gh issue list \
--repo "${GITHUB_REPOSITORY}" \
--state open \
--search '"Upstream source update available" in:title' \
--json number \
--jq 'length'
)"
if [ "${existing}" -eq 0 ]; then
gh issue create \
--repo "${GITHUB_REPOSITORY}" \
--title "Upstream source update available" \
--label "source-update" \
--body "The scheduled freshness check detected changes for: ${updates}. Review the workflow artifact and use scripts/update_sources.py to stage a dated snapshot. No source or generated dataset was modified automatically."
fi
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
sources/cache/*
!sources/cache/.gitkeep
.DS_Store
.venv/
__pycache__/
*.pyc
*.tmp
Expand Down
22 changes: 21 additions & 1 deletion DATASET_PIPELINE.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ canonica. `scripts/export_sql.py` crea lo script SQLite-compatible.
- `reports/build-metadata.json`: fonti, qualità, readiness e statistiche;
- `reports/legacy-comparison.json`: confronto storico limitato e deterministico;
- `reports/release-diff.json`: confronto logico con v1.1.0;
- `reports/reconciliation-backlog.json`: segmenti da revisionare per regione,
provincia e codice territoriale sorgente;
- `reports/export-manifest.json`: digest degli export;
- `reports/determinism.json`: firme di due build;
- `reports/quality-validation.json`: gate strutturali separati dalla readiness.
Expand Down Expand Up @@ -114,7 +116,25 @@ a commit SHA immutabili.

## Aggiornamento fonti

1. acquisire un nuovo snapshot dalla stessa origine autorizzata;
Controllare senza modificare il repository:

```bash
python scripts/update_sources.py --check
```

Per preparare esplicitamente un nuovo snapshot in un percorso datato:

```bash
python scripts/update_sources.py \
--download geonames_postal_codes \
--output sources/cache/IT-new.zip
```

Lo script rifiuta di sovrascrivere file esistenti e non modifica il manifest.
Il workflow settimanale `Source freshness` apre una sola issue quando rileva
un checksum upstream differente; non esegue commit né rigenera il dataset.

1. acquisire o preparare un nuovo snapshot dalla stessa origine autorizzata;
2. conservarlo sotto un percorso datato;
3. aggiornare manifest, checksum, timestamp e riferimento;
4. modificare la trasformazione se il formato cambia;
Expand Down
2 changes: 1 addition & 1 deletion DATA_LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Dataset licensing

Il candidato v2 combina esclusivamente due fonti canoniche attribuite:
La release v2 combina esclusivamente due fonti canoniche attribuite:

| Componente | Licenza |
| --- | --- |
Expand Down
35 changes: 22 additions & 13 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
Italian Cities licensing notice
Italian Cities multi-license notice

Repository code and original documentation
------------------------------------------

The repository's original code and documentation are offered under CC0 1.0
Universal to the extent that the repository owner holds the applicable rights.
The complete legal text is available at:
The repository's original code and documentation are dedicated under CC0 1.0
Universal to the extent that the repository owner holds the applicable
rights. The complete legal text is available at:

LICENSES/CC0-1.0.txt

Dataset and third-party inputs
------------------------------

The CC0 dedication above does not apply to third-party source material or
prove that legacy geographic and postal values may be relicensed under CC0.
The canonical dataset combines:
The CC0 dedication above does not apply to third-party source material or to
the canonical dataset derived from it. Italian Cities v2 combines:

- legacy values whose upstream provenance and rights are not fully known;
- ISTAT-derived classifications and codes that require attribution under
CC BY 4.0.
- ISTAT municipality classifications and codes, licensed under CC BY 4.0;
- GeoNames Postal Codes for Italy, licensed under CC BY 4.0.

The dataset is therefore distributed with provisional licensing status and
must not be represented as entirely CC0. Read DATA_LICENSE.md, NOTICE.md and
DATA_SOURCES.md before reuse or redistribution.
Reuse of the canonical dataset therefore requires attribution to both ISTAT
and GeoNames under CC BY 4.0. It must not be represented as entirely CC0.
Read DATA_LICENSE.md, NOTICE.md and DATA_SOURCES.md before reuse or
redistribution.

Historical material
-------------------

Files under legacy/ are retained only as a historical archive and bounded
comparison input. They do not contribute to the v2 canonical dataset,
derived formats, GitHub Pages or release assets. Their upstream provenance
and rights have not been independently established by the current pipeline;
their presence does not extend the repository CC0 dedication to their
contents.

No warranty
-----------
Expand Down
2 changes: 1 addition & 1 deletion NOTICE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ determined or estimated algorithmically; the source `accuracy` field is
preserved by this project.

Historical files under `legacy/` do not contribute to the v2 canonical
dataset, derived formats, release candidate or GitHub Pages data. They are
dataset, derived formats, published release or GitHub Pages data. They are
used only for a bounded investigative comparison, which cannot establish
their original provenance.
Loading