wraith/.gitea/workflows/build-release.yml
Vantz Stockwell 5910e7a849
Some checks failed
Build & Sign Wraith / Build Windows + Sign (push) Failing after 2m34s
fix: skip Tauri bundler, build NSIS installer manually
Tauri's bundled makensis can't run under SYSTEM account.
Use --no-bundle, then build installer with system NSIS
directly — same pattern as the old Go pipeline.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 00:47:16 -04:00

241 lines
9.4 KiB
YAML

# =============================================================================
# Wraith — Build & Sign Release (Tauri v2)
# =============================================================================
# Native Windows build on STORMBREAKER runner, signs with Azure Key Vault
# EV cert via jsign, creates NSIS installer, uploads to Gitea packages.
#
# Trigger: push a tag matching v* (e.g. v1.0.0) or run manually.
# =============================================================================
name: Build & Sign Wraith
on:
push:
tags:
- 'v*'
workflow_dispatch:
env:
# Extra paths needed when running as SYSTEM
EXTRA_PATH: C:\Program Files (x86)\NSIS;C:\Program Files\Eclipse Adoptium\jre-21.0.10.7-hotspot\bin;C:\Users\vantz\.cargo\bin;C:\Users\vantz\.rustup\toolchains\stable-x86_64-pc-windows-msvc\bin;C:\Program Files\nodejs
jobs:
build-and-sign:
name: Build Windows + Sign
runs-on: windows
steps:
- name: Checkout code
shell: powershell
run: |
git clone --depth 1 --branch ${{ github.ref_name }} https://${{ secrets.GIT_TOKEN }}@git.command.vigilcyber.com/vstockwell/wraith.git .
- name: Get version from tag
id: version
shell: powershell
run: |
$tag = "${{ github.ref_name }}" -replace '^v',''
echo "version=$tag" >> $env:GITHUB_OUTPUT
Write-Host "Building version: $tag"
- name: Configure Rust
shell: powershell
run: |
$env:Path = "$env:EXTRA_PATH;$env:Path"
$ErrorActionPreference = "Continue"
rustup default stable
$ErrorActionPreference = "Stop"
- name: Verify toolchain
shell: powershell
run: |
$env:Path = "$env:EXTRA_PATH;$env:Path"
Write-Host "=== Toolchain versions ==="
node --version
rustc --version
cargo --version
java --version
- name: Install frontend dependencies
shell: powershell
run: |
$env:Path = "$env:EXTRA_PATH;$env:Path"
npm ci
- name: Build frontend
shell: powershell
run: |
$env:Path = "$env:EXTRA_PATH;$env:Path"
npm run build
- name: Install Tauri CLI
shell: powershell
run: |
$env:Path = "$env:EXTRA_PATH;$env:Path"
cargo install tauri-cli --version "^2"
- name: Build Tauri app
shell: powershell
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
run: |
$env:Path = "$env:EXTRA_PATH;$env:Path"
cargo tauri build --no-bundle
Write-Host "=== Build output ==="
Get-ChildItem src-tauri\target\release\Wraith.exe
- name: Build NSIS installer
shell: powershell
run: |
$env:Path = "$env:EXTRA_PATH;$env:Path"
$version = "${{ steps.version.outputs.version }}"
# Stage files
New-Item -ItemType Directory -Force -Path dist-pkg | Out-Null
Copy-Item src-tauri\target\release\Wraith.exe dist-pkg\
Copy-Item src-tauri\icons\icon.ico dist-pkg\wraith.ico -ErrorAction SilentlyContinue
# Write NSIS script
@"
!include "MUI2.nsh"
Name "Wraith"
OutFile "Wraith_${version}_x64-setup.exe"
InstallDir "`$PROGRAMFILES64\Wraith"
RequestExecutionLevel admin
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"
Section "Install"
SetOutPath "`$INSTDIR"
File "Wraith.exe"
File "wraith.ico"
CreateDirectory "`$SMPROGRAMS\Wraith"
CreateShortcut "`$SMPROGRAMS\Wraith\Wraith.lnk" "`$INSTDIR\Wraith.exe" "" "`$INSTDIR\wraith.ico"
CreateShortcut "`$DESKTOP\Wraith.lnk" "`$INSTDIR\Wraith.exe" "" "`$INSTDIR\wraith.ico"
WriteUninstaller "`$INSTDIR\uninstall.exe"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Wraith" "DisplayName" "Wraith"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Wraith" "UninstallString" "`$INSTDIR\uninstall.exe"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Wraith" "DisplayVersion" "${version}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Wraith" "Publisher" "Vigilance Cyber"
SectionEnd
Section "Uninstall"
Delete "`$INSTDIR\Wraith.exe"
Delete "`$INSTDIR\wraith.ico"
Delete "`$INSTDIR\uninstall.exe"
RMDir "`$INSTDIR"
Delete "`$SMPROGRAMS\Wraith\Wraith.lnk"
RMDir "`$SMPROGRAMS\Wraith"
Delete "`$DESKTOP\Wraith.lnk"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Wraith"
SectionEnd
"@ | Out-File -FilePath dist-pkg\installer.nsi -Encoding ascii
# Build installer
Push-Location dist-pkg
makensis installer.nsi
Pop-Location
Move-Item "dist-pkg\Wraith_${version}_x64-setup.exe" .
Write-Host "=== Installer built ==="
Get-ChildItem "Wraith_${version}_x64-setup.exe"
- name: Download jsign
shell: powershell
run: |
Invoke-WebRequest -Uri "https://github.com/ebourg/jsign/releases/download/7.0/jsign-7.0.jar" -OutFile jsign.jar
- name: Get Azure Key Vault access token
id: azure-token
shell: powershell
run: |
$body = @{
client_id = "${{ secrets.AZURE_CLIENT_ID }}"
client_secret = "${{ secrets.AZURE_CLIENT_SECRET }}"
scope = "https://vault.azure.net/.default"
grant_type = "client_credentials"
}
$resp = Invoke-RestMethod -Uri "https://login.microsoftonline.com/${{ secrets.AZURE_TENANT_ID }}/oauth2/v2.0/token" -Method POST -Body $body
$token = $resp.access_token
echo "::add-mask::$token"
echo "token=$token" >> $env:GITHUB_OUTPUT
- name: Sign Windows binaries
shell: powershell
run: |
$env:Path = "$env:EXTRA_PATH;$env:Path"
$version = "${{ steps.version.outputs.version }}"
Write-Host "=== Signing Wraith binaries ==="
$binaries = @("src-tauri\target\release\Wraith.exe", "Wraith_${version}_x64-setup.exe")
foreach ($path in $binaries) {
if (Test-Path $path) {
Write-Host "Signing: $path"
java -jar jsign.jar `
--storetype AZUREKEYVAULT `
--keystore "${{ secrets.AZURE_KEY_VAULT_URL }}" `
--storepass "${{ steps.azure-token.outputs.token }}" `
--alias "${{ secrets.AZURE_CERT_NAME }}" `
--tsaurl http://timestamp.digicert.com `
--tsmode RFC3161 `
$path
Write-Host "Signed: $path"
}
}
- name: Create version.json
shell: powershell
run: |
$version = "${{ steps.version.outputs.version }}"
$installer = Get-Item "Wraith_${version}_x64-setup.exe"
$hash = (Get-FileHash $installer.FullName -Algorithm SHA256).Hash.ToLower()
$json = @{
version = $version
filename = $installer.Name
sha256 = $hash
platform = "windows"
architecture = "amd64"
released = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ")
signed = $true
} | ConvertTo-Json
$json | Out-File -FilePath version.json -Encoding utf8
Write-Host "=== version.json ==="
Get-Content version.json
- name: Upload to Gitea packages
shell: powershell
run: |
$version = "${{ steps.version.outputs.version }}"
$giteaUrl = "https://git.command.vigilcyber.com"
$headers = @{ Authorization = "token ${{ secrets.GIT_TOKEN }}" }
Write-Host "=== Uploading Wraith v$version ==="
$installer = "Wraith_${version}_x64-setup.exe"
Write-Host "Uploading: $installer"
Invoke-RestMethod -Uri "$giteaUrl/api/packages/vstockwell/generic/wraith/$version/$installer" `
-Method PUT -Headers $headers -ContentType "application/octet-stream" `
-InFile $installer
Write-Host "Uploading: version.json"
Invoke-RestMethod -Uri "$giteaUrl/api/packages/vstockwell/generic/wraith/$version/version.json" `
-Method PUT -Headers $headers -ContentType "application/octet-stream" `
-InFile version.json
Write-Host "=== Upload complete ==="
- name: Create Gitea Release
shell: powershell
run: |
$version = "${{ steps.version.outputs.version }}"
$headers = @{
Authorization = "token ${{ secrets.GIT_TOKEN }}"
"Content-Type" = "application/json"
}
$body = @{
tag_name = "v$version"
name = "Wraith v$version"
body = "Wraith Desktop v$version - Tauri v2 / Rust build."
} | ConvertTo-Json
Invoke-RestMethod -Uri "https://git.command.vigilcyber.com/api/v1/repos/vstockwell/wraith/releases" `
-Method POST -Headers $headers -Body $body
Write-Host "Release created."