Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
name: Build and Release
name: Build

on:
push:
branches: [main]
tags: ["v*"]
pull_request:
workflow_dispatch:

permissions:
contents: write
contents: read

jobs:
build:
Expand Down Expand Up @@ -98,10 +97,3 @@ jobs:
with:
name: ThermoTray-release-${{ env.AppVersion }}
path: artifacts/release

- name: Create GitHub Release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v3
with:
files: artifacts/release/*
generate_release_notes: true
52 changes: 44 additions & 8 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,31 @@ jobs:
"AppVersion=$version" >> $env:GITHUB_ENV
"ReleaseTag=$tag" >> $env:GITHUB_ENV

- run: dotnet restore ThermoTray.sln
# Restore with the publish RID so build, test and publish share one assets graph.
- run: dotnet restore ThermoTray.sln --runtime win-x64
- run: dotnet build ThermoTray.sln --configuration Release --no-restore
- run: dotnet test ThermoTray.sln --configuration Release --no-build
- run: dotnet test ThermoTray.sln --configuration Release --no-build --no-restore
- run: dotnet format ThermoTray.sln --verify-no-changes --no-restore --verbosity minimal

- run: dotnet publish src/ThermoTray/ThermoTray.csproj --configuration Release --runtime win-x64 --self-contained true -p:PublishSingleFile=true --output publish/win-x64
- run: dotnet publish src/ThermoTray/ThermoTray.csproj --configuration Release --runtime win-x64 --self-contained true -p:PublishSingleFile=true --no-restore --output publish/win-x64

- name: Verify embedded administrator manifest
shell: pwsh
run: |
$mt = Get-ChildItem -Path "${env:ProgramFiles(x86)}\Windows Kits\10\bin" -Filter mt.exe -Recurse -ErrorAction SilentlyContinue |
Sort-Object FullName -Descending |
Select-Object -First 1
if (-not $mt) { throw 'Windows SDK Manifest Tool (mt.exe) was not found' }

New-Item -ItemType Directory -Force -Path artifacts/verification | Out-Null
& $mt.FullName '-inputresource:publish/win-x64/ThermoTray.exe;#1' '-out:artifacts/verification/manifest.xml'
if ($LASTEXITCODE -ne 0) { throw "mt.exe failed with exit code $LASTEXITCODE" }

$manifest = Get-Content artifacts/verification/manifest.xml -Raw
if ($manifest -notmatch 'requestedExecutionLevel\s+level="requireAdministrator"') {
throw 'The published executable does not require administrator elevation'
}

- run: choco install innosetup --no-progress --yes
- run: '& "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" /DAppVersion=$env:AppVersion installer\ThermoTray.iss'
shell: pwsh
Expand All @@ -46,9 +65,25 @@ jobs:
- name: Build the portable archive
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path artifacts | Out-Null
$files = Get-ChildItem publish/win-x64 -Exclude *.pdb
Compress-Archive -Path $files -DestinationPath "artifacts/ThermoTray-$env:AppVersion-win-x64-portable.zip" -Force
$releaseDir = Join-Path $PWD 'artifacts/release'
New-Item -ItemType Directory -Force -Path $releaseDir | Out-Null
$files = Get-ChildItem publish/win-x64 -File | Where-Object Extension -ne '.pdb'
$zipPath = Join-Path $releaseDir "ThermoTray-$env:AppVersion-win-x64-portable.zip"
Compress-Archive -Path $files -DestinationPath $zipPath -CompressionLevel Optimal -Force

$installerPath = "artifacts/installer/ThermoTray-Setup-$env:AppVersion.exe"
if (-not (Test-Path -LiteralPath $installerPath)) {
throw "Installer was not created: $installerPath"
}
Copy-Item -LiteralPath $installerPath -Destination $releaseDir

$checksums = Get-ChildItem $releaseDir -File |
Sort-Object Name |
ForEach-Object {
$hash = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash
"$hash $($_.Name)"
}
$checksums | Set-Content -LiteralPath (Join-Path $releaseDir 'SHA256SUMS.txt') -Encoding utf8

# Creates the tag at this commit when it does not exist yet, which is what makes a manual run a
# complete release path rather than something that has to be tagged first.
Expand All @@ -58,8 +93,9 @@ jobs:
GH_TOKEN: ${{ github.token }}
run: |
gh release create $env:ReleaseTag `
"artifacts/installer/ThermoTray-Setup-$env:AppVersion.exe" `
"artifacts/ThermoTray-$env:AppVersion-win-x64-portable.zip" `
"artifacts/release/ThermoTray-Setup-$env:AppVersion.exe" `
"artifacts/release/ThermoTray-$env:AppVersion-win-x64-portable.zip" `
"artifacts/release/SHA256SUMS.txt" `
--target $env:GITHUB_SHA `
--title "ThermoTray $env:AppVersion" `
--generate-notes
52 changes: 52 additions & 0 deletions AI_HANDOFF.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,55 @@ Findings and what each one changed. None of them reproduced on this machine's ow
- User requested publication to GitHub and release of the executable. The repository is `https://github.com/nojackno2-ctrl/ThermoTray.git`, currently on `main` with the full intended ThermoTray change set uncommitted.
- `gh` version `2.95.0` is installed, but `gh auth status` reports `The token in default is invalid` for `nojackno2-ctrl`. No commit, push, pull request, or GitHub Release was performed.
- Resume with `gh auth login -h github.com`, then rerun `gh auth status` before staging. The intended release assets are the latest portable ZIP in `artifacts\\release` and the self-contained executable from `publish\\win-x64`; Inno Setup is unavailable locally, so no fresh installer exists.

## 2026-08-05 full code review and safe cleanup

- The working tree was clean on `main` at `b8625f7`; the current baseline built with 0 warnings/errors, passed 137 tests, passed `dotnet format --verify-no-changes`, `git diff --check`, and an additional .NET analyzer build with 0 warnings.
- Fixed hardware-topology lifecycle issues: removed old sensor event handlers before rebuilding the cached topology, cleared reference-keyed source-name entries when sensors are re-enumerated, retry-marked failed topology scans, and detached computer handlers when `Computer.Open()` fails so retries cannot accumulate callbacks.
- Fixed a possible UI crash when registry I/O fails while changing the startup setting by treating `IOException` like the other expected startup failures.
- Fixed the native HICON cleanup path so an exception during icon conversion cannot leak the temporary icon handle.
- Fixed a startup-setting race: background reconciliation now serializes Task Scheduler operations and ignores stale results when the user changes the checkbox during the probe or registration.
- Fixed CI/release overlap: the regular build workflow is now read-only CI and no longer triggers or creates releases on tags; the dedicated release workflow now restores with `win-x64`, publishes with the shared assets graph, and includes a `SHA256SUMS.txt` release asset as documented.
- Final validation: Release build passed with 0 warnings/errors; all 137 tests passed; `dotnet format --verify-no-changes` and `git diff --check` passed; explicit `win-x64` self-contained single-file publish passed. The review EXE in `publish\win-x64-review` contains 9 files totalling 187,372,368 bytes, has SHA-256 `0067F2779C16CA35265E8FEEC7BBA2B7CF7C9A1E3481371B1665EA6FDDD9315D`, and its embedded manifest is `requireAdministrator`. Static workflow checks confirmed only `release.yml` owns tag releases, preserves the embedded-manifest check, and publishes `SHA256SUMS.txt`. README examples now use 1.1.3. No commit or push was performed.

## 2026-08-05 complete codebase Chinese commenting

- Added comprehensive Traditional Chinese XML documentation comments (`/// <summary>`) and inline logic comments to all C# source files in `src/ThermoTray/`, all unit test files in `tests/ThermoTray.Tests/`, and the Inno Setup script `installer/ThermoTray.iss`.
- Preserved all code behavior, method signatures, and recent uncommitted bug fixes in `HardwareSensorService.cs`, `MainViewModel.cs`, and `TrayIconService.cs`.
- Validation: `dotnet build ThermoTray.sln --configuration Release` passed with 0 warnings and 0 errors; `dotnet test ThermoTray.sln --configuration Release` passed all 137 tests; `dotnet format ThermoTray.sln --verify-no-changes` passed with code 0.

## 2026-08-05 GitHub release preparation

- Bumped the product version from 1.1.3 to 1.1.4 because v1.1.3 already exists on GitHub; updated the installer fallback and README release examples accordingly.
- Explicit `win-x64` restore, Release build, 137 tests, format verification, and `git diff --check` passed.
- Self-contained `win-x64` publish passed and `mt.exe` confirmed the embedded `requireAdministrator` manifest. Inno Setup 6.7.3 compiled `artifacts\\installer\\ThermoTray-Setup-1.1.4.exe` successfully.
- The first local ZIP command failed because `Compress-Archive` received `FileInfo` objects instead of full paths; no product failure was indicated. Re-running with explicit full paths succeeded: installer `artifacts\\release\\ThermoTray-Setup-1.1.4.exe` is 53,992,887 bytes with SHA-256 `72DC90703E5F6F637F916A7EB2C1D70CED40EDB40F1E8052F1A0BECC13D472AB`; portable ZIP is 73,804,923 bytes with SHA-256 `FBA7485DB57BF2C4C27A329B4AEF847CDAC5B1253474EF356394CEB5703CBFCE`; the ZIP contains 8 files and no PDB.
- Pushed branch `agent/release-1.1.4` at commit `76665a3` and opened draft PR #3. GitHub Actions release run `30962293962` passed every build, test, format, publish, manifest, installer, archive, and release step.
- Published formal GitHub Release `v1.1.4` at `https://github.com/nojackno2-ctrl/ThermoTray/releases/tag/v1.1.4`. Downloaded remote assets were rehashed successfully: installer `53,994,651` bytes, SHA-256 `D9F0EBCCB2B6137DCCA8C6A46188BCFB38A798A67B5F7011206617E818124808`; portable ZIP `76,249,140` bytes, SHA-256 `EBDDA19A879F9F25455CDF2EE8989B497F83A606D60FC40552EAC33FD1D3268F`.

## 2026-08-05 dual-GPU utilization investigation

- The user reported that GPU utilization is ambiguous when the machine has both an NVIDIA dGPU and an AMD integrated GPU. The current `HardwareSensorService` ranks all GPU temperature sensors globally and all GPU load sensors globally, so the selected utilization and temperature can come from different physical GPUs; the screenshot shows 5% utilization while the source label is NVIDIA, matching this defect.
- Planned fix: retain GPU identity through the reading pipeline, pair temperature and load by `IHardware`, and expose one view-model card per readable GPU so each device has its own utilization, temperature, and source label. Live hardware verification remains pending.
- Implemented: `HardwareSensorService` now builds one candidate group per GPU hardware and returns `GpuReading` entries with paired temperature/load values; `MainViewModel` exposes an independent `GpuViewModel` for every entry; `MainWindow` renders a dynamic card for each GPU; `TrayIconService` creates and updates one independent GPU icon per entry with GPU number/device-name tooltips. The former single-GPU properties were removed, and the UI test fixture now covers NVIDIA + AMD cards.
- Validation after the implementation: `dotnet build ThermoTray.sln --configuration Release --no-restore` passed with 0 warnings/errors; `dotnet test ThermoTray.sln --configuration Release --no-build` passed 137/137. Live dual-GPU readings and final visual tray ordering remain pending manual launch on the user's machine.
- Final local validation after the README and ranking cleanup: Release build passed with 0 warnings/errors; all 137 tests passed; `dotnet format ThermoTray.sln --verify-no-changes --no-restore --verbosity minimal` passed; `git diff --check` passed. No commit or push was performed.

## 2026-08-05 card headings and tray field visibility

- Implemented the user's request to move device names to the top of each CPU/GPU card. CPU readings now carry the hardware name separately from the sensor source label; the source line below the values contains only the sensor name.
- Added independent persisted notification-area visibility choices for CPU utilization, CPU temperature, and each GPU's utilization and temperature. Existing settings default to showing every field; GPU choices are keyed by the stable GPU hardware ID.
- The cards keep showing all live values regardless of these choices. Tray icons hide unchecked lines, hide the whole icon when both lines are unchecked, and tooltips list only selected values while retaining device identification.
- Added 3 regression tests, bringing the local total to 140. Release `dotnet test --no-restore` passed 140/140; `dotnet format --verify-no-changes --no-restore` and `git diff --check` passed. No commit or push was performed.
- Elevated live UI and notification-area visual verification remains pending; the user must launch the updated publish/installer build to confirm the final arrangement on the actual display.

## 2026-08-05 GPU device-name duplication fix

- The user reported that GPU names appeared twice in the card. The top line already showed `DeviceName`, while the bottom `Source` line still contained `DeviceName • GPU Core`.
- `GpuViewModel` now strips the hardware-name prefix from the source line, matching the CPU card behavior; the card keeps the top device name and the `GPU 0/1` identifier.
- Added a regression test for the source text. Release `dotnet test --no-restore` passed 141/141; final visual verification remains pending manual launch.

## 2026-08-05 local branch integration

- Fast-forwarded the local `main` branch from `b8625f7` to `0407c60`, integrating the committed `agent/release-1.1.4` release work without creating an unnecessary merge commit.
- The working tree still contains the existing uncommitted GPU/card changes and was not staged, committed, stashed, or discarded. `origin/main` remains at `b8625f7`; no remote push was performed.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<!-- Single source of truth for the product version. The installer and CI read it from here. -->
<Version>1.1.3</Version>
<Version>1.1.4</Version>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down
Loading