All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 3m59s
All build artifacts now upload to files.command.vigilcyber.com/wraith/:
- Installer: /wraith/{ver}/Wraith_{ver}_x64-setup.exe + /wraith/latest/
- MCP bridge: /wraith/{ver}/wraith-mcp-bridge.exe + /wraith/latest/
- Update bundle: /wraith/{ver}/*.nsis.zip
- Update manifest: /wraith/update.json (Tauri updater endpoint)
- Version metadata: /wraith/{ver}/version.json + /wraith/latest/
Removed: Gitea package uploads, Gitea release creation/attachment.
Updated: tauri.conf.json updater endpoint, bridge auto-download URL,
manual update checker download URL.
CI is now: build -> sign -> upload to SeaweedFS. Done.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
198 lines
8.6 KiB
YAML
198 lines
8.6 KiB
YAML
# =============================================================================
|
|
# Wraith — Build & Sign Release (Tauri v2)
|
|
# =============================================================================
|
|
name: Build & Sign Wraith
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
workflow_dispatch:
|
|
|
|
env:
|
|
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: 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"
|
|
node --version
|
|
rustc --version
|
|
cargo --version
|
|
java --version
|
|
|
|
- name: Patch version from git tag
|
|
shell: powershell
|
|
run: |
|
|
$ver = ("${{ github.ref_name }}" -replace '^v','')
|
|
$conf = Get-Content src-tauri\tauri.conf.json -Raw
|
|
$conf = $conf -replace '"version":\s*"[^"]*"', "`"version`": `"$ver`""
|
|
[System.IO.File]::WriteAllText((Join-Path (Get-Location) "src-tauri\tauri.conf.json"), $conf)
|
|
Write-Host "Patched tauri.conf.json version to $ver"
|
|
|
|
- name: Install dependencies and build frontend
|
|
shell: powershell
|
|
run: |
|
|
$env:Path = "$env:EXTRA_PATH;$env:Path"
|
|
npm ci
|
|
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 (with update signing)
|
|
shell: powershell
|
|
run: |
|
|
$env:Path = "$env:EXTRA_PATH;$env:Path"
|
|
$env:TAURI_SIGNING_PRIVATE_KEY = "${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}"
|
|
$env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD = "${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}"
|
|
cargo tauri build
|
|
Write-Host "=== Build output ==="
|
|
Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*
|
|
|
|
- name: Build and package MCP bridge binary
|
|
shell: powershell
|
|
run: |
|
|
$env:Path = "$env:EXTRA_PATH;$env:Path"
|
|
cd src-tauri
|
|
cargo build --release --bin wraith-mcp-bridge
|
|
Write-Host "Bridge binary built:"
|
|
Get-ChildItem target\release\wraith-mcp-bridge.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 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"
|
|
[System.IO.File]::WriteAllText("$env:TEMP\aztoken.txt", $token)
|
|
|
|
- name: Sign binaries
|
|
shell: powershell
|
|
run: |
|
|
$env:Path = "$env:EXTRA_PATH;$env:Path"
|
|
$token = [System.IO.File]::ReadAllText("$env:TEMP\aztoken.txt")
|
|
# Sign NSIS installers + MCP bridge binary
|
|
$binaries = @()
|
|
$binaries += Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.exe
|
|
$binaries += Get-Item src-tauri\target\release\wraith-mcp-bridge.exe -ErrorAction SilentlyContinue
|
|
foreach ($binary in $binaries) {
|
|
Write-Host "Signing: $($binary.FullName)"
|
|
java -jar jsign.jar --storetype AZUREKEYVAULT --keystore "${{ secrets.AZURE_KEY_VAULT_URL }}" --storepass $token --alias "${{ secrets.AZURE_CERT_NAME }}" --tsaurl http://timestamp.digicert.com --tsmode RFC3161 $binary.FullName
|
|
Write-Host "Signed: $($binary.Name)"
|
|
}
|
|
Remove-Item "$env:TEMP\aztoken.txt" -ErrorAction SilentlyContinue
|
|
|
|
- name: Upload all artifacts to SeaweedFS
|
|
shell: powershell
|
|
run: |
|
|
$ver = ("${{ github.ref_name }}" -replace '^v','')
|
|
$s3 = "https://files.command.vigilcyber.com/wraith"
|
|
|
|
# Upload installer
|
|
$installers = Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.exe
|
|
foreach ($file in $installers) {
|
|
Write-Host "Uploading: $($file.Name)"
|
|
Invoke-RestMethod -Uri "$s3/$ver/$($file.Name)" -Method PUT -ContentType "application/octet-stream" -InFile $file.FullName
|
|
# Also upload as 'latest' for direct download links
|
|
Invoke-RestMethod -Uri "$s3/latest/$($file.Name)" -Method PUT -ContentType "application/octet-stream" -InFile $file.FullName
|
|
}
|
|
|
|
# Upload MCP bridge binary
|
|
$bridge = "src-tauri\target\release\wraith-mcp-bridge.exe"
|
|
if (Test-Path $bridge) {
|
|
Write-Host "Uploading: wraith-mcp-bridge.exe"
|
|
Invoke-RestMethod -Uri "$s3/$ver/wraith-mcp-bridge.exe" -Method PUT -ContentType "application/octet-stream" -InFile $bridge
|
|
Invoke-RestMethod -Uri "$s3/latest/wraith-mcp-bridge.exe" -Method PUT -ContentType "application/octet-stream" -InFile $bridge
|
|
}
|
|
|
|
# Upload .nsis.zip for Tauri auto-updater
|
|
$zipFile = Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.nsis.zip | Select-Object -First 1
|
|
if ($zipFile) {
|
|
Write-Host "Uploading: $($zipFile.Name)"
|
|
Invoke-RestMethod -Uri "$s3/$ver/$($zipFile.Name)" -Method PUT -ContentType "application/octet-stream" -InFile $zipFile.FullName
|
|
}
|
|
|
|
# Upload version.json metadata
|
|
$installer = $installers | Select-Object -First 1
|
|
if ($installer) {
|
|
$hash = (Get-FileHash $installer.FullName -Algorithm SHA256).Hash.ToLower()
|
|
@{ version = $ver; filename = $installer.Name; sha256 = $hash; platform = "windows"; architecture = "amd64"; released = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"); signed = $true } | ConvertTo-Json | Out-File version.json -Encoding utf8
|
|
Invoke-RestMethod -Uri "$s3/$ver/version.json" -Method PUT -ContentType "application/json" -InFile version.json
|
|
Invoke-RestMethod -Uri "$s3/latest/version.json" -Method PUT -ContentType "application/json" -InFile version.json
|
|
}
|
|
|
|
Write-Host "=== SeaweedFS upload complete ==="
|
|
|
|
- name: Generate and upload update.json for Tauri updater
|
|
shell: powershell
|
|
run: |
|
|
$ver = ("${{ github.ref_name }}" -replace '^v','')
|
|
$s3 = "https://files.command.vigilcyber.com/wraith"
|
|
|
|
$sigFile = Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.nsis.zip.sig | Select-Object -First 1
|
|
$zipFile = Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.nsis.zip | Select-Object -First 1
|
|
|
|
if ($sigFile -and $zipFile) {
|
|
$signature = Get-Content $sigFile.FullName -Raw
|
|
$downloadUrl = "$s3/$ver/$($zipFile.Name)"
|
|
|
|
$updateJson = @{
|
|
version = "v$ver"
|
|
notes = "Wraith Desktop v$ver"
|
|
pub_date = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ")
|
|
platforms = @{
|
|
"windows-x86_64" = @{
|
|
signature = $signature.Trim()
|
|
url = $downloadUrl
|
|
}
|
|
}
|
|
} | ConvertTo-Json -Depth 4
|
|
|
|
$updateJson | Out-File update.json -Encoding utf8
|
|
Write-Host "update.json content:"
|
|
Get-Content update.json
|
|
|
|
# Upload to root (Tauri updater endpoint)
|
|
Invoke-RestMethod -Uri "$s3/update.json" -Method PUT -ContentType "application/json" -InFile update.json
|
|
# Also versioned copy
|
|
Invoke-RestMethod -Uri "$s3/$ver/update.json" -Method PUT -ContentType "application/json" -InFile update.json
|
|
|
|
Write-Host "=== Update manifest uploaded ==="
|
|
} else {
|
|
Write-Host 'WARNING - No .sig file found, update signing may have failed'
|
|
}
|
|
|