--- phase: 06-wire-icon-intunewin plan: "01" subsystem: package-export tags: [icon, intunewin, tdd, PKG-04] dependency_graph: requires: [05-02] provides: [icon-in-intunewin] affects: [imptune/api/packages.py] tech_stack: added: [] patterns: [content-addressed-icon-lookup, optional-staging-copy] key_files: created: [] modified: - imptune/api/packages.py - tests/test_packages.py decisions: - "Icon copy is silent-skip on missing DB record or missing disk file — export always succeeds regardless of icon presence" - "shutil.copy2 preserves file metadata; icon staged as icon.png (constant name) for Intune package structure" metrics: duration: "~5 minutes" completed: "2026-04-10" tasks_completed: 1 files_modified: 2 requirements-completed: [PKG-04] --- # Phase 06 Plan 01: Wire Icon into .intunewin Export Summary **One-liner:** Icon lookup via `Icon.get_or_none` + `shutil.copy2` into tmpdir staging before `build_intunewin()` call, satisfying PKG-04 with silent-skip for missing icons. ## What Was Built Added 4 lines of production code to `imptune/api/packages.py` that look up an `Icon` record for the current printer and, if found and on disk, copy it as `icon.png` into the `.intunewin` staging directory before `build_intunewin()` is called. Two new integration tests were added to `tests/test_packages.py` in a new `TestIntunewinIconInclusion` class: - `test_intunewin_includes_icon`: uploads a 256x256 PNG, monkeypatches `build_intunewin`, asserts `icon.png` appears in staged files - `test_intunewin_without_icon_succeeds`: no icon uploaded, asserts export returns 200 with no crash ## Decisions Made - **Silent-skip pattern:** Missing `Icon` DB record or missing file on disk both result in the icon step being skipped silently. Export always proceeds; the icon is optional metadata. - **Constant filename:** Icon is always staged as `icon.png` regardless of the `original_filename` stored in the DB. This gives the `.intunewin` package a predictable icon path for Intune policies that reference it. ## TDD Execution **RED:** `test_intunewin_includes_icon` failed (icon.png not in staged files `['detect.ps1', 'drivers', 'install.ps1', 'uninstall.ps1']`). `test_intunewin_without_icon_succeeds` passed as expected baseline. **GREEN:** After adding `shutil`/`Icon` imports and the 4-line copy block, both tests passed. Full suite: 96 passed, 0 failed. ## Deviations from Plan None — plan executed exactly as written. ## Verification Results - `python -m pytest tests/test_packages.py -x -q` — 15 passed - `python -m pytest tests/ -q` — 96 passed, 0 failed - Code review: `shutil.copy2` call is BEFORE `build_intunewin()` call ✓ - Code review: `Icon` imported from `imptune.db.models`, `cfg.ICONS_DIR` used (not hardcoded) ✓ ## Self-Check Files exist: - `imptune/api/packages.py` — modified - `tests/test_packages.py` — modified Commits: - `2723cc8` — test(06-01): add failing test for icon inclusion in .intunewin export - `6310be5` — feat(06-01): wire icon into .intunewin staging before build ## Self-Check: PASSED