@@ -626,6 +626,44 @@ function Install-NodeJS {
626626 }
627627}
628628
629+ function Install-ProtobufRelease ($arch ) {
630+ Write-Verbose - Verbose " Fetching latest Protocol Buffers release info..."
631+ $release = Invoke-RestMethod - Uri " https://api.github.com/repos/protocolbuffers/protobuf/releases/latest"
632+ $assets = @ ($release.assets | Where-Object { $_.name -match " protoc-.*-$arch \.zip$" })
633+ if (-not $assets -or $assets.Count -eq 0 ) {
634+ throw " No matching protoc binary found for $arch "
635+ }
636+ if ($assets.Count -gt 1 ) {
637+ throw " Multiple matching protoc binaries found for $arch "
638+ }
639+ $asset = $assets [0 ]
640+ $downloadUrl = $asset.browser_download_url
641+ $tempDir = [System.IO.Path ]::GetTempPath()
642+ $zipPath = Join-Path - Path $tempDir - ChildPath (" protoc-{0}.zip" -f [System.Guid ]::NewGuid())
643+
644+ Write-Host " Downloading protoc from $downloadUrl ..."
645+ Invoke-WebRequest - Uri $downloadUrl - OutFile $zipPath
646+ $installDir = if ($IsWindows ) {
647+ " $env: USERPROFILE \protoc"
648+ } else {
649+ " $env: HOME /protoc"
650+ }
651+ if (-not (Test-Path $installDir )) { New-Item - ItemType Directory - Path $installDir | Out-Null }
652+
653+ Write-Host " Extracting protoc to $installDir ..."
654+ Expand-Archive - Path $zipPath - DestinationPath $installDir - Force
655+
656+ # Clean up downloaded archive to avoid leaving temporary files behind
657+ if (Test-Path $zipPath ) {
658+ Remove-Item - Path $zipPath - Force - ErrorAction SilentlyContinue
659+ }
660+ $env: PATH = " $installDir " + [System.IO.Path ]::DirectorySeparatorChar + " bin" + [System.IO.Path ]::PathSeparator + $env: PATH
661+
662+ Write-Host " Verifying protoc installation..."
663+ Write-Host (Get-Command protoc | Out-String )
664+ Write-Host " protoc version: $ ( protoc -- version) "
665+ }
666+
629667function Install-Protobuf {
630668 <#
631669 . SYNOPSIS
@@ -636,8 +674,9 @@ function Install-Protobuf {
636674 param ()
637675
638676 process {
639- if (Test-CommandAvailable - Name ' protoc' ) {
640- Write-Verbose " Protobuf already installed."
677+ # if ADO, we install the latest version
678+ if ($null -eq $env: TF_BUILD -and (Test-CommandAvailable - Name ' protoc' )) {
679+ Write-Verbose - Verbose " Protobuf already installed: $ ( protoc -- version) "
641680 return
642681 }
643682
@@ -649,7 +688,12 @@ function Install-Protobuf {
649688 Write-Warning " Homebrew not found, please install Protobuf manually"
650689 }
651690 } elseif ($IsWindows ) {
652- if (Test-CommandAvailable - Name ' winget' ) {
691+ if ($env: TF_BUILD ) {
692+ Write-Verbose - Verbose " Running in Azure DevOps, installing from zip"
693+ $arch = if ([Environment ]::Is64BitOperatingSystem) { " win64" } else { " win32" }
694+ Install-ProtobufRelease - arch $arch
695+ }
696+ elseif (Test-CommandAvailable - Name ' winget' ) {
653697 Write-Verbose - Verbose " Using winget to install Protobuf"
654698 winget install Google.Protobuf -- accept- source- agreements -- accept- package- agreements -- source winget -- force
655699 # need to add to PATH
@@ -663,9 +707,20 @@ function Install-Protobuf {
663707 Write-Warning " winget not found, please install Protobuf manually"
664708 }
665709 } else {
666- if (Test-CommandAvailable - Name ' apt' ) {
710+ if ($env: TF_BUILD ) {
711+ Write-Verbose - Verbose " Running in Azure DevOps on Linux, installing from zip"
712+ # check if ARM64 or x64
713+ $arch = if ([System.Runtime.InteropServices.RuntimeInformation ]::ProcessArchitecture -eq [System.Runtime.InteropServices.Architecture ]::Arm64) {
714+ " linux-aarch_64"
715+ } else {
716+ " linux-x86_64"
717+ }
718+ Install-ProtobufRelease - arch $arch
719+ } elseif (Test-CommandAvailable - Name ' apt' ) {
667720 Write-Verbose - Verbose " Using apt to install Protobuf"
668721 sudo apt install - y protobuf- compiler
722+ Write-Verbose - Verbose (Get-Command protoc | Out-String )
723+ Write-Verbose - Verbose " protoc version: $ ( protoc -- version) "
669724 } else {
670725 Write-Warning " apt not found, please install Protobuf manually"
671726 }
0 commit comments