1+ # !/usr/bin/env pwsh
2+ <#
3+ . SYNOPSIS
4+ Automated version bumping script for the project
5+
6+ . DESCRIPTION
7+ Updates version numbers across all project files automatically to prevent human errors.
8+ Supports preview mode for safe testing.
9+
10+ . PARAMETER NewVersion
11+ The new version number in semver format (e.g., "0.18.0")
12+
13+ . PARAMETER WhatIf
14+ Preview changes without applying them
15+
16+ . EXAMPLE
17+ .\bump-version.ps1 -NewVersion "0.18.0"
18+
19+ . EXAMPLE
20+ .\bump-version.ps1 -NewVersion "0.18.0" -WhatIf
21+ #>
22+
23+ param (
24+ [Parameter (Mandatory = $true )]
25+ [string ]$NewVersion ,
26+
27+ [switch ]$WhatIf
28+ )
29+
30+ # Script configuration
31+ $ErrorActionPreference = " Stop"
32+
33+ # Version file locations (relative to script root)
34+ $VersionFiles = @ (
35+ @ {
36+ Path = " ReflectorNet/ReflectorNet.csproj"
37+ Pattern = ' <Version>[\d\.]+</Version>'
38+ Replace = ' <Version>{VERSION}</Version>'
39+ Description = " Common csproj XML version"
40+ }
41+ )
42+
43+ function Write-ColorText {
44+ param ([string ]$Text , [string ]$Color = " White" )
45+ Write-Host $Text - ForegroundColor $Color
46+ }
47+
48+ function Test-SemanticVersion {
49+ param ([string ]$Version )
50+
51+ if ([string ]::IsNullOrWhiteSpace($Version )) {
52+ return $false
53+ }
54+
55+ # Basic semver pattern: major.minor.patch (with optional prerelease/build)
56+ $pattern = ' ^\d+\.\d+\.\d+(-[a-zA-Z0-9\-\.]+)?(\+[a-zA-Z0-9\-\.]+)?$'
57+ return $Version -match $pattern
58+ }
59+
60+ function Get-CurrentVersion {
61+ # Extract current version from package.json
62+ $packageJsonPath = Join-Path $PSScriptRoot " ReflectorNet/ReflectorNet.csproj"
63+ if (-not (Test-Path $packageJsonPath )) {
64+ throw " Could not find package.json at: $packageJsonPath "
65+ }
66+
67+ $content = Get-Content $packageJsonPath - Raw
68+ if ($content -match ' <Version>([\d\.]+)</Version>' ) {
69+ return $Matches [1 ]
70+ }
71+
72+ throw " Could not extract current version from package.json"
73+ }
74+
75+ function Update-VersionFiles {
76+ param ([string ]$OldVersion , [string ]$NewVersion , [bool ]$PreviewOnly = $false )
77+
78+ $changes = @ ()
79+
80+ foreach ($file in $VersionFiles ) {
81+ $fullPath = Join-Path $PSScriptRoot $file.Path
82+
83+ if (-not (Test-Path $fullPath )) {
84+ Write-ColorText " ⚠️ File not found: $ ( $file.Path ) " " Yellow"
85+ continue
86+ }
87+
88+ $content = Get-Content $fullPath - Raw
89+ $originalContent = $content
90+
91+ # Create the replacement string
92+ $replacement = $file.Replace -replace ' \{VERSION\}' , $NewVersion
93+
94+ # Apply the replacement
95+ $newContent = $content -replace $file.Pattern , $replacement
96+
97+ # Check if any changes were made
98+ if ($originalContent -ne $newContent ) {
99+ # Count matches for reporting
100+ $regexMatches = [regex ]::Matches($originalContent , $file.Pattern )
101+
102+ $changes += @ {
103+ Path = $file.Path
104+ Description = $file.Description
105+ Matches = $regexMatches.Count
106+ Content = $newContent
107+ OriginalContent = $originalContent
108+ }
109+
110+ Write-ColorText " 📝 $ ( $file.Description ) : $ ( $regexMatches.Count ) occurrence(s)" " Green"
111+
112+ # Show the actual changes
113+ foreach ($match in $regexMatches ) {
114+ $newValue = $match.Value -replace $file.Pattern , $replacement
115+ Write-ColorText " $ ( $match.Value ) → $newValue " " Gray"
116+ }
117+ }
118+ else {
119+ Write-ColorText " ⚠️ No matches found in: $ ( $file.Path ) " " Yellow"
120+ Write-ColorText " Pattern: $ ( $file.Pattern ) " " Gray"
121+ }
122+ }
123+
124+ if ($changes.Count -eq 0 ) {
125+ Write-ColorText " ❌ No version references found to update!" " Red"
126+ exit 1
127+ }
128+
129+ if ($PreviewOnly ) {
130+ Write-ColorText " `n 📋 Preview Summary:" " Cyan"
131+ Write-ColorText " Files to be modified: $ ( $changes.Count ) " " White"
132+ Write-ColorText " Total replacements: $ ( ($changes | Measure-Object - Property Matches - Sum).Sum) " " White"
133+ return $null
134+ }
135+
136+ # Apply changes
137+ foreach ($change in $changes ) {
138+ $fullPath = Join-Path $PSScriptRoot $change.Path
139+ Set-Content - Path $fullPath - Value $change.Content - NoNewline
140+ }
141+
142+ return $changes
143+ }
144+
145+ # Main execution
146+ try {
147+ Write-ColorText " 🚀 McpPlugin Version Bump Script" " Cyan"
148+ Write-ColorText " =================================" " Cyan"
149+
150+ # Validate semantic version format
151+ if (-not (Test-SemanticVersion $NewVersion )) {
152+ Write-ColorText " ❌ Invalid semantic version format: $NewVersion " " Red"
153+ Write-ColorText " Expected format: major.minor.patch (e.g., '1.2.3')" " Yellow"
154+ exit 1
155+ }
156+
157+ # Get current version
158+ $currentVersion = Get-CurrentVersion
159+ Write-ColorText " 📋 Current version: $currentVersion " " White"
160+ Write-ColorText " 📋 New version: $NewVersion " " White"
161+
162+ if ($currentVersion -eq $NewVersion ) {
163+ Write-ColorText " ⚠️ New version is the same as current version" " Yellow"
164+ exit 0
165+ }
166+
167+ Write-ColorText " `n 🔍 Scanning for version references..." " Cyan"
168+
169+ # Update version files
170+ $changes = Update-VersionFiles - OldVersion $currentVersion - NewVersion $NewVersion - PreviewOnly $WhatIf
171+
172+ if ($WhatIf ) {
173+ Write-ColorText " `n ✅ Preview completed. Use without -WhatIf to apply changes." " Green"
174+ exit 0
175+ }
176+
177+ if ($changes -and $changes.Count -gt 0 ) {
178+ Write-ColorText " `n 🎉 Version bump completed successfully!" " Green"
179+ Write-ColorText " Updated $ ( $changes.Count ) files" " White"
180+ Write-ColorText " Total replacements: $ ( ($changes | Measure-Object - Property Matches - Sum).Sum) " " White"
181+ Write-ColorText " Version: $currentVersion → $NewVersion " " White"
182+ Write-ColorText " `n 💡 Remember to commit these changes to git" " Cyan"
183+ }
184+ }
185+ catch {
186+ Write-ColorText " `n ❌ Script failed: $ ( $_.Exception.Message ) " " Red"
187+ exit 1
188+ }
0 commit comments