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
2 changes: 1 addition & 1 deletion Installer/Installer.iss
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#define MyAppPublisher "ThreadPilot"
#define MyAppURL "https://github.com/"
#define MyAppExeName "ThreadPilot.exe"
#define MyAppVersion "1.3.1"
#define MyAppVersion "1.4.0"

#ifndef MyWizardStyle
#define MyWizardStyle "modern dynamic windows11"
Expand Down
2 changes: 1 addition & 1 deletion Installer/ThreadPilot.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Package
Name="ThreadPilot"
Manufacturer="Prime Build"
Version="1.3.1.0"
Version="1.4.0.0"
UpgradeCode="PUT-GENERATED-UPGRADE-CODE-HERE"
Language="1033">
<SummaryInformation Description="ThreadPilot MSI template" />
Expand Down
2 changes: 1 addition & 1 deletion Installer/setup.iss
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#endif

#ifndef MyAppVersion
#define MyAppVersion "1.3.1"
#define MyAppVersion "1.4.0"
#endif

#ifndef MyAppSourceDir
Expand Down
36 changes: 18 additions & 18 deletions Tests/ThreadPilot.Core.Tests/PackagingMetadataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace ThreadPilot.Core.Tests

public sealed partial class PackagingMetadataTests
{
private const string HotfixVersion = "1.3.1";
private const string HotfixAssemblyVersion = "1.3.1.0";
private const string ReleaseVersion = "1.4.0";
private const string ReleaseAssemblyVersion = "1.4.0.0";

[Fact]
public void InnoInstallers_UseStableDisplayNameAndSeparateVersionMetadata()
Expand Down Expand Up @@ -57,24 +57,24 @@ public void PrimaryInstaller_CleansOnlyRecognizedLegacyBetaUninstallRegistryEntr
}

[Fact]
public void VersionMetadata_IsBumpedToHotfixVersion()
public void VersionMetadata_IsBumpedToReleaseVersion()
{
var root = FindRepositoryRoot();

AssertFileContains(Path.Combine(root, "ThreadPilot.csproj"), $"<Version>{HotfixVersion}</Version>");
AssertFileContains(Path.Combine(root, "ThreadPilot.csproj"), $"<AssemblyVersion>{HotfixAssemblyVersion}</AssemblyVersion>");
AssertFileContains(Path.Combine(root, "ThreadPilot.csproj"), $"<FileVersion>{HotfixAssemblyVersion}</FileVersion>");
AssertFileContains(Path.Combine(root, "ThreadPilot.csproj"), $"<InformationalVersion>{HotfixVersion}</InformationalVersion>");
AssertFileContains(Path.Combine(root, "app.manifest"), $"version=\"{HotfixAssemblyVersion}\"");
AssertFileContains(Path.Combine(root, "Installer", "ThreadPilot.wxs"), $"Version=\"{HotfixAssemblyVersion}\"");
AssertFileContains(Path.Combine(root, "chocolatey", "threadpilot.nuspec"), $"<version>{HotfixVersion}</version>");
AssertFileContains(Path.Combine(root, "chocolatey", "threadpilot.nuspec"), $"releases/tag/v{HotfixVersion}");
AssertFileContains(Path.Combine(root, "sonar-project.properties"), $"sonar.projectVersion={HotfixVersion}");
AssertFileContains(Path.Combine(root, "build", "build-release.ps1"), $"[string]$Version = \"{HotfixVersion}\"");
AssertFileContains(Path.Combine(root, "build", "build-installer.ps1"), $"[string]$Version = \"{HotfixVersion}\"");
AssertFileContains(Path.Combine(root, "build", "package-release-zips.ps1"), $"[string]$Version = \"{HotfixVersion}\"");
Assert.True(File.Exists(Path.Combine(root, "docs", "releases", $"v{HotfixVersion}.md")));
AssertFileContains(Path.Combine(root, "docs", "release", "RELEASE_NOTES.md"), $"v{HotfixVersion}");
AssertFileContains(Path.Combine(root, "ThreadPilot.csproj"), $"<Version>{ReleaseVersion}</Version>");
AssertFileContains(Path.Combine(root, "ThreadPilot.csproj"), $"<AssemblyVersion>{ReleaseAssemblyVersion}</AssemblyVersion>");
AssertFileContains(Path.Combine(root, "ThreadPilot.csproj"), $"<FileVersion>{ReleaseAssemblyVersion}</FileVersion>");
AssertFileContains(Path.Combine(root, "ThreadPilot.csproj"), $"<InformationalVersion>{ReleaseVersion}</InformationalVersion>");
AssertFileContains(Path.Combine(root, "app.manifest"), $"version=\"{ReleaseAssemblyVersion}\"");
AssertFileContains(Path.Combine(root, "Installer", "ThreadPilot.wxs"), $"Version=\"{ReleaseAssemblyVersion}\"");
AssertFileContains(Path.Combine(root, "chocolatey", "threadpilot.nuspec"), $"<version>{ReleaseVersion}</version>");
AssertFileContains(Path.Combine(root, "chocolatey", "threadpilot.nuspec"), $"releases/tag/v{ReleaseVersion}");
AssertFileContains(Path.Combine(root, "sonar-project.properties"), $"sonar.projectVersion={ReleaseVersion}");
AssertFileContains(Path.Combine(root, "build", "build-release.ps1"), $"[string]$Version = \"{ReleaseVersion}\"");
AssertFileContains(Path.Combine(root, "build", "build-installer.ps1"), $"[string]$Version = \"{ReleaseVersion}\"");
AssertFileContains(Path.Combine(root, "build", "package-release-zips.ps1"), $"[string]$Version = \"{ReleaseVersion}\"");
Assert.True(File.Exists(Path.Combine(root, "docs", "releases", $"v{ReleaseVersion}.md")));
AssertFileContains(Path.Combine(root, "docs", "release", "RELEASE_NOTES.md"), $"v{ReleaseVersion}");
}

