projection: admit the native Windows release

The native Desktop payload now enters the same public candidate and receipt as the Linux and server artifacts.

Source-Sha: 550aff16577a07f888f3ca150749265726072048
Policy-Sha: 550aff16577a07f888f3ca150749265726072048
Tree-Digest: f18eb172754ead927788c5aca2f3ad78b37103a21b657eb1a3328eb07cef0c7c
This commit is contained in:
Fimeg 2026-09-10 12:57:20 -04:00
commit 71a324ac7c
3 changed files with 72 additions and 1 deletions

View file

@ -242,6 +242,49 @@ jobs:
path: server/internal/services/posture-build.json path: server/internal/services/posture-build.json
retention-days: 1 retention-days: 1
# Qt/MSVC Windows payloads are built on the commissioned native body. This
# lane has build authority only; stage_package folds its bytes into the same
# candidate that release-trusted later verifies and publishes.
windows_native:
runs-on: windows-build
needs: [gate]
defaults:
run:
shell: powershell
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Build complete native Windows Desktop payload
run: |
$ErrorActionPreference = 'Stop'
$version = $env:GITHUB_REF -replace '^refs/tags/v', ''
$payload = Join-Path $env:RUNNER_TEMP 'redflag-desktop-payload'
& ./installer/windows/build-desktop.ps1 -OutputDirectory $payload -Version $version
if ($LASTEXITCODE -ne 0) { throw 'Native Windows payload failed.' }
$out = Join-Path $env:RUNNER_TEMP 'release-windows-native'
New-Item -ItemType Directory -Path $out | Out-Null
$desktop = Join-Path $out 'redflag-desktop-windows-amd64.exe'
Copy-Item (Join-Path $payload 'redflag-desktop.exe') $desktop
$archive = Join-Path $out ("redflag-$version-windows-desktop-amd64.zip")
Compress-Archive -Path (Join-Path $payload '*') -DestinationPath $archive
$item = [ordered]@{
platform = 'desktop-windows'
architecture = 'amd64'
filename = [IO.Path]::GetFileName($desktop)
sha256 = (Get-FileHash $desktop -Algorithm SHA256).Hash.ToLowerInvariant()
size = (Get-Item $desktop).Length
}
$snippet = Join-Path $out 'release-windows-native.artifacts.json'
@($item) | ConvertTo-Json -Depth 4 | Set-Content $snippet -Encoding UTF8
"NATIVE_WINDOWS_OUTPUT=$out" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
- uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3
with:
name: release-windows-native
path: ${{ env.NATIVE_WINDOWS_OUTPUT }}
if-no-files-found: error
retention-days: 1
# Build binaries for every target platform. The webui-dist and supply-chain # Build binaries for every target platform. The webui-dist and supply-chain
# posture artifacts are downloaded into the embed paths before the server compile. # posture artifacts are downloaded into the embed paths before the server compile.
release: release:
@ -572,7 +615,7 @@ jobs:
runs-on: redflag-linux-build runs-on: redflag-linux-build
container: container:
image: debian:13-slim@sha256:d7e12182ce18b85b93007c1dedf31f2d29e01ccf3182cc4017c709b6259bc132 image: debian:13-slim@sha256:d7e12182ce18b85b93007c1dedf31f2d29e01ccf3182cc4017c709b6259bc132
needs: [release] needs: [release, windows_native]
outputs: outputs:
receipt_sha256: ${{ steps.assemble.outputs.receipt_sha256 }} receipt_sha256: ${{ steps.assemble.outputs.receipt_sha256 }}
steps: steps:
@ -587,6 +630,22 @@ jobs:
with: with:
path: artifacts path: artifacts
- name: Admit native Windows bytes to the Windows candidate
run: |
set -euo pipefail
native=artifacts/release-windows-native
target=artifacts/release-windows-amd64
test -s "$native/redflag-desktop-windows-amd64.exe"
test -s "$native/release-windows-native.artifacts.json"
cp "$native/redflag-desktop-windows-amd64.exe" "$target/"
cp "$native"/*.zip "$target/"
jq -s 'add' \
"$target/release-windows-amd64.artifacts.json" \
"$native/release-windows-native.artifacts.json" \
> "$target/release-windows-amd64.artifacts.json.tmp"
mv "$target/release-windows-amd64.artifacts.json.tmp" \
"$target/release-windows-amd64.artifacts.json"
- name: Assemble deterministic release candidate - name: Assemble deterministic release candidate
id: assemble id: assemble
run: | run: |

View file

@ -103,6 +103,12 @@ def verify(candidate, version, commit, tag):
"contract target mismatch: " + name) "contract target mismatch: " + name)
require(f"redflag_{version}_amd64.deb" in files, "missing Debian package") require(f"redflag_{version}_amd64.deb" in files, "missing Debian package")
require("RedFlagSetup-windows-amd64.msi" in files, "missing Windows installer") require("RedFlagSetup-windows-amd64.msi" in files, "missing Windows installer")
desktop = "redflag-desktop-windows-amd64.exe"
require(desktop in files, "missing native Windows Desktop: " + desktop)
require(files[desktop].get("platform") == "desktop-windows" and
files[desktop].get("architecture") == "amd64", "native Windows Desktop target mismatch")
require(f"redflag-{version}-windows-desktop-amd64.zip" in files,
"missing complete native Windows Desktop payload")
def assemble(args): def assemble(args):

View file

@ -45,6 +45,12 @@ class CandidateTests(unittest.TestCase):
(directory / "redflag_0.2.9.4_amd64.deb").write_bytes(b"synthetic deb") (directory / "redflag_0.2.9.4_amd64.deb").write_bytes(b"synthetic deb")
if target == "windows-amd64": if target == "windows-amd64":
(directory / "RedFlagSetup-windows-amd64.msi").write_bytes(b"synthetic msi") (directory / "RedFlagSetup-windows-amd64.msi").write_bytes(b"synthetic msi")
desktop = "redflag-desktop-windows-amd64.exe"
payload = b"synthetic native windows desktop"
(directory / desktop).write_bytes(payload)
snippets.append(dict(filename=desktop, platform="desktop-windows",
architecture="amd64", sha256=hashlib.sha256(payload).hexdigest(), size=len(payload)))
(directory / "redflag-0.2.9.4-windows-desktop-amd64.zip").write_bytes(b"synthetic desktop payload")
(directory / ("release-" + target + ".artifacts.json")).write_text(json.dumps(snippets)) (directory / ("release-" + target + ".artifacts.json")).write_text(json.dumps(snippets))
ADAPTER.assemble(SimpleNamespace(artifacts=str(self.source), candidate=str(self.candidate), ADAPTER.assemble(SimpleNamespace(artifacts=str(self.source), candidate=str(self.candidate),
commit=self.commit, version="0.2.9.4", tag="v0.2.9.4", run_id=os.environ.get("GITHUB_RUN_ID", "123"))) commit=self.commit, version="0.2.9.4", tag="v0.2.9.4", run_id=os.environ.get("GITHUB_RUN_ID", "123")))