Skip to content

chore(repo): Build and publish native passkeys binaries on production releases#8955

Open
wobsoriano wants to merge 12 commits into
mainfrom
rob/electron-passkeys-ci-cd
Open

chore(repo): Build and publish native passkeys binaries on production releases#8955
wobsoriano wants to merge 12 commits into
mainfrom
rob/electron-passkeys-ci-cd

Conversation

@wobsoriano

@wobsoriano wobsoriano commented Jun 22, 2026

Copy link
Copy Markdown
Member

Description

Follow-up to #8786, which added the Electron SDK scaffold and the @clerk/electron-passkeys packages without shipping native binaries. This PR adds the release path for those native passkey binaries.

Since the passkeys package should be updated rarely, native binaries are produced by manually running the Electron Passkeys Native Build workflow before a production release that bumps @clerk/electron-passkeys. The workflow builds the macOS arm64/x64 and Windows arm64/x64 .node files on native runners, assembles them into the per-platform npm package directories, verifies every platform package contains exactly one binary, and uploads the assembled electron-passkeys-npm artifact with 90-day retention.

During a production release, the release workflow detects when @clerk/electron-passkeys is about to publish, downloads the latest successful manual artifact for the current branch, and verifies the binaries before changesets/action publishes.

Canary and snapshot releases continue to exclude these packages.

Here's a mermaid flow I generated with codex for this change:

flowchart TD
  A[Passkeys package needs a production release] --> B[Manually run Electron Passkeys Native Build]
  B --> C[Build native .node files on macOS and Windows runners]
  C --> D[Assemble per-platform npm package folders]
  D --> E[Verify each platform package has exactly one .node file]
  E --> F[Upload electron-passkeys-npm artifact with 90-day retention]

  G[Production release workflow runs on main] --> H[Detect whether @clerk/electron-passkeys version differs from npm]
  H -->|No passkeys publish| I[Run normal changesets release]
  H -->|Passkeys publish pending| J[Download latest successful manual artifact for main]
  J --> K[Verify downloaded platform packages contain binaries]
  K --> L[changesets publishes wrapper and platform packages]
Loading

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other: release pipeline

Summary by CodeRabbit

Summary

  • New Features

    • Added native passkey (WebAuthn) support to Clerk’s Electron SDK, with prebuilt binaries for macOS (arm64, x64) and Windows (arm64, x64).
  • Build & Release Automation

    • Added an Electron Passkeys native build workflow and packaging of platform binaries.
    • Updated the main release flow to fetch and verify native binaries only when needed.
  • Quality & Validation

    • Improved native binary checks to ensure the shipped .node file matches each package’s declared entry point, backed by expanded automated tests.

@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jun 24, 2026 8:09pm
swingset Ready Ready Preview, Comment Jun 24, 2026 8:09pm

Request Review

@changeset-bot

changeset-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dda7004

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@clerk/electron-passkeys Patch
@clerk/electron Patch
@clerk/electron-passkeys-darwin-arm64 Patch
@clerk/electron-passkeys-darwin-x64 Patch
@clerk/electron-passkeys-win32-arm64-msvc Patch
@clerk/electron-passkeys-win32-x64-msvc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 8f7dcd53-26f0-4d60-b85f-c9208755412b

📥 Commits

Reviewing files that changed from the base of the PR and between 086b901 and dda7004.

📒 Files selected for processing (1)
  • .github/workflows/electron-passkeys.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/electron-passkeys.yml

📝 Walkthrough

Walkthrough

Adds native binary build, validation, and release wiring for @clerk/electron-passkeys. Snapshot and canary package selection now excludes those packages. A new workflow builds and packages native binaries, and release gating now detects, downloads, and verifies them.

Changes

Electron Passkeys Native Binary Pipeline

Layer / File(s) Summary
Package predicate and changeset wiring
scripts/common.mjs, .changeset/config.json, .changeset/electron-passkeys-native-binaries.md
Adds the Electron Passkeys package predicate, updates Changesets fixed-package configuration, and adds the patch release note for native binaries.
Snapshot and canary exclusion
scripts/snapshot.mjs, scripts/canary.mjs
Updates snapshot and canary package selection to exclude Electron Passkeys packages using the shared predicate.
Binary verification script and tests
scripts/check-electron-passkeys-binaries.mjs, scripts/check-electron-passkeys-binaries.test.mjs
Adds the npm binary scan CLI, error formatting helpers, entrypoint guard, and Vitest coverage for missing and mismatched native binaries.
Publish detection script
scripts/detect-electron-passkeys-publish.mjs
Adds the CLI script that reads the local package version, queries npm for the published version, compares them, and prints should-build.
Native build CI workflow
.github/workflows/electron-passkeys.yml
Creates the manual Electron Passkeys workflow with matrix native builds, host smoke tests, artifact upload, packaging, binary verification, and npm artifact publication.
Release workflow gating and artifact download
.github/workflows/release.yml
Extends the release job permissions and conditionally downloads and verifies the Electron Passkeys npm artifact when publishing is needed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • jeremy-clerk

