feat(sdk): allow opting out of TRIGGER_VERSION locking via version: null#3413
feat(sdk): allow opting out of TRIGGER_VERSION locking via version: null#3413jorgehermo9 wants to merge 1 commit intotriggerdotdev:mainfrom
version: null#3413Conversation
…null` Closes triggerdotdev#3380. `TriggerOptions.version` is extended from `string` to `string | null`, and `ApiClientConfiguration` gains a new `version?: string | null` field that applies to every trigger inside an `auth.withAuth(...)` scope. Passing `null` omits `lockToVersion` from the request so the server resolves to the current deployed version, ignoring the `TRIGGER_VERSION` env var. Motivating use case: a single Node.js process triggers tasks in two Trigger.dev projects (e.g. a main project connected to the Vercel integration plus a sibling project for autonomous agents). The ambient `TRIGGER_VERSION` is scoped to the main project, and the SDK previously had no way to opt cross-project calls out of that pin. Resolution precedence (highest first): 1. per-call `options.version` 2. scoped `ApiClientConfiguration.version` 3. `TRIGGER_VERSION` env var `undefined` at any level falls through; only `null` explicitly unpins. All 7 trigger paths in `shared.ts` route through the new `apiClientManager.resolveLockToVersion(...)` helper. The parent-run `lockToVersion: taskContext.worker?.version` paths (triggerAndWait / batchTriggerAndWait / child tasks) are unchanged by design.
🦋 Changeset detectedLatest commit: 18df18c The changes in this PR will be included in the next version bump. This PR includes changesets to release 29 packages
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 |
|
Hi @jorgehermo9, thanks for your interest in contributing! This project requires that pull request authors are vouched, and you are not in the list of vouched users. This PR will be closed automatically. See https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md for more details. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
WalkthroughThis pull request introduces an opt-out mechanism for Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
| runWithConfig<R extends (...args: any[]) => Promise<any>>( | ||
| config: ApiClientConfiguration, | ||
| fn: R |
There was a problem hiding this comment.
🚩 runWithConfig uses global state, not AsyncLocalStorage — concurrent scopes can collide
The runWithConfig method at packages/core/src/v3/apiClientManager/index.ts:115-126 stores scoped config in a global variable via registerGlobal, not via AsyncLocalStorage. If two concurrent async operations both call runWithConfig (e.g., two simultaneous auth.withAuth blocks), the second call overwrites the global config, and the first call's finally block then restores the wrong original. This is a pre-existing design issue (not introduced by this PR), but the new version field is now also subject to this race. In practice, this is likely fine for server-side usage where each request runs in isolation, but it's worth noting for library consumers running multiple scoped operations concurrently in the same process.
(Refers to lines 115-126)
Was this helpful? React with 👍 or 👎 to provide feedback.
Closes #3380.
Summary
TriggerOptions.versionis widened fromstringtostring | null.ApiClientConfigurationgains aversion?: string | nullfield that applies insideauth.withAuth(...)scopes.nullomitslockToVersionfrom the request so the server resolves to the current deployed version, ignoring theTRIGGER_VERSIONenv var.Resolution precedence (highest first):
options.versionApiClientConfiguration.versionTRIGGER_VERSIONenv varundefinedat any level falls through to the next; onlynullexplicitly unpins. The parent-runlockToVersion: taskContext.worker?.versionpaths (triggerAndWait / batchTriggerAndWait / child tasks) are unchanged.Motivation
A single Node.js process (Next.js on Vercel) triggers tasks in two Trigger.dev projects. The Vercel integration injects
TRIGGER_VERSIONscoped to project A, but the SDK'stasks.trigger()unconditionally sends it aslockToVersionfor calls targeting project B too. When project B's deploy drifts behind, every cross-project call fails with a "version not found" 500. There was no supported SDK-level opt-out.Changes
packages/core/src/v3/apiClientManager/types.tsversion?: string | nulltoApiClientConfigurationpackages/core/src/v3/apiClientManager/index.tsresolveLockToVersion()method with three-level precedencepackages/core/src/v3/types/tasks.tsTriggerOptions.versiontostring | null, update JSDocpackages/trigger-sdk/src/v3/shared.tsapiClientManager.resolveLockToVersion(...), unusedgetEnvVarimport removedpackages/core/test/apiClientManager.test.ts.changeset/opt-out-trigger-version-locking.md@trigger.dev/coreand@trigger.dev/sdkUsage
Test plan
packages/core/test/apiClientManager.test.ts(all resolution paths: call > scope > env, null sentinel at each level, explicit undefined passthrough)pnpm exec vitest runin trigger-sdk: 10/10 pass)pnpm exec tsc --noEmitin trigger-sdk: exit 0)getEnvVar("TRIGGER_VERSION")in shared.ts, 7resolveLockToVersioncall sites, 7 untouchedtaskContext.worker?.versionlines