private static void AssertFileContains(string path, string expected)
Expand All @@ -100,7 +100,7 @@ private static string FindRepositoryRoot()
throw new InvalidOperationException("Repository root could not be located.");
}

[GeneratedRegex("#define MyAppVersion \"1\\.3\\.1\"", RegexOptions.CultureInvariant)]
[GeneratedRegex("#define MyAppVersion \"1\\.4\\.0\"", RegexOptions.CultureInvariant)]
private static partial Regex MyAppVersionRegex();
}
}
8 changes: 4 additions & 4 deletions ThreadPilot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
<TrimMode>link</TrimMode>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn>CS1998;CS0067;CS0414;WFAC010;IL3000;MVVMTK0034</NoWarn>
<Version>1.3.1</Version>
<AssemblyVersion>1.3.1.0</AssemblyVersion>
<FileVersion>1.3.1.0</FileVersion>
<InformationalVersion>1.3.1</InformationalVersion>
<Version>1.4.0</Version>
<AssemblyVersion>1.4.0.0</AssemblyVersion>
<FileVersion>1.4.0.0</FileVersion>
<InformationalVersion>1.4.0</InformationalVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion app.manifest
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.3.1.0" name="ThreadPilot.app"/>
<assemblyIdentity version="1.4.0.0" name="ThreadPilot.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
Expand Down
2 changes: 1 addition & 1 deletion build/build-installer.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
param(
[string]$Version = "1.3.1",
[string]$Version = "1.4.0",
[string]$Configuration = "Release",
[switch]$SkipPublish
)
Expand Down
2 changes: 1 addition & 1 deletion build/build-release.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
param(
[string]$Version = "1.3.1",
[string]$Version = "1.4.0",
[string]$Configuration = "Release",
[string]$Runtime = "win-x64"
)
Expand Down
2 changes: 1 addition & 1 deletion build/package-release-zips.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
param(
[string]$Version = "1.3.1"
[string]$Version = "1.4.0"
)

$ErrorActionPreference = "Stop"
Expand Down
4 changes: 2 additions & 2 deletions chocolatey/threadpilot.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
<metadata>
<id>threadpilot</id>
<version>1.3.1</version>
<version>1.4.0</version>
<title>ThreadPilot</title>
<authors>Prime Build</authors>
<projectUrl>https://github.com/PrimeBuild-pc/ThreadPilot</projectUrl>
Expand All @@ -15,7 +15,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Advanced Windows process and power plan manager with rules automation and performance controls.</description>
<summary>ThreadPilot process and power plan manager.</summary>
<releaseNotes>https://github.com/PrimeBuild-pc/ThreadPilot/releases/tag/v1.3.1</releaseNotes>
<releaseNotes>https://github.com/PrimeBuild-pc/ThreadPilot/releases/tag/v1.4.0</releaseNotes>
<tags>threadpilot process powerplan performance windows</tags>
</metadata>
<files>
Expand Down
38 changes: 38 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,44 @@

