Files
superset2/superset-frontend/plugins/plugin-chart-country-map/scripts/procedural/README.md
Evan Rusackas 9fd7fd441a fix(country-map): CI failures — license headers, lockfile sync, reproducible build
Three coordinated fixes for the 25 CI failures on the initial PR push:

1. **Lockfile sync.** Added @superset-ui/plugin-chart-country-map as
   a workspace dep in the previous commit but didn't update
   package-lock.json. CI's `npm ci` failed across frontend-build,
   cypress (12 jobs), playwright (4 jobs), docker (2 jobs), and
   frontend-check-translations. Re-ran `npm install --package-lock-only`
   to add the new workspace's 71 lock entries.

2. **License headers added** to 13 new files flagged by License Check:
   - 5 markdown READMEs / SIP_DRAFT (HTML-comment headers)
   - 5 YAML config files (`# Licensed ...`)
   - 2 Python files (`# Licensed ...`)
   - 1 shell script (preserves shebang)

3. **Reproducible build outputs.** The regen workflow detected drift
   on manifest.json + ukr_admin1_CAN.geo.json. Two root causes:
   - `build_timestamp_utc` field made manifest non-deterministic →
     dropped from the schema
   - Floating mapshaper version (`npx --yes mapshaper`) caused subtle
     simplification differences across runners → pinned to
     `mapshaper@0.7.15` via `npx --yes mapshaper@<version>`

Verified locally: rebuild from clean cache reproduces every output
byte-identically except the manifest (which now also matches once
the timestamp is gone).

Files changed:
  .gitignore                           — re-include rule for static dir
  superset-frontend/package-lock.json  — +71 lines for new workspace
  13 new files                         — ASF headers
  build.py                             — pin mapshaper, drop timestamp
  manifest.json (× 2)                  — regenerate w/o timestamp
  README.md (in static dir)            — header

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 22:32:51 -07:00

82 lines
3.6 KiB
Markdown

<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Procedural escape hatch
Small, named, single-purpose Python scripts for the rare cases where declarative YAML in `../config/` can't cleanly express a fix.
## When to put a script here
Use this directory when **all** of the following are true:
- You've tried to express the fix in YAML and the resulting schema is awkward, ambiguous, or requires a one-off type to be added
- The fix is small (typically <50 lines of code, single conceptual operation)
- The fix is tied to a *specific feature* in the data (not a generalizable transform)
## When NOT to put a script here
If any of the following apply, the fix belongs in `../config/` instead:
- It's a typo, rename, or attribute correction → `name_overrides.yaml`
- It's a reposition or bbox drop of a known territory → `flying_islands.yaml`
- It's adding a feature from another country → `territory_assignments.yaml`
- It's dissolving Admin 1 into a coarser admin level → `regional_aggregations.yaml`
- It's a multi-country composite → `composite_maps.yaml`
If the same kind of operation surfaces here twice, that's a signal to extend a YAML schema rather than ship a third script.
## Script conventions
- **Filename:** `NN_<descriptive_snake_case>.py`. The numeric prefix sets execution order; the name documents intent.
- **Header comment:** required. Must explain *what* the script does AND *why* this couldn't be expressed in YAML. If the "why" is weak, push it back into YAML.
- **Interface:** each script defines `def apply(geo: dict) -> dict` taking a parsed GeoJSON FeatureCollection and returning the modified one. The build orchestrator handles I/O.
- **No side effects** other than the returned data — no network calls, no file writes, no `print` other than logging via `sys.stderr`.
- **Pure function over GeoJSON.** Don't import shapely/geopandas unless the operation truly needs polygon math; many fixes are just attribute mutations.
## Skeleton
```python
"""
NN_descriptive_name.py
======================
WHAT: One-sentence summary of what this script does to the data.
WHY: One-paragraph explanation of why this couldn't be expressed in
../config/<some_yaml>.yaml. If you find yourself writing
"because I didn't want to add a field to the schema", push the
fix into the YAML schema instead.
UPSTREAM TRACKING: link to NE issue / community discussion / blog post
explaining the underlying source of the problem, so future
maintainers can re-evaluate when upstream catches up.
"""
import sys
def apply(geo: dict) -> dict:
# ... mutate features ...
return geo
```
## Currently empty
There are no procedural scripts yet. The audit suggested the France-with-Overseas Windward Islands sub-polygon drop *might* warrant one, but `composite_maps.yaml` already has a `drop_parts` field that covers it. We'll add scripts here only if/when a genuine edge case proves YAML can't express it.