docs: propose windows.file (declarative files + dotfile symlinks) - #49
Conversation
Expand the Phase 4 content-only windows.file() sketch into a full proposal covering text content, source symlinks, and copy, mirroring Home Manager's home.file intent for cross-platform dotfile reuse. Key design driver: Windows symlinks require privilege (SeCreateSymbolicLink) by default, lifted by Developer Mode (no admin) since Win10 1703. The helper must be privilege-aware and fail with a clear, actionable error, the same lesson learned from windows.env scope:machine needing elevation. No native DSC file resource exists in 3.2.2, so file is emitted via the built-in WindowsPowerShellScript resource with idempotent test/set scripts, reusing the mechanism validated for windows.path on hardware. Status: draft. Hardware validation deferred (design-first, like env/path).
- Drop linkType/junction knob; add elevate:true escape hatch for symlinks when Developer Mode is off (consistent with env scope:machine elevation). - One force flag + backup (rename to .bak), matching Home Manager; a populated directory is never rm'd even with force:true. - Omit executable on Windows (no POSIX exec bit; would be a no-op lie). - Do not mix Developer Mode into file: off -> user passes elevate:true. - No template helper; drift tie-in accepted. Open questions section becomes Decisions; one remaining UX note on framing elevate as secondary vs Developer Mode as recommended.
|
Folded in review decisions (commit 2d03c92):
One remaining note for the thread: |
- Removed redundant USERPROFILE local bin PATH addition from snapshots. - Updated CARGO_HOME PATH addition to use simplified dependencies. - Introduced new PowerShell functions for managing file content and symlinks. - Enhanced tests for Windows file operations, ensuring idempotency and safety. - Improved YAML serializer to handle multiline strings as literal block scalars. - Adjusted test descriptions for clarity regarding resource dependencies.
There was a problem hiding this comment.
Pull request overview
This PR introduces a concrete windows.file.* helper (text/symlink/copy/remove) for the Windows backend and updates the Windows DSC YAML emitter to better support the new script-heavy resources (multiline literals, dependency naming, env-var resolution). It also adds a dedicated proposal document describing the design and Windows-specific symlink constraints.
Changes:
- Add
windows.file.text/symlink/copy/removehelpers that emit idempotentMicrosoft.DSC.Transitional/WindowsPowerShellScriptresources (including optional elevation). - Update Windows YAML serialization to emit multiline strings as literal block scalars and adjust
dependsOnemission to use resource names. - Add host-level rewrite logic to resolve Winix-managed env-var references in env values and PATH scripts; expand tests/snapshots and add proposal docs/examples.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/windows-yaml.test.ts | Adds coverage for multiline literal-block YAML entries. |
| tests/windows-backend.test.ts | Updates dependsOn expectations + adds tests for windows.file.* and managed-env rewrites. |
| tests/snapshots/windows-example.test.ts.snap | Updates emitted YAML snapshot for new multiline style and dependsOn naming. |
| tests/snapshots/windows-backend.test.ts.snap | Adds snapshot for file helpers and updates existing snapshots for new YAML formatting/dependsOn naming. |
| src/types/windows.ts | Extends WinDscResource with elevated and internal winix metadata used for host-level rewrites. |
| src/index.ts | Exposes WinFile* types from the public entrypoint. |
| src/helpers/windows.ts | Implements windows.file.*, file script generation, and non-enumerable typed-helper metadata. |
| src/helpers/index.ts | Re-exports WinFile* types from helpers. |
| src/backends/windows/yaml.ts | Emits multiline strings as ` |
| src/backends/windows/index.ts | Resolves managed env references, switches dependsOn emission to resource names, and supports per-resource elevation metadata. |
| spec/proposals/windows-file.md | New design proposal doc for windows.file.*, including symlink privilege/Developer Mode behavior. |
| spec/proposals/windows-backend.md | Updates Windows backend proposal to reference windows-file.md and new windows.file.* API shape. |
| spec/proposals/README.md | Adds the windows-file.md proposal to the proposals index. |
| examples/windows/winix.config.ts | Updates Windows example config to demonstrate windows.file.text usage and document windows.file.*. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
What
Implements and documents
windows.file.*— declarative file management for the Windows backend, covering literal content, symlinks, copies, and removals for Windows dotfile workflows.This PR started from the
windows.fileproposal, then folded in the implementation and validation work needed to make the helper usable end-to-end:windows.file.text(target, content, opts?)windows.file.symlink(target, source, opts?)windows.file.copy(target, source, opts?)windows.file.remove(target, opts?)It also includes supporting Windows backend fixes discovered during validation: readable multiline YAML,
winget configure-compatibledependsOnnames, and nested Winix-managed env var resolution for PATH entries.Why
Two drivers:
windows.envend-to-end, settingEDITOR=nvimwas not enough for lazygit because it reads its ownconfig.yml. Writing that file is exactlywindows.file.text's job.home.file) on Windows hosts, from onewinix.config.ts.Implementation notes
No native general-purpose DSC file/symlink resource was available in the tested DSC/winget stack, so the helpers emit idempotent
Microsoft.DSC.Transitional/WindowsPowerShellScriptresources. The generated scripts:mklink;force,backup,recursive,elevate, anddependsOnwhere applicable.Windows symlink behavior
Windows symlinks require either elevation or Developer Mode. Developer Mode is the recommended dotfile path because it is a one-time system toggle and avoids UAC prompts on every apply.
elevate: trueremains the explicit escape hatch for one-off/admin applies.Validation
winget configureprobes for text, symlink, copy, remove, YAML block scalars, and dependency naming.windows.file.text; symlink/copy/remove examples are present but commented because they depend on local user paths.