21b6a30f08
Move a template fully between environments (local → live): container, projects, all scenes + editable fields, shared colours/layers, its categories & tags, and the asset files. - export_template.py <slug> → a self-contained bundle (template.json + assets/). One SQL query captures the whole tree as JSON; assets are resolved from template-media references and copied in. Source DB via PSQL env (default = local docker). - import_template.py <bundle> → idempotent SQL (pipe to target psql). Replaces by slug via one cascading delete (all content.* FKs are ON DELETE CASCADE), recreates rows verbatim (UUIDs preserved → FKs intact), merges categories/tags BY SLUG so they line up across DBs. --assets-to copies media; docker cp / mc cp hints for remote. - TEMPLATE_BUNDLES.md documents it. Round-trip tested on fr-instagram-promo: DB → bundle → DB restores identical 3 projects / 15 scenes / 138 fields and field values. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.5 KiB
2.5 KiB
Template import / export (portable bundles)
Move a template — everything: container, projects, all scenes + editable fields, shared colours/layers, the categories & tags it belongs to, and the asset files — between environments (e.g. local → live).
A bundle is a self-contained directory:
dist/template-bundles/<slug>/
├── template.json # every DB row related to the template
└── assets/ # the media it references (thumbnails, scene stills, preview…)
Export (from the source DB)
PYTHONIOENCODING=utf-8 python scripts/export_template.py <slug>
# → dist/template-bundles/<slug>/
# non-default source DB:
PSQL="psql 'postgresql://user:pass@host:5432/flatrender'" \
python scripts/export_template.py <slug>
Import (into ANY target DB)
The importer prints idempotent SQL — pipe it to the target's psql. It replaces
any template with the same slug (one cascading delete), recreates rows verbatim
(original UUIDs, so foreign keys stay intact), and merges categories & tags by
slug so they line up with whatever the target already calls them.
# local:
python scripts/import_template.py dist/template-bundles/<slug> \
| docker exec -i fr2-postgres psql -U postgres -d flatrender
# live:
python scripts/import_template.py dist/template-bundles/<slug> \
| psql "postgresql://user:pass@live-host:5432/flatrender"
Assets
The SQL only moves DB rows. Place the bundle's assets/ into the target's
template-media:
# copy locally while importing:
python scripts/import_template.py <bundle> --assets-to ./public/template-media | ...
# live docker frontend:
for f in <bundle>/assets/*; do docker cp "$f" <frontend-container>:/app/public/template-media/; done
# live MinIO/object store:
mc cp --recursive <bundle>/assets/ myminio/<bucket>/template-media/
Guarantees & notes
- Idempotent — re-importing the same bundle re-creates the template cleanly.
- Cross-DB safe — UUIDs are preserved; categories/tags merge by their unique slug.
- Round-trip tested — DB → bundle → DB restores identical counts and values.
- Not exported (intentionally): user data — comments, favourites, view/use counts.
- External (http) media referenced by a template is flagged on export but not bundled — host it on the target yourself.
- Scope today covers FlexStory/Remotion + standard fields. AEP-specific child tables (characters, colour presets) are an easy extension — add them to the export query and the importer's insert list (both are data-driven).