v0.2.7
This commit is contained in:
260
.github/workflows/release.yml
vendored
260
.github/workflows/release.yml
vendored
@@ -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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "clawx",
|
"name": "clawx",
|
||||||
"version": "0.2.7-beta.0",
|
"version": "0.2.7",
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"onlyBuiltDependencies": [
|
"onlyBuiltDependencies": [
|
||||||
"@discordjs/opus",
|
"@discordjs/opus",
|
||||||
|
|||||||
Reference in New Issue
Block a user