From f7fe612690a35ebb7d750864e8c1fe82e8dabeca Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 23 Feb 2026 15:34:03 -0800 Subject: [PATCH 01/10] Install protoc on Windows using zip for ADO --- helpers.build.psm1 | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/helpers.build.psm1 b/helpers.build.psm1 index 0b2e27d0f..3d2435fae 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -649,7 +649,36 @@ function Install-Protobuf { Write-Warning "Homebrew not found, please install Protobuf manually" } } elseif ($IsWindows) { - if (Test-CommandAvailable -Name 'winget') { + if ($env:TF_BUILD) { + Write-Verbose -Verbose "Running in Azure DevOps, installing from zip" + $arch = if ([Environment]::Is64BitOperatingSystem) { "win64" } else { "win32" } + + Write-Host "Fetching latest Protocol Buffers release info..." + $release = Invoke-RestMethod -Uri "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" + $asset = $release.assets | Where-Object { $_.name -match "protoc-.*-$arch\.zip" } + if (-not $asset) { throw "No matching protoc binary found for $arch" } + $downloadUrl = $asset.browser_download_url + $zipPath = "$env:TEMP\protoc.zip" + + Write-Host "Downloading protoc from $downloadUrl..." + Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath + $installDir = "$env:USERPROFILE\protoc" + if (-not (Test-Path $installDir)) { New-Item -ItemType Directory -Path $installDir | Out-Null } + + Write-Host "Extracting protoc to $installDir..." + Expand-Archive -Path $zipPath -DestinationPath $installDir -Force + + $envPath = [Environment]::GetEnvironmentVariable("Path", "Machine") + if ($envPath -notlike "*$installDir\bin*") { + $env:PATH += ";$installDir\bin" + } + + Write-Host "Verifying protoc installation..." + & "$installDir\bin\protoc.exe" --version + + Write-Host "✅ Protocol Buffers installed successfully!" + } + elseif (Test-CommandAvailable -Name 'winget') { Write-Verbose -Verbose "Using winget to install Protobuf" winget install Google.Protobuf --accept-source-agreements --accept-package-agreements --source winget --force # need to add to PATH @@ -666,6 +695,7 @@ function Install-Protobuf { if (Test-CommandAvailable -Name 'apt') { Write-Verbose -Verbose "Using apt to install Protobuf" sudo apt install -y protobuf-compiler + Write-Verbose -Verbose (Get-Command protoc | Out-String) } else { Write-Warning "apt not found, please install Protobuf manually" } From f9b2c7f5a05d9a663a63824ebdea6b6b27076e13 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 23 Feb 2026 16:15:52 -0800 Subject: [PATCH 02/10] force update of protoc in ADO --- helpers.build.psm1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/helpers.build.psm1 b/helpers.build.psm1 index 3d2435fae..afe807813 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -636,8 +636,9 @@ function Install-Protobuf { param() process { - if (Test-CommandAvailable -Name 'protoc') { - Write-Verbose "Protobuf already installed." + # if ADO, we install the latest version + if ($null -eq $env:TF_BUILD -and (Test-CommandAvailable -Name 'protoc')) { + Write-Verbose -Verbose "Protobuf already installed: $(protoc --version)" return } @@ -696,6 +697,7 @@ function Install-Protobuf { Write-Verbose -Verbose "Using apt to install Protobuf" sudo apt install -y protobuf-compiler Write-Verbose -Verbose (Get-Command protoc | Out-String) + Write-Verbose -Verbose "protoc version: $(protoc --version)" } else { Write-Warning "apt not found, please install Protobuf manually" } From 958ee75193a8020fe5db49ebeed3a25cdbdcb30b Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 23 Feb 2026 17:51:46 -0800 Subject: [PATCH 03/10] install as zip on Linux for ADO --- helpers.build.psm1 | 59 ++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/helpers.build.psm1 b/helpers.build.psm1 index afe807813..73d009a0a 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -626,6 +626,28 @@ function Install-NodeJS { } } +function Install-ProtobufRelease($arch) { + Write-Verbose -Verbose "Fetching latest Protocol Buffers release info..." + $release = Invoke-RestMethod -Uri "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" + $asset = $release.assets | Where-Object { $_.name -match "protoc-.*-$arch\.zip" } + if (-not $asset) { throw "No matching protoc binary found for $arch" } + $downloadUrl = $asset.browser_download_url + $zipPath = "$env:TEMP\protoc.zip" + + Write-Host "Downloading protoc from $downloadUrl..." + Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath + $installDir = "$env:USERPROFILE\protoc" + if (-not (Test-Path $installDir)) { New-Item -ItemType Directory -Path $installDir | Out-Null } + + Write-Host "Extracting protoc to $installDir..." + Expand-Archive -Path $zipPath -DestinationPath $installDir -Force + + $env:PATH += [System.Environment]::PathSeparator + "$installDir\bin" + + Write-Host "Verifying protoc installation..." + Write-Host -Verbose "protoc version: $(protoc --version)" +} + function Install-Protobuf { <# .SYNOPSIS @@ -653,31 +675,7 @@ function Install-Protobuf { if ($env:TF_BUILD) { Write-Verbose -Verbose "Running in Azure DevOps, installing from zip" $arch = if ([Environment]::Is64BitOperatingSystem) { "win64" } else { "win32" } - - Write-Host "Fetching latest Protocol Buffers release info..." - $release = Invoke-RestMethod -Uri "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" - $asset = $release.assets | Where-Object { $_.name -match "protoc-.*-$arch\.zip" } - if (-not $asset) { throw "No matching protoc binary found for $arch" } - $downloadUrl = $asset.browser_download_url - $zipPath = "$env:TEMP\protoc.zip" - - Write-Host "Downloading protoc from $downloadUrl..." - Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath - $installDir = "$env:USERPROFILE\protoc" - if (-not (Test-Path $installDir)) { New-Item -ItemType Directory -Path $installDir | Out-Null } - - Write-Host "Extracting protoc to $installDir..." - Expand-Archive -Path $zipPath -DestinationPath $installDir -Force - - $envPath = [Environment]::GetEnvironmentVariable("Path", "Machine") - if ($envPath -notlike "*$installDir\bin*") { - $env:PATH += ";$installDir\bin" - } - - Write-Host "Verifying protoc installation..." - & "$installDir\bin\protoc.exe" --version - - Write-Host "✅ Protocol Buffers installed successfully!" + Install-ProtobufRelease -arch $arch } elseif (Test-CommandAvailable -Name 'winget') { Write-Verbose -Verbose "Using winget to install Protobuf" @@ -693,7 +691,16 @@ function Install-Protobuf { Write-Warning "winget not found, please install Protobuf manually" } } else { - if (Test-CommandAvailable -Name 'apt') { + if ($env:TF_BUILD) { + Write-Verbose -Verbose "Running in Azure DevOps on Linux, installing from zip" + # check if ARM64 or x64 + $arch = if ([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture -eq [System.Runtime.InteropServices.Architecture]::Arm64) { + "linux-aarch_64" + } else { + "linux-x86_64" + } + Install-ProtobufRelease -arch $arch + } elseif (Test-CommandAvailable -Name 'apt') { Write-Verbose -Verbose "Using apt to install Protobuf" sudo apt install -y protobuf-compiler Write-Verbose -Verbose (Get-Command protoc | Out-String) From c5d735f0e1b1947b3885fba80852035cc7845ba0 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 23 Feb 2026 19:21:55 -0800 Subject: [PATCH 04/10] fix home dir and path separator --- helpers.build.psm1 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/helpers.build.psm1 b/helpers.build.psm1 index 73d009a0a..2ef8cc229 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -636,13 +636,17 @@ function Install-ProtobufRelease($arch) { Write-Host "Downloading protoc from $downloadUrl..." Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath - $installDir = "$env:USERPROFILE\protoc" + $installDir = if ($IsWindows) { + "$env:USERPROFILE\protoc" + } else { + "$env:HOME/protoc" + } if (-not (Test-Path $installDir)) { New-Item -ItemType Directory -Path $installDir | Out-Null } Write-Host "Extracting protoc to $installDir..." Expand-Archive -Path $zipPath -DestinationPath $installDir -Force - $env:PATH += [System.Environment]::PathSeparator + "$installDir\bin" + $env:PATH += [System.IO.Path]::PathSeparator + "$installDir\bin" Write-Host "Verifying protoc installation..." Write-Host -Verbose "protoc version: $(protoc --version)" From b2170e2bd82b6fe5742e65e9bc5abff44c6452fa Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 23 Feb 2026 19:50:22 -0800 Subject: [PATCH 05/10] put new install early in PATH --- helpers.build.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers.build.psm1 b/helpers.build.psm1 index 2ef8cc229..e28820092 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -646,7 +646,7 @@ function Install-ProtobufRelease($arch) { Write-Host "Extracting protoc to $installDir..." Expand-Archive -Path $zipPath -DestinationPath $installDir -Force - $env:PATH += [System.IO.Path]::PathSeparator + "$installDir\bin" + $env:PATH = "$installDir\bin" + [System.IO.Path]::PathSeparator + $env:PATH Write-Host "Verifying protoc installation..." Write-Host -Verbose "protoc version: $(protoc --version)" From 82fe3b1fc41e47afe11f50ba0fffca795d4fe66f Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 23 Feb 2026 20:25:18 -0800 Subject: [PATCH 06/10] add tracing --- helpers.build.psm1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helpers.build.psm1 b/helpers.build.psm1 index e28820092..643fe270e 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -649,7 +649,8 @@ function Install-ProtobufRelease($arch) { $env:PATH = "$installDir\bin" + [System.IO.Path]::PathSeparator + $env:PATH Write-Host "Verifying protoc installation..." - Write-Host -Verbose "protoc version: $(protoc --version)" + Write-Host (Get-Command protoc | Out-String) + Write-Host "protoc version: $(protoc --version)" } function Install-Protobuf { From 7abc01e73a089ed1ca0e1d69ef7d2d1edb63a09a Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 23 Feb 2026 21:12:04 -0800 Subject: [PATCH 07/10] fix dir separator --- helpers.build.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers.build.psm1 b/helpers.build.psm1 index 643fe270e..c6a0d9ec7 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -646,7 +646,7 @@ function Install-ProtobufRelease($arch) { Write-Host "Extracting protoc to $installDir..." Expand-Archive -Path $zipPath -DestinationPath $installDir -Force - $env:PATH = "$installDir\bin" + [System.IO.Path]::PathSeparator + $env:PATH + $env:PATH = "$installDir" + [System.IO.Path]::DirectorySeparatorChar + "bin" + [System.IO.Path]::PathSeparator + $env:PATH Write-Host "Verifying protoc installation..." Write-Host (Get-Command protoc | Out-String) From 85ffa6d63545e9271d8fa8966324c69f493f70ed Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Tue, 24 Feb 2026 06:42:32 -0800 Subject: [PATCH 08/10] Update helpers.build.psm1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- helpers.build.psm1 | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/helpers.build.psm1 b/helpers.build.psm1 index c6a0d9ec7..9a6bafd4f 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -629,8 +629,14 @@ function Install-NodeJS { function Install-ProtobufRelease($arch) { Write-Verbose -Verbose "Fetching latest Protocol Buffers release info..." $release = Invoke-RestMethod -Uri "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" - $asset = $release.assets | Where-Object { $_.name -match "protoc-.*-$arch\.zip" } - if (-not $asset) { throw "No matching protoc binary found for $arch" } + $assets = @($release.assets | Where-Object { $_.name -match "protoc-.*-$arch\.zip$" }) + if (-not $assets -or $assets.Count -eq 0) { + throw "No matching protoc binary found for $arch" + } + if ($assets.Count -gt 1) { + throw "Multiple matching protoc binaries found for $arch" + } + $asset = $assets[0] $downloadUrl = $asset.browser_download_url $zipPath = "$env:TEMP\protoc.zip" From d520a4265e485082179bab1d278198df215ffebc Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Tue, 24 Feb 2026 06:42:47 -0800 Subject: [PATCH 09/10] Update helpers.build.psm1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- helpers.build.psm1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helpers.build.psm1 b/helpers.build.psm1 index 9a6bafd4f..f389a420f 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -638,7 +638,8 @@ function Install-ProtobufRelease($arch) { } $asset = $assets[0] $downloadUrl = $asset.browser_download_url - $zipPath = "$env:TEMP\protoc.zip" + $tempDir = [System.IO.Path]::GetTempPath() + $zipPath = Join-Path -Path $tempDir -ChildPath ("protoc-{0}.zip" -f [System.Guid]::NewGuid()) Write-Host "Downloading protoc from $downloadUrl..." Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath From 46ca9615994c647af1deae9813c7af1282fbff32 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Tue, 24 Feb 2026 06:43:01 -0800 Subject: [PATCH 10/10] Update helpers.build.psm1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- helpers.build.psm1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/helpers.build.psm1 b/helpers.build.psm1 index f389a420f..aac96e182 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -653,6 +653,10 @@ function Install-ProtobufRelease($arch) { Write-Host "Extracting protoc to $installDir..." Expand-Archive -Path $zipPath -DestinationPath $installDir -Force + # Clean up downloaded archive to avoid leaving temporary files behind + if (Test-Path $zipPath) { + Remove-Item -Path $zipPath -Force -ErrorAction SilentlyContinue + } $env:PATH = "$installDir" + [System.IO.Path]::DirectorySeparatorChar + "bin" + [System.IO.Path]::PathSeparator + $env:PATH Write-Host "Verifying protoc installation..."