Skip to content

feat(ci): derive matrix — kind: thumb (wire #361 thumb-bake into derive.yml) #402

Description

@gerchowl

Motivation

#361 landed the per-material thumb-bake pipeline at `bake/preview/` (renderer, orchestrator, vendored shader_ball.glb with native UVs, blank fingerprint gate). #391 landed the canonical `MatVisClient(repo=…, tag=…)` API. Everything is in place to actually run the bake — but there's no GHA workflow that triggers it. Today an operator wanting thumbs has to invoke `python bake/preview/run.py` locally with HF env vars manually set.

The bake fits cleanly into the existing derive matrix architecture: input is `@`, output is per-material per-source artifacts published back to HF. `#365` (concurrency-group fix) ensures that adding a new `kind` doesn't displace pending resize/ktx2 dispatches.

Decision / proposed approach

  1. Add `kind: thumb` to `.github/workflows/derive.yml`'s `workflow_dispatch.inputs.kind` enum (alongside `resize`, `ktx2`).
  2. Plan step extension: when `kind=thumb`, `target-tier` resolves to literal `"thumb"` (no source-tier interpolation needed; the bake reads from the highest tier available per material via the existing `run.py` fallback).
  3. New Dagger function `thumb` in `.dagger/src/mat_vis_ci/main.py` (mirrors `derive` / `derive_ktx2` shape). Inside the baker container:
    • Install Playwright + Chromium
    • Set `MAT_VIS_DATASET=@` (uses the new env var from feat(client): repo+tag override via constructor + MAT_VIS_DATASET env (#384) #391)
    • Run `python bake/preview/run.py --out /tmp/thumbs --source --skip-check`
    • Upload each `/<material_id>/thumb.png` to HF as `/<material_id>/thumb/thumb.png` (new "thumb" tier)
    • Update the source's manifest entry: `tiers: {…, thumb: {complete: true}}`
    • Wrap upload in atomic batches (mirrors the per-file derive's batch convention)
  4. Concurrency key naturally separates via the existing `derive-{repo}-{kind}-{source-tier}-{target-tier}-budget` template — `thumb` lives in its own group.
  5. Forward-compat: feat(client): VisAsset.thumb discovery surface (#362) #363's `VisAsset.thumb` already expects `tier="thumb"` as a named alias. After this lands, existing client code starts returning real thumbs without changes.

What already exists

Scope

P0

  • `derive.yml`: `kind` enum gains `thumb`; plan step handles `kind=thumb` → `target-tier=thumb`; matrix step dispatches to dagger `thumb` cell
  • `.dagger/src/mat_vis_ci/main.py`: `thumb` function — runs `bake/preview/run.py`, uploads PNGs, updates manifest
  • Manifest update glue (probably extends the existing `hf_push.py` or adds a `thumb_publish.py`): per-source `tiers.thumb.complete=true` flag
  • HF path convention: `/<material_id>/thumb/thumb.png` (matches existing `/<material_id>//.png` shape)
  • Live test: dispatch the workflow against `gerchowl/mat-vis-tst@v2026.04.99-tst-full-369` for one source (ambientcg), verify PNGs land + manifest updates
  • Acceptance: `MatVisClient().asset("ambientcg", "Metal007").thumb` returns the PNG bytes (closes the feat(client): VisAsset.thumb discovery surface (#362) #363 forward-coupling)

P1

  • CI `check_thumbs.py` fingerprint gate runs as a workflow step before HF upload (catch silent regressions)
  • Per-source thumb-tier completeness reported in workflow summary
  • `hf upload` retries on transient 5xx (already in baker for resize/ktx2; reuse)

Pitfalls

Acceptance criteria

  • `gh workflow run derive.yml -f kind=thumb -f sources=ambientcg -f repo-id=gerchowl/mat-vis-tst -f release-tag=v2026.04.99-tst-full-369` runs to green
  • Post-run: `hf api datasets/gerchowl/mat-vis-tst/resolve/v2026.04.99-tst-full-369/release-manifest.json` shows `sources.ambientcg.tiers.thumb.complete=true`
  • Post-run: `hf api datasets/gerchowl/mat-vis-tst/resolve/v2026.04.99-tst-full-369/ambientcg/Metal007/thumb/thumb.png` returns valid PNG bytes
  • `MatVisClient(repo="gerchowl/mat-vis-tst", tag="v2026.04.99-tst-full-369").asset("ambientcg", "Metal007").thumb` returns the same bytes (round-trip verify)
  • Concurrency: a parallel `kind=resize` dispatch on the same repo doesn't cancel the thumb dispatch (verified via the bugfix(ci): derive.yml concurrency cancels sibling dispatches (closes #364) #365-fixed concurrency key)

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:ciCI/CD, GitHub Actions, workflowsfeatureNew feature or requestpriority:highShould be done in the current milestone

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions