Skip to content

Test artifact signing#2709

Draft
mokagio wants to merge 31 commits intotrunkfrom
test-artifact-signing
Draft

Test artifact signing#2709
mokagio wants to merge 31 commits intotrunkfrom
test-artifact-signing

Conversation

@mokagio
Copy link
Contributor

@mokagio mokagio commented Mar 5, 2026

Related issues

  • Fixes #

How AI was used in this PR

Proposed Changes

Testing Instructions

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

mokagio and others added 7 commits March 10, 2026 16:29
Temporary change for iterating on Azure Trusted Signing integration.
Skips lint, tests, Mac builds, and distribution steps.
Restore the full pipeline before merging to trunk.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The current Windows code signing certificate expires soon.
Azure Trusted Signing is Microsoft's cloud-based replacement
that uses short-lived certificates managed via Azure AD.

- Add `windowsSign.ts` config for `@electron/windows-sign`
- Update `forge.config.ts` to use `windowsSign` instead of
  `certificateFile`/`certificatePassword`
- Update `build-for-windows.ps1` to install Azure NuGet
  package, generate `metadata.json`, and export paths
- Update `package-appx.mjs` to build unsigned AppX then
  sign sideload variant via `signtool` + Azure DLib
- Update sideload publisher to match new cert subject

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The CI Windows agents don't have standalone `nuget` CLI.
Use `dotnet add package` with a temp project instead.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CI agents have neither `nuget` nor `dotnet` CLI.
NuGet packages are just zip files, so download and
extract with PowerShell builtins instead.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`Expand-Archive` only accepts `.zip` extensions.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`@electron/windows-sign` already adds `/fd`, `/tr`, `/td`.
Keep only Azure-specific `/dlib` and `/dmdf` in `signWithParams`.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Without it, Buildkite doesn't report status to GitHub.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mokagio mokagio force-pushed the test-artifact-signing branch from 891915b to 287a2b3 Compare March 10, 2026 05:33
mokagio and others added 16 commits March 10, 2026 16:51
`@electron/windows-sign` v1.1.2 always dual-signs with
sha1 then sha256. Azure Trusted Signing only supports
SHA256, so the sha1 pass fails with "no certificates".

Use a custom `hookModulePath` that calls signtool
directly with SHA256-only parameters.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Squirrel/electron-winstaller calls signtool directly,
not through @electron/windows-sign. Passing the
`windowsSign` object got stringified as a literal arg.
Use `signWithParams` string for Squirrel instead.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The DLib tries multiple auth methods by default.
Without excluding them, it never reaches
EnvironmentCredential (which reads AZURE_TENANT_ID
etc.) and fails with "no certificates found".

Also add diagnostic logging for env vars.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve metadata.json path to avoid 8.3 short names
(e.g. BUILDK~1) that the Azure DLib may not handle.

Add a smoke test that signs a dummy file before the
full build, so auth issues surface early with clear
debug output.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PowerShell on Windows chokes on UTF-8 em dashes
in string literals, causing a parse error.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SDK 19041 signtool doesn't support /dlib and /dmdf
(requires 22621+). Download a modern signtool via
the Microsoft.Windows.SDK.BuildTools NuGet package.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Redirect stderr to stdout and print all output
so we can see the actual signing error.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The `& cmd 2>&1` pattern doesn't capture native exe
output in PowerShell. Use Start-Process with file
redirects and print the exact command being run.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Check signtool version, DLib directory contents, and
file sizes. Use cmd /c for output capture since
Start-Process produces empty output.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signtool writes to stderr, which PowerShell treats as
a fatal error under `$ErrorActionPreference = "Stop"`.
Temporarily set to "Continue" for the smoke test.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PowerShell keeps eating signtool output. Use cmd /c
with file redirection instead and read back with
Get-Content. Also test signtool without dlib first
to isolate the issue.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
signtool exits 3 with zero output when using /dlib.
List DLib directory, NuGet package DLLs, and run
dumpbin to identify missing runtime dependencies.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Azure DLib is a C++/CLI assembly that needs the
.NET runtime (via Ijwhost.dll/hostfxr.dll). Without
it, signtool silently exits 3 with zero output.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The vendored signtool in electron-winstaller is too
old for the /dlib flag. Use the windowsSign option
which creates a fake signtool via @electron/windows-sign
that delegates to our Azure signing hook.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
60% of files sent to Azure signing were .ps1 npm
shim scripts from node_modules/.bin. These are text
files that don't need code signing. Saves ~65s.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove metadata.json dump, env var presence
logging, duplicate headers, and verbose runtime
listing. Keep functional code only.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mokagio mokagio force-pushed the test-artifact-signing branch from 287a2b3 to 53f342f Compare March 10, 2026 05:51
@mokagio
Copy link
Contributor Author

