From 899d7d6e6106d9cf67ca74054009a3994377b1c8 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 27 Sep 2016 13:08:42 +0100 Subject: [PATCH] Appveyor (#175) * First pass of Cake build * Update Cake but still need cake itself to run on full CLR * Test out appveyor * 3.5 build fix * Build master and PRs differently. Still scared to auto publish to nuget. --- appveyor.yml | 33 +++ build.cake | 233 ++++++++++++++++++++++ build.ps1 | 130 ++++++++++++ src/SharpCompress/Compressors/LZMA/Log.cs | 2 +- 4 files changed, 397 insertions(+), 1 deletion(-) create mode 100644 appveyor.yml create mode 100644 build.cake create mode 100644 build.ps1 diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..4916dbb8f --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,33 @@ +# configuration for "master" branch +- + version: '0.13.{build}' + + init: + - git config --global core.autocrlf true + + branches: + only: + - master + + build_script: + - ps: .\build.ps1 + + test: off + + cache: + - tools -> build.cake + - tools -> build.ps1 + +# configuration for "default" branch +- + init: + - git config --global core.autocrlf true + + build_script: + - ps: .\build.ps1 + + test: off + + cache: + - tools -> build.cake + - tools -> build.ps1 \ No newline at end of file diff --git a/build.cake b/build.cake new file mode 100644 index 000000000..a1870d7e0 --- /dev/null +++ b/build.cake @@ -0,0 +1,233 @@ +#addin "Cake.Json" + +#addin "nuget:?package=NuGet.Core" + +using NuGet; + + +////////////////////////////////////////////////////////////////////// +// ARGUMENTS +////////////////////////////////////////////////////////////////////// + +var target = Argument("target", "Default"); +var apiKey = Argument("apiKey", ""); +var repo = Argument("repo", ""); + +////////////////////////////////////////////////////////////////////// +// PREPARATION +////////////////////////////////////////////////////////////////////// + +var sources = new [] { "https://api.nuget.org/v3/index.json" }; +var publishTarget = ""; + +Warning("============="); +var globalPath = MakeFullPath("global.json"); +var nupkgs = MakeFullPath("nupkgs"); +Warning("Operating on global.json: " + globalPath); +Warning("============="); + +////////////////////////////////////////////////////////////////////// +// FUNCTIONS +////////////////////////////////////////////////////////////////////// + +string MakeFullPath(string relativePath) +{ + if (string.IsNullOrEmpty(repo)) + { + return MakeAbsolute(new DirectoryPath(relativePath)).ToString(); + } + if (!System.IO.Path.IsPathRooted(repo)) + { + return MakeAbsolute(new DirectoryPath(System.IO.Path.Combine(repo,relativePath))).ToString(); + } + return System.IO.Path.Combine(repo, relativePath); +} + +IEnumerable GetAllProjects() +{ + var global = DeserializeJsonFromFile(globalPath); + var projs = global["projects"].Select(x => x.ToString()); + foreach(var y in projs) + { + yield return MakeFullPath(y); + } +} + +IEnumerable GetSourceProjects() +{ + return GetAllProjects().Where(x => x.EndsWith("src")); +} + +IEnumerable GetTestProjects() +{ + return GetAllProjects().Where(x => x.EndsWith("test")); +} + +IEnumerable GetFrameworks(string path) +{ + var projectJObject = DeserializeJsonFromFile(path); + foreach(var prop in ((JObject)projectJObject["frameworks"]).Properties()) + { + yield return prop.Name; + } +} + +string GetVersion(string path) +{ + var projectJObject = DeserializeJsonFromFile(path); + return ((JToken)projectJObject["version"]).ToString(); +} + +IEnumerable GetProjectJsons(IEnumerable projects) +{ + foreach(var proj in projects) + { + foreach(var projectJson in GetFiles(proj + "/**/project.json")) + { + yield return MakeFullPath(projectJson.ToString()); + } + } +} + +bool IsNuGetPublished (FilePath file, string nugetSource) +{ + var pkg = new ZipPackage(file.ToString()); + + var repo = PackageRepositoryFactory.Default.CreateRepository(nugetSource); + + var packages = repo.FindPackagesById(pkg.Id); + + var version = SemanticVersion.Parse(pkg.Version.ToString()); + + //Filter the list of packages that are not Release (Stable) versions + var exists = packages.Any (p => p.Version == version); + + return exists; +} + +////////////////////////////////////////////////////////////////////// +// TASKS +////////////////////////////////////////////////////////////////////// + +Task("Restore") + .Does(() => +{ + var settings = new DotNetCoreRestoreSettings + { + Sources = sources, + NoCache = true + }; + + foreach(var project in GetProjectJsons(GetSourceProjects().Concat(GetTestProjects()))) + { + DotNetCoreRestore(project, settings); + } +}); + +Task("Build") + .Does(() => +{ + var settings = new DotNetCoreBuildSettings + { + Configuration = "Release" + }; + + foreach(var project in GetProjectJsons(GetSourceProjects().Concat(GetTestProjects()))) + { + foreach(var framework in GetFrameworks(project)) + { + Information("Building: {0} on Framework: {1}", project, framework); + Information("========"); + settings.Framework = framework; + DotNetCoreBuild(project, settings); + } + } +}); + +Task("Test") + .Does(() => +{ + var settings = new DotNetCoreTestSettings + { + Configuration = "Release", + Verbose = true + }; + + foreach(var project in GetProjectJsons(GetTestProjects())) + { + settings.Framework = GetFrameworks(project).First(); + DotNetCoreTest(project.ToString(), settings); + } + +}).ReportError(exception => +{ + Error(exception.ToString()); +}); + +Task("Pack") + .Does(() => +{ + if (DirectoryExists(nupkgs)) + { + DeleteDirectory(nupkgs, true); + } + CreateDirectory(nupkgs); + + var settings = new DotNetCorePackSettings + { + Configuration = "Release", + OutputDirectory = nupkgs + }; + + foreach(var project in GetProjectJsons(GetSourceProjects())) + { + DotNetCorePack(project, settings); + } +}); + +Task("Publish") + .Does(() => +{ + var packages = GetFiles(nupkgs + "/*.nupkg"); + foreach(var package in packages) + { + if (package.ToString().Contains("symbols")) + { + Warning("Skipping Symbols package " + package); + continue; + } + if (IsNuGetPublished(package, sources[1])) + { + throw new InvalidOperationException(package + " is already published."); + } + NuGetPush(package, new NuGetPushSettings{ + ApiKey = apiKey, + Verbosity = NuGetVerbosity.Detailed, + Source = publishTarget + }); + } +}); + +////////////////////////////////////////////////////////////////////// +// TASK TARGETS +////////////////////////////////////////////////////////////////////// + +Task("PRBuild") + .IsDependentOn("Restore") + .IsDependentOn("Build") + .IsDependentOn("Test"); + +Task("MasterBuild") + .IsDependentOn("Restore") + .IsDependentOn("Build") + .IsDependentOn("Test") + .IsDependentOn("Pack"); + +Task("Default") + .IsDependentOn("PRBuild"); + +////////////////////////////////////////////////////////////////////// +// EXECUTION +////////////////////////////////////////////////////////////////////// + +RunTarget(target); \ No newline at end of file diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 000000000..878a2dc4d --- /dev/null +++ b/build.ps1 @@ -0,0 +1,130 @@ +<# +.SYNOPSIS +This is a Powershell script to bootstrap a Cake build. +.DESCRIPTION +This Powershell script will download NuGet if missing, restore NuGet tools (including Cake) +and execute your Cake build script with the parameters you provide. +.PARAMETER Target +The build script target to run. +.PARAMETER Configuration +The build configuration to use. +.PARAMETER Verbosity +Specifies the amount of information to be displayed. +.PARAMETER WhatIf +Performs a dry run of the build script. +No tasks will be executed. +.PARAMETER ScriptArgs +Remaining arguments are added here. +.LINK +http://cakebuild.net +#> + +[CmdletBinding()] +Param( + [string]$Script = "build.cake", + [string]$Target = "Default", + [ValidateSet("Release", "Debug")] + [string]$Configuration = "Release", + [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] + [string]$Verbosity = "Verbose", + [switch]$WhatIf, + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$ScriptArgs +) + +$CakeVersion = "0.16.1" +$DotNetChannel = "preview"; +$DotNetVersion = "1.0.0-preview2-003131"; +$DotNetInstallerUri = "https://raw.githubusercontent.com/dotnet/cli/rel/1.0.0-preview2/scripts/obtain/dotnet-install.ps1"; +$NugetUrl = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" + +# Make sure tools folder exists +$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent +$ToolPath = Join-Path $PSScriptRoot "tools" +if (!(Test-Path $ToolPath)) { + Write-Verbose "Creating tools directory..." + New-Item -Path $ToolPath -Type directory | out-null +} + +########################################################################### +# INSTALL .NET CORE CLI +########################################################################### + +Function Remove-PathVariable([string]$VariableToRemove) +{ + $path = [Environment]::GetEnvironmentVariable("PATH", "User") + if ($path -ne $null) + { + $newItems = $path.Split(';', [StringSplitOptions]::RemoveEmptyEntries) | Where-Object { "$($_)" -inotlike $VariableToRemove } + [Environment]::SetEnvironmentVariable("PATH", [System.String]::Join(';', $newItems), "User") + } + + $path = [Environment]::GetEnvironmentVariable("PATH", "Process") + if ($path -ne $null) + { + $newItems = $path.Split(';', [StringSplitOptions]::RemoveEmptyEntries) | Where-Object { "$($_)" -inotlike $VariableToRemove } + [Environment]::SetEnvironmentVariable("PATH", [System.String]::Join(';', $newItems), "Process") + } +} + +# Get .NET Core CLI path if installed. +$FoundDotNetCliVersion = $null; +if (Get-Command dotnet -ErrorAction SilentlyContinue) { + $FoundDotNetCliVersion = dotnet --version; +} + +if($FoundDotNetCliVersion -ne $DotNetVersion) { + $InstallPath = Join-Path $PSScriptRoot ".dotnet" + if (!(Test-Path $InstallPath)) { + mkdir -Force $InstallPath | Out-Null; + } + (New-Object System.Net.WebClient).DownloadFile($DotNetInstallerUri, "$InstallPath\dotnet-install.ps1"); + & $InstallPath\dotnet-install.ps1 -Channel $DotNetChannel -Version $DotNetVersion -InstallDir $InstallPath; + + Remove-PathVariable "$InstallPath" + $env:PATH = "$InstallPath;$env:PATH" + $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 + $env:DOTNET_CLI_TELEMETRY_OPTOUT=1 +} + +########################################################################### +# INSTALL NUGET +########################################################################### + +# Make sure nuget.exe exists. +$NugetPath = Join-Path $ToolPath "nuget.exe" +if (!(Test-Path $NugetPath)) { + Write-Host "Downloading NuGet.exe..." + (New-Object System.Net.WebClient).DownloadFile($NugetUrl, $NugetPath); +} + +########################################################################### +# INSTALL CAKE +########################################################################### + +# Make sure Cake has been installed. +$CakePath = Join-Path $ToolPath "Cake.$CakeVersion/Cake.exe" +if (!(Test-Path $CakePath)) { + Write-Host "Installing Cake..." + Invoke-Expression "&`"$NugetPath`" install Cake -Version $CakeVersion -OutputDirectory `"$ToolPath`"" | Out-Null; + if ($LASTEXITCODE -ne 0) { + Throw "An error occured while restoring Cake from NuGet." + } +} + +########################################################################### +# RUN BUILD SCRIPT +########################################################################### + +# Build the argument list. +$Arguments = @{ + target=$Target; + configuration=$Configuration; + verbosity=$Verbosity; + dryrun=$WhatIf; +}.GetEnumerator() | %{"--{0}=`"{1}`"" -f $_.key, $_.value }; + +# Start Cake +Write-Host "Running build script..." +Invoke-Expression "& `"$CakePath`" `"$Script`" $Arguments $ScriptArgs" +exit $LASTEXITCODE \ No newline at end of file diff --git a/src/SharpCompress/Compressors/LZMA/Log.cs b/src/SharpCompress/Compressors/LZMA/Log.cs index 44d42ad31..ba4612153 100644 --- a/src/SharpCompress/Compressors/LZMA/Log.cs +++ b/src/SharpCompress/Compressors/LZMA/Log.cs @@ -87,7 +87,7 @@ public static void WriteLine(string text) public static void WriteLine(string format, params object[] args) { EnsureIndent(); - Debug.WriteLine(format, args); + Debug.WriteLine(string.Format(format, args)); _needsIndent = true; } }