7 changed files with 450 additions and 48 deletions
@ -1,2 +1,2 @@ |
|||||
@ECHO OFF |
@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 |
#!/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 |
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" |
||||
koreBuildZip=$KOREBUILD_ZIP |
|
||||
fi |
|
||||
|
|
||||
buildFolder=".build" |
# Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) |
||||
buildFile="$buildFolder/KoreBuild.sh" |
chmod +x "$DIR/run.sh"; sync |
||||
|
"$DIR/run.sh" default-build "$@" |
||||
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 "$@" |
|
||||
|
|||||
@ -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