Update bootstrappers to use the compiled version of KoreBuild

[ci skip]
This commit is contained in:
Nate McMaster 2017-07-25 16:34:44 -07:00
Родитель 10b2e70f4c
Коммит b9153be745
7 изменённых файлов: 362 добавлений и 100 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -30,3 +30,4 @@ project.lock.json
/.vs/ /.vs/
.vscode/ .vscode/
global.json global.json
korebuild-lock.txt

222
build.ps1
Просмотреть файл

@ -1,67 +1,177 @@
$ErrorActionPreference = "Stop" #!/usr/bin/env powershell
#requires -version 4
function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) <#
{ .SYNOPSIS
while($true) Build this repository
{
try
{
Invoke-WebRequest $url -OutFile $downloadLocation
break
}
catch
{
$exceptionMessage = $_.Exception.Message
Write-Host "Failed to download '$url': $exceptionMessage"
if ($retries -gt 0) {
$retries--
Write-Host "Waiting 10 seconds before retrying. Retries left: $retries"
Start-Sleep -Seconds 10
} .DESCRIPTION
else Downloads korebuild if required. Then builds the repository.
{
$exception = $_.Exception .PARAMETER Path
throw $exception The folder to build. Defaults to the folder containing this script.
}
} .PARAMETER Channel
} The channel of KoreBuild to download. Overrides the value from the config file.
.PARAMETER DotNetHome
The directory where .NET Core tools will be stored.
.PARAMETER ToolsSource
The base url where build tools can be downloaded. Overrides the value from the config file.
.PARAMETER Update
Updates KoreBuild to the latest version even if a lock file is present.
.PARAMETER ConfigFile
The path to the configuration file that stores values. Defaults to version.xml.
.PARAMETER MSBuildArgs
Arguments to be passed to MSBuild
.NOTES
This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be.
When the lockfile is not present, KoreBuild will create one using latest available version from $Channel.
The $ConfigFile is expected to be an XML file. It is optional, and the configuration values in it are optional as well.
.EXAMPLE
Example config file:
```xml
<!-- version.xml -->
<Project>
<PropertyGroup>
<KoreBuildChannel>dev</KoreBuildChannel>
<KoreBuildToolsSource>https://aspnetcore.blob.core.windows.net/buildtools</KoreBuildToolsSource>
</PropertyGroup>
</Project>
```
#>
[CmdletBinding(PositionalBinding = $false)]
param(
[string]$Path = $PSScriptRoot,
[Alias('c')]
[string]$Channel,
[Alias('d')]
[string]$DotNetHome,
[Alias('s')]
[string]$ToolsSource,
[Alias('u')]
[switch]$Update,
[string]$ConfigFile = (Join-Path $PSScriptRoot 'version.xml'),
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$MSBuildArgs
)
Set-StrictMode -Version 2
$ErrorActionPreference = 'Stop'
#
# Functions
#
function Get-KoreBuild {
$lockFile = Join-Path $Path 'korebuild-lock.txt'
if (!(Test-Path $lockFile) -or $Update) {
Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile
} }
cd $PSScriptRoot $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1
if (!$version) {
$repoFolder = $PSScriptRoot Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'"
$env:REPO_FOLDER = $repoFolder
$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip"
if ($env:KOREBUILD_ZIP)
{
$koreBuildZip=$env:KOREBUILD_ZIP
} }
$version = $version.TrimStart('version:').Trim()
$korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version)
$buildFolder = ".build" if (!(Test-Path $korebuildPath)) {
$buildFile="$buildFolder\KoreBuild.ps1" Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version"
New-Item -ItemType Directory -Path $korebuildPath | Out-Null
if (!(Test-Path $buildFolder)) { $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip"
Write-Host "Downloading KoreBuild from $koreBuildZip"
$tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid()
New-Item -Path "$tempFolder" -Type directory | Out-Null
$localZipFile="$tempFolder\korebuild.zip"
DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6
try {
$tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip"
Get-RemoteFile $remotePath $tmpfile
if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) {
# Use built-in commands where possible as they are cross-plat compatible
Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath
}
else {
# Fallback to old approach for old installations of PowerShell
Add-Type -AssemblyName System.IO.Compression.FileSystem Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath)
}
New-Item -Path "$buildFolder" -Type directory | Out-Null }
copy-item "$tempFolder\**\build\*" $buildFolder -Recurse catch {
Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore
# Cleanup throw
if (Test-Path $tempFolder) { }
Remove-Item -Recurse -Force $tempFolder finally {
Remove-Item $tmpfile -ErrorAction Ignore
} }
} }
&"$buildFile" @args return $korebuildPath
}
function Join-Paths([string]$path, [string[]]$childPaths) {
$childPaths | ForEach-Object { $path = Join-Path $path $_ }
return $path
}
function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) {
if ($RemotePath -notlike 'http*') {
Copy-Item $RemotePath $LocalPath
return
}
$retries = 10
while ($retries -gt 0) {
$retries -= 1
try {
Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath
return
}
catch {
Write-Verbose "Request failed. $retries retries remaining"
}
}
Write-Error "Download failed: '$RemotePath'."
}
#
# Main
#
# Load configuration or set defaults
if (Test-Path $ConfigFile) {
[xml] $config = Get-Content $ConfigFile
if (!($Channel)) { [string] $Channel = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildChannel' }
if (!($ToolsSource)) { [string] $ToolsSource = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildToolsSource' }
}
if (!$DotNetHome) {
$DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } `
elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} `
elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}`
else { Join-Path $PSScriptRoot '.dotnet'}
}
if (!$Channel) { $Channel = 'dev' }
if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' }
# Execute
$korebuildPath = Get-KoreBuild
Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1')
try {
Install-Tools $ToolsSource $DotNetHome
Invoke-RepositoryBuild $Path @MSBuildArgs
}
finally {
Remove-Module 'KoreBuild' -ErrorAction Ignore
}

224
build.sh
Просмотреть файл

@ -1,46 +1,196 @@
#!/usr/bin/env bash #!/usr/bin/env bash
repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $repoFolder
koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" set -euo pipefail
if [ ! -z $KOREBUILD_ZIP ]; then
koreBuildZip=$KOREBUILD_ZIP #
# variables
#
RESET="\033[0m"
RED="\033[0;31m"
MAGENTA="\033[0;95m"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
[ -z "${DOTNET_HOME:-}"] && DOTNET_HOME="$HOME/.dotnet"
config_file="$DIR/version.xml"
verbose=false
update=false
repo_path="$DIR"
channel=''
tools_source=''
#
# Functions
#
__usage() {
echo "Usage: $(basename ${BASH_SOURCE[0]}) [options] [[--] <MSBUILD_ARG>...]"
echo ""
echo "Arguments:"
echo " <MSBUILD_ARG>... Arguments passed to MSBuild. Variable number of arguments allowed."
echo ""
echo "Options:"
echo " --verbose Show verbose output."
echo " -c|--channel <CHANNEL> The channel of KoreBuild to download. Overrides the value from the config file.."
echo " --config-file <FILE> TThe path to the configuration file that stores values. Defaults to version.xml."
echo " -d|--dotnet-home <DIR> The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet."
echo " --path <PATH> The directory to build. Defaults to the directory containing the script."
echo " -s|--tools-source <URL> The base url where build tools can be downloaded. Overrides the value from the config file."
echo " -u|--update Update to the latest KoreBuild even if the lock file is present."
echo ""
echo "Description:"
echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be."
echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel."
if [[ "${1:-}" != '--no-exit' ]]; then
exit 2
fi
}
get_korebuild() {
local lock_file="$repo_path/korebuild-lock.txt"
if [ ! -f $lock_file ] || [ "$update" = true ]; then
__get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" $lock_file
fi
local version="$(grep 'version:*' -m 1 $lock_file)"
if [[ "$version" == '' ]]; then
__error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'"
return 1
fi
version="$(echo ${version#version:} | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version"
{
if [ ! -d "$korebuild_path" ]; then
mkdir -p "$korebuild_path"
local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip"
tmpfile="$(mktemp)"
echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}"
if __get_remote_file $remote_path $tmpfile; then
unzip -q -d "$korebuild_path" $tmpfile
fi
rm $tmpfile || true
fi fi
buildFolder=".build" source "$korebuild_path/KoreBuild.sh"
buildFile="$buildFolder/KoreBuild.sh" } || {
if [ -d "$korebuild_path" ]; then
if test ! -d $buildFolder; then echo "Cleaning up after failed installation"
echo "Downloading KoreBuild from $koreBuildZip" rm -rf "$korebuild_path" || true
tempFolder="/tmp/KoreBuild-$(uuidgen)"
mkdir $tempFolder
localZipFile="$tempFolder/korebuild.zip"
retries=6
until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null)
do
echo "Failed to download '$koreBuildZip'"
if [ "$retries" -le 0 ]; then
exit 1
fi fi
retries=$((retries - 1)) return 1
echo "Waiting 10 seconds before retrying. Retries left: $retries" }
sleep 10s }
__error() {
echo -e "${RED}$@${RESET}" 1>&2
}
__machine_has() {
hash "$1" > /dev/null 2>&1
return $?
}
__get_remote_file() {
local remote_path=$1
local local_path=$2
if [[ "$remote_path" != 'http'* ]]; then
cp $remote_path $local_path
return 0
fi
failed=false
if __machine_has wget; then
wget --tries 10 --quiet -O $local_path $remote_path || failed=true
fi
if [ "$failed" = true ] && __machine_has curl; then
failed=false
curl --retry 10 -sSL -f --create-dirs -o $local_path $remote_path || failed=true
fi
if [ "$failed" = true ]; then
__error "Download failed: $remote_path" 1>&2
return 1
fi
}
__read_dom () { local IFS=\> ; read -d \< ENTITY CONTENT ;}
#
# main
#
while [[ $# > 0 ]]; do
case $1 in
-\?|-h|--help)
__usage --no-exit
exit 0
;;
-c|--channel|-Channel)
shift
channel=${1:-}
[ -z "$channel" ] && __usage
;;
--config-file|-ConfigFile)
shift
config_file="${1:-}"
[ -z "$config_file" ] && __usage
;;
-d|--dotnet-home|-DotNetHome)
shift
DOTNET_HOME=${1:-}
[ -z "$DOTNET_HOME" ] && __usage
;;
--path|-Path)
shift
repo_path="${1:-}"
[ -z "$repo_path" ] && __usage
;;
-s|--tools-source|-ToolsSource)
shift
tools_source="${1:-}"
[ -z "$tools_source" ] && __usage
;;
-u|--update|-Update)
update=true
;;
--verbose|-Verbose)
verbose=true
;;
--)
shift
break
;;
*)
break
;;
esac
shift
done done
unzip -q -d $tempFolder $localZipFile if ! __machine_has unzip; then
__error 'Missing required command: unzip'
mkdir $buildFolder exit 1
cp -r $tempFolder/**/build/** $buildFolder
chmod +x $buildFile
# Cleanup
if test -d $tempFolder; then
rm -rf $tempFolder
fi
fi fi
$buildFile -r $repoFolder "$@" if ! __machine_has curl && ! __machine_has wget; then
__error 'Missing required command. Either wget or curl is required.'
exit 1
fi
if [ -f $config_file ]; then
comment=false
while __read_dom; do
if [ "$comment" = true ]; then [[ $CONTENT == *'-->'* ]] && comment=false ; continue; fi
if [[ $ENTITY == '!--'* ]]; then comment=true; continue; fi
if [ -z "$channel" ] && [[ $ENTITY == "KoreBuildChannel" ]]; then channel=$CONTENT; fi
if [ -z "$tools_source" ] && [[ $ENTITY == "KoreBuildToolsSource" ]]; then tools_source=$CONTENT; fi
done < $config_file
fi
[ -z "$channel" ] && channel='dev'
[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools'
get_korebuild
install_tools "$tools_source" "$DOTNET_HOME"
invoke_repository_build "$repo_path" $@

Просмотреть файл

@ -1,6 +1,6 @@
<Project> <Project>
<Import Project="dependencies.props" /> <Import Project="dependencies.props" />
<Import Project="..\version.props" /> <Import Project="..\version.xml" />
<PropertyGroup> <PropertyGroup>
<Product>Microsoft ASP.NET Core</Product> <Product>Microsoft ASP.NET Core</Product>

Просмотреть файл

@ -1,7 +0,0 @@
<!-- This file may be overwritten by automation. Only values allowed here are VersionPrefix and VersionSuffix. -->
<Project>
<PropertyGroup>
<VersionPrefix>2.1.0</VersionPrefix>
<VersionSuffix>preview1</VersionSuffix>
</PropertyGroup>
</Project>

8
version.xml Normal file
Просмотреть файл

@ -0,0 +1,8 @@
<!-- This file may be overwritten by automation. -->
<Project>
<PropertyGroup>
<KoreBuildChannel>dev</KoreBuildChannel>
<VersionPrefix>2.1.0</VersionPrefix>
<VersionSuffix>preview1</VersionSuffix>
</PropertyGroup>
</Project>