Skip to content

fix: auto-detect native binary distributor packages as externals#3286

Closed
ericallam wants to merge 1 commit intomainfrom
claude/fix-secure-exec-trigger-ZSHvu
Closed

fix: auto-detect native binary distributor packages as externals#3286
ericallam wants to merge 1 commit intomainfrom
claude/fix-secure-exec-trigger-ZSHvu

Conversation

@ericallam
Copy link
Copy Markdown
Member

Packages like @secure-exec/v8 distribute platform-specific native
binaries via optionalDependencies (e.g. @secure-exec/v8-darwin-arm64).
These packages use createRequire(import.meta.url).resolve() at runtime
to locate the correct platform binary, which breaks when esbuild bundles
them because import.meta.url then points to the bundle output directory.

Add a heuristic to the auto-external detection that checks if a package
has optionalDependencies with platform-specific names (darwin, linux,
win32, etc.). When 2+ such deps are found, the package is marked as
external so it resolves binaries from its real node_modules location.

https://claude.ai/code/session_01ScLShmDQ92z8bY9A2T1cPB

Packages like @secure-exec/v8 distribute platform-specific native
binaries via optionalDependencies (e.g. @secure-exec/v8-darwin-arm64).
These packages use createRequire(import.meta.url).resolve() at runtime
to locate the correct platform binary, which breaks when esbuild bundles
them because import.meta.url then points to the bundle output directory.

Add a heuristic to the auto-external detection that checks if a package
has optionalDependencies with platform-specific names (darwin, linux,
win32, etc.). When 2+ such deps are found, the package is marked as
external so it resolves binaries from its real node_modules location.

https://claude.ai/code/session_01ScLShmDQ92z8bY9A2T1cPB
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 28, 2026

⚠️ No Changeset found

Latest commit: b3860c0

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 28, 2026

Walkthrough

The change extends the auto-external detection logic in packages/cli-v3/src/build/externals.ts by adding a new check for platform-specific native binary distributors. When a resolved package's package.json contains optionalDependencies with names matching common platform/OS/variant substrings (requiring at least two matches), the package is marked as external. A new platformPattern regex and hasPlatformSpecificOptionalDeps() helper function were introduced to inspect and identify these platform-specific distributions. The new check is positioned after binding.gyp detection and before caching negative results, altering the control flow to return an external-marking result instead of continuing with the previous logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description explains the problem (packages using createRequire with import.meta.url breaking when bundled) and the solution (checking optionalDependencies for platform-specific names), but omits required template sections like checklist, testing steps, and changelog. Fill out the required template sections: complete the checklist, describe testing steps performed, and add a changelog entry summarizing the change.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: auto-detect native binary distributor packages as externals' accurately and concisely describes the main change: extending auto-external detection to identify packages that distribute platform-specific native binaries.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/fix-secure-exec-trigger-ZSHvu

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment on lines +669 to +670
const platformPattern =
/[-.](darwin|linux|win32|windows|freebsd|android|macos|sunos|openbsd|aix)/i;
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.

