From b9f2bd350cb5b51576902a1256f7559fdeb80984 Mon Sep 17 00:00:00 2001 From: TheAbider <51920546+TheAbider@users.noreply.github.com> Date: Tue, 8 Sep 2026 21:53:46 -0700 Subject: [PATCH 1/2] Chocolatey: tag-pinned PNG icon, distinct source URL, and a manual republish job Moderator feedback on rackstack 1.123.1: raw.githubusercontent.com icons are not accepted. The nuspec now points at the release's own tag on jsDelivr and uses the PNG icon (the guideline prefers png/svg over ico). projectSourceUrl now differs from projectUrl and docsUrl points at the wiki, clearing the two guideline notes from the same review. RackStack.psd1 IconUri moved to the same CDN for consistency. ci.yml gains a workflow_dispatch job that rebuilds and re-pushes the Chocolatey package for an EXISTING release from its published hash, so a nuspec fix can land on a version already in moderation without rebuilding the EXE or cutting a new version. The normal job is skipped on dispatch. Pack verified locally against the stamped 1.123.1 nuspec; 5514/5514 tests. --- .github/workflows/ci.yml | 77 +++++++++++++++++++++++++++++++- RackStack.psd1 | 2 +- dist/chocolatey/rackstack.nuspec | 6 +-- 3 files changed, 80 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a1accc..306115b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,16 @@ on: branches: [master] pull_request: branches: [master] + # Manual: rebuild and re-push the Chocolatey package for an EXISTING release, e.g. + # after a moderator asks for a nuspec change. Uses the published release's own + # hash, so the EXE is untouched and no new version (or antivirus resubmission) + # is needed. Chocolatey accepts a re-push of a version that is still in moderation. + workflow_dispatch: + inputs: + chocolatey_version: + description: 'Existing release version to republish to Chocolatey (e.g. 1.123.1)' + required: true + type: string # Top-level: read-only. Write privileges granted only on the test job that needs them. # Scorecard's Token-Permissions check awards full credit for this least-privilege pattern. @@ -11,6 +21,7 @@ permissions: read-all jobs: test: + if: github.event_name != 'workflow_dispatch' permissions: contents: write # needed for the auto-release step (gh release create) id-token: write # needed for actions/attest-* (SLSA L3 provenance + SBOM) @@ -549,7 +560,11 @@ jobs: $hash = (Get-FileHash -LiteralPath $exe -Algorithm SHA256).Hash.ToLower() Push-Location dist/chocolatey # Stamp the templated nuspec + install script with this version + hash. - (Get-Content 'rackstack.nuspec' -Raw) -replace '0\.0\.0', "$ver" | + # The icon URL is pinned to this release's tag (Chocolatey moderation does not + # accept raw.githubusercontent.com icons; a tag-pinned CDN URL is immutable). + (Get-Content 'rackstack.nuspec' -Raw) ` + -replace '0\.0\.0', "$ver" ` + -replace '@v0\.0\.0/', "@v$ver/" | Set-Content 'rackstack.nuspec' -Encoding utf8 (Get-Content 'tools/chocolateyinstall.ps1' -Raw) ` -replace '__VERSION__', $ver ` @@ -631,3 +646,63 @@ jobs: ) $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)." + + # ─────────────────────────────────────────────────────────────────────────── + # Manual republish of the Chocolatey package for an existing release + # (workflow_dispatch only). Rebuilds the .nupkg from the CURRENT dist/chocolatey + # templates and the published release's own EXE hash, then pushes it. The EXE + # is never rebuilt, so the release hash, cosign signature, and any antivirus + # clearance for that hash all stay valid. Chocolatey accepts a re-push of a + # version that is still in moderation, which is how a moderator's nuspec + # request gets answered without cutting a new version. + # ─────────────────────────────────────────────────────────────────────────── + republish-chocolatey: + if: github.event_name == 'workflow_dispatch' + permissions: + contents: read + runs-on: windows-2025 + timeout-minutes: 10 + defaults: + run: + shell: pwsh + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Republish Chocolatey package + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CHOCO_API_KEY: ${{ secrets.CHOCO_API_KEY }} + run: | + $ver = '${{ inputs.chocolatey_version }}' + if ($ver -notmatch '^\d+\.\d+\.\d+$') { throw "chocolatey_version '$ver' is not x.y.z" } + if ([string]::IsNullOrWhiteSpace($env:CHOCO_API_KEY)) { throw 'CHOCO_API_KEY secret is not set' } + + # The hash comes from the published release, never from a local build. + $work = Join-Path $env:RUNNER_TEMP 'release' + New-Item -ItemType Directory -Force $work | Out-Null + gh release download "v$ver" --pattern 'release-hashes.txt' --dir $work --clobber + if ($LASTEXITCODE -ne 0) { throw "release v$ver or its release-hashes.txt not found" } + $line = Get-Content (Join-Path $work 'release-hashes.txt') | Where-Object { $_ -match '^\s*([a-f0-9]{64})\s+RackStack\.exe\s*$' } | Select-Object -First 1 + if (-not $line) { throw 'RackStack.exe hash not present in release-hashes.txt' } + $hash = ([regex]::Match($line, '^\s*([a-f0-9]{64})')).Groups[1].Value + Write-Host "Release v$ver RackStack.exe SHA-256: $hash" + + Push-Location dist/chocolatey + (Get-Content 'rackstack.nuspec' -Raw) ` + -replace '0\.0\.0', "$ver" ` + -replace '@v0\.0\.0/', "@v$ver/" | + Set-Content 'rackstack.nuspec' -Encoding utf8 + (Get-Content 'tools/chocolateyinstall.ps1' -Raw) ` + -replace '__VERSION__', $ver ` + -replace '__CHECKSUM_SHA256__', $hash | + Set-Content 'tools/chocolateyinstall.ps1' -Encoding utf8 + Get-Content 'rackstack.nuspec' | Select-String 'version>|iconUrl|projectUrl|projectSourceUrl|docsUrl' | ForEach-Object { Write-Host " $($_.Line.Trim())" } + choco pack rackstack.nuspec + if ($LASTEXITCODE -ne 0) { throw "choco pack exited $LASTEXITCODE" } + $nupkg = Get-ChildItem -Filter "rackstack.$ver.nupkg" | Select-Object -First 1 + if (-not $nupkg) { throw 'choco pack produced no .nupkg for this version' } + choco apikey --key $env:CHOCO_API_KEY --source https://push.chocolatey.org/ + choco push $nupkg.FullName --source https://push.chocolatey.org/ + if ($LASTEXITCODE -ne 0) { throw "choco push exited $LASTEXITCODE" } + Pop-Location + Write-Host "Republished rackstack $ver to Chocolatey." diff --git a/RackStack.psd1 b/RackStack.psd1 index 8ef7643..88d627c 100644 --- a/RackStack.psd1 +++ b/RackStack.psd1 @@ -29,7 +29,7 @@ Tags = @('RackStack', 'Windows', 'WindowsServer', 'HyperV', 'Sysadmin', 'CLI', 'Automation', 'ServerConfig') LicenseUri = 'https://github.com/TheAbider/RackStack/blob/master/LICENSE' ProjectUri = 'https://github.com/TheAbider/RackStack' - IconUri = 'https://raw.githubusercontent.com/TheAbider/RackStack/master/.github/assets/icon.png' + IconUri = 'https://cdn.jsdelivr.net/gh/TheAbider/RackStack@master/.github/assets/icon.png' ReleaseNotes = 'See https://github.com/TheAbider/RackStack/releases for per-version changelog.' } } diff --git a/dist/chocolatey/rackstack.nuspec b/dist/chocolatey/rackstack.nuspec index 3550c02..4c8e149 100644 --- a/dist/chocolatey/rackstack.nuspec +++ b/dist/chocolatey/rackstack.nuspec @@ -8,12 +8,12 @@ RackStack — Windows Server configuration toolkit TheAbider https://github.com/TheAbider/RackStack - https://raw.githubusercontent.com/TheAbider/RackStack/master/RackStack.ico + https://cdn.jsdelivr.net/gh/TheAbider/RackStack@v0.0.0/.github/assets/icon.png Copyright (c) 2026 TheAbider https://github.com/TheAbider/RackStack/blob/master/LICENSE false - https://github.com/TheAbider/RackStack - https://github.com/TheAbider/RackStack#readme + https://github.com/TheAbider/RackStack/tree/master + https://github.com/TheAbider/RackStack/wiki https://github.com/TheAbider/RackStack/issues windows-server hyper-v iscsi clustering powershell sysadmin automation msp admin-tools PowerShell automation toolkit for configuring Windows Server hosts From 74156f541adac9c8cbce0240a37b23c60e219f68 Mon Sep 17 00:00:00 2001 From: TheAbider <51920546+TheAbider@users.noreply.github.com> Date: Tue, 8 Sep 2026 21:53:58 -0700 Subject: [PATCH 2/2] Sync the structural-tests badge (5514) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 269812c..345f7d9 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ OpenSSF Best Practices codecov PSScriptAnalyzer 0 errors - 5495 structural tests + 5514 structural tests Pester 312 tests SLSA Level 3