feat: migrate all artifacts to SeaweedFS — single source of truth
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>
This commit is contained in:
Vantz Stockwell 2026-03-26 15:52:10 -04:00
parent 5d472a6e53
commit 037c76384b
4 changed files with 38 additions and 65 deletions

View File

@ -115,54 +115,60 @@ jobs:
}
Remove-Item "$env:TEMP\aztoken.txt" -ErrorAction SilentlyContinue
- name: Upload to Gitea
- name: Upload all artifacts to SeaweedFS
shell: powershell
run: |
$ver = ("${{ github.ref_name }}" -replace '^v','')
$giteaUrl = "https://git.command.vigilcyber.com"
$headers = @{ Authorization = "token ${{ secrets.GIT_TOKEN }}" }
$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 "$giteaUrl/api/packages/vstockwell/generic/wraith/$ver/wraith-mcp-bridge.exe" -Method PUT -Headers $headers -ContentType "application/octet-stream" -InFile $bridge
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
}
$installers = Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.exe
foreach ($file in $installers) {
$hash = (Get-FileHash $file.FullName -Algorithm SHA256).Hash.ToLower()
@{ version = $ver; filename = $file.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
Write-Host "Uploading: $($file.Name)"
Invoke-RestMethod -Uri "$giteaUrl/api/packages/vstockwell/generic/wraith/$ver/$($file.Name)" -Method PUT -Headers $headers -ContentType "application/octet-stream" -InFile $file.FullName
Write-Host "Uploading: version.json"
Invoke-RestMethod -Uri "$giteaUrl/api/packages/vstockwell/generic/wraith/$ver/version.json" -Method PUT -Headers $headers -ContentType "application/octet-stream" -InFile version.json
# 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
}
Write-Host "=== Upload complete ==="
# 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','')
$giteaUrl = "https://git.command.vigilcyber.com"
$headers = @{ Authorization = "token ${{ secrets.GIT_TOKEN }}" }
$s3 = "https://files.command.vigilcyber.com/wraith"
# Find the .sig file produced by Tauri signing
$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 = "$giteaUrl/api/packages/vstockwell/generic/wraith/$ver/$($zipFile.Name)"
$downloadUrl = "$s3/$ver/$($zipFile.Name)"
# Upload the .nsis.zip to packages
Write-Host "Uploading: $($zipFile.Name)"
Invoke-RestMethod -Uri "$giteaUrl/api/packages/vstockwell/generic/wraith/$ver/$($zipFile.Name)" -Method PUT -Headers $headers -ContentType "application/octet-stream" -InFile $zipFile.FullName
# Build update.json
$updateJson = @{
version = "v$ver"
notes = "Wraith Desktop v$ver"
@ -179,44 +185,13 @@ jobs:
Write-Host "update.json content:"
Get-Content update.json
# Upload to latest/ so the updater endpoint always points to the newest
Invoke-RestMethod -Uri "$giteaUrl/api/packages/vstockwell/generic/wraith/latest/update.json" -Method PUT -Headers $headers -ContentType "application/octet-stream" -InFile update.json
# Also upload to versioned path
Invoke-RestMethod -Uri "$giteaUrl/api/packages/vstockwell/generic/wraith/$ver/update.json" -Method PUT -Headers $headers -ContentType "application/octet-stream" -InFile 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'
Write-Host 'Sig files found'
Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.sig
}
- name: Create Release and attach installers
shell: powershell
run: |
$ver = ("${{ github.ref_name }}" -replace '^v','')
$giteaUrl = "https://git.command.vigilcyber.com"
$headers = @{ Authorization = "token ${{ secrets.GIT_TOKEN }}"; "Content-Type" = "application/json" }
$body = @{ tag_name = "v$ver"; name = "Wraith v$ver"; body = "Wraith Desktop v$ver - Tauri v2 / Rust build." } | ConvertTo-Json
$release = Invoke-RestMethod -Uri "$giteaUrl/api/v1/repos/vstockwell/wraith/releases" -Method POST -Headers $headers -Body $body
$releaseId = $release.id
Write-Host "Release v$ver created (id: $releaseId)"
$uploadHeaders = @{ Authorization = "token ${{ secrets.GIT_TOKEN }}" }
# Attach installer(s)
$installers = Get-ChildItem -Recurse src-tauri\target\release\bundle\nsis\*.exe
foreach ($file in $installers) {
Write-Host "Attaching $($file.Name) to release..."
Invoke-RestMethod -Uri "$giteaUrl/api/v1/repos/vstockwell/wraith/releases/$releaseId/assets?name=$($file.Name)" -Method POST -Headers $uploadHeaders -ContentType "application/octet-stream" -InFile $file.FullName
Write-Host "Attached: $($file.Name)"
}
# Attach MCP bridge binary
$bridge = "src-tauri\target\release\wraith-mcp-bridge.exe"
if (Test-Path $bridge) {
Write-Host "Attaching wraith-mcp-bridge.exe to release..."
Invoke-RestMethod -Uri "$giteaUrl/api/v1/repos/vstockwell/wraith/releases/$releaseId/assets?name=wraith-mcp-bridge.exe" -Method POST -Headers $uploadHeaders -ContentType "application/octet-stream" -InFile $bridge
Write-Host "Attached: wraith-mcp-bridge.exe"
}

View File

@ -48,10 +48,8 @@ pub async fn check_for_updates(app_handle: tauri::AppHandle) -> Result<UpdateInf
.unwrap_or("")
.to_string();
let html_url = latest.get("html_url")
.and_then(|v| v.as_str())
.unwrap_or("https://git.command.vigilcyber.com/vstockwell/wraith/releases")
.to_string();
// Direct download from SeaweedFS
let html_url = format!("https://files.command.vigilcyber.com/wraith/{}/", tag);
let update_available = version_is_newer(&tag, &current);

View File

@ -40,7 +40,7 @@ pub async fn ensure_bridge(app_version: &str) -> Result<(), String> {
};
let url = format!(
"https://git.command.vigilcyber.com/api/packages/vstockwell/generic/wraith/{}/{}",
"https://files.command.vigilcyber.com/wraith/{}/{}",
app_version, binary_name
);

View File

@ -52,7 +52,7 @@
"updater": {
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDNCRkQ2OUY2OEY0Q0ZFQkYKUldTLy9reVA5bW45T3dUQ1R5OFNCenVhL2srTXlLcHR4cFNaeCtJSmJUSTZKSUNHVTRIbWZwanEK",
"endpoints": [
"https://git.command.vigilcyber.com/api/packages/vstockwell/generic/wraith/latest/update.json"
"https://files.command.vigilcyber.com/wraith/update.json"
]
}
}