Update the bootstrapper to install the compiled version of KoreBuild
- Replace SplitPackages as a package reference with a RepoTask instead
This commit is contained in:
Родитель
006cf52afa
Коммит
f7fcc555ff
|
@ -2,7 +2,6 @@
|
|||
[Bb]in/
|
||||
TestResults/
|
||||
.nuget/
|
||||
.build/
|
||||
.testPublish/
|
||||
*.sln.ide/
|
||||
_ReSharper.*/
|
||||
|
@ -37,3 +36,4 @@ node_modules
|
|||
**/[Cc]ompiler/[Rr]esources/**/*.js
|
||||
*launchSettings.json
|
||||
global.json
|
||||
korebuild-lock.txt
|
||||
|
|
|
@ -1,10 +1,23 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26206.0
|
||||
VisualStudioVersion = 15.0.26621.2
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoherenceBuild", "tools\CoherenceBuild\CoherenceBuild.csproj", "{182ACF9E-135C-42D5-A19C-A6C9FCF0529F}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{DBFB488A-D866-4FD2-BADF-D760DDF114E0}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
build\repo.props = build\repo.props
|
||||
build\repo.targets = build\repo.targets
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoTasks", "build\tasks\RepoTasks.csproj", "{2DF1B138-D369-4701-82FA-187B9C90D7E8}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1C53F28D-BEF5-4DD4-9766-895C17FE2A09}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
packages\packages.csv = packages\packages.csv
|
||||
packages\packages.key.txt = packages\packages.key.txt
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -15,8 +28,16 @@ Global
|
|||
{182ACF9E-135C-42D5-A19C-A6C9FCF0529F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{182ACF9E-135C-42D5-A19C-A6C9FCF0529F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{182ACF9E-135C-42D5-A19C-A6C9FCF0529F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2DF1B138-D369-4701-82FA-187B9C90D7E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2DF1B138-D369-4701-82FA-187B9C90D7E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{2DF1B138-D369-4701-82FA-187B9C90D7E8} = {DBFB488A-D866-4FD2-BADF-D760DDF114E0}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {E8514249-D06D-486A-83DB-ABDE80756DEA}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
dev
|
227
build.ps1
227
build.ps1
|
@ -1,68 +1,177 @@
|
|||
$ErrorActionPreference = "Stop"
|
||||
#!/usr/bin/env powershell
|
||||
#requires -version 4
|
||||
|
||||
function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries)
|
||||
{
|
||||
while($true)
|
||||
{
|
||||
try
|
||||
{
|
||||
Invoke-WebRequest $url -OutFile $downloadLocation
|
||||
break
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Build this repository
|
||||
|
||||
.DESCRIPTION
|
||||
Downloads korebuild if required. Then builds the repository.
|
||||
|
||||
.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 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
|
||||
}
|
||||
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
|
||||
|
||||
$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:'"
|
||||
}
|
||||
else
|
||||
{
|
||||
$exception = $_.Exception
|
||||
throw $exception
|
||||
$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
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cd $PSScriptRoot
|
||||
|
||||
$repoFolder = $PSScriptRoot
|
||||
$env:REPO_FOLDER = $repoFolder
|
||||
|
||||
$korebuildVersion = $(Get-Content -Raw $PSScriptRoot/KoreBuildVersion.txt).Trim()
|
||||
$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/$korebuildVersion.zip"
|
||||
if ($env:KOREBUILD_ZIP)
|
||||
{
|
||||
$koreBuildZip=$env:KOREBUILD_ZIP
|
||||
}
|
||||
|
||||
$buildFolder = ".build"
|
||||
$buildFile="$buildFolder\KoreBuild.ps1"
|
||||
|
||||
if (!(Test-Path $buildFolder)) {
|
||||
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
|
||||
|
||||
else {
|
||||
# Fallback to old approach for old installations of PowerShell
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder)
|
||||
|
||||
New-Item -Path "$buildFolder" -Type directory | Out-Null
|
||||
copy-item "$tempFolder\**\build\*" $buildFolder -Recurse
|
||||
|
||||
# Cleanup
|
||||
if (Test-Path $tempFolder) {
|
||||
Remove-Item -Recurse -Force $tempFolder
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore
|
||||
throw
|
||||
}
|
||||
finally {
|
||||
Remove-Item $tmpfile -ErrorAction Ignore
|
||||
}
|
||||
}
|
||||
|
||||
return $korebuildPath
|
||||
}
|
||||
|
||||
&"$buildFile" @args
|
||||
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
|
||||
}
|
||||
|
|
222
build.sh
222
build.sh
|
@ -1,47 +1,195 @@
|
|||
#!/usr/bin/env bash
|
||||
repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd $repoFolder
|
||||
|
||||
koreBuildVersion=$(cat $repoFolder/KoreBuildVersion.txt)
|
||||
koreBuildZip="https://github.com/aspnet/KoreBuild/archive/$koreBuildVersion.zip"
|
||||
if [ ! -z $KOREBUILD_ZIP ]; then
|
||||
koreBuildZip=$KOREBUILD_ZIP
|
||||
fi
|
||||
set -euo pipefail
|
||||
|
||||
buildFolder=".build"
|
||||
buildFile="$buildFolder/KoreBuild.sh"
|
||||
#
|
||||
# variables
|
||||
#
|
||||
|
||||
if test ! -d $buildFolder; then
|
||||
echo "Downloading KoreBuild from $koreBuildZip"
|
||||
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=''
|
||||
|
||||
tempFolder="/tmp/KoreBuild-$(uuidgen)"
|
||||
mkdir $tempFolder
|
||||
#
|
||||
# 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."
|
||||
|
||||
localZipFile="$tempFolder/korebuild.zip"
|
||||
if [[ "${1:-}" != '--no-exit' ]]; then
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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}$@${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 curl ; then
|
||||
curl --retry 10 -sSL -f --create-dirs -o $local_path $remote_path || failed=true
|
||||
elif __machine_has wget; then
|
||||
wget --tries 10 -O $local_path $remote_path || failed=true
|
||||
else
|
||||
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
|
||||
|
||||
if ! __machine_has unzip; then
|
||||
__error 'Missing required command: unzip'
|
||||
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 "$@"
|
||||
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,5 +0,0 @@
|
|||
<Project>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SplitPackages" Version="1.0.3-*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -2,7 +2,7 @@
|
|||
<PropertyGroup>
|
||||
<NuGetPublishFeed>https://dotnet.myget.org/f/aspnetcore-ci-dev</NuGetPublishFeed>
|
||||
<NpmRegistry>$(NuGetPublishFeed)/npm/</NpmRegistry>
|
||||
<BuildDependsOn>$(BuildDependsOn);RunVerifier;RunSplitPackages;PublishNpmModules</BuildDependsOn>
|
||||
<BuildDependsOn>$(BuildDependsOn);RunVerifier;SplitPackages;PublishNpmModules</BuildDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="RunVerifier">
|
||||
|
@ -27,11 +27,6 @@
|
|||
<VerifierArgsList Include="--disable-partner-package-verification" Condition="'$(DISABLE_PARTNER_COHERENCE_CHECK)'=='true'"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(APIKEY)'!=''">
|
||||
<VerifierArgsList Include="--nuget-publish-feed $(NuGetPublishFeed)" />
|
||||
<VerifierArgsList Include="--api-key $(APIKEY)" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VerifierProjectDirectory>$(RepositoryRoot)tools\CoherenceBuild\</VerifierProjectDirectory>
|
||||
<VerifierArgs>@(VerifierArgsList, ' ')</VerifierArgs>
|
||||
|
@ -40,14 +35,19 @@
|
|||
<Exec Command="dotnet run $(VerifierArgs)" WorkingDirectory="$(VerifierProjectDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="RunSplitPackages" DependsOnTargets="_FindDotNetPath">
|
||||
<Target Name="SplitPackages">
|
||||
<PropertyGroup>
|
||||
<ProductPackagesSource>$(ArtifactsDir)product-packages</ProductPackagesSource>
|
||||
<SplitPackagesCsv>$(RepositoryRoot)packages\packages.csv</SplitPackagesCsv>
|
||||
<SplitPackagesArgs>--source $(ProductPackagesSource) --csv $(SplitPackagesCsv) --destination $(ArtifactsDir)</SplitPackagesArgs>
|
||||
<ProductPackagesSource>$(ArtifactsDir)product-packages\</ProductPackagesSource>
|
||||
</PropertyGroup>
|
||||
|
||||
<Exec Command=""$(DotNetPath)" "$(SplitPackagesNetCoreAppPath)" $(SplitPackagesArgs)" />
|
||||
<ItemGroup>
|
||||
<_PackagesToCopy Include="$(ProductPackagesSource)*.nupkg" />
|
||||
</ItemGroup>
|
||||
|
||||
<RepoTasks.CopyPackagesToSplitFolders
|
||||
Packages="@(_PackagesToCopy)"
|
||||
CsvFile="$(RepositoryRoot)packages\packages.csv"
|
||||
DestinationFolder="$(ArtifactsDir)" />
|
||||
|
||||
<RemoveDir Directories="$(ProductPackagesSource)" />
|
||||
</Target>
|
||||
|
@ -68,10 +68,4 @@
|
|||
<Exec Command="npm config delete $(AuthTokenSetting)" />
|
||||
<Error Text="Publishing npm modules failed" Condition="%(ExitCodes.Identity) > 0"/>
|
||||
</Target>
|
||||
|
||||
<Target Name="_FindDotNetPath">
|
||||
<GetDotNetHost>
|
||||
<Output TaskParameter="ExecutablePath" PropertyName="DotNetPath" />
|
||||
</GetDotNetHost>
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.Build.Framework;
|
||||
using NuGet.Packaging;
|
||||
using NuGet.Packaging.Core;
|
||||
using RepoTasks.Utilities;
|
||||
|
||||
namespace RepoTasks
|
||||
{
|
||||
public class CopyPackagesToSplitFolders : Microsoft.Build.Utilities.Task
|
||||
{
|
||||
/// <summary>
|
||||
/// The item group containing the nuget packages to split in different folders.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem[] Packages { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Path to the CSV file containing the names and subfolders where each package must go.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string CsvFile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The folder where packages should be copied. Subfolders will be created based on package category.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string DestinationFolder { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
if (Packages?.Length == 0)
|
||||
{
|
||||
Log.LogError("No packages were found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(CsvFile) || !File.Exists(CsvFile))
|
||||
{
|
||||
Log.LogError($"Package manifest (csv file) could not be loaded from '{CsvFile}'");
|
||||
return false;
|
||||
}
|
||||
|
||||
var expectedPackages = PackageCollection.DeserializeFromCsv(CsvFile);
|
||||
|
||||
Directory.CreateDirectory(DestinationFolder);
|
||||
|
||||
foreach (var package in Packages)
|
||||
{
|
||||
PackageIdentity identity;
|
||||
using (var reader = new PackageArchiveReader(package.ItemSpec))
|
||||
{
|
||||
identity = reader.GetIdentity();
|
||||
}
|
||||
|
||||
if (!expectedPackages.TryGetCategory(identity.Id, out var category))
|
||||
{
|
||||
Log.LogError($"{CsvFile} does not contain an entry for a package with id: {identity.Id}");
|
||||
return false;
|
||||
}
|
||||
|
||||
string destDir;
|
||||
switch (category)
|
||||
{
|
||||
case PackageCategory.Unknown:
|
||||
throw new InvalidOperationException($"Package {identity} does not have a recognized package category.");
|
||||
case PackageCategory.Shipping:
|
||||
destDir = Path.Combine(DestinationFolder, "ship");
|
||||
break;
|
||||
case PackageCategory.NoShip:
|
||||
destDir = Path.Combine(DestinationFolder, "noship");
|
||||
break;
|
||||
case PackageCategory.ShipOob:
|
||||
destDir = Path.Combine(DestinationFolder, "shipoob");
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(destDir);
|
||||
|
||||
var destFile = Path.Combine(destDir, Path.GetFileName(package.ItemSpec));
|
||||
|
||||
Log.LogMessage($"Copying {package.ItemSpec} to {destFile}");
|
||||
|
||||
File.Copy(package.ItemSpec, destFile);
|
||||
expectedPackages.Remove(identity.Id);
|
||||
}
|
||||
|
||||
if (expectedPackages.Count != 0)
|
||||
{
|
||||
var error = new StringBuilder();
|
||||
foreach (var key in expectedPackages.Keys)
|
||||
{
|
||||
error.Append(" - ").AppendLine(key);
|
||||
}
|
||||
|
||||
Log.LogError($"Expected the following packages based on the contents of {CsvFile}, but they were not found:" + error.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(RepoTasksSdkPath)\Sdk.props" Condition="'$(RepoTasksSdkPath)' != '' "/>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NuGet.ProjectModel" Version="$(NuGetInMSBuildVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(RepoTasksSdkPath)\Sdk.targets" Condition="'$(RepoTasksSdkPath)' != '' "/>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,6 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<_RepoTaskAssembly>$(MSBuildThisFileDirectory)bin\publish\RepoTasks.dll</_RepoTaskAssembly>
|
||||
</PropertyGroup>
|
||||
<UsingTask TaskName="RepoTasks.CopyPackagesToSplitFolders" AssemblyFile="$(_RepoTaskAssembly)" />
|
||||
</Project>
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
|
||||
namespace RepoTasks.Utilities
|
||||
{
|
||||
public enum PackageCategory
|
||||
{
|
||||
Unknown = 0,
|
||||
Shipping,
|
||||
NoShip,
|
||||
ShipOob
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace RepoTasks.Utilities
|
||||
{
|
||||
public class PackageCollection
|
||||
{
|
||||
private readonly IDictionary<string, PackageCategory> _packages = new Dictionary<string, PackageCategory>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private PackageCollection()
|
||||
{
|
||||
}
|
||||
|
||||
public bool TryGetCategory(string packageId, out PackageCategory category) => _packages.TryGetValue(packageId, out category);
|
||||
|
||||
public void Remove(string packageId) => _packages.Remove(packageId);
|
||||
|
||||
public int Count => _packages.Count;
|
||||
|
||||
public IEnumerable<string> Keys => _packages.Keys;
|
||||
|
||||
public static PackageCollection DeserializeFromCsv(string filepath)
|
||||
{
|
||||
using (var stream = File.OpenRead(filepath))
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
return DeserializeFromCsv(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public static PackageCollection DeserializeFromCsv(TextReader reader)
|
||||
{
|
||||
var lineNo = 0;
|
||||
var list = new PackageCollection();
|
||||
|
||||
string[] Split(string l) => l.Split(',').Select(s => s.Trim()).ToArray();
|
||||
|
||||
// Package,Category,...
|
||||
// Microsoft.AspNetCore.Razor.Tools,ship,...
|
||||
// Microsoft.VisualStudio.Web.CodeGeneration.Tools,ship,...
|
||||
// Microsoft.Extensions.SecretManager.Tools,ship,...
|
||||
|
||||
var line = reader.ReadLine();
|
||||
lineNo++;
|
||||
var columns = Split(line);
|
||||
|
||||
EnsureHeaderColumns(columns);
|
||||
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
lineNo++;
|
||||
|
||||
var values = Split(line);
|
||||
if (values.Length < 2)
|
||||
{
|
||||
throw new FormatException($"Error on line {lineNo}. Too few columns. Expected at least two.");
|
||||
}
|
||||
|
||||
PackageCategory category;
|
||||
switch (values[1].ToLowerInvariant())
|
||||
{
|
||||
case "ship":
|
||||
category = PackageCategory.Shipping;
|
||||
break;
|
||||
case "noship":
|
||||
category = PackageCategory.NoShip;
|
||||
break;
|
||||
case "shipoob":
|
||||
category = PackageCategory.ShipOob;
|
||||
break;
|
||||
default:
|
||||
category = PackageCategory.Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
if (list._packages.ContainsKey(values[0]))
|
||||
{
|
||||
throw new InvalidDataException($"Duplicate package id detected: {values[0]} on line {lineNo}");
|
||||
}
|
||||
|
||||
list._packages.Add(values[0], category);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void EnsureHeaderColumns(string[] columns)
|
||||
{
|
||||
if (columns.Length < 2)
|
||||
{
|
||||
throw new FormatException("Unrecognized number of columns in csv file");
|
||||
}
|
||||
|
||||
if (!columns[0].Equals("Package", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new FormatException("Unrecognized column: " + columns[0]);
|
||||
}
|
||||
|
||||
if (!columns[1].Equals("Category", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new FormatException("Unrecognized column: " + columns[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<KoreBuildChannel>dev</KoreBuildChannel>
|
||||
<VersionPrefix>2.1.0</VersionPrefix>
|
||||
<VersionSuffix>preview1</VersionSuffix>
|
||||
</PropertyGroup>
|
||||
</Project>
|
Загрузка…
Ссылка в новой задаче