-
Notifications
You must be signed in to change notification settings - Fork 0
Phases 2-5: application shell, safety, network profiles and distribution #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
825876f
a14466c
9aba51e
b3fe30b
aa63571
cfa2ea1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| name: Release | ||
|
|
||
| on: | ||
| push: | ||
| tags: [ 'v*' ] | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: 'Version to build (without the leading v)' | ||
| required: true | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| jobs: | ||
| release: | ||
| name: Build and publish | ||
| runs-on: windows-latest | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Resolve version | ||
| id: version | ||
| shell: powershell | ||
| run: | | ||
| $version = if ($env:GITHUB_REF -like 'refs/tags/v*') { | ||
| $env:GITHUB_REF -replace '^refs/tags/v', '' | ||
| } else { | ||
| '${{ github.event.inputs.version }}' | ||
| } | ||
| "version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 | ||
| Write-Host "Building version $version" | ||
|
|
||
| - name: Verify the manifest matches the tag | ||
| shell: powershell | ||
| run: | | ||
| $manifest = Import-PowerShellDataFile ./src/PCTools/PCTools.psd1 | ||
| $tagged = '${{ steps.version.outputs.version }}' | ||
| if ($manifest.ModuleVersion -ne $tagged) { | ||
| throw "Tag v$tagged does not match ModuleVersion $($manifest.ModuleVersion). Bump the manifest before tagging." | ||
| } | ||
|
|
||
| - name: Install test dependencies | ||
| shell: powershell | ||
| run: | | ||
| Set-PSRepository PSGallery -InstallationPolicy Trusted | ||
| Install-Module Pester -MinimumVersion 5.5.0 -Force -SkipPublisherCheck -Scope CurrentUser | ||
| Install-Module PSScriptAnalyzer -RequiredVersion 1.22.0 -Force -Scope CurrentUser | ||
|
|
||
| # Never publish something that has not passed its own suite. | ||
| - name: Test and analyze | ||
| shell: powershell | ||
| run: ./build/Invoke-Build.ps1 -Task All | ||
|
|
||
| - name: Stage artifacts and checksums | ||
| shell: powershell | ||
| run: ./build/Invoke-Build.ps1 -Task Release -Version ${{ steps.version.outputs.version }} | ||
|
|
||
| # Signing runs only when a certificate is configured. Without it the | ||
| # release still ships, unsigned, with checksums - which is what the | ||
| # project has today. | ||
| - name: Sign scripts | ||
| if: ${{ secrets.SIGNING_CERTIFICATE != '' }} | ||
| env: | ||
| SIGNING_CERTIFICATE: ${{ secrets.SIGNING_CERTIFICATE }} | ||
| SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} | ||
| shell: powershell | ||
| run: | | ||
| $pfxPath = Join-Path $env:RUNNER_TEMP 'signing.pfx' | ||
| [IO.File]::WriteAllBytes($pfxPath, [Convert]::FromBase64String($env:SIGNING_CERTIFICATE)) | ||
| $password = ConvertTo-SecureString $env:SIGNING_PASSWORD -AsPlainText -Force | ||
| $cert = Get-PfxCertificate -FilePath $pfxPath -Password $password | ||
|
|
||
| Get-ChildItem ./out -Include *.ps1, *.psm1, *.psd1 -Recurse | ForEach-Object { | ||
| Set-AuthenticodeSignature -FilePath $_.FullName -Certificate $cert ` | ||
| -TimestampServer 'http://timestamp.digicert.com' -HashAlgorithm SHA256 | ||
| } | ||
|
|
||
| Remove-Item $pfxPath -Force | ||
|
|
||
| # Signing rewrites the files, so the checksums must be regenerated. | ||
| ./build/Invoke-Build.ps1 -Task Checksum | ||
|
|
||
| # Publishing to the Gallery is opt-in: without an API key the release | ||
| # still ships as an archive. Gallery versions are immutable, so this runs | ||
| # after the suite has passed and only for a tagged build. | ||
| - name: Publish to the PowerShell Gallery | ||
| if: ${{ secrets.PSGALLERY_API_KEY != '' && startsWith(github.ref, 'refs/tags/v') }} | ||
| shell: powershell | ||
| env: | ||
| PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} | ||
| run: | | ||
| $module = './src/PCTools' | ||
|
|
||
| # Refuse to republish a version that already exists - the Gallery | ||
| # rejects it anyway, and failing here says why. | ||
| $version = (Import-PowerShellDataFile "$module/PCTools.psd1").ModuleVersion | ||
| $existing = Find-Module PCTools -RequiredVersion $version -ErrorAction SilentlyContinue | ||
| if ($existing) { | ||
| throw "PCTools $version is already on the PowerShell Gallery. Bump ModuleVersion before tagging." | ||
| } | ||
|
|
||
| Publish-Module -Path $module -NuGetApiKey $env:PSGALLERY_API_KEY -Verbose | ||
|
|
||
| - name: Publish release | ||
| uses: softprops/action-gh-release@v2 | ||
| with: | ||
| files: | | ||
| out/* | ||
|
Comment on lines
+106
to
+110
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When this workflow is run through Useful? React with 👍 / 👎. |
||
| generate_release_notes: true | ||
| body: | | ||
| ## Verifying this release | ||
|
|
||
| Every file below is listed in `SHA256SUMS`. Verify before running: | ||
|
|
||
| ```powershell | ||
| $file = 'pc-tools.ps1' | ||
| (Get-FileHash $file -Algorithm SHA256).Hash.ToLower() | ||
| # compare against the matching line in SHA256SUMS | ||
| ``` | ||
|
|
||
| Install commands are pinned to this tag in the | ||
| [README](https://github.com/likeBloodMoon/pc-powershelltools#install). | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,3 +20,4 @@ desktop.ini | |
| # PowerShell | ||
| *.psproj | ||
| testResults*.xml | ||
| obj/ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| # Migrating from the single-file tools | ||
|
|
||
| `pc-cleanuptool.ps1` and `pc-netdiag.ps1` still work and are still shipped. They | ||
| are frozen: bug fixes only, no new features. Everything they do now lives in the | ||
| `PCTools` module, usually with more control and always with a way to preview it | ||
| first. | ||
|
|
||
| ## Why bother | ||
|
|
||
| - `-WhatIf` on every action, so you can see the plan before committing to it. | ||
| - Actions return objects, so you can filter, total and export them. | ||
| - Failures are reported. The originals piped DISM, SFC, CHKDSK and winget to | ||
| `Out-Null`, so a failed repair looked exactly like a successful one. | ||
| - Preferences can be read and reverted, not just applied. | ||
| - Nothing blocks the UI thread. | ||
|
|
||
| ## Command mapping | ||
|
|
||
| ### Cleanup | ||
|
|
||
| | Was | Now | | ||
| |---|---| | ||
| | `Clear-TempFiles` | `Clear-PCTempFile` | | ||
| | `Clear-RecycleBinSafe` | `Clear-PCRecycleBin` | | ||
| | `Clear-WindowsUpdateCache` | `Clear-PCWindowsUpdateCache` | | ||
| | `Clear-PrefetchCache` | `Clear-PCPrefetchCache` | | ||
| | — | `Clear-PCBrowserCache` (new) | | ||
|
|
||
| ### Repair | ||
|
|
||
| | Was | Now | | ||
| |---|---| | ||
| | `Run-SystemHealthChecks` | `Repair-PCSystemImage` **and** `Repair-PCSystemFile` (split; DISM and SFC report separately) | | ||
| | `Run-ChkDskScan` | `Test-PCDisk` (takes a `-DriveLetter`; was hard-coded to `C:`) | | ||
| | `Create-SystemRestorePoint` | `New-PCRestorePoint` | | ||
|
|
||
| ### Network | ||
|
|
||
| | Was | Now | | ||
| |---|---| | ||
| | `Flush-DnsCache` | `Clear-PCDnsCache` | | ||
| | `Reset-NetworkStack` | `Reset-PCNetworkStack` (add `-SkipWinsock` to keep VPN LSPs) | | ||
| | `Get-ActiveAdapters` | `Get-PCNetworkAdapter -ConnectedOnly` | | ||
| | `Set-StaticIP` | `Set-PCNetworkAddress` (takes `-PrefixLength` or `-SubnetMask`) | | ||
| | `Set-DnsServers` | `Set-PCDnsServer` (or `-Preset Cloudflare\|Google\|Quad9`) | | ||
| | `Set-DhcpMode` | `Set-PCDhcp` (now also resets DNS) | | ||
| | `Run-QuickDiagnostics` | `Get-PCNetworkReport` | | ||
| | `Start-FullDiagnosticsWorker` | `Get-PCNetworkReport -Full` | | ||
| | `Save-Report` | `Export-PCReport` (works for any results, not just network) | | ||
|
|
||
| ### Preferences | ||
|
|
||
| The six one-way setters (`Set-DarkTheme`, `Disable-BingSearch`, | ||
| `Show-HiddenFiles`, `Show-FileExtensions`, `Disable-MouseAcceleration`, | ||
| `Enable-NumLock`) are replaced by two commands over a table of definitions: | ||
|
|
||
| ```powershell | ||
| Get-PCPreference # what is set right now | ||
| Set-PCPreference -Name DarkMode -Enabled $true # apply | ||
| Set-PCPreference -Name DarkMode -Enabled $false # restore the Windows default | ||
| ``` | ||
|
|
||
| Names: `DarkMode`, `DisableBingSearch`, `ShowHiddenFiles`, `ShowFileExtensions`, | ||
| `DisableMouseAcceleration`, `NumLockOnStartup`, `DisableStartMenuSuggestions`, | ||
| `ShowFullPathInTitleBar`, `LaunchExplorerToThisPC`. | ||
|
|
||
| ### Software | ||
|
|
||
| | Was | Now | | ||
| |---|---| | ||
| | `Install-BasicApps` | `Install-PCApplication -Preset Essentials` (or `-Id <winget ids>`) | | ||
|
|
||
| ## Behaviour changes worth knowing | ||
|
|
||
| - **`Run all` is now a profile.** `Invoke-PCMaintenance -ProfileName Full`. It | ||
| takes a restore point first and stops if it cannot. | ||
| - **Prefetch is not in any profile.** Clearing it costs launch performance for a | ||
| small disk saving. Call `Clear-PCPrefetchCache` explicitly if you want it. | ||
| - **The network stack reset is not in any general profile** and prompts by | ||
| default (`ConfirmImpact = 'High'`). | ||
| - **A failed action no longer stops the batch.** Every action reports its own | ||
| result; pass `-ContinueOnFailure $false` for the old behaviour. | ||
| - **Subnet masks are converted, not passed through.** `255.0.255.0` is rejected | ||
| as invalid rather than handed to `netsh`. | ||
|
|
||
| ## Running the old tools | ||
|
|
||
| Nothing was removed: | ||
|
|
||
| ```powershell | ||
| .\pc-cleanuptool.ps1 | ||
| .\pc-netdiag.ps1 | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,33 +1,40 @@ | ||
| @{ | ||
| # Target the lowest runtime the GUI supports. WinForms requires Windows | ||
| # PowerShell 5.1, so compatibility is checked against that. | ||
| Severity = @('Error', 'Warning') | ||
|
|
||
| ExcludeRules = @( | ||
| # The GUI shell intentionally holds module-scoped state ($sync, $App) | ||
| # that the analyzer reads as "assigned but never used". | ||
| 'PSUseDeclaredVarsMoreThanAssignments', | ||
| # The GUI shell deliberately holds module-scoped state ($sync, $App, | ||
| # control variables) that the analyzer reads as "assigned but never | ||
| # used" because the reads happen inside event handlers. | ||
| 'PSUseDeclaredVarsMoreThanAssignments' | ||
|
|
||
| # Write-Host is a deliberate choice in the console entry points, where | ||
| # coloured progress output is the whole point. | ||
| # Write-Host is a deliberate choice in the console entry points and the | ||
| # build script, where coloured progress output is the point. | ||
| 'PSAvoidUsingWriteHost' | ||
|
|
||
| # False-positive here by construction. Nearly every public action wraps | ||
| # its work in `Invoke-PCAction -Body { ... }`, and the analyzer does not | ||
| # follow parameter use into that scriptblock, so it flags parameters | ||
| # that are plainly used two lines further down. | ||
| 'PSReviewUnusedParameter' | ||
|
|
||
| # Purely cosmetic and extremely noisy against this codebase's existing | ||
| # style, including the original scripts. Enabling them buried the rules | ||
| # that catch real problems under a thousand indentation notes. Revisit | ||
| # as a one-off reformat, not as a gate. | ||
| 'PSUseConsistentIndentation' | ||
| 'PSUseConsistentWhitespace' | ||
| 'PSAlignAssignmentStatement' | ||
| 'PSPlaceOpenBrace' | ||
| 'PSPlaceCloseBrace' | ||
| ) | ||
|
|
||
| Rules = @{ | ||
| # The one formatting-adjacent rule worth keeping: it catches syntax that | ||
| # parses in PowerShell 7 but not in 5.1, which is the runtime the GUI | ||
| # actually requires. | ||
| PSUseCompatibleSyntax = @{ | ||
| Enable = $true | ||
| TargetVersions = @('5.1', '7.0') | ||
| } | ||
| PSPlaceOpenBrace = @{ | ||
| Enable = $true | ||
| OnSameLine = $true | ||
| NewLineAfter = $true | ||
| IgnoreOneLineBlock = $true | ||
| } | ||
| PSUseConsistentIndentation = @{ | ||
| Enable = $true | ||
| Kind = 'space' | ||
| IndentationSize = 4 | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a signing certificate is configured, this only finds loose script files under
out; the actualpc-tools-<version>.zipandPCTools-<version>.zipwere already compressed by the build and are never unpacked or signed. Consequently, users of the primary archive still receive unsignedpc-tools.ps1,.psm1, and.psd1files despite the signing-enabled release path. Sign the staging tree before compression, or repackage the archives after signing.Useful? React with 👍 / 👎.