Skip to content

fix: varlock/auto-load CLI resolution in serverless bundles#733

Open
RobAndrewHurst wants to merge 1 commit into
dmno-dev:mainfrom
RobAndrewHurst:vercel-execSyncVarlock
Open

fix: varlock/auto-load CLI resolution in serverless bundles#733
RobAndrewHurst wants to merge 1 commit into
dmno-dev:mainfrom
RobAndrewHurst:vercel-execSyncVarlock

Conversation

@RobAndrewHurst
Copy link
Copy Markdown

What's the Craic? 🍀

This PR fixes varlock/auto-load in Vercel/serverless environments where node_modules/varlock/dist is present but node_modules/.bin/varlock is not included in the traced function bundle.

Changes

  • Add package-local CLI fallback to execSyncVarlock.
  • Keep the existing resolution order: shell PATH lookup, then node_modules/.bin, then package-local CLI.
  • Use a static new URL('./cli/cli-executable.js', import.meta.url) reference so serverless file tracers can include the CLI entry.
  • Strip execSyncVarlock-only options before passing options to execSync and execFileSync.
  • Add a regression test for a missing .bin layout.
  • Add a patch bump file for varlock.

Why

Vercel serverless functions can trace node_modules/varlock/dist without including node_modules/.bin/varlock. Previously, that caused varlock/auto-load to fail during module initialization before the function handler ran.

Running the package-local CLI entry avoids depending on .bin while preserving existing behavior for normal local and package-manager execution.

Validation

  • bun run test src/lib/test/exec-sync-varlock.test.ts
  • bun run lint:fix
  • bun run --filter varlock pack:local

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves varlock/auto-load reliability in serverless/Vercel-style bundles by adding a fallback execution path that can run the Varlock CLI directly from the installed package files when node_modules/.bin/varlock is missing.

Changes:

  • Adds a package-local CLI resolution fallback to execSyncVarlock (after PATH and node_modules/.bin lookup).
  • Ensures execSyncVarlock-specific options are stripped before passing options into execSync/execFileSync.
  • Adds a regression test covering the “missing .bin” layout and includes a patch bump via bumpy.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
packages/varlock/src/lib/test/exec-sync-varlock.test.ts Adds a regression test verifying the new package-local CLI fallback behavior.
packages/varlock/src/lib/exec-sync-varlock.ts Implements the new resolution fallback to a package-local CLI entry and refactors option handling/result formatting.
.bumpy/vercel-package-cli-fallback.md Patch bump entry describing the serverless CLI resolution fix.

const isWindows = platform.match(/^win/i);
const moduleDir = import.meta.dirname ?? path.dirname(fileURLToPath(import.meta.url));
// Keep this URL static so serverless file tracers include the CLI entry.
const tracedPackageCliPath = fileURLToPath(new URL('./cli/cli-executable.js', import.meta.url));
@theoephraim
Copy link
Copy Markdown
Member

@RobAndrewHurst - thanks for this!

Can you clarify with some more context around your application? I understand you are running on vercel, but likely not nextjs, and maybe not vite either? Is it just raw vercel functions? Some other framework?

In general this seems like a good fallback, but I do want to flag something - in your situation this would potentially mean it would run varlock on each serverless invocation. If so that could introduce a lot of latency - not necessarily if it's just validation, but if it's loading anything external. So far the idea with these kinds of environments is that we resolve everything at build time, but this requires injecting some additional code, which usually happens in our framework integrations.

@RobAndrewHurst
Copy link
Copy Markdown
Author

@theoephraim

For context, the application is a good old home-cooked vanilla JavaScript app, with no framework of any kind. In the next major release, we’re planning to move toward Express for the backend.

You’re correct that each invocation would result in a call to Varlock and the secret manager. I’ve added a handler so that each request will create an OIDC token only if one isn’t currently available.

@theoephraim
Copy link
Copy Markdown
Member

gotcha - yeah I think you probably want to resolve and validate the config, and freeze it at build/deploy time, so that it's not running on each serverless invocation.

You'd need to add some kind of build tooling - probably vite with our vite plugin to your stack to do this. This would inject the varlock init code for you, as well as the resolved env blob.

Could also do something a little more manual with tsup (or tsdown).

I have a PR up (should be merged soon) that would also encrypt that injected blob using a secret set in vercel's secrets system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants