diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml new file mode 100644 index 0000000..e4e7c75 --- /dev/null +++ b/.github/workflows/build-macos.yml @@ -0,0 +1,65 @@ +name: build-macos + +on: + push: + paths-ignore: + - "**.md" + - LICENSE + branches: + - "master" + pull_request: + paths-ignore: + - "**.md" + - LICENSE + branches: + - master + +jobs: + build-and-test: + runs-on: macos-10.15 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Init + run: chmod +x ./build.sh + + - name: Install NuGet + uses: NuGet/setup-nuget@v1.0.5 + + - name: Setup Testspace + uses: testspace-com/setup-testspace@v1 + with: + domain: ${{github.repository_owner}} + + - name: Install .NET 3.1 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "3.1.x" + + - name: Install .NET 5 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "5.0.x" + + - name: Install .NET 6 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "6.0.x" + + - name: Install .NET 7 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "7.0.x" + + - name: Build + run: ./build.sh --target build + + - name: Run Tests + run: ./build.sh --target tests --exclusive + + - name: Push result to Testspace server + run: | + testspace [macos]**/*.trx + if: always() diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml new file mode 100644 index 0000000..3f65d18 --- /dev/null +++ b/.github/workflows/build-ubuntu.yml @@ -0,0 +1,65 @@ +name: build-ubuntu + +on: + push: + paths-ignore: + - "**.md" + - LICENSE + branches: + - "master" + pull_request: + paths-ignore: + - "**.md" + - LICENSE + branches: + - master + +jobs: + build-and-test: + runs-on: ubuntu-20.04 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Init + run: chmod +x ./build.sh + + - name: Install NuGet + uses: NuGet/setup-nuget@v1.0.5 + + - name: Setup Testspace + uses: testspace-com/setup-testspace@v1 + with: + domain: ${{github.repository_owner}} + + - name: Install .NET 3.1 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "3.1.x" + + - name: Install .NET 5 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "5.0.x" + + - name: Install .NET 6 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "6.0.x" + + - name: Install .NET 7 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "7.0.x" + + - name: Build + run: ./build.sh --target build + + - name: Run Tests + run: ./build.sh --target tests --exclusive + + - name: Push result to Testspace server + run: | + testspace [linux]**/*.trx + if: always() diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml new file mode 100644 index 0000000..9632c06 --- /dev/null +++ b/.github/workflows/build-windows.yml @@ -0,0 +1,59 @@ +name: build-windows + +on: + push: + paths-ignore: + - "**.md" + - LICENSE + branches: + - "master" + pull_request: + paths-ignore: + - "**.md" + - LICENSE + branches: + - master + +jobs: + build-and-test: + runs-on: windows-2019 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Testspace + uses: testspace-com/setup-testspace@v1 + with: + domain: ${{github.repository_owner}} + + - name: Install .NET 3.1 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "3.1.x" + + - name: Install .NET 5 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "5.0.x" + + - name: Install .NET 6 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "6.0.x" + + - name: Install .NET 7 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "7.0.x" + + - name: Build + run: .\build.ps1 --target build + + - name: Run Tests + run: .\build.ps1 --target tests --exclusive + + - name: Push result to Testspace server + run: | + testspace [windows]**/*.trx + if: always() diff --git a/.github/workflows/publish-nuget.yml b/.github/workflows/publish-nuget.yml new file mode 100644 index 0000000..a4f655f --- /dev/null +++ b/.github/workflows/publish-nuget.yml @@ -0,0 +1,75 @@ +name: "publish-nuget" + +on: + workflow_dispatch: + inputs: + package-version: + description: "Package Version" + required: true + package-source: + type: choice + description: Package Source + required: true + default: "myget" + options: + - myget + - nuget + package-id: + type: choice + description: Package Id + required: true + default: "LocalStack.AwsLocal" + options: + - LocalStack.AwsLocal + +jobs: + publish-nuget: + runs-on: ubuntu-20.04 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Init + run: chmod +x ./build.sh + + - name: Install NuGet + uses: NuGet/setup-nuget@v1.0.5 + + - name: Install .NET 3.1 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "3.1.x" + + - name: Install .NET 5 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "5.0.x" + + - name: Install .NET 6 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "6.0.x" + + - name: Install .NET 7 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: "7.0.x" + + - name: Build & Test + run: ./build.sh + + - name: "Print Version" + run: | + echo "Package Version: ${{ github.event.inputs.package-version }}" + + - name: Nuget Pack + run: ./build.sh --target nuget-pack --package-source ${{ github.event.inputs.package-source }} --package-id ${{ github.event.inputs.package-id }} --package-version ${{ github.event.inputs.package-version }} + + - name: MyGet Push + if: ${{ github.event.inputs.package-source == 'myget' }} + run: ./build.sh --target nuget-push --package-source ${{ github.event.inputs.package-source }} --package-id ${{ github.event.inputs.package-id }} --package-version ${{ github.event.inputs.package-version }} --package-secret ${{secrets.MYGET_API_KEY}} + + - name: NuGet Push + if: ${{ github.event.inputs.package-source == 'nuget' }} + run: ./build.sh --target nuget-push --package-source ${{ github.event.inputs.package-source }} --package-id ${{ github.event.inputs.package-id }} --package-version ${{ github.event.inputs.package-version }} --package-secret ${{secrets.NUGET_API_KEY}} diff --git a/build.ps1 b/build.ps1 index dc223b7..455c631 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,128 +1,3 @@ -########################################################################## -# This is the Cake bootstrapper script for PowerShell. -# This file is based on https://github.com/cake-build/resources modified for Cake.CoreCLR -# Feel free to change this file to fit your needs. -########################################################################## - -<# -.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 Script -The build script to execute. -.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 ShowDescription -Shows description about tasks. -.PARAMETER DryRun -Performs a dry run. -.PARAMETER Experimental -Uses the nightly builds of the Roslyn script engine. -.PARAMETER Mono -Uses the Mono Compiler rather than the Roslyn script engine. -.PARAMETER SkipToolPackageRestore -Skips restoring of packages. -.PARAMETER ScriptArgs -Remaining arguments are added here. -.LINK -https://cakebuild.net -#> - -[CmdletBinding()] -Param( - [string]$Script = "build.cake", - [string]$Target, - [string]$Configuration, - [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] - [string]$Verbosity, - [switch]$ShowDescription, - [Alias("WhatIf", "Noop")] - [switch]$DryRun, - [switch]$Experimental, - [switch]$Mono, - [switch]$SkipToolPackageRestore, - [Parameter(Position = 0, Mandatory = $false, ValueFromRemainingArguments = $true)] - [string[]]$ScriptArgs -) - -Write-Host "Preparing to run build script..." - -if (!$PSScriptRoot) { - $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent -} - -$CAKE_VERSION = "0.37.0" - -$TOOLS_DIR = Join-Path $PSScriptRoot "tools" -$CAKE_ROOT = Join-Path $TOOLS_DIR "/cake.coreclr/" -$CAKE_EXE = Join-Path $CAKE_ROOT "/Cake.dll" - -# Make sure that dotnet core installed. -try { - dotnet --version -} -catch { - Throw "Error: dotnet is not installed." -} - -# Install cake if its not installed -if (!(Test-Path $CAKE_EXE)) { - # Make sure tools folder exists - if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) { - Write-Verbose -Message "Creating tools directory..." - New-Item -Path $TOOLS_DIR -Type directory | out-null - } - - # Make sure that tools.csproj exist. - if (!(Test-Path "$TOOLS_DIR/tools.csproj")) { - Write-Verbose -Message "Creating tools.csproj..." - try { - New-Item "$TOOLS_DIR/tools.csproj" -ItemType file - "Exenetcoreapp3.1" | Out-File -FilePath "$TOOLS_DIR/tools.csproj" -Append - } - catch { - Throw "Could not download packages.config." - } - } - - $CAKE_NFW = Join-Path $TOOLS_DIR "/cake/" - - # Add dependencies - dotnet add $TOOLS_DIR/tools.csproj package Cake.CoreCLR -v $CAKE_VERSION --package-directory $TOOLS_DIR - # Add Cake.exe for VsCode intellisense support - dotnet add $TOOLS_DIR/tools.csproj package Cake -v $CAKE_VERSION --package-directory $TOOLS_DIR - - # Clean up - Move-Item -Path $CAKE_ROOT/$CAKE_VERSION/* -Destination $CAKE_ROOT - Remove-Item $CAKE_ROOT/$CAKE_VERSION/ -Force -Recurse - Move-Item -Path $CAKE_NFW/$CAKE_VERSION/* -Destination $CAKE_NFW - Remove-Item $CAKE_NFW/$CAKE_VERSION/ -Force -Recurse - Remove-Item $TOOLS_DIR/tools.csproj -} - -# Make sure that Cake has been installed. -if (!(Test-Path $CAKE_EXE)) { - Throw "Could not find Cake.dll at $CAKE_EXE" -} - -# Build Cake arguments -$cakeArguments = @("$Script"); -if ($Target) { $cakeArguments += "-target=$Target" } -if ($Configuration) { $cakeArguments += "-configuration=$Configuration" } -if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" } -if ($ShowDescription) { $cakeArguments += "-showdescription" } -if ($DryRun) { $cakeArguments += "-dryrun" } -if ($Experimental) { $cakeArguments += "-experimental" } -if ($Mono) { $cakeArguments += "-mono" } -$cakeArguments += $ScriptArgs - -# Start Cake -Write-Host "Running build script..." -&dotnet $TOOLS_DIR/cake.coreclr/Cake.dll $cakeArguments -exit $LASTEXITCODE \ No newline at end of file +dotnet build ./build/LocalStack.Build/LocalStack.Build.csproj >$null 2>&1 +dotnet run --project ./build/LocalStack.Build/LocalStack.Build.csproj --no-launch-profile --no-build -- $args +exit $LASTEXITCODE; \ No newline at end of file diff --git a/build.sh b/build.sh index 739b42e..2b2c46b 100644 --- a/build.sh +++ b/build.sh @@ -1,78 +1,2 @@ -#!/usr/bin/env bash - -########################################################################## -# This is the Cake bootstrapper script for Linux and OS X. -# This file is based on https://github.com/cake-build/resources modified for Cake.CoreCLR -# Feel free to change this file to fit your needs. -########################################################################## - -CAKE_VERSION=0.37.0 - -# Define directories. -SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -TOOLS_DIR=$SCRIPT_DIR/tools -CAKE_ROOT= $TOOLS_DIR/cake.coreclr/ -CAKE_EXE=$TOOLS_DIR/cake.coreclr/Cake.dll - -# Define default arguments. -SCRIPT="build.cake" -TARGET="Default" -CONFIGURATION="Release" -VERBOSITY="verbose" -DRYRUN= -SHOW_VERSION=false -CAKE_ARGUMENTS=() - -# Parse arguments. -for i in "$@"; do - case $1 in - -s|--script) SCRIPT="$2"; shift ;; - --) shift; CAKE_ARGUMENTS+=("$@"); break ;; - *) CAKE_ARGUMENTS+=("$1") ;; - esac - shift -done - -# Make sure that dotnet core installed. -if ! [ -x "$(command -v dotnet)" ]; then - echo 'Error: dotnet is not installed.' >&2 - exit 1 -fi - -# Install cake if its not installed -if [ ! -f "$CAKE_EXE" ]; then - - # Make sure the tools folder exist. - if [ ! -d "$TOOLS_DIR" ]; then - mkdir "$TOOLS_DIR" - fi - - # Make sure that tools.csproj exist. - if [ ! -f "$TOOLS_DIR/tools.csproj" ]; then - echo "Creating tools.csproj..." - echo "Exenetcoreapp3.1" > $TOOLS_DIR/tools.csproj - if [ $? -ne 0 ]; then - echo "An error occurred while creating tools.csproj." - exit 1 - fi - fi - - # Add dependencies - dotnet add $TOOLS_DIR/tools.csproj package Cake.CoreCLR -v $CAKE_VERSION --package-directory $TOOLS_DIR - mv $TOOLS_DIR/cake.coreclr/$CAKE_VERSION/* $TOOLS_DIR/cake.coreclr/ - rm -rf $TOOLS_DIR/cake.coreclr/$CAKE_VERSION/ - rm -f $TOOLS_DIR/tools.csproj -fi - -# Make sure that Cake has been installed. -if [ ! -f "$CAKE_EXE" ]; then - echo "Could not find Cake.exe at '$CAKE_EXE'." - exit 1 -fi - -# Start Cake -if $SHOW_VERSION; then - dotnet $TOOLS_DIR/cake.coreclr/Cake.dll -version -else - dotnet $TOOLS_DIR/cake.coreclr/Cake.dll $SCRIPT "${CAKE_ARGUMENTS[@]}" -fi \ No newline at end of file +dotnet build ./build/LocalStack.Build/LocalStack.Build.csproj > /dev/null 2>&1 +dotnet run --project ./build/LocalStack.Build/LocalStack.Build.csproj --no-launch-profile --no-build -- "$@" diff --git a/build/LocalStack.Build/BuildContext.cs b/build/LocalStack.Build/BuildContext.cs new file mode 100644 index 0000000..de00584 --- /dev/null +++ b/build/LocalStack.Build/BuildContext.cs @@ -0,0 +1,194 @@ +namespace LocalStack.Build; + +public sealed class BuildContext : FrostingContext +{ + public BuildContext(ICakeContext context) : base(context) + { + BuildConfiguration = context.Argument("config", "Release"); + ForceBuild = context.Argument("force-build", false); + ForceRestore = context.Argument("force-restore", false); + PackageVersion = context.Argument("package-version", "x.x.x"); + PackageId = context.Argument("package-id", default(string)); + PackageSecret = context.Argument("package-secret", default(string)); + PackageSource = context.Argument("package-source", default(string)); + + var sourceBuilder = ImmutableDictionary.CreateBuilder(); + sourceBuilder.AddRange(new[] + { + new KeyValuePair("myget", "https://www.myget.org/F/localstack-dotnet-client/api/v3/index.json"), + new KeyValuePair("nuget", "https://api.nuget.org/v3/index.json") + }); + PackageSourceMap = sourceBuilder.ToImmutable(); + + SolutionRoot = context.Directory("../../"); + SrcPath = SolutionRoot + context.Directory("src"); + TestsPath = SolutionRoot + context.Directory("tests"); + BuildPath = SolutionRoot + context.Directory("build"); + ArtifactOutput = SolutionRoot + context.Directory("artifacts"); + LocalStackAwsLocalFolder = SrcPath + context.Directory("LocalStack.AwsLocal"); + SlnFilePath = SolutionRoot + context.File("LocalStack.sln"); + LocalStackAwsLocalProjFile = LocalStackAwsLocalFolder + context.File("LocalStack.AwsLocal.csproj"); + + var packIdBuilder = ImmutableDictionary.CreateBuilder(); + packIdBuilder.AddRange(new[] + { + new KeyValuePair("LocalStack.AwsLocal", LocalStackAwsLocalProjFile), + }); + PackageIdProjMap = packIdBuilder.ToImmutable(); + } + + public string BuildConfiguration { get; } + + public bool ForceBuild { get; } + + public bool ForceRestore { get; } + + public string PackageVersion { get; } + + public string PackageId { get; } + + public string PackageSecret { get; } + + public string PackageSource { get; } + + public ImmutableDictionary PackageSourceMap { get; } + + public ImmutableDictionary PackageIdProjMap { get; } + + public ConvertableFilePath SlnFilePath { get; } + + public ConvertableDirectoryPath SolutionRoot { get; } + + public ConvertableDirectoryPath SrcPath { get; } + + public ConvertableDirectoryPath TestsPath { get; } + + public ConvertableDirectoryPath BuildPath { get; } + + public ConvertableDirectoryPath ArtifactOutput { get; } + + public ConvertableDirectoryPath LocalStackAwsLocalFolder { get; } + + public ConvertableFilePath LocalStackAwsLocalProjFile { get; } + + public static void ValidateArgument(string argumentName, string argument) + { + if (string.IsNullOrWhiteSpace(argument)) + { + throw new Exception($"{argumentName} can not be null or empty"); + } + } + + public void InstallXUnitNugetPackage() + { + if (!Directory.Exists("testrunner")) + { + Directory.CreateDirectory("testrunner"); + } + + var nugetInstallSettings = new NuGetInstallSettings + { + Version = "2.4.1", + Verbosity = NuGetVerbosity.Normal, + OutputDirectory = "testrunner", + WorkingDirectory = "." + }; + + this.NuGetInstall("xunit.runner.console", nugetInstallSettings); + } + + public IEnumerable GetProjMetadata() + { + DirectoryPath testsRoot = this.Directory(TestsPath); + List csProjFile = this.GetFiles($"{testsRoot}/**/*.csproj").Where(fp => fp.FullPath.EndsWith("Tests.csproj")).ToList(); + + IList projMetadata = new List(); + + foreach (FilePath csProj in csProjFile) + { + string csProjPath = csProj.FullPath; + + IEnumerable targetFrameworks = GetProjectTargetFrameworks(csProjPath); + string directoryPath = csProj.GetDirectory().FullPath; + string assemblyName = GetAssemblyName(csProjPath); + + var testProjMetadata = new ProjMetadata(directoryPath, csProjPath, targetFrameworks, assemblyName); + projMetadata.Add(testProjMetadata); + } + + return projMetadata; + } + + public void RunXUnitUsingMono(string targetFramework, string assemblyPath) + { + int exitCode = this.StartProcess("mono", new ProcessSettings + { + Arguments = $"./testrunner/xunit.runner.console.2.4.1/tools/{targetFramework}/xunit.console.exe {assemblyPath}" + }); + + if (exitCode != 0) + { + throw new InvalidOperationException($"Exit code: {exitCode}"); + } + } + + public string GetProjectVersion() + { + FilePath file = this.File("./src/Directory.Build.props"); + + this.Information(file.FullPath); + + string project = File.ReadAllText(file.FullPath, Encoding.UTF8); + int startIndex = project.IndexOf("", StringComparison.Ordinal) + "".Length; + int endIndex = project.IndexOf("", startIndex, StringComparison.Ordinal); + + string version = project.Substring(startIndex, endIndex - startIndex); + version = $"{version}.{PackageVersion}"; + + return version; + } + + private IEnumerable GetProjectTargetFrameworks(string csprojPath) + { + FilePath file = this.File(csprojPath); + string project = File.ReadAllText(file.FullPath, Encoding.UTF8); + + bool multipleFrameworks = project.Contains(""); + string startElement = multipleFrameworks ? "" : ""; + string endElement = multipleFrameworks ? "" : ""; + + int startIndex = project.IndexOf(startElement, StringComparison.Ordinal) + startElement.Length; + int endIndex = project.IndexOf(endElement, startIndex, StringComparison.Ordinal); + + string targetFrameworks = project.Substring(startIndex, endIndex - startIndex); + + return targetFrameworks.Split(';'); + } + + private string GetAssemblyName(string csprojPath) + { + FilePath file = this.File(csprojPath); + string project = File.ReadAllText(file.FullPath, Encoding.UTF8); + + bool assemblyNameElementExists = project.Contains(""); + + string assemblyName; + + if (assemblyNameElementExists) + { + int startIndex = project.IndexOf("", StringComparison.Ordinal) + "".Length; + int endIndex = project.IndexOf("", startIndex, StringComparison.Ordinal); + + assemblyName = project.Substring(startIndex, endIndex - startIndex); + } + else + { + int startIndex = csprojPath.LastIndexOf("/", StringComparison.Ordinal) + 1; + int endIndex = csprojPath.IndexOf(".csproj", startIndex, StringComparison.Ordinal); + + assemblyName = csprojPath.Substring(startIndex, endIndex - startIndex); + } + + return assemblyName; + } +} \ No newline at end of file diff --git a/build/LocalStack.Build/GlobalUsings.cs b/build/LocalStack.Build/GlobalUsings.cs new file mode 100644 index 0000000..e75d8a2 --- /dev/null +++ b/build/LocalStack.Build/GlobalUsings.cs @@ -0,0 +1,22 @@ +global using Cake.Common; +global using Cake.Common.Diagnostics; +global using Cake.Common.IO; +global using Cake.Common.IO.Paths; +global using Cake.Common.Tools.DotNet.MSBuild; +global using Cake.Common.Tools.NuGet; +global using Cake.Common.Tools.NuGet.Install; +global using Cake.Common.Tools.NuGet.List; +global using Cake.Core; +global using Cake.Core.IO; +global using Cake.Frosting; + +global using LocalStack.Build; +global using LocalStack.Build.Models; + +global using System; +global using System.Collections.Generic; +global using System.Collections.Immutable; +global using System.IO; +global using System.Linq; +global using System.Text; +global using System.Text.RegularExpressions; \ No newline at end of file diff --git a/build/LocalStack.Build/LocalStack.Build.csproj b/build/LocalStack.Build/LocalStack.Build.csproj new file mode 100644 index 0000000..95b892f --- /dev/null +++ b/build/LocalStack.Build/LocalStack.Build.csproj @@ -0,0 +1,12 @@ + + + Exe + net7.0 + $(MSBuildProjectDirectory) + latest + CA1303 + + + + + diff --git a/build/LocalStack.Build/Models/ProjMetadata.cs b/build/LocalStack.Build/Models/ProjMetadata.cs new file mode 100644 index 0000000..27a3dc9 --- /dev/null +++ b/build/LocalStack.Build/Models/ProjMetadata.cs @@ -0,0 +1,3 @@ +namespace LocalStack.Build.Models; + +public record ProjMetadata(string DirectoryPath, string CsProjPath, IEnumerable TargetFrameworks, string AssemblyName); \ No newline at end of file diff --git a/build/LocalStack.Build/Program.cs b/build/LocalStack.Build/Program.cs new file mode 100644 index 0000000..8cce5dd --- /dev/null +++ b/build/LocalStack.Build/Program.cs @@ -0,0 +1,187 @@ +using Cake.Common.Tools.DotNet; +using Cake.Common.Tools.DotNet.Build; +using Cake.Common.Tools.DotNet.NuGet.Push; +using Cake.Common.Tools.DotNet.Pack; +using Cake.Common.Tools.DotNet.Test; + +return new CakeHost() + .UseContext() + .Run(args); + +[TaskName("Default"), IsDependentOn(typeof(TestTask))] +public class DefaultTask : FrostingTask +{ +} + +[TaskName("init")] +public sealed class InitTask : FrostingTask +{ + public override void Run(BuildContext context) + { + context.StartProcess("dotnet", new ProcessSettings + { + Arguments = "--info" + }); + + if (!context.IsRunningOnUnix()) + { + return; + } + + context.StartProcess("git", new ProcessSettings + { + Arguments = "config --global core.autocrlf true" + }); + + context.StartProcess("mono", new ProcessSettings + { + Arguments = "--version" + }); + + context.InstallXUnitNugetPackage(); + } +} + +[TaskName("build"), IsDependentOn(typeof(InitTask)),] +public sealed class BuildTask : FrostingTask +{ + public override void Run(BuildContext context) + { + context.DotNetBuild(context.SlnFilePath, + new DotNetBuildSettings + { + Configuration = context.BuildConfiguration + }); + } +} + +[TaskName("tests"), IsDependentOn(typeof(BuildTask))] +public sealed class TestTask : FrostingTask +{ + public override void Run(BuildContext context) + { + const string testResults = "results.trx"; + + var settings = new DotNetTestSettings + { + NoRestore = !context.ForceRestore, + NoBuild = !context.ForceBuild, + Configuration = context.BuildConfiguration, + Blame = true + }; + + IEnumerable projMetadata = context.GetProjMetadata(); + + foreach (ProjMetadata testProj in projMetadata) + { + string testProjectPath = testProj.CsProjPath; + string targetFrameworks = string.Join(",", testProj.TargetFrameworks); + + context.Warning($"Target Frameworks {targetFrameworks}"); + + foreach (string targetFramework in testProj.TargetFrameworks) + { + context.Warning($"=============Running {targetFramework.ToUpper()} tests for {testProj.AssemblyName}============="); + settings.Framework = targetFramework; + + if (context.IsRunningOnUnix() && targetFramework == "net461") + { + context.RunXUnitUsingMono(targetFramework, $"{testProj.DirectoryPath}/bin/{context.BuildConfiguration}/{targetFramework}/{testProj.AssemblyName}.dll"); + } + else + { + string testFilePrefix = targetFramework.Replace(".", "-"); + settings.ArgumentCustomization = args => args.Append($" --logger \"trx;LogFileName={testFilePrefix}_{testResults}\""); + context.DotNetTest(testProjectPath, settings); + } + context.Warning("=============================================================="); + } + } + } +} + +[TaskName("nuget-pack")] +public sealed class NugetPackTask : FrostingTask +{ + public override void Run(BuildContext context) + { + ValidatePackageVersion(context); + + if (!Directory.Exists(context.ArtifactOutput)) + { + Directory.CreateDirectory(context.ArtifactOutput); + } + + FilePath packageCsProj = context.PackageIdProjMap[context.PackageId]; + + var settings = new DotNetPackSettings + { + Configuration = context.BuildConfiguration, + OutputDirectory = context.ArtifactOutput, + MSBuildSettings = new DotNetMSBuildSettings() + }; + + settings.MSBuildSettings.SetVersion(context.PackageVersion); + + context.DotNetPack(packageCsProj.FullPath, settings); + } + + private static void ValidatePackageVersion(BuildContext context) + { + BuildContext.ValidateArgument("package-id", context.PackageId); + BuildContext.ValidateArgument("package-version", context.PackageVersion); + BuildContext.ValidateArgument("package-source", context.PackageSource); + + Match match = Regex.Match(context.PackageVersion, @"^(\d+)\.(\d+)\.(\d+)(\.(\d+))*$", RegexOptions.IgnoreCase); + + if (!match.Success) + { + throw new Exception($"Invalid version: {context.PackageVersion}"); + } + + string packageSource = context.PackageSourceMap[context.PackageSource]; + + var nuGetListSettings = new NuGetListSettings { AllVersions = false, Source = new List() { packageSource } }; + NuGetListItem nuGetListItem = context.NuGetList(context.PackageId, nuGetListSettings).Single(item => item.Name == context.PackageId); + string latestPackVersionStr = nuGetListItem.Version; + + Version packageVersion = Version.Parse(context.PackageVersion); + Version latestPackVersion = Version.Parse(latestPackVersionStr); + + if (packageVersion <= latestPackVersion) + { + throw new Exception($"The new package version {context.PackageVersion} should be greater than the latest package version {latestPackVersionStr}"); + } + } +} + +[TaskName("nuget-push")] +public sealed class NugetPushTask : FrostingTask +{ + public override void Run(BuildContext context) + { + BuildContext.ValidateArgument("package-id", context.PackageId); + BuildContext.ValidateArgument("package-version", context.PackageVersion); + BuildContext.ValidateArgument("package-secret", context.PackageSecret); + BuildContext.ValidateArgument("package-source", context.PackageSource); + + string packageId = context.PackageId; + string packageVersion = context.PackageVersion; + + ConvertableFilePath packageFile = context.ArtifactOutput + context.File($"{packageId}.{packageVersion}.nupkg"); + + if (!context.FileExists(packageFile)) + { + throw new Exception($"The specified {packageFile.Path} package file does not exists"); + } + + string packageSecret = context.PackageSecret; + string packageSource = context.PackageSourceMap[context.PackageSource]; + + context.DotNetNuGetPush(packageFile.Path.FullPath, new DotNetNuGetPushSettings() + { + ApiKey = packageSecret, + Source = packageSource, + }); + } +} \ No newline at end of file diff --git a/build/LocalStack.Build/Properties/launchSettings-example.json b/build/LocalStack.Build/Properties/launchSettings-example.json new file mode 100644 index 0000000..e58c2de --- /dev/null +++ b/build/LocalStack.Build/Properties/launchSettings-example.json @@ -0,0 +1,13 @@ +{ + "profiles": { + "LocalStack.Build": { + "commandName": "Project", + "commandLineArgs": "--target nuget-push --package-version 1.2.3 --package-source myget --package-id LocalStack.Client --package-secret ************************" + }, + "WSL 2": { + "commandName": "WSL2", + "commandLineArgs": "--target get-version", + "distributionName": "Ubuntu-18.04" + } + } +} \ No newline at end of file diff --git a/build/azure-pipelines.artifact.yml b/build/azure-pipelines.artifact.yml deleted file mode 100644 index e407fce..0000000 --- a/build/azure-pipelines.artifact.yml +++ /dev/null @@ -1,60 +0,0 @@ -trigger: - branches: - include: - - master - - releases/* - - feature/* - paths: - exclude: - - README.md - - CONTRIBUTING.md - - LICENSE -pr: none -pool: - vmImage: ubuntu-18.04 -variables: - Version.MajorMinor: 1.3 - Version.Revision: $[counter(variables['Version.MajorMinor'], 0)] -steps: - - bash: "sudo apt install nuget && mkdir ./testrunner && sudo chmod -R 777 ./testrunner && ls" - displayName: "Init Task" - - - task: UseDotNet@2 - displayName: ".NET Core 5.0.x" - inputs: - version: "5.0.x" - packageType: sdk - - - task: UseDotNet@2 - displayName: ".NET Core 3.1.x" - inputs: - version: "3.1.x" - packageType: sdk - - - task: UseDotNet@2 - displayName: ".NET Core 2.1.x" - inputs: - version: "2.1.x" - packageType: sdk - - - task: Bash@3 - displayName: "Compile & Tests" - inputs: - targetType: filePath - filePath: ./build.sh - - - bash: echo $(Version.Revision) && chmod +x ./build.sh && sudo ./build.sh --target=get-version --buildnumber=$BUILD_ID - displayName: "Package Version" - env: - BUILD_ID: $(Version.Revision) - - - bash: chmod +x ./build.sh && sudo ./build.sh --target=nuget-pack --buildnumber=$BUILD_ID - displayName: "Nuget Pack" - env: - BUILD_ID: $(Version.Revision) - - - task: PublishBuildArtifacts@1 - displayName: "Publish Artifact: LocalStack.AwsLocal" - inputs: - PathtoPublish: artifacts/ - ArtifactName: LocalStack.AwsLocal diff --git a/build/azure-pipelines.macos.yml b/build/azure-pipelines.macos.yml deleted file mode 100644 index 77890c1..0000000 --- a/build/azure-pipelines.macos.yml +++ /dev/null @@ -1,53 +0,0 @@ -trigger: - branches: - include: - - "*" - paths: - exclude: - - README.md - - CONTRIBUTING.md - - LICENSE -pr: - branches: - include: - - "*" -schedules: - - cron: "0 12 * * 0" - displayName: Weekly Sunday build - branches: - include: - - master - always: true -pool: - vmImage: macOS-10.14 -steps: - - - task: UseDotNet@2 - displayName: ".NET Core 5.0.x" - inputs: - version: "5.0.x" - packageType: sdk - - - task: UseDotNet@2 - displayName: ".NET Core 3.1.x" - inputs: - version: "3.1.x" - packageType: sdk - - - task: UseDotNet@2 - displayName: ".NET Core 2.1.x" - inputs: - version: "2.1.x" - packageType: sdk - - - task: Bash@3 - displayName: "Compile & Tests" - inputs: - targetType: filePath - filePath: ./build.sh - - - task: PublishTestResults@2 - inputs: - testResultsFormat: "VSTest" - testResultsFiles: "**/*.trx" - testRunTitle: "LocalStack.AwsLocal.Tests" diff --git a/build/azure-pipelines.ubuntu.yml b/build/azure-pipelines.ubuntu.yml deleted file mode 100644 index 443b5b0..0000000 --- a/build/azure-pipelines.ubuntu.yml +++ /dev/null @@ -1,55 +0,0 @@ -trigger: - branches: - include: - - "*" - paths: - exclude: - - README.md - - CONTRIBUTING.md - - LICENSE -pr: - branches: - include: - - "*" -schedules: - - cron: "0 12 * * 0" - displayName: Weekly Sunday build - branches: - include: - - master - always: true -pool: - vmImage: ubuntu-18.04 -steps: - - bash: "sudo apt install nuget && mkdir ./testrunner && sudo chmod -R 777 ./testrunner && ls" - displayName: "Init Task" - - - task: UseDotNet@2 - displayName: ".NET Core 5.0.x" - inputs: - version: "5.0.x" - packageType: sdk - - - task: UseDotNet@2 - displayName: ".NET Core 3.1.x" - inputs: - version: "3.1.x" - packageType: sdk - - - task: UseDotNet@2 - displayName: ".NET Core 2.1.x" - inputs: - version: "2.1.x" - packageType: sdk - - - task: Bash@3 - displayName: "Compile & Tests" - inputs: - targetType: filePath - filePath: ./build.sh - - - task: PublishTestResults@2 - inputs: - testResultsFormat: "VSTest" - testResultsFiles: "**/*.trx" - testRunTitle: "LocalStack.AwsLocal.Tests" diff --git a/build/azure-pipelines.windows.yml b/build/azure-pipelines.windows.yml deleted file mode 100644 index ed3e721..0000000 --- a/build/azure-pipelines.windows.yml +++ /dev/null @@ -1,37 +0,0 @@ -trigger: - branches: - include: - - "*" - paths: - exclude: - - README.md - - CONTRIBUTING.md - - LICENSE -pr: - branches: - include: - - "*" -schedules: - - cron: "0 12 * * 0" - displayName: Weekly Sunday build - branches: - include: - - master - always: true -pool: - vmImage: windows-2019 -steps: - - checkout: self - submodules: true - - - task: PowerShell@2 - displayName: "Compile & Tests" - inputs: - targetType: filePath - filePath: ./build.ps1 - - - task: PublishTestResults@2 - inputs: - testResultsFormat: "VSTest" - testResultsFiles: "**/*.trx" - testRunTitle: "LocalStack.AwsLocal.Tests" diff --git a/build/scripts/packageUpdate.ps1 b/build/scripts/packageUpdate.ps1 new file mode 100644 index 0000000..48318fe --- /dev/null +++ b/build/scripts/packageUpdate.ps1 @@ -0,0 +1,17 @@ +$regex = 'PackageReference Include="([^"]*)" Version="([^"]*)"' + +ForEach ($file in get-childitem . -recurse | where {$_.extension -like "*proj"}) +{ + $packages = Get-Content $file.FullName | + select-string -pattern $regex -AllMatches | + ForEach-Object {$_.Matches} | + ForEach-Object {$_.Groups[1].Value.ToString()}| + sort -Unique + + ForEach ($package in $packages) + { + write-host "Update $file package :$package" -foreground 'magenta' + $fullName = $file.FullName + iex "dotnet add $fullName package $package" + } +} \ No newline at end of file