From f4bbfd49ad17c4ffee4db7ffe8cc612610010b55 Mon Sep 17 00:00:00 2001 From: jwinterm Date: Sun, 13 Sep 2026 18:09:17 -0400 Subject: [PATCH] fix(ci): publish the signed Windows zips to the tag's release The Linux and macOS jobs already attach their tag-build output to the release, because this Gitea reports zero artifacts for every run through its REST API and its web download route answers "Not found." under every auth style. The Windows job was left out, so even a green signed build produced an exe nobody could fetch back. The step runs after the Authenticode, RFC 3161 timestamp and signer checks, so an unsigned or untimestamped binary can never reach a release. Both archives go up: the signed one users should download, and the unsigned one that stays byte-reproducible for verifiers. curl.exe rather than Invoke-WebRequest, because `shell: powershell` is Windows PowerShell 5.1 and its Invoke-WebRequest has no -Form for multipart uploads. Fail-safe like the others: no token, no resolvable release or a non-201 upload reports itself and exits 0 rather than reddening a build that produced a correctly signed binary. --- .gitea/workflows/build-windows.yml | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/.gitea/workflows/build-windows.yml b/.gitea/workflows/build-windows.yml index 03c3a3a7..a9df31db 100644 --- a/.gitea/workflows/build-windows.yml +++ b/.gitea/workflows/build-windows.yml @@ -270,3 +270,47 @@ jobs: wowlet-x86_64-windows.zip wowlet-x86_64-windows-unsigned.zip if-no-files-found: error + + - name: publish the Windows zips to the tag's release + # Same reason as the Linux and macOS jobs: artifacts upload fine, but + # this Gitea's REST listing reports zero for every run, so the signed exe + # cannot be fetched back through the API. Release assets can be. + # + # This runs after the Authenticode, timestamp and signer checks above, so + # an unsigned or untimestamped binary never reaches a release. curl.exe, + # not Invoke-WebRequest: `shell: powershell` is Windows PowerShell 5.1, + # whose Invoke-WebRequest has no -Form for multipart uploads. + # + # Fail-safe: a build that produced a correctly signed binary must not go + # red because publishing failed, so every bad path reports and exits 0. + if: startsWith(github.ref, 'refs/tags/') + shell: powershell + env: + RELEASE_TOKEN: ${{ github.token }} + run: | + $ErrorActionPreference = 'Continue' + if (-not $env:RELEASE_TOKEN) { + Write-Host "no token available to this runner, skipping the release upload" + exit 0 + } + $tag = $env:GITHUB_REF -replace '^refs/tags/', '' + $server = if ($env:GITHUB_SERVER_URL) { $env:GITHUB_SERVER_URL } else { 'https://git.such.software' } + $api = "$server/api/v1/repos/$env:GITHUB_REPOSITORY" + $auth = "Authorization: token $env:RELEASE_TOKEN" + $rid = '' + try { $rid = ((curl.exe -sS -H $auth "$api/releases/tags/$tag") | ConvertFrom-Json).id } catch { $rid = '' } + if (-not $rid) { + try { + $body = "{""tag_name"":""$tag"",""name"":""wowlet $tag""}" + $rid = ((curl.exe -sS -H $auth -H "Content-Type: application/json" -X POST -d $body "$api/releases") | ConvertFrom-Json).id + } catch { $rid = '' } + } + if (-not $rid) { + Write-Host "could not resolve or create a release for $tag, skipping the upload" + exit 0 + } + foreach ($f in @('wowlet-x86_64-windows.zip', 'wowlet-x86_64-windows-unsigned.zip')) { + if (-not (Test-Path $f)) { Write-Host "missing $f, nothing to publish for it"; continue } + $code = curl.exe -sS -o NUL -w '%{http_code}' -H $auth -F "attachment=@$f" "$api/releases/$rid/assets?name=$f" + Write-Host "release asset upload for $f returned HTTP $code" + }