Some checks failed
Build & Sign Wraith / Build Windows + Sign (push) Failing after 0s
Replaced Linux/MinGW cross-compilation with native MSVC build on Windows runner. PowerShell throughout. No more silent crash binaries. runs-on: windows targets the STORMBREAKER runner. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
221 lines
8.9 KiB
YAML
221 lines
8.9 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.
|
|
#
|
|
# Required secrets:
|
|
# AZURE_TENANT_ID — Azure AD tenant
|
|
# AZURE_CLIENT_ID — Service principal client ID
|
|
# AZURE_CLIENT_SECRET — Service principal secret
|
|
# AZURE_KEY_VAULT_URL — e.g. https://my-vault.vault.azure.net
|
|
# AZURE_CERT_NAME — Certificate/key name in the vault
|
|
# GIT_TOKEN — PAT for cloning private repo + uploading packages
|
|
# TAURI_SIGNING_PRIVATE_KEY — Tauri updater signing key (base64)
|
|
# TAURI_SIGNING_PRIVATE_KEY_PASSWORD — Password for the signing key
|
|
# =============================================================================
|
|
|
|
name: Build & Sign Wraith
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
build-and-sign:
|
|
name: Build Windows + Sign
|
|
runs-on: windows
|
|
steps:
|
|
# ---------------------------------------------------------------
|
|
# Checkout
|
|
# ---------------------------------------------------------------
|
|
- name: Checkout code
|
|
shell: pwsh
|
|
run: |
|
|
git clone --depth 1 --branch ${{ github.ref_name }} https://${{ secrets.GIT_TOKEN }}@git.command.vigilcyber.com/vstockwell/wraith.git .
|
|
|
|
# ---------------------------------------------------------------
|
|
# Extract version from tag
|
|
# ---------------------------------------------------------------
|
|
- name: Get version from tag
|
|
id: version
|
|
shell: pwsh
|
|
run: |
|
|
$tag = "${{ github.ref_name }}" -replace '^v',''
|
|
echo "version=$tag" >> $env:GITHUB_OUTPUT
|
|
Write-Host "Building version: $tag"
|
|
|
|
# ---------------------------------------------------------------
|
|
# Verify toolchain
|
|
# ---------------------------------------------------------------
|
|
- name: Verify toolchain
|
|
shell: pwsh
|
|
run: |
|
|
Write-Host "=== Toolchain versions ==="
|
|
node --version
|
|
rustc --version
|
|
cargo --version
|
|
java --version
|
|
python --version
|
|
|
|
# ---------------------------------------------------------------
|
|
# Build frontend
|
|
# ---------------------------------------------------------------
|
|
- name: Install frontend dependencies
|
|
shell: pwsh
|
|
run: npm ci
|
|
|
|
- name: Build frontend
|
|
shell: pwsh
|
|
run: |
|
|
npm run build
|
|
Write-Host "=== Frontend built ==="
|
|
Get-ChildItem dist\
|
|
|
|
# ---------------------------------------------------------------
|
|
# Build Tauri app (native MSVC)
|
|
# ---------------------------------------------------------------
|
|
- name: Install Tauri CLI
|
|
shell: pwsh
|
|
run: cargo install tauri-cli --version "^2"
|
|
|
|
- name: Build Tauri app
|
|
shell: pwsh
|
|
env:
|
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
|
run: |
|
|
cargo tauri build
|
|
Write-Host "=== Build output ==="
|
|
Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.exe
|
|
|
|
# ---------------------------------------------------------------
|
|
# Code signing — jsign + Azure Key Vault (EV cert)
|
|
# ---------------------------------------------------------------
|
|
- name: Download jsign
|
|
shell: pwsh
|
|
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: pwsh
|
|
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: pwsh
|
|
run: |
|
|
Write-Host "=== Signing Wraith binaries with EV certificate ==="
|
|
$installers = Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.exe
|
|
foreach ($binary in $installers) {
|
|
Write-Host "Signing: $($binary.FullName)"
|
|
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 `
|
|
$binary.FullName
|
|
Write-Host "Signed: $($binary.Name)"
|
|
}
|
|
|
|
# ---------------------------------------------------------------
|
|
# Create version.json
|
|
# ---------------------------------------------------------------
|
|
- name: Create version.json
|
|
shell: pwsh
|
|
run: |
|
|
$version = "${{ steps.version.outputs.version }}"
|
|
$installer = (Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.exe | Select-Object -First 1)
|
|
$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
|
|
|
|
# ---------------------------------------------------------------
|
|
# Upload to Gitea Package Registry
|
|
# ---------------------------------------------------------------
|
|
- name: Upload to Gitea packages
|
|
shell: pwsh
|
|
run: |
|
|
$version = "${{ steps.version.outputs.version }}"
|
|
$giteaUrl = "https://git.command.vigilcyber.com"
|
|
$owner = "vstockwell"
|
|
$package = "wraith"
|
|
$headers = @{ Authorization = "token ${{ secrets.GIT_TOKEN }}" }
|
|
|
|
Write-Host "=== Uploading Wraith v$version to Gitea packages ==="
|
|
|
|
# Upload installer(s)
|
|
$installers = Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.exe
|
|
foreach ($file in $installers) {
|
|
Write-Host "Uploading: $($file.Name)"
|
|
Invoke-RestMethod -Uri "$giteaUrl/api/packages/$owner/generic/$package/$version/$($file.Name)" `
|
|
-Method PUT -Headers $headers -ContentType "application/octet-stream" `
|
|
-InFile $file.FullName
|
|
}
|
|
|
|
# Upload version.json
|
|
Write-Host "Uploading: version.json"
|
|
Invoke-RestMethod -Uri "$giteaUrl/api/packages/$owner/generic/$package/$version/version.json" `
|
|
-Method PUT -Headers $headers -ContentType "application/octet-stream" `
|
|
-InFile version.json
|
|
|
|
# Upload updater signature if exists
|
|
$sigs = Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.sig -ErrorAction SilentlyContinue
|
|
foreach ($sig in $sigs) {
|
|
Write-Host "Uploading: $($sig.Name)"
|
|
Invoke-RestMethod -Uri "$giteaUrl/api/packages/$owner/generic/$package/$version/$($sig.Name)" `
|
|
-Method PUT -Headers $headers -ContentType "application/octet-stream" `
|
|
-InFile $sig.FullName
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "=== Upload complete ==="
|
|
|
|
# ---------------------------------------------------------------
|
|
# Create Gitea Release
|
|
# ---------------------------------------------------------------
|
|
- name: Create Gitea Release
|
|
shell: pwsh
|
|
run: |
|
|
$version = "${{ steps.version.outputs.version }}"
|
|
$giteaUrl = "https://git.command.vigilcyber.com"
|
|
$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 "$giteaUrl/api/v1/repos/vstockwell/wraith/releases" `
|
|
-Method POST -Headers $headers -Body $body
|
|
Write-Host "Release created."
|