mirror of
https://github.com/ElectronNET/Electron.NET.git
synced 2026-02-04 05:34:51 +00:00
Prepare for NUKE
This commit is contained in:
47
.github/workflows/ci.yml
vendored
Normal file
47
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup dotnet
|
||||||
|
uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: |
|
||||||
|
6.0.x
|
||||||
|
7.0.x
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: ./build.sh
|
||||||
|
|
||||||
|
windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup dotnet
|
||||||
|
uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: |
|
||||||
|
6.0.x
|
||||||
|
7.0.x
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
if ($env:GITHUB_REF -eq "refs/heads/main") {
|
||||||
|
.\build.ps1 -Target Publish
|
||||||
|
} elseif ($env:GITHUB_REF -eq "refs/heads/develop") {
|
||||||
|
.\build.ps1 -Target PrePublish
|
||||||
|
} else {
|
||||||
|
.\build.ps1
|
||||||
|
}
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -263,3 +263,6 @@ __pycache__/
|
|||||||
|
|
||||||
# Mac Only settings file
|
# Mac Only settings file
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# Nuke build tool
|
||||||
|
.nuke/temp
|
||||||
|
|||||||
134
.nuke/build.schema.json
Normal file
134
.nuke/build.schema.json
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"title": "Build Schema",
|
||||||
|
"$ref": "#/definitions/build",
|
||||||
|
"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"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"NoLogo": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Disables displaying the NUKE logo"
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ReleaseNotesFilePath": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "ReleaseNotesFilePath - To determine the SemanticVersion"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"CopyFiles",
|
||||||
|
"CreatePackage",
|
||||||
|
"Default",
|
||||||
|
"Package",
|
||||||
|
"PrePublish",
|
||||||
|
"Publish",
|
||||||
|
"PublishPackage",
|
||||||
|
"PublishPreRelease",
|
||||||
|
"PublishRelease",
|
||||||
|
"Restore",
|
||||||
|
"RunUnitTests"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"CopyFiles",
|
||||||
|
"CreatePackage",
|
||||||
|
"Default",
|
||||||
|
"Package",
|
||||||
|
"PrePublish",
|
||||||
|
"Publish",
|
||||||
|
"PublishPackage",
|
||||||
|
"PublishPreRelease",
|
||||||
|
"PublishRelease",
|
||||||
|
"Restore",
|
||||||
|
"RunUnitTests"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Verbosity": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Logging verbosity during build execution. Default is 'Normal'",
|
||||||
|
"enum": [
|
||||||
|
"Minimal",
|
||||||
|
"Normal",
|
||||||
|
"Quiet",
|
||||||
|
"Verbose"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
.nuke/parameters.json
Normal file
4
.nuke/parameters.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./build.schema.json",
|
||||||
|
"Solution": "src/ElectronNET.sln"
|
||||||
|
}
|
||||||
@@ -1,9 +1,3 @@
|
|||||||
# Not released
|
|
||||||
|
|
||||||
# 23.6.2
|
|
||||||
|
|
||||||
# Released
|
|
||||||
|
|
||||||
# 23.6.1
|
# 23.6.1
|
||||||
|
|
||||||
ElectronNET.CLI:
|
ElectronNET.CLI:
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
version: 1.0.{build}
|
|
||||||
image: Visual Studio 2019
|
|
||||||
build_script:
|
|
||||||
- cmd: buildAll.cmd
|
|
||||||
pull_requests:
|
|
||||||
do_not_increment_build_number: true
|
|
||||||
artifacts:
|
|
||||||
- path: ElectronNET.WebApp\bin\desktop
|
|
||||||
name: Desktop
|
|
||||||
7
build.cmd
Normal file
7
build.cmd
Normal file
@@ -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" %*
|
||||||
69
build.ps1
Normal file
69
build.ps1
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
[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\nuke\_build.csproj"
|
||||||
|
$TempDirectory = "$PSScriptRoot\\.nuke\temp"
|
||||||
|
|
||||||
|
$DotNetGlobalFile = "$PSScriptRoot\\global.json"
|
||||||
|
$DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1"
|
||||||
|
$DotNetChannel = "Current"
|
||||||
|
|
||||||
|
$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)"
|
||||||
|
|
||||||
|
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 }
|
||||||
62
build.sh
Normal file
62
build.sh
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/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/nuke/_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="Current"
|
||||||
|
|
||||||
|
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)"
|
||||||
|
|
||||||
|
"$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 -- "$@"
|
||||||
11
nuke/.editorconfig
Normal file
11
nuke/.editorconfig
Normal file
@@ -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
|
||||||
260
nuke/Build.cs
Normal file
260
nuke/Build.cs
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
using Microsoft.Build.Exceptions;
|
||||||
|
using Nuke.Common;
|
||||||
|
using Nuke.Common.CI.GitHubActions;
|
||||||
|
using Nuke.Common.IO;
|
||||||
|
using Nuke.Common.ProjectModel;
|
||||||
|
using Nuke.Common.Tools.DotNet;
|
||||||
|
using Nuke.Common.Tools.GitHub;
|
||||||
|
using Nuke.Common.Tools.NuGet;
|
||||||
|
using Nuke.Common.Utilities.Collections;
|
||||||
|
using Octokit;
|
||||||
|
using Octokit.Internal;
|
||||||
|
using Serilog;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
using static Nuke.Common.IO.FileSystemTasks;
|
||||||
|
using static Nuke.Common.IO.PathConstruction;
|
||||||
|
using static Nuke.Common.Tools.DotNet.DotNetTasks;
|
||||||
|
|
||||||
|
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<Build>(x => x.RunUnitTests);
|
||||||
|
|
||||||
|
[Nuke.Common.Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")]
|
||||||
|
readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release;
|
||||||
|
|
||||||
|
[Nuke.Common.Parameter("ReleaseNotesFilePath - To determine the SemanticVersion")]
|
||||||
|
readonly AbsolutePath ReleaseNotesFilePath = RootDirectory / "Changelog.md";
|
||||||
|
|
||||||
|
[Solution]
|
||||||
|
readonly Solution Solution;
|
||||||
|
|
||||||
|
string TargetProjectName => "ElectronNET";
|
||||||
|
|
||||||
|
string ApiTargetLibName => $"{TargetProjectName}.API";
|
||||||
|
|
||||||
|
string CliTargetLibName => $"{TargetProjectName}.CLI";
|
||||||
|
|
||||||
|
string DemoTargetLibName => $"{TargetProjectName}.WebApp";
|
||||||
|
|
||||||
|
AbsolutePath SourceDirectory => RootDirectory / "src";
|
||||||
|
|
||||||
|
AbsolutePath ResultDirectory => RootDirectory / "artifacts";
|
||||||
|
|
||||||
|
GitHubActions GitHubActions => GitHubActions.Instance;
|
||||||
|
|
||||||
|
// Note: The ChangeLogTasks from Nuke itself look buggy. So using the Cake source code.
|
||||||
|
IReadOnlyList<ReleaseNotes> ChangeLog { get; set; }
|
||||||
|
|
||||||
|
ReleaseNotes LatestReleaseNotes { get; set; }
|
||||||
|
|
||||||
|
SemVersion SemVersion { get; set; }
|
||||||
|
|
||||||
|
string Version { get; set; }
|
||||||
|
|
||||||
|
protected override void OnBuildInitialized()
|
||||||
|
{
|
||||||
|
var parser = new ReleaseNotesParser();
|
||||||
|
|
||||||
|
Log.Debug("Reading ChangeLog {FilePath}...", ReleaseNotesFilePath);
|
||||||
|
ChangeLog = parser.Parse(File.ReadAllText(ReleaseNotesFilePath));
|
||||||
|
ChangeLog.NotNull("ChangeLog / ReleaseNotes could not be read!");
|
||||||
|
|
||||||
|
LatestReleaseNotes = ChangeLog.First();
|
||||||
|
LatestReleaseNotes.NotNull("LatestVersion could not be read!");
|
||||||
|
|
||||||
|
Log.Debug("Using LastestVersion from ChangeLog: {LatestVersion}", LatestReleaseNotes.Version);
|
||||||
|
SemVersion = LatestReleaseNotes.SemVersion;
|
||||||
|
Version = LatestReleaseNotes.Version.ToString();
|
||||||
|
|
||||||
|
if (GitHubActions != null)
|
||||||
|
{
|
||||||
|
Log.Debug("Add Version Postfix if under CI - GithubAction(s)...");
|
||||||
|
|
||||||
|
var buildNumber = GitHubActions.RunNumber;
|
||||||
|
|
||||||
|
if (ScheduledTargets.Contains(Default))
|
||||||
|
{
|
||||||
|
Version = $"{Version}-ci-{buildNumber}";
|
||||||
|
}
|
||||||
|
else if (ScheduledTargets.Contains(PrePublish))
|
||||||
|
{
|
||||||
|
Version = $"{Version}-alpha-{buildNumber}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Information("Building version: {Version}", Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
Target Clean => _ => _
|
||||||
|
.Before(Restore)
|
||||||
|
.Executes(() =>
|
||||||
|
{
|
||||||
|
SourceDirectory.GlobDirectories("**/bin", "**/obj").ForEach(DeleteDirectory);
|
||||||
|
});
|
||||||
|
|
||||||
|
Target Restore => _ => _
|
||||||
|
.Executes(() =>
|
||||||
|
{
|
||||||
|
DotNetRestore(s => s
|
||||||
|
.SetProjectFile(Solution));
|
||||||
|
});
|
||||||
|
|
||||||
|
Target Compile => _ => _
|
||||||
|
.DependsOn(Restore)
|
||||||
|
.Executes(() =>
|
||||||
|
{
|
||||||
|
DotNetBuild(s => s
|
||||||
|
.SetProjectFile(Solution)
|
||||||
|
.SetConfiguration(Configuration)
|
||||||
|
.EnableNoRestore());
|
||||||
|
});
|
||||||
|
|
||||||
|
Target RunUnitTests => _ => _
|
||||||
|
.DependsOn(Compile)
|
||||||
|
.Executes(() =>
|
||||||
|
{
|
||||||
|
DotNetTest(s => s
|
||||||
|
.SetProjectFile(Solution)
|
||||||
|
.SetConfiguration(Configuration)
|
||||||
|
.EnableNoRestore()
|
||||||
|
.EnableNoBuild());
|
||||||
|
});
|
||||||
|
|
||||||
|
Target CreatePackages => _ => _
|
||||||
|
.DependsOn(Compile)
|
||||||
|
.Executes(() =>
|
||||||
|
{
|
||||||
|
var api = SourceDirectory / ApiTargetLibName / $"{ApiTargetLibName}.csproj";
|
||||||
|
var cli = SourceDirectory / CliTargetLibName / $"{CliTargetLibName}.csproj";
|
||||||
|
var projects = new[] { api, cli };
|
||||||
|
|
||||||
|
projects.ForEach(project =>
|
||||||
|
{
|
||||||
|
DotNetPack(s => s
|
||||||
|
.SetProject(project)
|
||||||
|
.SetVersion(Version)
|
||||||
|
.SetConfiguration(Configuration)
|
||||||
|
.SetOutputDirectory(ResultDirectory)
|
||||||
|
.SetIncludeSymbols(true)
|
||||||
|
.SetSymbolPackageFormat("snupkg")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Target PublishPackages => _ => _
|
||||||
|
.DependsOn(CreatePackages)
|
||||||
|
.DependsOn(RunUnitTests)
|
||||||
|
.Executes(() =>
|
||||||
|
{
|
||||||
|
var apiKey = Environment.GetEnvironmentVariable("NUGET_API_KEY");
|
||||||
|
|
||||||
|
|
||||||
|
if (apiKey.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
throw new BuildAbortedException("Could not resolve the NuGet API key.");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var nupkg in GlobFiles(ResultDirectory, "*.nupkg"))
|
||||||
|
{
|
||||||
|
DotNetNuGetPush(s => s
|
||||||
|
.SetTargetPath(nupkg)
|
||||||
|
.SetSource("https://api.nuget.org/v3/index.json")
|
||||||
|
.SetApiKey(apiKey));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Target PublishPreRelease => _ => _
|
||||||
|
.DependsOn(PublishPackages)
|
||||||
|
.Executes(() =>
|
||||||
|
{
|
||||||
|
string gitHubToken;
|
||||||
|
|
||||||
|
if (GitHubActions != null)
|
||||||
|
{
|
||||||
|
gitHubToken = GitHubActions.Token;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gitHubToken.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
throw new BuildAbortedException("Could not resolve GitHub token.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var credentials = new Credentials(gitHubToken);
|
||||||
|
|
||||||
|
GitHubTasks.GitHubClient = new GitHubClient(
|
||||||
|
new ProductHeaderValue(nameof(NukeBuild)),
|
||||||
|
new InMemoryCredentialStore(credentials));
|
||||||
|
|
||||||
|
GitHubTasks.GitHubClient.Repository.Release
|
||||||
|
.Create("ElectronNET", "Electron.NET", new NewRelease(Version)
|
||||||
|
{
|
||||||
|
Name = Version,
|
||||||
|
Body = String.Join(Environment.NewLine, LatestReleaseNotes.Notes),
|
||||||
|
Prerelease = true,
|
||||||
|
TargetCommitish = "develop",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Target PublishRelease => _ => _
|
||||||
|
.DependsOn(PublishPackages)
|
||||||
|
.Executes(() =>
|
||||||
|
{
|
||||||
|
string gitHubToken;
|
||||||
|
|
||||||
|
if (GitHubActions != null)
|
||||||
|
{
|
||||||
|
gitHubToken = GitHubActions.Token;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gitHubToken.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
throw new BuildAbortedException("Could not resolve GitHub token.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var credentials = new Credentials(gitHubToken);
|
||||||
|
|
||||||
|
GitHubTasks.GitHubClient = new GitHubClient(
|
||||||
|
new ProductHeaderValue(nameof(NukeBuild)),
|
||||||
|
new InMemoryCredentialStore(credentials));
|
||||||
|
|
||||||
|
GitHubTasks.GitHubClient.Repository.Release
|
||||||
|
.Create("ElectronNET", "Electron.NET", new NewRelease(Version)
|
||||||
|
{
|
||||||
|
Name = Version,
|
||||||
|
Body = String.Join(Environment.NewLine, LatestReleaseNotes.Notes),
|
||||||
|
Prerelease = false,
|
||||||
|
TargetCommitish = "main",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Target Package => _ => _
|
||||||
|
.DependsOn(RunUnitTests)
|
||||||
|
.DependsOn(CreatePackages);
|
||||||
|
|
||||||
|
Target Default => _ => _
|
||||||
|
.DependsOn(Package);
|
||||||
|
|
||||||
|
Target Publish => _ => _
|
||||||
|
.DependsOn(PublishRelease);
|
||||||
|
|
||||||
|
Target PrePublish => _ => _
|
||||||
|
.DependsOn(PublishPreRelease);
|
||||||
|
}
|
||||||
16
nuke/Configuration.cs
Normal file
16
nuke/Configuration.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using Nuke.Common.Tooling;
|
||||||
|
|
||||||
|
[TypeConverter(typeof(TypeConverter<Configuration>))]
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
nuke/Directory.Build.props
Normal file
8
nuke/Directory.Build.props
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
|
||||||
|
<!-- This file prevents unintended imports of unrelated MSBuild files -->
|
||||||
|
<!-- Uncomment to include parent Directory.Build.props file -->
|
||||||
|
<!--<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />-->
|
||||||
|
|
||||||
|
</Project>
|
||||||
8
nuke/Directory.Build.targets
Normal file
8
nuke/Directory.Build.targets
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
|
||||||
|
<!-- This file prevents unintended imports of unrelated MSBuild files -->
|
||||||
|
<!-- Uncomment to include parent Directory.Build.targets file -->
|
||||||
|
<!--<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" />-->
|
||||||
|
|
||||||
|
</Project>
|
||||||
80
nuke/Extensions/StringExtensions.cs
Normal file
80
nuke/Extensions/StringExtensions.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
/// <summary>
|
||||||
|
/// Contains extension methods for <see cref="System.String"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Original from Cake build tool source:
|
||||||
|
/// https://github.com/cake-build/cake/blob/9828d7b246d332054896e52ba56983822feb3f05/src/Cake.Core/Extensions/StringExtensions.cs
|
||||||
|
/// </remarks>
|
||||||
|
public static class StringExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Quotes the specified <see cref="System.String"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The string to quote.</param>
|
||||||
|
/// <returns>A quoted string.</returns>
|
||||||
|
public static string Quote(this string value)
|
||||||
|
{
|
||||||
|
if (!IsQuoted(value))
|
||||||
|
{
|
||||||
|
value = string.Concat("\"", value, "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unquote the specified <see cref="System.String"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The string to unquote.</param>
|
||||||
|
/// <returns>An unquoted string.</returns>
|
||||||
|
public static string UnQuote(this string value)
|
||||||
|
{
|
||||||
|
if (IsQuoted(value))
|
||||||
|
{
|
||||||
|
value = value.Trim('"');
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Splits the <see cref="String"/> into lines.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The string to split.</param>
|
||||||
|
/// <returns>The lines making up the provided string.</returns>
|
||||||
|
public static string[] SplitLines(this string content)
|
||||||
|
{
|
||||||
|
content = NormalizeLineEndings(content);
|
||||||
|
return content.Split(new[] { "\r\n" }, StringSplitOptions.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalizes the line endings in a <see cref="String"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The string to normalize line endings in.</param>
|
||||||
|
/// <returns>A <see cref="String"/> with normalized line endings.</returns>
|
||||||
|
public static string NormalizeLineEndings(this string value)
|
||||||
|
{
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
value = value.Replace("\r\n", "\n");
|
||||||
|
value = value.Replace("\r", string.Empty);
|
||||||
|
return value.Replace("\n", "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsQuoted(this string value)
|
||||||
|
{
|
||||||
|
return value.StartsWith("\"", StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& value.EndsWith("\"", StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
81
nuke/ReleaseNotes.cs
Normal file
81
nuke/ReleaseNotes.cs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represent release notes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Original from Cake build tool source:
|
||||||
|
/// https://github.com/cake-build/cake/blob/9828d7b246d332054896e52ba56983822feb3f05/src/Cake.Common/ReleaseNotes.cs
|
||||||
|
/// </remarks>
|
||||||
|
public sealed class ReleaseNotes
|
||||||
|
{
|
||||||
|
private readonly List<string> _notes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the version.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The version.</value>
|
||||||
|
public SemVersion SemVersion { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the version.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The version.</value>
|
||||||
|
public Version Version { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the release notes.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The release notes.</value>
|
||||||
|
public IReadOnlyList<string> Notes => _notes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the raw text of the line that <see cref="Version"/> was extracted from.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The raw text of the Version line.</value>
|
||||||
|
public string RawVersionLine { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ReleaseNotes"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="semVersion">The semantic version.</param>
|
||||||
|
/// <param name="notes">The notes.</param>
|
||||||
|
/// <param name="rawVersionLine">The raw text of the version line.</param>
|
||||||
|
public ReleaseNotes(SemVersion semVersion, IEnumerable<string> notes, string rawVersionLine)
|
||||||
|
: this(
|
||||||
|
semVersion?.AssemblyVersion ?? throw new ArgumentNullException(nameof(semVersion)),
|
||||||
|
semVersion,
|
||||||
|
notes,
|
||||||
|
rawVersionLine)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ReleaseNotes"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="version">The version.</param>
|
||||||
|
/// <param name="notes">The notes.</param>
|
||||||
|
/// <param name="rawVersionLine">The raw text of the version line.</param>
|
||||||
|
public ReleaseNotes(Version version, IEnumerable<string> notes, string rawVersionLine)
|
||||||
|
: this(
|
||||||
|
version ?? throw new ArgumentNullException(nameof(version)),
|
||||||
|
new SemVersion(version.Major, version.Minor, version.Build),
|
||||||
|
notes,
|
||||||
|
rawVersionLine)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReleaseNotes(Version version, SemVersion semVersion, IEnumerable<string> notes, string rawVersionLine)
|
||||||
|
{
|
||||||
|
Version = version ?? throw new ArgumentNullException(nameof(version));
|
||||||
|
SemVersion = semVersion ?? throw new ArgumentNullException(nameof(semVersion));
|
||||||
|
RawVersionLine = rawVersionLine;
|
||||||
|
_notes = new List<string>(notes ?? Enumerable.Empty<string>());
|
||||||
|
}
|
||||||
|
}
|
||||||
156
nuke/ReleaseNotesParser.cs
Normal file
156
nuke/ReleaseNotesParser.cs
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Microsoft.Build.Exceptions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The release notes parser.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Original from Cake build tool source:
|
||||||
|
/// https://github.com/cake-build/cake/blob/9828d7b246d332054896e52ba56983822feb3f05/src/Cake.Common/ReleaseNotesParser.cs
|
||||||
|
/// </remarks>
|
||||||
|
public sealed class ReleaseNotesParser
|
||||||
|
{
|
||||||
|
private readonly Regex _versionRegex;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ReleaseNotesParser"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public ReleaseNotesParser()
|
||||||
|
{
|
||||||
|
_versionRegex = new Regex(@"(?<Version>\d+(\s*\.\s*\d+){0,3})(?<Release>-[a-z][0-9a-z-]*)?");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses all release notes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The content.</param>
|
||||||
|
/// <returns>All release notes.</returns>
|
||||||
|
public IReadOnlyList<ReleaseNotes> Parse(string content)
|
||||||
|
{
|
||||||
|
if (content == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(content));
|
||||||
|
}
|
||||||
|
|
||||||
|
var lines = content.SplitLines();
|
||||||
|
if (lines.Length > 0)
|
||||||
|
{
|
||||||
|
var line = lines[0].Trim();
|
||||||
|
|
||||||
|
if (line.StartsWith("#", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return ParseComplexFormat(lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.StartsWith("*", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return ParseSimpleFormat(lines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BuildAbortedException("Unknown release notes format.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private IReadOnlyList<ReleaseNotes> ParseComplexFormat(string[] lines)
|
||||||
|
{
|
||||||
|
var lineIndex = 0;
|
||||||
|
var result = new List<ReleaseNotes>();
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (lineIndex >= lines.Length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create release notes.
|
||||||
|
var semVer = SemVersion.Zero;
|
||||||
|
var version = SemVersion.TryParse(lines[lineIndex], out semVer);
|
||||||
|
if (!version)
|
||||||
|
{
|
||||||
|
throw new BuildAbortedException("Could not parse version from release notes header.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var rawVersionLine = lines[lineIndex];
|
||||||
|
|
||||||
|
// Increase the line index.
|
||||||
|
lineIndex++;
|
||||||
|
|
||||||
|
// Parse content.
|
||||||
|
var notes = new List<string>();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Sanity checks.
|
||||||
|
if (lineIndex >= lines.Length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lines[lineIndex].StartsWith("#", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current line.
|
||||||
|
var line = (lines[lineIndex] ?? string.Empty).Trim('*').Trim();
|
||||||
|
if (!string.IsNullOrWhiteSpace(line))
|
||||||
|
{
|
||||||
|
notes.Add(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
lineIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Add(new ReleaseNotes(semVer, notes, rawVersionLine));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.OrderByDescending(x => x.SemVersion).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IReadOnlyList<ReleaseNotes> ParseSimpleFormat(string[] lines)
|
||||||
|
{
|
||||||
|
var lineIndex = 0;
|
||||||
|
var result = new List<ReleaseNotes>();
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (lineIndex >= lines.Length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim the current line.
|
||||||
|
var line = (lines[lineIndex] ?? string.Empty).Trim('*', ' ');
|
||||||
|
if (string.IsNullOrWhiteSpace(line))
|
||||||
|
{
|
||||||
|
lineIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse header.
|
||||||
|
var semVer = SemVersion.Zero;
|
||||||
|
var version = SemVersion.TryParse(lines[lineIndex], out semVer);
|
||||||
|
if (!version)
|
||||||
|
{
|
||||||
|
throw new BuildAbortedException("Could not parse version from release notes header.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the description.
|
||||||
|
line = line.Substring(semVer.ToString().Length).Trim('-', ' ');
|
||||||
|
|
||||||
|
// Add the release notes to the result.
|
||||||
|
result.Add(new ReleaseNotes(semVer, new[] { line }, line));
|
||||||
|
|
||||||
|
lineIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.OrderByDescending(x => x.SemVersion).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
378
nuke/SemVersion.cs
Normal file
378
nuke/SemVersion.cs
Normal file
@@ -0,0 +1,378 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Class for representing semantic versions.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Original from Cake build tool source:
|
||||||
|
/// https://github.com/cake-build/cake/blob/9828d7b246d332054896e52ba56983822feb3f05/src/Cake.Common/SemanticVersion.cs
|
||||||
|
/// </remarks>
|
||||||
|
public class SemVersion : IComparable, IComparable<SemVersion>, IEquatable<SemVersion>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the default version of a SemanticVersion.
|
||||||
|
/// </summary>
|
||||||
|
public static SemVersion Zero { get; } = new SemVersion(0, 0, 0, null, null, "0.0.0");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Regex property for parsing a semantic version number.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Regex SemVerRegex =
|
||||||
|
new Regex(
|
||||||
|
@"(?<Major>0|(?:[1-9]\d*))(?:\.(?<Minor>0|(?:[1-9]\d*))(?:\.(?<Patch>0|(?:[1-9]\d*)))?(?:\-(?<PreRelease>[0-9A-Z\.-]+))?(?:\+(?<Meta>[0-9A-Z\.-]+))?)?",
|
||||||
|
RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the major number of the version.
|
||||||
|
/// </summary>
|
||||||
|
public int Major { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the minor number of the version.
|
||||||
|
/// </summary>
|
||||||
|
public int Minor { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the patch number of the version.
|
||||||
|
/// </summary>
|
||||||
|
public int Patch { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the prerelease of the version.
|
||||||
|
/// </summary>
|
||||||
|
public string PreRelease { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the meta of the version.
|
||||||
|
/// </summary>
|
||||||
|
public string Meta { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether semantic version is a prerelease or not.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPreRelease { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether semantic version has meta or not.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasMeta { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the VersionString of the semantic version.
|
||||||
|
/// </summary>
|
||||||
|
public string VersionString { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the AssemblyVersion of the semantic version.
|
||||||
|
/// </summary>
|
||||||
|
public Version AssemblyVersion { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SemVersion"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="major">Major number.</param>
|
||||||
|
/// <param name="minor">Minor number.</param>
|
||||||
|
/// <param name="patch">Patch number.</param>
|
||||||
|
/// <param name="preRelease">Prerelease string.</param>
|
||||||
|
/// <param name="meta">Meta string.</param>
|
||||||
|
public SemVersion(int major, int minor, int patch, string preRelease = null, string meta = null) : this(major,
|
||||||
|
minor, patch, preRelease, meta, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SemVersion"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="major">Major number.</param>
|
||||||
|
/// <param name="minor">Minor number.</param>
|
||||||
|
/// <param name="patch">Patch number.</param>
|
||||||
|
/// <param name="preRelease">Prerelease string.</param>
|
||||||
|
/// <param name="meta">Meta string.</param>
|
||||||
|
/// <param name="versionString">The complete version number.</param>
|
||||||
|
public SemVersion(int major, int minor, int patch, string preRelease, string meta, string versionString)
|
||||||
|
{
|
||||||
|
Major = major;
|
||||||
|
Minor = minor;
|
||||||
|
Patch = patch;
|
||||||
|
AssemblyVersion = new Version(major, minor, patch);
|
||||||
|
IsPreRelease = !string.IsNullOrEmpty(preRelease);
|
||||||
|
HasMeta = !string.IsNullOrEmpty(meta);
|
||||||
|
PreRelease = IsPreRelease ? preRelease : null;
|
||||||
|
Meta = HasMeta ? meta : null;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(versionString))
|
||||||
|
{
|
||||||
|
VersionString = versionString;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}.{1}.{2}", Major, Minor, Patch);
|
||||||
|
|
||||||
|
if (IsPreRelease)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(CultureInfo.InvariantCulture, "-{0}", PreRelease);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasMeta)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(CultureInfo.InvariantCulture, "+{0}", Meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
VersionString = sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method which tries to parse a semantic version string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="version">the version that should be parsed.</param>
|
||||||
|
/// <param name="semVersion">the out parameter the parsed version should be stored in.</param>
|
||||||
|
/// <returns>Returns a boolean indicating if the parse was successful.</returns>
|
||||||
|
public static bool TryParse(string version,
|
||||||
|
out SemVersion semVersion)
|
||||||
|
{
|
||||||
|
semVersion = Zero;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(version))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var match = SemVerRegex.Match(version);
|
||||||
|
if (!match.Success)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!int.TryParse(
|
||||||
|
match.Groups["Major"].Value,
|
||||||
|
NumberStyles.Integer,
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
out var major) ||
|
||||||
|
!int.TryParse(
|
||||||
|
match.Groups["Minor"].Value,
|
||||||
|
NumberStyles.Integer,
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
out var minor) ||
|
||||||
|
!int.TryParse(
|
||||||
|
match.Groups["Patch"].Value,
|
||||||
|
NumberStyles.Integer,
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
out var patch))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
semVersion = new SemVersion(
|
||||||
|
major,
|
||||||
|
minor,
|
||||||
|
patch,
|
||||||
|
match.Groups["PreRelease"]?.Value,
|
||||||
|
match.Groups["Meta"]?.Value,
|
||||||
|
version);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if two SemVersion objects are equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">the other SemVersion want to test equality to.</param>
|
||||||
|
/// <returns>A boolean indicating whether the objecst we're equal or not.</returns>
|
||||||
|
public bool Equals(SemVersion other)
|
||||||
|
{
|
||||||
|
return other is object
|
||||||
|
&& Major == other.Major
|
||||||
|
&& Minor == other.Minor
|
||||||
|
&& Patch == other.Patch
|
||||||
|
&& string.Equals(PreRelease, other.PreRelease, StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& string.Equals(Meta, other.Meta, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares to SemVersion objects to and another.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">The SemVersion object we compare with.</param>
|
||||||
|
/// <returns>Return 0 if the objects are identical, 1 if the version is newer and -1 if the version is older.</returns>
|
||||||
|
public int CompareTo(SemVersion other)
|
||||||
|
{
|
||||||
|
if (other is null)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Equals(other))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Major > other.Major)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Major < other.Major)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Minor > other.Minor)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Minor < other.Minor)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Patch > other.Patch)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Patch < other.Patch)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsPreRelease != other.IsPreRelease)
|
||||||
|
{
|
||||||
|
return other.IsPreRelease ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (StringComparer.InvariantCultureIgnoreCase.Compare(PreRelease, other.PreRelease))
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return (string.IsNullOrEmpty(Meta) != string.IsNullOrEmpty(other.Meta))
|
||||||
|
? string.IsNullOrEmpty(Meta) ? 1 : -1
|
||||||
|
: StringComparer.InvariantCultureIgnoreCase.Compare(Meta, other.Meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares to SemVersion objects to and another.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object we compare with.</param>
|
||||||
|
/// <returns>Return 0 if the objects are identical, 1 if the version is newer and -1 if the version is older.</returns>
|
||||||
|
public int CompareTo(object obj)
|
||||||
|
{
|
||||||
|
return (obj is SemVersion semVersion)
|
||||||
|
? CompareTo(semVersion)
|
||||||
|
: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Equals-method for the SemVersion class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">the other SemVersion want to test equality to.</param>
|
||||||
|
/// <returns>A boolean indicating whether the objecst we're equal or not.</returns>
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return (obj is SemVersion semVersion)
|
||||||
|
&& Equals(semVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method for getting the hashcode of the SemVersion object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The hashcode of the SemVersion object.</returns>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
var hashCode = Major;
|
||||||
|
hashCode = (hashCode * 397) ^ Minor;
|
||||||
|
hashCode = (hashCode * 397) ^ Patch;
|
||||||
|
hashCode = (hashCode * 397) ^
|
||||||
|
(PreRelease != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(PreRelease) : 0);
|
||||||
|
hashCode = (hashCode * 397) ^ (Meta != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(Meta) : 0);
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the string representation of an SemVersion object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The string representation of the object.</returns>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
int[] verParts = { Major, Minor, Patch };
|
||||||
|
string ver = string.Join(".", verParts);
|
||||||
|
return $"{ver}{(IsPreRelease ? "-" : string.Empty)}{PreRelease}{Meta}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The greater than-operator for the SemVersion class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="operand1">first SemVersion.</param>
|
||||||
|
/// <param name="operand2">second. SemVersion.</param>
|
||||||
|
/// <returns>A value indicating if the operand1 was greater than operand2.</returns>
|
||||||
|
public static bool operator >(SemVersion operand1, SemVersion operand2)
|
||||||
|
=> operand1 is { } && operand1.CompareTo(operand2) == 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The less than-operator for the SemVersion class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="operand1">first SemVersion.</param>
|
||||||
|
/// <param name="operand2">second. SemVersion.</param>
|
||||||
|
/// <returns>A value indicating if the operand1 was less than operand2.</returns>
|
||||||
|
public static bool operator <(SemVersion operand1, SemVersion operand2)
|
||||||
|
=> operand1 is { }
|
||||||
|
? operand1.CompareTo(operand2) == -1
|
||||||
|
: operand2 is { };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The greater than or equal to-operator for the SemVersion class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="operand1">first SemVersion.</param>
|
||||||
|
/// <param name="operand2">second. SemVersion.</param>
|
||||||
|
/// <returns>A value indicating if the operand1 was greater than or equal to operand2.</returns>
|
||||||
|
public static bool operator >=(SemVersion operand1, SemVersion operand2)
|
||||||
|
=> operand1 is { }
|
||||||
|
? operand1.CompareTo(operand2) >= 0
|
||||||
|
: operand2 is null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The lesser than or equal to-operator for the SemVersion class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="operand1">first SemVersion.</param>
|
||||||
|
/// <param name="operand2">second. SemVersion.</param>
|
||||||
|
/// <returns>A value indicating if the operand1 was lesser than or equal to operand2.</returns>
|
||||||
|
public static bool operator <=(SemVersion operand1, SemVersion operand2)
|
||||||
|
=> operand1 is null || operand1.CompareTo(operand2) <= 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The equal to-operator for the SemVersion class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="operand1">first SemVersion.</param>
|
||||||
|
/// <param name="operand2">second. SemVersion.</param>
|
||||||
|
/// <returns>A value indicating if the operand1 was equal to operand2.</returns>
|
||||||
|
public static bool operator ==(SemVersion operand1, SemVersion operand2)
|
||||||
|
=> operand1?.Equals(operand2) ?? operand2 is null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The not equal to-operator for the SemVersion class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="operand1">first SemVersion.</param>
|
||||||
|
/// <param name="operand2">second. SemVersion.</param>
|
||||||
|
/// <returns>A value indicating if the operand1 was not equal to operand2.</returns>
|
||||||
|
public static bool operator !=(SemVersion operand1, SemVersion operand2)
|
||||||
|
=> !(operand1?.Equals(operand2) ?? operand2 is null);
|
||||||
|
}
|
||||||
21
nuke/_build.csproj
Normal file
21
nuke/_build.csproj
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<RootNamespace></RootNamespace>
|
||||||
|
<NoWarn>CS0649;CS0169</NoWarn>
|
||||||
|
<NukeRootDirectory>..</NukeRootDirectory>
|
||||||
|
<NukeScriptDirectory>..</NukeScriptDirectory>
|
||||||
|
<NukeTelemetryVersion>1</NukeTelemetryVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Nuke.Common" Version="6.2.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageDownload Include="NuGet.CommandLine" Version="[6.3.1]" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Reference in New Issue
Block a user