diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..5fa488a --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,80 @@ +name: Build + +on: + push: + branches: [ "master" ] + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get Version + id: version + uses: paulhatch/semantic-version@v5.3.0 + with: + tag_prefix: "v" + namespace: beta + debug: true + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: | + 8.0.x + - name: Build + run: dotnet build "MouseTrap/MouseTrap.csproj" -c Release -o ./dist + + - name: Create Zip + uses: vimtor/action-zip@v1.1 + with: + files: ./dist/ + dest: MouseTrap-${{ steps.version.outputs.version }}.zip + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: mousetrap + path: ${{ github.workspace }}/MouseTrap-${{ steps.version.outputs.version }}.zip + + - name: Add Version Tag + uses: actions/github-script@v6 + with: + script: | + github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `refs/tags/${{ steps.version.outputs.version_tag }}`, + sha: context.sha + }) + + - name: Create release + id: create_release + uses: softprops/action-gh-release@v1 + # if: startsWith(github.ref, 'refs/tags/') + with: + tag_name: ${{ steps.version.outputs.version_tag }} + draft: false + prerelease: true + body: | + MouseTrap is a portable application. + Download the *.zip archive and extract it to some safe place (where you don't delete it by mistake) + and double click mousetrap.exe to run it. + + Please download and install [**.NET 8 Runtime**](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) if you have trouble running mousetrap + _in most cases it will notify you with a simple message dialog if the runtime is missing_ + + [Documentation + Help](https://github.com/r-Larch/MouseTrap/blob/master/README.md) + + ![#f03c15](https://placehold.it/15/f03c15/000000?text=+) Please Note!! + > The **MouseTrap.exe is not signed!** Because Code signing certificates cost a lot of money. + So in case you get some "Windows protected your PC" warning, just hit "more infos" and then "Run anyway". + Or download the Source Code and Build it on your own. + files: ./MouseTrap-${{ steps.version.outputs.version }}.zip + diff --git a/MouseTrap.sln b/MouseTrap.sln index a05c531..7912c87 100644 --- a/MouseTrap.sln +++ b/MouseTrap.sln @@ -8,8 +8,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{02A88C37-94A2-41A9-82FD-D279583D03D6}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig - appveyor.yml = appveyor.yml - build\Create-Artifacts.ps1 = build\Create-Artifacts.ps1 + .github\workflows\build.yml = .github\workflows\build.yml README.md = README.md EndProjectSection EndProject diff --git a/README.md b/README.md index bc0a6ed..36feec1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # MouseTrap -[![Build](https://ci.appveyor.com/api/projects/status/32r7s2skrgm9ubva?svg=true)](https://ci.appveyor.com/project/r-Larch/mousetrap/branch/master) -[![master](https://ci.appveyor.com/api/projects/status/32r7s2skrgm9ubva?svg=true&passingText=master%20-%20OK)](https://ci.appveyor.com/project/r-Larch/mousetrap/branch/master) +[![Build](https://github.com/r-Larch/MouseTrap/actions/workflows/build.yml/badge.svg)](https://github.com/r-Larch/MouseTrap/actions/workflows/build.yml) MouseTrap is a small tool to map the cursor between multiple monitors with
different resolutions and scaling settings. @@ -19,29 +18,14 @@ For this tool to function correctly you should have: You can find the latest release here: > [Download](https://github.com/r-Larch/MouseTrap/releases) -You can install MouseTrap with **chocolatey**: -```Powershell -# install the package -choco install mousetrap - -# running it -mousetrap -``` - ->If you don't have chocolatey allready, I highly recommend installing it.
->It's as simple as pasting the following in a cmd or Powershell window: ->```Powershell ->PowerShell ->Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object >System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) ->``` ->*[Why Chocolatey](https://chocolatey.org/docs/why) + [installation](https://chocolatey.org/docs/installation)* - ## Changelog ### Version 1.0.16 - **Migrate to .NET 8** + - Discontinue `chocolatey` support + - Migrate CI to Github Actions - Bug fixes ### Version 1.0.15 diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index b6830ee..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,63 +0,0 @@ -image: Visual Studio 2022 - -branches: - only: - - master - -version: 1.0.{build} -configuration: Release -platform: Any CPU -skip_tags: true # to prevent a endless build loop - -environment: - choco_api_token: - secure: Rym1kbOorVRtBplky8zDAaWiNA3MnD48MoL5SboGtQPXqVJZVXJrytFD0AtwVqID - -before_build: -- cmd: nuget restore - -assembly_info: - patch: true - file: AssemblyInfo.* - assembly_version: '{version}' - assembly_file_version: '{version}' - assembly_informational_version: '{version}-rc1' - -build: - verbosity: minimal - project: MouseTrap.sln - -after_build: -- ps: .\build\Create-Artifacts.ps1 $env:appveyor_build_version - -artifacts: -- path: MouseTrap\bin\*.zip -- path: MouseTrap\bin\*.nupkg - -deploy: -- provider: GitHub - release: v$(appveyor_build_version)-beta - prerelease: true - draft: false - description: | - MouseTrap is a portable application. - Download the *.zip archive and extract it to some safe place (where you don't delete it by mistake) - and double click mousetrap.exe to run it. - - Please download and install [**.NET 8 Runtime**](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) if you have trouble running mousetrap - _in most cases it will notify you with a simple message dialog if the runtime is missing_ - - [Documentation + Help](https://github.com/r-Larch/MouseTrap/blob/master/README.md) - - ![#f03c15](https://placehold.it/15/f03c15/000000?text=+) Please Note!! - > The **MouseTrap.exe is not signed!** Because Code signing certificates cost a lot of money. - So in case you get some "Windows protected your PC" warning, just hit "more infos" and then "Run anyway". - Or download the Source Code and Build it on your own. - auth_token: - secure: OI8UYJ7wYXUR0hQ3rrAd7zTd0yCV5Ssl1dGrSo+yqcKspC8XTx9/5Us3SfmDbXW+/L96DCCPhJTRbCZmtbVMPUDyJiBzuWjAc8wPlXLTAZMAbmbFS1lLEwC0B/sMfUdZ - # artifact: /*\.exe/ - on: - branch: master - -after_deploy: -- ps: choco push $(Resolve-Path $env:appveyor_build_folder\MouseTrap\bin\*.nupkg).ToString() --source https://push.chocolatey.org/ --key $env:choco_api_token \ No newline at end of file diff --git a/build/Create-Artifacts.ps1 b/build/Create-Artifacts.ps1 deleted file mode 100644 index d73e452..0000000 --- a/build/Create-Artifacts.ps1 +++ /dev/null @@ -1,419 +0,0 @@ - -param ( - [Parameter(Mandatory=$false)] - [ValidatePattern("^\d+\.\d+\.\d+$")] - [string] - $ReleaseVersionNumber, - - [Parameter(Mandatory=$false)] - [switch] - $Alpha = $false, - - [Parameter(Mandatory=$false)] - [switch] - $Beta = $false -) - - -$Root = Split-path -parent $(Split-Path -parent $MyInvocation.MyCommand.Path) - -$SolutionFile = [System.IO.Path]::Combine($Root, "MouseTrap.sln"); -$DistFolder = [System.IO.Path]::Combine($Root, "dist"); -$TempFolder = [System.IO.Path]::Combine($Root, "temp"); -$ReadmeFile = [System.IO.Path]::Combine($Root, "README.md"); -$ProjectRoot = [System.IO.Path]::Combine($Root, "MouseTrap"); -$BuildDir = [System.IO.Path]::Combine($ProjectRoot, "bin\net6.0-windows"); -$OutputDir = [System.IO.Path]::Combine($ProjectRoot, "bin"); -$chocoNuspec = [System.IO.Path]::Combine($ProjectRoot, "choco\MouseTrap.nuspec"); -$AssemblyInfo = [System.IO.Path]::Combine($ProjectRoot, "Properties\AssemblyInfo.cs"); - -$GithubGetRepoApi = "https://api.github.com/repos/r-Larch/MouseTrap"; - -function Main() { - - # auto commit ? ============================= - - #if ([Git]::HasStagedChanges()) { - # [Git]::ShowStaged(); - # if ([UI]::Comfirm("you have staged changes! Do you wand to auto commit them?") -eq $false) { - # [Git]::Discard($AssemblyInfo); - # [Git]::Discard($chocoNuspec); - # [UI]::ThrowError("Please commit your staged changes first"); - # } - #} - - #if ([Git]::HasUnstagedChanges()) { - # [Git]::ShowUnstaged(); - # if ([UI]::Comfirm("you have unstaged changes! Do you wand to auto commit them?") -eq $false) { - # [UI]::ThrowError("Please commit your unstaged changes first"); - # } - # else { - # [Git]::Stage("*"); - # } - #} - - - # version number ============================= - - #[Git]::Stage($AssemblyInfo); # backup - #if ([string]::IsNullOrEmpty($ReleaseVersionNumber)) { - # $ReleaseVersionNumber = GetVersion $AssemblyInfo; - #} - #else { - # SetVersion $AssemblyInfo $ReleaseVersionNumber; - #} - - - # Git tags and history ============================= - - $tag = [Git]::CreateVersionTag($ReleaseVersionNumber, $Alpha, $Beta); - $previousTag = [Git]::GetVersionTags() | where { $_ -ne $tag } | sort -Descending | select -first 4 | select -last 1; - $history = [Git]::GetHistorySince($previousTag); - - - # update .nuspec ============================= - - # [Git]::Stage($chocoNuspec); # backup - $repo = $(Invoke-Webrequest $GithubGetRepoApi).Content | ConvertFrom-Json; - $topics = $(Invoke-Webrequest $GithubGetRepoApi/topics -Headers @{'Accept'='application/vnd.github.mercy-preview+json'}).Content | ConvertFrom-Json - $xml = [xml] $(gc -Path $chocoNuspec -Encoding UTF8); - $xml.package.metadata.version = $ReleaseVersionNumber; - $xml.package.metadata.summary = $repo.description; - $xml.package.metadata.tags = [string]::Join(" ", $topics.names); - # $xml.package.metadata.description = [string]::Join("`r`n", $(gc -Path $ReadmeFile)); - $xml.package.metadata.copyright = "Copyright $([DateTime]::Now.Year) René Larch"; - $xml.package.metadata.releaseNotes = [string]::Join("`r`n", $history); - # $xml.package.metadata.licenseUrl = ; - # $xml.package.metadata.projectUrl = $repo.html_url; - # $xml.package.metadata.projectSourceUrl = $repo.html_url; - # $xml.package.metadata.bugTrackerUrl = ; - # $xml.package.metadata.docsUrl = ; - # $xml.package.metadata.iconUrl = ; - $xml.Save($chocoNuspec); - - - # commit changes ============================= - - #[Git]::Stage($AssemblyInfo); - #[Git]::Stage($chocoNuspec); - - #if ([Git]::HasTag($tag)) { - # if ([Git]::HasStagedChanges()) { - # [Git]::RemoveTag($tag); - # [Git]::Commit("Update $tag"); - # [Git]::AddTag($tag); - # } - #} - #else { - # if ([Git]::HasStagedChanges()) { - # [Git]::Commit("Release $tag"); - # } - # [Git]::AddTag($tag); - #} - - - # Build ============================= - - # BuildSolution $SolutionFile "Release" $OutputDir; - # $exacutable = [System.IO.Path]::Combine($OutputDir, "MouseTrap.exe") - # SignExecutable $exacutable "renelarch@gmail.com"; - # Copy-Item $exacutable "$DistFolder\MouseTrap.$ReleaseVersionNumber.exe"; - # Zip $OutputDir "$DistFolder\MouseTrap.$ReleaseVersionNumber.zip"; - - - # Release Artifact ================== - - CleanDir $TempFolder; - [System.IO.Directory]::CreateDirectory($TempFolder); - Copy-Item "$([System.IO.Path]::Combine($BuildDir, "*.exe"))" "$TempFolder\"; - Copy-Item "$([System.IO.Path]::Combine($BuildDir, "*.dll"))" "$TempFolder\"; - Copy-Item "$([System.IO.Path]::Combine($BuildDir, "*.pdb"))" "$TempFolder\"; - Copy-Item "$([System.IO.Path]::Combine($BuildDir, "*.runtimeconfig.json"))" "$TempFolder\"; - Zip $TempFolder "$OutputDir\MouseTrap.$ReleaseVersionNumber.zip"; - CleanDir $TempFolder; - - - # choco ============================= - - ChocoPack $chocoNuspec $OutputDir; - - - # commit results ============================= - - #[Git]::Stage("$DistFolder\MouseTrap.$ReleaseVersionNumber.exe"); - #[Git]::Stage("$DistFolder\MouseTrap.$ReleaseVersionNumber.nupkg"); - #[Git]::Commit("$tag binarys"); - -} - - -function ChocoPack([string] $nuspec, [string] $nupkg) { - - if (!$(Get-Command choco -errorAction SilentlyContinue)) { - Write-Host "Install chocolatey"; - iwr https://chocolatey.org/install.ps1 -UseBasicParsing | iex - $env:Path += ";%ALLUSERSPROFILE%\chocolatey\bin"; - } - - & choco pack "$nuspec" --outputdirectory "$nupkg"; - if (-not $?) { - throw "The choco pack process returned an error code." - } - - #$xml = [xml] $(gc -Path $chocoNuspec -Encoding UTF8); - #$name = $xml.package.metadata.id + "." + $xml.package.metadata.version + ".nupkg"; - #$file = [System.IO.Path]::Combine($nupkg, $name); - - # Push-AppveyorArtifact $file; - - # if ([UI]::Ask("Enter 'choco push' to publish '$name':", "choco push")) { - # & choco push $file; - # if (-not $?) { - # throw "The publish process returned an error code." - # } - # } -} - - -class Git { - static [string[]] GetTags() { - return $(git tag --list).Split("`n"); - } - static [string[]] GetVersionTags() { - return [Git]::GetTags() | Select-String -pattern "v[\d+\.]+(-(alpha|beta))?"; - } - static [string] GetLatastVersionTag() { - return [Git]::GetVersionTags() | sort -Descending | select -first 1; - } - static [string[]] GetHistorySince([string] $tagOrHash) { - if ([string]::IsNullOrEmpty($tagOrHash)){ - return $(git log --oneline); - } - return $(git log "$tagOrHash..HEAD" --oneline); - } - static AddTag([string] $tag) { - git tag -a "$tag" -m "$tag" | Write-Host -ForegroundColor Green; - } - static RemoveTag([string] $tag) { - git tag -d "$tag" | Write-Host -ForegroundColor Magenta; - } - static [string] CreateVersionTag([string] $version, [bool] $alpha = $false, [bool] $beta = $false) { - $tag = "v$version"; - if ($alpha) { - $tag += "-alpha"; - } - elseif ($beta) { - $tag += "-beta"; - } - return $tag; - } - static [bool] HasTag([string] $tag) { - return [Git]::GetTags().Contains($tag); - } - - static [bool] HasUncommittedChanges() { - return [string]::IsNullOrEmpty($(git diff HEAD --stat)) -eq $false; - } - static [bool] HasUnstagedChanges() { - return [string]::IsNullOrEmpty($(git diff --stat)) -eq $false; - } - static [bool] HasStagedChanges() { - return [string]::IsNullOrEmpty($(git diff --staged --stat)) -eq $false; - } - static ShowUnstaged() { - Write-Host "`n Unstaged changes:`n" -ForegroundColor DarkGreen; - git diff --stat | Write-Host -ForegroundColor Green; - } - static ShowStaged() { - Write-Host "`n Staged changes:`n" -ForegroundColor DarkGreen; - git diff --staged --stat | Write-Host -ForegroundColor Green; - } - - static Stage([string] $file) { - git add $file | Write-Host -ForegroundColor Green; - } - static Unstage([string] $file) { - git reset HEAD "$file" | Write-Host -ForegroundColor DarkYellow; - } - static Discard([string] $file) { - git checkout -- "$file" | Write-Host -ForegroundColor Magenta; - } - static FullReset([string] $file) { - [Git]::Unstage($file); - [Git]::Discard($file); - } - static Commit([string] $msg) { - git commit -m $msg | Write-Host -ForegroundColor Green; - } -} - - -class UI { - static [bool] Comfirm([string] $message) { - - $choices = [Collections.ObjectModel.Collection[Management.Automation.Host.ChoiceDescription]]::new(); - $choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes')) - $choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&No')) - - Write-Host ""; - $decision = $global:Host.UI.PromptForChoice($null, $message, $choices, 1) - if ($decision -eq 0) { - return $true; - } else { - return $false; - } - } - static [bool] Ask([string] $msg, [string] $answare) { - $res = ""; - do { - Write-Host "`n`n $msg ( to skip)" -ForegroundColor Green; - Write-Host " " -NoNewline; - - $res = Read-Host - if ($res -eq $answare) { - return $true; - } - } - while (![string]::IsNullOrEmpty($res)); - - return $false; - } - static ThrowError($error) { - Write-Host "`n $error" -ForegroundColor Red; - Write-Host ""; - exit; - } -} - - -function SignExecutable([string] $executable, [string] $subjectName) { - # Code signing, works on my machine but probably not very portable - # Use the following command to create a self-signed cert to build a signed version of the WACS executable - # New-SelfSignedCertificate ` - # -CertStoreLocation cert:\currentuser\my ` - # -Subject "CN=WACS" ` - # -KeyUsage DigitalSignature ` - # -Type CodeSigning - - $from = "C:\Program Files (x86)\Windows Kits\"; - $SignTool = $(Get-ChildItem $from -Recurse -File ` - | Where {$_.Name -eq "signtool.exe"} ` - | where {$_.FullName -like "*\x86\*" -or $_.FullName -like "*\x64\*" -or $_.FullName -like "*\App Certification Kit\*" } ` - | select -first 1 ` - ).FullName; - - if (Test-Path $SignTool) { - & $SignTool sign /n "$subjectName" "$executable" #/tr http://timestamp.comodoca.com/authenticode - } - else { - throw 'signtool.exe Not found! Please open "Visual Studio Installer" and install "ClickOnce Publication Tools"'; - } -} - - - -function BuildSolution([string] $solutionFile, [string] $configuration, [string] $outputDir) { - $NuGet = GetTool "nuget.exe" "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"; - $NuGetFolder = Join-Path -Path $([System.IO.Path]::GetDirectoryName($solutionFile)) "packages"; - - # Restore NuGet packages - cmd.exe /c "$NuGet restore $solutionFile -NonInteractive -PackagesDirectory $NuGetFolder" - - $MSBuild = GetMSBuildPath; - - # Clean solution - & $MSBuild "$solutionFile" "/p:OutDir=$outputDir;Configuration=$configuration" /maxcpucount /t:Clean - if (-not $?) { - throw "The MSBuild process returned an error code." - } - - # Build - & $MSBuild "$solutionFile" "/p:OutDir=$outputDir;Configuration=$configuration" /maxcpucount - if (-not $?) { - throw "The MSBuild process returned an error code." - } -} - -function GetTool([string] $fileName, [string] $downloadUrl = $null) { - $tool = "$env:HOMEDRIVE\Tools\nuget.exe" - If ($(Test-Path $tool) -eq $false) { - if ([string]::IsNullOrEmpty($downloadUrl)) { - throw [System.IO.FileNotFoundException]::new("$tool not found", $tool); - } - else { - Invoke-WebRequest $downloadUrl -OutFile $tool - } - } - return $tool; -} - -function Zip([string] $directoryPath, [string] $destinationZipFile, [bool] $overwrite = $true) { - if (Test-Path $destinationZipFile) { - if ($overwrite) { - Remove-Item $destinationZipFile; - } - else { - throw "Target File allready exists: '$destinationZipFile'"; - } - } - Add-Type -assembly "system.io.compression.filesystem"; - [io.compression.zipfile]::CreateFromDirectory($directoryPath, $destinationZipFile); -} - -function GetVersion([string] $assemblyInfo) { - return $(Select-String -path $assemblyInfo -pattern 'AssemblyFileVersion\("([^"]+)"\)').Matches.Groups[1].Value; -} - -function SetVersion([string] $assemblyInfo, [string] $version) { - $versionParts = $version.Split(".") - $NewVersion = 'AssemblyVersion("' + $versionParts[0] + '.' + $versionParts[1] + '.' + $versionParts[2] + '")' - $NewFileVersion = 'AssemblyFileVersion("' + $version + '")' - - (gc -Path $assemblyInfo) ` - -replace 'AssemblyVersion\("[0-9\.*]+"\)', $NewVersion | - sc -Path $assemblyInfo -Encoding UTF8 - (gc -Path $assemblyInfo) ` - -replace 'AssemblyFileVersion\("[0-9\.]+"\)', "$NewFileVersion" | - sc -Path $assemblyInfo -Encoding UTF8 -} - -function GetMSBuildPath() { - $vs14key = "HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0" - $vs15key = "HKLM:\SOFTWARE\wow6432node\Microsoft\VisualStudio\SxS\VS7" - $msbuildPath = "" - - if (Test-Path $vs14key) { - $key = Get-ItemProperty $vs14key - $subkey = $key.MSBuildToolsPath - if ($subkey) { - $msbuildPath = Join-Path $subkey "msbuild.exe" - } - } - - if (Test-Path $vs15key) { - $key = Get-ItemProperty $vs15key - $subkey = $key."15.0" - if ($subkey) { - $msbuildPath = Join-Path $subkey "MSBuild\15.0\bin\amd64\msbuild.exe" - } - } - - return $msbuildPath -} - -function CleanDir([string] $dir) { - if (Test-Path $dir) { - Remove-Item $dir -Recurse - } - New-Item $dir -Type Directory -} - - - -######################### -# run main # -######################### - -Main; - -######################### \ No newline at end of file