All notable changes to this project are documented in this file.

## v1.4.0 - Safe in-app updater

### Added

- Added safe in-app updater support.
- Added manual update checks from Settings.
- Added optional background update checks with a default 7-day interval.
- Added latest/current version display in Settings.
- Added update download and install flow with explicit user confirmation.
- Added updater documentation.

### Security

- Update metadata is fetched only from the official PrimeBuild-pc/ThreadPilot GitHub repository.
- Prereleases are excluded by default.
- Installer assets are selected from GitHub HTTPS release assets.
- SHA256 checksums are verified when SHA256SUMS.txt is available.
- Checksum mismatches are rejected.
- Authenticode signature verification is performed on a best-effort basis, rejecting explicitly invalid signatures.
- Installer launch uses ProcessStartInfo without shell command construction.
- Concurrent update attempts are prevented.

### User data preservation

- Updates preserve AppData, settings, profiles, CPU masks, rules, custom/imported power plans, and logs.
- Only updater temporary files are cleaned by the update flow.
- Full uninstall behavior remains separate.

### Changed

- Project version updated to 1.4.0.
- Installer, packaging, Chocolatey, and release metadata updated to v1.4.0.

### Verification

- Build passed.
- Automated tests passed.

## v1.3.1 - Localization and installer metadata hotfix

### Fixed
Expand Down
18 changes: 9 additions & 9 deletions docs/release/PACKAGING.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,9 @@ Generate manifests locally with:

```powershell
./build/generate-winget-manifests.ps1 `
-Version "1.3.0" `
-Tag "v1.3.0" `
-InstallerUrl "https://github.com/PrimeBuild-pc/ThreadPilot/releases/download/v1.3.0/ThreadPilot_v1.3.0_Setup.exe" `
-Version "1.4.0" `
-Tag "v1.4.0" `
-InstallerUrl "https://github.com/PrimeBuild-pc/ThreadPilot/releases/download/v1.4.0/ThreadPilot_v1.4.0_Setup.exe" `
-InstallerSha256 "<sha256>" `
-OutputRoot "winget-manifests"
```
Expand Down Expand Up @@ -224,9 +224,9 @@ Local packaging-only validation:

```powershell
./build/publish-chocolatey.ps1 `
-Version "1.3.0" `
-Tag "v1.3.0" `
-InstallerPath ".\artifacts\release\installer\ThreadPilot_v1.3.0_Setup.exe" `
-Version "1.4.0" `
-Tag "v1.4.0" `
-InstallerPath ".\artifacts\release\installer\ThreadPilot_v1.4.0_Setup.exe" `
-DryRun `
-PackageOutputDirectory ".\artifacts\choco-dryrun" `
-MetadataOutputPath ".\artifacts\choco-dryrun\chocolatey-package-metadata.json"
Expand All @@ -250,9 +250,9 @@ Public publish path:

