|
1 |
| -$ErrorActionPreference = "Stop" |
2 |
| - |
3 |
| -function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) |
4 |
| -{ |
5 |
| - while($true) |
6 |
| - { |
7 |
| - try |
8 |
| - { |
9 |
| - Invoke-WebRequest $url -OutFile $downloadLocation |
10 |
| - break |
11 |
| - } |
12 |
| - catch |
13 |
| - { |
14 |
| - $exceptionMessage = $_.Exception.Message |
15 |
| - Write-Host "Failed to download '$url': $exceptionMessage" |
16 |
| - if ($retries -gt 0) { |
17 |
| - $retries-- |
18 |
| - Write-Host "Waiting 10 seconds before retrying. Retries left: $retries" |
19 |
| - Start-Sleep -Seconds 10 |
| 1 | +#!/usr/bin/env powershell |
| 2 | +#requires -version 4 |
| 3 | + |
| 4 | +<# |
| 5 | +.SYNOPSIS |
| 6 | +Build this repository |
| 7 | +
|
| 8 | +.DESCRIPTION |
| 9 | +Downloads korebuild if required. Then builds the repository. |
| 10 | +
|
| 11 | +.PARAMETER Path |
| 12 | +The folder to build. Defaults to the folder containing this script. |
| 13 | +
|
| 14 | +.PARAMETER Channel |
| 15 | +The channel of KoreBuild to download. Overrides the value from the config file. |
| 16 | +
|
| 17 | +.PARAMETER DotNetHome |
| 18 | +The directory where .NET Core tools will be stored. |
| 19 | +
|
| 20 | +.PARAMETER ToolsSource |
| 21 | +The base url where build tools can be downloaded. Overrides the value from the config file. |
| 22 | +
|
| 23 | +.PARAMETER Update |
| 24 | +Updates KoreBuild to the latest version even if a lock file is present. |
| 25 | +
|
| 26 | +.PARAMETER ConfigFile |
| 27 | +The path to the configuration file that stores values. Defaults to version.xml. |
| 28 | +
|
| 29 | +.PARAMETER MSBuildArgs |
| 30 | +Arguments to be passed to MSBuild |
| 31 | +
|
| 32 | +.NOTES |
| 33 | +This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. |
| 34 | +When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. |
| 35 | +
|
| 36 | +The $ConfigFile is expected to be an XML file. It is optional, and the configuration values in it are optional as well. |
| 37 | +
|
| 38 | +.EXAMPLE |
| 39 | +Example config file: |
| 40 | +```xml |
| 41 | +<!-- version.xml --> |
| 42 | +<Project> |
| 43 | + <PropertyGroup> |
| 44 | + <KoreBuildChannel>dev</KoreBuildChannel> |
| 45 | + <KoreBuildToolsSource>https://aspnetcore.blob.core.windows.net/buildtools</KoreBuildToolsSource> |
| 46 | + </PropertyGroup> |
| 47 | +</Project> |
| 48 | +``` |
| 49 | +#> |
| 50 | +[CmdletBinding(PositionalBinding = $false)] |
| 51 | +param( |
| 52 | + [string]$Path = $PSScriptRoot, |
| 53 | + [Alias('c')] |
| 54 | + [string]$Channel, |
| 55 | + [Alias('d')] |
| 56 | + [string]$DotNetHome, |
| 57 | + [Alias('s')] |
| 58 | + [string]$ToolsSource, |
| 59 | + [Alias('u')] |
| 60 | + [switch]$Update, |
| 61 | + [string]$ConfigFile = (Join-Path $PSScriptRoot 'version.xml'), |
| 62 | + [Parameter(ValueFromRemainingArguments = $true)] |
| 63 | + [string[]]$MSBuildArgs |
| 64 | +) |
| 65 | + |
| 66 | +Set-StrictMode -Version 2 |
| 67 | +$ErrorActionPreference = 'Stop' |
| 68 | + |
| 69 | +# |
| 70 | +# Functions |
| 71 | +# |
| 72 | + |
| 73 | +function Get-KoreBuild { |
| 74 | + |
| 75 | + $lockFile = Join-Path $Path 'korebuild-lock.txt' |
| 76 | + |
| 77 | + if (!(Test-Path $lockFile) -or $Update) { |
| 78 | + Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile |
| 79 | + } |
| 80 | + |
| 81 | + $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 |
| 82 | + if (!$version) { |
| 83 | + Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'" |
| 84 | + } |
| 85 | + $version = $version.TrimStart('version:').Trim() |
| 86 | + $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) |
20 | 87 |
|
| 88 | + if (!(Test-Path $korebuildPath)) { |
| 89 | + Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" |
| 90 | + New-Item -ItemType Directory -Path $korebuildPath | Out-Null |
| 91 | + $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip" |
| 92 | + |
| 93 | + try { |
| 94 | + $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" |
| 95 | + Get-RemoteFile $remotePath $tmpfile |
| 96 | + if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { |
| 97 | + # Use built-in commands where possible as they are cross-plat compatible |
| 98 | + Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath |
21 | 99 | }
|
22 |
| - else |
23 |
| - { |
24 |
| - $exception = $_.Exception |
25 |
| - throw $exception |
| 100 | + else { |
| 101 | + # Fallback to old approach for old installations of PowerShell |
| 102 | + Add-Type -AssemblyName System.IO.Compression.FileSystem |
| 103 | + [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath) |
26 | 104 | }
|
27 | 105 | }
|
| 106 | + catch { |
| 107 | + Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore |
| 108 | + throw |
| 109 | + } |
| 110 | + finally { |
| 111 | + Remove-Item $tmpfile -ErrorAction Ignore |
| 112 | + } |
28 | 113 | }
|
| 114 | + |
| 115 | + return $korebuildPath |
| 116 | +} |
| 117 | + |
| 118 | +function Join-Paths([string]$path, [string[]]$childPaths) { |
| 119 | + $childPaths | ForEach-Object { $path = Join-Path $path $_ } |
| 120 | + return $path |
29 | 121 | }
|
30 | 122 |
|
31 |
| -cd $PSScriptRoot |
| 123 | +function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { |
| 124 | + if ($RemotePath -notlike 'http*') { |
| 125 | + Copy-Item $RemotePath $LocalPath |
| 126 | + return |
| 127 | + } |
32 | 128 |
|
33 |
| -$repoFolder = $PSScriptRoot |
34 |
| -$env:REPO_FOLDER = $repoFolder |
| 129 | + $retries = 10 |
| 130 | + while ($retries -gt 0) { |
| 131 | + $retries -= 1 |
| 132 | + try { |
| 133 | + Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath |
| 134 | + return |
| 135 | + } |
| 136 | + catch { |
| 137 | + Write-Verbose "Request failed. $retries retries remaining" |
| 138 | + } |
| 139 | + } |
35 | 140 |
|
36 |
| -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" |
37 |
| -if ($env:KOREBUILD_ZIP) |
38 |
| -{ |
39 |
| - $koreBuildZip=$env:KOREBUILD_ZIP |
| 141 | + Write-Error "Download failed: '$RemotePath'." |
40 | 142 | }
|
41 | 143 |
|
42 |
| -$buildFolder = ".build" |
43 |
| -$buildFile="$buildFolder\KoreBuild.ps1" |
| 144 | +# |
| 145 | +# Main |
| 146 | +# |
44 | 147 |
|
45 |
| -if (!(Test-Path $buildFolder)) { |
46 |
| - Write-Host "Downloading KoreBuild from $koreBuildZip" |
| 148 | +# Load configuration or set defaults |
47 | 149 |
|
48 |
| - $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid() |
49 |
| - New-Item -Path "$tempFolder" -Type directory | Out-Null |
| 150 | +if (Test-Path $ConfigFile) { |
| 151 | + [xml] $config = Get-Content $ConfigFile |
| 152 | + if (!($Channel)) { [string] $Channel = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildChannel' } |
| 153 | + if (!($ToolsSource)) { [string] $ToolsSource = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildToolsSource' } |
| 154 | +} |
50 | 155 |
|
51 |
| - $localZipFile="$tempFolder\korebuild.zip" |
| 156 | +if (!$DotNetHome) { |
| 157 | + $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } ` |
| 158 | + elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} ` |
| 159 | + elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}` |
| 160 | + else { Join-Path $PSScriptRoot '.dotnet'} |
| 161 | +} |
52 | 162 |
|
53 |
| - DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6 |
| 163 | +if (!$Channel) { $Channel = 'dev' } |
| 164 | +if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } |
54 | 165 |
|
55 |
| - Add-Type -AssemblyName System.IO.Compression.FileSystem |
56 |
| - [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) |
| 166 | +# Execute |
57 | 167 |
|
58 |
| - New-Item -Path "$buildFolder" -Type directory | Out-Null |
59 |
| - copy-item "$tempFolder\**\build\*" $buildFolder -Recurse |
| 168 | +$korebuildPath = Get-KoreBuild |
| 169 | +Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') |
60 | 170 |
|
61 |
| - # Cleanup |
62 |
| - if (Test-Path $tempFolder) { |
63 |
| - Remove-Item -Recurse -Force $tempFolder |
64 |
| - } |
| 171 | +try { |
| 172 | + Install-Tools $ToolsSource $DotNetHome |
| 173 | + Invoke-RepositoryBuild $Path @MSBuildArgs |
| 174 | +} |
| 175 | +finally { |
| 176 | + Remove-Module 'KoreBuild' -ErrorAction Ignore |
65 | 177 | }
|
66 |
| - |
67 |
| -&"$buildFile" @args |
|
0 commit comments