Files
superset2/superset-frontend/plugins/plugin-chart-country-map/scripts/procedural
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
..

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

"""
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.