microsoft/hve-core
Publicmirrored fromhttps://github.com/microsoft/hve-coreAvailable
scripts/extension/Package-Extension.ps1
290lines ยท modecode
| 1 | #!/usr/bin/env pwsh |
| 2 | |
| 3 | <# |
| 4 | .SYNOPSIS |
| 5 | Packages the HVE Core VS Code extension. |
| 6 | |
| 7 | .DESCRIPTION |
| 8 | This script packages the VS Code extension into a .vsix file. |
| 9 | It uses the version from package.json or a specified version. |
| 10 | Optionally adds a dev patch number for pre-release builds. |
| 11 | Supports VS Code Marketplace pre-release channel with -PreRelease switch. |
| 12 | |
| 13 | .PARAMETER Version |
| 14 | Optional. The version to use for the package. |
| 15 | If not specified, uses the version from package.json. |
| 16 | |
| 17 | .PARAMETER DevPatchNumber |
| 18 | Optional. Dev patch number to append (e.g., "123" creates "1.0.0-dev.123"). |
| 19 | |
| 20 | .PARAMETER ChangelogPath |
| 21 | Optional. Path to a changelog file to include in the package. |
| 22 | |
| 23 | .PARAMETER PreRelease |
| 24 | Optional. When specified, packages the extension for VS Code Marketplace pre-release channel. |
| 25 | Uses vsce --pre-release flag which marks the extension for the pre-release track. |
| 26 | |
| 27 | .EXAMPLE |
| 28 | ./Package-Extension.ps1 |
| 29 | # Packages using version from package.json |
| 30 | |
| 31 | .EXAMPLE |
| 32 | ./Package-Extension.ps1 -Version "2.0.0" |
| 33 | # Packages with specific version |
| 34 | |
| 35 | .EXAMPLE |
| 36 | ./Package-Extension.ps1 -DevPatchNumber "123" |
| 37 | # Packages with dev version (e.g., 1.0.0-dev.123) |
| 38 | |
| 39 | .EXAMPLE |
| 40 | ./Package-Extension.ps1 -Version "1.1.0" -DevPatchNumber "456" |
| 41 | # Packages with specific dev version (1.1.0-dev.456) |
| 42 | |
| 43 | .EXAMPLE |
| 44 | ./Package-Extension.ps1 -PreRelease |
| 45 | # Packages for VS Code Marketplace pre-release channel |
| 46 | |
| 47 | .EXAMPLE |
| 48 | ./Package-Extension.ps1 -Version "1.1.0" -PreRelease |
| 49 | # Packages with ODD minor version for pre-release channel |
| 50 | #> |
| 51 | |
| 52 | [CmdletBinding()] |
| 53 | param( |
| 54 | [Parameter(Mandatory = $false)] |
| 55 | [string]$Version = "", |
| 56 | |
| 57 | [Parameter(Mandatory = $false)] |
| 58 | [string]$DevPatchNumber = "", |
| 59 | |
| 60 | [Parameter(Mandatory = $false)] |
| 61 | [string]$ChangelogPath = "", |
| 62 | |
| 63 | [Parameter(Mandatory = $false)] |
| 64 | [switch]$PreRelease |
| 65 | ) |
| 66 | |
| 67 | $ErrorActionPreference = "Stop" |
| 68 | |
| 69 | # Determine script and repo paths |
| 70 | $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path |
| 71 | $RepoRoot = (Get-Item "$ScriptDir/../..").FullName |
| 72 | $ExtensionDir = Join-Path $RepoRoot "extension" |
| 73 | $GitHubDir = Join-Path $RepoRoot ".github" |
| 74 | $PackageJsonPath = Join-Path $ExtensionDir "package.json" |
| 75 | |
| 76 | Write-Host "๐ฆ HVE Core Extension Packager" -ForegroundColor Cyan |
| 77 | Write-Host "==============================" -ForegroundColor Cyan |
| 78 | Write-Host "" |
| 79 | |
| 80 | # Verify paths exist |
| 81 | if (-not (Test-Path $ExtensionDir)) { |
| 82 | Write-Error "Extension directory not found: $ExtensionDir" |
| 83 | exit 1 |
| 84 | } |
| 85 | |
| 86 | if (-not (Test-Path $PackageJsonPath)) { |
| 87 | Write-Error "package.json not found: $PackageJsonPath" |
| 88 | exit 1 |
| 89 | } |
| 90 | |
| 91 | if (-not (Test-Path $GitHubDir)) { |
| 92 | Write-Error ".github directory not found: $GitHubDir" |
| 93 | exit 1 |
| 94 | } |
| 95 | |
| 96 | # Read current package.json |
| 97 | Write-Host "๐ Reading package.json..." -ForegroundColor Yellow |
| 98 | try { |
| 99 | $packageJson = Get-Content -Path $PackageJsonPath -Raw | ConvertFrom-Json |
| 100 | } catch { |
| 101 | Write-Error "Failed to parse package.json: $_`nPlease check $PackageJsonPath for JSON syntax errors." |
| 102 | exit 1 |
| 103 | } |
| 104 | |
| 105 | # Validate package.json has required version field |
| 106 | if (-not $packageJson.PSObject.Properties['version']) { |
| 107 | Write-Error "package.json is missing required 'version' field" |
| 108 | exit 1 |
| 109 | } |
| 110 | |
| 111 | # Determine version |
| 112 | $baseVersion = if ($Version -and $Version -ne "") { |
| 113 | # Validate specified version format |
| 114 | if ($Version -notmatch '^\d+\.\d+\.\d+$') { |
| 115 | Write-Error "Invalid version format specified: '$Version'. Expected semantic version format (e.g., 1.0.0).`nPre-release suffixes like '-dev.123' should be added via -DevPatchNumber parameter, not in the version itself." |
| 116 | exit 1 |
| 117 | } |
| 118 | $Version |
| 119 | } else { |
| 120 | # Use version from package.json |
| 121 | $currentVersion = $packageJson.version |
| 122 | if ($currentVersion -notmatch '^\d+\.\d+\.\d+') { |
| 123 | $errorMessage = @( |
| 124 | "Invalid version format in package.json: '$currentVersion'.", |
| 125 | "Expected semantic version format (e.g., 1.0.0).", |
| 126 | "Pre-release suffixes should not be committed to package.json.", |
| 127 | "Use -DevPatchNumber parameter to add '-dev.N' suffix during packaging." |
| 128 | ) -join "`n" |
| 129 | Write-Error $errorMessage |
| 130 | exit 1 |
| 131 | } |
| 132 | # Extract base version (validation above ensures this will match) |
| 133 | $currentVersion -match '^(\d+\.\d+\.\d+)' | Out-Null |
| 134 | $Matches[1] |
| 135 | } |
| 136 | |
| 137 | # Apply dev patch number if provided |
| 138 | $packageVersion = if ($DevPatchNumber -and $DevPatchNumber -ne "") { |
| 139 | "$baseVersion-dev.$DevPatchNumber" |
| 140 | } else { |
| 141 | $baseVersion |
| 142 | } |
| 143 | |
| 144 | Write-Host " Using version: $packageVersion" -ForegroundColor Green |
| 145 | |
| 146 | # Handle temporary version update for dev builds |
| 147 | $originalVersion = $packageJson.version |
| 148 | |
| 149 | if ($packageVersion -ne $originalVersion) { |
| 150 | Write-Host "" |
| 151 | Write-Host "๐ Temporarily updating package.json version..." -ForegroundColor Yellow |
| 152 | $packageJson.version = $packageVersion |
| 153 | $packageJson | ConvertTo-Json -Depth 10 | Set-Content -Path $PackageJsonPath -Encoding UTF8NoBOM |
| 154 | Write-Host " Version: $originalVersion -> $packageVersion" -ForegroundColor Green |
| 155 | } |
| 156 | |
| 157 | # Handle changelog if provided |
| 158 | if ($ChangelogPath -and $ChangelogPath -ne "") { |
| 159 | Write-Host "" |
| 160 | Write-Host "๐ Processing changelog..." -ForegroundColor Yellow |
| 161 | |
| 162 | if (Test-Path $ChangelogPath) { |
| 163 | $changelogDest = Join-Path $ExtensionDir "CHANGELOG.md" |
| 164 | Copy-Item -Path $ChangelogPath -Destination $changelogDest -Force |
| 165 | Write-Host " Copied changelog to extension directory" -ForegroundColor Green |
| 166 | } else { |
| 167 | Write-Warning "Changelog file not found: $ChangelogPath" |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | # Prepare extension directory |
| 172 | Write-Host "" |
| 173 | Write-Host "๐๏ธ Preparing extension directory..." -ForegroundColor Yellow |
| 174 | |
| 175 | # Clean any existing copied directories |
| 176 | $dirsToClean = @(".github", "scripts") |
| 177 | foreach ($dir in $dirsToClean) { |
| 178 | $dirPath = Join-Path $ExtensionDir $dir |
| 179 | if (Test-Path $dirPath) { |
| 180 | Remove-Item -Path $dirPath -Recurse -Force |
| 181 | Write-Host " Cleaned existing $dir directory" -ForegroundColor Gray |
| 182 | } |
| 183 | } |
| 184 | |
| 185 | # Copy required directories |
| 186 | Write-Host " Copying .github..." -ForegroundColor Gray |
| 187 | Copy-Item -Path "$RepoRoot/.github" -Destination "$ExtensionDir/.github" -Recurse |
| 188 | |
| 189 | Write-Host " Copying scripts/dev-tools..." -ForegroundColor Gray |
| 190 | New-Item -Path "$ExtensionDir/scripts" -ItemType Directory -Force | Out-Null |
| 191 | Copy-Item -Path "$RepoRoot/scripts/dev-tools" -Destination "$ExtensionDir/scripts/dev-tools" -Recurse |
| 192 | |
| 193 | Write-Host " โ
Extension directory prepared" -ForegroundColor Green |
| 194 | |
| 195 | # Package extension |
| 196 | Write-Host "" |
| 197 | Write-Host "๐ฆ Packaging extension..." -ForegroundColor Yellow |
| 198 | |
| 199 | if ($PreRelease) { |
| 200 | Write-Host " Mode: Pre-release channel" -ForegroundColor Magenta |
| 201 | } |
| 202 | |
| 203 | # Initialize vsixFile variable to avoid scope issues |
| 204 | $vsixFile = $null |
| 205 | |
| 206 | # Build vsce arguments |
| 207 | $vsceArgs = @('package', '--no-dependencies') |
| 208 | if ($PreRelease) { |
| 209 | $vsceArgs += '--pre-release' |
| 210 | } |
| 211 | |
| 212 | Push-Location $ExtensionDir |
| 213 | |
| 214 | try { |
| 215 | # Check if vsce is available |
| 216 | $vsceCmd = Get-Command vsce -ErrorAction SilentlyContinue |
| 217 | if (-not $vsceCmd) { |
| 218 | $vsceCmd = Get-Command npx -ErrorAction SilentlyContinue |
| 219 | if ($vsceCmd) { |
| 220 | Write-Host " Using npx @vscode/vsce..." -ForegroundColor Gray |
| 221 | & npx @vscode/vsce @vsceArgs |
| 222 | } else { |
| 223 | Write-Error "Neither vsce nor npx found. Please install @vscode/vsce globally or ensure npm is available." |
| 224 | exit 1 |
| 225 | } |
| 226 | } else { |
| 227 | Write-Host " Using vsce..." -ForegroundColor Gray |
| 228 | & vsce @vsceArgs |
| 229 | } |
| 230 | |
| 231 | if ($LASTEXITCODE -ne 0) { |
| 232 | Write-Error "Failed to package extension" |
| 233 | exit 1 |
| 234 | } |
| 235 | |
| 236 | # Find the generated vsix file |
| 237 | $vsixFile = Get-ChildItem -Path $ExtensionDir -Filter "*.vsix" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 |
| 238 | |
| 239 | if ($vsixFile) { |
| 240 | Write-Host "" |
| 241 | Write-Host "โ
Extension packaged successfully!" -ForegroundColor Green |
| 242 | Write-Host " File: $($vsixFile.Name)" -ForegroundColor Cyan |
| 243 | Write-Host " Size: $([math]::Round($vsixFile.Length / 1KB, 2)) KB" -ForegroundColor Cyan |
| 244 | Write-Host " Version: $packageVersion" -ForegroundColor Cyan |
| 245 | } else { |
| 246 | Write-Error "No .vsix file found after packaging" |
| 247 | exit 1 |
| 248 | } |
| 249 | |
| 250 | } finally { |
| 251 | Pop-Location |
| 252 | |
| 253 | # Cleanup copied directories |
| 254 | Write-Host "" |
| 255 | Write-Host "๐งน Cleaning up..." -ForegroundColor Yellow |
| 256 | |
| 257 | foreach ($dir in $dirsToClean) { |
| 258 | $dirPath = Join-Path $ExtensionDir $dir |
| 259 | if (Test-Path $dirPath) { |
| 260 | Remove-Item -Path $dirPath -Recurse -Force |
| 261 | Write-Host " Removed $dir" -ForegroundColor Gray |
| 262 | } |
| 263 | } |
| 264 | |
| 265 | # Restore original version if it was changed |
| 266 | if ($packageVersion -ne $originalVersion) { |
| 267 | Write-Host "" |
| 268 | Write-Host "๐ Restoring original package.json version..." -ForegroundColor Yellow |
| 269 | $packageJson.version = $originalVersion |
| 270 | $packageJson | ConvertTo-Json -Depth 10 | Set-Content -Path $PackageJsonPath -Encoding UTF8NoBOM |
| 271 | Write-Host " Version restored to: $originalVersion" -ForegroundColor Green |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | Write-Host "" |
| 276 | Write-Host "๐ Done!" -ForegroundColor Green |
| 277 | Write-Host "" |
| 278 | |
| 279 | # Output for CI/CD consumption |
| 280 | if ($env:GITHUB_OUTPUT) { |
| 281 | if ($vsixFile) { |
| 282 | "version=$packageVersion" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 |
| 283 | "vsix-file=$($vsixFile.Name)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 |
| 284 | "pre-release=$($PreRelease.IsPresent)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 |
| 285 | } else { |
| 286 | Write-Warning "Cannot write GITHUB_OUTPUT: vsix file not available" |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | exit 0 |
| 291 | |