mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-07-24 21:41:08 +02:00
feat(x): sign Windows builds with Azure Trusted Signing in CI
Wire windowsSign (packager + Squirrel maker) through Azure Trusted Signing's signtool dlib. Signing activates only when the CI env vars are present; local and mac/linux builds are unaffected. The Windows job stages the dlib, metadata.json, and a modern SDK signtool under C:\azsign (space-free paths — @electron/windows-sign splits signWithParams on spaces). Requires repo secrets: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_ENDPOINT, AZURE_CODE_SIGNING_NAME, AZURE_CERT_PROFILE_NAME. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
873187805f
commit
71c5034e10
2 changed files with 65 additions and 0 deletions
37
.github/workflows/electron-build.yml
vendored
37
.github/workflows/electron-build.yml
vendored
|
|
@ -243,8 +243,45 @@ jobs:
|
|||
run: pnpm install --frozen-lockfile
|
||||
working-directory: apps/x
|
||||
|
||||
- name: Setup Azure Trusted Signing
|
||||
shell: pwsh
|
||||
run: |
|
||||
# Stage everything under a path WITHOUT spaces: @electron/windows-sign
|
||||
# splits signWithParams on spaces, so the /dlib and /dmdf paths must be
|
||||
# space-free.
|
||||
$dir = "C:\azsign"
|
||||
New-Item -ItemType Directory -Force -Path $dir | Out-Null
|
||||
|
||||
# The signtool plugin that delegates signing to Azure Trusted Signing.
|
||||
nuget install Microsoft.Trusted.Signing.Client -x -OutputDirectory "$dir\nuget"
|
||||
$dlib = "$dir\nuget\Microsoft.Trusted.Signing.Client\bin\x64\Azure.CodeSigning.Dlib.dll"
|
||||
if (-not (Test-Path $dlib)) { throw "Azure.CodeSigning.Dlib.dll not found at $dlib" }
|
||||
|
||||
# Tells the dlib which account/profile to sign with.
|
||||
@{
|
||||
Endpoint = "${{ secrets.AZURE_ENDPOINT }}"
|
||||
CodeSigningAccountName = "${{ secrets.AZURE_CODE_SIGNING_NAME }}"
|
||||
CertificateProfileName = "${{ secrets.AZURE_CERT_PROFILE_NAME }}"
|
||||
} | ConvertTo-Json | Out-File "$dir\metadata.json" -Encoding utf8
|
||||
|
||||
# Newest Windows SDK signtool (the one vendored by @electron/windows-sign
|
||||
# is too old to load the dlib). Copied into the space-free dir.
|
||||
$signtool = Get-ChildItem "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe" |
|
||||
Where-Object { $_.Directory.Parent.Name -match '^\d+(\.\d+)+$' } |
|
||||
Sort-Object { [version]$_.Directory.Parent.Name } | Select-Object -Last 1
|
||||
if (-not $signtool) { throw "signtool.exe not found in Windows SDK" }
|
||||
Copy-Item $signtool.FullName "$dir\signtool.exe"
|
||||
& "$dir\signtool.exe" | Select-Object -First 3
|
||||
|
||||
echo "AZURE_CODE_SIGNING_DLIB=$dlib" >> $env:GITHUB_ENV
|
||||
echo "AZURE_METADATA_JSON=$dir\metadata.json" >> $env:GITHUB_ENV
|
||||
echo "SIGNTOOL_PATH=$dir\signtool.exe" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Build electron app
|
||||
env:
|
||||
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
|
||||
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
|
||||
VITE_PUBLIC_POSTHOG_KEY: ${{ secrets.VITE_PUBLIC_POSTHOG_KEY }}
|
||||
VITE_PUBLIC_POSTHOG_HOST: ${{ secrets.VITE_PUBLIC_POSTHOG_HOST }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,28 @@ const pkg = require('./package.json');
|
|||
const SKIP_PACMAN = process.env.ROWBOAT_SKIP_PACMAN === '1';
|
||||
const SKIP_CODE_SIGNING = process.env.ROWBOAT_SKIP_CODE_SIGNING === '1';
|
||||
|
||||
// Windows code signing via Azure Trusted Signing — CI-only. The GitHub workflow
|
||||
// downloads the Azure dlib, writes metadata.json, and exports these env vars;
|
||||
// when they're absent (local builds, mac/linux jobs) Windows signing is skipped.
|
||||
// signtool loads Azure.CodeSigning.Dlib.dll (/dlib), which reads metadata.json
|
||||
// (/dmdf) for the endpoint/account/profile and authenticates via
|
||||
// AZURE_TENANT_ID / AZURE_CLIENT_ID / AZURE_CLIENT_SECRET.
|
||||
// NOTE: @electron/windows-sign splits signWithParams on spaces, so the dlib and
|
||||
// metadata paths must not contain spaces (the workflow stages them in C:\azsign).
|
||||
const WINDOWS_SIGN =
|
||||
!SKIP_CODE_SIGNING &&
|
||||
process.env.AZURE_CODE_SIGNING_DLIB &&
|
||||
process.env.AZURE_METADATA_JSON
|
||||
? {
|
||||
// The signtool vendored by @electron/windows-sign is too old for the
|
||||
// Azure dlib; the workflow points this at the Windows SDK's signtool.
|
||||
...(process.env.SIGNTOOL_PATH ? { signToolPath: process.env.SIGNTOOL_PATH } : {}),
|
||||
signWithParams: `/v /debug /dlib ${process.env.AZURE_CODE_SIGNING_DLIB} /dmdf ${process.env.AZURE_METADATA_JSON}`,
|
||||
timestampServer: 'http://timestamp.acs.microsoft.com',
|
||||
hashes: ['sha256'],
|
||||
}
|
||||
: undefined;
|
||||
|
||||
// Stage the ACP coding-adapters (@agentclientprotocol/*-acp) and their full
|
||||
// production dependency closure into the packaged app.
|
||||
//
|
||||
|
|
@ -202,6 +224,9 @@ module.exports = {
|
|||
NSAudioCaptureUsageDescription: 'Rowboat needs access to system audio to transcribe meetings from other apps (Zoom, Meet, etc.)',
|
||||
NSCameraUsageDescription: 'Rowboat uses your camera in video chat mode so the assistant can see you and give feedback (e.g. pitch practice).',
|
||||
},
|
||||
// Signs the packaged app's executables (rowboat.exe etc.); the Squirrel
|
||||
// maker below separately signs the installer it produces.
|
||||
...(WINDOWS_SIGN ? { windowsSign: WINDOWS_SIGN } : {}),
|
||||
...(SKIP_CODE_SIGNING ? {} : {
|
||||
osxSign: {
|
||||
batchCodesignCalls: true,
|
||||
|
|
@ -260,6 +285,9 @@ module.exports = {
|
|||
// GitHub release page next to setup.exe and users grab the
|
||||
// wrong one (it neither launches the app nor auto-updates).
|
||||
noMsi: true,
|
||||
// Sign the Squirrel installer (setup.exe) and the binaries it
|
||||
// repackages. No-op unless the CI signing env vars are set.
|
||||
...(WINDOWS_SIGN ? { windowsSign: WINDOWS_SIGN } : {}),
|
||||
})
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue