init-tools-native.ps1 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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. $ArcadeToolsDirectory = "$env:SYSTEMDRIVE\arcade-tools"
  71. if (Test-Path $ArcadeToolsDirectory) { # if this directory exists, we should use native tools on machine
  72. $NativeTools.PSObject.Properties | ForEach-Object {
  73. $ToolName = $_.Name
  74. $ToolVersion = $_.Value
  75. $InstalledTools = @{}
  76. if ((Get-Command "$ToolName" -ErrorAction SilentlyContinue) -eq $null) {
  77. if ($ToolVersion -eq "latest") {
  78. $ToolVersion = ""
  79. }
  80. $ToolDirectories = (Get-ChildItem -Path "$ArcadeToolsDirectory" -Filter "$ToolName-$ToolVersion*" | Sort-Object -Descending)
  81. if ($ToolDirectories -eq $null) {
  82. Write-Error "Unable to find directory for $ToolName $ToolVersion; please make sure the tool is installed on this image."
  83. exit 1
  84. }
  85. $ToolDirectory = $ToolDirectories[0]
  86. $BinPathFile = "$($ToolDirectory.FullName)\binpath.txt"
  87. if (-not (Test-Path -Path "$BinPathFile")) {
  88. Write-Error "Unable to find binpath.txt in '$($ToolDirectory.FullName)' ($ToolName $ToolVersion); artifact is either installed incorrectly or is not a bootstrappable tool."
  89. exit 1
  90. }
  91. $BinPath = Get-Content "$BinPathFile"
  92. $ToolPath = Convert-Path -Path $BinPath
  93. Write-Host "Adding $ToolName to the path ($ToolPath)..."
  94. Write-Host "##vso[task.prependpath]$ToolPath"
  95. $env:PATH = "$ToolPath;$env:PATH"
  96. $InstalledTools += @{ $ToolName = $ToolDirectory.FullName }
  97. }
  98. }
  99. return $InstalledTools
  100. } else {
  101. $NativeTools.PSObject.Properties | ForEach-Object {
  102. $ToolName = $_.Name
  103. $ToolVersion = $_.Value
  104. if ((Get-Command "$ToolName" -ErrorAction SilentlyContinue) -eq $null) {
  105. Write-PipelineTelemetryError -Category 'NativeToolsBootstrap' -Message "$ToolName not found on path. Please install $ToolName $ToolVersion before proceeding."
  106. Write-PipelineTelemetryError -Category 'NativeToolsBootstrap' -Message "If this is running on a build machine, the arcade-tools directory was not found, which means there's an error with the image."
  107. }
  108. }
  109. exit 0
  110. }
  111. } else {
  112. $NativeTools.PSObject.Properties | ForEach-Object {
  113. $ToolName = $_.Name
  114. $ToolVersion = $_.Value
  115. $LocalInstallerArguments = @{ ToolName = "$ToolName" }
  116. $LocalInstallerArguments += @{ InstallPath = "$InstallBin" }
  117. $LocalInstallerArguments += @{ BaseUri = "$BaseUri" }
  118. $LocalInstallerArguments += @{ CommonLibraryDirectory = "$EngCommonBaseDir" }
  119. $LocalInstallerArguments += @{ Version = "$ToolVersion" }
  120. if ($Verbose) {
  121. $LocalInstallerArguments += @{ Verbose = $True }
  122. }
  123. if (Get-Variable 'Force' -ErrorAction 'SilentlyContinue') {
  124. if($Force) {
  125. $LocalInstallerArguments += @{ Force = $True }
  126. }
  127. }
  128. if ($Clean) {
  129. $LocalInstallerArguments += @{ Clean = $True }
  130. }
  131. Write-Verbose "Installing $ToolName version $ToolVersion"
  132. Write-Verbose "Executing '$InstallerPath $($LocalInstallerArguments.Keys.ForEach({"-$_ '$($LocalInstallerArguments.$_)'"}) -join ' ')'"
  133. & $InstallerPath @LocalInstallerArguments
  134. if ($LASTEXITCODE -Ne "0") {
  135. $errMsg = "$ToolName installation failed"
  136. if ((Get-Variable 'DoNotAbortNativeToolsInstallationOnFailure' -ErrorAction 'SilentlyContinue') -and $DoNotAbortNativeToolsInstallationOnFailure) {
  137. $showNativeToolsWarning = $true
  138. if ((Get-Variable 'DoNotDisplayNativeToolsInstallationWarnings' -ErrorAction 'SilentlyContinue') -and $DoNotDisplayNativeToolsInstallationWarnings) {
  139. $showNativeToolsWarning = $false
  140. }
  141. if ($showNativeToolsWarning) {
  142. Write-Warning $errMsg
  143. }
  144. $toolInstallationFailure = $true
  145. } else {
  146. # We cannot change this to Write-PipelineTelemetryError because of https://github.com/dotnet/arcade/issues/4482
  147. Write-Host $errMsg
  148. exit 1
  149. }
  150. }
  151. }
  152. if ((Get-Variable 'toolInstallationFailure' -ErrorAction 'SilentlyContinue') -and $toolInstallationFailure) {
  153. # We cannot change this to Write-PipelineTelemetryError because of https://github.com/dotnet/arcade/issues/4482
  154. Write-Host 'Native tools bootstrap failed'
  155. exit 1
  156. }
  157. }
  158. }
  159. else {
  160. Write-Host 'No native tools defined in global.json'
  161. exit 0
  162. }
  163. if ($Clean) {
  164. exit 0
  165. }
  166. if (Test-Path $InstallBin) {
  167. Write-Host 'Native tools are available from ' (Convert-Path -Path $InstallBin)
  168. Write-Host "##vso[task.prependpath]$(Convert-Path -Path $InstallBin)"
  169. return $InstallBin
  170. }
  171. elseif (-not ($PathPromotion)) {
  172. Write-PipelineTelemetryError -Category 'NativeToolsBootstrap' -Message 'Native tools install directory does not exist, installation failed'
  173. exit 1
  174. }
  175. exit 0
  176. }
  177. catch {
  178. Write-Host $_.ScriptStackTrace
  179. Write-PipelineTelemetryError -Category 'NativeToolsBootstrap' -Message $_
  180. ExitWithExitCode 1
  181. }