|
| 1 | +# Developer Guide |
| 2 | + |
| 3 | +This guide covers setting up a development environment for contributing to LsiGitCheckout. |
| 4 | + |
| 5 | +## Prerequisites |
| 6 | + |
| 7 | +### PowerShell 7.6 LTS |
| 8 | + |
| 9 | +LsiGitCheckout requires PowerShell 7.6 LTS or later. PowerShell 7.x installs side-by-side with Windows PowerShell 5.1 — it will not replace or interfere with the built-in version. |
| 10 | + |
| 11 | +**Windows:** |
| 12 | + |
| 13 | +```powershell |
| 14 | +winget install Microsoft.PowerShell |
| 15 | +``` |
| 16 | + |
| 17 | +Or download the MSI installer from [PowerShell GitHub Releases](https://github.com/PowerShell/PowerShell/releases). |
| 18 | + |
| 19 | +**macOS:** |
| 20 | + |
| 21 | +```bash |
| 22 | +brew install --cask powershell |
| 23 | +``` |
| 24 | + |
| 25 | +**Linux (Ubuntu/Debian):** |
| 26 | + |
| 27 | +```bash |
| 28 | +# Register Microsoft package repository |
| 29 | +wget -q https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb |
| 30 | +sudo dpkg -i packages-microsoft-prod.deb |
| 31 | +rm packages-microsoft-prod.deb |
| 32 | + |
| 33 | +# Install PowerShell |
| 34 | +sudo apt-get update |
| 35 | +sudo apt-get install -y powershell |
| 36 | +``` |
| 37 | + |
| 38 | +For other Linux distributions, see the [official installation docs](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-linux). |
| 39 | + |
| 40 | +**Verify installation:** |
| 41 | + |
| 42 | +```bash |
| 43 | +pwsh --version |
| 44 | +# Expected: PowerShell 7.6.x |
| 45 | +``` |
| 46 | + |
| 47 | +### Git |
| 48 | + |
| 49 | +Git must be installed and available on PATH. |
| 50 | + |
| 51 | +```bash |
| 52 | +git --version |
| 53 | +``` |
| 54 | + |
| 55 | +### Pester 5.x (Test Framework) |
| 56 | + |
| 57 | +Install the Pester module inside PowerShell 7: |
| 58 | + |
| 59 | +```powershell |
| 60 | +pwsh -Command "Install-Module Pester -Force -MinimumVersion 5.0 -Scope CurrentUser" |
| 61 | +``` |
| 62 | + |
| 63 | +Verify: |
| 64 | + |
| 65 | +```powershell |
| 66 | +pwsh -Command "Get-Module Pester -ListAvailable" |
| 67 | +``` |
| 68 | + |
| 69 | +## Editor Setup |
| 70 | + |
| 71 | +### VS Code with PowerShell Extension |
| 72 | + |
| 73 | +1. Install [Visual Studio Code](https://code.visualstudio.com/). |
| 74 | +1. Open the workspace file — this will prompt you to install the recommended PowerShell extension: `code LsiGitCheckout.code-workspace` |
| 75 | +1. If not prompted automatically, install the **PowerShell** extension (`ms-vscode.powershell`) from the Extensions sidebar. |
| 76 | + |
| 77 | +> **Important:** Always open the project via the `.code-workspace` file, not the folder directly. The workspace file contains terminal profiles, debug configurations, and extension recommendations. |
| 78 | +
|
| 79 | +### What the Workspace Configures |
| 80 | + |
| 81 | +The `LsiGitCheckout.code-workspace` file provides: |
| 82 | + |
| 83 | +- **Terminal profiles**: defaults to `pwsh` on all platforms (PowerShell 7.x, not Windows PowerShell 5.1) |
| 84 | +- **File associations**: `.ps1`, `.psm1`, `.psd1` mapped to PowerShell language mode |
| 85 | +- **Editor settings**: 4-space indentation for PowerShell files |
| 86 | +- **Launch configurations**: pre-configured debug profiles for tests and script execution (see [Debugging](#debugging)) |
| 87 | +- **Extension recommendations**: prompts to install the PowerShell extension |
| 88 | + |
| 89 | +## Project Structure |
| 90 | + |
| 91 | +```text |
| 92 | +LsiGitCheckout.ps1 # Entry point (~230 lines) — params, module import, main flow |
| 93 | +LsiGitCheckout.psm1 # Module (~2520 lines) — all 36 function definitions |
| 94 | +LsiGitCheckout.psd1 # Module manifest — metadata, exported functions |
| 95 | +tests/ |
| 96 | + LsiGitCheckout.Unit.Tests.ps1 # Unit tests (no network required) |
| 97 | + LsiGitCheckout.Integration.Tests.ps1 # Integration tests (needs network) |
| 98 | + *.json # 16 test dependency configurations |
| 99 | +``` |
| 100 | + |
| 101 | +The entry point script imports the module, calls `Initialize-LsiGitCheckout` to set module state from CLI parameters, then runs the main logic. All functions live in the `.psm1` file using `$script:` scoped variables for shared state. |
| 102 | + |
| 103 | +## Running Tests |
| 104 | + |
| 105 | +### Unit Tests |
| 106 | + |
| 107 | +Fast tests covering pure and near-pure functions. No network or git operations required. |
| 108 | + |
| 109 | +```powershell |
| 110 | +pwsh -Command "Invoke-Pester ./tests/LsiGitCheckout.Unit.Tests.ps1 -Output Detailed" |
| 111 | +``` |
| 112 | + |
| 113 | +Covers: `Parse-VersionPattern`, `Test-SemVerCompatibility`, `Get-CompatibleVersionsForPattern`, `Select-VersionFromIntersection`, `Get-SemVersionIntersection`, `Format-SemVersion`, `Get-TagIntersection`, `Get-HostnameFromUrl`, `Validate-DependencyConfiguration`, `Get-AbsoluteBasePath`. |
| 114 | + |
| 115 | +### Integration Tests |
| 116 | + |
| 117 | +Runs `LsiGitCheckout.ps1` with `-DryRun` against all 16 test JSON configurations and asserts expected exit codes. Requires network access to GitHub. |
| 118 | + |
| 119 | +```powershell |
| 120 | +pwsh -Command "Invoke-Pester ./tests/LsiGitCheckout.Integration.Tests.ps1 -Output Detailed" |
| 121 | +``` |
| 122 | + |
| 123 | +### All Tests |
| 124 | + |
| 125 | +```powershell |
| 126 | +pwsh -Command "Invoke-Pester ./tests/ -Output Detailed" |
| 127 | +``` |
| 128 | + |
| 129 | +### Running from VS Code |
| 130 | + |
| 131 | +The workspace includes pre-configured launch profiles accessible from the **Run and Debug** sidebar (Ctrl+Shift+D / Cmd+Shift+D): |
| 132 | + |
| 133 | +| Profile | Description | |
| 134 | +|---------|-------------| |
| 135 | +| **Run Unit Tests** | Runs unit tests with debugger attached | |
| 136 | +| **Run Integration Tests** | Runs integration tests with debugger attached | |
| 137 | +| **Run All Tests** | Runs both unit and integration tests | |
| 138 | +| **Run Script (DryRun - SemVer)** | Runs `LsiGitCheckout.ps1 -DryRun` against `tests/dependencies_semver.json` | |
| 139 | +| **Run Script (Custom Config)** | Prompts for a config file path, then runs with `-DryRun` | |
| 140 | + |
| 141 | +Select a profile and press **F5** to launch. Breakpoints set in `.psm1` or `.ps1` files will be hit. |
| 142 | + |
| 143 | +## Debugging |
| 144 | + |
| 145 | +### VS Code Breakpoints |
| 146 | + |
| 147 | +1. Open the workspace: `code LsiGitCheckout.code-workspace` |
| 148 | +2. Set breakpoints by clicking the gutter in any `.ps1` or `.psm1` file |
| 149 | +3. Select a launch profile from the Run and Debug sidebar |
| 150 | +4. Press **F5** — the debugger will stop at breakpoints |
| 151 | +5. Use the **Debug Console** to inspect variables and module state (e.g., `$script:RepositoryDictionary`) |
| 152 | + |
| 153 | +All launch profiles use `createTemporaryIntegratedConsole` to ensure a clean PowerShell session for each run, avoiding stale module state between debug sessions. |
| 154 | + |
| 155 | +### Command-Line Debugging |
| 156 | + |
| 157 | +**Debug logging:** The `-EnableDebug` flag writes a timestamped log file: |
| 158 | + |
| 159 | +```powershell |
| 160 | +pwsh -File ./LsiGitCheckout.ps1 -InputFile tests/dependencies_semver.json -DryRun -EnableDebug |
| 161 | +# Creates: debug_log_YYYYMMDDHHMM.txt |
| 162 | +``` |
| 163 | + |
| 164 | +**Error context:** The `-EnableErrorContext` flag adds stack traces and line numbers to error output: |
| 165 | + |
| 166 | +```powershell |
| 167 | +pwsh -File ./LsiGitCheckout.ps1 -InputFile tests/dependencies_semver.json -DryRun -EnableErrorContext |
| 168 | +``` |
| 169 | + |
| 170 | +**Interactive breakpoints** (terminal-based, no VS Code required): |
| 171 | + |
| 172 | +```powershell |
| 173 | +pwsh |
| 174 | +Set-PSBreakpoint -Script ./LsiGitCheckout.psm1 -Command Process-DependencyFile |
| 175 | +./LsiGitCheckout.ps1 -InputFile tests/dependencies_semver.json -DryRun |
| 176 | +``` |
| 177 | + |
| 178 | +## Manual Testing |
| 179 | + |
| 180 | +Run any of the 16 test configurations individually: |
| 181 | + |
| 182 | +```powershell |
| 183 | +# SemVer mode |
| 184 | +pwsh -File ./LsiGitCheckout.ps1 -InputFile tests/dependencies_semver.json -DryRun |
| 185 | +
|
| 186 | +# Agnostic mode with recursive dependencies |
| 187 | +pwsh -File ./LsiGitCheckout.ps1 -InputFile tests/dependencies.recursive.example.json -DryRun |
| 188 | +
|
| 189 | +# Expected failure (API incompatibility) |
| 190 | +pwsh -File ./LsiGitCheckout.ps1 -InputFile tests/dependencies.API-incompatibility-test.json -DryRun |
| 191 | +# Exit code should be 1 |
| 192 | +``` |
| 193 | + |
| 194 | +See the integration test file (`tests/LsiGitCheckout.Integration.Tests.ps1`) for the full test matrix with expected exit codes. |
| 195 | + |
| 196 | +## Coding Conventions |
| 197 | + |
| 198 | +See [CLAUDE.md](../CLAUDE.md) for the full coding conventions. Key points: |
| 199 | + |
| 200 | +- **PowerShell 7.6 LTS** — use `??` null-coalescing, `-AsHashtable` for JSON, etc. |
| 201 | +- **Function names**: `Verb-Noun` PascalCase (e.g., `Test-GitInstalled`, `Parse-VersionPattern`) |
| 202 | +- **Logging**: always use `Write-Log` with appropriate level, never raw `Write-Host` |
| 203 | +- **Error handling**: wrap operations in `Invoke-WithErrorContext -Context "description" -ScriptBlock { ... }` |
| 204 | +- **Module state**: use `$script:` prefix for shared variables, initialize via `Initialize-LsiGitCheckout` |
| 205 | +- **CHANGELOG**: update `CHANGELOG.md` following [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format |
0 commit comments