🚩 Regex does not match @scope/platform-arch naming convention (e.g. @esbuild/*)

The platformPattern regex at packages/cli-v3/src/build/externals.ts:670 uses [-.](darwin|linux|...) which requires a dot or hyphen before the platform name. This means scoped packages where the platform name immediately follows the / separator — like @esbuild/linux-x64, @esbuild/darwin-arm64 — will NOT match. I verified this by testing the regex against both naming conventions:

  • @rollup/rollup-linux-x64-gnu → ✅ matches (-linux)
  • @swc/core-darwin-arm64 → ✅ matches (-darwin)
  • @esbuild/linux-x64 → ❌ no match (/linux)
  • @esbuild/darwin-arm64 → ❌ no match (/darwin)

This is likely acceptable because: (1) the PR specifically targets napi-rs/Rust packages which use the name-platform-arch convention, (2) the @scope/platform-arch convention is primarily used by esbuild which is a build tool rarely needed at task runtime, and (3) adding / to the character class [-./] could increase false positive risk for scoped packages. However, if a user's task code depends on esbuild at runtime, it won't be auto-detected as external.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@packages/cli-v3/src/build/externals.ts`:
- Around line 669-670: The platformPattern regex only matches when platform
tokens are preceded by '-' or '.', causing cases like '@esbuild/linux-x64' to be
missed; update the const platformPattern to accept start-of-string or additional
delimiters such as '/' and '@' (e.g., allow ^ or characters like / and @ before
the (darwin|linux|...) group) while keeping the i flag so names like
`@esbuild/linux-x64` or linux-x64 will be detected by the auto-external logic.
🪄 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 UI

Review profile: CHILL

Plan: Pro

Run ID: e3b1a400-a22b-411c-9d88-de14abf53f0d

📥 Commits

Reviewing files that changed from the base of the PR and between 2366b21 and b3860c0.

📒 Files selected for processing (1)
  • packages/cli-v3/src/build/externals.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (28)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: typecheck / typecheck
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

**/*.{ts,tsx}: For apps and internal packages (apps/*, internal-packages/*), use pnpm run typecheck --filter <package> for verification, never use build as it proves almost nothing about correctness
Use testcontainers helpers (redisTest, postgresTest, containerTest from @internal/testcontainers) for integration tests with Redis and PostgreSQL instead of mocking
When writing Trigger.dev tasks, always import from @trigger.dev/sdk - never use @trigger.dev/sdk/v3 or deprecated client.defineJob

Files:

  • packages/cli-v3/src/build/externals.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

**/*.{ts,tsx,js,jsx}: Use pnpm for package management in this monorepo (version 10.23.0) with Turborepo for orchestration - run commands from root with pnpm run
Add crumbs as you write code for debug tracing using // @Crumbs comments or `// `#region` `@crumbs blocks - they stay on the branch throughout development and are stripped via agentcrumbs strip before merge

Files:

  • packages/cli-v3/src/build/externals.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

Files:

  • packages/cli-v3/src/build/externals.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • packages/cli-v3/src/build/externals.ts
packages/cli-v3/src/build/**/*

📄 CodeRabbit inference engine (packages/cli-v3/CLAUDE.md)

packages/cli-v3/src/build/**/*: Bundle worker code using the build system in src/build/ based on configuration from trigger.config.ts
Build system in src/build/ should use configuration from trigger.config.ts in user projects to determine bundling, build extensions, and output structure

Files:

  • packages/cli-v3/src/build/externals.ts
packages/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/**/*.{ts,tsx,js,jsx}: For public packages (packages/*), use pnpm run build --filter <package> for verification
Add a changeset via pnpm run changeset:add when modifying any public package (packages/* or integrations/*) - default to patch for bug fixes and minor changes

Files:

  • packages/cli-v3/src/build/externals.ts
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: packages/cli-v3/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:34.140Z
Learning: Applies to packages/cli-v3/src/build/**/* : Build system in `src/build/` should use configuration from `trigger.config.ts` in user projects to determine bundling, build extensions, and output structure
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2026-03-25T15:29:25.853Z
Learning: Applies to trigger.config.ts : Configure build options including `external` packages, `jsx` settings, `conditions`, and `extensions` in the `build` option
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-23T06:24:14.566Z
Learning: Applies to packages/**/*.{ts,tsx,js,jsx} : Add a changeset via `pnpm run changeset:add` when modifying any public package (`packages/*` or `integrations/*`) - default to patch for bug fixes and minor changes
📚 Learning: 2026-03-25T15:29:25.853Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2026-03-25T15:29:25.853Z
Learning: Applies to trigger.config.ts : Configure build options including `external` packages, `jsx` settings, `conditions`, and `extensions` in the `build` option

Applied to files:

  • packages/cli-v3/src/build/externals.ts
📚 Learning: 2026-03-02T12:43:34.140Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: packages/cli-v3/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:34.140Z
Learning: Applies to packages/cli-v3/src/build/**/* : Build system in `src/build/` should use configuration from `trigger.config.ts` in user projects to determine bundling, build extensions, and output structure

Applied to files:

  • packages/cli-v3/src/build/externals.ts
📚 Learning: 2026-03-23T06:24:14.566Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-23T06:24:14.566Z
Learning: Applies to packages/**/*.{ts,tsx,js,jsx} : Add a changeset via `pnpm run changeset:add` when modifying any public package (`packages/*` or `integrations/*`) - default to patch for bug fixes and minor changes

Applied to files:

  • packages/cli-v3/src/build/externals.ts
📚 Learning: 2026-03-26T10:00:03.545Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 3254
File: packages/cli-v3/src/apiClient.ts:61-86
Timestamp: 2026-03-26T10:00:03.545Z
Learning: In triggerdotdev/trigger.dev, the `api.v1.platform-notifications` loader filters `PlatformNotification` records by `surface: "CLI"` before returning them. As a result, `card` and `changelog` notification types (which are `WEBAPP`-only) never reach the CLI endpoint, and the `CliPlatformNotificationResponseSchema` in `packages/cli-v3/src/apiClient.ts` does not need to include those types in its `data.type` enum. Do not flag missing `card`/`changelog` enum values in this schema as a bug.

Applied to files:

  • packages/cli-v3/src/build/externals.ts
📚 Learning: 2026-03-02T12:43:34.140Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: packages/cli-v3/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:34.140Z
Learning: Applies to packages/cli-v3/src/build/**/* : Bundle worker code using the build system in `src/build/` based on configuration from `trigger.config.ts`

Applied to files:

  • packages/cli-v3/src/build/externals.ts
📚 Learning: 2026-03-22T13:26:12.060Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3244
File: apps/webapp/app/components/code/TextEditor.tsx:81-86
Timestamp: 2026-03-22T13:26:12.060Z
Learning: In the triggerdotdev/trigger.dev codebase, do not flag `navigator.clipboard.writeText(...)` calls for `missing-await`/`unhandled-promise` issues. These clipboard writes are intentionally invoked without `await` and without `catch` handlers across the project; keep that behavior consistent when reviewing TypeScript/TSX files (e.g., usages like in `apps/webapp/app/components/code/TextEditor.tsx`).

Applied to files:

  • packages/cli-v3/src/build/externals.ts
📚 Learning: 2026-03-22T19:24:14.403Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3187
File: apps/webapp/app/v3/services/alerts/deliverErrorGroupAlert.server.ts:200-204
Timestamp: 2026-03-22T19:24:14.403Z
Learning: In the triggerdotdev/trigger.dev codebase, webhook URLs are not expected to contain embedded credentials/secrets (e.g., fields like `ProjectAlertWebhookProperties` should only hold credential-free webhook endpoints). During code review, if you see logging or inclusion of raw webhook URLs in error messages, do not automatically treat it as a credential-leak/secrets-in-logs issue by default—first verify the URL does not contain embedded credentials (for example, no username/password in the URL, no obvious secret/token query params or fragments). If the URL is credential-free per this project’s conventions, allow the logging.

Applied to files:

  • packages/cli-v3/src/build/externals.ts
🔇 Additional comments (1)
packages/cli-v3/src/build/externals.ts (1)

405-411: Good insertion point for the new native-binary heuristic.

This check is in the right spot (before negative caching), so packages identified here won’t get cached as non-external.

Comment on lines +669 to +670
const platformPattern =
/[-.](darwin|linux|win32|windows|freebsd|android|macos|sunos|openbsd|aix)/i;
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.

⚠️ Potential issue | 🟠 Major

Expand delimiter matching in platformPattern to avoid false negatives.

Line 670 only matches platform tokens preceded by - or ., so names like @esbuild/linux-x64 won’t match and can slip past auto-external detection.

💡 Proposed fix
-const platformPattern =
-  /[-.](darwin|linux|win32|windows|freebsd|android|macos|sunos|openbsd|aix)/i;
+const platformPattern =
+  /(?:^|[-./_])(darwin|linux|win32|windows|freebsd|android|macos|sunos|openbsd|aix)(?:$|[-./_])/i;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli-v3/src/build/externals.ts` around lines 669 - 670, The
platformPattern regex only matches when platform tokens are preceded by '-' or
'.', causing cases like '@esbuild/linux-x64' to be missed; update the const
platformPattern to accept start-of-string or additional delimiters such as '/'
and '@' (e.g., allow ^ or characters like / and @ before the (darwin|linux|...)
group) while keeping the i flag so names like `@esbuild/linux-x64` or linux-x64
will be detected by the auto-external logic.

@ericallam ericallam closed this Mar 28, 2026
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