docs(06-01): complete wire-icon-intunewin plan

- SUMMARY.md: icon lookup + copy into .intunewin staging
- STATE.md: advanced to 06-01 complete, 100% progress, PKG-04 decision recorded
- ROADMAP.md: phase 06 marked Complete (1/1 plans)
- REQUIREMENTS.md: PKG-04 marked complete
This commit is contained in:
2026-04-10 16:22:22 +02:00
parent 6310be5e76
commit 906f3ca101
4 changed files with 86 additions and 12 deletions
+2 -2
View File
@@ -41,7 +41,7 @@ Requirements for initial release. Each maps to roadmap phases.
- [x] **PKG-01**: User can export a complete .intunewin package (script + drivers + detection + metadata) - [x] **PKG-01**: User can export a complete .intunewin package (script + drivers + detection + metadata)
- [x] **PKG-02**: .intunewin is generated natively in Python (no IntuneWinAppUtil.exe dependency) - [x] **PKG-02**: .intunewin is generated natively in Python (no IntuneWinAppUtil.exe dependency)
- [x] **PKG-03**: User can export a NinjaRMM ZIP package (install script + driver folder) - [x] **PKG-03**: User can export a NinjaRMM ZIP package (install script + driver folder)
- [ ] **PKG-04**: User can upload a custom PNG icon for Intune app display (256x256, max 750KB) - [x] **PKG-04**: User can upload a custom PNG icon for Intune app display (256x256, max 750KB)
- [x] **PKG-05**: User can preview and copy Intune install/uninstall command strings before export - [x] **PKG-05**: User can preview and copy Intune install/uninstall command strings before export
### Infrastructure ### Infrastructure
@@ -108,7 +108,7 @@ Which phases cover which requirements. Updated during roadmap creation.
| PKG-01 | Phase 5 | Complete | | PKG-01 | Phase 5 | Complete |
| PKG-02 | Phase 5 | Complete | | PKG-02 | Phase 5 | Complete |
| PKG-03 | Phase 5 | Complete | | PKG-03 | Phase 5 | Complete |
| PKG-04 | Phase 6 | Pending | | PKG-04 | Phase 6 | Complete |
| PKG-05 | Phase 5 | Complete | | PKG-05 | Phase 5 | Complete |
**Coverage:** **Coverage:**
+2 -2
View File
@@ -17,7 +17,7 @@ Decimal phases appear between their surrounding integers in numeric order.
- [x] **Phase 3: Printer Configuration** - Full printer config form, client/tenant labels, SQLite persistence (completed 2026-04-10) - [x] **Phase 3: Printer Configuration** - Full printer config form, client/tenant labels, SQLite persistence (completed 2026-04-10)
- [x] **Phase 4: Script Generation** - PowerShell install/uninstall/detection scripts with all correctness guards (completed 2026-04-10) - [x] **Phase 4: Script Generation** - PowerShell install/uninstall/detection scripts with all correctness guards (completed 2026-04-10)
- [x] **Phase 5: Package Export** - .intunewin and NinjaRMM ZIP export, icon upload, command preview (completed 2026-04-10) - [x] **Phase 5: Package Export** - .intunewin and NinjaRMM ZIP export, icon upload, command preview (completed 2026-04-10)
- [ ] **Phase 6: Wire Icon into .intunewin Export** - Embed uploaded icon in .intunewin package, closing PKG-04 gap - [x] **Phase 6: Wire Icon into .intunewin Export** - Embed uploaded icon in .intunewin package, closing PKG-04 gap (completed 2026-04-10)
- [ ] **Phase 7: Dashboard & Navigation Polish** - Fix /packages 404 nav link, wire dashboard recent queries - [ ] **Phase 7: Dashboard & Navigation Polish** - Fix /packages 404 nav link, wire dashboard recent queries
## Phase Details ## Phase Details
@@ -137,5 +137,5 @@ Phases execute in numeric order: 1 -> 2 -> 3 -> 4 -> 5
| 3. Printer Configuration | 2/2 | Complete | 2026-04-10 | | 3. Printer Configuration | 2/2 | Complete | 2026-04-10 |
| 4. Script Generation | 2/2 | Complete | 2026-04-10 | | 4. Script Generation | 2/2 | Complete | 2026-04-10 |
| 5. Package Export | 2/2 | Complete | 2026-04-10 | | 5. Package Export | 2/2 | Complete | 2026-04-10 |
| 6. Wire Icon into .intunewin Export | 0/1 | Pending | | | 6. Wire Icon into .intunewin Export | 1/1 | Complete | 2026-04-10 |
| 7. Dashboard & Navigation Polish | 0/1 | Pending | | | 7. Dashboard & Navigation Polish | 0/1 | Pending | |
+10 -8
View File
@@ -3,14 +3,14 @@ gsd_state_version: 1.0
milestone: v1.0 milestone: v1.0
milestone_name: milestone milestone_name: milestone
status: executing status: executing
stopped_at: Completed 05-02-PLAN.md stopped_at: Completed 06-01-PLAN.md
last_updated: "2026-04-10T13:10:59.353Z" last_updated: "2026-04-10T14:22:10.956Z"
last_activity: "2026-04-10 — Plan 04-02 complete: uninstall/detect templates, render_uninstall/render_detect, 3 script API endpoints, 75 tests green" last_activity: "2026-04-10 — Plan 04-02 complete: uninstall/detect templates, render_uninstall/render_detect, 3 script API endpoints, 75 tests green"
progress: progress:
total_phases: 5 total_phases: 7
completed_phases: 5 completed_phases: 6
total_plans: 11 total_plans: 12
completed_plans: 11 completed_plans: 12
--- ---
--- ---
@@ -74,6 +74,7 @@ Progress: [█████████░] 89%
| Phase 04-script-generation P02 | 2 | 2 tasks | 6 files | | Phase 04-script-generation P02 | 2 | 2 tasks | 6 files |
| Phase 05-package-export P01 | 2 | 1 tasks | 3 files | | Phase 05-package-export P01 | 2 | 1 tasks | 3 files |
| Phase 05-package-export P02 | 15 | 2 tasks | 9 files | | Phase 05-package-export P02 | 15 | 2 tasks | 9 files |
| Phase 06-wire-icon-intunewin P01 | 5 | 1 tasks | 2 files |
## Accumulated Context ## Accumulated Context
@@ -113,6 +114,7 @@ Recent decisions affecting current work:
- [Phase 05-package-export]: Icons stored SHA256-addressed under DATA_DIR/icons — consistent with DRIVERS_DIR content-addressing pattern - [Phase 05-package-export]: Icons stored SHA256-addressed under DATA_DIR/icons — consistent with DRIVERS_DIR content-addressing pattern
- [Phase 05-package-export]: Icon replace via delete-then-create — unique FK makes upsert awkward, delete first is simpler - [Phase 05-package-export]: Icon replace via delete-then-create — unique FK makes upsert awkward, delete first is simpler
- [Phase 05-package-export]: Export/command sections conditionally shown when has_driver is true — avoids confusing broken links before driver assigned - [Phase 05-package-export]: Export/command sections conditionally shown when has_driver is true — avoids confusing broken links before driver assigned
- [Phase 06-wire-icon-intunewin]: Icon copy is silent-skip on missing DB record or missing disk file — export always succeeds regardless of icon presence
### Pending Todos ### Pending Todos
@@ -125,6 +127,6 @@ None yet.
## Session Continuity ## Session Continuity
Last session: 2026-04-10T13:07:54.905Z Last session: 2026-04-10T14:22:10.947Z
Stopped at: Completed 05-02-PLAN.md Stopped at: Completed 06-01-PLAN.md
Resume file: None Resume file: None
@@ -0,0 +1,72 @@
---
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
---
# 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