mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 21:26:15 -08:00
feat(release): manifest-driven screenshot capture with fail-closed mock-data guards (#1261)
Third slice of the release-notes pipeline (#1256 format+generator, #1257 CI gate): release screenshots become reproducible and provably mock-only. The v0.20 capture script was single-use (hard-coded slugs, paths, hero) and fail-open: a lost IPTVNATOR_E2E_DATA_DIR silently fell back to the user's real ~/.iptvnator database, `...process.env` leaked ambient TMDB keys and proxies, nothing gated network access, and no frame content was ever validated. Each hole leaks real playlists, credentials, or copyrighted artwork into published screenshots without a single signal. New pipeline: - tools/release/screenshots.manifest.json — declarative shots (slug, title, named setup steps, themes). Adding a feature shot = one manifest entry. - capture-release-screenshots.ts — orchestrator; output goes to apps/website/public/blog/<release>/screenshots/<slug>-<theme>.png, release slug derived from package.json (or --release), --only/--theme filters. - capture-app-driver.ts / capture-navigation.ts — launch, seeding, theme, and the named-action vocabulary; actions are order-independent (every portal action starts from the dashboard). - screenshot-guards.mjs — the fail-closed policy, pure and unit-tested: G1 the real database is snapshotted (sha256+mtime) before launch and must be byte-identical after; the isolated DB must actually exist G2 the app receives an allowlisted environment, never ...process.env G3 deny-by-default network gate; known app-level calls (GitHub update check) are answered by local stubs; any other blocked request fails the run — a silently-blocked TMDB call would leave a frame that looks broken rather than unsafe G4 every frame is scanned before capture: external img/background URLs, credential-shaped text, MAC addresses, non-localhost m3u8 references G5 TMDB enrichment asserted disabled via the renderer's IndexedDB Any violation deletes every frame captured in the run and exits non-zero. The guards paid for themselves on the first live run: G3 caught the mock server redirecting stream endpoints to a public demo HLS (test-streams.mux.dev) — meaning earlier hand-run captures could embed third-party video frames. The M3U shot now deliberately captures the groups layout without starting playback. `.changes` validation now cross-checks `screenshot:` slugs against the manifest, so a note cannot reference an image the capture run never produces. Verified end-to-end: 10/10 shots (5 slugs × dark/light) captured against dist build + xtream-mock-server, frames visually inspected (fictional titles/artwork only), guard-violation paths exercised live. 67 unit tests in release-tools, lint green, script files within the repo size limit. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e5132cbb5
commit
b4ec68c1fa
14 files changed
+2344
-15
No files matched your search
+24
-1
@@ -30,7 +30,7 @@ of the current season, watch progress, and click-to-play inline.
|
||||
| `type` | yes | `breaking`, `feature`, `fix`, `perf`, or `internal` |
|
||||
| `area` | yes | lowercase slug, same as the conventional-commit scope |
|
||||
| `issues` | no | issue numbers this closes — `[1187]` or `1187` |
|
||||
| `screenshot` | no | slug from the release screenshot manifest |
|
||||
| `screenshot` | no | slug from `tools/release/screenshots.manifest.json` |
|
||||
|
||||
There is **no version field**. The release version is chosen deliberately at
|
||||
release time, not derived from these files.
|
||||
@@ -84,3 +84,26 @@ The website publishes **one post per minor version** (`v0-18` … `v0-22`), and
|
||||
release screenshots live under the matching `blog/v0-24/` directory. A patch
|
||||
release therefore edits the existing post rather than generating a new one, so
|
||||
`--format blog` refuses to overwrite unless you pass `--force`.
|
||||
|
||||
## Screenshots
|
||||
|
||||
`pnpm run release:screenshots` captures every manifest shot in dark and light
|
||||
against the built app plus the Xtream mock server — never a real account.
|
||||
The run is fail-closed: it proves the real `~/.iptvnator/databases` directory
|
||||
(including the SQLite WAL sidecars, checked after Electron exits) was not
|
||||
touched, launches the app with an allowlisted environment, records and blocks
|
||||
all non-localhost traffic, scans every frame for external resources and
|
||||
credential-shaped text, and asserts TMDB enrichment stays disabled. Frames are
|
||||
staged outside the repository and published only once every shot and every
|
||||
guard has passed.
|
||||
|
||||
Adding a shot for a new feature = one entry in
|
||||
`tools/release/screenshots.manifest.json` (plus, if navigation is new, one
|
||||
named action in `tools/release/capture-navigation.ts`).
|
||||
|
||||
```bash
|
||||
pnpm nx run electron-backend:build-e2e # once, before capturing
|
||||
pnpm run release:screenshots # all shots, both themes
|
||||
pnpm run release:screenshots -- --only dashboard --theme dark
|
||||
pnpm run release:screenshots -- --release v0-24
|
||||
```
|
||||
Reference in new issue
Block a user