diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 00000000..c611527d
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,52 @@
+# ------------------------------------------------------------------------------
+#
+#
+# This code was generated.
+#
+# - To turn off auto-generation set:
+#
+# [GitHubActions (AutoGenerate = false)]
+#
+# - To trigger manual generation invoke:
+#
+# nuke --generate-configuration GitHubActions_build --host GitHubActions
+#
+#
+# ------------------------------------------------------------------------------
+
+name: build
+
+on:
+ push:
+ branches:
+ - master
+ - main
+ tags:
+ - 'v*.*.*'
+ paths:
+ - '**/*.*'
+ - '!**/*.md'
+
+jobs:
+ ubuntu-latest:
+ name: ubuntu-latest
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: 'Cache: .nuke/temp, ~/.nuget/packages'
+ uses: actions/cache@v3
+ with:
+ path: |
+ .nuke/temp
+ ~/.nuget/packages
+ key: ${{ runner.os }}-${{ hashFiles('global.json', 'src/**/*.csproj', 'src/**/package.json') }}
+ - name: 'Run: Compile, Test, Pack, Publish'
+ run: ./build.cmd Compile Test Pack Publish
+ env:
+ NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
+ MYGET_API_KEY: ${{ secrets.MYGET_API_KEY }}
+ - name: 'Publish: artifacts'
+ uses: actions/upload-artifact@v3
+ with:
+ name: artifacts
+ path: artifacts
diff --git a/.github/workflows/dotnet-core.yml b/.github/workflows/dotnet-core.yml
deleted file mode 100644
index eb3d4556..00000000
--- a/.github/workflows/dotnet-core.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: Build & Test
-
-on:
- pull_request:
- branches: [ master ]
-
-jobs:
- build:
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v2
- - name: Setup .NET Core
- uses: actions/setup-dotnet@v1
- with:
- dotnet-version: 3.1.101
- - name: Install dependencies
- run: dotnet restore
- - name: Build
- run: dotnet build --configuration Release --no-restore
- - name: Test
- run: dotnet test --no-restore --verbosity normal
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
new file mode 100644
index 00000000..2ae90d48
--- /dev/null
+++ b/.github/workflows/pr.yml
@@ -0,0 +1,56 @@
+# ------------------------------------------------------------------------------
+#
+#
+# This code was generated.
+#
+# - To turn off auto-generation set:
+#
+# [GitHubActions (AutoGenerate = false)]
+#
+# - To trigger manual generation invoke:
+#
+# nuke --generate-configuration GitHubActions_pr --host GitHubActions
+#
+#
+# ------------------------------------------------------------------------------
+
+name: pr
+
+on:
+ pull_request:
+ branches:
+ - master
+ - main
+ paths:
+ - '**/*.*'
+ - '!**/*.md'
+
+jobs:
+ windows-latest:
+ name: windows-latest
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: 'Cache: .nuke/temp, ~/.nuget/packages'
+ uses: actions/cache@v3
+ with:
+ path: |
+ .nuke/temp
+ ~/.nuget/packages
+ key: ${{ runner.os }}-${{ hashFiles('global.json', 'src/**/*.csproj', 'src/**/package.json') }}
+ - name: 'Run: Compile, Test, Pack'
+ run: ./build.cmd Compile Test Pack
+ ubuntu-latest:
+ name: ubuntu-latest
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: 'Cache: .nuke/temp, ~/.nuget/packages'
+ uses: actions/cache@v3
+ with:
+ path: |
+ .nuke/temp
+ ~/.nuget/packages
+ key: ${{ runner.os }}-${{ hashFiles('global.json', 'src/**/*.csproj', 'src/**/package.json') }}
+ - name: 'Run: Compile, Test, Pack'
+ run: ./build.cmd Compile Test Pack
diff --git a/.gitignore b/.gitignore
index 47a88458..e9b9b7f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,16 +12,8 @@ appsettings.development.json
*.userprefs
# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-[Xx]64/
-[Xx]86/
-[Bb]uild/
-bld/
-[Bb]in/
-[Oo]bj/
+**/bin/**
+**/obj/**
# Visual Studio 2015 cache/options directory
.vs/
diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json
new file mode 100644
index 00000000..77854d44
--- /dev/null
+++ b/.nuke/build.schema.json
@@ -0,0 +1,124 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "$ref": "#/definitions/build",
+ "title": "Build Schema",
+ "definitions": {
+ "build": {
+ "type": "object",
+ "properties": {
+ "Configuration": {
+ "type": "string",
+ "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)",
+ "enum": [
+ "Debug",
+ "Release"
+ ]
+ },
+ "Continue": {
+ "type": "boolean",
+ "description": "Indicates to continue a previously failed build attempt"
+ },
+ "Help": {
+ "type": "boolean",
+ "description": "Shows the help text for this build assembly"
+ },
+ "Host": {
+ "type": "string",
+ "description": "Host for execution. Default is 'automatic'",
+ "enum": [
+ "AppVeyor",
+ "AzurePipelines",
+ "Bamboo",
+ "Bitbucket",
+ "Bitrise",
+ "GitHubActions",
+ "GitLab",
+ "Jenkins",
+ "Rider",
+ "SpaceAutomation",
+ "TeamCity",
+ "Terminal",
+ "TravisCI",
+ "VisualStudio",
+ "VSCode"
+ ]
+ },
+ "MyGetApiKey": {
+ "type": "string",
+ "default": "Secrets must be entered via 'nuke :secrets [profile]'"
+ },
+ "NoLogo": {
+ "type": "boolean",
+ "description": "Disables displaying the NUKE logo"
+ },
+ "NuGetApiKey": {
+ "type": "string",
+ "default": "Secrets must be entered via 'nuke :secrets [profile]'"
+ },
+ "Partition": {
+ "type": "string",
+ "description": "Partition to use on CI"
+ },
+ "Plan": {
+ "type": "boolean",
+ "description": "Shows the execution plan (HTML)"
+ },
+ "Profile": {
+ "type": "array",
+ "description": "Defines the profiles to load",
+ "items": {
+ "type": "string"
+ }
+ },
+ "Root": {
+ "type": "string",
+ "description": "Root directory during build execution"
+ },
+ "Skip": {
+ "type": "array",
+ "description": "List of targets to be skipped. Empty list skips all dependencies",
+ "items": {
+ "type": "string",
+ "enum": [
+ "Clean",
+ "Compile",
+ "Pack",
+ "Publish",
+ "Restore",
+ "Test"
+ ]
+ }
+ },
+ "Solution": {
+ "type": "string",
+ "description": "Path to a solution file that is automatically loaded"
+ },
+ "Target": {
+ "type": "array",
+ "description": "List of targets to be invoked. Default is '{default_target}'",
+ "items": {
+ "type": "string",
+ "enum": [
+ "Clean",
+ "Compile",
+ "Pack",
+ "Publish",
+ "Restore",
+ "Test"
+ ]
+ }
+ },
+ "Verbosity": {
+ "type": "string",
+ "description": "Logging verbosity during build execution. Default is 'Normal'",
+ "enum": [
+ "Minimal",
+ "Normal",
+ "Quiet",
+ "Verbose"
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/.nuke/parameters.json b/.nuke/parameters.json
new file mode 100644
index 00000000..59c4f855
--- /dev/null
+++ b/.nuke/parameters.json
@@ -0,0 +1,4 @@
+{
+ "$schema": "./build.schema.json",
+ "Solution": "FluentEmail.sln"
+}
\ No newline at end of file
diff --git a/FluentEmail.sln b/FluentEmail.sln
index 7b3ce08e..036074d2 100644
--- a/FluentEmail.sln
+++ b/FluentEmail.sln
@@ -43,12 +43,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentEmail.Liquid", "src\R
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentEmail.Liquid.Tests", "test\FluentEmail.Liquid.Tests\FluentEmail.Liquid.Tests.csproj", "{C8063CBA-D8F3-467A-A75C-63843F0DE862}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{FBF3809D-D89B-4CE4-89D8-3B2A9B7B7F9D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FBF3809D-D89B-4CE4-89D8-3B2A9B7B7F9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBF3809D-D89B-4CE4-89D8-3B2A9B7B7F9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{386B8AB1-E99A-4E08-83BE-DD1B8C2EE876}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{386B8AB1-E99A-4E08-83BE-DD1B8C2EE876}.Debug|Any CPU.Build.0 = Debug|Any CPU
{386B8AB1-E99A-4E08-83BE-DD1B8C2EE876}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/build.cmd b/build.cmd
new file mode 100755
index 00000000..b08cc590
--- /dev/null
+++ b/build.cmd
@@ -0,0 +1,7 @@
+:; set -eo pipefail
+:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
+:; ${SCRIPT_DIR}/build.sh "$@"
+:; exit $?
+
+@ECHO OFF
+powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %*
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 00000000..c0c0e612
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,74 @@
+[CmdletBinding()]
+Param(
+ [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
+ [string[]]$BuildArguments
+)
+
+Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)"
+
+Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 }
+$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
+
+###########################################################################
+# CONFIGURATION
+###########################################################################
+
+$BuildProjectFile = "$PSScriptRoot\build\_build.csproj"
+$TempDirectory = "$PSScriptRoot\\.nuke\temp"
+
+$DotNetGlobalFile = "$PSScriptRoot\\global.json"
+$DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1"
+$DotNetChannel = "STS"
+
+$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
+$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
+$env:DOTNET_MULTILEVEL_LOOKUP = 0
+
+###########################################################################
+# EXECUTION
+###########################################################################
+
+function ExecSafe([scriptblock] $cmd) {
+ & $cmd
+ if ($LASTEXITCODE) { exit $LASTEXITCODE }
+}
+
+# If dotnet CLI is installed globally and it matches requested version, use for execution
+if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and `
+ $(dotnet --version) -and $LASTEXITCODE -eq 0) {
+ $env:DOTNET_EXE = (Get-Command "dotnet").Path
+}
+else {
+ # Download install script
+ $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
+ New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null
+ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+ (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
+
+ # If global.json exists, load expected version
+ if (Test-Path $DotNetGlobalFile) {
+ $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
+ if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
+ $DotNetVersion = $DotNetGlobal.sdk.version
+ }
+ }
+
+ # Install by channel or version
+ $DotNetDirectory = "$TempDirectory\dotnet-win"
+ if (!(Test-Path variable:DotNetVersion)) {
+ ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
+ } else {
+ ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
+ }
+ $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
+}
+
+Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)"
+
+if (Test-Path env:NUKE_ENTERPRISE_TOKEN) {
+ & $env:DOTNET_EXE nuget remove source "nuke-enterprise" > $null
+ & $env:DOTNET_EXE nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password $env:NUKE_ENTERPRISE_TOKEN > $null
+}
+
+ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet }
+ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments }
diff --git a/build.sh b/build.sh
new file mode 100755
index 00000000..2f10dcb5
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,67 @@
+#!/usr/bin/env bash
+
+bash --version 2>&1 | head -n 1
+
+set -eo pipefail
+SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
+
+###########################################################################
+# CONFIGURATION
+###########################################################################
+
+BUILD_PROJECT_FILE="$SCRIPT_DIR/build/_build.csproj"
+TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp"
+
+DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
+DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh"
+DOTNET_CHANNEL="STS"
+
+export DOTNET_CLI_TELEMETRY_OPTOUT=1
+export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
+export DOTNET_MULTILEVEL_LOOKUP=0
+
+###########################################################################
+# EXECUTION
+###########################################################################
+
+function FirstJsonValue {
+ perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}"
+}
+
+# If dotnet CLI is installed globally and it matches requested version, use for execution
+if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then
+ export DOTNET_EXE="$(command -v dotnet)"
+else
+ # Download install script
+ DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
+ mkdir -p "$TEMP_DIRECTORY"
+ curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
+ chmod +x "$DOTNET_INSTALL_FILE"
+
+ # If global.json exists, load expected version
+ if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then
+ DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")")
+ if [[ "$DOTNET_VERSION" == "" ]]; then
+ unset DOTNET_VERSION
+ fi
+ fi
+
+ # Install by channel or version
+ DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
+ if [[ -z ${DOTNET_VERSION+x} ]]; then
+ "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
+ else
+ "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
+ fi
+ export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
+fi
+
+echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)"
+
+if [[ ! -z ${NUKE_ENTERPRISE_TOKEN+x} && "$NUKE_ENTERPRISE_TOKEN" != "" ]]; then
+ "$DOTNET_EXE" nuget remove source "nuke-enterprise" &>/dev/null || true
+ "$DOTNET_EXE" nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password "$NUKE_ENTERPRISE_TOKEN" --store-password-in-clear-text &>/dev/null || true
+fi
+
+"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet
+"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@"
diff --git a/build/.editorconfig b/build/.editorconfig
new file mode 100644
index 00000000..31e43dcd
--- /dev/null
+++ b/build/.editorconfig
@@ -0,0 +1,11 @@
+[*.cs]
+dotnet_style_qualification_for_field = false:warning
+dotnet_style_qualification_for_property = false:warning
+dotnet_style_qualification_for_method = false:warning
+dotnet_style_qualification_for_event = false:warning
+dotnet_style_require_accessibility_modifiers = never:warning
+
+csharp_style_expression_bodied_methods = true:silent
+csharp_style_expression_bodied_properties = true:warning
+csharp_style_expression_bodied_indexers = true:warning
+csharp_style_expression_bodied_accessors = true:warning
diff --git a/build/Build.CI.GitHubActions.cs b/build/Build.CI.GitHubActions.cs
new file mode 100644
index 00000000..74d67155
--- /dev/null
+++ b/build/Build.CI.GitHubActions.cs
@@ -0,0 +1,28 @@
+using Nuke.Common.CI.GitHubActions;
+
+[GitHubActions(
+ "pr",
+ GitHubActionsImage.WindowsLatest,
+ GitHubActionsImage.UbuntuLatest,
+ OnPullRequestBranches = new[] { "master", "main" },
+ OnPullRequestIncludePaths = new[] { "**/*.*" },
+ OnPullRequestExcludePaths = new[] { "**/*.md" },
+ PublishArtifacts = false,
+ InvokedTargets = new[] { nameof(Compile), nameof(Test), nameof(Pack) },
+ CacheKeyFiles = new[] { "global.json", "src/**/*.csproj", "src/**/package.json" }),
+]
+[GitHubActions(
+ "build",
+ GitHubActionsImage.UbuntuLatest,
+ OnPushBranches = new[] { "master", "main" },
+ OnPushTags = new[] { "v*.*.*" },
+ OnPushIncludePaths = new[] { "**/*.*" },
+ OnPushExcludePaths = new[] { "**/*.md" },
+ PublishArtifacts = true,
+ InvokedTargets = new[] { nameof(Compile), nameof(Test), nameof(Pack), nameof(Publish) },
+ ImportSecrets = new [] { "NUGET_API_KEY", "MYGET_API_KEY" },
+ CacheKeyFiles = new[] { "global.json", "src/**/*.csproj", "src/**/package.json" })
+]
+public partial class Build
+{
+}
diff --git a/build/Build.Publish.cs b/build/Build.Publish.cs
new file mode 100644
index 00000000..dd477d3e
--- /dev/null
+++ b/build/Build.Publish.cs
@@ -0,0 +1,56 @@
+using System.Collections.Generic;
+
+using Nuke.Common;
+using Nuke.Common.Git;
+using Nuke.Common.IO;
+using Nuke.Common.Tooling;
+using Nuke.Common.Tools.DotNet;
+
+using static Nuke.Common.Tools.DotNet.DotNetTasks;
+
+public partial class Build
+{
+ string NuGetSource => "https://api.nuget.org/v3/index.json";
+ [Parameter] [Secret] string NuGetApiKey;
+
+ string MyGetGetSource => "https://www.myget.org/F/fluentemail/api/v2/package";
+ [Parameter] [Secret] string MyGetApiKey;
+
+ string ApiKeyToUse => IsTaggedBuild ? NuGetApiKey : MyGetApiKey;
+ string SourceToUse => IsTaggedBuild ? NuGetSource : MyGetGetSource;
+
+ Target Publish => _ => _
+ .OnlyWhenDynamic(() => IsRunningOnLinux && (GitRepository.IsOnMainOrMasterBranch() || IsTaggedBuild))
+ .DependsOn(Pack)
+ .Requires(() => NuGetApiKey, () => MyGetApiKey)
+ .Executes(() =>
+ {
+ if (SourceToUse == MyGetGetSource && !string.IsNullOrWhiteSpace(MyGetApiKey))
+ {
+ Serilog.Log.Warning("MyGet not configured, skipping publish");
+ return;
+ }
+
+ DotNetNuGetPush(_ => _
+ .Apply(PushSettingsBase)
+ .Apply(PushSettings)
+ .CombineWith(PushPackageFiles, (_, v) => _
+ .SetTargetPath(v))
+ .Apply(PackagePushSettings),
+ PushDegreeOfParallelism,
+ PushCompleteOnFailure);
+ });
+
+ Configure PushSettingsBase => _ => _
+ .SetSource(SourceToUse)
+ .SetApiKey(ApiKeyToUse)
+ .SetSkipDuplicate(true);
+
+ Configure PushSettings => _ => _;
+ Configure PackagePushSettings => _ => _;
+
+ IEnumerable PushPackageFiles => ArtifactsDirectory.GlobFiles("*.nupkg");
+
+ bool PushCompleteOnFailure => true;
+ int PushDegreeOfParallelism => 2;
+}
\ No newline at end of file
diff --git a/build/Build.cs b/build/Build.cs
new file mode 100644
index 00000000..02c5c5d0
--- /dev/null
+++ b/build/Build.cs
@@ -0,0 +1,149 @@
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Xml.Linq;
+using Nuke.Common;
+using Nuke.Common.Git;
+using Nuke.Common.IO;
+using Nuke.Common.ProjectModel;
+using Nuke.Common.Tools.DotNet;
+using Nuke.Common.Utilities.Collections;
+
+using static Nuke.Common.Tools.DotNet.DotNetTasks;
+
+partial class Build : NukeBuild
+{
+ /// Support plugins are available for:
+ /// - JetBrains ReSharper https://nuke.build/resharper
+ /// - JetBrains Rider https://nuke.build/rider
+ /// - Microsoft VisualStudio https://nuke.build/visualstudio
+ /// - Microsoft VSCode https://nuke.build/vscode
+
+ public static int Main () => Execute(x => x.Compile);
+
+ [Solution] readonly Solution Solution;
+ [GitRepository] readonly GitRepository GitRepository;
+
+ [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")]
+ readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release;
+
+ AbsolutePath SourceDirectory => RootDirectory / "src";
+
+ AbsolutePath ArtifactsDirectory => RootDirectory / "artifacts";
+
+ bool IsTaggedBuild;
+ string VersionPrefix;
+ string VersionSuffix;
+
+ static bool IsRunningOnLinux => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
+
+ string DetermineVersionPrefix()
+ {
+ var versionPrefix = GitRepository.Tags.SingleOrDefault(x => x.StartsWith("v"))?[1..];
+ if (!string.IsNullOrWhiteSpace(versionPrefix))
+ {
+ IsTaggedBuild = true;
+ Serilog.Log.Information("Tag version {VersionPrefix} from Git found, using it as version prefix", VersionPrefix);
+ }
+ else
+ {
+ var propsDocument = XDocument.Parse((SourceDirectory / "Directory.Build.props").ReadAllText());
+ versionPrefix = propsDocument.Element("Project").Element("PropertyGroup").Element("VersionPrefix").Value;
+ Serilog.Log.Information("Version prefix {VersionPrefix} read from Directory.Build.props", versionPrefix);
+ }
+
+ return versionPrefix;
+ }
+
+ protected override void OnBuildInitialized()
+ {
+ VersionPrefix = DetermineVersionPrefix();
+
+ VersionSuffix = !IsTaggedBuild
+ ? $"preview-{DateTime.UtcNow:yyyyMMdd-HHmm}"
+ : "";
+
+ if (IsLocalBuild)
+ {
+ VersionSuffix = $"dev-{DateTime.UtcNow:yyyyMMdd-HHmm}";
+ }
+
+ Serilog.Log.Information("BUILD SETUP");
+ Serilog.Log.Information("Configuration:\t{Configuration}", Configuration);
+ Serilog.Log.Information("Version prefix:\t{VersionPrefix}", VersionPrefix);
+ Serilog.Log.Information("Version suffix:\t{VersionSuffix}", VersionSuffix);
+ Serilog.Log.Information("Tagged build:\t{IsTaggedBuild}", IsTaggedBuild);
+ }
+
+ Target Clean => _ => _
+ .Before(Restore)
+ .Executes(() =>
+ {
+ SourceDirectory.GlobDirectories("**/bin", "**/obj").ForEach(x => x.DeleteDirectory());
+ ArtifactsDirectory.CreateOrCleanDirectory();
+ });
+
+ Target Restore => _ => _
+ .Executes(() =>
+ {
+ DotNetRestore(s => s
+ .SetProjectFile(Solution));
+ });
+
+ Target Compile => _ => _
+ .DependsOn(Restore)
+ .Executes(() =>
+ {
+ DotNetBuild(s => s
+ .SetProjectFile(Solution)
+ .SetAssemblyVersion(VersionPrefix)
+ .SetFileVersion(VersionPrefix)
+ .SetInformationalVersion(VersionPrefix)
+ .SetConfiguration(Configuration)
+ .EnableNoRestore()
+ .SetDeterministic(IsServerBuild)
+ .SetContinuousIntegrationBuild(IsServerBuild)
+ );
+ });
+
+ Target Test => _ => _
+ .After(Compile)
+ .Executes(() =>
+ {
+ DotNetTest(s => s
+ .SetProjectFile(Solution)
+ .SetConfiguration(Configuration)
+ .EnableNoRestore()
+ );
+ });
+
+ Target Pack => _ => _
+ .After(Test, Compile)
+ .Produces(ArtifactsDirectory / "*.*")
+ .Executes(() =>
+ {
+ if (Configuration != Configuration.Release)
+ {
+ throw new InvalidOperationException("Cannot pack if compilation hasn't been done in Release mode, use --configuration Release");
+ }
+
+ var nugetVersion = VersionPrefix;
+ if (!string.IsNullOrWhiteSpace(VersionSuffix))
+ {
+ nugetVersion += "-" + VersionSuffix;
+ }
+
+ ArtifactsDirectory.CreateOrCleanDirectory();
+
+ DotNetPack(s => s
+ .SetAssemblyVersion(VersionPrefix)
+ .SetFileVersion(VersionPrefix)
+ .SetInformationalVersion(VersionPrefix)
+ .SetVersion(nugetVersion)
+ .SetConfiguration(Configuration)
+ .SetOutputDirectory(ArtifactsDirectory)
+ .SetDeterministic(IsServerBuild)
+ .SetContinuousIntegrationBuild(IsServerBuild)
+ );
+ });
+}
diff --git a/build/Configuration.cs b/build/Configuration.cs
new file mode 100644
index 00000000..9b22a3bd
--- /dev/null
+++ b/build/Configuration.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel;
+using Nuke.Common.Tooling;
+
+[TypeConverter(typeof(TypeConverter))]
+public class Configuration : Enumeration
+{
+ public static Configuration Debug = new Configuration { Value = nameof(Debug) };
+ public static Configuration Release = new Configuration { Value = nameof(Release) };
+
+ public static implicit operator string(Configuration configuration)
+ {
+ return configuration.Value;
+ }
+}
diff --git a/build/Directory.Build.props b/build/Directory.Build.props
new file mode 100644
index 00000000..e147d635
--- /dev/null
+++ b/build/Directory.Build.props
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/build/Directory.Build.targets b/build/Directory.Build.targets
new file mode 100644
index 00000000..25326095
--- /dev/null
+++ b/build/Directory.Build.targets
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/build/_build.csproj b/build/_build.csproj
new file mode 100644
index 00000000..1ba62d5e
--- /dev/null
+++ b/build/_build.csproj
@@ -0,0 +1,19 @@
+
+
+
+ Exe
+ net6.0
+
+ CS0649;CS0169
+ ..
+ ..
+ 1
+ true
+ true
+
+
+
+
+
+
+
diff --git a/build/_build.csproj.DotSettings b/build/_build.csproj.DotSettings
new file mode 100644
index 00000000..7bc28484
--- /dev/null
+++ b/build/_build.csproj.DotSettings
@@ -0,0 +1,27 @@
+
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ Implicit
+ Implicit
+ ExpressionBody
+ 0
+ NEXT_LINE
+ True
+ False
+ 120
+ IF_OWNER_IS_SINGLE_LINE
+ WRAP_IF_LONG
+ False
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index e2b23164..6d86d5b6 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -9,8 +9,8 @@
https://github.com/lukencode/FluentEmail
https://github.com/lukencode/FluentEmail
MIT
- 3.0.2
+ 3.0.2
true
true
@@ -36,7 +36,7 @@
-
+
diff --git a/src/Renderers/FluentEmail.Liquid/FluentEmail.Liquid.csproj b/src/Renderers/FluentEmail.Liquid/FluentEmail.Liquid.csproj
index dceefbab..6c650514 100644
--- a/src/Renderers/FluentEmail.Liquid/FluentEmail.Liquid.csproj
+++ b/src/Renderers/FluentEmail.Liquid/FluentEmail.Liquid.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/src/Senders/FluentEmail.Mailgun/FluentEmail.Mailgun.csproj b/src/Senders/FluentEmail.Mailgun/FluentEmail.Mailgun.csproj
index 2ad7eff6..02782a0a 100644
--- a/src/Senders/FluentEmail.Mailgun/FluentEmail.Mailgun.csproj
+++ b/src/Senders/FluentEmail.Mailgun/FluentEmail.Mailgun.csproj
@@ -8,7 +8,7 @@
-
+
diff --git a/test/Directory.Build.props b/test/Directory.Build.props
index b35672c9..8919cacb 100644
--- a/test/Directory.Build.props
+++ b/test/Directory.Build.props
@@ -4,12 +4,6 @@
false
true
-
-
-
-
-
-
diff --git a/test/FluentEmail.Core.Tests/FluentEmail.Core.Tests.csproj b/test/FluentEmail.Core.Tests/FluentEmail.Core.Tests.csproj
index cc26ca67..ce07c919 100644
--- a/test/FluentEmail.Core.Tests/FluentEmail.Core.Tests.csproj
+++ b/test/FluentEmail.Core.Tests/FluentEmail.Core.Tests.csproj
@@ -1,24 +1,24 @@
- netcoreapp3.1
+ net6.0
true
-
-
+
+
+
+
+
-
-
-
-
-
-
+
+
+
@@ -26,16 +26,10 @@
-
- PreserveNewest
-
+
-
- PreserveNewest
-
-
- PreserveNewest
-
+
+
diff --git a/test/FluentEmail.Core.Tests/MailgunSenderTests.cs b/test/FluentEmail.Core.Tests/MailgunSenderTests.cs
index 40cb8bf9..072b4390 100644
--- a/test/FluentEmail.Core.Tests/MailgunSenderTests.cs
+++ b/test/FluentEmail.Core.Tests/MailgunSenderTests.cs
@@ -7,6 +7,7 @@
namespace FluentEmail.Mailgun.Tests
{
+ [Explicit("Requires a valid sender name and API key")]
public class MailgunSenderTests
{
const string toEmail = "bentest1@mailinator.com";
diff --git a/test/FluentEmail.Liquid.Tests/FluentEmail.Liquid.Tests.csproj b/test/FluentEmail.Liquid.Tests/FluentEmail.Liquid.Tests.csproj
index e2c5dcfc..78d329a6 100644
--- a/test/FluentEmail.Liquid.Tests/FluentEmail.Liquid.Tests.csproj
+++ b/test/FluentEmail.Liquid.Tests/FluentEmail.Liquid.Tests.csproj
@@ -1,7 +1,7 @@
- netcoreapp3.1
+ net6.0
true
@@ -14,23 +14,17 @@
-
-
-
+
-
-
-
-
-
-
-
+
+
+
diff --git a/test/FluentEmail.Razor.Tests/FluentEmail.Razor.Tests.csproj b/test/FluentEmail.Razor.Tests/FluentEmail.Razor.Tests.csproj
index 2b40ef07..7edafa8d 100644
--- a/test/FluentEmail.Razor.Tests/FluentEmail.Razor.Tests.csproj
+++ b/test/FluentEmail.Razor.Tests/FluentEmail.Razor.Tests.csproj
@@ -1,7 +1,7 @@
- netcoreapp3.1
+ net6.0
true
@@ -23,16 +23,14 @@
-
-
-
-
-
+
+
+