fix(ci): sign Windows Electron release artifacts

Wire Azure Artifact Signing into the Electron packaging flow so the packaged app and installer executables are signed before publish metadata is generated, and fix the reusable signing action to handle file lists correctly.
This commit is contained in:
LukeParkerDev
2026-03-28 06:58:28 +10:00
parent b0ce0038de
commit 1c6707cfa9
3 changed files with 51 additions and 6 deletions

View File

@@ -52,19 +52,19 @@ runs:
- name: Sign files
if: inputs.files != ''
shell: pwsh
env:
INPUT_FILES: ${{ inputs.files }}
run: |
$files = @'
${{ inputs.files }}
'@ -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_ }
$files = $env:INPUT_FILES -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_ }
& ./script/sign-windows.ps1 @files
- name: Verify signatures
if: inputs.files != ''
shell: pwsh
env:
INPUT_FILES: ${{ inputs.files }}
run: |
$files = @'
${{ inputs.files }}
'@ -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_ }
$files = $env:INPUT_FILES -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_ }
foreach ($file in $files) {
$sig = Get-AuthenticodeSignature $file
if ($sig.Status -ne "Valid") {

View File

@@ -378,6 +378,16 @@ jobs:
- uses: ./.github/actions/setup-bun
- uses: ./.github/actions/windows-trusted-signing
if: runner.os == 'Windows'
with:
azure-client-id: ${{ vars.AZURE_CLIENT_ID || secrets.AZURE_CLIENT_ID }}
azure-tenant-id: ${{ vars.AZURE_TENANT_ID || secrets.AZURE_TENANT_ID }}
azure-subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID || secrets.AZURE_SUBSCRIPTION_ID }}
trusted-signing-account-name: ${{ vars.AZURE_TRUSTED_SIGNING_ACCOUNT_NAME || secrets.AZURE_TRUSTED_SIGNING_ACCOUNT_NAME }}
trusted-signing-certificate-profile: ${{ vars.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE || secrets.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE }}
trusted-signing-endpoint: ${{ vars.AZURE_TRUSTED_SIGNING_ENDPOINT || secrets.AZURE_TRUSTED_SIGNING_ENDPOINT }}
- uses: actions/setup-node@v4
with:
node-version: "24"
@@ -445,6 +455,21 @@ jobs:
env:
OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }}
- name: Verify signed Windows Electron artifacts
if: runner.os == 'Windows'
shell: pwsh
run: |
$files = @()
$files += Get-ChildItem "${{ github.workspace }}\packages\desktop-electron\dist\*.exe" | Select-Object -ExpandProperty FullName
$files += Get-ChildItem "${{ github.workspace }}\packages\desktop-electron\dist\*unpacked\*.exe" | Select-Object -ExpandProperty FullName
foreach ($file in $files | Select-Object -Unique) {
$sig = Get-AuthenticodeSignature $file
if ($sig.Status -ne "Valid") {
throw "Invalid signature for ${file}: $($sig.Status)"
}
}
- uses: actions/upload-artifact@v4
with:
name: opencode-electron-${{ matrix.settings.target }}

View File

@@ -1,5 +1,24 @@
import { execFile } from "node:child_process"
import path from "node:path"
import { fileURLToPath } from "node:url"
import { promisify } from "node:util"
import type { Configuration } from "electron-builder"
const execFileAsync = promisify(execFile)
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..")
const signScript = path.join(rootDir, "script", "sign-windows.ps1")
async function signWindows(configuration: { path: string }) {
if (process.platform !== "win32") return
await execFileAsync(
"pwsh",
["-NoLogo", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", signScript, configuration.path],
{ cwd: rootDir },
)
}
const channel = (() => {
const raw = process.env.OPENCODE_CHANNEL
if (raw === "dev" || raw === "beta" || raw === "prod") return raw
@@ -44,6 +63,7 @@ const getBase = (): Configuration => ({
},
win: {
icon: `resources/icons/icon.ico`,
sign: signWindows,
target: ["nsis"],
},
nsis: {