Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,34 @@ jobs:
$wheel = @(Get-ChildItem "release-assets/*.whl")
$installers = @(Get-ChildItem "desktop/src-tauri/target/release/bundle/nsis/*.exe")
if ($wheel.Count -ne 1 -or $installers.Count -ne 1) { throw "expected one wheel and one NSIS installer" }
Copy-Item $installers[0].FullName release-assets/
$installerAsset = Join-Path release-assets "ArcheAxis.OS-Windows-x64-setup.exe"
Copy-Item $installers[0].FullName $installerAsset
Copy-Item .hermes/desktop-runtime-v1/runtime/release-identity.json release-assets/
python scripts/release_checksum.py --wheel $wheel[0].FullName --installer (Join-Path release-assets $installers[0].Name) --artifact release-assets/release-identity.json --output release-assets/SHA256SUMS.txt
python scripts/release_checksum.py --wheel $wheel[0].FullName --installer $installerAsset --artifact release-assets/release-identity.json --output release-assets/SHA256SUMS.txt
- name: Verify checksum manifest payload equality
shell: pwsh
run: |
$manifestNames = @(Get-Content release-assets/SHA256SUMS.txt | ForEach-Object {
if ($_ -notmatch '^[0-9a-fA-F]{64} (.+)$') { throw "invalid SHA256SUMS line: $_" }
$Matches[1]
})
$payloadNames = @(Get-ChildItem release-assets -File | Where-Object Name -ne 'SHA256SUMS.txt' | ForEach-Object Name)
$manifestComparison = Compare-Object ($manifestNames | Sort-Object) ($payloadNames | Sort-Object)
if ($manifestComparison) { throw "SHA256SUMS payload set differs from staged payload set: $($manifestComparison | Out-String)" }
if ($manifestNames.Count -ne 3 -or ($manifestNames | Select-Object -Unique).Count -ne 3) {
throw "expected exactly three unique checksum-bound payloads"
}
- name: Publish verified assets
env:
GH_TOKEN: ${{ github.token }}
shell: pwsh
run: gh release create $env:GITHUB_REF_NAME release-assets/* --verify-tag --title "ArcheAxis OS $env:GITHUB_REF_NAME" --generate-notes
run: |
$wheel = @(Get-ChildItem "release-assets/*.whl")
if ($wheel.Count -ne 1) { throw "expected exactly one release wheel" }
$releaseAssets = @(
$wheel[0].FullName,
(Resolve-Path "release-assets/ArcheAxis.OS-Windows-x64-setup.exe").Path,
(Resolve-Path "release-assets/release-identity.json").Path,
(Resolve-Path "release-assets/SHA256SUMS.txt").Path
)
gh release create $env:GITHUB_REF_NAME $releaseAssets --verify-tag --title "ArcheAxis OS $env:GITHUB_REF_NAME" --generate-notes
25 changes: 25 additions & 0 deletions tests/test_release_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,31 @@ def test_release_checksum_script_refuses_no_artifacts(tmp_path) -> None:
assert result.returncode != 0, "should have failed without artifact arguments"


def test_release_workflow_stages_installer_under_provider_stable_name() -> None:
"""The checksum filename must equal the name exposed by GitHub Releases."""
root = Path(__file__).resolve().parents[1]
workflow = (root / ".github" / "workflows" / "release.yml").read_text(
encoding="utf-8"
)

assert 'ArcheAxis.OS-Windows-x64-setup.exe' in workflow
assert 'Copy-Item $installers[0].FullName $installerAsset' in workflow
assert '--installer $installerAsset' in workflow


def test_release_workflow_publishes_only_checksum_bound_allowlist() -> None:
"""No wildcard or unlisted staging payload may reach a public release."""
root = Path(__file__).resolve().parents[1]
workflow = (root / ".github" / "workflows" / "release.yml").read_text(
encoding="utf-8"
)

assert 'gh release create $env:GITHUB_REF_NAME release-assets/*' not in workflow
assert 'Verify checksum manifest payload equality' in workflow
assert '$releaseAssets = @(' in workflow
assert 'gh release create $env:GITHUB_REF_NAME $releaseAssets' in workflow


def test_release_identity_injection_manifests_exact_commit_and_tree(tmp_path) -> None:
"""Verify scripts/release_inject_identity.py writes valid identity manifest."""
import json
Expand Down
Loading