Poem

🐇 I hop through binaries, neat and bright,
Mac and Windows take their flight.
A passkey packet, bundled tight,
Then release checks it’s all done right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding native passkeys binary build and publish support for production releases.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands.

Comment thread .github/workflows/electron-passkeys.yml Fixed
Comment thread .github/workflows/electron-passkeys.yml Fixed
@pkg-pr-new

pkg-pr-new Bot commented Jun 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@8955

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@8955

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@8955

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@8955

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@8955

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@8955

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@8955

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@8955

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@8955

@clerk/express

npm i https://pkg.pr.new/@clerk/express@8955

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@8955

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@8955

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@8955

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@8955

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@8955

@clerk/react

npm i https://pkg.pr.new/@clerk/react@8955

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@8955

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@8955

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@8955

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@8955

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@8955

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@8955

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@8955

commit: dda7004

@wobsoriano wobsoriano changed the title chore(repo): Build and publish native binaries on production releases chore(repo): Build and publish native passkeys binaries on production releases Jun 22, 2026
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Comment thread .changeset/config.json
Comment on lines +11 to +19
"fixed": [
[
"@clerk/electron-passkeys",
"@clerk/electron-passkeys-darwin-arm64",
"@clerk/electron-passkeys-darwin-x64",
"@clerk/electron-passkeys-win32-arm64-msvc",
"@clerk/electron-passkeys-win32-x64-msvc"
]
],

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all five packages must publish at the same version number. The four platform packages are optionalDependencies of the wrapper at an exact version, and napi-rs's native loader matches the .node binary by the package version it was built with

@wobsoriano wobsoriano marked this pull request as ready for review June 23, 2026 00:33

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/electron-passkeys.yml:
- Around line 11-20: The workflow file has a duplicate permissions key defined
in the YAML structure, which causes a parsing error. Remove the second
permissions block that only contains contents: read and keep only the first
permissions block that includes both contents: read and actions: read. This will
resolve the YAML syntax error and allow the workflow to parse correctly.

In @.github/workflows/release.yml:
- Around line 46-52: Navigate to the `.github/workflows/electron-passkeys.yml`
reusable workflow file and locate the duplicate `permissions` key that is
causing the YAML parsing error. Remove one of the duplicate `permissions` blocks
so that only a single `permissions` definition remains in the file. This will
resolve the syntax error and allow the workflow call in the build-native job to
execute successfully.

In `@scripts/check-electron-passkeys-binaries.mjs`:
- Around line 27-45: The main function lacks error handling for the
findMissingBinaries call, which means any thrown errors will result in unhandled
rejections instead of GitHub annotations. Wrap the await
findMissingBinaries(npmDir) call in a try-catch block and use console.error with
the ::error:: format to report caught exceptions. Additionally, the error
message template is inaccurate as it always says "empty package" regardless of
the count value; update the message logic to correctly indicate that the issue
is having an incorrect number of binaries (not exactly 1), adjusting the text
appropriately when count is greater than 1 versus when count is 0.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 935b7c82-ea09-45c8-a2d9-eae66f8d7961

📥 Commits

Reviewing files that changed from the base of the PR and between 52d310c and 9a80889.

📒 Files selected for processing (10)
  • .changeset/config.json
  • .changeset/electron-passkeys-native-binaries.md
  • .github/workflows/electron-passkeys.yml
  • .github/workflows/release.yml
  • scripts/canary.mjs
  • scripts/check-electron-passkeys-binaries.mjs
  • scripts/check-electron-passkeys-binaries.test.mjs
  • scripts/common.mjs
  • scripts/detect-electron-passkeys-publish.mjs
  • scripts/snapshot.mjs

Comment thread .github/workflows/electron-passkeys.yml Outdated
Comment thread .github/workflows/release.yml Outdated
Comment thread scripts/check-electron-passkeys-binaries.mjs
name: Electron Passkeys Native Build

on:
workflow_dispatch:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workflow is manual because native passkey releases are rare. The release workflow consumes the artifact only when publish is pending.

