diff --git a/.gitea/workflows/build-release.yml b/.gitea/workflows/build-release.yml index 476d8af..942a4a1 100644 --- a/.gitea/workflows/build-release.yml +++ b/.gitea/workflows/build-release.yml @@ -1,12 +1,6 @@ # ============================================================================= # 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: @@ -16,7 +10,6 @@ on: 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: @@ -29,14 +22,6 @@ jobs: 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: | @@ -49,22 +34,16 @@ jobs: 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 + - name: Install dependencies and build frontend 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 @@ -75,76 +54,75 @@ jobs: - 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" - $ver = "${{ steps.version.outputs.version }}" - $outName = "Wraith_${ver}_x64-setup.exe" + $ver = ("${{ github.ref_name }}" -replace '^v','') + $outExe = "Wraith_" + $ver + "_x64-setup.exe" + $workDir = (Get-Location).Path - # 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 + New-Item -ItemType Directory -Force -Path "$workDir\dist-pkg" | Out-Null + Copy-Item "$workDir\src-tauri\target\release\Wraith.exe" "$workDir\dist-pkg\" + Copy-Item "$workDir\src-tauri\icons\icon.ico" "$workDir\dist-pkg\wraith.ico" -ErrorAction SilentlyContinue - # Write NSIS script — use single-quoted here-string to avoid PS interpolation - $nsi = @' - !include "MUI2.nsh" - Name "Wraith" - OutFile "OUTFILE_PLACEHOLDER" - 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" "VER_PLACEHOLDER" - 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 - '@ - $nsi = $nsi.Replace("OUTFILE_PLACEHOLDER", $outName).Replace("VER_PLACEHOLDER", $ver) - $nsi | Out-File -FilePath dist-pkg\installer.nsi -Encoding ascii + $nsiContent = @' +!include "MUI2.nsh" +Name "Wraith" +OutFile "OUTFILE_PLACEHOLDER" +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" "VER_PLACEHOLDER" + 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 +'@ + $nsiContent = $nsiContent.Replace("OUTFILE_PLACEHOLDER", $outExe).Replace("VER_PLACEHOLDER", $ver) + [System.IO.File]::WriteAllText("$workDir\dist-pkg\installer.nsi", $nsiContent) - # Build installer - makensis dist-pkg\installer.nsi - Move-Item "dist-pkg\$outName" . + Write-Host "=== NSIS script written ===" + Write-Host "Working dir: $workDir" + Write-Host "OutFile: $outExe" + Get-ChildItem "$workDir\dist-pkg\" + + & makensis "$workDir\dist-pkg\installer.nsi" + Move-Item "$workDir\dist-pkg\$outExe" "$workDir\" Write-Host "=== Installer built ===" - Get-ChildItem $outName + Get-ChildItem "$workDir\$outExe" - 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 + - name: Get Azure token id: azure-token shell: powershell run: | @@ -157,86 +135,49 @@ jobs: $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 + [System.IO.File]::WriteAllText("$env:TEMP\aztoken.txt", $token) - - name: Sign Windows binaries + - name: Sign binaries shell: powershell run: | $env:Path = "$env:EXTRA_PATH;$env:Path" - $ver = "${{ steps.version.outputs.version }}" - Write-Host "=== Signing Wraith binaries ===" - $binaries = @("src-tauri\target\release\Wraith.exe", "Wraith_${ver}_x64-setup.exe") + $ver = ("${{ github.ref_name }}" -replace '^v','') + $token = [System.IO.File]::ReadAllText("$env:TEMP\aztoken.txt") + $binaries = @("src-tauri\target\release\Wraith.exe", "Wraith_" + $ver + "_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" + 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 $path + Write-Host "Signed." } } + Remove-Item "$env:TEMP\aztoken.txt" -ErrorAction SilentlyContinue - - name: Create version.json + - name: Upload to Gitea shell: powershell run: | - $version = "${{ steps.version.outputs.version }}" - $installer = Get-Item "Wraith_${version}_x64-setup.exe" - Write-Host "Installer: $($installer.FullName)" - $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 }}" + $ver = ("${{ github.ref_name }}" -replace '^v','') + $installer = "Wraith_" + $ver + "_x64-setup.exe" $giteaUrl = "https://git.command.vigilcyber.com" $headers = @{ Authorization = "token ${{ secrets.GIT_TOKEN }}" } - Write-Host "=== Uploading Wraith v$version ===" + # Version JSON + $hash = (Get-FileHash $installer -Algorithm SHA256).Hash.ToLower() + @{ version = $ver; filename = $installer; 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 - $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 $installer" + Invoke-RestMethod -Uri "$giteaUrl/api/packages/vstockwell/generic/wraith/$ver/$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 "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 Write-Host "=== Upload complete ===" - - name: Create Gitea Release + - name: Create 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." + $ver = ("${{ github.ref_name }}" -replace '^v','') + $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 + Invoke-RestMethod -Uri "https://git.command.vigilcyber.com/api/v1/repos/vstockwell/wraith/releases" -Method POST -Headers $headers -Body $body + Write-Host "Release v$ver created."