microsoft/hve-core
Publicmirrored fromhttps://github.com/microsoft/hve-coreAvailable
scripts/release/Update-VersionFiles.ps1
205lines · modecode
| 1 | #!/usr/bin/env pwsh |
| 2 | # Copyright (c) Microsoft Corporation. |
| 3 | # SPDX-License-Identifier: MIT |
| 4 | #Requires -Version 7.0 |
| 5 | |
| 6 | <# |
| 7 | .SYNOPSIS |
| 8 | Updates version strings across all version-tracked files in the repository. |
| 9 | |
| 10 | .DESCRIPTION |
| 11 | Central version bump script called by both release-prerelease-pr.yml and |
| 12 | release-stable.yml workflows. Updates: |
| 13 | |
| 14 | - package.json |
| 15 | - package-lock.json (version and packages[""].version) |
| 16 | - extension/templates/package.template.json |
| 17 | - .github/plugin/marketplace.json (metadata.version and plugins[*].version) |
| 18 | - plugins/*/.github/plugin/plugin.json (glob) |
| 19 | - .release-please-manifest.json |
| 20 | |
| 21 | After updating the files, runs 'npm run plugin:generate' to regenerate |
| 22 | plugin outputs so plugin-validation passes. |
| 23 | |
| 24 | .PARAMETER Version |
| 25 | The version string to write (e.g. '3.3.0'). |
| 26 | |
| 27 | .PARAMETER RepoRoot |
| 28 | Optional. Repository root directory. Defaults to the git working tree root. |
| 29 | |
| 30 | .PARAMETER SkipPluginGenerate |
| 31 | Optional. Skip running 'npm run plugin:generate' after updating files. |
| 32 | |
| 33 | .EXAMPLE |
| 34 | ./Update-VersionFiles.ps1 -Version '3.3.0' |
| 35 | |
| 36 | .EXAMPLE |
| 37 | ./Update-VersionFiles.ps1 -Version '3.3.0' -RepoRoot '/path/to/repo' |
| 38 | |
| 39 | .NOTES |
| 40 | Called by CI workflows. Requires Node.js and npm dependencies installed |
| 41 | when SkipPluginGenerate is not set. |
| 42 | #> |
| 43 | |
| 44 | [CmdletBinding()] |
| 45 | param( |
| 46 | [Parameter(Mandatory = $true)] |
| 47 | [ValidatePattern('^\d+\.\d+\.\d+')] |
| 48 | [string]$Version, |
| 49 | |
| 50 | [Parameter(Mandatory = $false)] |
| 51 | [string]$RepoRoot = "", |
| 52 | |
| 53 | [Parameter(Mandatory = $false)] |
| 54 | [switch]$SkipPluginGenerate |
| 55 | ) |
| 56 | |
| 57 | $ErrorActionPreference = 'Stop' |
| 58 | |
| 59 | #region Helpers |
| 60 | |
| 61 | function Resolve-RepoRoot { |
| 62 | <# |
| 63 | .SYNOPSIS |
| 64 | Resolves the repository root directory. |
| 65 | #> |
| 66 | param([string]$Supplied) |
| 67 | |
| 68 | if ($Supplied) { |
| 69 | return (Resolve-Path $Supplied).Path |
| 70 | } |
| 71 | |
| 72 | # Walk up from script location to find the repo root |
| 73 | $candidate = (Resolve-Path (Join-Path $PSScriptRoot "../..")).Path |
| 74 | if (Test-Path (Join-Path $candidate ".git")) { |
| 75 | return $candidate |
| 76 | } |
| 77 | |
| 78 | throw "Unable to determine repository root. Pass -RepoRoot explicitly." |
| 79 | } |
| 80 | |
| 81 | function Update-JsonVersion { |
| 82 | <# |
| 83 | .SYNOPSIS |
| 84 | Updates a version field in a JSON file using a script block. |
| 85 | #> |
| 86 | param( |
| 87 | [string]$FilePath, |
| 88 | [string]$Description, |
| 89 | [scriptblock]$Transform, |
| 90 | [switch]$AsHashtable |
| 91 | ) |
| 92 | |
| 93 | if (-not (Test-Path $FilePath)) { |
| 94 | Write-Host " ⏭️ Skipping $Description — file not found: $FilePath" -ForegroundColor Yellow |
| 95 | return |
| 96 | } |
| 97 | |
| 98 | $convertParams = @{ Depth = 20 } |
| 99 | if ($AsHashtable) { $convertParams['AsHashtable'] = $true } |
| 100 | $raw = Get-Content -Raw $FilePath |
| 101 | if ([string]::IsNullOrWhiteSpace($raw)) { |
| 102 | throw "File is empty or whitespace-only: $FilePath" |
| 103 | } |
| 104 | $json = $raw | ConvertFrom-Json @convertParams |
| 105 | $json = & $Transform $json |
| 106 | $json | ConvertTo-Json -Depth 20 | Set-Content -Path $FilePath -Encoding UTF8 -NoNewline |
| 107 | Write-Host " ✅ Updated $Description" -ForegroundColor Green |
| 108 | } |
| 109 | |
| 110 | #endregion Helpers |
| 111 | |
| 112 | #region Main |
| 113 | |
| 114 | if ($MyInvocation.InvocationName -ne '.') { |
| 115 | try { |
| 116 | $root = Resolve-RepoRoot -Supplied $RepoRoot |
| 117 | Write-Host "🔄 Updating version files to $Version" -ForegroundColor Cyan |
| 118 | Write-Host " 📂 Repo root: $root" -ForegroundColor Gray |
| 119 | |
| 120 | # 1. package.json |
| 121 | Update-JsonVersion ` |
| 122 | -FilePath (Join-Path $root "package.json") ` |
| 123 | -Description "package.json" ` |
| 124 | -Transform { param($j) $j.version = $Version; $j } |
| 125 | |
| 126 | # 2. package-lock.json (version + packages[""].version) |
| 127 | Update-JsonVersion ` |
| 128 | -FilePath (Join-Path $root "package-lock.json") ` |
| 129 | -Description "package-lock.json" ` |
| 130 | -AsHashtable ` |
| 131 | -Transform { |
| 132 | param($j) |
| 133 | $j['version'] = $Version |
| 134 | if ($j.ContainsKey('packages') -and $j['packages'].ContainsKey('')) { |
| 135 | $j['packages']['']['version'] = $Version |
| 136 | } |
| 137 | $j |
| 138 | } |
| 139 | |
| 140 | # 3. extension/templates/package.template.json |
| 141 | Update-JsonVersion ` |
| 142 | -FilePath (Join-Path $root "extension/templates/package.template.json") ` |
| 143 | -Description "extension/templates/package.template.json" ` |
| 144 | -Transform { param($j) $j.version = $Version; $j } |
| 145 | |
| 146 | # 4. .github/plugin/marketplace.json |
| 147 | Update-JsonVersion ` |
| 148 | -FilePath (Join-Path $root ".github/plugin/marketplace.json") ` |
| 149 | -Description ".github/plugin/marketplace.json" ` |
| 150 | -Transform { |
| 151 | param($j) |
| 152 | $j.metadata.version = $Version |
| 153 | foreach ($plugin in $j.plugins) { |
| 154 | $plugin.version = $Version |
| 155 | } |
| 156 | $j |
| 157 | } |
| 158 | |
| 159 | # 5. plugins/*/.github/plugin/plugin.json (glob) |
| 160 | $pluginJsonFiles = Get-ChildItem -Path (Join-Path $root "plugins") ` |
| 161 | -Filter "plugin.json" -Recurse -Force ` |
| 162 | | Where-Object { $_.FullName -match 'plugins[/\\][^/\\]+[/\\]\.github[/\\]plugin[/\\]plugin\.json$' } |
| 163 | |
| 164 | foreach ($pluginFile in $pluginJsonFiles) { |
| 165 | $relativePath = $pluginFile.FullName.Replace($root, '').TrimStart('/\') |
| 166 | Update-JsonVersion ` |
| 167 | -FilePath $pluginFile.FullName ` |
| 168 | -Description $relativePath ` |
| 169 | -Transform { param($j) $j.version = $Version; $j } |
| 170 | } |
| 171 | |
| 172 | # 6. .release-please-manifest.json |
| 173 | Update-JsonVersion ` |
| 174 | -FilePath (Join-Path $root ".release-please-manifest.json") ` |
| 175 | -Description ".release-please-manifest.json" ` |
| 176 | -Transform { param($j) $j.'.' = $Version; $j } |
| 177 | |
| 178 | # 7. Regenerate plugin outputs |
| 179 | if (-not $SkipPluginGenerate) { |
| 180 | Write-Host " 🔧 Running npm run plugin:generate ..." -ForegroundColor Cyan |
| 181 | Push-Location $root |
| 182 | try { |
| 183 | npm run plugin:generate |
| 184 | if ($LASTEXITCODE -ne 0) { |
| 185 | throw "npm run plugin:generate failed with exit code $LASTEXITCODE" |
| 186 | } |
| 187 | Write-Host " ✅ Plugin generation complete" -ForegroundColor Green |
| 188 | } |
| 189 | finally { |
| 190 | Pop-Location |
| 191 | } |
| 192 | } |
| 193 | else { |
| 194 | Write-Host " ⏭️ Skipping plugin:generate (SkipPluginGenerate set)" -ForegroundColor Yellow |
| 195 | } |
| 196 | |
| 197 | Write-Host "✅ All version files updated to $Version" -ForegroundColor Green |
| 198 | } |
| 199 | catch { |
| 200 | Write-Host "❌ Version update failed: $_" -ForegroundColor Red |
| 201 | throw |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | #endregion Main |
| 206 | |