Repository navigation
Add code signing and download optimization steps for Windows and macOS build artifacts - #16
Merged
Merged
Conversation
Introduce optional signing support in the reusable build workflow, driven by the SIGNATURE_KEYS secret (an openssl PEM containing private key and certificate) and an optional SIGNATURE_KEYS_PASSWORD. - Document the signing behavior and secrets at the top of the workflow - Expose HAS_SIGNING_KEYS so signing steps are skipped when unset - Windows: build the client first, convert the PEM to a PFX on the runner, derive the certificate subject for the MSIX Publisher, and sign all client executables with signtool before packaging exe / zip / msi / msix - macOS: convert the PEM to a P12 and sign the app and dmg before upload Unsigned builds remain the default when no keys are provided.
Read the private key from secrets.SIGNATURE_KEYS and the certificate from the new vars.SIGNATURE_CRT, writing each to its own temp file and combining them into PFX/P12 at build time instead of expecting a single combined PEM. Fail early with clear errors when the certificate variable is missing or lacks a BEGIN CERTIFICATE block, so that the certificate can be maintained as a visible variable while the key stays secret.
- Retry delays now increase exponentially (1x, 2x, 4x...) to avoid hammering the same source on repeated failures - electron.d.ts download tries GitHub first, then npmmirror mirrors when GitHub Releases returns errors like 504 - Each mirror download is verified against the expected SHA-256 checksum, with retries, longer timeout, and clear error messages on failure
The Windows SDK `bin` directory also contains non-version folders such as `x86` and `x64`. Sorting all directories by name descending could select one of these instead of a real version (e.g. `x86` > `10.x`), producing invalid paths to `signtool.exe` and failing signing steps. Filter to semver-like directory names, sort them as `[version]` objects, and verify the computed `signtool.exe` path exists before using it. This makes signing and installer PATH setup robust.
Member
Author
|
Oh No |
Register the generated self-signed certificate as a system trust root so that `security find-identity -v` reports it as valid and codesign can build a complete certificate chain. Without this, the identity is filtered out as untrusted and the macOS build fails to sign.
- Add Electron mirror to CI to work around intermittent GitHub 504s - Skip osx-sign identity validation for self-signed certificates - Fix typo in test-agent-host-e2e script path
macOS codesign failed to find a signing identity when SIGNATURE_CRT contained a leaf certificate issued by a CA missing from the trust store, because the chain could not be built (CSSMERR_TP_NOT_TRUSTED). - Split the PEM bundle and export only the leaf cert into the PKCS#12, importing any intermediate/root certs into the temporary keychain - Check for an expired leaf certificate and fail early - Use trustAsRoot for CA-issued leaves (trustRoot only works for self-signed certs) and restrict trust to the codeSign policy - Select the identity by SHA-1 fingerprint instead of display name, which can carry diagnostic suffixes like CSSMERR_TP_NOT_TRUSTED - Warn when the identity is still not trusted
codesign must build the chain to a self-signed root itself, so a bare leaf certificate in SIGNATURE_CRT fails with errSecInternalComponent. Validate the chain (issuer/subject matching, self-signed root) and fail early with actionable guidance, then import all CA certs into the temporary keychain instead of pinning the leaf as trust anchor.
When SIGNATURE_CRT contains only a CA-issued leaf certificate, codesign fails with errSecInternalComponent because it cannot build a chain to a self-signed root. Instead of failing the build, generate a self-signed certificate from the same private key (preserving the leaf's subject) and use it for signing. A warning reminds users to append the issuing CA to SIGNATURE_CRT for a stable chain. Also disable codesign timestamping unless the chain is anchored at an Apple root, since Apple's timestamp service does not support non-Apple signing identities and would otherwise fail the signing step.
Iamliuxiaozhen
marked this pull request as ready for review
November 8, 2026 17:14
Member
Author
|
It’s good to go, but I’ll refine it a bit further. |
Accept the signing certificate chain from `secrets.CRT` or `vars.CRT` (full chain) with fallback to the legacy `vars.SIGNATURE_CRT`, and normalize CRLF line endings before parsing PEM. Detect the leaf certificate by matching its public key against `SIGNATURE_KEYS`, then reorder the chain leaf-first so certificate order in the PEM no longer matters. Fail with clear errors when no certificate block is found or no certificate matches the key.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Introduce optional signing support in the reusable build workflow, driven by the SIGNATURE_KEYS secret (an openssl PEM containing private key and certificate) and an optional SIGNATURE_KEYS_PASSWORD.
Unsigned builds remain the default when no keys are provided.