7 changed files with 450 additions and 48 deletions
@ -1,2 +1,2 @@ |
|||
@ECHO OFF |
|||
PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" |
|||
PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE" |
|||
|
|||
@ -1,46 +1,8 @@ |
|||
#!/usr/bin/env bash |
|||
repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" |
|||
cd $repoFolder |
|||
|
|||
koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" |
|||
if [ ! -z $KOREBUILD_ZIP ]; then |
|||
koreBuildZip=$KOREBUILD_ZIP |
|||
fi |
|||
set -euo pipefail |
|||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" |
|||
|
|||
buildFolder=".build" |
|||
buildFile="$buildFolder/KoreBuild.sh" |
|||
|
|||
if test ! -d $buildFolder; then |
|||
echo "Downloading KoreBuild from $koreBuildZip" |
|||
|
|||
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 |
|||
retries=$((retries - 1)) |
|||
echo "Waiting 10 seconds before retrying. Retries left: $retries" |
|||
sleep 10s |
|||
done |
|||
|
|||
unzip -q -d $tempFolder $localZipFile |
|||
|
|||
mkdir $buildFolder |
|||
cp -r $tempFolder/**/build/** $buildFolder |
|||
|
|||
chmod +x $buildFile |
|||
|
|||
# Cleanup |
|||
if test -d $tempFolder; then |
|||
rm -rf $tempFolder |
|||
fi |
|||
fi |
|||
|
|||
$buildFile -r $repoFolder "$@" |
|||
# Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) |
|||
chmod +x "$DIR/run.sh"; sync |
|||
"$DIR/run.sh" default-build "$@" |
|||
|
|||
@ -0,0 +1,2 @@ |
|||
@ECHO OFF |
|||
PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE" |
|||
@ -0,0 +1,196 @@ |
|||
#!/usr/bin/env powershell |
|||
#requires -version 4 |
|||
|
|||
<# |
|||
.SYNOPSIS |
|||
Executes KoreBuild commands. |
|||
|
|||
.DESCRIPTION |
|||
Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`. |
|||
|
|||
.PARAMETER Command |
|||
The KoreBuild command to run. |
|||
|
|||
.PARAMETER Path |
|||
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 korebuild.json. |
|||
|
|||
.PARAMETER ToolsSourceSuffix |
|||
The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. |
|||
|
|||
.PARAMETER Arguments |
|||
Arguments to be passed to the command |
|||
|
|||
.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 JSON file. It is optional, and the configuration values in it are optional as well. Any options set |
|||
in the file are overridden by command line parameters. |
|||
|
|||
.EXAMPLE |
|||
Example config file: |
|||
```json |
|||
{ |
|||
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", |
|||
"channel": "dev", |
|||
"toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" |
|||
} |
|||
``` |
|||
#> |
|||
[CmdletBinding(PositionalBinding = $false)] |
|||
param( |
|||
[Parameter(Mandatory = $true, Position = 0)] |
|||
[string]$Command, |
|||
[string]$Path = $PSScriptRoot, |
|||
[Alias('c')] |
|||
[string]$Channel, |
|||
[Alias('d')] |
|||
[string]$DotNetHome, |
|||
[Alias('s')] |
|||
[string]$ToolsSource, |
|||
[Alias('u')] |
|||
[switch]$Update, |
|||
[string]$ConfigFile, |
|||
[string]$ToolsSourceSuffix, |
|||
[Parameter(ValueFromRemainingArguments = $true)] |
|||
[string[]]$Arguments |
|||
) |
|||
|
|||
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 $ToolsSourceSuffix |
|||
} |
|||
|
|||
$version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 |
|||
if (!$version) { |
|||
Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'" |
|||
} |
|||
$version = $version.TrimStart('version:').Trim() |
|||
$korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) |
|||
|
|||
if (!(Test-Path $korebuildPath)) { |
|||
Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" |
|||
New-Item -ItemType Directory -Path $korebuildPath | Out-Null |
|||
$remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip" |
|||
|
|||
try { |
|||
$tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" |
|||
Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix |
|||
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 |
|||
[System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath) |
|||
} |
|||
} |
|||
catch { |
|||
Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore |
|||
throw |
|||
} |
|||
finally { |
|||
Remove-Item $tmpfile -ErrorAction Ignore |
|||
} |
|||
} |
|||
|
|||
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, [string]$RemoteSuffix) { |
|||
if ($RemotePath -notlike 'http*') { |
|||
Copy-Item $RemotePath $LocalPath |
|||
return |
|||
} |
|||
|
|||
$retries = 10 |
|||
while ($retries -gt 0) { |
|||
$retries -= 1 |
|||
try { |
|||
Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath |
|||
return |
|||
} |
|||
catch { |
|||
Write-Verbose "Request failed. $retries retries remaining" |
|||
} |
|||
} |
|||
|
|||
Write-Error "Download failed: '$RemotePath'." |
|||
} |
|||
|
|||
# |
|||
# Main |
|||
# |
|||
|
|||
# Load configuration or set defaults |
|||
|
|||
$Path = Resolve-Path $Path |
|||
if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' } |
|||
|
|||
if (Test-Path $ConfigFile) { |
|||
try { |
|||
$config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json |
|||
if ($config) { |
|||
if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } |
|||
if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} |
|||
} |
|||
} |
|||
catch { |
|||
Write-Warning "$ConfigFile could not be read. Its settings will be ignored." |
|||
Write-Warning $Error[0] |
|||
} |
|||
} |
|||
|
|||
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 { |
|||
Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile |
|||
Invoke-KoreBuildCommand $Command @Arguments |
|||
} |
|||
finally { |
|||
Remove-Module 'KoreBuild' -ErrorAction Ignore |
|||
} |
|||
@ -0,0 +1,231 @@ |
|||
#!/usr/bin/env bash |
|||
|
|||
set -euo pipefail |
|||
|
|||
# |
|||
# variables |
|||
# |
|||
|
|||
RESET="\033[0m" |
|||
RED="\033[0;31m" |
|||
YELLOW="\033[0;33m" |
|||
MAGENTA="\033[0;95m" |
|||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" |
|||
[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" |
|||
verbose=false |
|||
update=false |
|||
repo_path="$DIR" |
|||
channel='' |
|||
tools_source='' |
|||
tools_source_suffix='' |
|||
|
|||
# |
|||
# Functions |
|||
# |
|||
__usage() { |
|||
echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] <Arguments>...]" |
|||
echo "" |
|||
echo "Arguments:" |
|||
echo " command The command to be run." |
|||
echo " <Arguments>... Arguments passed to the command. 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> The path to the configuration file that stores values. Defaults to korebuild.json." |
|||
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|-ToolsSource <URL> The base url where build tools can be downloaded. Overrides the value from the config file." |
|||
echo " --tools-source-suffix|-ToolsSourceSuffix <SUFFIX> The suffix to append to tools-source. Useful for query strings." |
|||
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 version |
|||
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" "$tools_source_suffix" |
|||
fi |
|||
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" "$tools_source_suffix"; then |
|||
unzip -q -d "$korebuild_path" "$tmpfile" |
|||
fi |
|||
rm "$tmpfile" || true |
|||
fi |
|||
|
|||
source "$korebuild_path/KoreBuild.sh" |
|||
} || { |
|||
if [ -d "$korebuild_path" ]; then |
|||
echo "Cleaning up after failed installation" |
|||
rm -rf "$korebuild_path" || true |
|||
fi |
|||
return 1 |
|||
} |
|||
} |
|||
|
|||
__error() { |
|||
echo -e "${RED}error: $*${RESET}" 1>&2 |
|||
} |
|||
|
|||
__warn() { |
|||
echo -e "${YELLOW}warning: $*${RESET}" |
|||
} |
|||
|
|||
__machine_has() { |
|||
hash "$1" > /dev/null 2>&1 |
|||
return $? |
|||
} |
|||
|
|||
__get_remote_file() { |
|||
local remote_path=$1 |
|||
local local_path=$2 |
|||
local remote_path_suffix=$3 |
|||
|
|||
if [[ "$remote_path" != 'http'* ]]; then |
|||
cp "$remote_path" "$local_path" |
|||
return 0 |
|||
fi |
|||
|
|||
local failed=false |
|||
if __machine_has wget; then |
|||
wget --tries 10 --quiet -O "$local_path" "${remote_path}${remote_path_suffix}" || failed=true |
|||
else |
|||
failed=true |
|||
fi |
|||
|
|||
if [ "$failed" = true ] && __machine_has curl; then |
|||
failed=false |
|||
curl --retry 10 -sSL -f --create-dirs -o "$local_path" "${remote_path}${remote_path_suffix}" || failed=true |
|||
fi |
|||
|
|||
if [ "$failed" = true ]; then |
|||
__error "Download failed: $remote_path" 1>&2 |
|||
return 1 |
|||
fi |
|||
} |
|||
|
|||
# |
|||
# main |
|||
# |
|||
|
|||
command="${1:-}" |
|||
shift |
|||
|
|||
while [[ $# -gt 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 |
|||
if [ ! -f "$config_file" ]; then |
|||
__error "Invalid value for --config-file. $config_file does not exist." |
|||
exit 1 |
|||
fi |
|||
;; |
|||
-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 |
|||
;; |
|||
--tools-source-suffix|-ToolsSourceSuffix) |
|||
shift |
|||
tools_source_suffix="${1:-}" |
|||
[ -z "$tools_source_suffix" ] && __usage |
|||
;; |
|||
-u|--update|-Update) |
|||
update=true |
|||
;; |
|||
--verbose|-Verbose) |
|||
verbose=true |
|||
;; |
|||
--) |
|||
shift |
|||
break |
|||
;; |
|||
*) |
|||
break |
|||
;; |
|||
esac |
|||
shift |
|||
done |
|||
|
|||
if ! __machine_has unzip; then |
|||
__error 'Missing required command: unzip' |
|||
exit 1 |
|||
fi |
|||
|
|||
if ! __machine_has curl && ! __machine_has wget; then |
|||
__error 'Missing required command. Either wget or curl is required.' |
|||
exit 1 |
|||
fi |
|||
|
|||
[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json" |
|||
if [ -f "$config_file" ]; then |
|||
if __machine_has jq ; then |
|||
if jq '.' "$config_file" >/dev/null ; then |
|||
config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" |
|||
config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" |
|||
else |
|||
__warn "$config_file is invalid JSON. Its settings will be ignored." |
|||
fi |
|||
elif __machine_has python ; then |
|||
if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then |
|||
config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" |
|||
config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" |
|||
else |
|||
__warn "$config_file is invalid JSON. Its settings will be ignored." |
|||
fi |
|||
else |
|||
__warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.' |
|||
fi |
|||
|
|||
[ ! -z "${config_channel:-}" ] && channel="$config_channel" |
|||
[ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" |
|||
fi |
|||
|
|||
[ -z "$channel" ] && channel='dev' |
|||
[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' |
|||
|
|||
get_korebuild |
|||
set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" |
|||
invoke_korebuild_command "$command" "$@" |
|||
Loading…
Reference in new issue