This commit is contained in:
EthanShoeDev
2025-11-30 17:52:15 -05:00
commit 01a35296a9
12 changed files with 1309 additions and 0 deletions

View File

@@ -0,0 +1,449 @@
# Winget Configure vs DSC CLI: In-Depth Comparison
Both `winget configure` and the `dsc` CLI can apply declarative configurations that include winget packages. This doc explains when to use each, their differences, and practical examples.
---
## Quick Comparison
| Aspect | `winget configure` | `dsc` CLI |
|--------|-------------------|-----------|
| **Focus** | Winget-centric configurations | General-purpose DSC (any resource) |
| **Output** | Human-friendly, interactive | JSON output, scriptable |
| **State checking** | Limited | Full (`get`, `test`, `set`) |
| **Diffing** | No built-in | Yes (`dsc config test`) |
| **Complexity** | Simpler | More powerful |
| **Install** | Built into winget | Separate install (`winget install Microsoft.DSC`) |
---
## Entry Points
### Winget Configure
```powershell
# Apply a configuration
winget configure ./config.dsc.yaml
# Apply with auto-accept (for scripts)
winget configure ./config.dsc.yaml --accept-configuration-agreements
# Show what would happen (dry run) — limited support
winget configure show ./config.dsc.yaml
```
### DSC CLI
```powershell
# Check current state (what IS installed)
dsc config get --file ./config.dsc.yaml
# Test if current state matches desired (diffing)
dsc config test --file ./config.dsc.yaml
# Apply the configuration
dsc config set --file ./config.dsc.yaml
# Export current state to a config
dsc config export --resource Microsoft.WinGet.DSC/WinGetPackage
```
---
## Configuration File Format
Both use the same YAML format (DSCv3 schema):
```yaml
# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2
properties:
configurationVersion: 0.2.0
resources:
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: install-vscode
directives:
description: Install VS Code
allowPrerelease: true
settings:
id: Microsoft.VisualStudioCode
source: winget
```
---
## Example Project Structures
### Option A: Winget Configure (Simple Setup)
Best for: Personal machine setup, quick provisioning
```
my-windows-config/
├── config.dsc.yaml # Main configuration
├── README.md
└── install.ps1 # Optional wrapper script
```
**config.dsc.yaml**
```yaml
# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2
properties:
configurationVersion: 0.2.0
resources:
# Developer Tools
- resource: Microsoft.WinGet.DSC/WinGetPackage
directives:
description: Visual Studio Code
settings:
id: Microsoft.VisualStudioCode
source: winget
- resource: Microsoft.WinGet.DSC/WinGetPackage
directives:
description: Git
settings:
id: Git.Git
source: winget
- resource: Microsoft.WinGet.DSC/WinGetPackage
directives:
description: Node.js LTS
settings:
id: OpenJS.NodeJS.LTS
source: winget
version: "20.10.0" # Pinned version
```
**install.ps1**
```powershell
#!/usr/bin/env pwsh
Write-Host "Applying Windows configuration..." -ForegroundColor Cyan
winget configure ./config.dsc.yaml --accept-configuration-agreements
Write-Host "Done!" -ForegroundColor Green
```
**Usage:**
```powershell
.\install.ps1
# or directly:
winget configure ./config.dsc.yaml
```
---
### Option B: DSC CLI (Advanced/Enterprise)
Best for: CI/CD, drift detection, mixed resource types, automation
```
my-windows-config/
├── configs/
│ ├── packages.dsc.yaml # Winget packages
│ ├── settings.dsc.yaml # Windows settings/registry
│ └── full.dsc.yaml # Combined config
├── scripts/
│ ├── apply.ps1
│ ├── test.ps1 # Drift detection
│ └── export.ps1 # Generate config from current state
├── lockfiles/
│ └── packages.lock.yaml # Version-locked config
└── README.md
```
**configs/packages.dsc.yaml**
```yaml
# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2
properties:
configurationVersion: 0.2.0
resources:
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: vscode
directives:
description: Visual Studio Code
settings:
id: Microsoft.VisualStudioCode
source: winget
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: git
directives:
description: Git
settings:
id: Git.Git
source: winget
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: nodejs
directives:
description: Node.js LTS
settings:
id: OpenJS.NodeJS.LTS
source: winget
```
**scripts/apply.ps1**
```powershell
#!/usr/bin/env pwsh
param(
[string]$Config = "./configs/packages.dsc.yaml"
)
Write-Host "Testing current state..." -ForegroundColor Cyan
$testResult = dsc config test --file $Config | ConvertFrom-Json
if ($testResult.results | Where-Object { $_.result.inDesiredState -eq $false }) {
Write-Host "Drift detected. Applying configuration..." -ForegroundColor Yellow
dsc config set --file $Config
} else {
Write-Host "System is already in desired state." -ForegroundColor Green
}
```
**scripts/test.ps1** (Drift Detection)
```powershell
#!/usr/bin/env pwsh
param(
[string]$Config = "./configs/packages.dsc.yaml"
)
Write-Host "Checking for configuration drift..." -ForegroundColor Cyan
$result = dsc config test --file $Config | ConvertFrom-Json
$drifted = $result.results | Where-Object { $_.result.inDesiredState -eq $false }
if ($drifted) {
Write-Host "`nDrift detected in:" -ForegroundColor Red
$drifted | ForEach-Object {
Write-Host " - $($_.resource.type): $($_.resource.id)" -ForegroundColor Yellow
}
exit 1
} else {
Write-Host "No drift detected. System matches desired state." -ForegroundColor Green
exit 0
}
```
**scripts/export.ps1** (Generate Config from Current State)
```powershell
#!/usr/bin/env pwsh
# Export currently installed winget packages to a DSC config
$packages = winget list --source winget | Select-Object -Skip 2 | ForEach-Object {
$parts = $_ -split '\s{2,}'
if ($parts.Length -ge 2) {
@{
name = $parts[0]
id = $parts[1]
version = if ($parts.Length -ge 3) { $parts[2] } else { $null }
}
}
} | Where-Object { $_ -ne $null }
# Output as DSC YAML format
Write-Output "# Auto-generated from current system state"
Write-Output "# yaml-language-server: `$schema=https://aka.ms/configuration-dsc-schema/0.2"
Write-Output "properties:"
Write-Output " configurationVersion: 0.2.0"
Write-Output " resources:"
foreach ($pkg in $packages) {
Write-Output " - resource: Microsoft.WinGet.DSC/WinGetPackage"
Write-Output " id: $($pkg.id.ToLower() -replace '[^a-z0-9]', '-')"
Write-Output " settings:"
Write-Output " id: $($pkg.id)"
Write-Output " source: winget"
if ($pkg.version) {
Write-Output " version: `"$($pkg.version)`""
}
Write-Output ""
}
```
---
## Version Locking
### With Winget Configure
Pin versions directly in the YAML:
```yaml
resources:
- resource: Microsoft.WinGet.DSC/WinGetPackage
settings:
id: OpenJS.NodeJS.LTS
source: winget
version: "20.10.0" # Exact version lock
```
### With DSC CLI
Same approach, but you can also generate a locked config:
```powershell
# Get current installed versions
dsc config get --file ./config.dsc.yaml > current-state.json
# Or use winget export with versions
winget export -o winget-lock.json --include-versions
```
**Lockfile Pattern:**
Create two files:
- `packages.dsc.yaml` — Desired packages (may float versions)
- `packages.lock.dsc.yaml` — Locked versions for reproducibility
```yaml
# packages.lock.dsc.yaml - Generated/maintained with exact versions
properties:
configurationVersion: 0.2.0
resources:
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: nodejs
settings:
id: OpenJS.NodeJS.LTS
source: winget
version: "20.10.0"
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: git
settings:
id: Git.Git
source: winget
version: "2.43.0"
```
---
## Diffing / Drift Detection
### Winget Configure
Limited support — `winget configure show` gives some info but no true diff:
```powershell
winget configure show ./config.dsc.yaml
```
### DSC CLI (Full Diffing)
```powershell
# Test returns JSON with inDesiredState boolean for each resource
dsc config test --file ./config.dsc.yaml
```
**Example output:**
```json
{
"results": [
{
"resource": {
"type": "Microsoft.WinGet.DSC/WinGetPackage",
"id": "vscode"
},
"result": {
"inDesiredState": true
}
},
{
"resource": {
"type": "Microsoft.WinGet.DSC/WinGetPackage",
"id": "nodejs"
},
"result": {
"inDesiredState": false,
"diff": {
"version": {
"desired": "20.10.0",
"actual": "18.19.0"
}
}
}
}
]
}
```
**CI/CD Integration:**
```powershell
# In a CI pipeline - fail if drift detected
$result = dsc config test --file ./config.dsc.yaml | ConvertFrom-Json
$hasDrift = $result.results | Where-Object { -not $_.result.inDesiredState }
if ($hasDrift) {
Write-Error "Configuration drift detected!"
exit 1
}
```
---
## When to Use Which
### Use `winget configure` when:
- ✅ You want a simple, interactive setup experience
- ✅ Your config is mostly/entirely winget packages
- ✅ You're doing one-time machine provisioning
- ✅ You don't need drift detection
- ✅ You want minimal dependencies (built into winget)
### Use `dsc` CLI when:
- ✅ You need drift detection / compliance checking
- ✅ You're building CI/CD pipelines
- ✅ You want JSON output for automation
- ✅ You're mixing winget with other DSC resources (registry, files, etc.)
- ✅ You need the full `get`/`test`/`set` lifecycle
- ✅ Enterprise configuration management
---
## Mixed Resource Example (DSC Only)
DSC can combine winget packages with other configuration types:
```yaml
# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2
properties:
configurationVersion: 0.2.0
resources:
# Install VS Code
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: vscode
settings:
id: Microsoft.VisualStudioCode
source: winget
# Configure VS Code settings (after install)
- resource: Microsoft.Windows.Developer/DeveloperMode
id: enable-dev-mode
settings:
Ensure: Present
# Set environment variable
- resource: Microsoft.Windows.Developer/EnvironmentVariable
id: set-editor
settings:
Name: EDITOR
Value: code
Target: User
```
This is where DSC really shines — you can configure the entire system state, not just packages.
---
## Summary
| Task | Winget Configure | DSC CLI |
|------|-----------------|---------|
| Apply config | `winget configure ./config.yaml` | `dsc config set --file ./config.yaml` |
| Check current state | ❌ | `dsc config get --file ./config.yaml` |
| Diff/test | Limited | `dsc config test --file ./config.yaml` |
| Output format | Human text | JSON (scriptable) |
| Version locking | Manual in YAML | Manual in YAML + export tools |
| Multiple resource types | Winget only | Any DSC resource |

159
docs/winget-notes.md Normal file
View File

@@ -0,0 +1,159 @@
# Winget Quick Reference
Windows Package Manager (`winget`) is Microsoft's CLI tool for installing, updating, and managing software.
---
## Search for Packages
```powershell
# Search by name
winget search vscode
# Web-based search UI
# https://solrevdev.com/winget-search/
```
---
## Install
```powershell
# Basic install
winget install <package-name>
# Install with exact ID match (-e = --exact)
winget install -e --id Microsoft.VisualStudioCode
# Install specific version
winget install -e --id Oven-sh.Bun --version 1.1.0
# Accept all agreements automatically (useful for scripts)
winget install -e --id Oven-sh.Bun --accept-package-agreements --accept-source-agreements
```
### Installation Scope
```powershell
# Install for current user only (no admin required)
winget install -e --id Oven-sh.Bun --scope user
# Install system-wide (requires admin)
winget install -e --id Oven-sh.Bun --scope machine
```
---
## Uninstall
```powershell
# Basic uninstall
winget uninstall <package-name>
# Uninstall with exact ID
winget uninstall -e --id Oven-sh.Bun
# Uninstall and remove app data (if supported)
winget uninstall -e --id Oven-sh.Bun --purge
```
---
## Update / Upgrade
```powershell
# List packages with available updates
winget upgrade
# Update a specific package
winget upgrade -e --id Oven-sh.Bun
# Update ALL packages
winget upgrade --all
# Update all, accepting agreements (for scripts)
winget upgrade --all --accept-package-agreements --accept-source-agreements
```
---
## View Package Info
```powershell
# Show package details (version, publisher, license, install URL)
winget show Oven-sh.Bun
# Show all available versions
winget show Oven-sh.Bun --versions
```
---
## List Installed Packages
```powershell
# List all installed packages (from all sources)
winget list
# Filter by name
winget list bun
```
---
## Export / Import (Lockfile-like System)
Export your installed packages to a JSON file for reproducible setups:
```powershell
# Export all packages
winget export -o winget-pkgs.json
# Export with pinned versions
winget export -o winget-pkgs-lock.json --include-versions
```
Import on a new machine:
```powershell
# Install all packages from export file
winget import -i winget-pkgs-lock.json --accept-package-agreements --accept-source-agreements
```
---
## Common Flags Reference
| Flag | Long Form | Description |
|------|-----------|-------------|
| `-e` | `--exact` | Match package ID exactly |
| `-h` | `--silent` | Silent install (no UI) |
| `-i` | `--interactive` | Interactive install (show installer UI) |
| `-o` | `--output` | Output file path |
| `-v` | `--version` | Specify version |
| | `--scope` | `user` or `machine` |
| | `--accept-package-agreements` | Auto-accept package license |
| | `--accept-source-agreements` | Auto-accept source agreements |
---
## Settings
Open winget settings file:
```powershell
winget settings
```
Example settings (JSON):
```json
{
"installBehavior": {
"preferences": {
"scope": "user"
}
}
}
```