Skip to content

Legacy Chocolatey publisher (disabled) #5

Legacy Chocolatey publisher (disabled)

Legacy Chocolatey publisher (disabled) #5

name: Legacy Chocolatey publisher (disabled)
on:
workflow_dispatch:
inputs:
ref:
description: Published RMUX tag, for example v0.9.0
required: true
type: string
permissions:
contents: read
concurrency:
group: rmux-chocolatey-${{ inputs.ref }}
cancel-in-progress: false
jobs:
publish:
name: Validate and publish Chocolatey package
if: inputs.ref == 'v0.9.1'
runs-on: windows-latest
timeout-minutes: 45
environment: release
env:
RELEASE_REF: ${{ inputs.ref }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
ref: ${{ env.RELEASE_REF }}
persist-credentials: false
- name: Verify signed tag and public release identity
id: identity
shell: pwsh
env:
GH_TOKEN: ${{ github.token }}
run: |
$ErrorActionPreference = "Stop"
$tag = $env:RELEASE_REF
if ($tag -notmatch '^v(?<version>[0-9]+\.[0-9]+\.[0-9]+)$') {
throw "ref must be a stable RMUX tag such as v0.9.0"
}
$version = $Matches.version
$actualSha = (& git rev-parse HEAD).Trim()
$tagRef = gh api "repos/${{ github.repository }}/git/ref/tags/$tag" | ConvertFrom-Json
if ($tagRef.object.type -ne "tag") {
throw "release tag must be annotated and signed"
}
$tagObject = gh api "repos/${{ github.repository }}/git/tags/$($tagRef.object.sha)" | ConvertFrom-Json
if (-not $tagObject.verification.verified) {
throw "release tag signature is not verified by GitHub"
}
if ($tagObject.object.type -ne "commit" -or $tagObject.object.sha -ne $actualSha) {
throw "signed tag target does not match checked-out source"
}
$release = gh api "repos/${{ github.repository }}/releases/tags/$tag" | ConvertFrom-Json
if ($release.draft -or $release.target_commitish -ne $actualSha) {
throw "public release target does not match the signed tag"
}
$manifest = Get-Content -LiteralPath Cargo.toml -Raw
$workspaceVersion = [regex]::Match(
$manifest,
'(?ms)^\[workspace\.package\]\s*.*?^version\s*=\s*"(?<version>[^"]+)"\s*$'
).Groups['version'].Value
if ($workspaceVersion -ne $version) {
throw "workspace version $workspaceVersion does not match $tag"
}
"version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
"source_sha=$actualSha" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
- name: Download canonical release inputs
shell: pwsh
env:
GH_TOKEN: ${{ github.token }}
run: |
$ErrorActionPreference = "Stop"
New-Item -ItemType Directory -Force -Path release-assets | Out-Null
gh release download $env:RELEASE_REF `
--repo "${{ github.repository }}" `
--pattern SHA256SUMS `
--pattern "rmux-${{ steps.identity.outputs.version }}-windows-x86_64.zip" `
--dir release-assets
- name: Verify canonical Windows archive checksum
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$version = "${{ steps.identity.outputs.version }}"
$archiveName = "rmux-$version-windows-x86_64.zip"
$archive = Join-Path release-assets $archiveName
$lines = @(
Get-Content -LiteralPath release-assets\SHA256SUMS |
Where-Object { $_ -match "^[0-9a-fA-F]{64}\s+\*?$([regex]::Escape($archiveName))$" }
)
if ($lines.Count -ne 1) {
throw "SHA256SUMS has no unique entry for $archiveName"
}
$line = $lines[0]
$expected = ($line -split '\s+')[0].ToLowerInvariant()
$actual = (Get-FileHash -Algorithm SHA256 -LiteralPath $archive).Hash.ToLowerInvariant()
if ($actual -ne $expected) {
throw "checksum mismatch for $archiveName"
}
- name: Generate and pack Chocolatey package
shell: bash
run: |
set -euo pipefail
version='${{ steps.identity.outputs.version }}'
scripts/generate-chocolatey-package.sh \
--version "$version" \
--checksums release-assets/SHA256SUMS \
--output-dir target/chocolatey/rmux
cd target/chocolatey/rmux
choco pack rmux.nuspec --output-directory .. --limit-output
- name: Verify exact receipt payload identity
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
python3 - <<'PY'
import json
import os
import urllib.request
def get(path):
request = urllib.request.Request(
f"https://api.github.com{path}",
headers={
"Accept": "application/vnd.github+json",
"Authorization": f"Bearer {os.environ['GH_TOKEN']}",
"User-Agent": "rmux-chocolatey-recovery/1",
"X-GitHub-Api-Version": "2022-11-28",
},
)
with urllib.request.urlopen(request, timeout=30) as response:
return json.load(response)
source = "fb827cd7adf206995bab274aeafc58ddd09ac5b5"
run = get("/repos/Helvesec/rmux/actions/runs/30112540725")
assert {
"id": run["id"],
"run_attempt": run["run_attempt"],
"workflow_id": run["workflow_id"],
"path": run["path"],
"event": run["event"],
"head_branch": run["head_branch"],
"head_sha": run["head_sha"],
"status": run["status"],
"conclusion": run["conclusion"],
} == {
"id": 30112540725,
"run_attempt": 1,
"workflow_id": 316435347,
"path": ".github/workflows/release-receipt.yml",
"event": "workflow_dispatch",
"head_branch": "v0.9.1",
"head_sha": source,
"status": "completed",
"conclusion": "failure",
}
artifact = get("/repos/Helvesec/rmux/actions/artifacts/8604206888")
assert artifact["id"] == 8604206888
assert artifact["name"] == (
"rmux-downstream-chocolatey-payload-"
f"{source}-359441935"
)
assert artifact["digest"] == (
"sha256:0fa0195e4139752fbbd2f68e2a015b4f50c759cb7e94bcb34385398c8661134d"
)
assert artifact["expired"] is False
assert artifact["workflow_run"]["id"] == 30112540725
assert artifact["workflow_run"]["head_sha"] == source
jobs = get(
"/repos/Helvesec/rmux/actions/runs/30112540725/jobs"
"?per_page=100&filter=latest"
)["jobs"]
producer = [
job
for job in jobs
if job["name"].endswith(
"Prepare exact downstream payloads / Materialize exact channel payloads"
)
]
assert len(producer) == 1 and producer[0]["conclusion"] == "success"
PY
- name: Download exact receipt payload
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
artifact-ids: 8604206888
merge-multiple: true
path: target/chocolatey/expected
github-token: ${{ github.token }}
repository: ${{ github.repository }}
run-id: 30112540725
- name: Select the exact receipt package
shell: pwsh
run: |
$generated = "target/chocolatey/rmux.0.9.1.nupkg"
$expected = "target/chocolatey/expected/rmux.0.9.1.nupkg"
Remove-Item -LiteralPath $generated -Force
Copy-Item -LiteralPath $expected -Destination $generated
$selectedHash = (Get-FileHash -Algorithm SHA256 -LiteralPath $generated).Hash
$expectedHash = (Get-FileHash -Algorithm SHA256 -LiteralPath $expected).Hash
if ($selectedHash -ne $expectedHash) { throw "Exact Chocolatey package copy failed" }
- name: Install and smoke-test package
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$version = "${{ steps.identity.outputs.version }}"
$packageRoot = (Resolve-Path target\chocolatey).Path
$package = Join-Path $packageRoot "rmux.$version.nupkg"
if (-not (Test-Path -LiteralPath $package)) {
throw "Chocolatey package was not generated: $package"
}
choco install rmux `
--source $packageRoot `
--version $version `
--yes `
--no-progress `
--force
$versionOutput = (& rmux -V).Trim()
if ($versionOutput -ne "rmux $version") {
throw "Unexpected rmux version from Chocolatey install: $versionOutput"
}
.\scripts\smoke-installed-rmux.ps1 `
-Rmux rmux `
-SkipDaemon `
-RequireDaemonCommand
choco uninstall rmux --yes --no-progress
"CHOCOLATEY_PACKAGE=$package" | Out-File -FilePath $env:GITHUB_ENV -Append
- name: Push package once
shell: pwsh
env:
CHOCOLATEY_API_KEY: ${{ secrets.CHOCOLATEY_API_KEY }}
run: |
$ErrorActionPreference = "Stop"
if ([string]::IsNullOrWhiteSpace($env:CHOCOLATEY_API_KEY)) {
throw "Missing required release environment secret: CHOCOLATEY_API_KEY"
}
$version = "${{ steps.identity.outputs.version }}"
$query = "https://community.chocolatey.org/api/v2/FindPackagesById()?id='rmux'"
$response = Invoke-WebRequest -Uri $query -Method Get
[xml]$feed = $response.Content
$namespaces = [System.Xml.XmlNamespaceManager]::new($feed.NameTable)
$namespaces.AddNamespace("atom", "http://www.w3.org/2005/Atom")
$namespaces.AddNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata")
$namespaces.AddNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices")
$existing = $feed.SelectSingleNode(
"//atom:entry/m:properties[d:Version='$version']/d:Version",
$namespaces
)
if ($existing) {
Write-Host "Chocolatey package rmux $version already exists; skipping push."
exit 0
}
choco push $env:CHOCOLATEY_PACKAGE `
--source "https://push.chocolatey.org/" `
--api-key $env:CHOCOLATEY_API_KEY `
--yes `
--no-progress