This commit is contained in:
paisley
2026-03-26 17:39:46 +08:00
committed by GitHub
Unverified
parent bed62c64e8
commit 19a6d2dd34
2 changed files with 132 additions and 132 deletions

View File

@@ -83,147 +83,147 @@ jobs:
if: matrix.platform == 'win' if: matrix.platform == 'win'
run: pnpm run package:win run: pnpm run package:win
# # Detect release channel from tag to skip code signing for alpha/beta builds # Detect release channel from tag to skip code signing for alpha/beta builds
# - name: Detect Windows release channel - name: Detect Windows release channel
# if: matrix.platform == 'win' if: matrix.platform == 'win'
# id: win-channel id: win-channel
# shell: bash shell: bash
# run: | run: |
# if [[ "${{ github.ref }}" == refs/tags/v* ]]; then if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
# TAG="${GITHUB_REF#refs/tags/v}" TAG="${GITHUB_REF#refs/tags/v}"
# else else
# TAG="${{ github.event.inputs.version }}" TAG="${{ github.event.inputs.version }}"
# fi fi
# if [[ "$TAG" =~ (alpha|beta) ]]; then if [[ "$TAG" =~ (alpha|beta) ]]; then
# echo "is_stable=false" >> $GITHUB_OUTPUT echo "is_stable=false" >> $GITHUB_OUTPUT
# echo "Channel: prerelease ($TAG) — skipping code signing" echo "Channel: prerelease ($TAG) — skipping code signing"
# else else
# echo "is_stable=true" >> $GITHUB_OUTPUT echo "is_stable=true" >> $GITHUB_OUTPUT
# echo "Channel: stable ($TAG) — will sign" echo "Channel: stable ($TAG) — will sign"
# fi fi
# - name: Validate unsigned Windows artifacts before SignPath - name: Validate unsigned Windows artifacts before SignPath
# if: matrix.platform == 'win' && steps.win-channel.outputs.is_stable == 'true' if: matrix.platform == 'win' && steps.win-channel.outputs.is_stable == 'true'
# shell: pwsh shell: pwsh
# run: | run: |
# $unsignedExeFiles = Get-ChildItem -Path "release" -Filter *.exe -File $unsignedExeFiles = Get-ChildItem -Path "release" -Filter *.exe -File
# if (-not $unsignedExeFiles) { if (-not $unsignedExeFiles) {
# throw "No unsigned .exe files found in release/ before SignPath upload" throw "No unsigned .exe files found in release/ before SignPath upload"
# } }
# $unsignedCount = $unsignedExeFiles.Count $unsignedCount = $unsignedExeFiles.Count
# "UNSIGNED_EXE_COUNT=$unsignedCount" | Out-File -FilePath $env:GITHUB_ENV -Append "UNSIGNED_EXE_COUNT=$unsignedCount" | Out-File -FilePath $env:GITHUB_ENV -Append
# Write-Host "Found $unsignedCount unsigned .exe file(s):" Write-Host "Found $unsignedCount unsigned .exe file(s):"
# $unsignedExeFiles | ForEach-Object { Write-Host " - $($_.Name)" } $unsignedExeFiles | ForEach-Object { Write-Host " - $($_.Name)" }
# - name: Upload unsigned Windows artifacts for SignPath - name: Upload unsigned Windows artifacts for SignPath
# if: matrix.platform == 'win' && steps.win-channel.outputs.is_stable == 'true' if: matrix.platform == 'win' && steps.win-channel.outputs.is_stable == 'true'
# id: upload-unsigned-windows-artifact id: upload-unsigned-windows-artifact
# uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
# with: with:
# name: unsigned-win-exe-${{ github.run_id }}-${{ github.run_attempt }} name: unsigned-win-exe-${{ github.run_id }}-${{ github.run_attempt }}
# path: release/*.exe path: release/*.exe
# retention-days: 1 retention-days: 1
# - name: Sign Windows artifacts via SignPath - name: Sign Windows artifacts via SignPath
# if: matrix.platform == 'win' && steps.win-channel.outputs.is_stable == 'true' if: matrix.platform == 'win' && steps.win-channel.outputs.is_stable == 'true'
# id: signpath-sign-windows id: signpath-sign-windows
# uses: signpath/github-action-submit-signing-request@v2 uses: signpath/github-action-submit-signing-request@v2
# with: with:
# api-token: ${{ secrets.SIGNPATH_API_TOKEN }} api-token: ${{ secrets.SIGNPATH_API_TOKEN }}
# organization-id: "78e37079-23df-4800-b41c-33312ad7c1e3" organization-id: "78e37079-23df-4800-b41c-33312ad7c1e3"
# project-slug: "ValueCell" project-slug: "ValueCell"
# signing-policy-slug: "ValueCell-sign" signing-policy-slug: "ValueCell-sign"
# github-artifact-id: ${{ steps.upload-unsigned-windows-artifact.outputs.artifact-id }} github-artifact-id: ${{ steps.upload-unsigned-windows-artifact.outputs.artifact-id }}
# wait-for-completion: true wait-for-completion: true
# output-artifact-directory: release/signed output-artifact-directory: release/signed
# - name: Replace unsigned executables with signed ones - name: Replace unsigned executables with signed ones
# if: matrix.platform == 'win' && steps.win-channel.outputs.is_stable == 'true' if: matrix.platform == 'win' && steps.win-channel.outputs.is_stable == 'true'
# shell: pwsh shell: pwsh
# run: | run: |
# Write-Host "SignPath GitHub artifact ID: ${{ steps.upload-unsigned-windows-artifact.outputs.artifact-id }}" Write-Host "SignPath GitHub artifact ID: ${{ steps.upload-unsigned-windows-artifact.outputs.artifact-id }}"
# $signedExeFiles = Get-ChildItem -Path "release/signed" -Filter *.exe -File -Recurse $signedExeFiles = Get-ChildItem -Path "release/signed" -Filter *.exe -File -Recurse
# if (-not $signedExeFiles) { if (-not $signedExeFiles) {
# throw "No signed .exe files found in release/signed" throw "No signed .exe files found in release/signed"
# } }
# $signedCount = $signedExeFiles.Count $signedCount = $signedExeFiles.Count
# if ($env:UNSIGNED_EXE_COUNT -and ($signedCount -ne [int]$env:UNSIGNED_EXE_COUNT)) { if ($env:UNSIGNED_EXE_COUNT -and ($signedCount -ne [int]$env:UNSIGNED_EXE_COUNT)) {
# throw "Signed .exe count ($signedCount) does not match unsigned count ($env:UNSIGNED_EXE_COUNT)" throw "Signed .exe count ($signedCount) does not match unsigned count ($env:UNSIGNED_EXE_COUNT)"
# } }
# foreach ($file in $signedExeFiles) { foreach ($file in $signedExeFiles) {
# Copy-Item -Path $file.FullName -Destination "release/$($file.Name)" -Force Copy-Item -Path $file.FullName -Destination "release/$($file.Name)" -Force
# } }
# $finalExeFiles = Get-ChildItem -Path "release" -Filter *.exe -File $finalExeFiles = Get-ChildItem -Path "release" -Filter *.exe -File
# if ($env:UNSIGNED_EXE_COUNT -and ($finalExeFiles.Count -ne [int]$env:UNSIGNED_EXE_COUNT)) { if ($env:UNSIGNED_EXE_COUNT -and ($finalExeFiles.Count -ne [int]$env:UNSIGNED_EXE_COUNT)) {
# throw "Final release .exe count ($($finalExeFiles.Count)) does not match unsigned count ($env:UNSIGNED_EXE_COUNT)" throw "Final release .exe count ($($finalExeFiles.Count)) does not match unsigned count ($env:UNSIGNED_EXE_COUNT)"
# } }
# Write-Host "Signed executables copied to release/ ($($finalExeFiles.Count) file(s))" Write-Host "Signed executables copied to release/ ($($finalExeFiles.Count) file(s))"
# # Code signing changes the .exe binary, invalidating the sha512 hash that # Code signing changes the .exe binary, invalidating the sha512 hash that
# # electron-builder wrote into latest.yml during the initial build. # electron-builder wrote into latest.yml during the initial build.
# # Recalculate the hash for each signed .exe and patch the yml files so # Recalculate the hash for each signed .exe and patch the yml files so
# # electron-updater can verify the download successfully. # electron-updater can verify the download successfully.
# # #
# # Actual latest.yml structure (from electron-builder NSIS): # Actual latest.yml structure (from electron-builder NSIS):
# # files: # files:
# # - url: ClawX-0.2.4-win-x64.exe ← files[] entries have url/sha512/size # - url: ClawX-0.2.4-win-x64.exe ← files[] entries have url/sha512/size
# # sha512: <base64> # sha512: <base64>
# # size: 430775882 # size: 430775882
# # path: ClawX-0.2.4-win-arm64.exe ← top-level has path/sha512 (no size!) # path: ClawX-0.2.4-win-arm64.exe ← top-level has path/sha512 (no size!)
# # sha512: <base64> # sha512: <base64>
# # releaseDate: '...' # releaseDate: '...'
# - name: Update latest.yml sha512 after code signing - name: Update latest.yml sha512 after code signing
# if: matrix.platform == 'win' && steps.win-channel.outputs.is_stable == 'true' if: matrix.platform == 'win' && steps.win-channel.outputs.is_stable == 'true'
# shell: pwsh shell: pwsh
# run: | run: |
# $ymlFiles = Get-ChildItem -Path "release" -Filter "*.yml" -File | Where-Object { $_.Name -ne "builder-debug.yml" } $ymlFiles = Get-ChildItem -Path "release" -Filter "*.yml" -File | Where-Object { $_.Name -ne "builder-debug.yml" }
# $exeFiles = Get-ChildItem -Path "release" -Filter "*.exe" -File $exeFiles = Get-ChildItem -Path "release" -Filter "*.exe" -File
# foreach ($yml in $ymlFiles) { foreach ($yml in $ymlFiles) {
# $content = Get-Content $yml.FullName -Raw $content = Get-Content $yml.FullName -Raw
# $modified = $false $modified = $false
# foreach ($exe in $exeFiles) { foreach ($exe in $exeFiles) {
# # Compute new sha512 (base64) for the signed exe # Compute new sha512 (base64) for the signed exe
# $hash = Get-FileHash -Path $exe.FullName -Algorithm SHA512 $hash = Get-FileHash -Path $exe.FullName -Algorithm SHA512
# $hashBytes = [byte[]]::new($hash.Hash.Length / 2) $hashBytes = [byte[]]::new($hash.Hash.Length / 2)
# for ($i = 0; $i -lt $hashBytes.Length; $i++) { for ($i = 0; $i -lt $hashBytes.Length; $i++) {
# $hashBytes[$i] = [Convert]::ToByte($hash.Hash.Substring($i * 2, 2), 16) $hashBytes[$i] = [Convert]::ToByte($hash.Hash.Substring($i * 2, 2), 16)
# } }
# $newSha512 = [Convert]::ToBase64String($hashBytes) $newSha512 = [Convert]::ToBase64String($hashBytes)
# $newSize = (Get-Item $exe.FullName).Length $newSize = (Get-Item $exe.FullName).Length
# $escapedName = [Regex]::Escape($exe.Name) $escapedName = [Regex]::Escape($exe.Name)
# # 1) files[] entries: url: <name>\n sha512: <hash>\n size: <n> # 1) files[] entries: url: <name>\n sha512: <hash>\n size: <n>
# $urlPattern = "(?m)(url:\s*${escapedName}\s*\r?\n\s*sha512:\s*)(\S+)(\s*\r?\n\s*size:\s*)(\d+)" $urlPattern = "(?m)(url:\s*${escapedName}\s*\r?\n\s*sha512:\s*)(\S+)(\s*\r?\n\s*size:\s*)(\d+)"
# if ($content -match $urlPattern) { if ($content -match $urlPattern) {
# $content = $content -replace $urlPattern, "`${1}${newSha512}`${3}${newSize}" $content = $content -replace $urlPattern, "`${1}${newSha512}`${3}${newSize}"
# $modified = $true $modified = $true
# Write-Host "Updated $($yml.Name) files[]: $($exe.Name) sha512=$newSha512 size=$newSize" Write-Host "Updated $($yml.Name) files[]: $($exe.Name) sha512=$newSha512 size=$newSize"
# } }
# # 2) Top-level entry: path: <name>\nsha512: <hash>\n (no size field) # 2) Top-level entry: path: <name>\nsha512: <hash>\n (no size field)
# $pathPattern = "(?m)(path:\s*${escapedName}\s*\r?\n)sha512:\s*\S+" $pathPattern = "(?m)(path:\s*${escapedName}\s*\r?\n)sha512:\s*\S+"
# if ($content -match $pathPattern) { if ($content -match $pathPattern) {
# $content = $content -replace $pathPattern, "`${1}sha512: ${newSha512}" $content = $content -replace $pathPattern, "`${1}sha512: ${newSha512}"
# $modified = $true $modified = $true
# Write-Host "Updated $($yml.Name) top-level: $($exe.Name) sha512=$newSha512" Write-Host "Updated $($yml.Name) top-level: $($exe.Name) sha512=$newSha512"
# } }
# } }
# if ($modified) { if ($modified) {
# Set-Content -Path $yml.FullName -Value $content -NoNewline Set-Content -Path $yml.FullName -Value $content -NoNewline
# Write-Host "Saved updated $($yml.Name)" Write-Host "Saved updated $($yml.Name)"
# } }
# } }
# Write-Host "" Write-Host ""
# Write-Host "=== Final yml contents ===" Write-Host "=== Final yml contents ==="
# foreach ($yml in $ymlFiles) { foreach ($yml in $ymlFiles) {
# Write-Host "--- $($yml.Name) ---" Write-Host "--- $($yml.Name) ---"
# Get-Content $yml.FullName Get-Content $yml.FullName
# Write-Host "" Write-Host ""
# } }
# Linux specific steps # Linux specific steps
- name: Build Linux - name: Build Linux

View File

@@ -1,6 +1,6 @@
{ {
"name": "clawx", "name": "clawx",
"version": "0.3.1-alpha.0", "version": "0.3.1",
"pnpm": { "pnpm": {
"onlyBuiltDependencies": [ "onlyBuiltDependencies": [
"@discordjs/opus", "@discordjs/opus",