init-tools-native.ps1 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <#
  2. .SYNOPSIS
  3. Entry point script for installing native tools
  4. .DESCRIPTION
  5. Reads $RepoRoot\global.json file to determine native assets to install
  6. and executes installers for those tools
  7. .PARAMETER BaseUri
  8. Base file directory or Url from which to acquire tool archives
  9. .PARAMETER InstallDirectory
  10. Directory to install native toolset. This is a command-line override for the default
  11. Install directory precedence order:
  12. - InstallDirectory command-line override
  13. - NETCOREENG_INSTALL_DIRECTORY environment variable
  14. - (default) %USERPROFILE%/.netcoreeng/native
  15. .PARAMETER Clean
  16. Switch specifying to not install anything, but cleanup native asset folders
  17. .PARAMETER Force
  18. Clean and then install tools
  19. .PARAMETER DownloadRetries
  20. Total number of retry attempts
  21. .PARAMETER RetryWaitTimeInSeconds
  22. Wait time between retry attempts in seconds
  23. .PARAMETER GlobalJsonFile
  24. File path to global.json file
  25. .PARAMETER PathPromotion
  26. Optional switch to enable either promote native tools specified in the global.json to the path (in Azure Pipelines)
  27. or break the build if a native tool is not found on the path (on a local dev machine)
  28. .NOTES
  29. #>
  30. [CmdletBinding(PositionalBinding=$false)]
  31. Param (
  32. [string] $BaseUri = 'https://netcorenativeassets.blob.core.windows.net/resource-packages/external',
  33. [string] $InstallDirectory,
  34. [switch] $Clean = $False,
  35. [switch] $Force = $False,
  36. [int] $DownloadRetries = 5,
  37. [int] $RetryWaitTimeInSeconds = 30,
  38. [string] $GlobalJsonFile,
  39. [switch] $PathPromotion
  40. )
  41. if (!$GlobalJsonFile) {
  42. $GlobalJsonFile = Join-Path (Get-Item $PSScriptRoot).Parent.Parent.FullName 'global.json'
  43. }
  44. Set-StrictMode -version 2.0
  45. $ErrorActionPreference='Stop'
  46. . $PSScriptRoot\pipeline-logging-functions.ps1
  47. Import-Module -Name (Join-Path $PSScriptRoot 'native\CommonLibrary.psm1')
  48. try {
  49. # Define verbose switch if undefined
  50. $Verbose = $VerbosePreference -Eq 'Continue'
  51. $EngCommonBaseDir = Join-Path $PSScriptRoot 'native\'
  52. $NativeBaseDir = $InstallDirectory
  53. if (!$NativeBaseDir) {
  54. $NativeBaseDir = CommonLibrary\Get-NativeInstallDirectory
  55. }
  56. $Env:CommonLibrary_NativeInstallDir = $NativeBaseDir
  57. $InstallBin = Join-Path $NativeBaseDir 'bin'
  58. $InstallerPath = Join-Path $EngCommonBaseDir 'install-tool.ps1'
  59. # Process tools list
  60. Write-Host "Processing $GlobalJsonFile"
  61. If (-Not (Test-Path $GlobalJsonFile)) {
  62. Write-Host "Unable to find '$GlobalJsonFile'"
  63. exit 0
  64. }
  65. $NativeTools = Get-Content($GlobalJsonFile) -Raw |
  66. ConvertFrom-Json |
  67. Select-Object -Expand 'native-tools' -ErrorAction SilentlyContinue
  68. if ($NativeTools) {
  69. if ($PathPromotion -eq $True) {
  70. if ($env:SYSTEM_TEAMPROJECT) { # check to see if we're in an Azure pipelines build
  71. $NativeTools.PSObject.Properties | ForEach-Object {
  72. $ToolName = $_.Name
  73. $ToolVersion = $_.Value
  74. $InstalledTools = @{}
  75. if ((Get-Command "$ToolName" -ErrorAction SilentlyContinue) -eq $null) {
  76. if ($ToolVersion -eq "latest") {
  77. $ToolVersion = ""
  78. }
  79. $ArcadeToolsDirectory = "C:\arcade-tools"
  80. if (-not (Test-Path $ArcadeToolsDirectory)) {
  81. Write-Error "Arcade tools directory '$ArcadeToolsDirectory' was not found; artifacts were not properly installed."
  82. exit 1
  83. }
  84. $ToolDirectories = (Get-ChildItem -Path "$ArcadeToolsDirectory" -Filter "$ToolName-$ToolVersion*" | Sort-Object -Descending)
  85. if ($ToolDirectories -eq $null) {
  86. Write-Error "Unable to find directory for $ToolName $ToolVersion; please make sure the tool is installed on this image."
  87. exit 1
  88. }
  89. $ToolDirectory = $ToolDirectories[0]
  90. $BinPathFile = "$($ToolDirectory.FullName)\binpath.txt"
  91. if (-not (Test-Path -Path "$BinPathFile")) {
  92. Write-Error "Unable to find binpath.txt in '$($ToolDirectory.FullName)' ($ToolName $ToolVersion); artifact is either installed incorrectly or is not a bootstrappable tool."
  93. exit 1
  94. }
  95. $BinPath = Get-Content "$BinPathFile"
  96. $ToolPath = Convert-Path -Path $BinPath
  97. Write-Host "Adding $ToolName to the path ($ToolPath)..."
  98. Write-Host "##vso[task.prependpath]$ToolPath"
  99. $env:PATH = "$ToolPath;$env:PATH"
  100. $InstalledTools += @{ $ToolName = $ToolDirectory.FullName }
  101. }
  102. }
  103. return $InstalledTools
  104. } else {
  105. $NativeTools.PSObject.Properties | ForEach-Object {
  106. $ToolName = $_.Name
  107. $ToolVersion = $_.Value
  108. if ((Get-Command "$ToolName" -ErrorAction SilentlyContinue) -eq $null) {
  109. Write-PipelineTelemetryError -Category 'NativeToolsBootstrap' -Message "$ToolName not found on path. Please install $ToolName $ToolVersion before proceeding."
  110. }
  111. }
  112. exit 0
  113. }
  114. } else {
  115. $NativeTools.PSObject.Properties | ForEach-Object {
  116. $ToolName = $_.Name
  117. $ToolVersion = $_.Value
  118. $LocalInstallerArguments = @{ ToolName = "$ToolName" }
  119. $LocalInstallerArguments += @{ InstallPath = "$InstallBin" }
  120. $LocalInstallerArguments += @{ BaseUri = "$BaseUri" }
  121. $LocalInstallerArguments += @{ CommonLibraryDirectory = "$EngCommonBaseDir" }
  122. $LocalInstallerArguments += @{ Version = "$ToolVersion" }
  123. if ($Verbose) {
  124. $LocalInstallerArguments += @{ Verbose = $True }
  125. }
  126. if (Get-Variable 'Force' -ErrorAction 'SilentlyContinue') {
  127. if($Force) {
  128. $LocalInstallerArguments += @{ Force = $True }
  129. }
  130. }
  131. if ($Clean) {
  132. $LocalInstallerArguments += @{ Clean = $True }
  133. }
  134. Write-Verbose "Installing $ToolName version $ToolVersion"
  135. Write-Verbose "Executing '$InstallerPath $($LocalInstallerArguments.Keys.ForEach({"-$_ '$($LocalInstallerArguments.$_)'"}) -join ' ')'"
  136. & $InstallerPath @LocalInstallerArguments
  137. if ($LASTEXITCODE -Ne "0") {
  138. $errMsg = "$ToolName installation failed"
  139. if ((Get-Variable 'DoNotAbortNativeToolsInstallationOnFailure' -ErrorAction 'SilentlyContinue') -and $DoNotAbortNativeToolsInstallationOnFailure) {
  140. $showNativeToolsWarning = $true
  141. if ((Get-Variable 'DoNotDisplayNativeToolsInstallationWarnings' -ErrorAction 'SilentlyContinue') -and $DoNotDisplayNativeToolsInstallationWarnings) {
  142. $showNativeToolsWarning = $false
  143. }
  144. if ($showNativeToolsWarning) {
  145. Write-Warning $errMsg
  146. }
  147. $toolInstallationFailure = $true
  148. } else {
  149. # We cannot change this to Write-PipelineTelemetryError because of https://github.com/dotnet/arcade/issues/4482
  150. Write-Host $errMsg
  151. exit 1
  152. }
  153. }
  154. }
  155. if ((Get-Variable 'toolInstallationFailure' -ErrorAction 'SilentlyContinue') -and $toolInstallationFailure) {
  156. # We cannot change this to Write-PipelineTelemetryError because of https://github.com/dotnet/arcade/issues/4482
  157. Write-Host 'Native tools bootstrap failed'
  158. exit 1
  159. }
  160. }
  161. }
  162. else {
  163. Write-Host 'No native tools defined in global.json'
  164. exit 0
  165. }
  166. if ($Clean) {
  167. exit 0
  168. }
  169. if (Test-Path $InstallBin) {
  170. Write-Host 'Native tools are available from ' (Convert-Path -Path $InstallBin)
  171. Write-Host "##vso[task.prependpath]$(Convert-Path -Path $InstallBin)"
  172. return $InstallBin
  173. }
  174. elseif (-not ($PathPromotion)) {
  175. Write-PipelineTelemetryError -Category 'NativeToolsBootstrap' -Message 'Native tools install directory does not exist, installation failed'
  176. exit 1
  177. }
  178. exit 0
  179. }
  180. catch {
  181. Write-Host $_.ScriptStackTrace
  182. Write-PipelineTelemetryError -Category 'NativeToolsBootstrap' -Message $_
  183. ExitWithExitCode 1
  184. }