Comment on lines +68 to +70
- name: Determine whether electron-passkeys is about to publish
id: detect-native
run: node scripts/detect-electron-passkeys-publish.mjs >> "$GITHUB_OUTPUT"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only enables the binary download path when @clerk/electron-passkeys is actually about to publish

Comment on lines +75 to +87
- name: Download electron-passkeys native binaries
if: ${{ steps.detect-native.outputs.should-build == 'true' }}
uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21
with:
github_token: ${{ github.token }}
workflow: electron-passkeys.yml
name: electron-passkeys-npm
path: packages/electron-passkeys/npm
branch: ${{ github.ref_name }}
event: workflow_dispatch
workflow_conclusion: success
search_artifacts: true
allow_forks: false

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pulls the latest successful manual native-build artifact for this branch so changesets can publish the platform packages with their .node files

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 75-91: The workflow downloads electron-passkeys binaries without
verifying they were built from the same commit as the release. The "Download
electron-passkeys native binaries" step retrieves artifacts by branch and build
success but doesn't validate the source commit, and the "Verify
electron-passkeys binaries are present" step only checks for file presence, not
provenance. Add a verification step between these two that captures the source
commit SHA of the downloaded artifact and compares it against the current
release commit (accessible via github.sha or github.ref_name context). Only
proceed with subsequent steps if the commit SHAs match, preventing mismatched
binaries from being published.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 7554401e-7ff6-4ce4-a600-57648f32ebd6

📥 Commits

Reviewing files that changed from the base of the PR and between 3fcfb27 and e7caae9.

📒 Files selected for processing (4)
  • .github/workflows/electron-passkeys.yml
  • .github/workflows/release.yml
  • scripts/check-electron-passkeys-binaries.mjs
  • scripts/check-electron-passkeys-binaries.test.mjs
🚧 Files skipped from review as they are similar to previous changes (3)
  • scripts/check-electron-passkeys-binaries.test.mjs
  • .github/workflows/electron-passkeys.yml
  • scripts/check-electron-passkeys-binaries.mjs

Comment thread .github/workflows/release.yml
timeout-minutes: ${{ vars.TIMEOUT_MINUTES_NORMAL && fromJSON(vars.TIMEOUT_MINUTES_NORMAL) || 10 }}

permissions:
actions: read

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

required because we need to read workflow runs and artifacts from electron-passkeys.yml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
scripts/check-electron-passkeys-binaries.test.mjs (1)

56-63: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a mismatch test where main is path-prefixed (e.g., ./passkeys.node).

This will lock in expected behavior for common package.json main formats and prevent false release gate failures.

Suggested test addition
+  test('accepts declared binary when main uses ./ prefix', async () => {
+    const root = await createRoot();
+    await createPlatformDir(root, 'darwin-arm64', ['passkeys.node'], './passkeys.node');
+
+    await expect(findMissingBinaries(root)).resolves.toEqual([]);
+  });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-electron-passkeys-binaries.test.mjs` around lines 56 - 63, Add
a new mismatch test in findMissingBinaries coverage for the package.json main
field when it is path-prefixed, such as ./passkeys.node, so the behavior is
locked in for common main formats. Update the test suite around
findMissingBinaries and createPlatformDir to assert that a dir is still flagged
correctly when the declared binary includes a leading path prefix, matching the
existing missing-binary expectations in this check-electron-passkeys-binaries
test file.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/electron-passkeys.yml:
- Line 34: Disable persisted checkout credentials in both workflow jobs by
updating the actions/checkout usage in the electron-passkeys workflow to set
persist-credentials to false. Make this change in each checkout step (the one in
the first job and the one in the second job) since the workflow does not perform
git-authenticated write operations, and refer to the actions/checkout step
configurations to locate them.

---

Nitpick comments:
In `@scripts/check-electron-passkeys-binaries.test.mjs`:
- Around line 56-63: Add a new mismatch test in findMissingBinaries coverage for
the package.json main field when it is path-prefixed, such as ./passkeys.node,
so the behavior is locked in for common main formats. Update the test suite
around findMissingBinaries and createPlatformDir to assert that a dir is still
flagged correctly when the declared binary includes a leading path prefix,
matching the existing missing-binary expectations in this
check-electron-passkeys-binaries test file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 84671be1-109d-4716-b8a6-97add6e2ea5e

📥 Commits

Reviewing files that changed from the base of the PR and between e7caae9 and 086b901.

📒 Files selected for processing (3)
  • .github/workflows/electron-passkeys.yml
  • scripts/check-electron-passkeys-binaries.mjs
  • scripts/check-electron-passkeys-binaries.test.mjs

Comment thread .github/workflows/electron-passkeys.yml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants