diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3b2d9ed..188b8e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -579,3 +579,43 @@ jobs: # storage quota, so there is no storage argument for deleting them. If disk hygiene # ever matters, prune Actions *artifacts* — never releases that a published package # points at. Run-Tests section 206 asserts this workflow contains no release deletion. + + # ───────────────────────────────────────────────────────────────────────── + # Antivirus false-positive submission reminder. + # + # Microsoft clears false positives PER HASH. A clearance covers exactly the + # binary it was granted for, so every release starts over with the + # machine-learning models regardless of how small the change was. v1.122.4 + # was cleared on 2026-08-12 ("the detection has been removed") — that + # clearance does nothing for the next build. + # + # This writes the new hash and the submission link into the run summary so + # the obligation shows up exactly where the release is already being + # validated, rather than depending on someone remembering. + # ───────────────────────────────────────────────────────────────────────── + - name: Remind — submit this build to Microsoft + if: steps.vercheck.outputs.bumped == 'true' && steps.releasecheck.outputs.exists == 'false' + shell: pwsh + run: | + $ver = '${{ steps.vercheck.outputs.version }}' + $sha = (Get-FileHash 'builds\RackStack.exe' -Algorithm SHA256).Hash.ToLower() + $lines = @( + "## Submit v$ver to Microsoft" + "" + "False-positive clearances are **per hash**, so this build is not covered by any" + "previous determination. Submit it, including for patch releases." + "" + "| | |" + "|---|---|" + "| Version | ``$ver`` |" + "| SHA-256 | ``$sha`` |" + "" + "1. https://www.microsoft.com/en-us/wdsi/filesubmission -> **Software developer**" + "2. Priority **Medium** — the default is Low, which states it *may never be processed by an analyst*" + "3. Upload the release asset verified against ``release-hashes.txt``, never a local ``builds/`` copy" + "4. Cite the prior clearance to speed review: submission ``665636df-07e9-4437-9f44-adb3030413ef``" + "" + "Typical turnaround: about two days." + ) + $lines -join "`n" | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8 + Write-Host "Submission reminder written to the run summary (SHA-256 $sha)." diff --git a/README.md b/README.md index bed2376..680db49 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ OpenSSF Best Practices codecov PSScriptAnalyzer 0 errors - 5485 structural tests + 5493 structural tests Pester 312 tests SLSA Level 3

diff --git a/Tests/Run-Tests.ps1 b/Tests/Run-Tests.ps1 index 8f1968a..ff9c59a 100644 --- a/Tests/Run-Tests.ps1 +++ b/Tests/Run-Tests.ps1 @@ -10774,7 +10774,13 @@ Write-SectionHeader "SECTION 209: BUILD METADATA INTEGRITY" try { $ciPath209 = Join-Path $script:ModuleRoot '.github\workflows\ci.yml' if (Test-Path -LiteralPath $ciPath209) { - $ci209 = Get-Content -LiteralPath $ciPath209 -Raw + # -Encoding UTF8 is load-bearing. ci.yml has no BOM, and Windows PowerShell + # 5.1 decodes BOM-less files as ANSI, so its em-dashes and box-drawing + # characters arrive as mojibake while pwsh 7 reads them correctly. The suite + # is run BOTH ways — directly under pwsh, and under powershell.exe by + # local/Validate-Release.ps1 — so without this, assertions that touch any + # non-ASCII text in this file pass in one host and fail in the other. + $ci209 = Get-Content -LiteralPath $ciPath209 -Raw -Encoding UTF8 # Compiler must be pinned to an exact version, never floating. Write-TestResult "Build: ps2exe is pinned to an explicit version" ` @@ -10804,6 +10810,31 @@ try { Write-TestResult "Build: EXE CompanyName matches RackStack.psd1 ('$psdCompany209')" ` ($psdCompany209 -and $exeCompany209 -and $psdCompany209 -eq $exeCompany209) ` "psd1='$psdCompany209' exe='$exeCompany209'" + + # Antivirus FP clearances are granted per hash, so every release — patches + # included — has to be resubmitted. Depending on memory for that failed + # once already; the release job prints the obligation, with the new hash, + # into the run summary that gets read while validating the release. + # Anchor on ASCII only. The step name contains an em-dash; matching it would + # re-introduce the host-dependent decoding problem above even with -Encoding + # set, and 'name: Remind' is already unique in this workflow. + $reminder209 = [regex]::Match($ci209, '(?s)- name: Remind.*?(?=\r?\n\s{6}- name:|\r?\n\s{0,4}\S|\z)') + Write-TestResult "Build: release job carries the Microsoft submission reminder" ` + $reminder209.Success "no reminder step found in ci.yml release job" + $rBody209 = $reminder209.Value + Write-TestResult "Build: reminder links the WDSI submission portal" ` + ($reminder209.Success -and $rBody209 -match 'wdsi/filesubmission') + # Single-quoted so the backslash in builds\RackStack.exe stays literal — the + # first cut of this used a double-quoted pattern whose over-escaped \\\\ + # required two backslashes and never matched the one that is actually there. + Write-TestResult "Build: reminder publishes the new SHA-256" ` + ($reminder209.Success -and $rBody209 -match 'Get-FileHash' -and ` + $rBody209 -match 'SHA256' -and $rBody209 -match 'RackStack\.exe') + Write-TestResult "Build: reminder writes to the run summary" ` + ($reminder209.Success -and $rBody209 -match 'GITHUB_STEP_SUMMARY') + # Only meaningful on an actual release — must carry the same gate as the build steps. + Write-TestResult "Build: reminder is gated on a version bump" ` + ($reminder209.Success -and $rBody209 -match "steps\.vercheck\.outputs\.bumped == 'true'") } else { Write-TestResult "Build: metadata integrity" -Skipped -Message "no .github/workflows in this layout" diff --git a/dist/winget/1.122.4/TheAbider.RackStack.installer.yaml b/dist/winget/1.122.4/TheAbider.RackStack.installer.yaml new file mode 100644 index 0000000..278d415 --- /dev/null +++ b/dist/winget/1.122.4/TheAbider.RackStack.installer.yaml @@ -0,0 +1,16 @@ +# yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.6.0.schema.json +PackageIdentifier: TheAbider.RackStack +PackageVersion: 1.122.4 +Platform: + - Windows.Desktop +MinimumOSVersion: 6.1.0.0 +InstallerType: portable +Commands: + - rackstack +ReleaseDate: 2026-08-10 +Installers: + - Architecture: x64 + InstallerUrl: https://github.com/TheAbider/RackStack/releases/download/v1.122.4/RackStack.exe + InstallerSha256: 658EDCC53D5139CE0A0F4DF167FA3F3CB293111DFF851BE300D8E4B788323034 +ManifestType: installer +ManifestVersion: 1.6.0 diff --git a/dist/winget/1.122.4/TheAbider.RackStack.locale.en-US.yaml b/dist/winget/1.122.4/TheAbider.RackStack.locale.en-US.yaml new file mode 100644 index 0000000..cbd37d5 --- /dev/null +++ b/dist/winget/1.122.4/TheAbider.RackStack.locale.en-US.yaml @@ -0,0 +1,33 @@ +# yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.6.0.schema.json +PackageIdentifier: TheAbider.RackStack +PackageVersion: 1.122.4 +PackageLocale: en-US +Publisher: TheAbider +PublisherUrl: https://github.com/TheAbider +PublisherSupportUrl: https://github.com/TheAbider/RackStack/issues +PackageName: RackStack +PackageUrl: https://github.com/TheAbider/RackStack +License: MIT +LicenseUrl: https://github.com/TheAbider/RackStack/blob/master/LICENSE +Copyright: Copyright (c) 2026 TheAbider +ShortDescription: PowerShell automation toolkit for configuring Windows Server hosts. +Description: |- + RackStack is a menu-driven PowerShell tool that automates everything between + "Windows is installed" and "server is in production." It provides 201 CLI + actions and 60+ interactive menus covering networking, Hyper-V, SAN/iSCSI, + clustering, VM deployment, cloud onboarding, and batch automation, all with + undo, transaction rollback, and audit logging. Built for MSPs, sysadmins, + and infrastructure teams who build Windows Servers repeatedly. +Moniker: rackstack +Tags: + - windows-server + - hyper-v + - iscsi + - clustering + - powershell + - sysadmin + - automation + - msp +ReleaseNotesUrl: https://github.com/TheAbider/RackStack/releases/tag/v1.122.4 +ManifestType: defaultLocale +ManifestVersion: 1.6.0 diff --git a/dist/winget/1.122.4/TheAbider.RackStack.yaml b/dist/winget/1.122.4/TheAbider.RackStack.yaml new file mode 100644 index 0000000..bd0ff0e --- /dev/null +++ b/dist/winget/1.122.4/TheAbider.RackStack.yaml @@ -0,0 +1,6 @@ +# yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.6.0.schema.json +PackageIdentifier: TheAbider.RackStack +PackageVersion: 1.122.4 +DefaultLocale: en-US +ManifestType: version +ManifestVersion: 1.6.0