mokagio commented Mar 10, 2026

Hey @fredrikekelund @p-jackson @jkmassel 👋

This PR replaces the expiring PFX-based Windows code signing with Azure Trusted Signing.

Key changes:

  • windowsSign.ts configures @electron/windows-sign with a custom hook (scripts/azure-sign-hook.js) that calls signtool directly with SHA256-only params (Azure doesn't support the sha1+sha256 dual-sign that @electron/windows-sign does by default)
  • build-for-windows.ps1 installs the Azure NuGet package, generates metadata.json, and exports the necessary env vars
  • package-appx.mjs builds an unsigned AppX first, then signs the sideload variant via signtool + Azure DLib
  • MakerSquirrel uses the windowsSign hook instead of certificateFile/certificatePassword

CI is green — the Windows dev build passed with signing working end-to-end.
Could you grab the build artifact and test it on your Windows machines to make sure everything installs, launches, and auto-updates as expected?

Thanks!


Posted by Claude (Opus 4.6) on behalf of @mokagio with approval.

@mokagio
Copy link
Contributor Author

mokagio commented Mar 10, 2026

Hey @fredrikekelund @p-jackson @jkmassel 👋

🤔 not sure if others should be pinged, an likely @jkmassel should have not as his contribution to the Windows setup is back in the day... @p-jackson @fredrikekelund I'd appreciate if you could ping the most appropriate folks? Thanks!

@p-jackson
Copy link
Member

Heya @mokagio I don't see any artifact in the buildkite interface

CleanShot 2026-03-11 at 14 22 21@2x

The monorepo restructuring moved build output from `out/` to
`apps/studio/out/`, but the test pipeline wasn't updated.
The release pipeline already uses the correct paths.

---

Generated with the help of Claude Code, https://claude.ai/code

Co-Authored-By: Claude Code Opus 4.6 <noreply@anthropic.com>
@mokagio
Copy link
Contributor Author

mokagio commented Mar 11, 2026

Heya @mokagio I don't see any artifact in the buildkite interface

Apologies @p-jackson ! The artifacts are now there

image

This branch used the pre-apps/ setup when I deleted the other pipeline steps to run faster. Then the rebase messed up the paths.

@p-jackson
Copy link
Member

I was able to use the new installer (signed 11 March 4:57PM) no problems. Signed as Automattic Inc., issued by Microsoft.

Just double clicked the installer and it updated and launched Studio hands free as expected 👍

mokagio and others added 6 commits March 12, 2026 15:48
Use a shared helper for Azure signtool args and source the
sideload AppX publisher from `AZURE_APPX_PUBLISHER`.
Include `scripts/**/*` in `tsconfig.json` so typed linting can cover
the modified signing scripts.

---

Generated with the help of Codex, GPT-5

Co-Authored-By: OpenAI Codex <codex@openai.com>
Keep the sideload publisher visible in `package-appx.mjs` but stop
treating it as required CI configuration until the team decides
whether the signed AppX path is actually needed.

---

Generated with the help of Codex, GPT-5

Co-Authored-By: OpenAI Codex <codex@openai.com>
The signing infrastructure (DLib download, signtool, metadata generation,
.NET check, smoke test) now lives in `a8c-ci-toolkit` as a reusable script.
Points to the `add-azure-trusted-signing` branch until it's merged and released.

---

Generated with the help of Claude Code, https://claude.ai/code

Co-Authored-By: Claude Code Opus 4.6 <noreply@anthropic.com>
PowerShell doesn't search PATH for `.ps1` files with the `&` operator.
Use `Get-Command` to resolve the full path first.

---

Generated with the help of Claude Code, https://claude.ai/code

Co-Authored-By: Claude Code Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants