run.ps1 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #!/usr/bin/env powershell
  2. #requires -version 4
  3. <#
  4. .SYNOPSIS
  5. Executes KoreBuild commands.
  6. .DESCRIPTION
  7. Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`.
  8. .PARAMETER Command
  9. The KoreBuild command to run.
  10. .PARAMETER Path
  11. The folder to build. Defaults to the folder containing this script.
  12. .PARAMETER Channel
  13. The channel of KoreBuild to download. Overrides the value from the config file.
  14. .PARAMETER DotNetHome
  15. The directory where .NET Core tools will be stored.
  16. .PARAMETER ToolsSource
  17. The base url where build tools can be downloaded. Overrides the value from the config file.
  18. .PARAMETER Update
  19. Updates KoreBuild to the latest version even if a lock file is present.
  20. .PARAMETER ConfigFile
  21. The path to the configuration file that stores values. Defaults to korebuild.json.
  22. .PARAMETER Arguments
  23. Arguments to be passed to the command
  24. .NOTES
  25. This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be.
  26. When the lockfile is not present, KoreBuild will create one using latest available version from $Channel.
  27. The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set
  28. in the file are overridden by command line parameters.
  29. .EXAMPLE
  30. Example config file:
  31. ```json
  32. {
  33. "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json",
  34. "channel": "dev",
  35. "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools"
  36. }
  37. ```
  38. #>
  39. [CmdletBinding(PositionalBinding = $false)]
  40. param(
  41. [Parameter(Mandatory=$true, Position = 0)]
  42. [string]$Command,
  43. [string]$Path = $PSScriptRoot,
  44. [Alias('c')]
  45. [string]$Channel,
  46. [Alias('d')]
  47. [string]$DotNetHome,
  48. [Alias('s')]
  49. [string]$ToolsSource,
  50. [Alias('u')]
  51. [switch]$Update,
  52. [string]$ConfigFile,
  53. [Parameter(ValueFromRemainingArguments = $true)]
  54. [string[]]$Arguments
  55. )
  56. Set-StrictMode -Version 2
  57. $ErrorActionPreference = 'Stop'
  58. #
  59. # Functions
  60. #
  61. function Get-KoreBuild {
  62. $lockFile = Join-Path $Path 'korebuild-lock.txt'
  63. if (!(Test-Path $lockFile) -or $Update) {
  64. Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile
  65. }
  66. $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1
  67. if (!$version) {
  68. Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'"
  69. }
  70. $version = $version.TrimStart('version:').Trim()
  71. $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version)
  72. if (!(Test-Path $korebuildPath)) {
  73. Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version"
  74. New-Item -ItemType Directory -Path $korebuildPath | Out-Null
  75. $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip"
  76. try {
  77. $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip"
  78. Get-RemoteFile $remotePath $tmpfile
  79. if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) {
  80. # Use built-in commands where possible as they are cross-plat compatible
  81. Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath
  82. }
  83. else {
  84. # Fallback to old approach for old installations of PowerShell
  85. Add-Type -AssemblyName System.IO.Compression.FileSystem
  86. [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath)
  87. }
  88. }
  89. catch {
  90. Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore
  91. throw
  92. }
  93. finally {
  94. Remove-Item $tmpfile -ErrorAction Ignore
  95. }
  96. }
  97. return $korebuildPath
  98. }
  99. function Join-Paths([string]$path, [string[]]$childPaths) {
  100. $childPaths | ForEach-Object { $path = Join-Path $path $_ }
  101. return $path
  102. }
  103. function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) {
  104. if ($RemotePath -notlike 'http*') {
  105. Copy-Item $RemotePath $LocalPath
  106. return
  107. }
  108. $retries = 10
  109. while ($retries -gt 0) {
  110. $retries -= 1
  111. try {
  112. Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath
  113. return
  114. }
  115. catch {
  116. Write-Verbose "Request failed. $retries retries remaining"
  117. }
  118. }
  119. Write-Error "Download failed: '$RemotePath'."
  120. }
  121. #
  122. # Main
  123. #
  124. # Load configuration or set defaults
  125. $Path = Resolve-Path $Path
  126. if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' }
  127. if (Test-Path $ConfigFile) {
  128. try {
  129. $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json
  130. if ($config) {
  131. if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel }
  132. if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource}
  133. }
  134. } catch {
  135. Write-Warning "$ConfigFile could not be read. Its settings will be ignored."
  136. Write-Warning $Error[0]
  137. }
  138. }
  139. if (!$DotNetHome) {
  140. $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } `
  141. elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} `
  142. elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}`
  143. else { Join-Path $PSScriptRoot '.dotnet'}
  144. }
  145. if (!$Channel) { $Channel = 'dev' }
  146. if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' }
  147. # Execute
  148. $korebuildPath = Get-KoreBuild
  149. Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1')
  150. try {
  151. Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile
  152. Invoke-KoreBuildCommand $Command @Arguments
  153. }
  154. finally {
  155. Remove-Module 'KoreBuild' -ErrorAction Ignore
  156. }