diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml deleted file mode 100644 index 427db0e..0000000 --- a/.github/workflows/master.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: release - -on: - workflow_dispatch: - -jobs: - build: - runs-on: windows-2025 - steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - - uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0 - with: - dotnet-version: "10.x" - - uses: nuget/setup-nuget@fd55a6f3b34392fa83fde1454582407d8c714123 # 4.0.0 - - uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # 3.0.0 - with: - msbuild-architecture: x64 - - - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # 4.0.1 - id: changes - with: - filters: | - buildprops: - - 'Directory.Build.props' - - - name: Update version - if: steps.changes.outputs.buildprops == 'false' - run: | - (Get-Content Directory.Build.props) | % { - $m = [regex]::match($_, '(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?'); - if(!$m.Success -or $m.Groups[4].Success -or $m.Groups[5].Success) { $_; } - else { $_ -replace $m.Value, ("{0}.{1}.{2}-pre${{ github.run_number }}" -f $m.Groups[1].Value,$m.Groups[2].Value,([convert]::ToInt32($m.Groups[3].Value)+1)); } - } | Set-Content Directory.Build.props - - - name: Restore application packages - run: dotnet restore LibreHardwareMonitor.Windows.WinUI\LibreHardwareMonitor.Windows.WinUI.csproj - - - name: Build application - run: dotnet build LibreHardwareMonitor.Windows.WinUI\LibreHardwareMonitor.Windows.WinUI.csproj -c Release --no-restore -p:Platform=x64 - - - name: Publish WinUI application - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # 7.0.1 - with: - name: LibreHardwareMonitor.Windows.WinUI - path: | - bin/Release/net10.0-windows10.0.19041.0 - - - name: Restore library packages - run: dotnet restore LibreHardwareMonitorLib\LibreHardwareMonitorLib.csproj - - - name: Build x64 libraries - run: dotnet build LibreHardwareMonitorLib\LibreHardwareMonitorLib.csproj -c Release --no-restore -p:Platform=x64 - - - name: Run library tests - run: dotnet test LibreHardwareMonitorLib.Tests\LibreHardwareMonitorLib.Tests.csproj -c Release -p:Platform=x64 - - - name: Run WinUI tests - run: dotnet test LibreHardwareMonitor.Windows.WinUI.Tests\LibreHardwareMonitor.Windows.WinUI.Tests.csproj -c Release -p:Platform=x64 - - - name: Publish x64 libraries - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # 7.0.1 - with: - name: LibreHardwareMonitorLib (x64) - path: | - bin/Release/x64 - - - name: Build reference libraries - run: dotnet build LibreHardwareMonitorLib\LibreHardwareMonitorLib.csproj -c Release --no-restore -p:BuildOnlyRefs=true - - - name: Pack main nupkg - run: dotnet pack LibreHardwareMonitorLib\LibreHardwareMonitorLib.csproj -c Release -p:PackMainNuget=true --no-build --output bin\Release - - - name: Publish nupkg - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # 7.0.1 - with: - name: LibreHardwareMonitorLib-nupkg - path: | - bin/Release/LibreHardwareMonitorLib.*.nupkg - - - name: Publish to NuGet - if: github.repository == 'LibreHardwareMonitor/LibreHardwareMonitor' - run: nuget push bin\Release\LibreHardwareMonitorLib.*.nupkg -Source 'https://api.nuget.org/v3/index.json' -ApiKey ${{secrets.NUGET_API_KEY}} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..74d46cb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,146 @@ +name: release + +on: + push: + tags: + - "v*" + workflow_dispatch: + inputs: + version: + description: "Version/tag to create (e.g. v1.2.3)" + required: false + type: string + +permissions: + contents: write + +jobs: + build: + runs-on: windows-2025-vs2026 + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0 + with: + dotnet-version: "10.x" + + - uses: nuget/setup-nuget@fd55a6f3b34392fa83fde1454582407d8c714123 # 4.0.0 + + - uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # 3.0.0 + with: + msbuild-architecture: x64 + + - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # 4.0.1 + id: changes + with: + filters: | + buildprops: + - 'Directory.Build.props' + + - name: Update version + run: | + $inputVersion = "${{ inputs.version }}" + if ($inputVersion) { + $cleanVersion = $inputVersion -replace '^v', '' + (Get-Content Directory.Build.props) | % { + $m = [regex]::match($_, '(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?'); + if($m.Success) { $_ -replace $m.Value, "$cleanVersion"; } + else { $_; } + } | Set-Content Directory.Build.props + } elseif ('${{ steps.changes.outputs.buildprops }}' -eq 'false') { + (Get-Content Directory.Build.props) | % { + $m = [regex]::match($_, '(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?'); + if(!$m.Success -or $m.Groups[4].Success -or $m.Groups[5].Success) { $_; } + else { $_ -replace $m.Value, ("{0}.{1}.{2}-pre${{ github.run_number }}" -f $m.Groups[1].Value,$m.Groups[2].Value,([convert]::ToInt32($m.Groups[3].Value)+1)); } + } | Set-Content Directory.Build.props + } + + - name: Get Version + id: get_version + run: | + $content = Get-Content Directory.Build.props + $m = [regex]::match($content, '([^<]+)') + if ($m.Success) { + $version = $m.Groups[1].Value + } else { + $version = "1.0.0-draft" + } + echo "VERSION=$version" >> $env:GITHUB_OUTPUT + echo "Detected version: $version" + + - name: Determine Tag + id: tag_name + run: | + $inputVersion = "${{ inputs.version }}" + if ($inputVersion) { + $tag = $inputVersion + if ($tag -notmatch '^v') { + $tag = "v" + $tag + } + } elseif ("${{ github.ref_type }}" -eq "tag") { + $tag = "${{ github.ref_name }}" + } else { + $tag = "v${{ steps.get_version.outputs.VERSION }}" + } + echo "TAG=$tag" >> $env:GITHUB_OUTPUT + echo "Release tag: $tag" + + - name: Restore application packages + run: dotnet restore LibreHardwareMonitor.Windows.WinUI\LibreHardwareMonitor.Windows.WinUI.csproj + + - name: Build application + run: dotnet build LibreHardwareMonitor.Windows.WinUI\LibreHardwareMonitor.Windows.WinUI.csproj -c Release --no-restore -p:Platform=x64 + + - name: Restore library packages + run: dotnet restore LibreHardwareMonitorLib\LibreHardwareMonitorLib.csproj + + - name: Build x64 libraries + run: dotnet build LibreHardwareMonitorLib\LibreHardwareMonitorLib.csproj -c Release --no-restore -p:Platform=x64 + + - name: Run library tests + run: dotnet test LibreHardwareMonitorLib.Tests\LibreHardwareMonitorLib.Tests.csproj -c Release -p:Platform=x64 + + - name: Run WinUI tests + run: dotnet test LibreHardwareMonitor.Windows.WinUI.Tests\LibreHardwareMonitor.Windows.WinUI.Tests.csproj -c Release -p:Platform=x64 + + - name: Publish WinUI application + run: dotnet publish LibreHardwareMonitor.Windows.WinUI\LibreHardwareMonitor.Windows.WinUI.csproj -c Release -r win-x64 -p:Platform=x64 -p:PublishSingleFile=true -p:PublishSelfContained=true --self-contained true --no-restore -o publish/app + + - name: Stage Release Assets + run: | + New-Item -ItemType Directory -Force -Path release-staging + + # Copy application binary (single file, self-contained, with .NET version) + Copy-Item publish/app/LibreHardwareMonitor.Windows.WinUI.exe release-staging/LibreHardwareMonitor.Windows.WinUI-net10.0.exe + + # Copy library DLL (net10.0 build) + Copy-Item bin/Release/x64/net10.0/LibreHardwareMonitorLib.dll release-staging/LibreHardwareMonitorLib.dll + + # Create source code ZIP + git archive --format=zip --output release-staging/LibreHardwareMonitor-source.zip HEAD + + # Generate SHA256 checksums + $sha256 = [System.Security.Cryptography.SHA256]::Create() + Get-ChildItem release-staging | Where-Object { $_.Name -ne "SHA256SUMS.txt" } | ForEach-Object { + $fileStream = [System.IO.File]::OpenRead($_.FullName) + $hashBytes = $sha256.ComputeHash($fileStream) + $fileStream.Close() + $hash = [System.BitConverter]::ToString($hashBytes).Replace("-", "").ToLower() + "{0} {1}" -f $hash, $_.Name + } | Set-Content release-staging/SHA256SUMS.txt + + # Log hashes for visibility + Get-Content release-staging/SHA256SUMS.txt + + - name: Create GitHub Release + uses: softprops/action-gh-release@c062e0e6d8b788de3acf9a2f64f336f74783b400 # v2.0.8 + with: + tag_name: ${{ steps.tag_name.outputs.TAG }} + name: ${{ steps.tag_name.outputs.TAG }} + draft: false + prerelease: ${{ contains(steps.tag_name.outputs.TAG, '-pre') }} + files: | + release-staging/LibreHardwareMonitor.Windows.WinUI-net10.0.exe + release-staging/LibreHardwareMonitorLib.dll + release-staging/LibreHardwareMonitor-source.zip + release-staging/SHA256SUMS.txt diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/status-checks.yml similarity index 84% rename from .github/workflows/pull-requests.yml rename to .github/workflows/status-checks.yml index 092ff31..8fc3e3a 100644 --- a/.github/workflows/pull-requests.yml +++ b/.github/workflows/status-checks.yml @@ -1,4 +1,4 @@ -name: pull requests +name: status-checks on: pull_request: @@ -7,7 +7,7 @@ on: jobs: build: - runs-on: windows-2025 + runs-on: windows-2025-vs2026 steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0 @@ -59,22 +59,8 @@ jobs: - name: Run WinUI tests run: dotnet test LibreHardwareMonitor.Windows.WinUI.Tests\LibreHardwareMonitor.Windows.WinUI.Tests.csproj -c Release -p:Platform=x64 - - name: Publish x64 libraries - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # 7.0.1 - with: - name: LibreHardwareMonitorLib (x64) - path: | - bin/Release/x64 - - name: Build reference libraries run: dotnet build LibreHardwareMonitorLib\LibreHardwareMonitorLib.csproj -c Release --no-restore -p:BuildOnlyRefs=true - name: Pack main nupkg run: dotnet pack LibreHardwareMonitorLib\LibreHardwareMonitorLib.csproj -c Release -p:PackMainNuget=true --no-build --output bin\Release - - - name: Publish nupkg - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # 7.0.1 - with: - name: LibreHardwareMonitorLib-nupkg - path: | - bin/Release/LibreHardwareMonitorLib.*.nupkg diff --git a/LibreHardwareMonitor.Windows.WinUI.Tests/Services/AppSettingsTests.cs b/LibreHardwareMonitor.Windows.WinUI.Tests/Services/AppSettingsTests.cs index e77489f..1953206 100644 --- a/LibreHardwareMonitor.Windows.WinUI.Tests/Services/AppSettingsTests.cs +++ b/LibreHardwareMonitor.Windows.WinUI.Tests/Services/AppSettingsTests.cs @@ -18,7 +18,7 @@ public class AppSettingsTests : IDisposable // Use reflection to instantiate AppSettings with custom filename var ctor = typeof(AppSettings).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(string) }, null); - _settings = (AppSettings)ctor.Invoke(new object[] { _tempFile }); + _settings = (AppSettings)ctor!.Invoke(new object[] { _tempFile }); } public void Dispose() @@ -109,7 +109,7 @@ public class AppSettingsTests : IDisposable // Create new instance pointing to same file var ctor = typeof(AppSettings).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(string) }, null); - var loadedSettings = (AppSettings)ctor.Invoke(new object[] { _tempFile }); + var loadedSettings = (AppSettings)ctor!.Invoke(new object[] { _tempFile }); loadedSettings.Load(); diff --git a/LibreHardwareMonitor.Windows.WinUI.Tests/Utilities/SensorFormatterTests.cs b/LibreHardwareMonitor.Windows.WinUI.Tests/Utilities/SensorFormatterTests.cs index ca9dc74..81ca386 100644 --- a/LibreHardwareMonitor.Windows.WinUI.Tests/Utilities/SensorFormatterTests.cs +++ b/LibreHardwareMonitor.Windows.WinUI.Tests/Utilities/SensorFormatterTests.cs @@ -221,6 +221,7 @@ public class SensorFormatterTests mockSensor.Setup(s => s.SensorType).Returns(SensorType.Temperature); var result = SensorFormatter.GetPlotValue(mockSensor.Object, TemperatureUnit.Fahrenheit); + Assert.NotNull(result); Assert.Equal(77.9, result.Value, 1); } @@ -243,6 +244,7 @@ public class SensorFormatterTests var result = SensorFormatter.GetPlotValue(mockSensor.Object, 25.5f, TemperatureUnit.Fahrenheit); + Assert.NotNull(result); Assert.Equal(77.9, result.Value, 1); } diff --git a/LibreHardwareMonitor.Windows.WinUI.Tests/ViewModels/SimpleViewModelsTests.cs b/LibreHardwareMonitor.Windows.WinUI.Tests/ViewModels/SimpleViewModelsTests.cs index 57afbdc..d88101e 100644 --- a/LibreHardwareMonitor.Windows.WinUI.Tests/ViewModels/SimpleViewModelsTests.cs +++ b/LibreHardwareMonitor.Windows.WinUI.Tests/ViewModels/SimpleViewModelsTests.cs @@ -11,7 +11,7 @@ public class SimpleViewModelsTests { private class TestViewModel : ViewModelBase { - private string _testProperty; + private string _testProperty = string.Empty; public string TestProperty { get => _testProperty; @@ -28,7 +28,7 @@ public class SimpleViewModelsTests public void ViewModelBase_SetProperty_ChangesValueAndRaisesEvent() { var vm = new TestViewModel(); - string changedProperty = null; + string? changedProperty = null; vm.PropertyChanged += (sender, args) => changedProperty = args.PropertyName; // Change value @@ -57,7 +57,7 @@ public class SimpleViewModelsTests public void ViewModelBase_OnPropertyChanged_RaisesEvent() { var vm = new TestViewModel(); - string changedProperty = null; + string? changedProperty = null; vm.PropertyChanged += (sender, args) => changedProperty = args.PropertyName; vm.TriggerPropertyChanged("CustomProperty");