```powershell
./build/publish-chocolatey.ps1 `
-Version "1.3.0" `
-Tag "v1.3.0" `
-InstallerPath ".\artifacts\release\installer\ThreadPilot_v1.3.0_Setup.exe" `
-Version "1.4.0" `
-Tag "v1.4.0" `
-InstallerPath ".\artifacts\release\installer\ThreadPilot_v1.4.0_Setup.exe" `
-ApiKey "<chocolatey-api-key>"
```

Expand Down
58 changes: 27 additions & 31 deletions docs/release/RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,37 @@
# ThreadPilot v1.3.1 Release Notes Draft
## ThreadPilot v1.4.0

## Highlights
### Added

- Completed the Simplified Chinese localization pass for the main WPF views, dialogs, context menus, tray menu, tooltips, accessibility text, status text, and user-facing service notifications.
- Kept English as the default startup language and Simplified Chinese as an optional Settings choice.
- Changed installer display metadata so installed apps list ThreadPilot as `ThreadPilot` while preserving version metadata separately as `1.3.1`.
- Improved uninstall cleanup for ThreadPilot-owned application files, shortcuts, startup entries, and per-user AppData/settings when the uninstaller runs.
- Added safe in-app updater support.
- Added manual update checks from Settings.
- Added optional background update checks with a default 7-day interval.
- Added latest/current version display in Settings.
- Added update download and install flow with explicit user confirmation.
- Added updater documentation.

## Fixed
### Security

- Fixed incomplete zh-CN coverage that left many v1.3.0 UI surfaces in English.
- Fixed Inno Setup `AppVerName` so uninstall tools do not show versioned names such as `ThreadPilot 1.3.1`.
- Added guarded cleanup for the obsolete `ThreadPilot 0.1.0-beta` uninstall registry entry only when it exactly matches the legacy ThreadPilot display name and Program Files install location.
- Update metadata is fetched only from the official PrimeBuild-pc/ThreadPilot GitHub repository.
- Prereleases are excluded by default.
- Installer assets are selected from GitHub HTTPS release assets.
- SHA256 checksums are verified when SHA256SUMS.txt is available.
- Checksum mismatches are rejected.
- Authenticode signature verification is performed on a best-effort basis, rejecting explicitly invalid signatures.
- Installer launch uses ProcessStartInfo without shell command construction.
- Concurrent update attempts are prevented.

## Safety
### User data preservation

- No automatic in-app updater was added.
- No elevation, affinity, process control, power plan, or system tweak behavior was changed.
- Normal install/update preserves existing user settings and data.
- Full uninstall removes only ThreadPilot-owned AppData for the uninstalling user account; elevated uninstall contexts may not be able to clean another Windows user's per-user AppData.
- Updates preserve AppData, settings, profiles, CPU masks, rules, custom/imported power plans, and logs.
- Only updater temporary files are cleaned by the update flow.
- Full uninstall behavior remains separate.

## Testing
### Changed

- Added resource key parity coverage for `Locales/en-US.xaml` and `Locales/zh-CN.xaml`.
- Added hardcoded-English checks for important WPF views with brand and technical terms whitelisted.
- Added release metadata tests for installer display name, uninstall cleanup scope, legacy beta uninstall-entry cleanup, and v1.3.1 version surfaces.
- Project version updated to 1.4.0.
- Installer, packaging, Chocolatey, and release metadata updated to v1.4.0.

## Compatibility and Upgrade Notes
### Verification

- Requires Windows 11 build 22000 or newer.
- Existing settings, profiles, masks, persistent rules, imported power plans, and logs continue to load after update.
- Existing process, affinity, power plan, automation, and system tweak behavior is unchanged.

## Known Non-Goals

- No GitHub release or tag is created by this hotfix branch.
- No automatic in-app updating.
- No anti-cheat bypass.
- No Windows Service.
- No registry or IFEO persistence.
- Build passed.
- Automated tests passed.
37 changes: 37 additions & 0 deletions docs/releases/v1.4.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## ThreadPilot v1.4.0

### Added

- Added safe in-app updater support.
- Added manual update checks from Settings.
- Added optional background update checks with a default 7-day interval.
- Added latest/current version display in Settings.
- Added update download and install flow with explicit user confirmation.
- Added updater documentation.

### Security

- Update metadata is fetched only from the official PrimeBuild-pc/ThreadPilot GitHub repository.
- Prereleases are excluded by default.
- Installer assets are selected from GitHub HTTPS release assets.
- SHA256 checksums are verified when SHA256SUMS.txt is available.
- Checksum mismatches are rejected.
- Authenticode signature verification is performed on a best-effort basis, rejecting explicitly invalid signatures.
- Installer launch uses ProcessStartInfo without shell command construction.
- Concurrent update attempts are prevented.

### User data preservation

- Updates preserve AppData, settings, profiles, CPU masks, rules, custom/imported power plans, and logs.
- Only updater temporary files are cleaned by the update flow.
- Full uninstall behavior remains separate.

### Changed

- Project version updated to 1.4.0.
- Installer, packaging, Chocolatey, and release metadata updated to v1.4.0.

### Verification

- Build passed.
- Automated tests passed.
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
sonar.projectKey=threadpilot
sonar.projectName=ThreadPilot
sonar.projectVersion=1.3.1
sonar.projectVersion=1.4.0

sonar.sourceEncoding=UTF-8
sonar.sources=.
Expand Down
Loading