diff --git a/.gitignore b/.gitignore index 97fbeb8..97b4392 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,11 @@ +### VisualStudio template ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore # User-specific files +*.rsuser *.suo *.user *.userosscache @@ -10,6 +14,9 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs +# Mono auto generated files +mono_crash.* + # Build results [Dd]ebug/ [Dd]ebugPublic/ @@ -17,41 +24,62 @@ [Rr]eleases/ x64/ x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ +[Ll]ogs/ -# Visual Studio 2015 cache/options directory +# Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ +# Visual Studio 2017 auto generated files +Generated\ Files/ + # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* -# NUNIT +# NUnit *.VisualState.xml TestResult.xml +nunit-*.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c -# DNX +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core project.lock.json +project.fragment.lock.json artifacts/ +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio *_i.c *_p.c -*_i.h +*_h.h *.ilk *.meta *.obj +*.iobj *.pch *.pdb +*.ipdb *.pgc *.pgd *.rsp @@ -61,7 +89,9 @@ artifacts/ *.tlh *.tmp *.tmp_proj +*_wpftmp.csproj *.log +*.tlog *.vspscc *.vssscc .builds @@ -89,6 +119,9 @@ ipch/ *.vspx *.sap +# Visual Studio Trace Files +*.e2e + # TFS 2012 Local Workspace $tf/ @@ -100,20 +133,29 @@ _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user -# JustCode is a .NET coding add-in -.JustCode - # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* -*.ncrunchsolution # MightyMoose *.mm.* @@ -141,7 +183,7 @@ publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings +# Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj @@ -153,13 +195,15 @@ PublishScripts/ # NuGet Packages *.nupkg +# NuGet Symbol Packages +*.snupkg # The packages folder can be ignored because of Package Restore -**/packages/* +**/[Pp]ackages/* # except build/, which is used as an MSBuild target. -!**/packages/build/ +!**/[Pp]ackages/build/ # Uncomment if necessary however generally it will be regenerated when needed -#!**/packages/repositories.config -# NuGet v3's project.json files produces more ignoreable files +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets @@ -176,12 +220,15 @@ AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt +*.appx +*.appxbundle +*.appxupload # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache -!*.[Cc]ache/ +!?*.[Cc]ache/ # Others ClientBin/ @@ -189,11 +236,15 @@ ClientBin/ *~ *.dbmdl *.dbproj.schemaview +*.jfm *.pfx *.publishsettings -node_modules/ orleans.codegen.cs +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ @@ -208,15 +259,22 @@ _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak # SQL Server files *.mdf *.ldf +*.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl # Microsoft Fakes FakesAssemblies/ @@ -226,6 +284,7 @@ FakesAssemblies/ # Node.js Tools for Visual Studio .ntvs_analysis.dat +node_modules/ # Visual Studio 6 build log *.plg @@ -233,6 +292,20 @@ FakesAssemblies/ # Visual Studio 6 workspace options file *.opt +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts @@ -248,12 +321,162 @@ paket-files/ # FAKE - F# Make .fake/ +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + # JetBrains Rider -.idea/ *.sln.iml -# Cake -tools/* +### Rider template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser # SonarQube .sonarqube/ + diff --git a/.idea/.idea.Todoist.Net/.idea/.gitignore b/.idea/.idea.Todoist.Net/.idea/.gitignore new file mode 100644 index 0000000..1677852 --- /dev/null +++ b/.idea/.idea.Todoist.Net/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/modules.xml +/projectSettingsUpdater.xml +/.idea.Todoist.Net.iml +/contentModel.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.Todoist.Net/.idea/.name b/.idea/.idea.Todoist.Net/.idea/.name new file mode 100644 index 0000000..f011465 --- /dev/null +++ b/.idea/.idea.Todoist.Net/.idea/.name @@ -0,0 +1 @@ +Todoist.Net \ No newline at end of file diff --git a/.idea/.idea.Todoist.Net/.idea/GitLink.xml b/.idea/.idea.Todoist.Net/.idea/GitLink.xml new file mode 100644 index 0000000..009597c --- /dev/null +++ b/.idea/.idea.Todoist.Net/.idea/GitLink.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.Todoist.Net/.idea/encodings.xml b/.idea/.idea.Todoist.Net/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.Todoist.Net/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.Todoist.Net/.idea/indexLayout.xml b/.idea/.idea.Todoist.Net/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.Todoist.Net/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.Todoist.Net/.idea/vcs.xml b/.idea/.idea.Todoist.Net/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/.idea.Todoist.Net/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json new file mode 100644 index 0000000..6443a22 --- /dev/null +++ b/.nuke/build.schema.json @@ -0,0 +1,122 @@ +{ + "$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" + ] + }, + "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" + } + }, + "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": [ + "Compile", + "NugetPack", + "Sonar", + "SonarBegin", + "Test", + "UnitTest", + "UpdateBuildVersion" + ] + } + }, + "Solution": { + "type": "string", + "description": "Path to a solution file that is automatically loaded" + }, + "sonar:apikey": { + "type": "string", + "description": "SonarQube API key" + }, + "Target": { + "type": "array", + "description": "List of targets to be invoked. Default is '{default_target}'", + "items": { + "type": "string", + "enum": [ + "Compile", + "NugetPack", + "Sonar", + "SonarBegin", + "Test", + "UnitTest", + "UpdateBuildVersion" + ] + } + }, + "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 0000000..cf63c48 --- /dev/null +++ b/.nuke/parameters.json @@ -0,0 +1,4 @@ +{ + "$schema": "./build.schema.json", + "Solution": "Todoist.Net.sln" +} diff --git a/README.md b/README.md index 9deda81..e1cfade 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Todoist.Net [![Build status](https://ci.appveyor.com/api/projects/status/r5ylbxtpjya9ayk2?svg=true)](https://ci.appveyor.com/project/olsh/todoist-net) -[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=todoist-net&metric=alert_status)](https://sonarcloud.io/dashboard?id=todoist-net) +[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=olsh_todoist-net&metric=alert_status)](https://sonarcloud.io/dashboard?id=olsh_todoist-net) [![NuGet](https://img.shields.io/nuget/v/Todoist.Net.svg)](https://www.nuget.org/packages/Todoist.Net/) A [Todoist Sync API](https://developer.todoist.com/sync/v9/) client for .NET. diff --git a/Todoist.Net.sln b/Todoist.Net.sln index 76f313b..38681ed 100644 --- a/Todoist.Net.sln +++ b/Todoist.Net.sln @@ -8,20 +8,24 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{28A18847-32D8-4A08-A1BF-BC51E3FBAB96}" ProjectSection(SolutionItems) = preProject appveyor.yml = appveyor.yml - build.cake = build.cake README.md = README.md + .gitignore = .gitignore EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Todoist.Net", "src\Todoist.Net\Todoist.Net.csproj", "{0D84413B-43C0-4F0E-92A6-669F2E9EA5CB}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Todoist.Net.Tests", "src\Todoist.Net.Tests\Todoist.Net.Tests.csproj", "{6F7D284C-2790-41E6-BAB5-DB0524F630D7}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{51A0DD62-8257-48DA-BE1C-5E1F3DE9A5F2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {51A0DD62-8257-48DA-BE1C-5E1F3DE9A5F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51A0DD62-8257-48DA-BE1C-5E1F3DE9A5F2}.Release|Any CPU.ActiveCfg = Release|Any CPU {0D84413B-43C0-4F0E-92A6-669F2E9EA5CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0D84413B-43C0-4F0E-92A6-669F2E9EA5CB}.Debug|Any CPU.Build.0 = Debug|Any CPU {0D84413B-43C0-4F0E-92A6-669F2E9EA5CB}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/appveyor.yml b/appveyor.yml index df8faef..f799d83 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,13 +1,21 @@ -version: 1.0.{build} image: Visual Studio 2022 + +skip_branch_with_pr: true +skip_tags: true + install: - - dotnet tool install -g Cake.Tool --version 2.2.0 - SET JAVA_HOME=C:\Program Files\Java\jdk17 - SET PATH=%JAVA_HOME%\bin;%PATH% + build_script: -- cmd: dotnet cake --Target=CI + - cmd: >- + build.cmd update-build-version sonar unit-test nuget-pack --configuration Release + test: off + cache: - '%USERPROFILE%\.sonar\cache' - '%USERPROFILE%\.nuget\packages -> **\*.csproj' - - 'tools -> build.cake' + +artifacts: + - path: 'artifacts\*.nupkg' diff --git a/build.cake b/build.cake deleted file mode 100644 index 19c2cd6..0000000 --- a/build.cake +++ /dev/null @@ -1,119 +0,0 @@ -#tool nuget:?package=MSBuild.SonarQube.Runner.Tool&version=4.8.0 -#addin nuget:?package=Cake.Sonar&version=1.1.30 - -var target = Argument("target", "Default"); - -var buildConfiguration = "Release"; -var projectName = "Todoist.Net"; -var testProjectName = "Todoist.Net.Tests"; -var projectFolder = string.Format("./src/{0}/", projectName); -var testProjectFolder = string.Format("./src/{0}/", testProjectName); -var projectFile = string.Format("./src/{0}/{0}.csproj", projectName); -var testProjectFile = string.Format("./src/{0}/{0}.csproj", testProjectName); - -var extensionsVersion = XmlPeek(projectFile, "Project/PropertyGroup[1]/VersionPrefix/text()"); - -Task("UpdateBuildVersion") - .WithCriteria(BuildSystem.AppVeyor.IsRunningOnAppVeyor) - .Does(() => -{ - var buildNumber = BuildSystem.AppVeyor.Environment.Build.Number; - - BuildSystem.AppVeyor.UpdateBuildVersion(string.Format("{0}.{1}", extensionsVersion, buildNumber)); -}); - -Task("Build") - .Does(() => -{ - var settings = new DotNetBuildSettings - { - Configuration = buildConfiguration - }; - - DotNetBuild(string.Format("{0}.sln", projectName), settings); -}); - -Task("UnitTest") - .IsDependentOn("Build") - .Does(() => -{ - var settings = new DotNetTestSettings - { - Configuration = buildConfiguration, - Filter = "trait=unit" - }; - - DotNetTest(testProjectFile, settings); -}); - -Task("Test") - .IsDependentOn("Build") - .Does(() => -{ - var settings = new DotNetTestSettings - { - Configuration = buildConfiguration, - Loggers = new List { "console;verbosity=detailed" }, - Filter = "trait!=mfa-required" - }; - - DotNetTest(testProjectFile, settings); -}); - -Task("NugetPack") - .IsDependentOn("Build") - .Does(() => -{ - var settings = new DotNetPackSettings - { - Configuration = buildConfiguration, - OutputDirectory = "." - }; - - DotNetPack(projectFolder, settings); -}); - -Task("CreateArtifact") - .IsDependentOn("NugetPack") - .WithCriteria(BuildSystem.AppVeyor.IsRunningOnAppVeyor) - .Does(() => -{ - BuildSystem.AppVeyor.UploadArtifact(string.Format("{0}.{1}.nupkg", projectName, extensionsVersion)); -}); - -Task("SonarBegin") - .Does(() => { - SonarBegin(new SonarBeginSettings { - Url = "https://sonarcloud.io", - Login = EnvironmentVariable("sonar:apikey"), - Key = "todoist-net", - Name = "Todoist.Net", - ArgumentCustomization = args => args - .Append($"/o:olsh-github"), - Version = "1.0.0.0" - }); - }); - -Task("SonarEnd") - .Does(() => { - SonarEnd(new SonarEndSettings { - Login = EnvironmentVariable("sonar:apikey") - }); - }); - -Task("Sonar") - .IsDependentOn("SonarBegin") - .IsDependentOn("Build") - .IsDependentOn("SonarEnd"); - -Task("Default") - .IsDependentOn("Test") - .IsDependentOn("NugetPack"); - -Task("CI") - .IsDependentOn("UpdateBuildVersion") - .IsDependentOn("Sonar") - .IsDependentOn("UnitTest") - .IsDependentOn("CreateArtifact"); - -RunTarget(target); diff --git a/build.cmd b/build.cmd new file mode 100755 index 0000000..b08cc59 --- /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 0000000..c0c0e61 --- /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 0000000..2f10dcb --- /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 0000000..6a84a60 --- /dev/null +++ b/build/.editorconfig @@ -0,0 +1,13 @@ +[*.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 + +dotnet_diagnostic.S3903.severity = none diff --git a/build/Build.cs b/build/Build.cs new file mode 100644 index 0000000..4785908 --- /dev/null +++ b/build/Build.cs @@ -0,0 +1,121 @@ +using Nuke.Common; +using Nuke.Common.CI; +using Nuke.Common.CI.AppVeyor; +using Nuke.Common.ProjectModel; +using Nuke.Common.Tools.DotNet; +using Nuke.Common.Tools.Git; +using Nuke.Common.Tools.SonarScanner; + +using static Nuke.Common.Tools.DotNet.DotNetTasks; +using static Nuke.Common.Tools.SonarScanner.SonarScannerTasks; + +class Build : NukeBuild +{ + public static int Main () => Execute(x => x.Compile, x => x.UnitTest, x => x.NugetPack); + + [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] + readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release; + + [Parameter("SonarQube API key", Name = "sonar:apikey")] readonly string SonarQubeApiKey; + + [Solution(GenerateProjects = true)] readonly Solution Solution; + + [CI] readonly AppVeyor AppVeyor; + + Target UpdateBuildVersion => _ => _ + .Requires(() => AppVeyor) + .Before(Compile) + .Executes(() => + { + AppVeyor.Instance.UpdateBuildVersion($"{Solution.src.Todoist_Net.GetProperty("Version")}.{AppVeyor.BuildNumber}"); + }); + + Target Compile => _ => _ + .Executes(() => + { + DotNetBuild(s => s + .SetProjectFile(Solution) + .SetConfiguration(Configuration)); + }); + + Target UnitTest => _ => _ + .DependsOn(Compile) + .Before(Sonar) + .Executes(() => + { + DotNetTest(s => s + .SetProjectFile(Solution.src.Todoist_Net_Tests) + .SetConfiguration(Configuration) + .SetFilter("trait=unit") + .SetNoBuild(true)); + }); + + Target Test => _ => _ + .DependsOn(Compile) + .Executes(() => + { + DotNetTest(s => s + .SetProjectFile(Solution.src.Todoist_Net_Tests) + .SetConfiguration(Configuration) + .SetLoggers("console;verbosity=detailed") + .SetFilter("trait!=mfa-required") + .SetNoBuild(true)); + }); + + Target NugetPack => _ => _ + .DependsOn(Compile) + .Executes(() => + { + DotNetPack(s => s + .SetProject(Solution.src.Todoist_Net) + .SetConfiguration(Configuration) + .SetOutputDirectory(RootDirectory / "artifacts") + .SetNoBuild(true) + .SetNoRestore(true)); + }); + + Target SonarBegin => _ => _ + .Unlisted() + .Before(Compile) + .Executes(() => + { + SonarScannerBegin(s => + { + s = s + .SetServer("https://sonarcloud.io") + .SetFramework("net5.0") + .SetLogin(SonarQubeApiKey) + .SetProjectKey("todoist-net") + .SetName("Todoist.Net") + .SetOrganization("olsh") + .SetVersion("1.0.0.0"); + + if (AppVeyor != null) + { + if (AppVeyor.PullRequestNumber != null) + { + s = s + .SetPullRequestKey(AppVeyor.PullRequestNumber.ToString()) + .SetPullRequestBase(AppVeyor.RepositoryBranch) + .SetPullRequestBranch(AppVeyor.PullRequestHeadRepositoryBranch); + } + else + { + s = s + .SetBranchName(AppVeyor.RepositoryBranch); + } + } + + return s; + }); + }); + + Target Sonar => _ => _ + .DependsOn(SonarBegin, Compile) + .Executes(() => + { + SonarScannerEnd(s => s + .SetLogin(SonarQubeApiKey) + .SetFramework("net5.0")); + }); +} diff --git a/build/Configuration.cs b/build/Configuration.cs new file mode 100644 index 0000000..9c08b1a --- /dev/null +++ b/build/Configuration.cs @@ -0,0 +1,16 @@ +using System; +using System.ComponentModel; +using System.Linq; +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 0000000..e147d63 --- /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 0000000..2532609 --- /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 0000000..86bf5d9 --- /dev/null +++ b/build/_build.csproj @@ -0,0 +1,19 @@ + + + + Exe + net6.0 + + CS0649;CS0169;CA1050;CA1822;CA2211;IDE1006 + .. + .. + 1 + false + + + + + + + + diff --git a/build/_build.csproj.DotSettings b/build/_build.csproj.DotSettings new file mode 100644 index 0000000..eb3f4c2 --- /dev/null +++ b/build/_build.csproj.DotSettings @@ -0,0 +1,28 @@ + + DO_NOT_SHOW + 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