Compare commits

...

1111 Commits

Author SHA1 Message Date
claude[bot] d7eae64913 fix(core): remove duplicate error logging and improve AggregateError messages
- Remove per-provider console.error calls (rely on AggregateError for error propagation)
- Include failed provider names in AggregateError message for better debugging

Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
2026-05-12 14:35:13 +00:00
claude[bot] 1e29a72515 fix(core): throw AggregateError after Promise.allSettled to preserve caller failure detection
Keep Promise.allSettled for resilience (all providers get a chance to flush),
but throw AggregateError if any failed so callers can still detect failures.

Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
2026-05-12 13:57:45 +00:00
claude[bot] c5b5fde24d fix(core): use Promise.allSettled in TracingSDK flush/shutdown
Switch TracingSDK.flush() and shutdown() from Promise.all to
Promise.allSettled to prevent one provider's rejection from
abandoning the other providers' in-flight exports.

This fixes an issue where user-emitted trace data (logger.info
calls, child spans) could be silently dropped on shutdown when
any provider fails to flush, particularly affecting self-hosted
deployments with processKeepAliveEnabled: false.

Fixes #3556

Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
2026-05-12 13:47:24 +00:00
github-actions[bot] 41a486ea7e chore: release v4.4.6 (#3501)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 5s
🧭 Helm Chart Release / lint-and-test (push) Has been cancelled
🧭 Helm Chart Release / release (push) Has been cancelled
## Summary
1 improvement, 1 bug fix.

## Improvements
- Fail attempts on uncaught exceptions instead of hanging to
`MAX_DURATION_EXCEEDED`. A Node `EventEmitter` (e.g. `node-redis`)
emitting `"error"` with no `.on("error", ...)` listener escalates to
`uncaughtException`, which the worker previously reported but did not
act on — runs drifted to maxDuration with empty attempts. They now fail
fast with the original error and status `FAILED`, and respect the task's
normal retry policy. You should still attach `.on("error", ...)`
listeners to long-lived clients to handle errors gracefully.
([#3529](https://github.com/triggerdotdev/trigger.dev/pull/3529))

## Bug fixes
- Fix dev workers spinning at 100% CPU after the parent CLI disconnects.
Orphaned `trigger-dev-run-worker` (and indexer) processes were caught in
an `uncaughtException` feedback loop: a periodic IPC send via
`process.send` would throw `ERR_IPC_CHANNEL_CLOSED` once the parent
closed the channel, which re-entered the same handler that itself called
`process.send`, scheduled via `setImmediate` and amplified by
source-map-support's `prepareStackTrace`. Fixed by (1) silently dropping
packets in `ZodIpcConnection` when the channel is disconnected, (2)
adding a `process.on("disconnect", ...)` handler in dev workers so they
exit cleanly when the CLI closes the IPC channel, and (3) wrapping all
`uncaughtException`-path `process.send` calls in a `safeSend` guard that
checks `process.connected` and swallows synchronous throws.
([#3491](https://github.com/triggerdotdev/trigger.dev/pull/3491))

<details>
<summary>Raw changeset output</summary>

# Releases
## @trigger.dev/build@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`

## trigger.dev@4.4.6

### Patch Changes

- Fix dev workers spinning at 100% CPU after the parent CLI disconnects.
Orphaned `trigger-dev-run-worker` (and indexer) processes were caught in
an `uncaughtException` feedback loop: a periodic IPC send via
`process.send` would throw `ERR_IPC_CHANNEL_CLOSED` once the parent
closed the channel, which re-entered the same handler that itself called
`process.send`, scheduled via `setImmediate` and amplified by
source-map-support's `prepareStackTrace`. Fixed by (1) silently dropping
packets in `ZodIpcConnection` when the channel is disconnected, (2)
adding a `process.on("disconnect", ...)` handler in dev workers so they
exit cleanly when the CLI closes the IPC channel, and (3) wrapping all
`uncaughtException`-path `process.send` calls in a `safeSend` guard that
checks `process.connected` and swallows synchronous throws.
([#3491](https://github.com/triggerdotdev/trigger.dev/pull/3491))
- Fail attempts on uncaught exceptions instead of hanging to
`MAX_DURATION_EXCEEDED`. A Node `EventEmitter` (e.g. `node-redis`)
emitting `"error"` with no `.on("error", ...)` listener escalates to
`uncaughtException`, which the worker previously reported but did not
act on — runs drifted to maxDuration with empty attempts. They now fail
fast with the original error and status `FAILED`, and respect the task's
normal retry policy. You should still attach `.on("error", ...)`
listeners to long-lived clients to handle errors gracefully.
([#3529](https://github.com/triggerdotdev/trigger.dev/pull/3529))
-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`
    -   `@trigger.dev/build@4.4.6`
    -   `@trigger.dev/schema-to-json@4.4.6`

## @trigger.dev/core@4.4.6

### Patch Changes

- Fix dev workers spinning at 100% CPU after the parent CLI disconnects.
Orphaned `trigger-dev-run-worker` (and indexer) processes were caught in
an `uncaughtException` feedback loop: a periodic IPC send via
`process.send` would throw `ERR_IPC_CHANNEL_CLOSED` once the parent
closed the channel, which re-entered the same handler that itself called
`process.send`, scheduled via `setImmediate` and amplified by
source-map-support's `prepareStackTrace`. Fixed by (1) silently dropping
packets in `ZodIpcConnection` when the channel is disconnected, (2)
adding a `process.on("disconnect", ...)` handler in dev workers so they
exit cleanly when the CLI closes the IPC channel, and (3) wrapping all
`uncaughtException`-path `process.send` calls in a `safeSend` guard that
checks `process.connected` and swallows synchronous throws.
([#3491](https://github.com/triggerdotdev/trigger.dev/pull/3491))
- Fail attempts on uncaught exceptions instead of hanging to
`MAX_DURATION_EXCEEDED`. A Node `EventEmitter` (e.g. `node-redis`)
emitting `"error"` with no `.on("error", ...)` listener escalates to
`uncaughtException`, which the worker previously reported but did not
act on — runs drifted to maxDuration with empty attempts. They now fail
fast with the original error and status `FAILED`, and respect the task's
normal retry policy. You should still attach `.on("error", ...)`
listeners to long-lived clients to handle errors gracefully.
([#3529](https://github.com/triggerdotdev/trigger.dev/pull/3529))

## @trigger.dev/python@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`
    -   `@trigger.dev/build@4.4.6`
    -   `@trigger.dev/sdk@4.4.6`

## @trigger.dev/react-hooks@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`

## @trigger.dev/redis-worker@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`

## @trigger.dev/rsc@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`

## @trigger.dev/schema-to-json@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`

## @trigger.dev/sdk@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`

</details>

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-12 11:33:00 +01:00
James Ritchie 1e4b896c30 Fix(webapp): Notification style updates (#3553)
### Style updates to the notifications
- Tightened up the typography
- Brighter background to make it stand out a bit more
- A bit more padding to make it more readable
- Show the close button on hover instead
- Turned the notification into a separate component as it's shared on
the admin page modal
- Minor tweaks to the behavior of toggling the notification beween
open/closed side menu states

### Before
<img width="224" height="313" alt="before"
src="https://github.com/user-attachments/assets/c9a9377c-4a3b-4477-921a-3c86385d3f0b"
/>

### After (with image)
<img width="239" height="284" alt="CleanShot 2026-05-11 at 17 22 01"
src="https://github.com/user-attachments/assets/311b4dbc-4853-4e6c-9f83-8173b38bd466"
/>

### After (no image)
<img width="239" height="189" alt="after"
src="https://github.com/user-attachments/assets/884e062b-3608-4cb3-a462-d50597257753"
/>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-05-12 11:23:36 +01:00
Eric Allam 2301ed608c refactor(run-engine): make taskIdentifier optional on run-queue messages (#3559)
## Summary

Make `taskIdentifier` optional on the run-queue message schema. No
behavior change in this PR; readers continue to accept payloads that
include the field. A separate change will stop writing it on the wire to
shrink the per-run payload that lives in Redis while runs wait to be
dequeued.

## Design

The field is written into every payload at enqueue time but no consumer
reads it back on the dequeue path. Both the run-engine and supervisor
derive `taskIdentifier` from the loaded `TaskRun` row instead. Relaxing
the schema first means readers tolerate payloads that omit it, so the
writer-side change can ship without producing schema-parse errors during
a rolling deploy.

`projectId` is left required: `WorkerQueueResolver.#getOverride` reads
it for project-scoped runtime worker-queue overrides.

## Test plan

- [x] `pnpm run typecheck --filter @internal/run-engine`
- [x] `pnpm run typecheck --filter webapp`
- [x] `pnpm run test ./src/run-queue/tests/enqueueMessage.test.ts
./src/run-queue/tests/workerQueueResolver.test.ts --run` (28/28 passing)
2026-05-12 11:03:34 +01:00
Eric Allam 5f1a3e1653 refactor(run-engine): route TTL expiration through the batch path only (#3554)
## Summary

TTL expiration on queued runs was being scheduled twice: once via a
per-run `expireRun` worker job (the original implementation) and once
via the batch TTL system (added more recently). Both paths attempt to
flip the same run to `EXPIRED`. The per-run job almost always won the
race, leaving the batch consumer to observe runs already expired by the
older path.

This collapses TTL expiration onto the batch path so every queued TTLed
run goes through a single Redis-backed sorted set + batch consumer
instead of also getting its own scheduled redis-worker job.

## Design

`engine.trigger` and `delayedRunSystem.enqueueDelayedRun` no longer call
`ttlSystem.scheduleExpireRun`. The remaining `enqueueSystem.enqueueRun({
includeTtl: true })` already adds the run to the TTL sorted set;
`TtlSystem.expireRunsBatch` flips it to `EXPIRED` when the TTL fires.

Delayed runs get the same coverage by passing `includeTtl: true` on
their post-delay enqueue, so the TTL is armed from the moment the run
enters the queue (matching how the old job behaved —
`parseNaturalLanguageDuration` is evaluated at enqueue time).

The new path explicitly does not re-expire runs once they have been
allocated a concurrency slot. That is intentional: TTL is for runs that
are queued and have never started. Once a run has a slot it is on its
way to executing.

## Test plan

- [x] `pnpm run test --filter @internal/run-engine
./src/engine/tests/ttl.test.ts` — 15 tests, including a new "Re-enqueued
runs are not expired by TTL once they have started" that locks in the
queued-and-never-started contract.
- [x] `pnpm run test --filter @internal/run-engine
./src/engine/tests/delays.test.ts` — 5 tests, including "Delayed run
with a ttl" which now also asserts the TTL is armed from queue-enter
time, not `createdAt`.
- [x] `pnpm run test --filter @internal/run-engine
./src/engine/tests/lazyWaitpoint.test.ts` — 12 tests.
- [x] `pnpm run typecheck --filter @internal/run-engine`.
2026-05-12 07:58:42 +01:00
Iss 2b845455b0 feat(webapp): admin back-office editors for org max projects and batch rate limit (#3475)
## Summary

- Adds admin-only editors on the back-office org page for
`Organization.maximumProjectCount` and
`Organization.batchRateLimitConfig`, alongside the existing API rate
limit editor.
- Splits the back-office org page into per-section components
(`ApiRateLimitSection`, `BatchRateLimitSection`, `MaxProjectsSection`)
so each tool is self-contained — adding new sections later doesn't bloat
the route.
- Generalizes the rate-limit form into a reusable `RateLimitSection`
component + `RateLimitDomain` server config so API and batch share the
same UI, validation, and action handler. Each domain only owns its env
defaults, DB column, and logger key.
- "Saved." banner and validation errors are scoped to the section that
submitted, not the page.

Heads-up: the API rate-limit log key was renamed
`admin.backOffice.rateLimit` → `admin.backOffice.apiRateLimit` for
symmetry with the new `admin.backOffice.batchRateLimit`.

## Test plan

- [ ] As an admin, visit `/admin/back-office/orgs/:orgId` and confirm
all three sections render with the org's current values (or system
defaults).
- [ ] Edit and save each section; confirm only that section shows the
"Saved." banner.
- [ ] Submit invalid input (e.g. `0` tokens, malformed interval);
confirm errors render in the offending form only and the other sections
stay closed.
- [ ] Confirm a non-admin user is redirected away from the route.
- [ ] After saving a rate-limit override, hit the org with traffic and
confirm the new limit is enforced (API rate limit + batch rate limit
code paths read the column at request time).
2026-05-11 10:19:41 -04:00
Eric Allam a5ba406530 feat(webapp,redis): handle UNBLOCKED during ElastiCache role change (#3549)
## Summary

When ElastiCache demotes a primary to replica — during a Multi-AZ
failover or a vertical node-type change — the demoting primary issues an
`UNBLOCKED` reply to any in-flight blocking commands (`BLPOP`, `BRPOP`,
`BLMOVE`, `XREADGROUP ... BLOCK`, etc.) to clear them before the role
flips. ioredis surfaces these as `ReplyError` to caller code.

The shared `defaultReconnectOnError` added in #3548 only matches
`READONLY` and `LOADING`. This extends it to `UNBLOCKED` so the
disconnect-reconnect-retry cycle handles BLPOP-shaped errors the same
way the existing two cases handle non-blocking-command errors.

## Fix

```ts
export function defaultReconnectOnError(err: Error): boolean | 1 | 2 {
  const msg = err.message ?? "";
  if (
    msg.startsWith("READONLY") ||
    msg.startsWith("LOADING") ||
    msg.startsWith("UNBLOCKED")
  ) {
    return 2;
  }
  return false;
}
```

Returning `2` tells ioredis to disconnect, reconnect, and re-issue the
command. For a BLPOP that means a fresh BLPOP against the new primary
instead of the `UNBLOCKED` error escaping to the caller.

## Test plan

- [ ] CI green
- [ ] Trigger a Multi-AZ failover or a vertical scale event on an
ElastiCache replication group whose clients are running blocking
commands and confirm no `UNBLOCKED` errors surface to caller code during
the cutover.
2026-05-11 11:02:40 +01:00
Eric Allam 567e2a2c32 feat(webapp,redis): handle READONLY / LOADING during ElastiCache failover (#3548)
## Summary

During an ElastiCache role swap (failover) or node-type change (vertical
scale), the ioredis TCP/TLS connection stays open but the server starts
answering with `READONLY` (the client is talking to a node that became a
replica) or `LOADING` (node still loading data from disk). Without an
explicit hook, those errors surface to caller code as `ReplyError`
instances — every write op on the affected connection fails until the
cluster fully cuts over.

This PR adds `reconnectOnError` to every prod ioredis client so the
disconnect + reconnect + retry cycle absorbs these errors and caller
code never sees them.

## Fix

```ts
export function defaultReconnectOnError(err: Error): boolean | 1 | 2 {
  const msg = err.message ?? "";
  if (msg.startsWith("READONLY") || msg.startsWith("LOADING")) return 2;
  return false;
}
```

Returning `2` tells ioredis to disconnect, reconnect, and re-issue the
failed command. After reconnect, DNS / SG state routes the new socket to
a writable node.

The helper lives in `@internal/redis` and is wired into both the shared
`createRedisClient` (which covers RunQueue, schedule-engine,
redis-worker, and every other internal-package consumer) and the direct
`new Redis(...)` call sites in the webapp.

V1-only marqs files are intentionally not migrated.

## Test plan

- [x] `pnpm run typecheck --filter webapp`
- [x] `pnpm run typecheck --filter @internal/run-engine`
- [x] Verified end-to-end against a live ElastiCache vertical-scale
event — caller-surfaced errors went from tens of thousands during the
cutover window down to a handful per ioredis client
- [ ] Confirm steady-state behavior unchanged after deploy
2026-05-11 07:17:07 +01:00
James Ritchie 6cdd8814a3 fix(webapp): Fix for resizable side panel getting stuck at its min-size (#3538)
## Summary

- Run-view inspector panel was glitching out on Firefox: visual flicker
on close, locking up at min size, and intermittent `panelHasSpace`
invariant errors. Root cause is the underlying `react-window-splitter`
library's collapse animation, which uses `@react-spring/rafz` and
interacts poorly with Firefox.
- Disabled the library's collapse animation on Firefox only, app-wide
(every consumer of `RESIZABLE_PANEL_ANIMATION`). Chromium and Safari
behaviour is unchanged.

## Changes

- **Firefox animation skip** in `RESIZABLE_PANEL_ANIMATION` —
UA-detected at module load, resolves to `undefined` for Firefox so the
library's animation actor completes in one frame instead of running its
rAF loop.
- **Inspector min raised 50px → 250px** so dragging can't shrink the
panel into a near-useless width.
- **`autosaveId` bumped `v2` → `v3`** to invalidate stale persisted
snapshots (the library has a `// TODO` branch that ignores prop changes
for already-registered panels, so existing users would otherwise still
see the old 50px min).
- **`react-window-splitter` pinned** to exact `0.4.1` to protect the
patch from drifting if line offsets change in a patch release.
- **Two hunks added to the existing `@window-splitter/state` patch:**
- Removed the library's auto-collapse-on-drag block entirely. Every
collapsible panel in the app is parent-controlled, and that block was
triggering state-machine deadlocks when handlers were no-ops.
Drag-to-collapse is now disabled across the app; collapse is only
triggered explicitly (close button, ESC, URL change, etc.).
- In `getDeltaForEvent`, fall back to the panel's `default` before its
`min` when expanding — so the first ever click on a span opens the
inspector at 500px, not 250px.

## Local testing confirmed

- [x] Firefox: open a run, click various spans → panel opens instantly
at 500px, drags freely between 250px and max, closes instantly to 0. No
console errors.
- [x] Chrome/Chromium: same flow, but with smooth open/close animation
as before.
- [x] Safari: same as Chrome.
- [x] Reload mid-session → panel restores cleanly to the dragged size.
- [x] Other resizable panels in the app (logs, deployments, schedules,
batches, bulk-actions, runs index) still animate on Chromium/Safari.

## Notes

- Linear: TRI-8584
- Branch contains intermediate commits exploring an unsuccessful
snapshot-validator approach; they're reverted by the final commit.
Cumulative diff is 6 files. Squash on merge if you'd prefer a clean
history.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 21:31:01 +01:00
Eric Allam ead1e5a53d feat(webapp): reload LLM pricing registry on Redis pub/sub (#3534)
## Summary

Adds a Redis pub/sub reload path to the webapp's in-memory LLM pricing
registry. When enabled on a process, the registry reloads from the
database whenever a publish lands on the configured channel — instead of
waiting for the existing 5-minute interval. Lets pricing/model changes
propagate to cost enrichment within seconds.

Subscription is **off by default** and opt-in per process. Only
OTel-ingesting services need real-time freshness; dashboard and worker
services run fine on the periodic interval and shouldn't pile onto each
publish with a full-table reload.

## Design

When `LLM_PRICING_RELOAD_PUBSUB_ENABLED=true`, subscribes via
`createRedisClient` against `COMMON_WORKER_REDIS_*` and listens on
`LLM_PRICING_RELOAD_CHANNEL` (default `llm-registry:reload`). The
5-minute periodic reload stays as a backstop, and a SIGTERM/SIGINT
handler closes the subscription cleanly.

The publisher side lives outside this PR — any process running in the
same Redis namespace can trigger a reload by `PUBLISH
llm-registry:reload <anything>`. Includes a `.server-changes/` note for
the changelog.

### Debounced reload

Bursts of publishes are coalesced. The first publish schedules a reload
at T+`LLM_PRICING_RELOAD_DEBOUNCE_MS` (default 1s); subsequent publishes
during that window are no-ops because the trailing reload picks up
everything when it queries the DB. Bounds reload rate to at most 1 per
debounce window regardless of publisher chattiness, so a runaway
upstream publisher can't fan out into a flood of full-table-scan
reloads.

## Test plan

- [ ] With `LLM_PRICING_RELOAD_PUBSUB_ENABLED=false` (default):
`redis-cli PUBSUB NUMSUB llm-registry:reload` returns `0` while the
webapp is up
- [ ] With it set to `true`: returns `>= 1`
- [ ] `redis-cli PUBLISH llm-registry:reload test` returns `1` (one
subscriber received) on a subscribed process
- [ ] Mutate an `LlmModel` row externally, publish on the channel,
observe the registry's match() picks up the change without waiting for
the 5-min tick
- [ ] Publish 100x in rapid succession; confirm only one reload fires
within the debounce window
2026-05-09 08:59:40 +01:00
James Ritchie f7a2bc7c96 Feat(webapp) filters UX update (#3451)
## Lots of filter UX improvements across lots of routes

### General
- Promoted important filters out of the "More filters" so they're always
visible
- SearchInput primitive is now reusable and Esc now clears the field (AI
filter input also clears with Esc)
- Tooltips + keyboard shortcuts on every primary filter button
- Brighter text on selected filter items / queue items 
- Filter dropdowns reordered for better hierarchy
- Removed debounce on Tasks page search for faster filtering

### Tasks page search
- Esc now clears the field
- ENTER submits a search to improve performance when you have lots of
tasks


https://github.com/user-attachments/assets/4b30521e-dbc4-4468-b2af-8c85bdfb9002

### Runs filters
- Moves Status and Tasks out of the More filters menu
- "Root only" toggle is set to false when you filter for a Task. This
state isn't stored and flips back to the stored value if filters are
cleared
<img width="1690" height="986" alt="CleanShot 2026-04-26 at 19 24 08@2x"
src="https://github.com/user-attachments/assets/b07da73c-140e-451f-a7bf-c32129317f63"
/>

### Batches filters
- General consistency improvements
<img width="1429" height="948" alt="CleanShot 2026-05-08 at 09 50 35"
src="https://github.com/user-attachments/assets/e5ec267f-2aa3-43ef-991e-93bf01bdaea5"
/>

### Schedules
- General consistency improvements
<img width="1567" height="1141" alt="CleanShot 2026-05-08 at 09 51 11"
src="https://github.com/user-attachments/assets/34b7da88-87c6-4e4d-a70f-fe13ea9f87ec"
/>

### Queues
- General consistency improvements
<img width="824" height="416" alt="CleanShot 2026-05-08 at 09 52 02"
src="https://github.com/user-attachments/assets/b4adc102-8192-4a68-b199-a175c2645a6c"
/>

### Waitpoint tokens
- General consistency improvements
<img width="941" height="363" alt="CleanShot 2026-05-08 at 09 52 19"
src="https://github.com/user-attachments/assets/d43aeb3f-7f80-454d-b183-fd077a4e3ff7"
/>

### Models
- General consistency improvements
<img width="1570" height="509" alt="CleanShot 2026-05-08 at 09 53 17"
src="https://github.com/user-attachments/assets/066d7646-4672-4cae-8ec0-e30a82889914"
/>

### AI metrics
- General consistency improvements
<img width="1568" height="624" alt="CleanShot 2026-05-08 at 09 53 43"
src="https://github.com/user-attachments/assets/fdfc4806-26fa-458d-a5ed-5c226b3bbc9f"
/>

### Logs
- General consistency improvements
<img width="1267" height="752" alt="CleanShot 2026-05-08 at 09 54 30"
src="https://github.com/user-attachments/assets/3e9ba871-b9dd-490e-aded-5d87134fd2bb"
/>

### Errors
- General consistency improvements
<img width="1568" height="670" alt="CleanShot 2026-05-08 at 09 54 50"
src="https://github.com/user-attachments/assets/fdda027a-e24f-4804-b4bb-203a6c2db960"
/>

### Query
- General consistency improvements
- History, Scope, Triggered (date) filters all have shortcut tooltips
- Scope filter now reuses the metrics ScopeFilter component
<img width="1566" height="716" alt="CleanShot 2026-05-08 at 09 55 22"
src="https://github.com/user-attachments/assets/0130b4a2-9daf-4edc-bada-3380aff4022a"
/>

### Dashboards
- General consistency improvements
- Scope filter gets nicer icons and a shortcut
- Nice icons for the Scope menu items
<img width="1567" height="769" alt="CleanShot 2026-05-08 at 09 56 10"
src="https://github.com/user-attachments/assets/7bea25f7-6c33-4d4a-a36d-3a1cb56afe09"
/>

### Custom dashboard
- General consistency improvements
- Add chart, Add title, and the kebab menu now have tooltips + shortcuts
<img width="1566" height="782" alt="CleanShot 2026-05-08 at 09 58 11"
src="https://github.com/user-attachments/assets/9df4db25-b2c0-43a2-b92f-00256337d5a9"
/>

### Environment variables
- General consistency improvements
<img width="1569" height="930" alt="CleanShot 2026-05-08 at 09 58 55"
src="https://github.com/user-attachments/assets/26e614b4-88e7-400b-aa6d-a96bad488fb8"
/>

### Preview branches
- General consistency improvements
<img width="1570" height="986" alt="CleanShot 2026-05-08 at 09 59 17"
src="https://github.com/user-attachments/assets/57a2b939-3670-4252-ab2c-d6dc65bdda1b"
/>
2026-05-08 17:35:09 +01:00
Iss 3cb6b5e9c4 docs(bun): note WebSocket limitation with remote browser connections (#3537) 2026-05-08 17:25:28 +01:00
Iss f8ddb766fa feat: Plain customer cards (#2933) 2026-05-08 11:51:57 -04:00
Daniel Sutton 61ae67cc02 fix(webapp): stop leaking exception messages on 5xx API responses (#3536)
When a webapp API route's catch-all 500 branch handles a non-typed
exception, it returns the raw `error.message` to the caller. If the
exception originates from an internal subsystem (the ORM client, an
infra dependency, etc.) the server-side error string is surfaced
verbatim in the response body — exposing implementation details the API
surface shouldn't carry.

The leak shows up in three shapes across the routes:

- `return json({ error: error.message }, { status: 500 })`
- `return json({ error: error instanceof Error ? error.message :
"Internal Server Error" }, { status: 500 })`
- ``return json({ error: `Internal server error: ${error.message}` }, {
status: 500 })``

(plus a couple of analogous neverthrow-Result variants on admin routes.)

## Fix

Across 19 webapp routes, replace each leaking branch with a generic body
(`"Something went wrong"` / `"Internal Server Error"` to match the
file's existing fallback) and add `logger.error(...)` so full visibility
is preserved server-side. Catch blocks that branch on typed user-input
errors (`ServiceValidationError`, `EngineServiceValidationError`,
`OutOfEntitlementError`, `PrismaClientKnownRequestError`) are left
intact — those messages are constructed deliberately and intended to be
customer-facing.

## Test plan

- [x] `pnpm run typecheck --filter webapp`
- [x] Per-route manual probe: inject a synthetic `Error` at the top of
the catch'd `try` block (or fake the wrapped call's rejection / Result
error), curl the route with the dev API key, confirm the response body
changed from the synthetic message verbatim → generic body. 21/21 leak
sites verified end-to-end.
- [x] 4xx-typed-error paths spot-checked: throwing
`ServiceValidationError` from inside the catch'd try still surfaces its
message at 422 as intended.
2026-05-08 16:25:53 +01:00
Daniel Sutton 749dc467f1 feat(webapp): link Sentry events to OTel traces via trace_id (#3531)
## Summary

Stamps the active OpenTelemetry `trace_id` and `span_id` onto every
Sentry event captured from the webapp, so engineers can copy a
`trace_id` from a Sentry issue and search for the corresponding trace in
any OTel-aware backend. Also adds an `otel_sampled` tag to indicate
whether the trace was head-sampled — a cheap signal for whether the link
will resolve to span data or hit a missing trace.

## Why

Sentry and OTel were OTel-disconnected: `apps/webapp/sentry.server.ts`
initialised Sentry with `skipOpenTelemetrySetup: true`, and no
error-capture site (`logger.server.ts`, the Remix-wrapped `handleError`,
the root `ErrorBoundary`) attached OTel context to the event. With many
spans/sec across services, getting from a Sentry issue to its trace was
guesswork.

## Approach

Single global Sentry event processor, registered immediately after
`Sentry.init`. On each event it reads
`trace.getActiveSpan()?.spanContext()` via `@opentelemetry/api`, then
writes:

- `event.contexts.trace.trace_id` and `event.contexts.trace.span_id`
(Sentry's native trace context fields)
- `event.tags.otel_sampled` = `"true"` | `"false"` (derived from
`traceFlags`)

If no active span (module-load errors, scheduled timers without a
context, primary cluster process), the processor returns the event
unmodified — Sentry's default propagation context fills in.

Implementation is co-located in `apps/webapp/sentry.server.ts` (no
separate helper module — `sentry.server.ts` is built standalone by
esbuild and a separate import would have required a new bundling step).
Helper functions are exported so the unit tests can reach them without
re-running `Sentry.init`.

## Non-goals (deliberate)

- No sample rate change. ~95% of Sentry events will carry a `trace_id`
that returns no spans in the tracing backend (head-sampled out). The
`otel_sampled` tag makes that obvious at a glance. Raising find-rate is
a separate conversation with cost trade-offs.
- No user/org tags or `Sentry.setUser` (would need auth-helper +
per-request scope wiring across multiple worker entrypoints — separate
ticket).
- Webapp image only. No changes to supervisor or CLI workers.

## Test plan

- [x] Unit tests in `apps/webapp/test/sentryTraceContext.server.test.ts`
— 9 tests covering: helper returns \`undefined\` with no active span;
returns \`traceId\`/\`spanId\`/\`sampled=true\` for a recording span;
returns \`sampled=false\` for a non-recording span; processor leaves the
event unchanged with no active span; processor stamps
\`trace_id\`/\`span_id\` onto \`contexts.trace\`; preserves existing
\`contexts.trace\` fields; tags \`otel_sampled\` correctly for both
sampled and non-sampled cases; never throws if \`@opentelemetry/api\`
access throws.
- [x] \`pnpm run typecheck --filter webapp\` passes.
- [x] Manually verified end-to-end against a sandboxed Sentry project:
confirmed both sampled and non-sampled traces correctly populate
\`contexts.trace.trace_id\` matching the OTel ids logged from the
loader, and the \`otel_sampled\` tag appears with the expected value.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 11:47:24 +01:00
Eric Allam 3e6458f9b5 ci(claude): switch Claude Code actions to ANTHROPIC_API_KEY (#3532)
## Summary

Both Claude Code workflows (`claude.yml` and `claude-md-audit.yml`)
authenticated via `CLAUDE_CODE_OAUTH_TOKEN`, which broke when the org
disabled Claude subscription access for Claude Code:

> Your organization has disabled Claude subscription access for Claude
Code · Use an Anthropic API key instead, or ask your admin to enable
access

This switches both workflows to `anthropic_api_key: ${{
secrets.ANTHROPIC_API_KEY }}` (secret already added to the repo).

## Test plan

- [ ] Confirm `📝 CLAUDE.md Audit` runs to completion on this PR
- [ ] Confirm `@claude` mention in a PR comment still triggers the
`Claude Code` workflow successfully
2026-05-07 11:52:58 +01:00
Matt Aitken 62e006617e fix(cli): fail attempt on uncaught exception instead of hanging to maxDuration (TRI-9117) (#3529)
⚒️ Publish Worker (v4) / build (supervisor) (push) Has been cancelled
When a Node EventEmitter (e.g. node-redis) emits an "error" event with
no
listener attached, Node escalates it to process.on("uncaughtException")
in
the task worker. The worker reported the error via the
UNCAUGHT_EXCEPTION
IPC event but did not exit, and the supervisor-side handler in
taskRunProcess only logged the message at debug level — leaving the
run()
promise orphaned until maxDuration fired and producing empty attempts
(durationMs=0, costInCents=0).

The supervisor now rejects the in-flight attempt with an
UncaughtExceptionError and gracefully terminates the worker (preserving
the OTEL flush window) on UNCAUGHT_EXCEPTION. The attempt fails fast
with
TASK_EXECUTION_FAILED, surfacing the original error name, message, and
stack trace, and falls under the normal retry policy. This mirrors the
existing indexing-side behavior in indexWorkerManifest. Apply the same
handling to unhandled promise rejections, which Node already routes
through uncaughtException by default.
2026-05-06 19:35:43 +01:00
Saadi Myftija 6e8b039a4e ci: GHCR commit-SHA tag, OCI labels, and build provenance (#3528)
- Tags webapp images by full commit SHA on `main` pushes
(`ghcr.io/triggerdotdev/trigger.dev:<sha>`) so any commit can be
resolved to a digest easily.
- Adds OCI labels (`source`, `revision`, `version`, `created`) so
`docker inspect`, vulnerability scanners, and
registry browsers see source/commit/version directly.
- Signs each pushed digest with SLSA build provenance via
`actions/attest-build-provenance@v4.1.0` (pinned by SHA), enabling `gh
attestation verify oci://...` against the source commit and workflow.
2026-05-06 09:40:15 +02:00
Eric Allam 31999afcaa perf(webapp): trim BackgroundWorker.metadata to the schedule slice on create (#3525)
Large deploys (projects with many tasks or source files) blocked the
webapp event loop for several seconds inside Prisma's client-side
serializer on `BackgroundWorker.create`, tail-latencying every other
in-flight request on the same Node process. The `metadata` JSON column
was being written with the full deploy manifest — every task's config,
every queue and prompt, and the full source of every file — all of which
already live on dedicated columns or in dedicated tables.

Fix: project the manifest to `{ packageVersion, contentHash, tasks: [{
id, filePath, schedule }] }` on insert. The only post-write read site is
`changeCurrentDeployment`, which feeds `tasks[].schedule` into
`syncDeclarativeSchedules` at deploy promotion. The retained top-level
keys and per-task `filePath` are kept solely so
`BackgroundWorkerMetadata.safeParse` still succeeds on read.

## Test plan

- [ ] Deploy a project with declarative schedules; verify schedules are
created on first deploy
- [ ] Modify / remove schedules across subsequent deploys; verify sync
- [ ] Roll back to a previous deploy; verify `changeCurrentDeployment`
re-syncs schedules
- [ ] Inspect `BackgroundWorker.metadata` on a fresh deploy — should be
a small object, not the full manifest
2026-05-05 14:52:36 +01:00
Daniel Sutton 14920ce2c4 fix(webapp): downgrade expected user-input error logs to warn (#3523)
`dac9c83bd` added `ignoreErrors: /^ServiceValidationError(?::|$)/` in
`apps/webapp/sentry.server.ts` to drop SVEs before they reach Sentry.
The
filter only matches when the captured event's *type* is
`ServiceValidationError`, but nine call sites in the webapp catch SVE
(and
analogous user-input error types — `OutOfEntitlementError`,
`CreateDeclarativeScheduleError`, `QueryError`) and call
`logger.error("wrapper message", { error: e })` *before* the type check.
The captured event is then titled with the wrapper message, with the
inner
error buried in `extra.error` — invisible to the SDK filter. Result: a
steady stream of expected user-input failures escalating as
`error`-level
events when they should be `warn`.

Each catch block now type-discriminates first, logs expected types at
`warn`,
and keeps unknown-error fall-throughs at `error`. For service sites that
wrap into SVE (`createBackgroundWorker`,
`createDeploymentBackgroundWorkerV4`),
the inner error is logged at `error` before wrapping — mirrors the
`waitpointCompletionPacket.server.ts` pattern from `dac9c83bd`.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 11:31:39 +01:00
nicktrn a8966a40ab fix(helm): bump clickhouse subchart 9.3.7 -> 9.4.4 (clickhouse 25.7.5) (#3524)
Fixes #3520. The bundled bitnami clickhouse subchart was pinned at
`9.3.7` (clickhouse `25.6.1-debian-12-r0`), which hits a memory-tracker
accounting bug under sustained ingest - the global counter overflows to
~7 EiB and every query gets rejected by OvercommitTracker until the pod
is restarted. Self-hosters running 4.0.5 through 4.4.5 are exposed
regardless of chart version since the subchart pin hadn't moved.

Bumping to `9.4.4` (clickhouse `25.7.5-debian-12-r0`) pulls in the
25.7.x memory-tracker fixes. This is also the latest publicly packaged
release at `oci://registry-1.docker.io/bitnamicharts` - that registry
has been frozen since 2025-08-28 (Bitnami catalog changes), but the
chart source remains under Apache 2 on `bitnami/charts`. The image
continues to resolve via `bitnamilegacy/clickhouse` per the existing
`values.yaml` override, since `bitnami/clickhouse` itself moved to
paid-only.

Verified locally: `helm dependency update` + `helm lint` + `helm
template` + kubeconform across all 57 rendered manifests. Rendered
statefulset image is
`docker.io/bitnamilegacy/clickhouse:25.7.5-debian-12-r0`.
2026-05-05 10:49:54 +01:00
Eric Allam 386b4f65ff feat(webapp): per-org S2 basin migration (#3516)
## Summary

Move from a single shared S2 basin to **per-org basins** with retention
tied to the org's billing plan. Stops S2 from deleting streams out from
under live chat sessions when basin retention fires before the chat
ends, and unlocks per-org cost attribution.

OSS / s2-lite installs are unaffected: provisioning is gated by
`REALTIME_STREAMS_PER_ORG_BASINS_ENABLED` (default `false`), and the
read precedence falls back to the global basin env var when an entity
has no stamped basin.

```
basin = run.streamBasinName ?? session.streamBasinName ?? env.REALTIME_STREAMS_S2_BASIN
```

## Design

Three nullable `streamBasinName` columns (`Organization`, `TaskRun`,
`Session`) plus a provisioner that idempotently creates the basin and
reconfigures retention on plan changes. The trigger and session-create
paths stamp the org's basin onto new rows; the realtime read path picks
the basin from the entity context.

Admin routes back-fill existing orgs and force-reconfigure a single org.

## Test plan

- [x] `pnpm run typecheck --filter webapp --filter @internal/run-engine`
- [x] Backfill admin route end-to-end (provision + DB stamp + S2 basin
config).
- [x] Reconfigure on plan change (all retention tiers).
- [x] chat.agent multi-turn drives streams into the per-org basin.
- [x] Legacy fallback when entity has no stamped basin.
- [x] Provisioner is a no-op when the flag is off.
2026-05-05 10:06:58 +01:00
nicktrn 3d418a9482 ci: add zizmor workflow security scanner (#3506)
Adds zizmor alongside the actionlint job from #3503. Both now run as
parallel jobs in a single `.github/workflows/workflow-checks.yml`,
triggered on `.github/workflows/**` and `.github/actions/**` changes.

Zizmor is configured with `unpinned-uses: hash-pin` policy via
`.github/zizmor.yml`, so any future unpinned action will fail CI.
Findings upload SARIF to the Security tab alongside CodeQL.

Bulk of the diff is cleanup of the findings zizmor surfaced on first
run. `zizmor --fix=all` handled most of them mechanically; the rest were
judgment calls.
2026-05-05 09:20:08 +01:00
Oskar Otwinowski 5dab2ae714 docs(private links): refresh PrivateLink setup screenshots, add ElastiCache IP-finding tip and NLB inbound-rules step (#3517) 2026-05-04 16:33:56 +02:00
James Ritchie 45ec23cc73 feat(webapp): app auto session logout (#3473)
<img width="2284" height="2028" alt="CleanShot 2026-05-01 at 18 53
50@2x"
src="https://github.com/user-attachments/assets/4f58cbb1-0168-40fb-a523-017f2ba625a1"
/>


## Performance
- **Per-request DB hit**: `getUserId` runs `getEffectiveSessionDuration`
(User lookup + Org `aggregate`) on *every* authenticated request,
including each fetcher poll. Consider caching the effective duration in
the session cookie with a short TTL (e.g. 60s) and revalidating in the
background.
- **Double session commit in `root.tsx`**: `getUser` already runs the
expiry check; then `commitAuthenticatedSessionLazy` commits the cookie
again. Fine, but doubles `Set-Cookie` headers on every page load — worth
a quick perf check.

## Correctness / Edge cases
- **Lazy backfill assumes a root.tsx hit first**: users whose first
post-deploy request is a fetcher/API route (`/resources/*`) skip the
backfill until they navigate to a page. Not a security hole, but
`getUserId` could backfill itself for completeness.
- **No upper bound on `Organization.maxSessionDuration`**: admin API
accepts `1` second, which would instant-logout every member on next
request. Add a `min(60)` (or `min(300)` to match the lowest user option)
to the Zod schema.
- **No clock-skew tolerance**: `isSessionExpired` is exact-millisecond.
Multi-instance deploys with skewed clocks could log users out a few
seconds early/late. Probably fine for the 5-min minimum, but worth
noting.

## Security
- **Auto-logout audit log lacks IP/orgId**: HIPAA forensics typically
wants source IP and which org context. Currently logs only `userId` +
path. IP isn't PII for audit purposes; orgIds help correlate. Add both.
- **Cookie `Max-Age` is 1 year regardless of user's setting**:
intentional (server-side `issuedAt` is the source of truth), but
reviewers will ask. Add a one-line comment on the cookie config
explaining why.

## API surface
- **`maxSessionDuration` is admin-PAT only**: no in-app UI for org
owners to set/change their own cap. If this is "Trigger staff sets it
during HIPAA onboarding", say so in the PR description; otherwise add an
org-settings UI.
- **Auto-submit dropdown has no confirmation**: misclicking "5 minutes"
immediately shortens the user's session window with no undo. Consider a
save button or 3-sec undo toast.

## Schema / migration
- **`User.sessionDuration NOT NULL DEFAULT 31556952`**: instant on PG
11+ (metadata-only), but call out in the PR description so reviewers
don't worry about a table rewrite on the User table.
- **No DB-level constraint matching `SESSION_DURATION_OPTIONS`**: if the
option list changes, existing users keep orphaned values. The dropdown's
tag-along behaviour hides this — fine for now, but if you ever drop an
option you'll need a backfill.

## UX
- **Session expiry only fires on next request**: an idle authenticated
tab keeps showing UI past the cap (until SSE/polling catches it, ~60s).
Add a client-side timer based on the user's effective duration that
triggers a fetcher to `/account` or `/logout` at expiry.
- **No "you were signed out" message on logout**: users hitting their
cap are bounced to `/` with no explanation. Was intentionally reverted
in this PR — call that out so reviewers don't request it.

## Tests
- Unit coverage on `sessionDuration.server.ts` is solid (215 lines).
Missing: integration test for `getUserId` → expired session → redirect
to `/logout`, and one for the loader's clamping fix (the most recent
bug). Add at least the second one to lock in the regression.

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 15:02:26 +01:00
nicktrn 8c56d85f90 fix(helm): supervisor OTLP endpoint resolves cross-namespace (#3504)
Reported by external contributor. The supervisor template hardcoded a
short DNS name for `OTEL_EXPORTER_OTLP_ENDPOINT`, which the supervisor
then propagates verbatim into runner pods
(`apps/supervisor/src/workloadManager/kubernetes.ts:196`). When runners
are spawned in a different namespace via
`supervisor.config.kubernetes.namespace`, the short name doesn't resolve
and span/log export silently fails - runs complete fine but the
dashboard shows nothing.

Same FQDN pattern the chart already uses for
`TRIGGER_WORKLOAD_API_DOMAIN` (line 203). Verified with `helm template
trigger . --namespace my-ns` - renders
`http://trigger-webapp.my-ns.svc.cluster.local:3030/otel`.

Cheers Niels
2026-05-02 09:58:27 +01:00
Eric Allam dc98ae4e28 chore: clean up stranded .server-changes/ files from v4.4.5 (#3509)
## Summary

Delete 34 `.server-changes/*.md` files that should have been cleaned up
automatically when v4.4.5 (#3406) was merged but were stranded by a
workflow race.

## Why these are stale

The `update-lockfile` job in `.github/workflows/changesets-pr.yml` is
what cleans up consumed `.server-changes/*.md` files on the release
branch. When v4.4.5 was merged on 2026-05-01, the post-merge workflow
run on `main` failed at `pnpm install --frozen-lockfile` (stale lockfile
in the merge commit), and `cancel-in-progress: true` cancelled the
in-flight run from the previous push — so `update-lockfile` never
reached the cleanup step.

Result: the 34 files described changes that v4.4.5 already shipped, and
they were re-appearing in the v4.4.6 release PR (#3501) under "Server
changes" plus showing up as deletions in its diff.

## What this PR keeps

- `fix-rollback-schedule-sync.md` — genuinely new for v4.4.6 (#3468),
the only server change introduced after v4.4.5
- `README.md`, `.gitkeep` — directory infrastructure
- `dev-cli-disconnect-md` — leaving alone (typo'd filename from March,
no `.md` extension, not picked up by the cleanup glob anyway)

## After merge

The next run of `changesets-pr.yml` will refresh #3501 with a "Server
changes" section that only lists the v4.4.6 entry, and the only
`.server-changes/` deletion in its diff will be
`fix-rollback-schedule-sync.md`.

## Related

- #3505 is the proper underlying fix — collapses the three-job graph
into a single atomic commit by `changesets/action` so this race can't
strand the cleanup again. This PR is just the one-time catch-up for the
files that already got stranded.
2026-05-02 09:55:08 +01:00
nicktrn cad8791859 chore: make changeset:version atomic (#3505)
Follow-up to the v4.4.5 release incident where the release PR (#3406)
was merged with a stale lockfile and stale Chart.yaml, breaking npm +
helm releases. The two automation jobs (`update-lockfile`,
`bump-chart-version`) got cancelled mid-flight by `cancel-in-progress`
when the merge fired the workflow again on `main`.

This restructures `changeset:version` so all the post-version-bump
fixups happen in the same script and end up in a single atomic commit on
`changeset-release/main`, via `changesets/action`'s normal commit step.

Pattern borrowed from Cloudflare workers-sdk, Astro, shadcn/ui.

## Before

```
push: main
└── release-pr (changeset version → bumps package.jsons, opens PR)
    └── update-lockfile (separate job, separate commit)
        └── bump-chart-version (separate job, separate commit)
```

Three jobs, three commits to the release branch.

## After

```
push: main
└── release-pr
    └── changesets/action runs:
          changeset version
          pnpm install --lockfile-only
          node scripts/bump-helm-chart.mjs
          node scripts/cleanup-server-changes.mjs
        ...all staged and committed as ONE commit by the action
```

One job, one commit.
2026-05-02 09:45:44 +01:00
nicktrn b19cf6df25 ci: add actionlint workflow (#3503)
Adds an `actionlint` job that runs on changes to `.github/workflows/**`
and `.github/actions/**`. Catches workflow bugs at PR time — expression
typos, deprecated runner labels, broken matrices, and shellcheck issues
in `run:` blocks.

Run from the official `docker://rhysd/actionlint` image, digest-pinned
alongside everything else.

Existing workflows had 6 shellcheck findings, all fixed.
2026-05-01 18:22:50 +01:00
nicktrn 57cca979c6 docs: refresh compute private beta page with may 1 updates (#3502)
Updates the compute private beta page with the May 1 release entry, plus
a deploy-time warning when `us-east-1-next` is the project default.

The new What's new entry, verbatim:

### May 1, 2026

- **Cold starts are faster across all machine sizes.** Every preset
starts faster, including `micro` and `small-1x` - there's no longer a
cold-start penalty for picking a smaller machine.
- **First runs after a deploy are faster on every preset.** Boot
snapshot creation is significantly quicker across the board, so the cold
path is consistently snappier.
- **`large-1x` and `large-2x` no longer hard-fail.** They're still not
recommended - cold-start performance trails the smaller presets and
we're ironing out reliability issues.

Follow-up to #3472 and #3479.
2026-05-01 17:32:13 +01:00
Eric Allam b65a04eb37 fix(cli,core): stop dev workers spinning at 100% CPU after parent CLI disconnect (#3491)
Orphaned `trigger-dev-run-worker` processes were pinning CPU at 100%
after the dev CLI exited — stuck in an uncaughtException feedback loop
where a closed IPC channel kept throwing `ERR_IPC_CHANNEL_CLOSED` back
into a handler that itself called `process.send`.

Fix:
- `ZodIpcConnection` no-ops sends when the channel is disconnected.
- Dev workers exit on `process.disconnect` instead of being re-parented
to init.
- All worker `uncaughtException` handlers route through a `safeSend`
guard so the handler can never re-enter itself.

Verified end-to-end: `kill -9` of the dev CLI now cleans up all child
workers within ~2s.
2026-05-01 17:11:06 +01:00
nicktrn 706a0b88c9 chore: upgrade pnpm to 10.33.2 with security hardening (#3489)
## Summary

- Upgrade pnpm from 10.23.0 → 10.33.2 (latest minor)
- Enable `blockExoticSubdeps: true` for supply-chain defense
- Update all version references across the repo

## Security improvements in 10.28.2+

- Path traversal protection in `directories.bin`
- Symlink-escape protection for `file:/git:` dependencies (prevents
reading `/etc/passwd`, `~/.ssh/...`)
- https://pnpm.io/settings#blockexoticsubdeps

## Files updated

- `package.json` — `packageManager` field
- `docker/Dockerfile` — 5 `corepack prepare` calls
- `apps/supervisor/Containerfile` — 1 `corepack prepare` call
- `pnpm-workspace.yaml` — added `blockExoticSubdeps: true`
- `CLAUDE.md`, `AGENTS.md`, `CONTRIBUTING.md`, `ai/references/repo.md` —
version references

## Verification

- `pnpm install --frozen-lockfile` succeeds (no lockfile regen needed)
- `pnpm install` (plain) produces zero lockfile diff
- All CI checks pass

Slack thread:
https://triggerdotdev.slack.com/archives/C061L2MHW93/p1777625600974279?thread_ts=1777622248.762639&cid=C061L2MHW93

https://claude.ai/code/session_01G759MUqmjsPh9k1qDxbdjG

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-01 16:24:26 +01:00
nicktrn 159408074a ci: swap buildjet/setup-node for actions/setup-node v6.4.0 (#3497)
Last action still firing the Node 20 deprecation warning after #3494.
`buildjet/setup-node@v4.0.4` (the latest tag) declares `runs: using:
'node20'` and the repo hasn't shipped a node24 update.

Workflows here run on `ubuntu-latest` (not buildjet runners), so the
buildjet fork wasn't giving us anything we don't get from
`actions/setup-node` directly. Swapping to `actions/setup-node@v6.4.0`
(node24 runtime) silences the warning.
2026-05-01 16:19:03 +01:00
Eric Allam 04bdf4b90b perf(webapp): throttle PAT + OAT lastAccessedAt writes to once per 5 min (#3493)
## Summary

Each successful PAT (`PersonalAccessToken`) or OAT
(`OrganizationAccessToken`) authentication issues a `prisma.X.update({
lastAccessedAt: new Date() })` to bump the timestamp. For tokens used at
high frequency (CLI clients, integrations) this generates a per-request
DB write that is mostly redundant — the `lastAccessedAt` field is only
surfaced on the settings page so users can decide which tokens to
revoke, and "within the last 5 minutes" is plenty of granularity for
that.

## Design

Replace each unconditional `update` with a conditional `updateMany`
whose `WHERE` requires the existing `lastAccessedAt` to be `NULL` or
strictly older than 5 minutes:

```ts
await prisma.personalAccessToken.updateMany({
  where: {
    id: personalAccessToken.id,
    OR: [
      { lastAccessedAt: null },
      { lastAccessedAt: { lt: new Date(Date.now() - PAT_LAST_ACCESSED_THROTTLE_MS) } },
    ],
  },
  data: { lastAccessedAt: new Date() },
});
```

The conditional runs inside the SQL `UPDATE`, so concurrent auths can't
race into a double-write.

No schema change. No migration. No new infrastructure. Throttle is a
hardcoded constant (`5 * 60 * 1000`) — easy to revisit.

## Test plan

- [x] `pnpm run typecheck --filter webapp`
- [x] `pnpm vitest run ./test/services/personalAccessToken.test.ts
./test/services/organizationAccessToken.test.ts` — 6/6 pass, verifying
the throttle `WHERE` clause is constructed correctly and the `update` is
skipped on token-not-found / wrong-prefix paths
2026-05-01 16:15:51 +01:00
nicktrn 1acdc506ea chore: bump helm chart version to 4.4.5 (#3500)
🧭 Helm Chart Release / lint-and-test (push) Has been cancelled
🧭 Helm Chart Release / release (push) Has been cancelled
Follow-up to v4.4.5 release. The `bump-chart-version` job on the release
PR was cancelled before it could run, so Chart.yaml was merged still
pointing at 4.4.4. The helm release job ([failed
run](https://github.com/triggerdotdev/trigger.dev/actions/runs/25218553990/job/73947054128))
caught it via its version-match guard.

Once this merges I'll re-run the helm release workflow manually.
2026-05-01 16:13:32 +01:00
devin-ai-integration[bot] 30bd567d48 fix: sync declarative schedules on deployment rollback (#3468)
##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

- Reviewed the code flow for deployment rollback
(`ChangeCurrentDeploymentService`) and confirmed it was missing schedule
sync
- Verified all 4 callers of `ChangeCurrentDeploymentService` (UI
rollback, UI promote, API promote, finalize deployment) are now covered
- Ran `pnpm run typecheck --filter webapp` — passes cleanly

---

## Changelog

When rolling back (or manually promoting) a deployment, declarative
schedules were not being synced to match the target deployment's worker
metadata. Schedules remained as configured by the most recent deployment
rather than reflecting the target version's schedule configuration.

This fix adds a call to `syncDeclarativeSchedules` in
`ChangeCurrentDeploymentService` after the deployment promotion is
updated. It parses the target deployment's stored
`BackgroundWorkerMetadata` to restore the correct schedule state. This
covers both rollback and promote paths (UI and API). Errors are handled
gracefully so they don't block the deployment change itself.

---

## Screenshots

N/A — backend-only change.

💯

Link to Devin session:
https://app.devin.ai/sessions/0debf012b58c4132be778f8ea88cd2b6

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: nick <55853254+nicktrn@users.noreply.github.com>
2026-05-01 15:39:19 +01:00
Eric Allam 139cccf27e fix: update pnpm-lock.yaml for v4.4.5 release (#3498)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
## Summary

The v4.4.5 release PR (#3406) was merged before the automated
lockfile-update job in
[\`changesets-pr.yml\`](.github/workflows/changesets-pr.yml) could push
its commit. As a result main now has \`package.json\` bumped to
\`4.4.5\` but \`pnpm-lock.yaml\` still pinned to \`4.4.4\`.

This blocks every subsequent \`pnpm install --frozen-lockfile\` run,
including:
- \`release.yml\` for v4.4.5 publish ([run
#25217579660](https://github.com/triggerdotdev/trigger.dev/actions/runs/25217579660))
— never published packages to npm
- \`changesets-pr.yml\` on the next push to main ([run
#25217579645](https://github.com/triggerdotdev/trigger.dev/actions/runs/25217579645))

## Root cause (from CI logs)

\`\`\`
ERR_PNPM_OUTDATED_LOCKFILE Cannot install with "frozen-lockfile" because
pnpm-lock.yaml is not up to date with <ROOT>/packages/build/package.json
- @trigger.dev/core (lockfile: workspace:4.4.4, manifest:
workspace:4.4.5)
\`\`\`

Regenerated via \`pnpm install --lockfile-only\` against current main.
The diff is exactly what the canceled \`update-lockfile\` job would have
produced:

- 12 \`workspace:4.4.4\` → \`workspace:4.4.5\` specifier bumps
- pnpm metadata refresh (deprecation annotations on transitive deps, one
optional \`bufferutil\` peer resolution on \`react-email\`)

No new direct dependencies, no version drops.

## Follow-ups (separate PRs)

1. **Re-run release.yml** via \`workflow_dispatch\` (\`type: release\`,
\`ref\` = merge commit on main once this lands) to actually publish
4.4.5 to npm.
2. **Workflow fix** to prevent recurrence: fold the lockfile update into
\`changeset:version\` so the \`release-pr\` job creates a single commit
with version bumps + lockfile in sync. Removes the race window where the
release PR is mergeable before \`update-lockfile\` runs.
2026-05-01 15:37:59 +01:00
nicktrn cb94382ffb ci: vouch dependabot[bot] (#3496)
Dependabot's first auto-bump PR (#3495) was auto-closed because
`dependabot[bot]` isn't in the vouch list and isn't exempt from the
require-draft check.

Two changes:

- Add `dependabot[bot]` to `.github/VOUCHED.td` so the vouch check
passes.
- Add `dependabot[bot]` to the require-draft exception in
`vouch-check-pr.yml` (alongside `devin-ai-integration[bot]`) so its PRs
aren't closed for being non-draft.

Without both, dependabot bumps will keep getting closed and we lose the
weekly action update flow that #3494 set up.
2026-05-01 15:30:11 +01:00
github-actions[bot] d825427cbc chore: release v4.4.5 (#3406)
## Summary
8 new features, 18 improvements, 11 bug fixes.

## Breaking changes
- Add server-side deprecation gate for deploys from v3 CLI versions
(gated by `DEPRECATE_V3_CLI_DEPLOYS_ENABLED`). v4 CLI deploys are
unaffected.
([#3415](https://github.com/triggerdotdev/trigger.dev/pull/3415))

## Improvements
- Add `--no-browser` flag to `init` and `login` to skip auto-opening the
browser during authentication. Also error loudly when `init` is run
without `--yes` under non-TTY stdin (previously default-and-exited
silently, leaving the project half-initialized). Both commands now show
an `Examples` section in `--help`.
([#3483](https://github.com/triggerdotdev/trigger.dev/pull/3483))
- Add `isReplay` boolean to the run context (`ctx.run.isReplay`),
derived from the existing `replayedFromTaskRunFriendlyId` database
field. Defaults to `false` for backwards compatibility.
([#3454](https://github.com/triggerdotdev/trigger.dev/pull/3454))
- Redact the `resolveWaitpoint` runtime log so it only emits `id` and
`type` instead of the full completed waitpoint. Previously the log
printed the entire waitpoint (including `output`) to stdout in
production runs, which could leak sensitive payloads. The value returned
by `wait.forToken()` is unchanged.
([#3490](https://github.com/triggerdotdev/trigger.dev/pull/3490))
- Add `SessionId` friendly ID generator and schemas for the new durable
Session primitive. Exported from `@trigger.dev/core/v3/isomorphic`
alongside `RunId`, `BatchId`, etc. Ships the
`CreateSessionStreamWaitpoint` request/response schemas alongside the
main Session CRUD.
([#3417](https://github.com/triggerdotdev/trigger.dev/pull/3417))
- Truncate large error stacks and messages to prevent OOM crashes. Stack
traces are capped at 50 frames (keeping top 5 + bottom 45 with an
omission notice), individual stack lines at 1024 chars, and error
messages at 1000 chars. Applied in parseError, sanitizeError, and OTel
span recording.
([#3405](https://github.com/triggerdotdev/trigger.dev/pull/3405))

## Server changes

These changes affect the self-hosted Docker image and Trigger.dev Cloud:

- Add a "Back office" tab to `/admin` and a per-organization detail page
at `/admin/back-office/orgs/:orgId`. The first action available on that
page is editing the org's API rate limit: admins can save a
`tokenBucket` override (refill rate, interval, max tokens) and see a
plain-English preview of the resulting sustained rate and burst
allowance. Writes are audit-logged via the server logger.
([#3434](https://github.com/triggerdotdev/trigger.dev/pull/3434))
- Optional `DEPLOY_REGISTRY_ECR_DEFAULT_REPOSITORY_POLICY` env var to
apply a default repository policy when the webapp creates new ECR repos
([#3467](https://github.com/triggerdotdev/trigger.dev/pull/3467))
- Ship the Errors page to all users, with a polish + bug-fix pass:
pinned "No channel" item in the Slack alert channel picker,
viewer-timezone alert timestamps via Slack's `<!date^>` token, Activity
sparkline peak tooltip, centered loading spinner and bug-icon empty
state on the error detail page, ellipsis on the Configure alerts
trigger.
([#3477](https://github.com/triggerdotdev/trigger.dev/pull/3477))
- Configure the set of machine presets to build boot snapshots for at
deploy time via `COMPUTE_TEMPLATE_MACHINE_PRESETS` (CSV of preset names,
default `small-1x`). Use `COMPUTE_TEMPLATE_MACHINE_PRESETS_REQUIRED`
(CSV, default = full PRESETS list) to scope which preset failures fail a
required-mode deploy. Optional preset failures are logged and don't
block the deploy.
([#3492](https://github.com/triggerdotdev/trigger.dev/pull/3492))
- Regenerating a RuntimeEnvironment API key no longer invalidates the
previous key immediately. The old key is recorded in a new
`RevokedApiKey` table with a 24 hour grace window, and
`findEnvironmentByApiKey` falls back to it when the submitted key
doesn't match any live environment. The grace window can be ended early
(or extended) by updating `expiresAt` on the row.
([#3420](https://github.com/triggerdotdev/trigger.dev/pull/3420))
- Add the `Session` primitive — a durable, task-bound, bidirectional I/O
channel that outlives a single run and acts as the run manager for
`chat.agent`. Ships the Postgres `Session` + `SessionRun` tables,
ClickHouse `sessions_v1` + replication service, the `sessions` JWT
scope, and the public CRUD + realtime routes (`/api/v1/sessions`,
`/realtime/v1/sessions/:session/:io`) including `end-and-continue` for
server-orchestrated run handoffs and session-stream waitpoints.
([#3417](https://github.com/triggerdotdev/trigger.dev/pull/3417))
- Add `KUBERNETES_POD_DNS_NDOTS_OVERRIDE_ENABLED` flag (off by default)
that overrides the cluster default and sets `dnsConfig.options.ndots` on
runner pods (defaulting to 2, configurable via
`KUBERNETES_POD_DNS_NDOTS`). Kubernetes defaults pods to `ndots: 5`, so
any name with fewer than 5 dots — including typical external domains
like `api.example.com` — is first walked through every entry in the
cluster search list (`<ns>.svc.cluster.local`, `svc.cluster.local`,
`cluster.local`) before being tried as-is, turning one resolution into
4+ CoreDNS queries (×2 with A+AAAA). Using a lower `ndots` value reduces
DNS query amplification in the `cluster.local` zone.
  
Note: before enabling, make sure no code path relies on search-list
expansion for names with dots ≥ the configured value — those names will
hit their as-is form first and could resolve externally before falling
back to the cluster search path.
([#3441](https://github.com/triggerdotdev/trigger.dev/pull/3441))
- Vercel integration option to disable auto promotions
([#3376](https://github.com/triggerdotdev/trigger.dev/pull/3376))
- Make it clear in the admin that feature flags are global and should
rarely be changed.
([#3408](https://github.com/triggerdotdev/trigger.dev/pull/3408))
- Admin worker groups API: add GET loader and expose more fields on
POST. ([#3390](https://github.com/triggerdotdev/trigger.dev/pull/3390))
- Add 60s fresh / 60s stale SWR cache to `getEntitlement` in
`platform.v3.server.ts`. Eliminates a synchronous billing-service HTTP
round trip on every trigger. Reuses the existing `platformCache` (LRU
memory + Redis) pattern already used for `limits` and `usage`. Cache key
is `${orgId}`. Errors return a permissive `{ hasAccess: true }` fallback
(existing behavior) and are also cached to prevent thundering-herd on
billing outages.
([#3388](https://github.com/triggerdotdev/trigger.dev/pull/3388))
- Show a `MicroVM` badge next to the region name on the regions page.
([#3407](https://github.com/triggerdotdev/trigger.dev/pull/3407))
- Increase default maximum project count per organization from 10 to 25
([#3409](https://github.com/triggerdotdev/trigger.dev/pull/3409))
- Merge execution snapshot creation into the dequeue taskRun.update
transaction, reducing 2 DB commits to 1 per dequeue operation
([#3395](https://github.com/triggerdotdev/trigger.dev/pull/3395))
- Add per-worker Node.js heap metrics to the OTel meter —
`nodejs.memory.heap.used`, `nodejs.memory.heap.total`,
`nodejs.memory.heap.limit`, `nodejs.memory.external`,
`nodejs.memory.array_buffers`, `nodejs.memory.rss`. Host-metrics only
publishes RSS, which overstates V8 heap by the external + native
footprint; these give direct heap visibility per cluster worker so
`NODE_MAX_OLD_SPACE_SIZE` can be sized against observed heap peaks
rather than RSS.
([#3437](https://github.com/triggerdotdev/trigger.dev/pull/3437))
- Tag Prisma spans with `db.datasource: "writer" | "replica"` so
monitors and trace queries can distinguish the writer pool from the
replica pool. Applies to all `prisma:engine:*` spans (including
`prisma:engine:connection` used by the connection-pool monitors) and the
outer `prisma:client:operation` span.
([#3422](https://github.com/triggerdotdev/trigger.dev/pull/3422))
- Clarify the cross-region intent in the Terraform and AI-prompt helpers
on the Add Private Connection page. Both already default
`supported_regions` to `["us-east-1", "eu-central-1"]`; added an inline
comment / parenthetical so the user understands why both regions are
listed (Trigger.dev runs in both, so the service must be consumable from
either).
([#3465](https://github.com/triggerdotdev/trigger.dev/pull/3465))
- Add `RUN_ENGINE_READ_REPLICA_SNAPSHOTS_SINCE_ENABLED` flag (default
off) to route the Prisma reads inside `RunEngine.getSnapshotsSince`
through the read-only replica client. Offloads the snapshot polling
queries (fired by every running task runner) from the primary. When
disabled, behavior is unchanged.
([#3423](https://github.com/triggerdotdev/trigger.dev/pull/3423))
- Stop creating TaskRunTag records and _TaskRunToTaskRunTag join table
entries during task triggering. The denormalized runTags string array on
TaskRun already stores tag names, making the M2M relation redundant
write overhead.
([#3369](https://github.com/triggerdotdev/trigger.dev/pull/3369))
- Stop writing per-tick state (`lastScheduledTimestamp`,
`nextScheduledTimestamp`, `lastRunTriggeredAt`) on `TaskSchedule` and
`TaskScheduleInstance`. The schedule engine now carries the previous
fire time forward via the worker queue payload, eliminating ~270K
dead-tuple-driven autovacuums per year on these hot tables and the
associated `IO:XactSync` mini-spikes on the writer. Customer-facing
`payload.lastTimestamp` semantics are unchanged.
([#3476](https://github.com/triggerdotdev/trigger.dev/pull/3476))
- Replace the expensive DISTINCT query for task filter dropdowns with a
dedicated TaskIdentifier registry table backed by Redis. Environments
migrate automatically on their next deploy, with a transparent fallback
to the legacy query for unmigrated environments. Also fixes duplicate
dropdown entries when a task changes trigger source, and adds
active/archived grouping for removed tasks. Moves BackgroundWorkerTask
reads in the trigger hot path to the read replica.
([#3368](https://github.com/triggerdotdev/trigger.dev/pull/3368))
- Public Access Tokens (PATs) minted before an API key rotation now keep
working during the 24h grace window. `validatePublicJwtKey` falls back
to any non-expired `RevokedApiKey` rows for the signing environment when
the primary signature check against the env's current `apiKey` fails.
The fallback query only runs on the failure path, so the hot success
path is unchanged.
([#3464](https://github.com/triggerdotdev/trigger.dev/pull/3464))
- Batch items that hit the environment queue size limit now fast-fail
without
retries and without creating pre-failed TaskRuns.
([#3352](https://github.com/triggerdotdev/trigger.dev/pull/3352))
- Show the cancel button in the runs list for runs in `DEQUEUED` status.
`DEQUEUED` was missing from `NON_FINAL_RUN_STATUSES` so the list hid the
button even though the single run page allowed it.
([#3421](https://github.com/triggerdotdev/trigger.dev/pull/3421))
- Reduce 5xx feedback loops on hot debounce keys by quantizing
`delayUntil`,
  adding an unlocked fast-path skip, and gracefully handling redlock
contention in `handleDebounce` so the SDK no longer retries into a herd.
([#3453](https://github.com/triggerdotdev/trigger.dev/pull/3453))
- Fix RSS memory leak in the realtime proxy routes. `/realtime/v1/runs`,
`/realtime/v1/runs/:id`, and `/realtime/v1/batches/:id` called `fetch()`
into Electric with no abort signal, so when a client disconnected mid
long-poll, undici kept the upstream socket open and buffered response
chunks that would never be consumed — retained only in RSS, invisible to
V8 heap tooling. Thread `getRequestAbortSignal()` through
`RealtimeClient.streamRun/streamRuns/streamBatch` to `longPollingFetch`
and cancel the upstream body in the error path. Isolated reproducer
showed ~44 KB retained per leaked request; signal propagation releases
it cleanly.
([#3442](https://github.com/triggerdotdev/trigger.dev/pull/3442))
- Fix memory leak where every aborted SSE connection pinned the full
request/response graph on Node 20, caused by `AbortSignal.any()` in
`sse.ts` retaining its source signals indefinitely (see
nodejs/node#54614, nodejs/node#55351). Also clear the
`setTimeout(abort)` timer in `entry.server.tsx` so successful HTML
renders don't pin the React tree for 30s per request.
([#3430](https://github.com/triggerdotdev/trigger.dev/pull/3430))
- Preserve filters on the queues page when submitting modal actions.
([#3471](https://github.com/triggerdotdev/trigger.dev/pull/3471))
- Fix Redis connection leak in realtime streams and broken abort signal
propagation.
  
**Redis connections**: Non-blocking methods (ingestData, appendPart,
getLastChunkIndex) now share a single Redis connection instead of
creating one per request. streamResponse still uses dedicated
connections (required for XREAD BLOCK) but now tears them down
immediately via disconnect() instead of graceful quit(), with a 15s
inactivity fallback.
  
**Abort signal**: request.signal is broken in Remix/Express due to a
Node.js undici GC bug (nodejs/node#55428) that severs the signal chain
when Remix clones the Request internally. Added getRequestAbortSignal()
wired to Express res.on("close") via httpAsyncStorage, which fires
reliably on client disconnect. All SSE/streaming routes updated to use
it. ([#3399](https://github.com/triggerdotdev/trigger.dev/pull/3399))
- Prevent dashboard crash (React error #31) when span accessory item
text is not a string. Filters out malformed accessory items in
SpanCodePathAccessory instead of passing objects to React as children.
([#3400](https://github.com/triggerdotdev/trigger.dev/pull/3400))
- Upgrade Remix packages from 2.1.0 to 2.17.4 to address security
vulnerabilities in React Router
([#3372](https://github.com/triggerdotdev/trigger.dev/pull/3372))
- Fix Vercel integration settings page (remove redundant section
toggles) and improve the Vercel onboarding flow so the modal closes
after connecting a GitHub repo and the marketplace `next` URL is
preserved across the GitHub app install redirect.
([#3424](https://github.com/triggerdotdev/trigger.dev/pull/3424))

<details>
<summary>Raw changeset output</summary>

# Releases
## @trigger.dev/build@4.4.5

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.5`

## trigger.dev@4.4.5

### Patch Changes

- Add `--no-browser` flag to `init` and `login` to skip auto-opening the
browser during authentication. Also error loudly when `init` is run
without `--yes` under non-TTY stdin (previously default-and-exited
silently, leaving the project half-initialized). Both commands now show
an `Examples` section in `--help`.
([#3483](https://github.com/triggerdotdev/trigger.dev/pull/3483))
-   Updated dependencies:
    -   `@trigger.dev/core@4.4.5`
    -   `@trigger.dev/build@4.4.5`
    -   `@trigger.dev/schema-to-json@4.4.5`

## @trigger.dev/core@4.4.5

### Patch Changes

- Add `isReplay` boolean to the run context (`ctx.run.isReplay`),
derived from the existing `replayedFromTaskRunFriendlyId` database
field. Defaults to `false` for backwards compatibility.
([#3454](https://github.com/triggerdotdev/trigger.dev/pull/3454))
- Redact the `resolveWaitpoint` runtime log so it only emits `id` and
`type` instead of the full completed waitpoint. Previously the log
printed the entire waitpoint (including `output`) to stdout in
production runs, which could leak sensitive payloads. The value returned
by `wait.forToken()` is unchanged.
([#3490](https://github.com/triggerdotdev/trigger.dev/pull/3490))
- Add `SessionId` friendly ID generator and schemas for the new durable
Session primitive. Exported from `@trigger.dev/core/v3/isomorphic`
alongside `RunId`, `BatchId`, etc. Ships the
`CreateSessionStreamWaitpoint` request/response schemas alongside the
main Session CRUD.
([#3417](https://github.com/triggerdotdev/trigger.dev/pull/3417))
- Truncate large error stacks and messages to prevent OOM crashes. Stack
traces are capped at 50 frames (keeping top 5 + bottom 45 with an
omission notice), individual stack lines at 1024 chars, and error
messages at 1000 chars. Applied in parseError, sanitizeError, and OTel
span recording.
([#3405](https://github.com/triggerdotdev/trigger.dev/pull/3405))

## @trigger.dev/python@4.4.5

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.5`
    -   `@trigger.dev/build@4.4.5`
    -   `@trigger.dev/sdk@4.4.5`

## @trigger.dev/react-hooks@4.4.5

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.5`

## @trigger.dev/redis-worker@4.4.5

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.5`

## @trigger.dev/rsc@4.4.5

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.5`

## @trigger.dev/schema-to-json@4.4.5

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.5`

## @trigger.dev/sdk@4.4.5

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.5`

</details>

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-01 15:13:11 +01:00
nicktrn ee3887a321 feat(webapp): configurable deploy template machine presets (#3492)
The webapp's compute template creation hardcoded a single machine preset
(`small-1x`) at deploy time, regardless of which presets a project
actually uses. Tasks running on any other preset paid full cold-snapshot
creation cost on first run.

Two new env vars:

- `COMPUTE_TEMPLATE_MACHINE_PRESETS` - CSV of preset names to build boot
snapshots for during deploy. Defaults to `small-1x` so existing deploys
don't change behavior.
- `COMPUTE_TEMPLATE_MACHINE_PRESETS_REQUIRED` - CSV of presets whose
failure fails a required-mode deploy. Defaults to the full `PRESETS`
list. Optional preset failures are logged but don't block the deploy.

The compute client now sends the multi-config request shape; the service
evaluates per-preset outcomes against the required set and surfaces a
combined failure message when a required preset fails.

Both env vars are validated at boot via the env schema - unknown preset
names or `_REQUIRED` entries that aren't a subset of `_PRESETS` fail
loudly at startup rather than silently per-deploy.
2026-05-01 15:10:26 +01:00
nicktrn 39baea8094 ci: pin actions to SHAs and add dependabot config (#3494)
Most actions in this repo were several major versions behind, which is
why every CI run has been emitting Node 20 deprecation warnings.

Pinning every action to a commit SHA (with the version as a trailing
comment) means each CI run uses the exact code that was reviewed when
the bump landed, instead of whatever a maintainer last pointed the major
tag at. Dependabot is configured to group all action bumps into one
weekly PR with a 7-day cooldown.

Worth flagging:

- The Claude Code action ships ~daily but the model is set separately
via `--model` in `claude_args`, so SHA-pinning the action gives
reproducibility without locking the model.
- The kubeconform container is digest-pinned
(`docker://image:tag@sha256:...`). Dependabot's github-actions ecosystem
doesn't track `docker://` references ([explicit TODO in
dependabot-core](https://github.com/dependabot/dependabot-core/blob/main/github_actions/lib/dependabot/github_actions/file_parser.rb)),
so it needs manual bumps either way - but the digest pin protects
against tag repointing for free.
2026-05-01 14:08:43 +00:00
Matt Aitken 7c7d785552 Don't log waitpoint output when resolving (#3490)
Redact the `resolveWaitpoint` runtime log so it only emits `id` and
`type` instead of the full completed waitpoint. Previously the log
printed the entire waitpoint (including `output`) to stdout in
production runs, which could leak sensitive payloads. The value returned
by `wait.forToken()` is unchanged.
2026-05-01 12:37:57 +01:00
DKP 1dfd595986 fix(webapp): invalid HTML nesting in errors Activity tooltip (#3488)
The Activity peak count tooltip in the errors list rendered a `<button>`
(from `SimpleTooltip`'s default `TooltipTrigger`) inside the row's `<a>`
link (`TableCell to={errorPath}`). Interactive content nested inside
other interactive content is invalid HTML and triggers accessibility
warnings. Adding `asChild` to `SimpleTooltip` makes the existing
`<span>` the trigger directly, removing the nested `<button>`.
2026-05-01 10:31:25 +01:00
nicktrn e2b9e0f9f5 feat(cli-v3): add --no-browser flag and examples to init/login --help (#3483)
Closes the most common friction point hit while setting up a fresh
project from an agent harness: the CLI auto-opens the user's default
browser during auth and there is no supported way to skip it (the
existing `isLinuxServer()` path only triggers when `xdg-open` is missing
entirely).

`--no-browser` on `login` and `init` prints the URL and waits to be
visited from any browser. The flag threads through the embedded
`login()` call inside `init`.

While here:
- `init` now errors loudly when stdin is non-TTY without `--yes` instead
of default-and-exiting silently at the first prompt (which left the
project half-initialized: deps installed, no config or example file).
- Both commands gain an `Examples` block in `--help` rendered between
the description and the arguments/options list, so `--help | head`
surfaces the common invocations.

Other commands also call `login()` embedded and would benefit from
`--no-browser` too, but kept this PR scoped to the cases the friction
log called out.
2026-05-01 09:39:22 +01:00
Eric Allam ac7177d61f feat(schedule-engine): stop persisting per-tick schedule state (#3476)
## Summary

Each scheduled-task tick previously issued **3 Prisma `UPDATE`s**
against
`TaskSchedule.lastRunTriggeredAt`,
`TaskScheduleInstance.lastScheduledTimestamp`,
and `TaskScheduleInstance.nextScheduledTimestamp`. All three were pure
denormalization — every value can be derived without persisting.

After this PR `TaskSchedule` and `TaskScheduleInstance` become **near
read-only**:
writes happen only on schedule create / update / delete (rare admin
actions),
so the per-tick autovacuum churn on these hot tables disappears.

## Design

The previous fire time travels forward through the **schedule worker
payload**,
not through the database. Concretely:

- The `schedule.triggerScheduledTask` worker payload gains an optional
  `lastScheduleTime: z.coerce.date().optional()` field.
- When the engine fires a schedule, it re-enqueues the next tick with
  `lastScheduleTime = scheduleTimestamp` (the just-fired time).
- When the next tick dequeues, `payload.lastTimestamp` is sourced from
`params.lastScheduleTime` directly. No DB round-trip, no cron-derivation
  drift across DST boundaries, no caveats around recently-edited cron
  expressions.

`payload.lastTimestamp` keeps its `Date | undefined` SDK shape.
First-ever
fires still report `undefined`, so customer `if
(!payload.lastTimestamp)`
first-run patterns keep working.

For Redis jobs that were enqueued **before** this change (which lack
`lastScheduleTime` in their payload), the engine falls back to
`instance.lastScheduledTimestamp` once. Once those drain, the column is
never read again. Revert is code-only; the columns stay in place and can
be dropped in a follow-up once the rollout is stable.

## Files

- `internal-packages/schedule-engine/*` — engine refactor,
`workerCatalog`
schema field, `TriggerScheduleParams` extension, tests updated to assert
  on the worker-payload flow rather than DB readbacks.
- `internal-packages/database/prisma/schema.prisma` — `/// @deprecated`
  triple-slash docstrings on the three columns. No migration.
- `apps/webapp/app/presenters/v3/ScheduleListPresenter.server.ts` —
drops
the `lastRunTriggeredAt` Prisma select; "Last run" cell is approximated
from the cron expression's previous slot, gated on `schedule.createdAt`
so brand-new schedules show "–". UI is best-effort; the runs page is the
  source of truth.
- `apps/webapp/app/v3/utils/calculateNextSchedule.server.ts` — adds a
  `previousScheduledTimestamp` helper for the UI cell above. Public API
responses (`api.v1.schedules.*`) already compute `nextRun` from cron and
  don't expose `lastTimestamp` — no public API change.
- `references/scheduled-tasks/` — new reference project with declarative
  schedules at multiple cadences and three throw-on-fail validators
(`first-fire-detector`, `interval-validator`, `upcoming-validator`) for
  E2E-verifying the worker-payload flow.

Refs TRI-8891

## Test plan

- [x] `pnpm run typecheck --filter @internal/schedule-engine --filter
webapp`
- [x] `pnpm run build --filter @trigger.dev/core`
- [x] `pnpm run test --filter @internal/schedule-engine` — integration
test
asserts first-fire `lastTimestamp === undefined`, second fire carries
      the previous fire's timestamp exactly.
- [x] E2E against local webapp via `references/scheduled-tasks`:
- Fresh schedules attached → all three deprecated columns stay `NULL`
after
    multiple fires.
  - Redis payload at second fire contains
    `"lastScheduleTime":"<previous fire timestamp>"`.
- `TaskRun.payload` and the every-minute task's returned output both
confirm
`lastTimestamp = null` on first fire and `lastTimestamp = <prev fire>`
on
    second fire, exactly 60s apart.
  - All three throw-on-FAIL validators completed successfully on every
    non-first fire.
- [x] Schedules REST API end-to-end (`POST` / `GET` / `PUT` / `activate`
/
`deactivate` / `DELETE`) — `nextRun` recomputed live from cron + tz on
      every response, no reads of deprecated columns.
2026-05-01 08:22:39 +01:00
DKP 19c16759f6 feat(webapp): errors page polish and GA rollout (#3477)
## What this does

Polish + bug-fix pass on the Errors page so it can ship to everyone.
Touches the Slack alert config UX, errors list, error detail page, and
unhides the SideMenu entry for non-admins.
## Decisions

**"No channel" item over standalone Remove button**
Chose pinning a `<XMarkIcon /> No channel` `SelectItem` above the
channel list. Rejected the standalone "Remove channel" link in a
`<Hint>` — color/hover behaviour clashed with the sibling `<TextLink>`,
and "channel selection" is the right context for clearing. Server action
already deletes the channel when `slackChannel=""` is submitted.

**Slack `<!date^>` token over per-user TZ field for alerts**
Chose Slack's native `<!date^TS^…>` token so each viewer sees timestamps
in their own timezone (UTC fallback). Rejected per-user/per-org TZ
schema work — works for multi-region channels for free. Email/dashboard
TZ source-of-truth filed as TRI-8885 / TRI-8886.

**Make errors GA**
2026-04-30 17:56:51 +01:00
nicktrn 24de77c4ab docs: call out compute private beta limitations (#3479)
Updates the private beta page with current caveats so beta orgs aren't
surprised.

Refs TRI-8900.
2026-04-30 17:40:10 +01:00
Eric Allam 04b4d85f50 fix(webapp): allow JWT auth on POST /api/v1/sessions (#3474)
## Summary

`POST /api/v1/sessions` was secret-key-only because the customer browser
flow runs through `chat.createStartSessionAction` (server-side, holds
the secret key). But the `cli-v3` MCP `start_agent_chat` tool is itself
a server-side surface — developer's CLI/IDE acting as their own server —
and only holds a JWT minted from the user's PAT. Without JWT support on
this route the entire MCP agent toolkit (`start_agent_chat`,
`send_agent_message`, `close_agent_chat`) is blocked at session
creation.

Add `allowJWT: true` plus an `authorization` block requiring the
`write:sessions` (or `admin`) super-scope.

## Why a wildcard `sessions` resource

Resource scoping by `taskIdentifier` isn't possible at auth-resolve time
— action routes don't pass `body` to the `resource` callback, and the
task name only lives in the body. So the resource is `sessions: "*"` and
the super-scope does the actual gating. The JWT-issuer (cli-v3 MCP,
customer servers wrapping their own auth helpers, etc.) decides which
scopes to mint, which is where per-task narrowing lives.

## Test plan

- [x] Verified end-to-end against local:
`mcp__trigger__start_agent_chat` → `send_agent_message("pong")` →
`send_agent_message("echo")` → `close_agent_chat` all succeed. Two
assistant turns reuse the same runId (continuation in the idle window).
- [ ] Browser-mediated `chat.createStartSessionAction` flow continues to
work unchanged (still uses secret-key path under the hood).
- [ ] Loader (GET) and other session routes — unchanged, no scope drift.

## Notes

This unblocks T17 in the [ai-chat e2e smoke
catalog](https://github.com/triggerdotdev/trigger.dev/blob/feature/tri-7532-ai-sdk-chat-transport-and-chat-task-system/.claude/skills/ai-chat-e2e/SMOKE-TESTS.md)
(which lives in the feature branch's skill catalog, not this repo).
Pairs with the cli-v3 MCP fix on the feature branch (`feat: AI SDK
custom useChat transport & chat.task harness`, PR #3173) — that PR's
`agentChat.ts` change makes the call shape correct (`taskIdentifier` +
`triggerConfig`); this PR opens the door for the JWT to actually pass.
2026-04-30 09:56:45 +01:00
ThullyoCunha f1736595cd feat(webapp): apply default repository policy on ECR repo creation (#3467)
🚀 Publish Trigger.dev Docker / units (push) Failing after 13m3s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 13m3s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
## Summary

Self-hosters that operate the webapp's ECR account separately from the
account running the EKS workers (e.g., a shared platform account that
hosts the registry plus per-team accounts that host clusters) currently
hit a 403 Forbidden the first time **any** project is deployed:

```
Failed to pull image "<acct-A>.dkr.ecr.<region>.amazonaws.com/<namespace>/proj_…:…":
unexpected status from HEAD request to .../v2/.../manifests/sha256:…: 403 Forbidden
```

`ensureEcrRepositoryExists` in
`apps/webapp/app/v3/getDeploymentImageRef.server.ts` calls
`CreateRepository` and `PutLifecyclePolicy`, but never
`SetRepositoryPolicy` — so the new repo inherits the AWS default (only
the registry-owner account can read/pull). Workers in the cluster
account get 403 every single deploy. The only workarounds today are
running a one-off post-create script or pre-creating every repo by hand.

## Proposed change

Add an optional env var:

```
DEPLOY_REGISTRY_ECR_DEFAULT_REPOSITORY_POLICY  (V4 mirror: V4_DEPLOY_REGISTRY_ECR_DEFAULT_REPOSITORY_POLICY)
```

Raw IAM policy JSON. When set, the webapp calls `SetRepositoryPolicy`
immediately after `CreateRepository` so every new repo carries that
policy from creation. Operators control the principal/actions; we don't
bake in any opinions about cross-account boundaries.

Example value (for the typical self-host case — grant pull to the
cluster account):

```json
{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "AllowClusterAccountPull",
    "Effect": "Allow",
    "Principal": {"AWS": "arn:aws:iam::<cluster-account-id>:root"},
    "Action": [
      "ecr:GetDownloadUrlForLayer",
      "ecr:BatchGetImage",
      "ecr:BatchCheckLayerAvailability"
    ]
  }]
}
```

## Why env var (not a chart-level field)

- Mirrors the shape of the sibling vars (`DEPLOY_REGISTRY_ECR_TAGS`,
`DEPLOY_REGISTRY_ECR_ASSUME_ROLE_ARN`, etc.) which are already
operator-supplied via `webapp.extraEnvVars` in self-host setups.
- Cloud is unaffected — the env var is optional, unset by default;
existing behavior unchanged.
- Existing repos are unaffected — only newly-created repos get the
policy.
- `RepositoryCreationTemplate` from the AWS provider isn't an
alternative here: it only applies to repos created via
pull-through-cache or replication, not to `ecr:CreateRepository` API
calls.

## Implementation

- `apps/webapp/app/env.server.ts` — declare
`DEPLOY_REGISTRY_ECR_DEFAULT_REPOSITORY_POLICY` and the V4 fallback.
- `apps/webapp/app/v3/registryConfig.server.ts` — propagate
`ecrDefaultRepositoryPolicy` to `RegistryConfig`.
- `apps/webapp/app/v3/getDeploymentImageRef.server.ts` —
`createEcrRepository` accepts the policy; if set, calls
`SetRepositoryPolicy` after `PutLifecyclePolicy`.
- `docs/self-hosting/env/webapp.mdx` — documentation row added under
**Deploy & Registry**.

## Verification

Verified end-to-end against a self-hosted Trigger.dev on EKS where the
ECR account is separate from the cluster account:

- **Without the env var** (current `main`): the new project's first run
pod stays in `ImagePullBackOff` with `403 Forbidden`.
- **With the env var set** to a JSON granting
`ecr:BatchGetImage`/`GetDownloadUrlForLayer`/`BatchCheckLayerAvailability`
to the cluster account: a fresh `trigger.dev deploy --env prod` followed
by a `hello-world` run completes in ~5s end-to-end on the first try.

Manually also confirmed that existing repos are untouched (the call only
fires inside `createEcrRepository`, which only runs when
`DescribeRepositories` returned `RepositoryNotFoundException`).

## Out of scope

- Chart values surface for this — operators already pass the existing
ECR vars via `webapp.extraEnvVars`, so this follows the same pattern.
Happy to add a first-class chart field in a follow-up if that's the
preferred direction.
- IAM-policy validation in the webapp — we forward the JSON verbatim to
AWS and surface AWS's error messages on misuse, matching how
`DEPLOY_REGISTRY_ECR_TAGS` is handled today.

This is a draft pending CI / CodeRabbit pass — happy to iterate on
direction (e.g., split into per-action env vars, or extend the chart
values schema) if any of the above choices feels off.

---------

Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2026-04-29 15:17:23 +01:00
nicktrn 8e368cc3d7 docs: add compute private beta page (#3472) 2026-04-29 13:42:29 +01:00
nicktrn 226b93edf9 fix(webapp): preserve filters on queues page action redirects (#3471)
Queues page action handler was rebuilding the redirect URL with only
`?page=`, so any pause/resume/override modal confirmation wiped the
user's search query. With hundreds of queues filtered down to a handful,
every confirmation dropped you back to the unfiltered list - and
pagination still pointed at the previous numeric page, so you'd land on
a different slice than you came from.

Swap the manual rebuild for `url.search` so the full querystring
(including any future filter params) flows through. Drops the now-unused
`SearchParamsSchema.parse` call inside `action`; the loader still
validates on the way back.
2026-04-29 13:06:14 +01:00
devin-ai-integration[bot] b0131352f6 fix(webapp): constrain usage chart height to 320px (#3469)
##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

Ran the webapp locally with `CLOUD_ENV=development` and verified the
usage page chart height at different viewport sizes. The chart now
renders at a fixed 320px height instead of expanding to fill the
viewport.

---

## Changelog

Fix the "Usage by day" chart on the usage settings page taking up 100%
of the viewport height.

The regression was introduced in PR #2905 when the `UsageChart` was
migrated from using `ChartContainer` directly (with `max-h-96 min-h-40
w-full`) to the new `Chart.Root` compound component. The
`ChartContainer` base class includes `aspect-video` (16:9 ratio), and
the `max-h-96` constraint was lost during migration, causing the chart
to scale its height based on viewport width.

Fix: wrap `Chart.Root` in a fixed-height container (`h-80` = 320px) and
use the `fillContainer` prop, which applies `!aspect-auto` to override
the `aspect-video` ratio.

---

## Screenshots

Before (chart fills entire viewport):

![before](https://app.devin.ai/api/presigned_proxy?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcmdfaWQiOiJvcmctMWYzMWQ4ZTQ4NjI3NGRjYTg5MDM5MGQ4ZWY2YWVjNzQiLCJ1c2VyX2lkIjpudWxsLCJidWNrZXRfbmFtZSI6ImRldmluYXR0YWNobWVudHMiLCJidWNrZXRfa2V5IjoiYXR0YWNobWVudHNfcHJpdmF0ZS9vcmctMWYzMWQ4ZTQ4NjI3NGRjYTg5MDM5MGQ4ZWY2YWVjNzQvOGRhMTdiMDEtZThiOC00MGI4LWIxOGUtNmJmMzc0ZjYzYjMxIiwiaWF0IjoxNzc3NDU1Mjg2LCJleHAiOjE3NzgwNjAwODYsImZpbGVuYW1lIjoiY3VycmVudC1icm9rZW4ucG5nIn0.LU6idghnalKHL2ZAJGVxWTmPnuUgoL-6QNRdk3bDJqg)

After (chart constrained to 320px):

![after](https://app.devin.ai/api/presigned_proxy?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcmdfaWQiOiJvcmctMWYzMWQ4ZTQ4NjI3NGRjYTg5MDM5MGQ4ZWY2YWVjNzQiLCJ1c2VyX2lkIjpudWxsLCJidWNrZXRfbmFtZSI6ImRldmluYXR0YWNobWVudHMiLCJidWNrZXRfa2V5IjoiYXR0YWNobWVudHNfcHJpdmF0ZS9vcmctMWYzMWQ4ZTQ4NjI3NGRjYTg5MDM5MGQ4ZWY2YWVjNzQvMDliN2E2YzktZjIzYi00YTJiLWE0N2EtMTk3NzBhZGU1MmU3IiwiaWF0IjoxNzc3NDU1Mjg2LCJleHAiOjE3NzgwNjAwODYsImZpbGVuYW1lIjoib3B0aW9uLWItaDgwLWZpbGxDb250YWluZXIucG5nIn0.uKi3Yw4Z6GvoNuEVO8B4hwSvvHtyYzXUhtSEHcuSvTY)

💯

Link to Devin session:
https://app.devin.ai/sessions/6e5ed40516d3448db85950feb1115ab3

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: nick <55853254+nicktrn@users.noreply.github.com>
2026-04-29 10:56:35 +01:00
Eric Allam 99dfee3a57 fix(webapp): honor RevokedApiKey grace window for public access tokens (#3464)
## Summary

Follow-up to #3420. PATs (public access tokens) minted before an API key
rotation 401'd immediately on the realtime stream endpoints, even though
the rotation flow advertises a 24h overlap. This fixes the gap.

## Root cause

PATs are JWTs signed with the env's `apiKey` at mint time. When that
secret is rotated, `validatePublicJwtKey`
(`apps/webapp/app/services/realtime/jwtAuth.server.ts`) only verifies
the signature against `environment.parentEnvironment?.apiKey ??
environment.apiKey` — i.e. the env's *current* canonical key. Any PAT in
the wild signed with the previous key fails signature verification →
401, even within the grace window.

#3420 wired up the grace-window fallback in two places —
`findEnvironmentByApiKey` (raw secret-key auth) and `api.v1.auth.jwt.ts`
(signs new JWTs with the canonical key when minting from an old one) —
but the *verify* path for already-issued PATs was never updated.

In a typical app, `POST /api/v1/tasks/.../trigger` (Bearer secret) keeps
working through rotation because that path has the fallback, but `GET
/realtime/v1/streams/run_*/...` and `POST
/realtime/v1/streams/run_*/input/...` 401 for runs that were already in
flight when the rotation happened.

## Fix

After the primary `validateJWT` against the env's current `apiKey`, fall
back to non-expired `RevokedApiKey` rows for the signing env (parent env
when the request is against a child) — but **only on the failure path**,
so the hot success path is unchanged. Uses `$replica` to match the rest
of the auth path.

Symmetrical to the `findEnvironmentByApiKey` two-step from #3420.

## Changes

- `apps/webapp/app/services/realtime/jwtAuth.server.ts` —
`validateAgainstRevokedApiKeys` helper invoked only on `!result.ok`
- `apps/webapp/app/models/runtimeEnvironment.server.ts` —
`findEnvironmentById` also selects `parentEnvironment.id` so we can
scope the revoked-keys lookup to the correct env

## Test plan

E2E verified locally via curl against `GET /realtime/v1/runs/{runId}`
(PAT-authenticated):

- [x] Pre-rotation, PAT signed with K1 → **200** with run body
- [x] Simulate rotation (insert `RevokedApiKey` row + flip env `apiKey`
to K2 in a single transaction, mirroring `regenerateApiKey`)
- [x] Same PAT (K1) within grace window → **200** with run body —
fallback hits
- [x] Fresh PAT signed with K2 → **200** — current key still works
- [x] Set `RevokedApiKey.expiresAt` to past → **401** — fallback finds
no live row
- [x] Bogus signature (no rotation) → **401**
- [x] Cleanup verified: env `apiKey` restored, `RevokedApiKey` row
deleted
- [x] `pnpm run typecheck --filter webapp` passes
2026-04-29 10:00:33 +01:00
Eric Allam dac9c83bdc chore(webapp,run-engine): downgrade boundary log noise to warn (#3462)
## Summary

Several boundary catches and customer-input validation paths were
logging at `error` level for failures the system already handles
gracefully — disconnect on auth failure, return undefined, skip retries,
etc. This batch routes them to `warn` (which stays in stdout) or counts
them as OTel metrics, so visibility is preserved without surfacing them
as alerts.

## Changes

**New helper / pattern:**
- `apiBuilder.server.ts` — `logBoundaryError(message, error, url)`
inspects the inner error type at loader/action boundary catches;
downgrades to `warn` for `AbortError`, `ServiceValidationError`, and
`EngineServiceValidationError`.
- `platform.v3.server.ts` — `platform_client.failures_total` OTel
counter with `{function, kind}` labels; helper
`recordPlatformFailure(fn, kind)` replaces the previous error-level
logging across all `BillingClient` wrappers.

**Log-level downgrades:**
- `handleSocketIo.server.ts` — `Worker authentication failed` → warn
(system disconnects on failure; refs TRI-8863)
- `waitpointSystem.ts` — when `runStatus === "CANCELED"` in the
suspended-without-checkpoint branch, skip the throw and warn instead
(benign cancel-vs-resume race, nothing to resume)
- `runAttemptSystem.ts` — `flushedMetadata` parse/validate failures →
warn (customer-side data shape, system returns gracefully)
- `batch-queue/index.ts` — final-attempt failures with
`result.skipRetries` → warn (callbacks already opted out of retry, e.g.
queue size limit hit)
- `queryPerformanceMonitor.server.ts` — slow queries → warn
(observability signal, not an application error)
- `timeoutDeployment.server.ts` — deployment-state mismatch in the
timeout job → warn (timeout-vs-completion race)

**Inner error preservation:**
- `waitpointCompletionPacket.server.ts` — `logger.error(uploadError)`
before throwing the `ServiceValidationError` wrapper, so the underlying
upload error stays visible.

## Why

The pattern across all of these is the same: a boundary log treated any
thrown/returned error as `error` regardless of cause, even when the
cause was an expected, system-handled condition (client disconnect,
customer quota, race condition, schema validation of customer data).
That made the logs noisy and made it harder to spot real bugs.

Where the underlying signal is still useful operationally (slow queries,
billing call failures), we route it to OTel metrics with low-cardinality
labels so dashboards and alerts can be tuned independently of error
logs.

## Test plan

- [ ] `pnpm run typecheck --filter webapp`
- [ ] `pnpm run build --filter @internal/run-engine`
- [ ] Trigger a run on hello-world and verify task lifecycle is
unaffected
- [ ] Cancel a suspended run and verify the cancel-while-suspended
branch in `waitpointSystem.ts` returns `{status: "skipped"}` instead of
throwing
- [ ] Confirm `platform_client.failures_total` counter shows up in
metrics with `{function, kind}` labels when the billing client errors
2026-04-29 10:00:22 +01:00
Oskar Otwinowski 1a7943ce1b feat(docs): Private Links official documentation (#3466)
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-04-28 21:20:52 +02:00
Oskar Otwinowski 5fe72eefa5 feat(webapp): Private Links setup wizard UI tweaks (#3465) 2026-04-28 21:20:11 +02:00
nicktrn fefe61f006 ci(helm): roll prereleases on main pushes + manual trigger (#3461)
Today the helm prerelease workflow only fires on PRs that touch
`hosting/k8s/helm/**`. Two consequences we ran into:

1. The `changeset-release/main` PR's prerelease comment goes stale once
the release branch gets force-pushed without a helm-touching commit (the
bot's `Chart.yaml` bump alone doesn't seem to refire the trigger
reliably).
2. The release PR's chart references an `appVersion` (e.g. `v4.4.5`)
whose Docker images don't exist until *after* merge + tag. So that
prerelease chart can't actually be installed end-to-end.

Renames the workflow to `helm-prerelease.yml` and adds two new triggers:

- **`push: main`** with `paths: hosting/k8s/helm/**` -> rolling
prereleases versioned `<base>-main.<sha>`. `appVersion` stays at
whatever `Chart.yaml` has (i.e. last released), so installs pull real
images. Tests that chart structure is deployable, even if the app code
is one release behind.
- **`workflow_dispatch`** with optional `app_version` input -> manually
trigger a prerelease and optionally override `appVersion` (e.g. pin to
`main` or a specific tag). Useful for testing chart + app-version
combinations on demand.

PR behavior unchanged: same `<base>-pr<N>.<sha>` versioning, same
posted/updated comment.

Why not also bypass paths for `changeset-release/main`? The release PR's
chart references not-yet-built `v4.4.5` images, so those prereleases
aren't actually installable. The rolling main prerelease covers the
testable case better.

Why not SHA-pin `appVersion` to a built image like `main-<sha>`? Bigger
change - the docker publish workflows currently only push `:main` (no
SHA-suffixed tag). Worth doing later if we want first-class "install one
chart, get exactly that commit's app code" testing, but out of scope
here.

Diff is mostly a rename. Substantive changes:
- new `push` and `workflow_dispatch` triggers
- `prerelease` job `if:` extended for the new event types
- version logic branches per event
- new "Override appVersion" step (workflow_dispatch only)
- new "Write run summary" step so non-PR runs surface the install
instructions
- PR comment steps gated on `github.event_name == 'pull_request'`
- concurrency group falls back to `github.ref` for non-PR runs
2026-04-28 15:42:12 +01:00
Eric Allam c69e939c34 feat: Sessions - bidirectional durable agent streams (#3417)
> ⚠️ **Not released yet.** This PR is the server-side foundation only.
The SDK changes that customers will actually use (`chat.agent`
migration, `chat.createStartSessionAction`, `useTriggerChatTransport`
updates) live on a separate branch and ship together in an upcoming
`@trigger.dev/sdk` prerelease. Until that prerelease is published, this
surface is reachable only via direct HTTP.

## What this gives Trigger.dev users

A new first-class primitive, **Session**, for durable, task-bound,
bidirectional I/O that outlives any single run. Sessions are the run
manager for `chat.agent` going forward, and they unblock anything else
that needs "one identifier, many runs over time" with a stable channel
pair the client can write to and subscribe to.

### Use cases unblocked

- **Chat agents that persist across many runs.** One session per chat
(keyed on your own `chatId` via `externalId`), turns 1..N attach to the
same Session, the UI subscribes once and keeps receiving output as new
runs take over.
- **Approval loops and long-running tasks with user feedback.** The task
waits on `.in`, the client writes to `.in`, the server enforces
no-writes-after-close.
- **Workflow progress streams that live past the run.** Subscribe to
`.out` after the task finishes to replay history.
- **Resume-next-day flows.** A session is a durable row, not a transient
stream. Send a message a day later and the server triggers a fresh run
on the same session.

### How it works (Session-as-run-manager)

A Session row is task-bound (`taskIdentifier` + `triggerConfig` are
required) and owns its current run via `currentRunId` +
`currentRunVersion` for optimistic claim. Three trigger paths:

1. **Session create** — `POST /api/v1/sessions` creates the row and
triggers the first run synchronously.
2. **Append-time probe** — `POST
/realtime/v1/sessions/:session/in/append` checks if the current run is
alive; if it has terminated (idle exit, crash, etc.), the server
triggers a new run before processing the append.
3. **End-and-continue handoff** — `POST
/api/v1/sessions/:session/end-and-continue`, called by the running
agent, triggers a fresh run and atomically swaps `currentRunId`. Used by
`chat.requestUpgrade()` for version handoffs.

Every triggered run is recorded in the `SessionRun` audit table with a
reason (`initial`, `continuation`, `upgrade`, `manual`).

## Public API surface

### Control plane

- `POST /api/v1/sessions` — create. Idempotent on `(env, externalId)`.
Triggers the first run, returns the session and a session-scoped public
access token. Returns 409 if the upserted row is already closed.
- `GET /api/v1/sessions/:session` — retrieve by friendlyId
(`session_abc...`) or by your own externalId (server disambiguates by
prefix).
- `GET /api/v1/sessions` — list with filters (`type`, `tag`,
`taskIdentifier`, `externalId`, derived `status` ACTIVE/CLOSED/EXPIRED,
created-at range) and cursor pagination. Backed by ClickHouse.
- `PATCH /api/v1/sessions/:session` — update tags / metadata /
externalId.
- `POST /api/v1/sessions/:session/close` — terminate. Idempotent,
hard-blocks new server-brokered writes.
- `POST /api/v1/sessions/:session/end-and-continue` — agent-only handoff
to a fresh run.

### Realtime

- `PUT /realtime/v1/sessions/:session/:io` — initialize a channel.
Returns S2 credentials in headers so high-throughput clients can write
direct to S2.
- `GET /realtime/v1/sessions/:session/:io` — SSE subscribe. Supports
Last-Event-ID resume and an opt-in `X-Peek-Settled: 1` header that
fast-closes the stream when the upstream is already settled
(`trigger:turn-complete`), eliminating long-poll wait on
reconnect-on-reload paths.
- `POST /realtime/v1/sessions/:session/:io/append` — server-side
appends.
- `POST /api/v1/runs/:runFriendlyId/session-streams/wait` — runs wait on
a session stream as a waitpoint, with a race-check to avoid suspending
if data already landed.

### Auth scopes

`sessions` is a new resource type. `read:sessions:{id}`,
`write:sessions:{id}`, `admin:sessions:{id}` flow through the existing
JWT validator. Session-scoped public access tokens minted by the server
replace browser-held trigger-task tokens for chat-style flows — the
browser never sees a run identifier or a run-scoped token in steady
state.

## What's coming after this PR

- **SDK + chat.agent migration**: separate branch, separate PR, ships in
the next `@trigger.dev/sdk` prerelease alongside this server deploy.
Customers using the prerelease `chat.agent` will follow the [upgrade
guide](https://github.com/triggerdotdev/trigger.dev/blob/docs/tri-7532-ai-sdk-chat-transport-and-chat-task-system/docs/ai-chat/upgrade-guide.mdx).
- **Dashboard surfaces**: dedicated agent list, agent playground, agent
view on the run dashboard. Tracking separately.

## Implementation notes

- **Postgres `Session` table**: scalar scoping columns (`projectId`,
`runtimeEnvironmentId`, `environmentType`, `organizationId`) without
FKs, matching the January TaskRun FK-removal decision. Point-lookup
indexes only — list queries go to ClickHouse. Terminal markers
(`closedAt`, `expiresAt`) are write-once.
- **ClickHouse `sessions_v1`**: ReplacingMergeTree, partitioned by
month, ordered by `(org_id, project_id, environment_id, created_at,
session_id)`. Tags indexed via `tokenbf_v1` skip index.
- **`SessionsReplicationService`**: mirrors `RunsReplicationService`
exactly — leader-locked logical replication consumer,
`ConcurrentFlushScheduler`, retry with exponential backoff + jitter,
identical metric shape. Dedicated slot + publication so the two consume
independently.
- **S2 keys**: `sessions/{addressingKey}/{out|in}`. The existing
`runs/{runId}/{streamId}` key format for run-scoped streams is
untouched.
- **Optimistic claim**: `ensureRunForSession` triggers a run upfront
(cheap to cancel if it loses the race), then attempts an `updateMany`
keyed on `currentRunVersion`. Loser cancels its triggered run and reuses
the winner's. No DB lock held across the trigger.

### What did NOT change

Run-scoped `streams.pipe` / `streams.input` and the existing
`/realtime/v1/streams/{runId}/...` routes are unchanged. Sessions are
net-new — not a reshaping of the current streams API.

## Deploy notes

- Set `SESSION_REPLICATION_CLICKHOUSE_URL` and
`SESSION_REPLICATION_ENABLED=1` to enable the replication consumer.
- The `Session` table needs `REPLICA IDENTITY FULL` set on the prod
source DB before the publication is created (same one-time DDL we did
for `TaskRun`). Required for delete events to carry full column values.
- Cross-form authorization on the `GET /api/v1/sessions/:session` loader
(a JWT minted for either form authorizes both URL forms). Action routes
are URL-form-specific, matching how the SDK mints PATs.

## Verification

- Webapp typecheck clean (10/10).
- `apps/webapp/test/sessionsReplicationService.test.ts` — round-trip
tests for insert/update/delete through Postgres logical replication into
ClickHouse via testcontainers.
- Live end-to-end against local dev: create + retrieve (both forms) +
update + close, `.out.initialize` + `.out.append` x2 + `.in.send` +
`.out.subscribe` over SSE, list with all filter combinations +
pagination, `end-and-continue` swap, `X-Peek-Settled` fast-close
(verified in browser via reconnect-on-reload and via curl). Replicated
row lands in ClickHouse within ~1s.
- Multi-round Devin + CodeRabbit review feedback addressed
(read-after-write paths use `prisma` writer, info-leak on auth-routes
masked as 403, peek-settled discriminator parsing fix, etc.).

## Test plan

- [ ] `pnpm run typecheck --filter webapp`
- [ ] `pnpm run test --filter webapp
./test/sessionsReplicationService.test.ts --run`
- [ ] Start the webapp with `SESSION_REPLICATION_CLICKHOUSE_URL` and
`SESSION_REPLICATION_ENABLED=1`. Confirm the slot and publication
auto-create on boot.
- [ ] `POST /api/v1/sessions` and verify the row replicates to
`trigger_dev.sessions_v1` within a couple of seconds.
- [ ] `POST /api/v1/sessions/:id/close`, then confirm `POST
/realtime/v1/sessions/:id/out/append` returns 400.
- [ ] Reuse a closed session's `externalId` on `POST /api/v1/sessions`
and confirm 409.
- [ ] `GET /realtime/v1/sessions/:id/out` with `X-Peek-Settled: 1` after
a turn completes and confirm `X-Session-Settled: true` response header +
immediate close.
2026-04-28 12:35:55 +01:00
Eric Allam e134da7306 fix(run-engine): debounce hot-key lock contention and 5xx feedback loop (#3453)
## Changes

Three changes in
`internal-packages/run-engine/src/engine/systems/debounceSystem.ts`, in
order of impact:

1. **Fast-path skip before the lock.** In `handleExistingRun`, do an
unlocked read of `delayUntil` (and `createdAt` for the max-duration
check) from the run row before entering `runLock.lock("handleDebounce",
...)`. If `newDelayUntil <= currentDelayUntil` and the run is still
within its max-duration window, return the existing run immediately
without taking the lock. Safe because debounce is monotonic-forward only
— a stale read either matches reality or undershoots, both of which
decay correctly (re-checked properly inside the lock by whichever caller
is actually pushing forward). Trailing-mode triggers carrying
`updateData` still take the lock so the data update is applied.

2. **Quantize `newDelayUntil`.** Round the computed `newDelayUntil` to
1-second buckets (configurable via `quantizeNewDelayUntilMs`, set to 0
to disable). Without quantization, every call has a slightly larger
`newDelayUntil` than the last and they all pass the fast-path check.
With it, concurrent callers on the same key share a target time and ~95%
short-circuit. User-visible effect: a debounced run might fire up to 1s
earlier than the strict spec — non-issue for typical debounce use cases
(chat summarization, batched notifications, etc.).

3. **Graceful lock-contention fallback.** Wrap the `runLock.lock(...)`
call so `LockAcquisitionTimeoutError` and Redlock `ExecutionError` /
`ResourceLockedError` return the existing run id with success instead of
propagating a 5xx. Debounce is best-effort: if we can't take the lock,
the herd is already updating it for us; fall in line. This kills the 5xx
→ SDK-retry feedback loop. With (1)+(2) this rarely fires; without them
it's the difference between 5xx and 200.

Defaults preserve current behaviour aside from quantization (1s) and
fast-path (on). Both are configurable via `RunEngineOptions.debounce`.

##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works


---

## Changelog

Reduce 5xx feedback loops on hot debounce keys by quantizing
`delayUntil`, adding an unlocked fast-path skip before the redlock, and
gracefully handling redlock contention in `handleDebounce` so the SDK no
longer retries into a herd.

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-04-28 11:22:00 +01:00
devin-ai-integration[bot] 4b28080ed4 feat: add isReplay to run context (#3454)
## Summary

Adds `isReplay` boolean to the run context (`ctx.run.isReplay`),
following the same pattern as the existing `isTest`. The value is
derived from the existing `replayedFromTaskRunFriendlyId` database
field, so no schema migration is needed.

##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

- Verified `@trigger.dev/core` builds successfully
- Verified `webapp` typechecks successfully
- All new fields use `default(false)` for backwards compatibility

---

## Changelog

- Added `isReplay` to `TaskRun` and `V3TaskRun` schemas in `common.ts`
- Added `RUN_IS_REPLAY` semantic attribute and wired it in `taskContext`
- Propagated `isReplay` through the dequeue system, run attempt system,
and all execution context construction paths (V1 + V2)
- Added `isReplay` to `DequeuedMessage` and
`TaskRunExecutionLazyAttemptPayload` schemas
- Added patch changeset for `@trigger.dev/core`
- Updated docs: added `isReplay` to context reference, added "Detecting
replays" section to replaying page

---

💯

Link to Devin session:
https://app.devin.ai/sessions/1d6f1b3cc39a4623b72d05bf00f2d70c

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: nick <55853254+nicktrn@users.noreply.github.com>
2026-04-28 11:57:44 +02:00
nicktrn 91fd8a8a03 chore(security): close dependabot alerts q2 (#3456)
Closes ~80 dependabot alerts (3 critical, ~25 high, ~31 medium) by
bumping direct deps where possible and narrowly overriding the rest.
Cloud uses `resend` email transport and Node 20 - all bumps are safe for
both cloud and self-hosters.

## Direct upgrades

| Package | Where | From | To | Why |
|---|---|---|---|---|
| `vite` | root devDeps | ^5.4.21 | *(removed)* | dead pin; vitest pulls
vite transitively |
| `dompurify` | apps/webapp | ^3.2.6 | ^3.4.1 | XSS CVEs |
| `effect` | apps/webapp | ^3.11.7 | ^3.21.2 | AsyncLocalStorage CVE in
Effect fibers |
| `nodemailer` | internal-packages/emails | ^7.0.11 | ^8.0.6 | SMTP CRLF
injection (only affects self-hosters w/ smtp/aws-ses transport) |
| `uuid` | apps/webapp | ^9.0.0 | ^14.0.0 | buffer bounds check;
ESM-only but bundled by Remix |
| `uuid` + `@types/uuid` | packages/trigger-sdk | ^9.0.0 | *(removed)* |
dead deps, no usage |
| `@types/uuid` | apps/webapp | ^9.0.0 | *(removed)* | uuid 14 ships its
own types |
| `tar` | packages/cli-v3 | ^7.5.4 | ^7.5.13 | path traversal CVEs |
| `testcontainers` + `@testcontainers/postgresql` +
`@testcontainers/redis` | internal-packages/testcontainers | ^10.28.0 |
^11.14.0 | dev/test cleanup; one-line API fix for
`RedisContainer(image)` |
| `rimraf` | webapp + 6 packages | ^3.0.2 / ^5.0.7 | ^6.0.1 | dev/build
tool consolidation |

## Scoped overrides

All bound by both `>=` and `<` to avoid major-version yanks.

| Override | Closes |
|---|---|
| `tar@>=7 <7.5.11` → `^7.5.11` | supervisor's `@kubernetes/client-node
1.0.0` chain |
| `axios@>=1.0.0 <1.15.0` → `^1.15.0` | replaces older 1.9.0 pin |
| `systeminformation@>=5.0.0 <5.31.0` → `^5.31.0` | bumps existing
5.27.14 pin |
| `lodash@>=4.0.0 <4.18.0` → `^4.18.0` | bumps existing 4.17.23 pin |
| `lodash-es@>=4.0.0 <4.18.0` → `^4.18.0` | new (mirrors lodash) |
| `dompurify@>=3 <3.4.0` → `^3.4.1` | catches transitive dompurify via
mermaid |
| `vite@>=5.0.0 <6.4.2` → `^6.4.2` | path traversal; vite 5 has no patch
|
| `rollup@>=4 <4.59.0` → `^4.59.0` | path traversal in vite/vitest chain
|
| `flatted@>=3 <3.4.2` → `^3.4.2` | prototype pollution in eslint
flat-cache |
| `picomatch@>=2 <2.3.2` → `^2.3.2` | ReDoS in 2.x branch (transitive) |
| `picomatch@>=4 <4.0.4` → `^4.0.4` | ReDoS in 4.x branch
(vitest/tinyglobby) |
| `minimatch@>=3 <3.1.3` → `^3.1.3` | ReDoS in eslint 8 chain |
| `protobufjs@>=7 <7.5.5` → `^7.5.5` | **critical** RCE via
@opentelemetry/otlp-transformer |
| `fast-xml-parser@>=4 <4.5.5` → `^4.5.5` | DOCTYPE bypass + others (4.x
branch via aws-sdk in supervisor) |
| `fast-xml-parser@>=5 <5.7.0` → `^5.7.0` | **critical** + others (5.x
branch via aws-sdk in webapp) |
| `path-to-regexp@>=0.1 <0.1.13` → `^0.1.13` | ReDoS in express 4 /
@remix-run/express |
| `ajv@>=8 <8.18.0` → `^8.18.0` | DoS |
| `socket.io-parser@>=4 <4.2.6` → `^4.2.6` | DoS in @trigger.dev/core's
socket.io |
| `postcss@>=8 <8.5.10` → `^8.5.10` | XSS via stringify |
| `yaml@>=2 <2.8.3` → `^2.8.3` | DoS |
| `semver@>=5 <5.7.2` → `^5.7.2` | ReDoS in 5.x |
| `defu@>=6 <6.1.5` → `^6.1.5` | prototype pollution via __proto__ in
@prisma/config c12 chain |

## Dismissed (~47)

| Reason | Cluster | Count |
|---|---|---|
| `not_used` | langsmith + next 15.x in references/* | 10 |
| `not_used` | minimatch 8.x via prisma-generator-ts-enums
(references/prisma-6) | 3 |
| `not_used` | basic-ftp via puppeteer in references/hello-world +
references/seed | 2 |
| `not_used` | hono / @hono/node-server / express-rate-limit /
path-to-regexp 8.x / @modelcontextprotocol/sdk - all via mcp-sdk chain
(dormant in webapp; dev-only localhost in cli-v3) | 22 |
| `not_used` | fastify / @fastify/static / file-type via evalite devDep
| 5 |
| `tolerable_risk` | rollup 3 + minimatch 5/8/9/10 dev/build tooling |
13 |

## Notes

- **mcp-sdk chain**: `@vercel/sdk` in webapp imports `Vercel` API client
only; `mcp-server/*` subpath isn't loaded at runtime. cli-v3's MCP
server runs only via `trigger mcp` on developer machines. Bumping
`@modelcontextprotocol/sdk` to latest (1.29.0) wouldn't close these
alerts anyway - it ships hono ^4.11.4 which is still vulnerable - so
dismissal is the cleaner call.
- **References ignore list**: confirmed with current dependabot ignore
config; added `references/seed/package.json` (only gap).
- **undici** alerts (CVE-2026-1527, 4 alerts) will auto-close: lockfile
already at 6.25.0 > patched 6.24.0; just needs Dependabot rescan.
- **Effect 3.20 fix** is a runtime-only scheduler fix, no public API
changes - verified with research agent against our four `effect/*`
imports.
- **uuid 14** is ESM-only; we only call `validate`/`version` (no crypto
needed) so Node 20 requirement isn't load-bearing for us.
## Public packages (`packages/*`)

Minimal surface, deliberately. None of these change published runtime
behaviour - all changesets-worthy public package changes are deferred to
a regular release pass.

| Package | Change | Runtime impact |
|---|---|---|
| `packages/trigger-sdk` | Removed dead `uuid` dep (no source imports) |
None - dep was unused |
| `packages/cli-v3` | `tar` ^7.5.4 → ^7.5.13 | Patch bump within
already-allowed 7.x range; nothing CLI consumers see |
| `packages/core` / `packages/build` / `packages/python` /
`packages/rsc` / `packages/react-hooks` / `packages/schema-to-json` |
`rimraf` ^3.0.2 → ^6.0.1 in devDeps | Build-time only, no runtime change
|

No changeset added because nothing in these packages affects what
published consumers run.

## Validation

- Webapp typecheck (forced, no cache) passes after every commit
- Smoke-tested testcontainers v11 changes via real `postgresTest` +
`redisTest` (sync.test.ts, releaseConcurrency.test.ts) - both pass
- Webapp built + verified `require("uuid")` no longer in CJS server
output (now bundled inline)
- Test env webapp deployed at `dependabot-q2.rc0` (cloud#740) - no
issues observed
- Test suite run with package prerelease passed
2026-04-28 10:22:44 +01:00
nicktrn 9e99c81f64 ci: skip privileged PR jobs on fork PRs (#3458)
Fork PRs can't access org secrets or push to GHCR, so these two
`pull_request` jobs hard-fail with no path to passing:

- `claude-md-audit` - needs `CLAUDE_CODE_OAUTH_TOKEN`
- `helm-pr-prerelease` `prerelease` job - needs `packages: write` to
push the chart

Hit this on #3449. Approving the run didn't help; the jobs ran and
failed at the privileged step. The chart-validation `lint-and-test` job
is fork-safe and stays untouched - that remains the merge gate for Helm
changes.

Gate both jobs on same-repo head:

```yaml
if: github.event.pull_request.head.repo.full_name == github.repository
```

Other PR workflows already handle forks fine: `pr_checks`
(typecheck/units/e2e/sdk-compat) falls back to anonymous DockerHub pulls
when secrets are missing.
2026-04-28 09:54:16 +01:00
ThullyoCunha e8f1a7a0a1 fix(helm): expand CLICKHOUSE_PASSWORD in webapp CLICKHOUSE_URL via kubelet (#3449)
## Summary

When the official Helm chart is deployed with an external ClickHouse and
`clickhouse.external.existingSecret` set — the documented path for not
committing secrets to `values.yaml` — the webapp pod crash-loops on
startup:

```
goose run: parse "http://default:${CLICKHOUSE_PASSWORD}@<host>:8123?secure=false": net/url: invalid userinfo
```

Context in vouch request #3443. Re-opening in draft status per bot
policy (previous attempt was #3445, closed by automation because it
wasn't draft; no changes to the patch).

## Root cause

Two pieces interact:

1. `hosting/k8s/helm/templates/_helpers.tpl` renders `CLICKHOUSE_URL`
(and `RUN_REPLICATION_CLICKHOUSE_URL`) with a shell-style literal
`${CLICKHOUSE_PASSWORD}` expecting bash expansion at container start.
2. `docker/scripts/entrypoint.sh` does `export
GOOSE_DBSTRING="$CLICKHOUSE_URL"` — single-pass POSIX sh substitution,
so the inner `${...}` survives as literal text and goose rejects it.

Reproduces against the latest published chart
(`oci://ghcr.io/triggerdotdev/charts/trigger:4.0.5`) and `main`.

## Fix

Switch the two helpers (external + `existingSecret` branch) from
shell-style `${CLICKHOUSE_PASSWORD}` to Kubernetes'
`$(CLICKHOUSE_PASSWORD)`. Kubelet substitutes `$(VAR)` at pod-creation
time from earlier env entries, and the chart already declares
`CLICKHOUSE_PASSWORD` from the Secret immediately before
`CLICKHOUSE_URL`, so the URL reaches the entrypoint with the real
password already inlined. No entrypoint change, no image change. The
plain-password branch (no `existingSecret`) is unchanged.

Operator caveat added as template comments: `CLICKHOUSE_PASSWORD` must
be URL-userinfo-safe since kubelet substitutes verbatim without
percent-encoding. Hex-encoded passwords (e.g. `openssl rand -hex 32`)
are safe by construction.

## Verification

- `helm template` against `external.existingSecret` now renders `value:
"http://default:$(CLICKHOUSE_PASSWORD)@<host>:8123?secure=false"` (was
`${CLICKHOUSE_PASSWORD}`).
- `helm template` against the plain-password branch is byte-identical to
before.
- Deployed end-to-end on a staging EKS cluster (Meistrari platform):
webapp container reaches `goose: successfully migrated database to
version: 6`, Node.js ClickHouse client connects at runtime.

## Alternatives considered

- **Change `entrypoint.sh`** to `eval` / `envsubst` the URL — larger
surface, touches every deployment mode (Docker Compose + k8s) and every
container image.
- **Mirror the Postgres pattern** (chart reads the full URL via
`valueFrom.secretKeyRef`, as in `trigger-v4.postgres.useSecretUrl`) —
cleaner long-term but requires a new `values.yaml` field and a migration
path for existing users. Happy to follow up with that as a separate PR
if the minimal fix here isn't the preferred direction.

## Changeset

None added — the Helm chart isn't versioned through `@changesets/cli`
(docs/chart-only PRs historically merge without a changeset, e.g.
#2671). Happy to add one if the policy changed.

Closes #3443.
2026-04-27 22:15:27 +01:00
Eric Allam 4dced14ad5 chore: fix CONTRIBUTING.md setup steps and scope db:seed to webapp (#3450)
## Summary

Two fixes that together get a fresh-machine setup working from
`CONTRIBUTING.md` end-to-end with no manual workarounds:

### `CONTRIBUTING.md`

- Fix wrong path in the migration walkthrough: `cd packages/database` →
`cd internal-packages/database`. The current path doesn't exist; this
breaks step 2 for every contributor adding a migration.
- Renumber duplicate `4.` steps in **Adding migrations** and the skipped
`5.` in the hello-world **Running** section.
- Combine three sequential `pnpm run build --filter ...` calls into one
(Turbo parallelizes filters): `pnpm run build --filter webapp --filter
trigger.dev --filter @trigger.dev/sdk`.
- Add a `pnpm run db:seed` step after migrate. The seed creates the
local user, `References` org, and reference projects (including
`hello-world` with the stable `proj_rrkpdguyagvsoktglnod`). Removes the
manual instruction to edit the `externalRef` column in Postgres.
- Mention ClickHouse and the ClickHouse migrator alongside
Postgres/Redis in the Docker step (they're already part of `pnpm run
docker`, just invisible in the docs).
- Remove the V1-era **Add sample jobs** section.
`references/job-catalog` no longer exists; the hello-world flow above
replaces it.

### `turbo.json`

Scope `db:seed` to `webapp#db:seed → webapp#build`. The previous
root-level entry queued `build` for every workspace package — including
`references-*`, `docs`, `kubernetes-provider`, `coordinator`, etc. Only
`webapp` actually has a `db:seed` script, so the rest of those builds
were dead weight. Worse: a single broken reference (today,
`references-realtime-hooks-test` failing under Turbopack with
`node:fs/promises`) kills the whole seed pipeline.

After the change, `turbo run db:seed --dry-run` plan drops from 27 tasks
to 20 — only `webapp` and its real transitive workspace deps. Reference
projects no longer block seeding.

## Test plan

- [x] Fresh-machine setup followed end-to-end on a wiped Postgres +
ClickHouse: migrate → seed → build → webapp → CLI login → `trigger dev`
→ triggered `hello-world`, run completed with `{"message":"Hello,
world!"}`.
- [x] `turbo run db:seed --dry-run=json` confirms 20 tasks, all webapp
deps, no reference packages.
- [ ] CI green on the renamed turbo task name.
2026-04-27 18:13:29 +01:00
Eric Allam 5693b62cfb fix(webapp): propagate abort signal through realtime proxy fetch (#3442)
## Summary

Fixes an RSS-only memory leak in the three realtime proxy routes
(`/realtime/v1/runs`, `/realtime/v1/runs/:id`,
`/realtime/v1/batches/:id`). Client disconnects during an in-flight
long-poll would leave the upstream fetch to Electric running with no way
to abort it, so undici kept the socket open and buffered response chunks
that would never be consumed.

## Root cause

All three routes flow through
`RealtimeClient.streamRun/streamRuns/streamBatch` → `#streamRunsWhere` →
`#performElectricRequest` → `longPollingFetch(url, { signal })`. The
chain was already signal-aware, but `#streamRunsWhere` hardcoded
`signal=undefined` when calling `#performElectricRequest`, so no signal
ever reached `longPollingFetch`.

When a downstream client aborts a long-poll mid-flight:
1. Express tears down the downstream response socket.
2. The `longPollingFetch` promise has already resolved (it returns as
soon as upstream headers arrive) and handed back `new
Response(upstream.body, {...})`.
3. `undici` keeps the upstream socket open and continues buffering
chunks into the `ReadableStream` that nothing will ever read from.
4. The upstream connection is eventually closed by Electric's own poll
timeout (~20s). During that window the per-request buffers stay in
native memory.

These buffers live below V8's accounting — no `heapUsed` or `external`
growth, no sign in heap snapshots, only RSS. An isolated standalone
reproducer (`fetch` against a slow-streaming upstream, discard the
`Response` before consuming its body) measures **~44 KB retained per
leaked request** after GC. That's consistent with the undici socket +
receive buffer + HTTP parser state for a long-lived chunked response.
The pattern is the shape documented in
[nodejs/undici#1108](https://github.com/nodejs/undici/issues/1108) and
[#2143](https://github.com/nodejs/undici/issues/2143).

## What changed

- **`realtimeClient.server.ts`** — add optional `signal` parameter to
`streamRun`, `streamRuns`, `streamBatch`, and the shared
`#streamRunsWhere`; thread it through to `#performElectricRequest`
instead of hardcoding `undefined`.
- **`realtime.v1.runs.$runId.ts`, `realtime.v1.runs.ts`,
`realtime.v1.batches.$batchId.ts`** — pass `getRequestAbortSignal()`
(from `httpAsyncStorage.server.ts`) at the call site. This is the signal
wired to `res.on('close')` and fires reliably on downstream disconnect.
- **`longPollingFetch.ts`** — belt-and-suspenders: cancel the upstream
body explicitly in the error path, and treat `AbortError` as a clean
`499` instead of a `500`. This both releases undici's buffers
deterministically on error and avoids spurious 500s in request logs when
a client legitimately walks away.

## Verification

Standalone reproducer: slow upstream server streams 32 KB chunks every
100 ms for 5 seconds per request. The proxy does `fetch(url)` with
varying signal/cancel strategies, creates `new Response(upstream.body,
...)`, and discards it without consuming the body (simulating the leak
path).

Results from 1 000 parallel fetches per variant, measured post-GC:

| variant | Δ heap | Δ external | Δ RSS |
| --- | --- | --- | --- |
| A. no signal, body never consumed (the bug) | +0.3 MB | 0 MB | **+59.4
MB** |
| B. signal propagated, aborted after headers (this fix) | −0.1 MB | 0
MB | +15.4 MB |
| C. no signal, explicit `res.body.cancel()` | 0 MB | 0 MB | −25.4 MB |

10-round sustained test of variant B to distinguish accumulating
retention from one-time allocator overhead:
```
round  1/10  Δ=+3.2 MB     round  6/10  Δ=-12.5 MB
round  2/10  Δ=-7.6 MB     round  7/10  Δ=-11.9 MB
round  3/10  Δ=-11.7 MB    round  8/10  Δ=-2.6 MB
round  4/10  Δ=+3.2 MB     round  9/10  Δ=-8.0 MB
round  5/10  Δ=-1.2 MB     round 10/10  Δ=-12.6 MB
```
RSS oscillates in a 49-65 MB band with no upward trend — signal
propagation fully releases the buffers.

## Risk

- Behavior change only on aborted long-polls: the upstream fetch now
cancels promptly instead of running to its natural timeout. This saves
both memory and outbound traffic to Electric.
- `AbortError` now surfaces as `499` rather than `500`. Any dashboard or
alert that counts 500s in request logs will see slightly fewer of them;
this is the intended behavior.
- Signal-aware parameter is optional on
`RealtimeClient.streamRun/streamRuns/streamBatch`, so callers that don't
opt in get the previous behavior.

## Test plan

- [ ] Existing realtime integration tests pass
- [ ] Dashboard realtime views (runs list, batch details) continue
working normally across tab open/close cycles
- [ ] Under a burst of aborted long-polls, server RSS returns to
baseline rather than climbing
2026-04-24 16:00:02 +01:00
Eric Allam 2ce981d454 chore: add GautamBytes to vouch list (#3447)
Adds @GautamBytes to the vouch list so they can contribute to the
repository.

Closes #3307

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
2026-04-24 15:58:32 +01:00
nicktrn d2059556c3 chore: vouch for ThullyoCunha (#3444)
closes #3443
2026-04-24 15:29:30 +01:00
Iss 8dd1fc12c6 docs: document auth.withAuth scoped authentication helper (#3436) 2026-04-24 13:57:15 +01:00
Matt Aitken 8aa1e55588 test: e2e auth baseline tests + webapp testcontainer infrastructure (#3438)
Adds a minimal end-to-end test harness that spawns the compiled webapp
as a child
process against a throwaway Postgres container, plus a baseline of 8
auth-behaviour
tests. These tests will be used as a regression check before and after
the upcoming
apiBuilder RBAC migration to confirm auth behaviour is unchanged.

## What's included

**`internal-packages/testcontainers/src/webapp.ts`** (new)
Spawns `build/server.js` with a dynamically allocated port, polls
`/healthcheck`,
and exposes `WebappInstance` and `startTestServer()` (postgres container
+ webapp +
PrismaClient in one call). Key details:
- Uses `process.execPath` so the correct Node binary is found in forked
test processes
- Sets `NODE_PATH` to `node_modules/.pnpm/node_modules` so pnpm-hoisted
transitive
deps (e.g. `eventsource-parser`) resolve correctly inside the subprocess
- Overrides both `PORT` and `REMIX_APP_PORT` so Vite's automatic `.env`
loading
  doesn't override the dynamically allocated port

**`internal-packages/testcontainers/package.json`**
Adds `./webapp` sub-path export so tests can `import from
"@internal/testcontainers/webapp"`.

**`internal-packages/testcontainers/src/index.ts`**
Exports `createPostgresContainer` (used internally by `webapp.ts`).

**`apps/webapp/test/helpers/seedTestEnvironment.ts`** (new)
Creates a minimal org → project → environment row set with random
suffixes.

**`apps/webapp/test/api-auth.e2e.test.ts`** (new)
8 tests across two suites:
- API-key bearer: valid key (auth passes, 404), missing header (401),
invalid key (401), error body shape
- JWT bearer: valid JWT on JWT-enabled route (passes), valid JWT on
non-JWT route (401), empty-scope JWT (403), wrong signing key (401)

## How to run

```bash
# Build required first (one-time)
pnpm run build --filter webapp

cd apps/webapp && pnpm exec vitest run test/api-auth.e2e.test.ts
```

## Test plan
- [x] All 8 tests pass against the current webapp build
- [x] Webapp healthcheck returns 200 on startup
- [ ] CI passes

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-04-24 12:06:35 +01:00
Saadi Myftija 496ac78484 feat(supervisor): optional ndots override for runner pods (#3441)
⚒️ Publish Worker (v4) / build (supervisor) (push) Has been cancelled
Adds `KUBERNETES_POD_DNS_NDOTS_OVERRIDE_ENABLED` flag (off by default)
that overrides the cluster default and sets `dnsConfig.options.ndots` on
runner pods (defaulting to 2, configurable via
`KUBERNETES_POD_DNS_NDOTS`).

Kubernetes defaults pods to `ndots: 5`, so any name with fewer than 5
dots, including typical external domains like `api.example.com`, is
first walked through every entry in the cluster search list
(`<ns>.svc.cluster.local`, `svc.cluster.local`, `cluster.local`) before
being tried as-is, turning one resolution into 4+ CoreDNS queries (×2
with A+AAAA).

Using a lower `ndots` value reduces DNS query amplification in the
`cluster.local` zone.
2026-04-24 13:05:55 +02:00
Matt Aitken f7aefb705a fix: disable RunQueue Worker in priority tests to prevent partial-batch race (#3440)
## Summary

- The `processMasterQueueForEnvironment` call in the priority test was
racing against background `processQueueForWorkerQueue` jobs scheduled
50ms after each trigger
- With a 50ms debounce (`processWorkerQueueDebounceMs: 50`) and runs
triggered sequentially, the RunQueue Worker could process those jobs
mid-sequence, pushing partial batches to the worker queue in the wrong
overall priority order
- `masterQueueConsumersDisabled: true` only blocks the shard-level
polling loops — it does not prevent the RunQueue's own Worker from
processing these debounced jobs
- Fix: add `worker.disabled: true` to the test 1 engine config, which
propagates to `workerOptions.disabled` in the RunQueue constructor and
prevents the Worker from starting

## Test plan

- [x] Both priority tests pass: `pnpm run test
./src/engine/tests/priority.test.ts --run`
- [x] Test 1 log confirms no ` Starting run engine worker` or worker
loop messages — workers fully disabled
- [x] Test 2 unaffected (uses master queue consumers for automatic
promotion, no `disabled` flag added)

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-24 12:03:47 +01:00
nicktrn 3446be7b32 ci: automate helm chart release alongside package release (#3439)
Wires up automatic Helm chart releases to ride along with the existing
changeset-driven package release flow.

Today `Chart.yaml` is bumped by hand and `release-helm.yml` fires only
when a human pushes a `helm-v*` tag. With this, the changeset release PR
also carries a `Chart.yaml` bump so main always matches the published
version, and `release.yml` invokes `release-helm.yml` via
`workflow_call` after Docker images are published.

`helm-v${VERSION}` tag is pushed as a marker (same GITHUB_TOKEN trick as
`v.docker.*`). Manual `helm-v*` tag flow still works. Chart.yaml
consistency check in `release-helm.yml` is the safety net if the bump
job ever drifts.

First rollout: the open `changeset-release/main` PR has stale
Chart.yaml. Bump it manually on that branch before merging, otherwise
the first automated helm release fails at the consistency check.
2026-04-24 07:05:55 +01:00
Eric Allam ca399565ba feat(webapp): add per-worker Node.js heap metrics (#3437)
## Summary

Adds direct V8 heap and process-memory gauges to the webapp's
OpenTelemetry meter. The webapp already exports per-cluster-worker
Node.js runtime metrics (event-loop lag / utilization, active handles,
active requests, libuv threadpool size) via a custom meter under the
`trigger.dev` scope. Heap and memory were missing; this PR adds them
alongside, in the same observable-batch pattern.

## New gauges

| Metric | Source | Unit |
| --- | --- | --- |
| `nodejs.memory.heap.used` | `process.memoryUsage().heapUsed` | bytes |
| `nodejs.memory.heap.total` | `process.memoryUsage().heapTotal` | bytes
|
| `nodejs.memory.heap.limit` | `v8.getHeapStatistics().heap_size_limit`
| bytes |
| `nodejs.memory.external` | `process.memoryUsage().external` | bytes |
| `nodejs.memory.array_buffers` | `process.memoryUsage().arrayBuffers` |
bytes |
| `nodejs.memory.rss` | `process.memoryUsage().rss` | bytes |

Gated by the existing `INTERNAL_OTEL_NODEJS_METRICS_ENABLED` flag, same
as the adjacent event-loop / handle gauges. Zero overhead when disabled.

## Why

`@opentelemetry/host-metrics` publishes `process.memory.usage`, which is
RSS only. RSS is the sum of V8 heap, external memory (Buffers, etc.),
native code, and thread stacks. Without a direct heap metric it is not
possible to size the V8 heap cap (`--max-old-space-size`) from metrics
alone, because RSS overstates heap by the external + native footprint. A
worker can have a 4 GB RSS with a 2.5 GB heap and 1.5 GB of buffers; the
former constrains `--max-old-space-size`, the latter does not.

`nodejs.memory.heap.limit` also surfaces the configured
`--max-old-space-size` (read from
`v8.getHeapStatistics().heap_size_limit`), so operators can see the
current limit in the same dashboard as actual usage rather than
cross-referencing container environment variables.

## Risk

Minimal. Observable gauges are sampled at the configured metric-export
interval. `v8.getHeapStatistics()` and `process.memoryUsage()` are each
microsecond-level calls, and six gauges are added to the same batch
callback that already reads ~20 other Node.js runtime values per sample.
Same registration pattern as the existing event-loop metrics in the
file.

## Test plan

- [ ] Deploy and confirm the six new gauges appear at the configured
exporter
- [ ] In cluster mode, confirm per-worker granularity (one series per
cluster worker, tagged by `process.executable.name` /
`service.instance.id`)
- [ ] Confirm `nodejs.memory.heap.limit` reports the configured
`--max-old-space-size` value in bytes
2026-04-23 22:41:24 +01:00
Iss 41434b536b feat(webapp): admin Back Office tab with org API rate limit editor (#3434)
## Summary
- New **Back office** tab at `/admin`, per-org detail page at
`/admin/back-office/orgs/:orgId` designed to host future per-org admin
actions (project count, delete account, YC deals).
- First action: edit an organization's API rate limit — tokenBucket
override (refill rate, interval, max tokens), with a live plain-English
preview (e.g. *"1,500 requests per minute · 750 request burst
allowance"*). Writes are audit-logged via the server logger.
- Cleanup: removed unused `v2?` / `v3?` columns from the admin orgs list
(display only — Prisma select untouched).

## Test plan
- [ ] Back office tab visible in admin nav and highlighted when on a
sub-route
- [ ] `/admin/orgs` shows a Back office "Open" link per row; no v2/v3
columns
- [ ] Empty state at `/admin/back-office` links back to `/admin/orgs`
- [ ] Detail page renders the effective rate limit in view mode; Edit
reveals the form
- [ ] Save writes `Organization.apiRateLimiterConfig`, returns to view
mode, shows "Rate limit saved." banner
- [ ] Invalid values surface inline field errors and keep edit mode
- [ ] Non-admins hitting any new route are redirected to `/`
- [ ] Server logs show `admin.backOffice.rateLimit` info line per
mutation
2026-04-23 12:51:49 -04:00
devin-ai-integration[bot] cbb1f35ef0 chore(helm): bump appVersion to v4.4.4 (#3432)
🧭 Helm Chart Release / lint-and-test (push) Has been cancelled
🧭 Helm Chart Release / release (push) Has been cancelled
2026-04-23 18:47:44 +02:00
Eric Allam 486f49791d fix(webapp): eliminate SSE abort-signal memory leak (#3430)
## Summary

Fixes a server-side memory leak in the webapp's SSE helper. Every
aborted SSE connection (client tab close, navigation, timeout) was
pinning its full request/response graph indefinitely on Node 20, so any
long-running webapp process accumulated retained memory proportional to
streaming-request churn.

## Root cause

`apps/webapp/app/utils/sse.ts` combined four abort signals via
`AbortSignal.any([requestAbortSignal, timeoutSignal,
internalController.signal])`. The composite signal tracks its source
signals in an internal `Set<WeakRef>` registered against a
`FinalizationRegistry`; under sustained traffic those entries accumulate
faster than they're cleaned up, pinning every source signal (and its
listeners, and anything those listeners close over) until the parent
signal itself is GC'd or aborts.

This is a long-standing Node issue with multiple open reports:

- [nodejs/node#54614](https://github.com/nodejs/node/issues/54614) —
original report, still open. A [follow-up from
ChainSafe](https://github.com/nodejs/node/issues/54614#issuecomment-4055656572)
describes the exact same shape in a Lodestar production workload (req +
timeout signals composed per request accumulating in long-running
worker) and the same mitigation: drop `AbortSignal.any`, compose
manually.
- [nodejs/node#55351](https://github.com/nodejs/node/issues/55351) —
mechanism confirmed by Node member @jasnell: *"the set of dependent
signals known to the AbortSignal are kept in an internal Set using
WeakRefs. The AbortSignals are being properly gc'd but the Set is never
cleaned out of the WeakRefs making those leak."* Partially fixed by [PR
#55354](https://github.com/nodejs/node/pull/55354), shipped in Node
22.12.0 — but only covers the tight-loop case, not long-lived parent
signals.
- [nodejs/node#57584](https://github.com/nodejs/node/issues/57584) —
circular-dependency variant, still open.
- [nodejs/node#62363](https://github.com/nodejs/node/issues/62363) —
regression in Node 24/25 from an unrelated V8 change ("Don't pretenure
WeakCells"). Different root cause, same symptom.

A separate issue in `apps/webapp/app/entry.server.tsx` —
`setTimeout(abort, ABORT_DELAY)` with no `clearTimeout` on success paths
— kept the React render tree + `remixContext` alive for 30s per
successful HTML request. Same pattern fixed upstream in React Router
templates
([react-router#14200](https://github.com/remix-run/react-router/pull/14200)),
never backported to Remix v2.

## What changed

- **`apps/webapp/app/utils/sse.ts`** — single-signal abort chain.
`AbortSignal.any` removed; `AbortSignal.timeout` replaced by a plain
`setTimeout` cleared when the controller aborts; named sentinel
constants used as stackless abort reasons; request-abort handler
explicitly removed on cleanup.
- **`apps/webapp/app/entry.server.tsx`** — clears the `setTimeout(abort,
ABORT_DELAY)` timer in `onShellReady` / `onAllReady` / `onShellError`.
- **`apps/webapp/app/v3/tracer.server.ts` + `env.server.ts`** — gates
OpenTelemetry `HttpInstrumentation` and `ExpressInstrumentation` behind
`DISABLE_HTTP_INSTRUMENTATION=true` as an escape hatch for future
OTel-listener retention patterns. Defaults to enabled.
- **`apps/webapp/app/presenters/v3/RunStreamPresenter.server.ts`** —
uses the shared `ABORT_REASON_SEND_ERROR` sentinel.

## Verification

### Full-app reproduction (memlab)

Isolated local harness, 500 abrupt SSE disconnects against a
dev-presence route, GC between passes, heap snapshot diff with
[memlab](https://facebook.github.io/memlab/):

| Run | Heap delta after 500 conns + GC | memlab retained leaks |
| --- | --- | --- |
| Before | +16.0 MB (linear with request count) | 158 clusters; 250
`ServerResponse`, 1000 `AbortController`, 250 `SpanImpl` retained |
| After | **+3.3 MB (noise)** | **0 app-code leaks** |

### Standalone mechanism isolation

To confirm *which* axis of the change is load-bearing, a separate
standalone Node script (`/tmp/abort-leak-test.mjs`) ran 2000 requests ×
200 KB payload per variant:

| Variant | Heap delta after GC |
| --- | --- |
| baseline (no signal machinery) | 0 MB |
| V1: `AbortSignal.any` + string abort reason | **+9.1 MB** |
| V2: `AbortSignal.any` only (no reason) | **+10.8 MB** |
| V3: string reason only (no `AbortSignal.any`) | 0 MB |
| V4: neither (the fix) | 0 MB |
| V5: `AbortSignal.any` with no listener on the composite | **+10.2 MB**
|

This proves `AbortSignal.any` is the sole mechanism. The reason type
(`.abort()` vs `.abort("string")`) is irrelevant for retention — V3 is
clean, V5 leaks even without a listener on the composite.

## Risk

- `sse.ts` is used by the dev-presence routes. Behaviour is equivalent —
timeouts and client disconnects still abort the stream. `signal.reason`
is now a named string sentinel (`"timeout"`, `"request_aborted"`, etc.)
instead of the previous string arg or default `AbortError`. No in-tree
reader of `signal.reason` exists.
- `entry.server.tsx` change is a standard cleanup of an abort timer,
matches upstream React Router guidance.
- `tracer.server.ts` change is env-gated and defaults to current
behaviour.
- Three other webapp `AbortSignal.timeout()` callsites (alert delivery,
remote-build status) are fire-and-forget passed directly to `fetch` —
not composed with anything long-lived, no retention risk, untouched.

## Test plan

- [ ] Existing SSE integration tests pass
- [ ] Dev-presence SSE behaves normally across tab open/close cycles
- [ ] No heap growth under sustained aborted-connection traffic (heap
snapshot diff)

## Follow-up

The same `AbortSignal.any([userSignal, internalSignal])` pattern exists
in several SDK/core callsites that ship to customers
(`packages/core/src/v3/realtimeStreams/manager.ts`,
`packages/trigger-sdk/src/v3/{ai,chat,chat-client,sessions}.ts`,
`packages/core/src/v3/workers/warmStartClient.ts`). Whether those leak
in practice depends on the user passing a long-lived signal. Tracked
separately.
2026-04-23 15:54:05 +02:00
nicktrn 87b6716535 fix(helm): support webapp serviceAccount annotations for IRSA (#3429)
Mirrors the existing `supervisor.serviceAccount` pattern onto webapp so
operators can annotate the SA (IRSA `eks.amazonaws.com/role-arn`,
Workload Identity, etc.) or bring their own SA. Without this,
`webapp.serviceAccount.annotations` isn't exposed and operators have to
patch the SA out-of-band.

```yaml
webapp:
  serviceAccount:
    create: true
    name: ""
    annotations:
      eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/trigger-webapp
```

Three pieces, same as supervisor:
- `webapp.serviceAccount.create` toggle on the SA block
- `webapp.serviceAccount.annotations` + `name` values
- `trigger-v4.webappServiceAccountName` helper, used by the SA, the
token-syncer RoleBinding subject, and the Deployment's
`serviceAccountName`

Role + RoleBinding are left unguarded (matching supervisor's shape where
`rbac.create` is a separate toggle from `serviceAccount.create`) -
BYO-SA users take on the responsibility of ensuring the SA they supply
has the permissions the RoleBinding grants.

Verified with `helm template` against default values, an IRSA annotation
override, and `create: false` with a custom name.
2026-04-23 15:08:54 +02:00
Matt Aitken fc71e7dd75 fix: handle fast-completion race in batch streaming seal check (#3427)
## Problem

When `batchTrigger()` is called with large payloads, each item's payload
is uploaded to R2 server-side during the streaming loop before being
enqueued. This makes the loop slow — around 3 seconds per item. Workers
pick up and execute each item as it's enqueued, running concurrently
with the ongoing stream.

For the last item in the batch, a race exists between the streaming loop
finishing and the batch completion cleanup:

1. The loop enqueues the last item and returns from `enqueueBatchItem()`
2. A waiting worker picks up the item almost instantly and executes it
3. `recordSuccess()` fires, `processedCount` hits the expected total,
`finalizeBatch()` runs
4. `cleanup()` deletes all Redis keys for the batch, including
`enqueuedItemsKey`
5. The streaming loop exits and calls `getBatchEnqueuedCount()` — reads
the now-deleted key — returns 0

The count check finds `enqueuedCount (0) !== batch.runCount`, falls
through to a Postgres fallback, but the fallback only checked `sealed`.
The BatchQueue completion path sets `status = COMPLETED` in Postgres
without setting `sealed = true` (that's the streaming endpoint's job),
so the fallback misses it too.

This causes the endpoint to return `sealed: false`. The SDK treats this
as retryable and retries up to 5 times with exponential backoff. Each
retry calls `enqueueBatchItem()`, which reads the batch meta key from
Redis — also deleted by `cleanup()` — and throws "Batch not found or not
initialized" (500). The final retry gets a 422 because the batch is
already COMPLETED, which the SDK does not retry, causing an `ApiError`
to be thrown from `await batchTrigger()` in the parent run — even though
all child runs completed successfully.

## Fix

In the Postgres fallback inside `StreamBatchItemsService`, also check
`status === "COMPLETED"` alongside `sealed`. This covers the
fast-completion path where the BatchQueue finishes all runs before the
streaming endpoint gets to seal the batch normally.

Also switches `findUnique` to `findFirst` per webapp convention.

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-04-23 13:45:41 +01:00
Oskar Otwinowski 8eb596f3fe fix(vercel): Fix vercel settings page (#3424) 2026-04-22 19:01:34 +02:00
Eric Allam 2d3b2e82e6 feat(run-engine): flag to route getSnapshotsSince through read replica (#3423)
## Summary

Adds `RUN_ENGINE_READ_REPLICA_SNAPSHOTS_SINCE_ENABLED` (default `"0"`).
When enabled, the Prisma reads inside `RunEngine.getSnapshotsSince` run
against the read-only replica client instead of the primary. Offloads
the snapshot-polling queries fired by every running task runner off the
writer.

## Why

`getSnapshotsSince` is called from the managed runner's
fetch-and-process loop (once per poll interval, plus on every
snapshot-change notification). It runs four sequential reads per call —
one `findFirst` by snapshot id, one `findMany` on snapshots with
`createdAt > X`, one raw SQL against `_completedWaitpoints`, and chunked
`findMany` on `waitpoint`. Per concurrent run, every few seconds. It's
read-only, tolerates a small amount of staleness, and is an obvious
candidate for the replica.

## Replica-lag considerations

- **Step 1 "since snapshot not found"**: if the runner just received a
snapshot id from the primary and asks the replica before it replicates,
the function throws and the caller treats the response as an error
(runner falls back to a metadata refresh). Self-correcting, not silent.
- **Step 2 missing newly-created snapshots**: the next poll's `createdAt
> sinceSnapshot.createdAt` filter still picks them up once the replica
catches up.
- **Waitpoint junction race**: the riskiest path — if a latest snapshot
is replicated but its `_completedWaitpoints` join rows aren't yet, the
runner could advance past that snapshot with `completedWaitpoints: []`.
WAL/storage-level replication replays commits in order, so in practice
both should appear atomically on the reader, but the race window is why
the flag ships disabled.

Aurora reader shrinks all three windows to single-digit ms in typical
conditions, and its storage-level replication gives atomic visibility of
committed transactions on the reader.

## Test plan

- [ ] Flip the flag on in a non-prod environment, confirm snapshot
polling behaves normally and `getSnapshotsSince` errors in Sentry stay
flat.
- [ ] Verify writer query volume drops and reader query volume rises on
the snapshot-polling queries.
- [ ] Keep an eye on `AuroraReplicaLag` (or equivalent) during rollout.
2026-04-22 11:48:04 +01:00
Eric Allam 7c95ee498e feat(webapp): tag Prisma spans with db.datasource attribute (#3422)
## Summary

Stamp every Prisma span with `db.datasource: "writer" | "replica"` so
traces can distinguish which client the query went through.

Both `PrismaClient` instances share the same global
`@prisma/instrumentation`, so their spans come out with identical names
and attributes today. This makes them trivially filterable.

## How

Two pieces in `apps/webapp/app/`:

1. **`v3/tracer.server.ts`** — a `DatasourceAttributeSpanProcessor`
reads an OTel context key in `onStart` and calls
`span.setAttribute("db.datasource", value)`. Registered as the first
span processor.
2. **`db.server.ts`** — `tagDatasource(datasource, client)` wraps each
`PrismaClient` with `$extends({ query: { $allOperations } })`. The
middleware sets the context key around the query and directly tags the
active span (to catch `prisma:client:operation`, which Prisma creates
before the middleware fires).

### Context-propagation gotcha

`PrismaPromise` is lazy — `query(args)` returns a thenable that only
starts when someone `.then()`s it. The naive `context.with(ctx, () =>
query(args))` restores ALS synchronously, so when Prisma's internal code
awaits the thenable later, the engine spans fire with the original ALS.
Wrapping as `async () => await query(args)` forces the `.then()` inside
the `context.with` callback, so ALS stays on our context for the engine
spans.

### Coverage

- **Tagged**: all `prisma:engine:*` (`connection`, `db_query`,
`serialize`, `query`, etc.), `prisma:client:operation`,
`prisma:client:serialize`, `prisma:client:connect`
- **Not tagged**: `prisma:client:load_engine` — one-time startup, fires
before any query

Concurrent `Promise.all([writer.x, replica.y])` correctly tags each pool
separately (ALS isolates per-Promise chain).

### Performance

One `context.with` (~200ns) and one `setAttribute` per span (effectively
free per OTel JS benchmarks) per Prisma op. Negligible against a query
path measured in milliseconds.

## Test plan

- [ ] Verify `db.datasource` appears on `prisma:engine:connection` spans
after the webapp is restarted
- [ ] Spot-check a handful of real traces carry the attribute
2026-04-21 16:56:17 +01:00
nicktrn b570586899 fix(webapp): allow cancelling runs in DEQUEUED status from the runs list (#3421)
The cancel button was missing from the runs list for runs in `DEQUEUED`
status. The runs list gates the button on `run.isCancellable`, which
goes through `isCancellableRunStatus` -> `CANCELLABLE_RUN_STATUSES` =
`NON_FINAL_RUN_STATUSES`. `DEQUEUED` was never added to that list when
it was introduced in the run engine.

The single run page uses a separate check (`!run.isFinished`, i.e. the
inverse of `FINAL_RUN_STATUSES`), so cancellation already worked there -
only the list was affected.

Adding `DEQUEUED` to `NON_FINAL_RUN_STATUSES` also flips
`isCrashableRunStatus` and `isFailableRunStatus`, but:

- The crash path is the right behaviour - a `DEQUEUED` run (worker has
claimed but not yet executing) can legitimately crash before
`EXECUTING`, same as `PENDING`/`DELAYED` already do.
- The fail path (`failedTaskRun.server.ts`) is only reached from V1 code
paths (marqs consumers, v1 heartbeat handler). `DEQUEUED` is a
V2-engine-only status, so V1 consumers never see it.

When cancelling a `DEQUEUED` run the execution snapshot goes to
`PENDING_CANCEL` (worker must ack) but `TaskRun.status` flips to
`CANCELED` immediately - the UI reflects cancellation without waiting
for the worker. Added an integration test in
`run-engine/src/engine/tests/cancelling.test.ts` covering the full
trigger -> dequeue -> cancel -> worker-ack flow.

## Stall safety

The stall recovery path (PENDING_EXECUTING heartbeat miss ->
nack-and-requeue -> back to QUEUED) lives entirely inside
`@internal/run-engine` and never touches the webapp's `taskStatus.ts`
helpers - the engine has zero imports from `~/v3/taskStatus` and doesn't
know `CrashTaskRunService` / `FailedTaskRunService` exist. A stalled
DEQUEUED run still goes back to the queue for retry; this change cannot
cause stalls to crash or fail.

The only realistic impact is the intended UI fix - the theoretical V1
crash/fail branches for DEQUEUED are unreachable in practice because V1
runs never have DEQUEUED status.
2026-04-21 11:33:17 +01:00
Eric Allam 03e4d5fe31 feat(webapp,database): API key rotation grace period (#3420)
## Summary

Regenerating a RuntimeEnvironment API key no longer immediately
invalidates the previous one. Rotation is now overlap-based: the old key
keeps working for 24 hours so customers can roll it out in their env
vars without downtime, then stops working.

## Design

- **New `RevokedApiKey` table** (one row per revocation). Holds the
archived `apiKey`, a FK to the env, an `expiresAt`, and a `createdAt`.
Indexed on `apiKey` (high-cardinality equality — single-row hits) and on
`runtimeEnvironmentId`.
- **`regenerateApiKey` wraps both writes in a single `$transaction`:**
insert a `RevokedApiKey` with `expiresAt = now + 24h`, update the env
with the new `apiKey`/`pkApiKey`.
- **`findEnvironmentByApiKey` does a two-step lookup:** primary
unique-index hit on `RuntimeEnvironment.apiKey` first; on miss,
`RevokedApiKey.findFirst({ apiKey, expiresAt: { gt: now } })` with an
`include: { runtimeEnvironment }`. Two-step (not `OR`-join) keeps the
hot path identical to today and puts the fallback cost only on invalid
keys. Both lookups use `$replica`.
- **Admin endpoint** `POST /admin/api/v1/revoked-api-keys/:id` accepts
`{ expiresAt }` and updates the row. Setting to `now` ends the grace
window immediately; setting to the future extends it.
- **Modal copy** on the regenerate dialog updated — previously warned of
downtime, now explains the 24h overlap.

## Why a separate table instead of columns on `RuntimeEnvironment`

- Keeps the hot auth path's primary lookup unchanged — no
OR/nullable-apiKey semantics to reason about.
- Naturally supports multiple in-flight grace windows (regenerate twice
in a day → two old keys valid until their independent expiries).
- FK + cascade cleans up correctly when an env is deleted; nothing to
backfill.

## Test plan

Verified locally against hello-world with dev and prod env keys:

- [x] baseline — current key authenticates (`GET /api/v1/runs`) → `200`
- [x] regenerate via UI — DB shows old key in `RevokedApiKey` with
`expiresAt ≈ now+24h`, env has new key
- [x] grace window — both old and new keys → `200`; bogus key → `401`
- [x] admin endpoint: `expiresAt = now` → old key `401`
- [x] admin endpoint: `expiresAt = +1h` (after early-expire) → old key
`200` again
- [x] admin endpoint: `expiresAt = past` → old key `401`
- [x] admin 400 (invalid body), 404 (unknown id), 401 (missing/non-admin
PAT)
- [x] same flow exercised end-to-end on a PROD-typed env — behavior
identical
- [x] `pnpm run typecheck --filter webapp` passes
2026-04-20 18:28:16 +01:00
Iss de3b9a158b docs: document secret env vars and Vercel sync behavior (#3419) 2026-04-20 13:19:33 -04:00
DKP be6b490790 docs: skills page update (#3418) 2026-04-20 17:06:01 +01:00
Eric Allam 881288c615 feat(webapp): deprecate v3 CLI deploys server-side (#3415)
##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Summary

Adds a server-side gate that detects deploy attempts from v3 CLI
versions (i.e. `trigger.dev@3.x`) at the `POST /api/v1/deployments`
entry point and, when enabled, rejects them with a clear upgrade
message. v4 CLI deploys are completely unaffected.

The last 3.x CLI release was `3.3.7`, which we can't update. This
approach short-circuits the deploy before any DB writes, image-ref
generation, S2 stream creation, or queue enqueue — no side effects in
either mode.

## How v3 vs v4 are distinguished

I pulled the published CLI tarballs for `trigger.dev@3.3.7`, `4.0.0`,
`4.0.1`, `4.0.5`, `4.1.0`, `4.2.0`, and the current `4.4.4` in the repo.
The cleanest, most reliable signal is the request body to `POST
/api/v1/deployments`:

| Field on initialize | v3.3.7 CLI | v4.x CLI |
|---|---|---|
| `type` | **never sent** | always sent — `"MANAGED"` (run_engine_v2) or
`"V1"` |
| `isNativeBuild` / `gitMeta` / `triggeredVia` / `runtime` | not sent |
sent |
| `registryHost` / `namespace` | sent (v3-only; stripped by current Zod
schema) | not sent |

Every v4 call site I inspected sets `type: features.run_engine_v2 ?
"MANAGED" : "V1"` unconditionally. `payload.type` is `undefined` if and
only if the client is a 3.x CLI.

## Behavior

- Detection always runs and emits `logger.warn("Detected deploy from
deprecated v3 CLI", { environmentId, projectId, organizationId, enforced
})`, which lets us watch how many v3 deploys are still happening before
enforcement is flipped.
- Enforcement is gated behind `DEPRECATE_V3_CLI_DEPLOYS_ENABLED`
(default `"0"`, off). When `"1"`, the server returns `400` with:

> The trigger.dev CLI v3 is no longer supported for deployments. Please
upgrade your project to v4: https://trigger.dev/docs/migrating-from-v3

The v3 CLI surfaces this verbatim as `Failed to start deployment:
<message>` because `zodfetch` throws `ApiError` for non-retryable 4xx
(400/422) and `deploy.js` in 3.3.7 prints `error.message`.

## Out of scope (intentionally)

- `api.v1.deployments.$deploymentId.finalize.ts` /
`FinalizeDeploymentService` /
`createDeploymentBackgroundWorkerV3.server.ts` are V1-engine paths, not
the v3 CLI gate. Leaving them alone per review.
- Container-side `createDeploymentBackgroundWorker` call in
`managed-index-controller.ts` is still used by v4's in-image indexer.
Not touched.
- v3 `trigger dev` flow (different code path) — separate deprecation
if/when needed.

## Testing

- Ran `pnpm run typecheck --filter webapp` locally — passes.
- Verified v4 tarballs (4.0.0, 4.0.1, 4.0.5, 4.1.0, 4.2.0, 4.4.4) all
include `type:` in the `initializeDeployment` call site, so none will be
accidentally blocked.
- Verified v3.3.7 tarball's `initializeDeployment` payload has no `type`
field.

Rollout plan after merge:
1. Deploy with `DEPRECATE_V3_CLI_DEPLOYS_ENABLED` unset → watch
`Detected deploy from deprecated v3 CLI` log volume.
2. When comfortable, set `DEPRECATE_V3_CLI_DEPLOYS_ENABLED=1` to
enforce.

---

## Changelog

Detect v3 CLI deploys on `/api/v1/deployments` and, when
`DEPRECATE_V3_CLI_DEPLOYS_ENABLED=1`, reject them with an upgrade
message pointing at https://trigger.dev/docs/migrating-from-v3. v4 CLI
deploys are unaffected.


Link to Devin session:
https://app.devin.ai/sessions/b242c11bd86e4099aeec8b59bab62143
Requested by: @ericallam
2026-04-20 15:26:57 +01:00
Matt Aitken 6e6deb41e1 Admin endpoint to set concurrency burst factor (#3412)
Example cURL call using an admin user PAT (replace with a real one):

```sh
curl -X PUT https://cloud.trigger.dev/admin/api/v1/environments/<environmentId>/burst-factor \
    -H "Authorization: Bearer tr_pat_1234" \
    -H "Content-Type: application/json" \
    -d '{"burstFactor": 1.5}'
```
2026-04-19 19:35:04 +01:00
Iss 7d7ebdde52 feat: Increase default project limit per org from 10 to 25 (#3409) 2026-04-17 11:05:57 -04:00
nicktrn 9a988ab885 chore(webapp): clarify admin feature flags are global (#3408)
global flags are global.
2026-04-17 13:49:30 +01:00
nicktrn 581db83f64 feat(webapp): highlight microVM regions on the regions page (#3407)
Adds a `MicroVM` badge next to the region name on the regions page. Uses
the existing `small` badge variant for visual consistency with the
`Default` badge already on this page.
2026-04-17 13:40:05 +01:00
Eric Allam 69acdc2b32 fix(core): truncate large error stacks and messages to prevent OOM (#3405)
## Summary

Large error stacks and messages can OOM the worker process when
serialized into OTel spans or `TaskRunError` objects. This was reported
when throwing an error with a massive `.stack` property from a chat
agent hook.

This adds frame-based stack truncation (similar to Sentry's approach)
plus message length limits, applied consistently across all error
serialization paths.

### What changed

**`packages/core/src/v3/errors.ts`**
- `truncateStack()` — parses `error.stack` into message lines + frame
lines, caps at 50 frames (keep top 5 closest to throw + bottom 45 entry
points, with "... N frames omitted ..." in between). Individual lines
capped at 1024 chars.
- `truncateMessage()` — caps error messages at 1000 chars
- Applied in `parseError()` and `sanitizeError()`

**`packages/core/src/v3/otel/utils.ts`**
- `sanitizeSpanError()` now uses `truncateStack` and `truncateMessage`
from `errors.ts` instead of duplicating truncation logic
- Non-Error values (strings, JSON) capped at 5000 chars

**`packages/core/src/v3/tracer.ts`**
- `startActiveSpan` catch block now delegates to `recordSpanException()`
instead of calling `span.recordException()` directly

### Limits

| What | Limit | Rationale |
|------|-------|-----------|
| Stack frames | 50 | Matches Sentry's `STACKTRACE_FRAME_LIMIT` |
| Top frames kept | 5 | Closest to throw site |
| Bottom frames kept | 45 | Entry points / framework frames |
| Per-line length | 1024 | Matches Sentry, prevents regex DoS |
| Message length | 1000 | Bounded but generous |
| Generic string (non-Error) | 5000 | Fallback for JSON/string errors in
spans |

## Test plan

- [x] 17 unit tests in `packages/core/test/errors.test.ts`
- [x] E2E: threw a 300-frame / 5000-char-message error in the ai-chat
reference app, verified truncated stack and message in span via
`get_span_details`
- [x] Verified the run survived the error (no OOM, continued waiting for
next message)
2026-04-17 13:25:01 +01:00
Matt Aitken 45ba398c80 Error page graph: for a time bucket don't fill zeros for a version with no errors (#3402)
This caused performance issues with large numbers of versions, and bad
UX when hovering the graph (showing irrelevant versions)
2026-04-17 10:12:54 +01:00
Eric Allam 9636e43567 fix(webapp): reduce error-level log noise for handled/benign cases (#3403)
Two changes to cut error volume from logs that represent handled
conditions, not real errors (combined ~1600/hr in prod):

1. api.v1.waitpoints.tokens.$waitpointFriendlyId.complete.ts

The route throws `json(..., { status: 404 })` when a waitpoint
isn't found, but the generic catch block caught that Response,
logged it as an error (with an empty {} body because Error fields
are non-enumerable), and rethrew as a 500 — so clients saw a 500
instead of the intended 404, and every stale-waitpoint request
produced a Sentry event.

Fix: re-throw Response objects unchanged so the correct status
propagates and we don't log user 404s as errors. Also serialize
remaining Error instances explicitly (name/message/stack) so the
logs are actionable when we do hit a real error.

2. v3/marqs/sharedQueueConsumer.server.ts:603

"Task run has invalid status for execution. Going to ack" — the
message itself says we're handling it gracefully. Benign race
between dequeue and completion/cancellation. Demote to warn.
2026-04-17 09:34:13 +01:00
devin-ai-integration[bot] ff290dfe2f perf(run-engine): merge dequeue snapshot creation into taskRun.update transaction [TRI-8450] (#3395)
## Summary

Nests the `TaskRunExecutionSnapshot` creation inside the
`taskRun.update()` Prisma call in the dequeue flow, reducing **2 DB
commits → 1** per dequeue operation. This is the highest-volume of the
five unmerged flows identified in TRI-8450 (~9,200 commits/sec on the
engine service).

**Pattern**: Follows the same nested-write approach already used in the
completion path (`runAttemptSystem.ts:735`) and trigger path
(`engine/index.ts:674`).

**Changes**:
- `dequeueSystem.ts`: Moved snapshot creation into `executionSnapshots:
{ create: {...} }` within the existing `taskRun.update()`. Pre-generates
the snapshot ID via `generateInternalId()` (plain cuid, matching what
Prisma's `@default(cuid())` produces) so the event emission, heartbeat
enqueue, and return value can all be constructed from data already in
scope — **no extra DB read needed** after the merged write.
`SnapshotId.toFriendlyId()` is used only for the return value's
`friendlyId` field, matching the original `createExecutionSnapshot`
behavior.
- `executionSnapshotSystem.ts`: Added public
`enqueueHeartbeatIfNeeded()` method that exposes the heartbeat
scheduling logic (previously only available internally via
`createExecutionSnapshot`). This is needed because `PENDING_EXECUTING`
requires a heartbeat, unlike the `FINISHED` status in the completion
reference pattern. This method is reusable by future merge targets
(retry-immediate, checkpoint, cancel, requeue).

**Net DB change per dequeue**: eliminates 1 write transaction (the
separate `TaskRunExecutionSnapshot.create`). No extra reads added — the
snapshot ID is pre-generated and the `executionSnapshotCreated` event
payload is constructed inline from values already available in the
closure.

## Review & Testing Checklist for Human

- [ ] **Verify manually-constructed event payload matches DB state**:
The `executionSnapshotCreated` event is now built inline (not read back
from DB). Confirm the field values (`runStatus: "PENDING"`,
`attemptNumber`, `checkpointId`, `workerId`, `runnerId`,
`completedWaitpointIds`) match what Prisma actually writes. A mismatch
here would be silent — event consumers would get stale/wrong data.
- [ ] **Verify `attemptNumber` source is equivalent**: Old code used
`lockedTaskRun.attemptNumber` (post-update result). New code uses
`result.run.attemptNumber` (pre-update). The `taskRun.update()` data
payload does NOT include `attemptNumber`, so they should be identical —
but confirm this assumption holds for all dequeue scenarios (e.g.
retried runs).
- [ ] **Verify `isValid` defaults to `true` in schema**: The old
`createExecutionSnapshot` explicitly set `isValid: error ? false :
true`. The nested create omits `isValid` (no error in the dequeue happy
path). Confirm the Prisma schema default for
`TaskRunExecutionSnapshot.isValid` is `true`.
- [ ] **Verify `runStatus: "PENDING"` hardcoding matches the mapping**:
The old code passed `lockedTaskRun.status` ("DEQUEUED") to
`createExecutionSnapshot`, which mapped it to "PENDING" via `run.status
=== "DEQUEUED" ? "PENDING" : run.status`. The new code hardcodes
`"PENDING"` directly. This is correct but brittle if `status` ever
changes from "DEQUEUED" to something else upstream.
- [ ] **Spot-check `completedWaitpoints` connect + order logic**: The
nested create replicates the connect/order logic from
`createExecutionSnapshot` (lines 387-393). Verify the
`snapshot.completedWaitpoints` type provides `id` and `index` fields
compatible with this usage.
- [ ] **Verify `checkpoint` in return value**: The return now uses
`snapshot.checkpoint` (from the *previous* snapshot) instead of reading
the newly-created snapshot's checkpoint relation. Since `checkpointId`
is passed through unchanged, they should be identical — but worth a
sanity check.

**Recommended test plan**: deploy to staging, run the
`sample_pg_activity.py` sampler for a 5-minute window, and verify the
COMMIT count drop on the engine service + proportional `IO:XactSync`
reduction.

### Notes
- This only covers the **dequeue** flow (flow #1 from TRI-8450). The
remaining four flows (retry-immediate, checkpoint, requeue, cancel) are
separate follow-ups.
- The new `enqueueHeartbeatIfNeeded` method is deliberately designed for
reuse by those follow-up PRs.
- CI note: the `priority.test.ts` failure in shard 7 is a flaky ordering
assertion unrelated to this change (it compares `friendlyId` values in
dequeue order). The `audit` check is also pre-existing/unrelated.

Link to Devin session:
https://app.devin.ai/sessions/034fe0e7224f49278a2de260203e1377
Requested by: @ericallam

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <eallam@icloud.com>
2026-04-16 15:43:16 +01:00
Eric Allam 67d2025f33 feat(webapp): add 60s/60s SWR cache to getEntitlement (#3388)
Wraps getEntitlement in platform.v3.server.ts with the existing
platformCache (LRU memory + Redis) under a new `entitlement` namespace.
Eliminates a synchronous billing-service HTTP round trip on every
trigger.

Cache config: 60s fresh / 60s stale SWR. Cache key is the
organization id. Errors are caught inside the loader and return the
existing permissive { hasAccess: true } fallback, which is also
cached to prevent thundering-herd on billing outages.

Trade-off: plan upgrade/downgrade is now visible after up to ~120s
worst-case (60s fresh + 60s stale revalidation). Acceptable since
the existing limits and usage namespaces use 5min/10min, and the
defensive hasAccess: true fallback already exists.
2026-04-16 15:37:27 +01:00
Eric Allam 79b6053e13 feat(server): add TaskIdentifier registry to replace expensive distinct query (#3368)
Replace the expensive DISTINCT query for task filter dropdowns with a
dedicated TaskIdentifier registry table backed by Redis. Environments
migrate automatically on their next deploy, with a transparent fallback
to the legacy query for unmigrated environments. Also fixes duplicate
dropdown entries when a task changes trigger source, and adds
active/archived grouping for removed tasks. Moves BackgroundWorkerTask
reads in the trigger hot path to the read replica.
2026-04-16 15:22:19 +01:00
Eric Allam 94abe97132 fix(webapp): prevent dashboard crash when span accessory text is not a string (#3400) 2026-04-16 15:15:23 +01:00
Eric Allam 02d2334c8a fix(webapp): fix Redis connection leak in realtime streams and broken abort signal propagation (#3399)
Pool Redis connections for non-blocking ops (ingestData, appendPart,
getLastChunkIndex)
using a shared singleton instead of new Redis() per request. Use
redis.disconnect()
for immediate teardown in streamResponse cleanup. Add 15s inactivity
timeout fallback.

Fix broken request.signal in Remix/Express by wiring Express
res.on('close') to an
AbortController via httpAsyncStorage. All SSE/streaming routes now use
getRequestAbortSignal() which fires reliably on client disconnect,
bypassing the
Node.js undici GC bug (nodejs/node#55428) that severs the signal chain.
2026-04-16 15:15:10 +01:00
Eric Allam f5b4d34c4b chore: allow Devin bot in claude-code-action workflows (#3401) 2026-04-16 15:33:20 +02:00
nicktrn 93f2ca6bf4 feat(webapp): extend admin workers endpoint and unify admin api auth (#3390)
Extends the admin worker groups endpoint with a GET loader and more
fields on POST (type, hidden, workloadType, cloudProvider, location,
staticIPs, enableFastPath), and pulls the PAT + admin check that was
inlined or locally duplicated across every admin.api route into a shared
helper in personalAccessToken.server.ts. The generic
authenticateAdminRequest returns a discriminated result;
requireAdminApiRequest is the thin Remix loader/action wrapper that
throws. The neverthrow-style route (platform-notifications.ts) now
composes the generic helper instead of duplicating the check. Verified
locally against GET (listing) and POST (new fields, invalid enum,
minimal backwards-compat).
2026-04-16 13:46:53 +01:00
Eric Allam 0c33de88f0 chore: add Devin bot to vouch list and skip draft requirement (#3396) 2026-04-16 11:38:45 +01:00
Eric Allam 7c95207486 fix(run-engine): Stop querying for associated run tags during dequeue (#3379) 2026-04-15 16:38:32 +01:00
devin-ai-integration[bot] 7d82041809 fix(security): upgrade Remix packages 2.1.0 → 2.17.4 (#3372)
## Summary

Upgrades all `@remix-run/*` packages in `apps/webapp` from **2.1.0 →
2.17.4** to address security vulnerabilities. Recreation of #2951 on a
fresh checkout of `main`.

**Updated packages (`apps/webapp/package.json`):**
- `@remix-run/express`, `@remix-run/node`, `@remix-run/react`,
`@remix-run/serve`, `@remix-run/server-runtime`: 2.1.0 → 2.17.4
- `@remix-run/router`: ^1.15.3 → ^1.23.2
- `@remix-run/dev`, `@remix-run/eslint-config`, `@remix-run/testing`:
2.1.0 → 2.17.4

**Root `package.json` overrides:**
- `@remix-run/dev@2.17.4>tar-fs`: 2.1.3 → 2.1.4
- `testcontainers@10.28.0>tar-fs`: 3.0.9 → 3.1.1

**Documentation:** Updated Remix version references in `CLAUDE.md`,
`apps/webapp/CLAUDE.md`, and `.cursor/rules/webapp.mdc`.

**Server changes:** Added `.server-changes/upgrade-remix-security.md`
for release tracking per `CONTRIBUTING.md`.

No application code changes — only `package.json` files, documentation,
a server-changes entry, and the regenerated `pnpm-lock.yaml`.

### Updates since last revision

Addressed all 3 Devin Review findings:
1. **Missing `.server-changes/` file** — added
`.server-changes/upgrade-remix-security.md` (commit ce22a0bd4)
2. **Sentry Remix patch (`@sentry/remix@9.46.0`)** — verified the patch
at `patches/@sentry__remix@9.46.0.patch` applies cleanly against 2.17.4.
The patch modifies Sentry's own `RemixInstrumentation` wrapper (removing
`request.clone()` and form data attributes), not Remix internals. The
underlying Remix APIs it hooks into (`callRouteAction`,
`callRouteLoader`) are stable across 2.1→2.17.
3. **`remix-typedjson@0.3.1` compatibility** — peer deps declare
`@remix-run/react: ^1.16.0 || ^2.0`, covering 2.17.4. Confirmed working
at runtime across all 22 tested pages that use it (root.tsx, hooks,
route loaders).

### Verification performed during this session

- **Runtime:** Express+Remix integration, magic link login, client-side
routing, MetaFunction rendering
- **Operational:** hello-world task triggered via API, runs list, run
detail, tasks page
- **Comprehensive UI:** 22 pages, 11 filter types, environment/project
switchers, interactive elements
- **Docker:** Production Dockerfile (`docker/webapp/Dockerfile`) builds
successfully
- **Changelog audit:** All 16 minor versions reviewed — every breaking
change is behind opt-in future flags the webapp doesn't enable

## Review & Testing Checklist for Human

- [ ] **Verify auth flows in staging** — `remix-auth`,
`remix-auth-email-link`, and `remix-auth-github` declare peer deps on
`@remix-run/server-runtime@^1.x`, which is now 2.17.4. Login (magic link
+ OAuth) should be tested in a staging environment since local dev
testing may not exercise all auth code paths.
- [ ] **Verify tar-fs override versions** resolve the targeted security
advisories (2.1.4 and 3.1.1)
- [ ] **Review new transitive dependencies** added by the upgrade:
`turbo-stream@2.4.1`, `undici@6.25.0`, `valibot@1.3.1`, `ws@7.5.10`

Recommended test plan: deploy to staging and exercise core webapp flows
— login (email magic link + GitHub OAuth), dashboard navigation, task
triggering/viewing, and API endpoints — to catch runtime regressions not
covered by local testing.

### Notes
- Peer dependency warnings for `remix-auth-*` packages (expecting
`@remix-run/server-runtime@^1.x`) were present in the original PR #2951
as well and appear to be pre-existing
- The lockfile diff is large (~1200 lines) but mechanical — driven by
the Remix version bump cascading through transitive dependencies
- CI failures (`audit`, `units/internal/1-of-8`) are unrelated: `audit`
is a `claude-code-action` bot permissions issue; the internal test
failure is a ClickHouse testcontainers `Failed to connect to Reaper`
flake

Link to Devin session:
https://app.devin.ai/sessions/d9fa9953b9bf40e5a8d12b8f5ba5b86b
Requested by: @ericallam

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <eallam@icloud.com>
2026-04-15 13:50:22 +01:00
Eric Allam 73ea5865d8 fix(run-engine): distinguish oneTimeUseToken P2002 from idempotency key collision (#3374)
Prevent retrying when retrying won’t actually do any good
2026-04-15 10:42:58 +01:00
Oskar Otwinowski 097fab0d8c feat(webapp): Vercel integration - disable auto promotions (#3376)
<img width="1044" height="709" alt="image"
src="https://github.com/user-attachments/assets/7f2cf25c-3b74-46a9-8794-41be077e04bf"
/>
2026-04-14 19:29:31 +02:00
Iss 7fdb2c4d1e docs: troubleshooting and additional packages version pinning (#3092)
- Connection error troubleshooting
- Additional packages version pinning
- Realtime stream error troubleshooting
2026-04-14 15:11:06 +01:00
Iss f0f4527655 docs: added startup_timeout_sec note (#3124) 2026-04-14 15:10:49 +01:00
Iss b8ce6939b6 docs: adds deduplication key clarification (#3151) 2026-04-14 15:10:04 +01:00
Iss 54d22e9ee1 docs: add per-task middleware section to tasks overview (#3197) 2026-04-14 15:09:48 +01:00
Iss 8b4ac45aed docs: add Bun runtime setup for Sentry error tracking (#3233) 2026-04-14 15:09:32 +01:00
Iss 57a634ea50 docs: note retry.onThrow as a parallel wait (#3248) 2026-04-14 15:09:16 +01:00
Iss c37bb9abc8 docs: add Nango OAuth integration guide (#3262)
Adds a guide showing how to use Nango to make authenticated API calls
inside a Trigger.dev task, using GitHub + Claude as a concrete example.
2026-04-14 15:08:53 +01:00
Iss f2b1b76a07 docs: add list deployments endpoint, fix defaultMachine, and clarify wait token browser completion (#3350)
Adds missing list deployments API page, fixes defaultMachine → machine
in config docs, and clarifies browser CORS usage for wait token
completion with corrected warning placement
2026-04-14 15:08:33 +01:00
Eric Allam f739a5c545 fix(db): add index to ProjectAlertStorage to prevent sequence scans (#3349) 2026-04-14 15:04:16 +01:00
Eric Allam ed0c3e4f38 fix: stop creating TaskRunTag records and join table entries during triggering (#3369)
The TaskRun.runTags string array already stores tag names, making the
TaskRunTag M2M relation redundant write overhead. Remove createTags
calls, connect: tags, and join table writes from both V1 and V2 trigger
paths. Simplify the add-tags API to just push to runTags directly.
2026-04-14 05:40:51 +01:00
Eric Allam c09983ef19 docs(cli): Expand and improve the MCP server and dev CLI command (#3225)
Depends on #3224
2026-04-13 14:27:45 +01:00
Eric Allam 417ab876e3 fix(batch-queue): Batch items that hit the environment queue size limit now fast-fail (#3352) 2026-04-13 14:24:38 +01:00
nicktrn 4d7fbf0b1b docs: add task-level and config-level TTL documentation (#3200)
Documents TTL support at task-level and config-level. Companion to #3196
- merge after new packages are released.
2026-04-13 14:23:24 +01:00
github-actions[bot] 5ea36e08f2 chore: release v4.4.4 (#3228)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
## Summary
12 new features, 59 improvements, 17 bug fixes.

## Highlights

- Add support for setting TTL (time-to-live) defaults at the task level
and globally in trigger.config.ts, with per-trigger overrides still
taking precedence
([#3196](https://github.com/triggerdotdev/trigger.dev/pull/3196))
- Large run outputs can use the new API which allows switching object
storage providers.
([#3275](https://github.com/triggerdotdev/trigger.dev/pull/3275))

## Improvements
- Add platform notifications support to the CLI. The `trigger dev` and
`trigger login` commands now fetch and display platform notifications
(info, warn, error, success) from the server. Includes discovery-based
filtering to conditionally show notifications based on project file
patterns, color markup rendering for styled terminal output, and a
non-blocking display flow with a spinner fallback for slow fetches. Use
`--skip-platform-notifications` flag with `trigger dev` to disable the
notification check.
([#3254](https://github.com/triggerdotdev/trigger.dev/pull/3254))
- Add `get_span_details` MCP tool for inspecting individual spans within
a run trace.
([#3255](https://github.com/triggerdotdev/trigger.dev/pull/3255))
- New `get_span_details` tool returns full span attributes, timing,
events, and AI enrichment (model, tokens, cost, speed)
- Span IDs now shown in `get_run_details` trace output for easy
discovery
- New API endpoint `GET /api/v1/runs/:runId/spans/:spanId`
- New `retrieveSpan()` method on the API client
- `get_query_schema` — discover available TRQL tables and columns
- `query` — execute TRQL queries against your data
- `list_dashboards` — list built-in dashboards and their widgets
- `run_dashboard_query` — execute a single dashboard widget query
- `whoami` — show current profile, user, and API URL
- `list_profiles` — list all configured CLI profiles
- `switch_profile` — switch active profile for the MCP session
- `start_dev_server` — start `trigger dev` in the background and stream
output
- `stop_dev_server` — stop the running dev server
- `dev_server_status` — check dev server status and view recent logs
- `GET /api/v1/query/schema` — query table schema discovery
- `GET /api/v1/query/dashboards` — list built-in dashboards
- `--readonly` flag hides write tools (`deploy`, `trigger_task`,
`cancel_run`) so the AI cannot make changes
- `read:query` JWT scope for query endpoint authorization
- `get_run_details` trace output is now paginated with cursor support
- MCP tool annotations (`readOnlyHint`, `destructiveHint`) for all tools
- `get_query_schema` now requires a table name and returns only one
table's schema (was returning all tables)
- `get_current_worker` no longer inlines payload schemas; use new
`get_task_schema` tool instead
- Query results formatted as text tables instead of JSON (~50% fewer
tokens)
- `cancel_run`, `list_deploys`, `list_preview_branches` formatted as
text instead of raw JSON
- Schema and dashboard API responses cached to avoid redundant fetches
- Adapted the CLI API client to propagate the trigger source via http
headers.
([#3241](https://github.com/triggerdotdev/trigger.dev/pull/3241))
- Propagate run tags to span attributes so they can be extracted
server-side for LLM cost attribution metadata.
([#3213](https://github.com/triggerdotdev/trigger.dev/pull/3213))
- New `get_span_details` tool returns full span attributes, timing,
events, and AI enrichment (model, tokens, cost, speed)
- Span IDs now shown in `get_run_details` trace output for easy
discovery
- New API endpoint `GET /api/v1/runs/:runId/spans/:spanId`
- New `retrieveSpan()` method on the API client
- `get_query_schema` — discover available TRQL tables and columns
- `query` — execute TRQL queries against your data
- `list_dashboards` — list built-in dashboards and their widgets
- `run_dashboard_query` — execute a single dashboard widget query
- `whoami` — show current profile, user, and API URL
- `list_profiles` — list all configured CLI profiles
- `switch_profile` — switch active profile for the MCP session
- `start_dev_server` — start `trigger dev` in the background and stream
output
- `stop_dev_server` — stop the running dev server
- `dev_server_status` — check dev server status and view recent logs
- `GET /api/v1/query/schema` — query table schema discovery
- `GET /api/v1/query/dashboards` — list built-in dashboards
- `--readonly` flag hides write tools (`deploy`, `trigger_task`,
`cancel_run`) so the AI cannot make changes
- `read:query` JWT scope for query endpoint authorization
- `get_run_details` trace output is now paginated with cursor support
- MCP tool annotations (`readOnlyHint`, `destructiveHint`) for all tools
- `get_query_schema` now requires a table name and returns only one
table's schema (was returning all tables)
- `get_current_worker` no longer inlines payload schemas; use new
`get_task_schema` tool instead
- Query results formatted as text tables instead of JSON (~50% fewer
tokens)
- `cancel_run`, `list_deploys`, `list_preview_branches` formatted as
text instead of raw JSON
- Schema and dashboard API responses cached to avoid redundant fetches
- Add optional `hasPrivateLink` field to the dequeue message
organization object for private networking support
([#3264](https://github.com/triggerdotdev/trigger.dev/pull/3264))
- Define and manage AI prompts with `prompts.define()`. Create typesafe
prompt templates with variables, resolve them at runtime, and manage
versions and overrides from the dashboard without redeploying.
([#3244](https://github.com/triggerdotdev/trigger.dev/pull/3244))

## Bug fixes
- Fix dev CLI leaking build directories on rebuild, causing disk space
accumulation. Deprecated workers are now pruned (capped at 2 retained)
when no active runs reference them. The watchdog process also cleans up
`.trigger/tmp/` when the dev CLI is killed ungracefully (e.g. SIGKILL
from pnpm).
([#3224](https://github.com/triggerdotdev/trigger.dev/pull/3224))
- Fix `--load` flag being silently ignored on local/self-hosted builds.
([#3114](https://github.com/triggerdotdev/trigger.dev/pull/3114))
- Fixed `search_docs` tool failing due to renamed upstream Mintlify tool
(`SearchTriggerDev` → `search_trigger_dev`)
- Fixed `list_deploys` failing when deployments have null
`runtime`/`runtimeVersion` fields (#3139)
- Fixed `list_preview_branches` crashing due to incorrect response shape
access
- Fixed `metrics` table column documented as `value` instead of
`metric_value` in query docs
- Fixed dev CLI leaking build directories on rebuild — deprecated
workers now clean up their build dirs when their last run completes
- Fixed `search_docs` tool failing due to renamed upstream Mintlify tool
(`SearchTriggerDev` → `search_trigger_dev`)
- Fixed `list_deploys` failing when deployments have null
`runtime`/`runtimeVersion` fields (#3139)
- Fixed `list_preview_branches` crashing due to incorrect response shape
access
- Fixed `metrics` table column documented as `value` instead of
`metric_value` in query docs
- Fixed dev CLI leaking build directories on rebuild — deprecated
workers now clean up their build dirs when their last run completes

## Server changes

These changes affect the self-hosted Docker image and Trigger.dev Cloud:

- Add admin UI for viewing and editing feature flags (org-level
overrides and global defaults).
([#3291](https://github.com/triggerdotdev/trigger.dev/pull/3291))
- AI prompt management dashboard and enhanced span inspectors.
  
  **Prompt management:**
- Prompts list page with version status, model, override indicators, and
24h usage sparklines
- Prompt detail page with template viewer, variable preview, version
history timeline, and override editor
- Create, edit, and remove overrides to change prompt content or model
without redeploying
  - Promote any code-deployed version to current
- Generations tab with infinite scroll, live polling, and inline span
inspector
- Per-prompt metrics: total generations, avg tokens, avg cost, latency,
with version-level breakdowns
  
  **AI span inspectors:**
- Custom inspectors for `ai.generateText`, `ai.streamText`,
`ai.generateObject`, `ai.streamObject` parent spans
- `ai.toolCall` inspector showing tool name, call ID, and input
arguments
  - `ai.embed` inspector showing model, provider, and input text
- Prompt tab on AI spans linking to prompt version with template and
input variables
  - Compact timestamp and duration header on all AI span inspectors
  
  **AI metrics dashboard:**
- Operations, Providers, and Prompts filters on the AI Metrics dashboard
  - Cost by prompt widget
  - "AI" section in the sidebar with Prompts and AI Metrics links
  
  **Other improvements:**
  - Resizable panel sizes now persist across page refreshes
- Fixed `<div>` inside `<p>` DOM nesting warnings in span titles and
chat messages
([#3244](https://github.com/triggerdotdev/trigger.dev/pull/3244))
- Add allowRollbacks query param to the promote deployment API to enable
version downgrades
([#3214](https://github.com/triggerdotdev/trigger.dev/pull/3214))
- Pre-warm compute templates on deploy for orgs with compute access.
Required for projects using a compute region, background-only for
others.
([#3114](https://github.com/triggerdotdev/trigger.dev/pull/3114))
- Add automatic LLM cost calculation for spans with GenAI semantic
conventions. When a span arrives with `gen_ai.response.model` and token
usage data, costs are calculated from an in-memory pricing registry
backed by Postgres and dual-written to both span attributes
(`trigger.llm.*`) and a new `llm_metrics_v1` ClickHouse table that
captures usage, cost, performance (TTFC, tokens/sec), and behavioral
(finish reason, operation type) metrics.
([#3213](https://github.com/triggerdotdev/trigger.dev/pull/3213))
- Add API endpoint `GET /api/v1/runs/:runId/spans/:spanId` that returns
detailed span information including properties, events, AI enrichment
(model, tokens, cost), and triggered child runs.
([#3255](https://github.com/triggerdotdev/trigger.dev/pull/3255))
- Multi-provider object storage with protocol-based routing for
zero-downtime migration
([#3275](https://github.com/triggerdotdev/trigger.dev/pull/3275))
- Add IAM role-based auth support for object stores (no access keys
required).
([#3275](https://github.com/triggerdotdev/trigger.dev/pull/3275))
- Add platform notifications to inform users about new features,
changelogs, and platform events directly in the dashboard.
([#3254](https://github.com/triggerdotdev/trigger.dev/pull/3254))
- Add private networking support via AWS PrivateLink. Includes
BillingClient methods for managing private connections, org settings UI
pages for connection management, and supervisor changes to apply
`privatelink` pod labels for CiliumNetworkPolicy matching.
([#3264](https://github.com/triggerdotdev/trigger.dev/pull/3264))
- Reduce run start latency by skipping the intermediate queue when
concurrency is available. This optimization is rolled out per-region and
enabled automatically for development environments.
([#3299](https://github.com/triggerdotdev/trigger.dev/pull/3299))
- Extended the search filter on the environment variables page to match
on environment type (production, staging, development, preview) and
branch name, not just variable name and value.
([#3302](https://github.com/triggerdotdev/trigger.dev/pull/3302))
- Set `application_name` on Prisma connections from SERVICE_NAME so DB
load can be attributed by service
([#3348](https://github.com/triggerdotdev/trigger.dev/pull/3348))
- Fix transient R2/object store upload failures during batchTrigger()
item streaming.
  
- Added p-retry (3 attempts, 500ms–2s exponential backoff) around
`uploadPacketToObjectStore` in `BatchPayloadProcessor.process()` so
transient network errors self-heal server-side rather than aborting the
entire batch stream.
- Removed `x-should-retry: false` from the 500 response on the batch
items route so the SDK's existing 5xx retry path can recover if
server-side retries are exhausted. Item deduplication by index makes
full-stream retries safe.
([#3331](https://github.com/triggerdotdev/trigger.dev/pull/3331))
- Concurrency-keyed queues now use a single master queue entry per base
queue instead of one entry per key. Prevents high-CK-count tenants from
consuming the entire parentQueueLimit window and starving other tenants
on the same shard.
([#3219](https://github.com/triggerdotdev/trigger.dev/pull/3219))
- Reduce lock contention when processing large `batchTriggerAndWait`
batches. Previously, each batch item acquired a Redis lock on the parent
run to insert a `TaskRunWaitpoint` row, causing
`LockAcquisitionTimeoutError` with high concurrency (880 errors/24h in
prod). Since `blockRunWithCreatedBatch` already transitions the parent
to `EXECUTING_WITH_WAITPOINTS` before items are processed, the per-item
lock is unnecessary. The new `blockRunWithWaitpointLockless` method
performs only the idempotent CTE insert without acquiring the lock.
([#3232](https://github.com/triggerdotdev/trigger.dev/pull/3232))
- Strip `secure` query parameter from QUERY_CLICKHOUSE_URL before
passing to ClickHouse client. This was already done for the main and
logs ClickHouse clients but was missing for the query client, causing a
startup crash with `Error: Unknown URL parameters: secure`.
([#3204](https://github.com/triggerdotdev/trigger.dev/pull/3204))
- Fix `OrganizationsPresenter.#getEnvironment` matching the wrong
development environment on teams with multiple members. All dev
environments share the slug `"dev"`, so the previous `find` by slug
alone could return another member's environment. Now filters DEVELOPMENT
environments by `orgMember.userId` to ensure the logged-in user's dev
environment is selected.
([#3273](https://github.com/triggerdotdev/trigger.dev/pull/3273))

<details>
<summary>Raw changeset output</summary>

# Releases
## @trigger.dev/build@4.4.4

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.4`

## trigger.dev@4.4.4

### Patch Changes

- Add platform notifications support to the CLI. The `trigger dev` and
`trigger login` commands now fetch and display platform notifications
(info, warn, error, success) from the server. Includes discovery-based
filtering to conditionally show notifications based on project file
patterns, color markup rendering for styled terminal output, and a
non-blocking display flow with a spinner fallback for slow fetches. Use
`--skip-platform-notifications` flag with `trigger dev` to disable the
notification check.
([#3254](https://github.com/triggerdotdev/trigger.dev/pull/3254))

- Fix dev CLI leaking build directories on rebuild, causing disk space
accumulation. Deprecated workers are now pruned (capped at 2 retained)
when no active runs reference them. The watchdog process also cleans up
`.trigger/tmp/` when the dev CLI is killed ungracefully (e.g. SIGKILL
from pnpm).
([#3224](https://github.com/triggerdotdev/trigger.dev/pull/3224))

- Fix `--load` flag being silently ignored on local/self-hosted builds.
([#3114](https://github.com/triggerdotdev/trigger.dev/pull/3114))

- Add `get_span_details` MCP tool for inspecting individual spans within
a run trace.
([#3255](https://github.com/triggerdotdev/trigger.dev/pull/3255))

- New `get_span_details` tool returns full span attributes, timing,
events, and AI enrichment (model, tokens, cost, speed)
- Span IDs now shown in `get_run_details` trace output for easy
discovery
    -   New API endpoint `GET /api/v1/runs/:runId/spans/:spanId`
    -   New `retrieveSpan()` method on the API client

- MCP server improvements: new tools, bug fixes, and new flags.
([#3224](https://github.com/triggerdotdev/trigger.dev/pull/3224))

    **New tools:**

    -   `get_query_schema` — discover available TRQL tables and columns
    -   `query` — execute TRQL queries against your data
    -   `list_dashboards` — list built-in dashboards and their widgets
    -   `run_dashboard_query` — execute a single dashboard widget query
    -   `whoami` — show current profile, user, and API URL
    -   `list_profiles` — list all configured CLI profiles
    -   `switch_profile` — switch active profile for the MCP session
- `start_dev_server` — start `trigger dev` in the background and stream
output
    -   `stop_dev_server` — stop the running dev server
- `dev_server_status` — check dev server status and view recent logs

    **New API endpoints:**

    -   `GET /api/v1/query/schema` — query table schema discovery
    -   `GET /api/v1/query/dashboards` — list built-in dashboards

    **New features:**

- `--readonly` flag hides write tools (`deploy`, `trigger_task`,
`cancel_run`) so the AI cannot make changes
    -   `read:query` JWT scope for query endpoint authorization
- `get_run_details` trace output is now paginated with cursor support
- MCP tool annotations (`readOnlyHint`, `destructiveHint`) for all tools

    **Bug fixes:**

- Fixed `search_docs` tool failing due to renamed upstream Mintlify tool
(`SearchTriggerDev` → `search_trigger_dev`)
- Fixed `list_deploys` failing when deployments have null
`runtime`/`runtimeVersion` fields (#3139)
- Fixed `list_preview_branches` crashing due to incorrect response shape
access
- Fixed `metrics` table column documented as `value` instead of
`metric_value` in query docs
- Fixed dev CLI leaking build directories on rebuild — deprecated
workers now clean up their build dirs when their last run completes

    **Context optimizations:**

- `get_query_schema` now requires a table name and returns only one
table's schema (was returning all tables)
- `get_current_worker` no longer inlines payload schemas; use new
`get_task_schema` tool instead
- Query results formatted as text tables instead of JSON (~50% fewer
tokens)
- `cancel_run`, `list_deploys`, `list_preview_branches` formatted as
text instead of raw JSON
- Schema and dashboard API responses cached to avoid redundant fetches

- Add support for setting TTL (time-to-live) defaults at the task level
and globally in trigger.config.ts, with per-trigger overrides still
taking precedence
([#3196](https://github.com/triggerdotdev/trigger.dev/pull/3196))

- Adapted the CLI API client to propagate the trigger source via http
headers.
([#3241](https://github.com/triggerdotdev/trigger.dev/pull/3241))

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.4`
    -   `@trigger.dev/build@4.4.4`
    -   `@trigger.dev/schema-to-json@4.4.4`

## @trigger.dev/core@4.4.4

### Patch Changes

- Fix `list_deploys` MCP tool failing when deployments have null
`runtime` or `runtimeVersion` fields.
([#3224](https://github.com/triggerdotdev/trigger.dev/pull/3224))

- Propagate run tags to span attributes so they can be extracted
server-side for LLM cost attribution metadata.
([#3213](https://github.com/triggerdotdev/trigger.dev/pull/3213))

- Add `get_span_details` MCP tool for inspecting individual spans within
a run trace.
([#3255](https://github.com/triggerdotdev/trigger.dev/pull/3255))

- New `get_span_details` tool returns full span attributes, timing,
events, and AI enrichment (model, tokens, cost, speed)
- Span IDs now shown in `get_run_details` trace output for easy
discovery
    -   New API endpoint `GET /api/v1/runs/:runId/spans/:spanId`
    -   New `retrieveSpan()` method on the API client

- MCP server improvements: new tools, bug fixes, and new flags.
([#3224](https://github.com/triggerdotdev/trigger.dev/pull/3224))

    **New tools:**

    -   `get_query_schema` — discover available TRQL tables and columns
    -   `query` — execute TRQL queries against your data
    -   `list_dashboards` — list built-in dashboards and their widgets
    -   `run_dashboard_query` — execute a single dashboard widget query
    -   `whoami` — show current profile, user, and API URL
    -   `list_profiles` — list all configured CLI profiles
    -   `switch_profile` — switch active profile for the MCP session
- `start_dev_server` — start `trigger dev` in the background and stream
output
    -   `stop_dev_server` — stop the running dev server
- `dev_server_status` — check dev server status and view recent logs

    **New API endpoints:**

    -   `GET /api/v1/query/schema` — query table schema discovery
    -   `GET /api/v1/query/dashboards` — list built-in dashboards

    **New features:**

- `--readonly` flag hides write tools (`deploy`, `trigger_task`,
`cancel_run`) so the AI cannot make changes
    -   `read:query` JWT scope for query endpoint authorization
- `get_run_details` trace output is now paginated with cursor support
- MCP tool annotations (`readOnlyHint`, `destructiveHint`) for all tools

    **Bug fixes:**

- Fixed `search_docs` tool failing due to renamed upstream Mintlify tool
(`SearchTriggerDev` → `search_trigger_dev`)
- Fixed `list_deploys` failing when deployments have null
`runtime`/`runtimeVersion` fields (#3139)
- Fixed `list_preview_branches` crashing due to incorrect response shape
access
- Fixed `metrics` table column documented as `value` instead of
`metric_value` in query docs
- Fixed dev CLI leaking build directories on rebuild — deprecated
workers now clean up their build dirs when their last run completes

    **Context optimizations:**

- `get_query_schema` now requires a table name and returns only one
table's schema (was returning all tables)
- `get_current_worker` no longer inlines payload schemas; use new
`get_task_schema` tool instead
- Query results formatted as text tables instead of JSON (~50% fewer
tokens)
- `cancel_run`, `list_deploys`, `list_preview_branches` formatted as
text instead of raw JSON
- Schema and dashboard API responses cached to avoid redundant fetches

- Large run outputs can use the new API which allows switching object
storage providers.
([#3275](https://github.com/triggerdotdev/trigger.dev/pull/3275))

- Add optional `hasPrivateLink` field to the dequeue message
organization object for private networking support
([#3264](https://github.com/triggerdotdev/trigger.dev/pull/3264))

- Add support for setting TTL (time-to-live) defaults at the task level
and globally in trigger.config.ts, with per-trigger overrides still
taking precedence
([#3196](https://github.com/triggerdotdev/trigger.dev/pull/3196))

- Adapted the CLI API client to propagate the trigger source via http
headers.
([#3241](https://github.com/triggerdotdev/trigger.dev/pull/3241))

## @trigger.dev/python@4.4.4

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/sdk@4.4.4`
    -   `@trigger.dev/core@4.4.4`
    -   `@trigger.dev/build@4.4.4`

## @trigger.dev/react-hooks@4.4.4

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.4`

## @trigger.dev/redis-worker@4.4.4

### Patch Changes

- Adapted the CLI API client to propagate the trigger source via http
headers.
([#3241](https://github.com/triggerdotdev/trigger.dev/pull/3241))
-   Updated dependencies:
    -   `@trigger.dev/core@4.4.4`

## @trigger.dev/rsc@4.4.4

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.4`

## @trigger.dev/schema-to-json@4.4.4

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.4`

## @trigger.dev/sdk@4.4.4

### Patch Changes

- Define and manage AI prompts with `prompts.define()`. Create typesafe
prompt templates with variables, resolve them at runtime, and manage
versions and overrides from the dashboard without redeploying.
([#3244](https://github.com/triggerdotdev/trigger.dev/pull/3244))
- Add support for setting TTL (time-to-live) defaults at the task level
and globally in trigger.config.ts, with per-trigger overrides still
taking precedence
([#3196](https://github.com/triggerdotdev/trigger.dev/pull/3196))
- Adapted the CLI API client to propagate the trigger source via http
headers.
([#3241](https://github.com/triggerdotdev/trigger.dev/pull/3241))
-   Updated dependencies:
    -   `@trigger.dev/core@4.4.4`

</details>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-13 13:24:38 +01:00
Oskar Otwinowski 3c9647cb8c feat(webapp): Platform notifications admin imporovements (#3324)
- bugfix to show the changelog to the target audience
- more functionality for admins, to edit, delete and archive
notifications
2026-04-13 12:26:15 +02:00
nicktrn e59614a31c feat(webapp): gate microvm regions behind compute access feature flag (#3366)
Adds region-level gating so MICROVM regions are only visible and usable
by orgs with the `hasComputeAccess` feature flag. Admins and explicit
allowlist behavior unchanged.

- New shared helper (`regionAccess.server.ts`) with
`resolveComputeAccess`, `defaultVisibilityFilter`, and
`isComputeRegionAccessible`
- `RegionsPresenter` filters out MICROVM regions for non-compute orgs
- `SetDefaultRegionService` blocks setting a MICROVM region as default
without compute access
- `WorkerGroupService` blocks triggering runs in MICROVM regions without
compute access
- `computeTemplateCreation` refactored to use shared
`resolveComputeAccess`
- Updated snapshot callback schema
2026-04-13 11:24:00 +01:00
nicktrn bd41bb2cbd feat(webapp): set application_name on prisma connections (#3348)
Sets `application_name` on the Prisma writer and replica connection
strings using the existing `SERVICE_NAME` env var, so DB load can be
attributed by service.
2026-04-08 22:32:46 +01:00
Matt Aitken def21b26b6 fix(batch): retry R2 upload on transient failure in BatchPayloadProcessor (#3331)
⚒️ Publish Worker (v4) / build (supervisor) (push) Has been cancelled
A single "fetch failed" from the object store was aborting the entire
batch stream with no retry. Added p-retry (3 attempts, 500ms-2s backoff)
around ploadPacketToObjectStore so transient network errors self-heal
server-side instead of propagating to the SDK.
2026-04-07 15:29:10 +01:00
James Ritchie 4f2ff3d9de fix(wabapp): Fix for wrapping text on run inspector (#3328)
### Text wrapping fix

- Fixes message text not wrapping on the run inspector if there were no
spaces in the text
- Fixes inspector title truncation
- Adds a copy text button for the Message property

<img width="468" height="740" alt="CleanShot 2026-04-04 at 10 19 02@2x"
src="https://github.com/user-attachments/assets/71e42bf3-d103-44a2-b3b4-937c0b60a4bc"
/>
2026-04-04 11:02:12 +01:00
James Ritchie cf0fdde3c4 Feat(webapp): animated resizable panel (#3319)
This is a small improvement mainly with the UI Skills file:

- Animate open and close the Resizable panels
- Uses the built in animation hooks from react-window-splitter
- Includes a global variable for the animation easing and timing for
consistency


https://github.com/user-attachments/assets/50ed0019-ed12-4e08-b95c-7c6d1fe5bac0
2026-04-03 14:03:37 +01:00
James Ritchie e31b03eac2 fix(webapp): Responsive improvements for the onboarding screens (#3318)
Simple responsive breakpoint changes to the 3 onboarding screens + the
login screen to make it mobile friendlier

<img width="523" height="872" alt="CleanShot 2026-04-02 at 17 18 55"
src="https://github.com/user-attachments/assets/815d19ca-df9b-4b3e-8f6d-e00c81628679"
/>
2026-04-02 22:38:02 +01:00
Eric Allam f1f1d02f1d feat(dashboard): a few tweaks to the AI models page (#3315) 2026-04-02 16:48:36 +01:00
Oskar Otwinowski ed64042168 feat(private-links): Show assigned IPs for provisioned private links (#3317) 2026-04-02 16:47:55 +02:00
Matt Aitken 0e14b6d750 TaskRun optimizations: dropping FKs and some indexes (#3309)
## Summary

- Drop all 8 foreign key constraints on TaskRun. The run listing path is
now fully ClickHouse-backed so we no longer need Postgres to enforce
referential integrity on this table. The FK constraints add write
overhead on every insert/update with no remaining benefit. Prisma
queries are unaffected.
- Remove PostgresRunsRepository and its associated feature flag
(runsListRepository), which was the last remaining code path querying
TaskRun directly for list/count operations.
- Drop three indexes that were only useful for the Postgres run list
path and have no remaining query consumers:
- TaskRun_runtimeEnvironmentId_id_idx — was the cursor pagination index
for PostgresRunsRepository; superseded by the (runtimeEnvironmentId,
createdAt DESC) composite index
- TaskRun_scheduleId_idx — redundant with the (scheduleId, createdAt
DESC) composite index; no direct Postgres queries filter by scheduleId
alone
- TaskRun_rootTaskRunId_idx — no queries filter TaskRun by rootTaskRunId
as a WHERE clause anywhere in the codebase

All index drops use CONCURRENTLY IF EXISTS to avoid table locks in
production.

## Test plan

  - pnpm run db:migrate:deploy applies all migrations cleanly
  - pnpm run typecheck --filter webapp passes
  - Run list pages load correctly in the dashboard (ClickHouse path)
  - Scheduled task runs still trigger and appear correctly
2026-04-01 15:40:17 +01:00
James Ritchie bf736a79fc Feat(webapp): Models page UI improvements (#3308)
Lots of layout and UI improvements to the new Models page

<img width="2282" height="1356" alt="CleanShot 2026-04-01 at 14 14 35"
src="https://github.com/user-attachments/assets/4a13a291-5d5b-415f-962f-b9cfb25b887d"
/>
2026-04-01 14:48:05 +01:00
DKP f75d4d62af docs: Remove old idempotencyKey warning (#3306) 2026-04-01 12:04:28 +01:00
Matt Aitken 68e88d0d71 Object Storage seamless migration (#3275)
This allows seamless migration to different object storage.

Existing runs that have offloaded payloads/outputs will continue to use
the default object store (configured using `OBJECT_STORE_*` env vars).

You can add additional stores by setting new env vars:
- `OBJECT_STORE_DEFAULT_PROTOCOL` this determines where new run large
payloads will get stored.
- If you set that you need to set new env vars for that protocol.
  
Example:

```
OBJECT_STORE_DEFAULT_PROTOCOL=“s3"
OBJECT_STORE_S3_BASE_URL=https://s3.us-east-1.amazonaws.com
OBJECT_STORE_S3_ACCESS_KEY_ID=<val>
OBJECT_STORE_S3_SECRET_ACCESS_KEY=<val>
OBJECT_STORE_S3_REGION=us-east-1
OBJECT_STORE_S3_SERVICE=s3
```

---------

Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2026-04-01 10:06:12 +01:00
Iss 2637e47195 docs: add migration guide from n8n to Trigger.dev (#3283)
Adds a migration reference for users moving from n8n to Trigger.dev.
Includes a concept map, four common patterns covering the
migration-specific gaps, and a full customer onboarding example. The
onboarding workflow highlights the 3-day wait pattern, an area where
n8n's execution model has known reliability issues at production scale
that Trigger.dev handles natively
2026-03-31 17:38:39 -04:00
Matt Aitken 0977c56efe Errors (versions) (#3187)
- Added versions filtering on the Errors list and page
- Added errors stacked bars to the graph on the individual error page

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2026-03-31 19:06:54 +01:00
nicktrn 2ba77d89dd fix: add build step to @internal/compute package (#3303)
The @internal/compute package had its main/types pointing to
./src/index.ts with no build step. This works in dev (tsc resolves .ts
at compile time) but fails at runtime in Docker because Node.js can't
load .ts files directly.

Added tsconfig.build.json and build/clean/dev scripts matching the
pattern used by schedule-engine and other internal packages. Exports now
point to dist/.
2026-03-31 13:23:46 +01:00
Saadi Myftija 1307d97f7a fix(webapp): match environment when searching env variables (#3302)
Temporary workaround that enables filtering by environment in the
envvars page, without changing any UI.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-31 12:53:05 +02:00
Eric Allam a3407287c9 feat(engine): enqueue fast path; skip the queue under certain conditions (#3299)
## Summary

Currently, every triggered run follows a two-step path through Redis:

1. **Enqueue** — A Lua script atomically adds the message to a queue
sorted set (ordered by priority-adjusted timestamp)
2. **Dequeue** — A debounced `processQueueForWorkerQueue` job fires
~500ms later, checks concurrency limits, removes the message from the
sorted set, and pushes it to a worker queue (Redis list) where workers
pick it up via `BLPOP`

This means every run pays at least ~500ms of latency between being
triggered and being available for a worker to execute, even when the
queue is empty and concurrency is wide open.

### What changed

The enqueue Lua scripts now atomically decide whether to **skip the
queue sorted set entirely** and push directly to the worker queue. This
happens inside the same Lua script that handles normal enqueue, so the
decision is atomic with respect to concurrency bookkeeping.

A run takes the **fast path** when all of these are true:
- **Fast path is enabled** for this worker queue (gated per
`WorkerInstanceGroup`)
- **No available messages** in the queue (`ZRANGEBYSCORE` finds nothing
with score ≤ now) — this respects priority ordering and allows fast path
even when the queue has future-scored messages (e.g. nacked retries with
delay)
- **Environment concurrency** has capacity
- **Queue concurrency** has capacity (including per-concurrency-key
limits for CK queues)

When the fast path is taken:
- The message is stored and pushed directly to the worker queue
(`RPUSH`)
- Concurrency slots are claimed (`SADD` to the same sets used by the
normal dequeue path)
- The `processQueueForWorkerQueue` job is **not scheduled** (no work to
do)
- TTL sorted set is skipped (the `expireRun` worker job handles TTL
independently)

When any condition fails, the existing slow path runs unchanged.

### Rollout gating

- **Development environments**: Fast path is always enabled
- **Production environments**: Gated by a new `enableFastPath` boolean
on `WorkerInstanceGroup` (defaults to `false`), allowing
region-by-region rollout

### Rolling deploy safety

Each process registers its own Lua scripts via `defineCommand`
(identified by SHA hash). Old and new processes never share scripts. The
Redis data structures are fully compatible in both directions — ack,
nack, and release operations work identically regardless of which path a
message took.

## Test plan

- [x] Fast path taken when queue is empty and concurrency available
- [x] Slow path when `enableFastPath` is false
- [x] Slow path when queue has available messages (respects priority
ordering)
- [x] Fast path when queue only has future-scored messages
- [x] Slow path when env concurrency is full
- [x] Fast-path message can be acknowledged correctly
- [x] Fast-path message can be nacked and re-enqueued to the queue
sorted set
- [x] Run all existing run-queue tests (ack, nack, CK, concurrency
sweeper, dequeue) to verify no regressions
- [x] Typecheck passes for run-engine and webapp
2026-03-31 10:16:49 +01:00
nicktrn 0e63f8317e feat: add ttl support at task and config levels (#3196)
Add TTL (time-to-live) defaults at task-level and config-level, with
precedence: per-trigger > task > config > dev default (10m).

Docs PR: #3200 (merge after packages are released)
2026-03-30 23:25:07 +01:00
Eric Allam b07567888d fix(llm-catalog): refresh default model pricing on sync (#3281)
- Rebuild llm_pricing_tiers and llm_prices in syncLlmCatalog for
source=default
- Add vitest config, sync regression tests, and pin vitest 3.1.4
- Update pnpm-lock.yaml for the new devDependency
2026-03-30 21:59:43 +01:00
nicktrn 5447cf4843 feat(webapp): admin UI for feature flag overrides (#3291)
Adds a dialog to the admin orgs page for viewing and editing per-org
feature flag overrides. Flags are introspected from the catalog so the
UI stays in sync with available flags automatically. Also adds a new tab
for global flags.

Refactors featureFlags.server.ts to split catalog definition (shared)
from server-only runtime (flags(), makeSetMultipleFlags). The shared
module exports flag metadata and validation so both the UI and API
routes can use it without pulling in server dependencies.
2026-03-30 16:55:23 +01:00
Saadi Myftija 7210bdee9b feat(supervisor): custom tolerations for scheduled runs (#3297)
Adds support for taint tolerations for scheduled runs. Useful for
selectively tolerating taints on dedicated node pools.

The new `KUBERNETES_SCHEDULED_RUN_TOLERATIONS` env variable accepts a
comma-separated list in the format key=value:effect (or key:effect for
the Exists operator).

Drive-by: renames all `KUBERNETES_SCHEDULE_*` affinity env vars to
KUBERNETES_SCHEDULED_RUN_* for clarity — this feature isn't used in
production yet or published in a tagged image; the name change is fine.
2026-03-30 13:04:13 +02:00
Oskar Otwinowski 66b70101e9 feat(webapp): Org level feature flags for Private Links (#3287) 2026-03-30 11:46:01 +02:00
nicktrn 9cb3dcb07c feat(supervisor): compute workload manager (#3114)
Adds the `ComputeWorkloadManager` for routing task execution through the
compute gateway, including full checkpoint/restore support, OTel trace
integration, and template pre-warming.

## Changes

**Compute workload manager**
(`apps/supervisor/src/workloadManager/compute.ts`)
- Routes instance create, snapshot, delete, and restore through the
compute gateway API
- Wide event logging on create with full timing and context
- Configurable gateway timeout, auth token, image digest stripping

**Compute snapshot service**
(`apps/supervisor/src/services/computeSnapshotService.ts`)
- Timer wheel for delayed snapshot dispatch (avoids wasted work on
short-lived waitpoints)
- Configurable dispatch concurrency limit
(`COMPUTE_SNAPSHOT_DISPATCH_LIMIT`)
- Snapshot-complete callback handler with suspend completion reporting
- Trace context management and OTel span emission for snapshot
operations

**OTel trace service**
(`apps/supervisor/src/services/otlpTraceService.ts`)
- Fire-and-forget OTLP span emission for compute operations (provision,
restore, snapshot)
- BigInt nanosecond conversion preserving sub-ms precision for span
ordering

**Template creation**
(`apps/webapp/app/v3/services/computeTemplateCreation.server.ts`)
- Three-mode rollout: required (MICROVM projects), shadow (feature flag
/ percentage), skip
- Integrated into deploy finalize flow

**Shared compute package** (`internal-packages/compute/`)
- Gateway client with namespace-based API (instances, templates,
snapshots)
- Zod schemas for all gateway request/response types

**Database**
- `COMPUTE` variant added to `TaskRunCheckpointType` enum
- `WorkloadType` enum and column on `WorkerInstanceGroup`
- `hasComputeAccess` feature flag

**Env / config**
- Compute gateway URL, auth token, timeout
- Snapshot enable flag, delay, dispatch limit
- Dedicated OTLP endpoint for compute spans
(`COMPUTE_TRACE_OTLP_ENDPOINT`)
2026-03-29 22:03:59 +01:00
Oskar Otwinowski 2366b217bb fix(private-links): Private Links plans adjustments (#3285) 2026-03-27 20:03:41 +01:00
Oskar Otwinowski efe24f9c2a feat(private-link): Add private links UI (#3264)
⚒️ Publish Worker (v4) / build (supervisor) (push) Has been cancelled
2026-03-27 15:34:39 +01:00
Eric Allam 21cf8f9965 fix(webapp): disable resizable panel cookie saves to prevent large cookies causing HTTP 431 errors (#3282) 2026-03-27 13:04:04 +00:00
Oskar Otwinowski 8244ac6f84 feat(Notifications): Platform notifications for CLI and Dashboard (#3254)
For human reviewer:

- Check if Redis connection + code makes sense
- Check CLI methods (it's on a hotpath)
- Check DB Migrations and new tables


##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

Spawning new CLI / Dashboard notifications, check MVP, check if failures
not produce any problems with CLI/Dashboard

---

## Changelog

Added notifications mechanism for Dashboard and CLI

---

## Screenshots



💯
2026-03-26 14:19:17 +01:00
James Ritchie cd7d7593aa fix(webapp): Only show bright title text on the right hand inspector titles (#3276)
Only makes the span title text brighter when it's shown in the right
hand side inspector (in the spans list it stays dimmed)
2026-03-26 13:09:36 +00:00
Oskar Otwinowski 922a852a9b fix(Vercel): Initial deployment fix (#3263) 2026-03-26 11:21:13 +01:00
Saadi Myftija 38559480c9 feat: replicate trigger_source, root_trigger_source, and is_warm_start to ClickHouse (#3274)
Adds three new top-level columns to the ClickHouse task_runs_v2 table
primarily for analytics:

- `trigger_source` / `root_trigger_source` - extracted from the existing
TaskRun.annotations JSON during WAL
replication
- `is_warm_start` - new nullable boolean on TaskRun in Postgres, set in
the existing taskRun.update() at attempt
start (no additional write). null until the first attempt starts.

Run region is already available via the existing `worker_queue` column
in ClickHouse.
2026-03-26 10:27:31 +01:00
Eric Allam efcafdf388 fix(webapp): filter dev environments by userId in OrganizationsPresenter (#3273)
fix: filter dev environments by userId in OrganizationsPresenter
2026-03-26 07:59:39 +00:00
Saadi Myftija 97d2f72063 feat(supervisor): schedule-tree node affinity (#3271)
Scheduled runs create predictable hourly spikes that compete with
on-demand runs for node capacity. Runs triggered "on-demand" via the
SDK, API, or dashboard, are more sensitive to cold start latency since
users are typically
waiting on the result. When a burst of scheduled runs lands at the top
of the hour, it can saturate the shared pool resources causing
contention, affecting cold starts across the board.

The idea in this change is to absorb these periodic spikes in a
dedicated pool without affecting the cold starts of on-demand runs.
Scheduled runs are inherently less sensitive to cold starts.

### Changes in this PR

Follows up on run annotations (#3241), which made trigger origin
available on every run in the tree. This PR exposes
annotations at dequeue time to the supervisor. This enables scheduling
decisions based on trigger source.

The affinities are soft preferences at schedule time, so runs fall back
gracefully if the target pool is out out of capacity.
2026-03-25 18:24:19 +01:00
Eric Allam 1a6481a579 feat: add Model Registry feature with catalog pipeline, dashboard pages, and TSQL schema (#3270)
- Add llm-model-catalog package (renamed from llm-pricing) with Claude
CLI research pipeline
- Add Prisma schema: catalog columns + baseModelName on LlmModel
- Add ClickHouse: llm_model_aggregates MV + base_response_model column
- Add TSQL llm_models schema for query page integration
- Add ModelRegistryPresenter with catalog, metrics, and comparison
queries
- Add 3 dashboard pages: catalog (cards+table+filters), detail
(overview+metrics+cost estimator), compare
- Add sidebar navigation under AI section with hasAiAccess feature flag
- Add admin dashboard sync/seed for catalog metadata
- Add model variant grouping (dated snapshots under base models)
- Add shared formatters and design system component usage

refs TRI-7941
2026-03-25 16:30:08 +00:00
Eric Allam 947f33d55b fix: downgrade queue size limit errors to warnings (#3243)
Queue limit ServiceValidationErrors were being logged at error level.
These are
expected validation rejections, not bugs.

- Add logLevel property to ServiceValidationError (webapp + run-engine)
- Set logLevel: warn on all queue limit throws
- Schedule engine: detect queue limit failures and log as warn
- Redis-worker: respect logLevel on thrown errors
2026-03-25 16:08:30 +00:00
James Ritchie 2037254a9b Feat(webapp) AI screen UI improvements (#3269)
### Lots of UI improvements to the Prompts pages: 

#### New side menu icons
<img width="234" height="110" alt="CleanShot 2026-03-25 at 14 26 33"
src="https://github.com/user-attachments/assets/8039ee8f-92a0-477d-ac91-458dfa43020b"
/>

#### Compact horizontal start finish times so scanning generations list
is consistent
<img width="618" height="174" alt="CleanShot 2026-03-25 at 14 24 03"
src="https://github.com/user-attachments/assets/7eb69475-d539-4e34-b0b5-5cd5119c1aea"
/>

#### Tidied up the metrics view
<img width="1607" height="925" alt="CleanShot 2026-03-25 at 14 23 52"
src="https://github.com/user-attachments/assets/d4bf2761-8e09-4d91-bfb8-e10d1508042f"
/>

#### Copiable metadata
<img width="274" height="160" alt="CleanShot 2026-03-25 at 14 23 44"
src="https://github.com/user-attachments/assets/487c804d-c000-4cd0-9a19-30c2681712df"
/>

#### Cleaner versions list
<img width="463" height="264" alt="CleanShot 2026-03-25 at 14 23 28"
src="https://github.com/user-attachments/assets/a2dfede7-0e7d-4f9c-8b01-00ba13070f70"
/>

#### Overall consistency improvements, shortcut keys and UI behaviours
improvements
<img width="2279" height="1349" alt="CleanShot 2026-03-25 at 14 23 02"
src="https://github.com/user-attachments/assets/0c29257b-15a0-443c-b872-a9f4a7f6af13"
/>

---------

Co-authored-by: Eric Allam <eallam@icloud.com>
2026-03-25 16:02:41 +00:00
DKP 7f9b0463cf docs: Fixes and realtime improvements (#3265) 2026-03-25 15:28:41 +00:00
Eric Allam c00dae006b feat(mcp): add get_span_details tool (#3255)
Returns the fully detailed span with attributes and AI enrichment data
2026-03-24 13:18:49 +00:00
Eric Allam 774007e9b9 fix(mcp): get_run_details only caches completed runs (#3253) 2026-03-24 11:28:52 +00:00
Oskar Otwinowski f86e492c31 feat(vercel): Flow to support Vercel's template deployment (#3229) 2026-03-24 11:04:57 +01:00
Saadi Myftija d4772b5f60 feat: run annotations (#3241)
Adds an `annotations` JSONB column to task runs that captures where and
how each run was triggered.
This enables filtering and analyzing trigger origins without querying up
the run tree. Also enables making scheduling decisions based on the
trigger source, e.g., use separate affinities for scheduled runs.

Each run records:
- **triggerSource**: who initiated it (sdk, api, dashboard, cli, mcp,
schedule)
- **triggerAction**: what kind of action (trigger, replay, test)
- **rootTriggerSource**: the trigger source of the root ancestor,
propagated through the entire run
 tree
- **rootScheduleId**: schedule id, in case the run tree was triggered
from a schedule

Currently the main motivation for annotations it to determine whether a
run is part of a schedule-originated tree without traversing ancestors.

### A couple of design considerations
- **Decoupled source from method**: triggerSource and triggerAction are
separate fields to avoid
combinatorial explosion (every new source × every new action)
- **Server-side first**: all annotation values are primarily determined
on the server, only a minor SDK change needed
- **Forward-compatible**: annotation fields use
`z.enum([...]).or(anyString)` so new values can be
added without breaking validation; we currently don't need an explicit
version field for annotations.

Note: `metadata` would have been a more fitting name for the db column,
as it is consistent with other tables where we store this type of
information. It is already in use to store user metadata though, so we
go with `annotations` instead.
2026-03-23 16:07:30 +01:00
Matt Aitken 88f755082f Vouched: jrossi (#3247)
Fixes #3246
2026-03-23 12:18:27 +00:00
Eric Allam 54d95ee4b9 feat: AI prompt management dashboard and enhanced span inspectors (#3244)
- Full prompt management UI: list, detail, override, and version
management for AI prompts defined with `prompts.define()`
- Rich AI span inspectors for all AI SDK operations with token usage,
messages, and prompt context
- Real-time generation tracking with live polling and filtering

## Prompt management

Define prompts in your code with `prompts.define()`, then manage
versions and overrides from the dashboard without redeploying:

```typescript
import { task, prompts } from "@trigger.dev/sdk";
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";

const supportPrompt = prompts.define({
  id: "customer-support",
  model: "gpt-4o",
  variables: z.object({
    customerName: z.string(),
    plan: z.string(),
    issue: z.string(),
  }),
  content: `You are a support agent for Acme SaaS.
Customer: {{customerName}} ({{plan}} plan)
Issue: {{issue}}
Respond with empathy and precision.`,
});

export const supportTask = task({
  id: "handle-support",
  run: async (payload) => {
    const resolved = await supportPrompt.resolve({
      customerName: payload.name,
      plan: payload.plan,
      issue: payload.issue,
    });

    const result = await generateText({
      model: openai(resolved.model ?? "gpt-4o"),
      system: resolved.text,
      prompt: payload.issue,
      ...resolved.toAISDKTelemetry(),
    });

    return { response: result.text };
  },
});
```

The prompts list page shows each prompt with its current version, model,
override status, and a usage sparkline over the last 24 hours.

From the prompt detail page you can:

- **Create overrides** to change the prompt template or model without
redeploying. Overrides take priority over the deployed version when
`prompt.resolve()` is called.
- **Promote** any code-deployed version to be the current version
- **Browse generations** across all versions with infinite scroll and
live polling for new results
- **Filter** by version, model, operation type, and provider
- **View metrics** (total generations, avg tokens, avg cost, latency)
broken down by version

## AI span inspectors

Every AI SDK operation now gets a custom inspector in the run trace
view:

- **`ai.generateText` / `ai.streamText`** — Shows model, token usage,
cost, the full message thread (system prompt, user message, assistant
response), and linked prompt details
- **`ai.generateObject` / `ai.streamObject`** — Same as above plus the
JSON schema and structured output
- **`ai.toolCall`** — Shows tool name, call ID, and input arguments
- **`ai.embed`** — Shows model and the text being embedded

For generation spans linked to a prompt, a "Prompt" tab shows the prompt
metadata, the input variables passed to `resolve()`, and the template
content from the prompt version.

All AI span inspectors include a compact timestamp and duration header.

## Other improvements

- Resizable panel sizes now persist across page refreshes (patched
`@window-splitter/state` to fix snapshot restoration)
- Run page panels also persist their sizes
- Fixed `<div>` inside `<p>` DOM nesting warnings in span titles and
chat messages
- Added Operations and Providers filters to the AI metrics dashboard

## Screenshots

<img width="3680" height="2392" alt="CleanShot 2026-03-21 at 10 14
17@2x"
src="https://github.com/user-attachments/assets/f3e59989-a2fa-4990-a9d0-3cacda431868"
/>

<img width="3680" height="2392" alt="CleanShot 2026-03-21 at 10 15
37@2x"
src="https://github.com/user-attachments/assets/2f2d02df-2d2b-44fb-ac6f-9153f6a6c387"
/>

<img width="3680" height="2392" alt="CleanShot 2026-03-21 at 10 15
54@2x"
src="https://github.com/user-attachments/assets/baa161e0-ef91-4fa4-a55f-986b71cccdf0"
/>
2026-03-23 06:23:19 +00:00
Matt Aitken 35298ac357 Impersonating run and clearing fix (#3144)
- Automatically impersonate a run when visiting /runs/<run_id> if an
admin is logged in
- Clear existing impersonation when switching
2026-03-18 14:36:27 +00:00
Eric Allam 1cfc296c6b feat(ai): LLM metrics tracking and AI span inspector (#3213)
- Automatic LLM cost enrichment for AI SDK spans (streamText,
generateText, generateObject) or any other spans that use semantic
gen_ai attributes with support for 145+ models
- New AI span inspector sidebar showing model, tokens, cost, messages,
tool calls, and response text
- LLM metrics dual-write to ClickHouse `llm_metrics_v1` table for
analytics
- LLM metrics built-in dashboard (unlinked at the moment)
- Provider cost fallback — uses gateway/OpenRouter reported costs from
`providerMetadata` when registry pricing is unavailable
- Prefix-stripping for gateway/OpenRouter model names (e.g.
`mistral/mistral-large-3` matches `mistral-large-3` pricing)
- Admin dashboard for managing LLM model pricing (list, create, edit,
delete, search, test pattern matching)
- Missing models detection page — queries ClickHouse for unpriced models
with sample spans and Claude Code-ready prompts for adding pricing
- AI span seed script (`pnpm run db:seed:ai-spans`) with 51 spans across
12 provider systems for local dev testing
- UI fixes: `completionTokens`/`promptTokens` aliases,
`ai.response.object` display for generateObject, cache read/write token
breakdown

## Screenshots:

<img width="1030" height="104" alt="CleanShot 2026-03-17 at 16 48 54@2x"
src="https://github.com/user-attachments/assets/bc8fccda-e48b-4d0c-bfb1-e620064e5979"
/>

<img width="1094" height="1512" alt="CleanShot 2026-03-17 at 16 49
23@2x"
src="https://github.com/user-attachments/assets/c2424569-d07e-4d67-a436-e8250043a1ee"
/>

<img width="1074" height="1412" alt="CleanShot 2026-03-17 at 16 49
18@2x"
src="https://github.com/user-attachments/assets/22342ac4-4769-45d1-a328-a24fb9a82a50"
/>

<img width="1012" height="2292" alt="CleanShot 2026-03-17 at 16 39
01@2x"
src="https://github.com/user-attachments/assets/59e327d1-6652-4293-8be0-bb8326e5fbc5"
/>

<img width="3680" height="2392" alt="CleanShot 2026-03-15 at 08 29
38@2x"
src="https://github.com/user-attachments/assets/1f77beb8-de67-495b-b890-bcdb8d7f1fe8"
/>

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2026-03-17 18:26:43 +00:00
Eric Allam 411803e49e fix(engine): lockless waitpoint insert for batch items to eliminate lock contention (#3232)
When processing batchTriggerAndWait items, each batch item was acquiring
a
Redis lock on the parent run to insert a TaskRunWaitpoint row. With high
concurrency (processingConcurrency=50), this caused
LockAcquisitionTimeoutError
(880 errors/24h in prod), orphaned runs, and stuck parent runs.

Since blockRunWithCreatedBatch already transitions the parent to
EXECUTING_WITH_WAITPOINTS before items are processed, the per-item lock
is
unnecessary. The new blockRunWithWaitpointLockless method performs only
the
idempotent CTE insert and timeout scheduling without acquiring the lock.
2026-03-17 16:42:01 +00:00
Eric Allam dbbe9f77f9 feat(cli): Expand and improve the MCP server and dev CLI command (#3224)
## Summary

Major expansion of the MCP server (14 → 25 tools), context efficiency
optimizations, new API endpoints, and a fix for the dev CLI leaking
build directories on disk.

### New MCP tools

- **Query & analytics**: `get_query_schema`, `query`, `list_dashboards`,
`run_dashboard_query` — query your data using TRQL directly from AI
assistants
- **Profile management**: `whoami`, `list_profiles`, `switch_profile` —
see and switch CLI profiles per-project (persisted to
`.trigger/mcp.json`)
- **Dev server control**: `start_dev_server`, `stop_dev_server`,
`dev_server_status` — start/stop `trigger dev` and stream build output
- **Task introspection**: `get_task_schema` — get payload schema for a
specific task (split out from `get_current_worker` to reduce context)

### New API endpoints

- `GET /api/v1/query/schema` — discover TRQL tables and columns
(server-driven, multi-table)
- `GET /api/v1/query/dashboards` — list built-in dashboard widgets and
their queries

### New features

- **`--readonly` flag** — hides write tools (`deploy`, `trigger_task`,
`cancel_run`) so agents can't make changes
- **`read:query` JWT scope** — new authorization scope for query
endpoints, with per-table granularity (`read:query:runs`,
`read:query:llm_metrics`, etc.)
- **Paginated trace output** — `get_run_details` now paginates trace
events via cursor, caching the full trace in a temp file so subsequent
pages don't re-fetch
- **MCP tool annotations** — all tools now have
`readOnlyHint`/`destructiveHint` annotations for clients that support
them
- **Project-scoped profile persistence** — `switch_profile` saves to
`.trigger/mcp.json` (gitignored), automatically loaded on next MCP
server start

### Context optimizations

- `get_query_schema` requires a table name — returns one table's schema
instead of all tables (60-80% fewer tokens)
- `get_current_worker` no longer inlines payload schemas — use
`get_task_schema` for specific tasks
- Query results formatted as text tables instead of JSON (~50% fewer
tokens for flat data)
- `cancel_run`, `list_deploys`, `list_preview_branches` formatted as
text instead of raw `JSON.stringify()`
- Schema and dashboard API responses cached (1hr and 5min respectively)

### Bug fixes

- Fixed `search_docs` failing due to renamed upstream Mintlify tool
(`SearchTriggerDev` → `search_trigger_dev`)
- Fixed `list_deploys` failing when deployments have null
`runtime`/`runtimeVersion` fields (fixes #3139)
- Fixed `list_preview_branches` crashing due to incorrect response shape
access
- Fixed `metrics` table column documented as `value` instead of
`metric_value` in query docs
- Fixed `/api/v1/query` not accepting JWT auth (added `allowJWT: true`)

### Dev CLI build directory fix

The dev CLI was leaking `build-*` directories in `.trigger/tmp/` on
every rebuild, accumulating hundreds of MB over time (842MB observed).
Three layers of protection added:

1. **During session**: deprecated workers are pruned (capped at 2
retained) when no active runs reference them, preventing unbounded
accumulation
2. **On SIGKILL/crash**: the watchdog process now cleans up
`.trigger/tmp/` when it detects the parent CLI was killed
3. **On next startup**: existing `clearTmpDirs()` wipes any remaining
orphans

## Test plan

- [ ] `pnpm run mcp:smoke` — 17 automated smoke tests for all read-only
MCP tools
- [ ] `pnpm run mcp:test list` — verify 25 tools registered (21 in
`--readonly` mode)
- [ ] `pnpm run mcp:test --readonly list` — verify write tools hidden
- [ ] Manual: start dev server, trigger task, rebuild multiple times,
verify build dirs stay capped at 4
- [ ] Manual: SIGKILL the dev CLI, verify watchdog cleans up
`.trigger/tmp/`
- [ ] Verify new API endpoints return correct data: `GET
/api/v1/query/schema`, `GET /api/v1/query/dashboards`

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-03-17 11:38:23 +00:00
Jack Cheng f98e274b06 feat(webapp): allow version downgrades via promote API (#3214) 2026-03-17 07:38:20 +00:00
Matt Aitken cf0e1ff91a Vouched: bhekanik (#3227) 2026-03-16 22:24:49 +00:00
Matt Aitken 2406e850eb RunEngine readme updates (#3223) 2026-03-16 18:52:21 +00:00
Eric Allam 7672e8d998 fix(run-queue): prevent concurrency keys from bloating master queue shards (#3219)
Queues with concurrency keys now appear as a single entry in the master
queue instead of one entry per key. This prevents high-CK-count tenants
from consuming the entire `parentQueueLimit` window and starving other
tenants on the same shard.

A new per-queue **CK index** (sorted set) tracks active concurrency key
sub-queues. The master queue gets one `:ck:*` wildcard entry per base
queue. Dequeuing from that entry round-robins across sub-queues,
maintaining per-CK concurrency tracking and fairness.

All existing operations (enqueue, dequeue, ack, nack, DLQ, TTL expiry)
are CK-index-aware and keep the index consistent. Old-format entries
drain naturally during rollout — no migration step needed, single
deploy.
2026-03-14 13:37:54 +00:00
Eric Allam 2c688ca3d4 chore(repo): Add new contributing guidelines and auto-close outside PRs open in "ready to review" status (#3218) 2026-03-14 10:23:34 +00:00
Eric Allam 59ff68b00c chore(vouch): add bharathkumar39293 (#3217) 2026-03-14 09:12:51 +00:00
Eric Allam 440c16c4aa chore(repo): add agentcrumbs.dev support (#3206) 2026-03-13 13:37:09 +00:00
Eric Allam d4d8d9fabc fix(engine): add additional error logging around triggering runs (#3211) 2026-03-13 07:18:43 +00:00
Eric Allam 8108683073 vouch chengzp (#3212) 2026-03-12 23:33:25 +00:00
James Ritchie fea8ae4e53 feat(webapp): self serve preview branches and team members (#3201)
## Adds 2 self serve features

### 1. self serve preview branches

- Copies the patterns of the self serve concurrency
- Self serve only available on Pro plan (otherwise you are linked to the
billing plans page)
- Global self serve branches limit: 180 (+20 for the Pro plan). It can
be overridden per Org
- You need to archive branches before reducing the number of extra
branches you're paying for
- Branches are removed immediately but remain billed until the end of
the billing cycle like extra concurrency

### 2. self serve team members

- Copies the patterns of the self serve concurrency
- Self serve only available on Pro plan (otherwise you are linked to the
billing plans page)
- Global self serve members is unlimited but can be limited with the
same env var quota and overridden per org if needed
- You need to remove team members before reducing the number of members
you pay for
- Team members are removed immediately but remain billed until the end
of the billing cycle like extra concurrency
2026-03-12 14:56:10 +00:00
Iss 21fdb528f5 docs: deprecate syncVercelEnvVars extension and add conflict warning (#3208)
Deprecates the syncVercelEnvVars build extension and adds warnings in
both the Vercel integration docs and the extension's own page to prevent
conflicts with the native env var sync
2026-03-11 17:56:37 -04:00
Dinko Osrecki b8766e7a27 fix(webapp): strip secure param from query ClickHouse URL (#3204) 2026-03-11 06:42:49 +00:00
Eric Allam fef6d18e8f chore: add @edosrecki to vouched contributors (#3203) 2026-03-11 06:33:58 +00:00
github-actions[bot] c0b6309c72 chore: release v4.4.3 (#3182)
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 20s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
## Summary
2 new features, 2 improvements.

## Improvements
- Add syncSupabaseEnvVars to pull database connection strings and save
them as trigger.dev environment variables
([#3152](https://github.com/triggerdotdev/trigger.dev/pull/3152))
- Auto-cancel in-flight dev runs when the CLI exits, using a detached
watchdog process that survives pnpm SIGKILL
([#3191](https://github.com/triggerdotdev/trigger.dev/pull/3191))

## Server changes

These changes affect the self-hosted Docker image and Trigger.dev Cloud:

- A new Errors page for viewing and tracking errors that cause runs to
fail
  
  - Errors are grouped using error fingerprinting
- View top errors for a time period, filter by task, or search the text
  - View occurrences over time
- View all the runs for an error and bulk replay them
([#3172](https://github.com/triggerdotdev/trigger.dev/pull/3172))
- Add sidebar tabs (Options, AI, Schema) to the Test page for schemaTask
payload generation and schema viewing.
([#3188](https://github.com/triggerdotdev/trigger.dev/pull/3188))

<details>
<summary>Raw changeset output</summary>

# Releases
## @trigger.dev/build@4.4.3

### Patch Changes

- Add syncSupabaseEnvVars to pull database connection strings and save
them as trigger.dev environment variables
([#3152](https://github.com/triggerdotdev/trigger.dev/pull/3152))
-   Updated dependencies:
    -   `@trigger.dev/core@4.4.3`

## trigger.dev@4.4.3

### Patch Changes

- Auto-cancel in-flight dev runs when the CLI exits, using a detached
watchdog process that survives pnpm SIGKILL
([#3191](https://github.com/triggerdotdev/trigger.dev/pull/3191))
-   Updated dependencies:
    -   `@trigger.dev/core@4.4.3`
    -   `@trigger.dev/build@4.4.3`
    -   `@trigger.dev/schema-to-json@4.4.3`

## @trigger.dev/core@4.4.3

### Patch Changes

- Auto-cancel in-flight dev runs when the CLI exits, using a detached
watchdog process that survives pnpm SIGKILL
([#3191](https://github.com/triggerdotdev/trigger.dev/pull/3191))

## @trigger.dev/python@4.4.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.3`
    -   `@trigger.dev/build@4.4.3`
    -   `@trigger.dev/sdk@4.4.3`

## @trigger.dev/react-hooks@4.4.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.3`

## @trigger.dev/redis-worker@4.4.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.3`

## @trigger.dev/rsc@4.4.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.3`

## @trigger.dev/schema-to-json@4.4.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.3`

## @trigger.dev/sdk@4.4.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.3`

</details>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-10 10:17:24 +00:00
Eric Allam 436f20efc6 feat(cli): auto-cancel dev runs on CLI exit via detached watchdog (#3191)
When the dev CLI exits (e.g. ctrl+c via pnpm), runs that were
mid-execution
previously stayed stuck in EXECUTING status for up to 5 minutes until
the
heartbeat timeout fired. Now they are cancelled within seconds.

The dev CLI spawns a lightweight detached watchdog process at startup.
The
watchdog monitors the CLI process ID and, when it detects the CLI has
exited,
calls a new POST /engine/v1/dev/disconnect endpoint to cancel all
in-flight
runs immediately (skipping PENDING_CANCEL since the worker is known to
be dead).

Watchdog design:
- Fully detached (detached: true, stdio: ignore, unref()) so it survives
  even when pnpm sends SIGKILL to the process tree
- Active run IDs maintained via atomic file write
(.trigger/active-runs.json)
- Single-instance guarantee via PID file (.trigger/watchdog.pid)
- Safety timeout: exits after 24 hours to prevent zombie processes
- On clean shutdown, the watchdog is killed (no disconnect needed)

Disconnect endpoint:
- Rate-limited: 5 calls/min per environment
- Capped at 500 runs per call
- Small counts (<= 25): cancelled inline with pMap concurrency 10
- Large counts: delegated to the bulk action system
- Uses finalizeRun: true to skip PENDING_CANCEL and go straight to
FINISHED

Run engine change:
- cancelRun() now respects finalizeRun when the run is in EXECUTING
status,
skipping the PENDING_CANCEL waiting state and going directly to FINISHED
2026-03-09 12:14:43 +00:00
James Ritchie d1ea8d8f74 Fix(webapp) onboarding fixes (#3189)
### Fixes and improvements to the onboarding questions: 

**This change is worth double checking @matt-aitken** 
- Update to the Button.tsx file: it now takes `isLoading` that shows a
spinner in the middle of the button (replacing the button text and any
icons) and sets it to `disabled`. It does this nicely by keeping the
button width the same so there's no layout shift.

**Other fixes**
- Fixes an issue where if you type a custom option in the "What
technologies do you use" question, it doesn't check the list to see if
it matches. Now it checks the box if you've typed an option from that
list.
- When we randomize the list of onboarding question options, we now
store the position they appeared in the list
2026-03-09 10:09:21 +00:00
Eric Allam e64b101138 feat(webapp): Add test payload AI generation to the test page based on payload schemas (#3188)
<img width="2191" height="1023" alt="CleanShot 2026-03-06 at 13 36 53"
src="https://github.com/user-attachments/assets/4eba0d1a-1528-49a3-be5b-6bde89030193"
/>
<img width="411" height="1069" alt="CleanShot 2026-03-06 at 13 37 28"
src="https://github.com/user-attachments/assets/e5f7bb9c-c894-41cc-9ca6-96b43fcf6005"
/>

Add a tabbed sidebar to the Test page for standard tasks, reusing the
ClientTabs pattern from the Query page.

- Options tab: existing sidebar content (machine, version, queue, etc.)
- AI tab: AI-powered payload generation with streaming, supports JSON
  Schema, inferred schema from recent runs, and task source code lookup
  via tool calling for tasks without schemas
- Schema tab: displays payload JSON Schema (from schemaTask), inferred
  schema (from recent runs via @jsonhero/schema-infer), or empty state
  with schemaTask docs and example code

Data layer changes:
- Surface payloadSchema and inferredPayloadSchema from TestTaskPresenter
- Add payloadSchema and fileId to WorkerDeploymentWithWorkerTasks type
- Decompress zlib-deflated source files for AI context
2026-03-06 15:31:16 +00:00
Eric Allam 6f6523ff78 chore(repo): remove unnecessary "trigger.dev v4.4.2" header from the release PR description (#3183) 2026-03-06 14:07:32 +00:00
Matt Aitken d30ed3421e Logs query use_query_condition_cache=1 (#3186)
In theory this will make Log queries faster
2026-03-06 10:24:43 +00:00
Matt Aitken 5f359be286 feature: Errors page (#3172)
A top-level Errors page that aggregates errors from failed runs with
occurrences metrics.


https://github.com/user-attachments/assets/8f0ef55e-90dd-4faa-9051-59f4665181e4

Errors are “fingerprinted” so similar errors are grouped together (e.g.
has an ID in the error message).

You can view an individual error to view a timeline of when it fired,
the runs, and bulk replay them.
2026-03-05 11:05:45 +00:00
Oskar Otwinowski e49ccc1226 feat(buildExtensions): syncSupabaseEnvVars build extension (#3152)
with docs
2026-03-05 11:04:26 +01:00
Eric Allam c01332297b docs: update batch trigger concurrency limits (#3171) 2026-03-04 11:50:59 +00:00
Eric Allam c5ce2976be fix: Add repo flag when for updating the docker link during release (#3170) 2026-03-04 11:13:47 +00:00
Eric Allam e954a2c97a docs: realtime input streams (#3153)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-03-04 09:55:54 +00:00
github-actions[bot] e36b75785e chore: release v4.4.2 (#3127)
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 20s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
# trigger.dev v4.4.2

## Summary
2 new features, 2 improvements, 8 bug fixes.

## Improvements
- Add input streams for bidirectional communication with running tasks.
Define typed input streams with `streams.input<T>({ id })`, then consume
inside tasks via `.wait()` (suspends the process), `.once()` (waits for
next message), or `.on()` (subscribes to a continuous stream). Send data
from backends with `.send(runId, data)` or from frontends with the new
`useInputStreamSend` React hook.
([#3146](https://github.com/triggerdotdev/trigger.dev/pull/3146))
- Add PAYLOAD_TOO_LARGE error to handle graceful recovery of sending
batch trigger items with payloads that exceed the maximum payload size
([#3137](https://github.com/triggerdotdev/trigger.dev/pull/3137))

## Bug fixes
- Fix slow batch queue processing by removing spurious cooloff on
concurrency blocks and fixing a race condition where retry attempt
counts were not atomically updated during message re-queue.
([#3079](https://github.com/triggerdotdev/trigger.dev/pull/3079))
- fix(sdk): batch triggerAndWait variants now return correct
run.taskIdentifier instead of unknown
([#3080](https://github.com/triggerdotdev/trigger.dev/pull/3080))

## Server changes

These changes affect the self-hosted Docker image and Trigger.dev Cloud:

- Two-level tenant dispatch architecture for batch queue processing.
Replaces the
single master queue with a two-level index: a dispatch index (tenant →
shard)
and per-tenant queue indexes (tenant → queues). This enables O(1) tenant
selection and fair scheduling across tenants regardless of queue count.
Improves batch queue processing performance.
([#3133](https://github.com/triggerdotdev/trigger.dev/pull/3133))
- Add input streams with API routes for sending data to running tasks,
SSE reading, and waitpoint creation. Includes Redis cache for fast
`.send()` to `.wait()` bridging, dashboard span support for input stream
operations, and s2-lite support with configurable S2 endpoint, access
token skipping, and S2-Basin headers for self-hosted deployments. Adds
s2-lite to Docker Compose for local development.
([#3146](https://github.com/triggerdotdev/trigger.dev/pull/3146))
- Speed up batch queue processing by disabling cooloff and increasing
the batch queue processing concurrency limits on the cloud:
  
  - Pro plan: increase to 50 from 10.
  - Hobby plan: increase to 10 from 5.
- Free plan: increase to 5 from 1.
([#3079](https://github.com/triggerdotdev/trigger.dev/pull/3079))
- Move batch queue global rate limiter from FairQueue claim phase to
BatchQueue worker queue consumer for accurate per-item rate limiting.
Add worker queue depth cap to prevent unbounded growth that could cause
visibility timeouts.
([#3166](https://github.com/triggerdotdev/trigger.dev/pull/3166))
- Fix a race condition in the waitpoint system where a run could be
blocked by a completed waitpoint but never be resumed because of a
PostgreSQL MVCC issue. This was most likely to occur when creating a
waitpoint via `wait.forToken()` at the same moment as completing the
token with `wait.completeToken()`. Other types of waitpoints (timed,
child runs) were not affected.
([#3075](https://github.com/triggerdotdev/trigger.dev/pull/3075))
- Fix metrics dashboard chart series colors going out of sync and
widgets not reloading stale data when scrolled back into view
([#3126](https://github.com/triggerdotdev/trigger.dev/pull/3126))
- Gracefully handle oversized batch items instead of aborting the
stream.
  
When an NDJSON batch item exceeds the maximum size, the parser now emits
an error marker instead of throwing, allowing the batch to seal
normally. The oversized item becomes a pre-failed run with
`PAYLOAD_TOO_LARGE` error code, while other items in the batch process
successfully. This prevents `batchTriggerAndWait` from seeing connection
errors and retrying with exponential backoff.
  
Also fixes the NDJSON parser not consuming the remainder of an oversized
line split across multiple chunks, which caused "Invalid JSON" errors on
subsequent lines.
([#3137](https://github.com/triggerdotdev/trigger.dev/pull/3137))
- Require the user is an admin during an impersonation session.
Previously only the impersonation cookie was checked; now the real
user's admin flag is verified on every request. If admin has been
revoked, the session falls back to the real user's ID.
([#3078](https://github.com/triggerdotdev/trigger.dev/pull/3078))

<details>
<summary>Raw changeset output</summary>

# Releases
## @trigger.dev/build@4.4.2

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.2`

## trigger.dev@4.4.2

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/build@4.4.2`
    -   `@trigger.dev/core@4.4.2`
    -   `@trigger.dev/schema-to-json@4.4.2`

## @trigger.dev/python@4.4.2

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/sdk@4.4.2`
    -   `@trigger.dev/build@4.4.2`
    -   `@trigger.dev/core@4.4.2`

## @trigger.dev/react-hooks@4.4.2

### Patch Changes

- Add input streams for bidirectional communication with running tasks.
Define typed input streams with `streams.input<T>({ id })`, then consume
inside tasks via `.wait()` (suspends the process), `.once()` (waits for
next message), or `.on()` (subscribes to a continuous stream). Send data
from backends with `.send(runId, data)` or from frontends with the new
`useInputStreamSend` React hook.
([#3146](https://github.com/triggerdotdev/trigger.dev/pull/3146))

Upgrade S2 SDK from 0.17 to 0.22 with support for custom endpoints
(s2-lite) via the new `endpoints` configuration, `AppendRecord.string()`
API, and `maxInflightBytes` session option.

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.2`

## @trigger.dev/redis-worker@4.4.2

### Patch Changes

- Fix slow batch queue processing by removing spurious cooloff on
concurrency blocks and fixing a race condition where retry attempt
counts were not atomically updated during message re-queue.
([#3079](https://github.com/triggerdotdev/trigger.dev/pull/3079))
-   Updated dependencies:
    -   `@trigger.dev/core@4.4.2`

## @trigger.dev/rsc@4.4.2

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.2`

## @trigger.dev/schema-to-json@4.4.2

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.2`

## @trigger.dev/sdk@4.4.2

### Patch Changes

- Add input streams for bidirectional communication with running tasks.
Define typed input streams with `streams.input<T>({ id })`, then consume
inside tasks via `.wait()` (suspends the process), `.once()` (waits for
next message), or `.on()` (subscribes to a continuous stream). Send data
from backends with `.send(runId, data)` or from frontends with the new
`useInputStreamSend` React hook.
([#3146](https://github.com/triggerdotdev/trigger.dev/pull/3146))

Upgrade S2 SDK from 0.17 to 0.22 with support for custom endpoints
(s2-lite) via the new `endpoints` configuration, `AppendRecord.string()`
API, and `maxInflightBytes` session option.

- fix(sdk): batch triggerAndWait variants now return correct
run.taskIdentifier instead of unknown
([#3080](https://github.com/triggerdotdev/trigger.dev/pull/3080))

- Add PAYLOAD_TOO_LARGE error to handle graceful recovery of sending
batch trigger items with payloads that exceed the maximum payload size
([#3137](https://github.com/triggerdotdev/trigger.dev/pull/3137))

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.2`

## @trigger.dev/core@4.4.2

</details>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-04 09:47:24 +00:00
Eric Allam dee6f1d09e fix(batch): move batch queue global rate limiter to worker consumer level (#3166)
The global rate limiter was being applied at the FairQueue claim phase,
consuming 1 token per queue-claim-attempt rather than per item
processed.
  With many small queues (each batch is its own queue), consumers burned
  through tokens on empty or single-item queues, causing aggressive
  throttling well below the intended items/sec limit.

  Changes:
- Move rate limiter from FairQueue claim phase to BatchQueue worker
queue
    consumer loop (before blockingPop), so each token = 1 item processed
  - Replace the FairQueue rate limiter with a worker queue depth cap to
    prevent unbounded growth that could cause visibility timeouts
- Add BATCH_QUEUE_WORKER_QUEUE_MAX_DEPTH env var (optional, disabled by
default)
2026-03-03 14:44:27 +00:00
James Ritchie b192b71b93 Feat(webapp): add create custom dashboard button to metrics page (#3095)
Adds a "Create custom dashboard" button to the top right of the metrics
dashboard

 
<img width="3546" height="1934" alt="CleanShot 2026-02-19 at 11 25
12@2x"
src="https://github.com/user-attachments/assets/0bb46ade-47c9-4396-b62a-f4801d7d90b4"
/>
2026-03-02 18:23:02 +00:00
Eric Allam a9163dfd9d chore(docker): Pin goose in Dockerfile to v3.26.0 (#3163)
The latest goose requires go version 1.25:
https://github.com/pressly/goose/releases/tag/v3.27.0
2026-03-02 17:09:46 +00:00
Eric Allam 540e1c86a4 feat: Input Streams - Bidirectional task communication (#3146)
Input streams enable sending typed data to executing tasks from external
callers — backends, frontends, or other tasks. This unlocks interactive
use cases like approval UIs, cancel buttons, chat interfaces, and
human-in-the-loop AI workflows where the task needs to receive data
while running.

Three consumption patterns inside a task:

* `.wait()` — Suspend the task until data arrives (process freed, most
efficient)
* `.once()` — Wait for the next message (process stays alive)
* `.on()` — Subscribe to a continuous stream of messages

One send pattern from outside:

* `.send(runId, data)` — Send typed data to a specific run's input
stream

## User-facing API

### Define a typed input stream

```ts
import { streams, task } from "@trigger.dev/sdk";

const approval = streams.input<{ approved: boolean; reviewer: string }>({ id: "approval" });
```

### Consume inside a task

```ts
export const myTask = task({
  id: "my-task",
  run: async () => {
    // Pattern 1: Suspend until data arrives (most efficient — frees the process)
    const result = await approval.wait({ timeout: "5m" });

    // Pattern 2: Wait for next message (process stays alive)
    const data = await approval.once().unwrap();

    // Pattern 3: Subscribe to multiple messages
    approval.on((data) => { /* handle each message */ });
  },
});
```

### Send from outside

```ts
// From a backend (using secret API key)
await approval.send(runId, { approved: true, reviewer: "alice" });

// From a frontend (using public JWT token from trigger response)
const { send } = useInputStreamSend("approval", runId, { accessToken });
send({ approved: true, reviewer: "alice" });
```

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-02 16:49:54 +00:00
Eric Allam 2af5c860de chore(repo): Dispatch new-release to www.trigger.dev repo to generate version changelog draft PR (#3162) 2026-03-02 16:47:34 +00:00
James Ritchie a09038b066 Feature(webapp): new User and Project onboarding questions (#3109)
- New User onboarding questions added and stored in a new
`onboardingData` col
- Keeps the same Org creation screen and stores the data in the same
format in same DB column
- New Org onboarding questions addded and stored in a new
`onboardingData` col


https://github.com/user-attachments/assets/244e4bae-f74d-4ed4-a545-92c9b927e98b

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-03-02 14:45:14 +00:00
Eric Allam 2135dc56d6 chore(claude): Improve claude code instructions (#3161)
Also includes a claude.md audit workflow for PRs
2026-03-02 12:42:05 +00:00
Saadi Myftija 4a0fb2fc06 ci: pin vouch action version (#3160)
Pins vouch actions to `c6d80ead49839655b61b422700b7a3bc9d0804a9`
(v1.4.2) in favor of security practices. We were previously using the
`@main` tag.

Also removes the checkout steps as they're not needed in these
workflows.
2026-03-02 10:35:42 +01:00
James Ritchie e1f8134f44 fix(webapp): Removes the collapsible option from the query inspector to avoid firefox bug (#3155)
There's a bug in react-window-splitter on Firefox. When trying to expand
the inspector panel in the query editor, it checks if the main panel has
space but gets an object instead of a number for the auto-sized
query-main panel. This causes the expand calculation to fail and it
snaps it back to collapsed.

I've removed this behavior for now as it's not an important feature.
2026-02-28 20:09:13 +00:00
Oskar Otwinowski 10d6f01843 feat(vercel): Vercel SDK fixes and correct env vars behavior for staging envs (#3149) 2026-02-28 07:41:19 +00:00
Iss 24b92d3b68 docs: added runtime error note for supabase edge function (#3140) 2026-02-27 10:59:04 -05:00
Eric Allam 8003923598 feat(server): Gracefully handle oversized batch items instead of aborting the stream (#3137)
Gracefully handle oversized batch items instead of aborting the stream.

When an NDJSON batch item exceeds the maximum size, the parser now emits
an error marker instead of throwing, allowing the batch to seal
normally. The oversized item becomes a pre-failed run with
`PAYLOAD_TOO_LARGE` error code, while other items in the batch process
successfully. This prevents `batchTriggerAndWait` from seeing connection
errors and retrying with exponential backoff.

Also fixes the NDJSON parser not consuming the remainder of an oversized
line split across multiple chunks, which caused "Invalid JSON" errors on
subsequent lines.
2026-02-27 10:11:42 +00:00
Eric Allam cff45664fc fix: legacy master queue drain should never re-add entries (#3142) 2026-02-27 10:11:31 +00:00
Iss 51b6c3a580 docs: added note about Prisma 7.x for TASK_RUN_STALLED_EXECUTING error (#3138) 2026-02-26 16:01:31 -05:00
James Ritchie d5a27f08ed Fix(webapp): change "metrics" to "dashboard" (#3136)
<img width="249" height="245" alt="CleanShot 2026-02-26 at 16 44 46"
src="https://github.com/user-attachments/assets/2e38b60c-0fe4-4b88-b9b9-71df82943ace"
/>
2026-02-26 16:56:07 +00:00
Matt Aitken 719a44da01 Better explanation of batch processing concurrency (#3135) 2026-02-26 14:27:21 +00:00
Iss 92dfeb37b3 docs: Add workaround for Homebrew Bun ENOENT error to Bun guide (#3125) 2026-02-26 08:25:17 -05:00
Eric Allam b1e78a6590 feat(batch-queue): two-level tenant dispatch for fair queue (#3133)
Replace flat master queue index with two-level tenant dispatch to fix
noisy neighbor problem. When a tenant has many queues at capacity, the
scheduler now iterates tenants (Level 1) not queues, then fetches
per-tenant queues (Level 2) only for eligible tenants.

Single-deploy migration: new enqueues write to dispatch indexes only,
consumer drains old master queue alongside new dispatch path until
empty.
2026-02-26 13:07:27 +00:00
Eric Allam 5612383684 chore(repo): Improve formatting of server entries in release notes (#3134) 2026-02-26 11:59:47 +00:00
Iss 4451fcb84c docs: Query page output dot notation and metadata availability (#3132)
Clarifies in the Query docs that run metadata is not available on the
Query page and that the output column is JSON, so dot notation (e.g.
output.externalId) should be used for selecting and filtering. Adds an
example that filters by an output field in WHERE
2026-02-25 17:22:08 -05:00
Iss 863dbe8d60 docs: document waitpoint token API endpoints (#3130)
Adds REST API documentation for the 5 waitpoint token endpoints
(`/api/v1/waitpoints/tokens`), including create, list, retrieve,
complete, and HTTP callback. Also adds the `publicAccessToken` security
scheme used by the complete endpoint.

<!-- mintlify-editor-comments:start -->
Mintlify
---
0 threads from 0 users in Mintlify

- No unresolved comments
<!-- mintlify-editor-comments:end -->

<!-- mintlify-comment-->

<a
href="https://dashboard.mintlify.com/trigger/trigger/editor/docs%2Fdocument-waitpoint-endpoints?source=pr_comment"
target="_blank" rel="noopener noreferrer"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://d3gk2c5xim1je2.cloudfront.net/assets/open-mintlify-editor-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://d3gk2c5xim1je2.cloudfront.net/assets/open-mintlify-editor-light.svg"><img
src="https://d3gk2c5xim1je2.cloudfront.net/assets/open-mintlify-editor-light.svg"
alt="Open in Mintlify Editor"></picture></a>

<!-- /mintlify-comment -->
2026-02-25 12:52:14 -05:00
Eric Allam 39dd91b098 fix(engine) prevent MVCC race in blockRunWithWaitpoint pending check (#3075)
Split the CTE in blockRunWithWaitpoint so the pending waitpoint check
is a separate SQL statement. In READ COMMITTED isolation, each statement
gets its own snapshot, so a separate SELECT sees the latest committed
state from concurrent completeWaitpoint calls.

Previously, the CTE did INSERT + pending check in one statement (one
snapshot). If completeWaitpoint committed between the CTE start and
the SELECT, the SELECT would still see PENDING due to the stale
snapshot. Neither side would enqueue continueRunIfUnblocked, leaving
the run stuck forever.
2026-02-25 17:41:50 +00:00
Matt Aitken cf6b6e7063 Fix realtime connections pricing tier from 100 to 1000 (#3131)
Closes #

##  Checklist

- [ ] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [ ] The PR title follows the convention.
- [ ] I ran and tested the code works

---

## Testing

Verified the pricing definition displays the correct tier amount on the
plan selection page.

---

## Changelog

Fixed incorrect pricing tier for additional realtime connections from
$10/month per 100 to $10/month per 1000.

---

## Screenshots

N/A

💯

https://claude.ai/code/session_015QrZZJHPWta3QCBnhX2Pff

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-25 17:34:02 +00:00
Eric Allam bed3789c31 fix(batch-queue): speed up batch queue processing by disabling cooloff and fixing retry race (#3079)
Fix slow fair queue processing by removing spurious cooloff on
concurrency blocks and fixing a race condition where retry attempt
counts were not atomically updated during message re-queue.

Removed cooloff entirely from the batch queue
2026-02-25 17:33:01 +00:00
Eric Allam a482153365 feat(webapp): require the user is an admin during an impersonation session (#3078) 2026-02-25 16:07:10 +00:00
Eric Allam fe193418d0 chore(repo) auto-link server change entries to their PRs via GitHub API (#3129) 2026-02-25 16:02:32 +00:00
Matt Aitken e9fb8e3b52 Query fixes: stale widget fix, multiple series colors mismatch (#3126)
- Fix for series color assignment being out of sync with the graph
(ensures added series colors match their graph representation)
- Reload widgets when returning to screen if props changed (prevents
stale widgets after filtering and scrolling)
2026-02-25 15:50:17 +00:00
Eric Allam c05b30adfe chore(repo): fix enhanced release pr description to filter out dependency only updates (#3128) 2026-02-25 15:50:06 +00:00
Eric Allam f37bdaac84 fix(sdk): batch triggerAndWait variants now return correct run.taskIdentifier instead of unknown (#3080)
Fixes #2942
2026-02-25 15:37:04 +00:00
Eric Allam 3c0644a3b8 feat: unified GitHub release, server change tracking, and enhanced release PR (#3085)
- Add .server-changes/ convention for tracking server-only changes
- Create scripts/enhance-release-pr.mjs to deduplicate and categorize
changeset PR body
- Create scripts/generate-github-release.mjs to format unified GitHub
release body
- Change release.yml to create one unified GitHub release instead of
per-package releases
- Add update-release job to patch Docker image link after images are
pushed to GHCR
- Update changesets-pr.yml to trigger on .server-changes, enhance PR
body, and clean up consumed files
- Document server changes in CLAUDE.md, CONTRIBUTING.md, CHANGESETS.md,
and RELEASE.md
2026-02-25 13:54:19 +00:00
Eric Allam 19733c8338 docs(queues): Cover new queue limits and TTL system (#3030)
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3030"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-25 11:18:44 +00:00
Matt Aitken 9ba608d2cf TRQL function tests and fixes (#3076)
What changed
- Fixed some functions like dateAdd, toString, ifNotFinite
- Removed all functions that accept lambdas as they're not supported
(yet)
- Added tests for all TRQL functions that use ClickHouse
2026-02-24 19:44:07 +00:00
Iss 89c73ed8ba docs: document run result and batch API endpoints (#3121)
Adds OpenAPI specs and sidebar pages for four previously undocumented
public endpoints: retrieve
run result, per-task batch trigger, retrieve batch, and retrieve batch
results.
2026-02-24 13:30:16 -05:00
Iss 97bf89873e docs: document undocumented run API endpoints (#3120)
Adds API reference pages for three previously undocumented run
endpoints: retrieve run events, retrieve run trace, and add tags to a
run.
2026-02-24 10:49:39 -05:00
Iss b60788df82 docs: note that onCancel only runs during active execution (#3119)
Adds a warning to the onCancel docs clarifying that the hook only fires
when a run is actively executing
2026-02-23 21:24:38 +00:00
Eric Allam 6409fea6ac fix(engine): allow disabling the ttl system consumers independently from the whole system (#3115) 2026-02-23 16:39:30 +00:00
Eric Allam ae46e3f7c8 feat(server): New TTL system, enforce max queue length limits, lazy waitpoint creation (#2980)
This PR implements a new run TTL system and queue size limits to prevent
unbounded queue growth which should help prevent situations where queues
enter a "death spiral" where the queue will never be able to catch up.

The main/correct way to battle this situation is to enforce a maximum
TTL on all runs (e.g. up to 14 days) where runs that have been queued
for that maximum TTL will get auto-expired, making room for newer runs
to execute. This required creating a new TTL system that can handle
higher workloads and is now deeply integrated into the RunQueue. When
runs are enqueued with a TTL, they are added to their normal queue as
well as to the TTL queue. When runs are dequeued, they are removed from
both their normal queue and the TTL queue. If runs are dequeued by the
TTL system, they are removed from their normal queue. Both these
dequeues happen automatically so there is no race condition.

The TTL expiration system is also made reliable by expiring runs via a
Redis worker, which is enqueued to atomically inside the TTL dequeue lua
script.

### Optional associated waitpoints

Additionally, this PR implements an optimization where runs that aren't
triggered with a dependent parent run will no longer create an
associated waitpoint. Associated waitpoints are then lazily created if a
dependent run wants to wait for the child run post-facto (via debounce
or idempotency), which is a rare situation but is possible. This means
fewer waitpoint creations but also fewer waitpoint completions for runs
with no dependencies.

### Environment Queue Limits

Prevents any single queue growing too large by enforcing queue size
limits at trigger time.

- Queue size checks happen at trigger time - runs are rejected if queue
would exceed limit
- Dashboard UI shows queue limits on both the Queues page and a new
Limits page
- In-memory caching for queue size checks to reduce Redis load

### Batch trigger fixes

Currently when a batch item cannot be created for whatever reason (e.g.
queue limits) the run will never get created, which means a stalled run
if using `batchTriggerAndWait`. We've updated the system to handle this
differently: now when a batch item cannot be triggered and converted
into a run, we will eventually (after retrying 8 times up to 30s) we
will create a "pre-failed" run with the error details, correctly
resolving the batchTriggerAndWait.
2026-02-23 15:57:32 +00:00
Oskar Otwinowski 69dc7bcde8 feat(webapp): Vercel / Slack integrations improvements (#3108)
##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

Slack + GitHub + Vercel + Builds + Deployments

---

## Changelog

Settings changes:
- Split general from integrations
- Add new Slack section to org level integrations
Vercel improvements:
- bugfix for TRIGGER_SECRET_KEY collision
- onboarding improvements for connecting to projects
- new loops event
Slack improvements:
- nicer alerts
Webhook/Email alerts:
- rich events with Github & Vercel integration data

---

## Screenshots


<img width="2550" height="652" alt="Screenshot 2026-02-20 at 21 53 34"
src="https://github.com/user-attachments/assets/8d7c9f1d-5fe9-4516-8fb3-885460b4207f"
/>
<img width="843" height="710" alt="Screenshot 2026-02-23 at 10 55 54"
src="https://github.com/user-attachments/assets/8ea72c1f-431b-493c-b9a9-8076cce12262"
/>
<img width="765" height="466" alt="Screenshot 2026-02-20 at 21 52 46"
src="https://github.com/user-attachments/assets/157fafb8-b7bf-499d-8953-c2aed5e44ce0"
/>
<img width="691" height="261" alt="Screenshot 2026-02-20 at 22 04 24"
src="https://github.com/user-attachments/assets/3aea7369-2008-4af8-a9c0-5fbfa2cc381d"
/>
<img width="2032" height="1114" alt="Screenshot 2026-02-19 at 14 48 49"
src="https://github.com/user-attachments/assets/dc10c14e-cd15-445a-b5be-d694d29d20e5"
/>
<img width="2032" height="1114" alt="Screenshot 2026-02-19 at 14 49 04"
src="https://github.com/user-attachments/assets/1ef591fd-fd00-430a-9649-8b18cff9586d"
/>
<img width="1583" height="1115" alt="Screenshot 2026-02-19 at 17 32 56"
src="https://github.com/user-attachments/assets/c5c8f318-d193-4dd4-86f7-1cc4bbcc4e0c"
/>
<img width="422" height="187" alt="Screenshot 2026-02-20 at 21 57 41"
src="https://github.com/user-attachments/assets/37865cb6-4c0d-40ef-9c60-7b057d546c61"
/>
<img width="1583" height="1115" alt="Screenshot 2026-02-19 at 17 33 06"
src="https://github.com/user-attachments/assets/e9180e8e-e611-4734-9232-80c62ff863ad"
/>

💯
2026-02-23 13:48:09 +00:00
Matt Aitken 3a7054628f Fix: show the deprecation panel if it's an old project and v3 (#3113)
Without doing an expensive query we can’t tell if it’s definitely a v3
projects – like getting run counts.
So let’s just assume if the project hasn’t been upgraded to v4 (by
running dev/deploy CLI with v4) AND the project is older than the v4
release then it’s v3.
2026-02-23 11:10:37 +00:00
Eric Allam 676525279a docs: otel metrics (#3096) 2026-02-20 16:51:48 +00:00
James Ritchie 79f8cdef72 Fix(webapp): logs button + logs table row link fix (#3107)
Small fixes and improvements to the logs page:

- Clicking the Run ID didn't open inspector
- Swapped the "open link in tab" icon with Runs icon
- Prevent tooltip hovering on Level info

<img width="350" height="206" alt="CleanShot 2026-02-20 at 10 00 37@2x"
src="https://github.com/user-attachments/assets/3e82f24a-c0a1-4c01-a8e9-9e06a8af982a"
/>
2026-02-20 16:44:55 +00:00
github-actions[bot] 98bf706437 chore: release v4.4.1 (#3100)
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 6s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and publish to npm
yourself or [setup this action to publish
automatically](https://github.com/changesets/action#with-publishing). If
you're not ready to do a release yet, that's fine, whenever you add more
changesets to main, this PR will be updated.


# Releases
## @trigger.dev/build@4.4.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.1`

## trigger.dev@4.4.1

### Patch Changes

- Add OTEL metrics pipeline for task workers. Workers collect process
CPU/memory, Node.js runtime metrics (event loop utilization, event loop
delay, heap usage), and user-defined custom metrics via
`otel.metrics.getMeter()`. Metrics are exported to ClickHouse with
10-second aggregation buckets and 1m/5m rollups, and are queryable
through the dashboard query engine with typed attribute columns,
`prettyFormat()` for human-readable values, and AI query support.
([#3061](https://github.com/triggerdotdev/trigger.dev/pull/3061))
-   Updated dependencies:
    -   `@trigger.dev/build@4.4.1`
    -   `@trigger.dev/core@4.4.1`
    -   `@trigger.dev/schema-to-json@4.4.1`

## @trigger.dev/python@4.4.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/sdk@4.4.1`
    -   `@trigger.dev/build@4.4.1`
    -   `@trigger.dev/core@4.4.1`

## @trigger.dev/react-hooks@4.4.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.1`

## @trigger.dev/redis-worker@4.4.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.1`

## @trigger.dev/rsc@4.4.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.1`

## @trigger.dev/schema-to-json@4.4.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.1`

## @trigger.dev/sdk@4.4.1

### Patch Changes

- Add OTEL metrics pipeline for task workers. Workers collect process
CPU/memory, Node.js runtime metrics (event loop utilization, event loop
delay, heap usage), and user-defined custom metrics via
`otel.metrics.getMeter()`. Metrics are exported to ClickHouse with
10-second aggregation buckets and 1m/5m rollups, and are queryable
through the dashboard query engine with typed attribute columns,
`prettyFormat()` for human-readable values, and AI query support.
([#3061](https://github.com/triggerdotdev/trigger.dev/pull/3061))
-   Updated dependencies:
    -   `@trigger.dev/core@4.4.1`

## @trigger.dev/core@4.4.1

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 16:40:06 +00:00
Iss 354363e408 docs: Vercel integration – marketplace link, Build options, Root Directory warning (#3097)
Adds a direct Vercel Marketplace link, documents configuring build
options via the project config page, and adds a warning and workaround
for projects using a Vercel Root Directory
2026-02-20 10:56:44 -05:00
Iss 525145def0 docs: v3 deprecation notice and Migrate using AI updates on migrating-from-v3 (#3098)
Adds a deprecation warning at the top of the migrating-from-v3 page and
updates the “Migrate using AI” prompt and intro
2026-02-20 10:55:48 -05:00
Eric Allam 23c327ea16 fix(metrics): disable collecting system and filesystem metrics in deployed workers (#3106) 2026-02-20 15:45:35 +00:00
Eric Allam d794101c67 fix(webapp): fix broken MFA by only committing one auth session set-cookie call (#3104)
Co-authored-by: Oskar Otwinowski <oskar.otwinowski@gmail.com>
2026-02-20 15:09:53 +00:00
Eric Allam f325638892 fix(tests): fix flaky getSnapshotsSince test (#3103) 2026-02-20 14:52:59 +00:00
Eric Allam 68e3f8c9db chore(clickhouse): more clickhouse migration conflict fixes (#3102) 2026-02-20 13:28:58 +00:00
Eric Allam 2071090042 chore(clickhouse): fix clickhouse migration version conflict (#3101) 2026-02-20 14:24:56 +01:00
Eric Allam 469b039090 feat: OTEL metrics pipeline for task workers (#3061)
- Adds an end-to-end OTEL metrics pipeline: task workers collect and
export metrics via OpenTelemetry, the webapp ingests them into
ClickHouse, and they're queryable through the existing dashboard query
engine
- Workers emit process CPU/memory metrics (via
`@opentelemetry/host-metrics`) and Node.js runtime metrics (event loop
utilization, event loop delay, heap usage)
- Users can create custom metrics in their tasks via
`otel.metrics.getMeter()` from `@trigger.dev/sdk`
- Metrics are automatically tagged with run context (run ID, task slug,
machine, worker version) so they can be sliced per-run, per-task, or
per-machine
- The TSQL query engine gains metrics table support with typed attribute
columns, `prettyFormat()` for human-readable values, and per-schema time
bucket thresholds
- Includes reference tasks
(`references/hello-world/src/trigger/metrics.ts`) demonstrating
CPU-intensive, memory-ramp, bursty workload, and custom metrics patterns

## What changed

### Metrics collection (packages/core, packages/cli-v3)
- **Metrics export pipeline** — `TracingSDK` now sets up a
`MeterProvider` with a `PeriodicExportingMetricReader` that chains
through `TaskContextMetricExporter` (adds run context attributes) and
`BufferingMetricExporter` (batches exports to reduce overhead)
- **Host metrics** — Enabled `@opentelemetry/host-metrics` for process
CPU, memory, and system-level metrics
- **Node.js runtime metrics** — New `nodejsRuntimeMetrics.ts` module
using `performance.eventLoopUtilization()`, `monitorEventLoopDelay()`,
and `process.memoryUsage()` to emit 6 observable gauges
- File system and diskio metrics
- **Custom metrics** — Exposed `otel.metrics` from `@trigger.dev/sdk` so
users can create counters, histograms, and gauges in their tasks
- **Machine ID** — Stable per-worker machine identifier for grouping
metrics
- **Dev worker** — Drops `system.*` metrics to reduce noise, keeps
sending metrics between runs in warm workers

### Metrics ingestion (apps/webapp)
- **OTEL endpoint** — `otel.v1.metrics.ts` accepts OTEL metric export
requests (JSON and protobuf), converts to ClickHouse rows
- **ClickHouse schema** — `017_create_metrics_v1.sql` with 10-second
aggregation buckets, JSON attributes column, 60-day TTLs

### Query engine (internal-packages/tsql, apps/webapp)
- **Metrics query schema** — Typed columns for metric attributes
(`task_identifier`, `run_id`, `machine_name`, `worker_version`, etc.)
extracted from the JSON attributes column
- **`prettyFormat()`** — TSQL function that annotates columns with
format hints (`bytes`, `percent`, `durationSeconds`) for frontend
rendering without changing the underlying data
- **Per-schema time buckets** — Different tables can define their own
time bucket thresholds (metrics uses tighter intervals than runs)
- **AI query integration** — The AI query service knows about the
metrics table and can generate metric queries
- **Chart improvements** — Better formatting for byte values,
percentages, and durations in charts and tables

### Reference project
- **`references/hello-world/src/trigger/metrics.ts`** — 6 example tasks:
`cpu-intensive`, `memory-ramp`, `bursty-workload`, `sustained-workload`,
`concurrent-load`, `custom-metrics`

## Test plan

- [ ] Build all packages and webapp
- [ ] Start dev worker with hello-world reference project
- [ ] Run `cpu-intensive`, `memory-ramp`, and `custom-metrics` tasks
- [ ] Verify metrics in ClickHouse: `SELECT DISTINCT metric_name FROM
metrics_v1`
- [ ] Query via dashboard AI: "show me CPU utilization over time"
- [ ] Verify `prettyFormat` renders correctly in chart tooltips and
table cells
- [ ] Confirm dev worker drops `system.*` metrics but keeps `process.*`
and `nodejs.*`
2026-02-20 13:16:34 +00:00
Eric Allam 38981f5e70 chore(docs): cover maxDelay debounce option (#2985)
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2985">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-19 13:50:33 +00:00
Matt Aitken 22505e9803 Query and Metrics docs (#3074)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-02-19 13:50:13 +00:00
github-actions[bot] 84a00b6eb6 chore: release v4.4.0 (#2941)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 3s
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and publish to npm
yourself or [setup this action to publish
automatically](https://github.com/changesets/action#with-publishing). If
you're not ready to do a release yet, that's fine, whenever you add more
changesets to main, this PR will be updated.


# Releases
## @trigger.dev/sdk@4.4.0

### Minor Changes

- Added `query.execute()` which lets you query your Trigger.dev data
using TRQL (Trigger Query Language) and returns results as typed JSON
rows or CSV. It supports configurable scope (environment, project, or
organization), time filtering via `period` or `from`/`to` ranges, and a
`format` option for JSON or CSV output.
([#3060](https://github.com/triggerdotdev/trigger.dev/pull/3060))

    ```typescript
    import { query } from "@trigger.dev/sdk";
    import type { QueryTable } from "@trigger.dev/sdk";

    // Basic untyped query
const result = await query.execute("SELECT run_id, status FROM runs
LIMIT 10");

    // Type-safe query using QueryTable to pick specific columns
const typedResult = await query.execute<QueryTable<"runs", "run_id" |
"status" | "triggered_at">>(
      "SELECT run_id, status, triggered_at FROM runs LIMIT 10"
    );
    typedResult.results.forEach((row) => {
      console.log(row.run_id, row.status); // Fully typed
    });

    // Aggregation query with inline types
const stats = await query.execute<{ status: string; count: number }>(
      "SELECT status, COUNT(*) as count FROM runs GROUP BY status",
      { scope: "project", period: "30d" }
    );

    // CSV export
    const csv = await query.execute("SELECT run_id, status FROM runs", {
      format: "csv",
      period: "7d",
    });
    console.log(csv.results); // Raw CSV string
    ```

### Patch Changes

- Add `maxDelay` option to debounce feature. This allows setting a
maximum time limit for how long a debounced run can be delayed, ensuring
execution happens within a specified window even with continuous
triggers.
([#2984](https://github.com/triggerdotdev/trigger.dev/pull/2984))

    ```typescript
    await myTask.trigger(payload, {
      debounce: {
        key: "my-key",
        delay: "5s",
maxDelay: "30m", // Execute within 30 minutes regardless of continuous
triggers
      },
    });
    ```

- Aligned the SDK's `getRunIdForOptions` logic with the Core package to
handle semantic targets (`root`, `parent`) in root tasks.
([#2874](https://github.com/triggerdotdev/trigger.dev/pull/2874))

- Export `AnyOnStartAttemptHookFunction` type to allow defining
`onStartAttempt` hooks for individual tasks.
([#2966](https://github.com/triggerdotdev/trigger.dev/pull/2966))

- Fixed a minor issue in the deployment command on distinguishing
between local builds for the cloud vs local builds for self-hosting
setups.
([#3070](https://github.com/triggerdotdev/trigger.dev/pull/3070))

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.0`

## @trigger.dev/build@4.4.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.0`

## trigger.dev@4.4.0

### Patch Changes

- Fix runner getting stuck indefinitely when `execute()` is called on a
dead child process.
([#2978](https://github.com/triggerdotdev/trigger.dev/pull/2978))
- Add optional `timeoutInSeconds` parameter to the
`wait_for_run_to_complete` MCP tool. Defaults to 60 seconds. If the run
doesn't complete within the timeout, the current state of the run is
returned instead of waiting indefinitely.
([#3035](https://github.com/triggerdotdev/trigger.dev/pull/3035))
- Fixed a minor issue in the deployment command on distinguishing
between local builds for the cloud vs local builds for self-hosting
setups.
([#3070](https://github.com/triggerdotdev/trigger.dev/pull/3070))
-   Updated dependencies:
    -   `@trigger.dev/core@4.4.0`
    -   `@trigger.dev/build@4.4.0`
    -   `@trigger.dev/schema-to-json@4.4.0`

## @trigger.dev/core@4.4.0

### Patch Changes

- Add `maxDelay` option to debounce feature. This allows setting a
maximum time limit for how long a debounced run can be delayed, ensuring
execution happens within a specified window even with continuous
triggers.
([#2984](https://github.com/triggerdotdev/trigger.dev/pull/2984))

    ```typescript
    await myTask.trigger(payload, {
      debounce: {
        key: "my-key",
        delay: "5s",
maxDelay: "30m", // Execute within 30 minutes regardless of continuous
triggers
      },
    });
    ```

- Fixed a minor issue in the deployment command on distinguishing
between local builds for the cloud vs local builds for self-hosting
setups.
([#3070](https://github.com/triggerdotdev/trigger.dev/pull/3070))

- fix: vendor superjson to fix ESM/CJS compatibility
([#2949](https://github.com/triggerdotdev/trigger.dev/pull/2949))

Bundle superjson during build to avoid `ERR_REQUIRE_ESM` errors on
Node.js versions that don't support `require(ESM)` by default (&lt;
22.12.0) and AWS Lambda which intentionally disables it.

- Add Vercel integration support to API schemas: `commitSHA` and
`integrationDeployments` on deployment responses, and `source` field for
environment variable imports.
([#2994](https://github.com/triggerdotdev/trigger.dev/pull/2994))

## @trigger.dev/python@4.4.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.0`
    -   `@trigger.dev/sdk@4.4.0`
    -   `@trigger.dev/build@4.4.0`

## @trigger.dev/react-hooks@4.4.0

### Patch Changes

- Fix `onComplete` callback firing prematurely when the realtime stream
disconnects before the run finishes.
([#2929](https://github.com/triggerdotdev/trigger.dev/pull/2929))
-   Updated dependencies:
    -   `@trigger.dev/core@4.4.0`

## @trigger.dev/redis-worker@4.4.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.0`

## @trigger.dev/rsc@4.4.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.0`

## @trigger.dev/schema-to-json@4.4.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.0`

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-19 13:38:10 +00:00
James Ritchie 506b161751 feature(webapp): Show a v3 deprecation notice in the side bar (#3090)
- If your project is v3, show a v3 deprecation panel in the side menu
- If there is an active incident, show the incident panel instead
- Links to the Migration guide in the docs
- Displays when the side menu is collapsed



https://github.com/user-attachments/assets/f8492713-c58b-4f83-bcce-0e85f4a967ef

<img width="972" height="694" alt="CleanShot 2026-02-19 at 08 13 59@2x"
src="https://github.com/user-attachments/assets/0599dd20-d598-48c6-b83c-208648cee071"
/>
2026-02-19 11:02:10 +00:00
Matt Aitken 1ec7722690 Add Queue Management API endpoints and SDK documentation (#3087)
Closes #<issue>

##  Checklist

- [ ] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [ ] The PR title follows the convention.
- [ ] I ran and tested the code works

---

## Testing

N/A - Documentation and OpenAPI schema updates only.

---

## Changelog

Added comprehensive Queue Management API support:

**OpenAPI Endpoints:**
- `GET /api/v1/queues` - List all queues with pagination support
- `GET /api/v1/queues/{queueParam}` - Retrieve a specific queue by ID,
task ID, or custom queue name
- `POST /api/v1/queues/{queueParam}/pause` - Pause or resume a queue
- `POST /api/v1/queues/{queueParam}/concurrency/override` - Override
queue concurrency limits
- `POST /api/v1/queues/{queueParam}/concurrency/reset` - Reset
concurrency limits to base values

**Schema Definitions:**
- `QueueObject` - Complete queue representation with concurrency details
- `ListQueuesResult` - Paginated queue listing response

**Documentation:**
- Updated `queue-concurrency.mdx` with SDK usage examples for queue
management
- Added 5 new management API documentation pages for each endpoint
- Updated `docs.json` navigation structure with new "Queues API" section

All endpoints support flexible queue identification (by ID, task ID, or
custom queue name) and include TypeScript code samples.

---

## Screenshots

N/A

💯

https://claude.ai/code/session_01LyrXwxHCbejvi34fykifPP

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-18 22:35:39 +00:00
Iss 2825a200e6 docs: added v3 to v4 migreation note about IP change (#3086) 2026-02-18 18:08:00 +00:00
Matt Aitken eb0f963393 feat(metrics): Dashboard charts performance improvements (#3083)
Summary
- Only render the top 50 series
- Improved rendering performance on bar charts
2026-02-18 16:12:00 +00:00
nicktrn 59b6eb9a3e feat(webapp): add region selector to test and replay task (#3082)
Adds a region selector to the Test task page and Replay run dialog, so
users can override the region from the dashboard. Disabled with a
placeholder for dev environments.

Closes #3016
2026-02-18 10:39:38 +00:00
Mihai Popescu b793f33e59 Logs: new materialized view and some UI improvements (#3069)
This will prevent internal logs to be added to the
task_events_search_table

Closes #<issue>

##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

Ran the migration, deleted the old invalid rows and ran new tasks.
The undesired logs are not added to the table.

---

## Changelog

Updated the MATERIALIZED VIEW to also filter for `trace_id != ''`

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2026-02-18 09:48:52 +00:00
Oskar Otwinowski 6e0b54b081 docs(vercel): add comprehensive Vercel integration docs (#3081)
Expand documentation for the Vercel integration with detailed usage,
installation, environment variable sync, atomic deployments, and
environment mapping. Replace the previous "coming soon" placeholder with
complete instructions and UI flow for connecting via the Trigger.dev
dashboard or the Vercel Marketplace. Explain required GitHub
integration,
how env vars sync in both directions, which vars are excluded, and how
to control sync behavior. Describe atomic deployments (default for
production), how they gate Vercel deployments to ensure task/app
consistency, and note related configuration changes. Add tips and notes
to guide setup and troubleshooting.

This provides users with actionable guidance to connect Vercel, map
environments, and keep app and tasks in sync without custom CI scripts.
2026-02-17 18:19:00 +01:00
Eric Allam 4c986ad1eb fix(docs): Fix loop to iterate over results.runs (#3077)
To get access to the runs from `batch.triggerAndWait` use `results.runs`
2026-02-17 13:52:58 +01:00
Saadi Myftija 7af789bc3e fix(deployments): external build token generation issue (#3070)
Fixes an issue introduced in #3024.

The behavior for local builds in older CLI versions relies on
`externalBuildData` to be defined to distinguish from the self-hosting
local build path, even though it doesn't actually use the token.
2026-02-16 19:05:40 +01:00
Oskar Otwinowski 72ce6a8300 fix(vercel): Keep search params for OAuth redirects (#3071) 2026-02-16 18:51:33 +01:00
Pramod Dhungana 921285ca32 add friendly messages for common http error codes (#3001)
Closes #<issue>

##  Checklist

- [ x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x ] The PR title follows the convention.
- [ x] I ran and tested the code works

---

## Testing

Verified the error message mapping logic locally and ensured existing
behavior remains unchanged.


---

## Changelog

Added friendly messages for HTTP 401, 403, and 429 errors.





<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3001">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-16 11:42:26 +00:00
Iss 667a93ca3c docs: add ClickHouse migration troubleshooting tip (#3011)
Adds troubleshooting tip for when ClickHouse migrations report "no
migrations to run" but the schema is missing. This happens when the
goose migration tracker is out of sync with the actual schema state.

<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3011"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-16 11:41:31 +00:00
DKP 4dfa65809a Dropped bracket highlight and border by 50% (#3068) 2026-02-16 11:31:02 +00:00
Matt Aitken d4cd34094e Query API and SDK (#3060)
Summary
- Add API endpoint to run TRQL queries
- Implement SDK function for executing queries

## SDK
Added `query.execute()` which lets you query your Trigger.dev data using
TRQL (Trigger Query Language) and returns results as typed JSON rows or
CSV. It supports configurable scope (environment, project, or
organization), time filtering via `period` or `from`/`to` ranges, and a
`format` option for JSON or CSV output.

```typescript
import { query } from "@trigger.dev/sdk";
import type { QueryTable } from "@trigger.dev/sdk";

// Basic untyped query
const result = await query.execute("SELECT run_id, status FROM runs LIMIT 10");

// Type-safe query using QueryTable to pick specific columns
const typedResult = await query.execute<QueryTable<"runs", "run_id" | "status" | "triggered_at">>(
  "SELECT run_id, status, triggered_at FROM runs LIMIT 10"
);
typedResult.results.forEach(row => {
  console.log(row.run_id, row.status); // Fully typed
});

// Aggregation query with inline types
const stats = await query.execute<{ status: string; count: number }>(
  "SELECT status, COUNT(*) as count FROM runs GROUP BY status",
  { scope: "project", period: "30d" }
);

// CSV export
const csv = await query.execute(
  "SELECT run_id, status FROM runs",
  { format: "csv", period: "7d" }
);
console.log(csv.results); // Raw CSV string
```
2026-02-16 10:53:41 +00:00
James Ritchie 796ad29386 Fix(webapp): consistent query button width (#3067)
Prevents layout shift by keeping the button width the same when
isLoading

Normal state
<img width="423" height="186" alt="CleanShot 2026-02-16 at 10 31 23"
src="https://github.com/user-attachments/assets/232bc14f-dc2c-4092-9b46-f6d652568633"
/>

isLoading
<img width="403" height="137" alt="CleanShot 2026-02-16 at 10 31 43"
src="https://github.com/user-attachments/assets/e9215b48-c2cc-4ede-91ff-08bbdb2382a0"
/>
2026-02-16 10:49:37 +00:00
James Ritchie b4e08bddec Fix(webapp): metrics UI improvements (#3063)
- Lots of small UI improvements
- Toggle full screen charts with "V" shortcut

<img width="3504" height="2286" alt="CleanShot 2026-02-14 at 20 06
30@2x"
src="https://github.com/user-attachments/assets/32403661-06b3-4f6c-a074-243b3f43197d"
/>

<img width="362" height="222" alt="CleanShot 2026-02-14 at 20 06 58@2x"
src="https://github.com/user-attachments/assets/ee4f5859-4b71-482e-9636-5abd78d9f623"
/>

<img width="434" height="360" alt="CleanShot 2026-02-14 at 20 06 53@2x"
src="https://github.com/user-attachments/assets/44339348-f3f3-425b-bbf3-bb41ed6a8e59"
/>

<img width="460" height="310" alt="CleanShot 2026-02-14 at 20 06 48@2x"
src="https://github.com/user-attachments/assets/eb3b6af6-b88a-4677-8a48-acfa6b768770"
/>

<img width="502" height="332" alt="CleanShot 2026-02-14 at 20 06 45@2x"
src="https://github.com/user-attachments/assets/b788d78b-8f4a-4b18-94c8-487673f3ec7b"
/>

<img width="370" height="257" alt="CleanShot 2026-02-14 at 20 10 29@2x"
src="https://github.com/user-attachments/assets/a81e8b14-b2eb-402c-bf3b-affd0d4fde26"
/>
2026-02-14 21:26:25 +00:00
Iss 5d6085dcff docs: Realtime skipColumns and Bun indexing troubleshooting (#3054)
Documents the skipColumns option on useRealtimeRun and
useRealtimeRunsWithTag for status-only subscriptions (smaller payloads,
e.g. for progress/completion UI). Adds a troubleshooting section for the
“Failed to index deployment” source-map error when using the Bun
runtime, with a pnpm patch workaround and link to the GitHub issue
2026-02-14 14:02:00 -05:00
nicktrn 1d744fa3c6 fix(dashboard): apply time filter preset periods immediately on click (#3053)
Extract `applyPeriod` callback from `applySelection` so preset period
buttons ("Created in the last X") apply immediately when clicked,
instead of only updating the selection state and requiring a separate
apply step.

Also validates `maxPeriodDays` on instant-apply so the upgrade prompt
still works correctly for plan-limited periods.
2026-02-13 18:35:39 +00:00
Matt Aitken a3d3b17df4 TRQL: always add FINAL keyword (#3051)
For now we’re going to always add FINAL to TRQL queries for data
correctness.

In the future we will implement an automated optimization where we use
`SELECT argMax(column, _version)` and `WHERE _is_deleted = 0`. But this
is a more complex change and needs more investigation of downsides.
2026-02-13 17:34:43 +00:00
James Ritchie 35e11e09a3 Fix(webapp): Show an error to the user when their add-on upgrade payment fails (#3050)
A customer experienced a bug where their subscription downgraded to the
free plan unintentionally. This was due to a concurrency upgrade payment
attempt that failed a card check. We auto retry the payment across 2
weeks of attempts. When the final attempt failed, the whole subscription
downgraded.

Now we check if the payment is successful and if not, return an error
immediately so the subscription isn't modified until a successful
payment is made for an upgrade.
2026-02-13 16:52:04 +00:00
Matt Aitken 9030e94362 Metrics improvements (#3046)
Summary
- Remove LIMIT from built-in dashboard queries
- Make concurrency configurable per project via environment variables
- Fix widget fallback period to Metrics default (1d) instead of 7d
- Handle concurrency at the project level
- Sort series for graphs so largest is displayed at the bottom (legend
shows largest at top)
- Use average aggregation for some built-in charts
- Improve aggregation handling for the legend
- Only render chart points when there is data; render dots on line
charts
- Truncate legend items and show tooltip on hover
- Better preserve chart configuration when the underlying query changes
2026-02-13 15:57:11 +00:00
Eric Allam 2462c80c8a chore(vouch): vouch for capaj (#3048) 2026-02-13 15:56:05 +01:00
Mihai Popescu a8f9a90280 improv(webapp): Add new table for optimized logs search (#3036)
##  Checklist

- [X] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [X] The PR title follows the convention.
- [X] I ran and tested the code works

---

## Testing

Tested the migration on test env and locally.
Tested query and merge performance.
Generated tasks and observed the ingested data and searches.

---

## Changelog

* New ClickHouse table & MV (task_events_search_v1): A search-optimized
materialized view that filters out debug events, partial spans, and
empty span events at ingestion time.
* ClickHouse client updates: New getLogsSearchListQueryBuilder and
taskEventsSearch accessor on the ClickHouse class.
* LogsListPresenter: Switches to the new search table, uses
triggered_timestamp for cursor pagination instead of unixTimestamp.
  *  Spans route: Also switches to the new search query builder.
* Seed spanSpammer task: Adds a 10s trace with events and metadata
operations for testing.
2026-02-13 16:28:14 +02:00
Oskar Otwinowski 4b7f67604a feat(webapp/deployments): Vercel improvements & fixes (#3037) 2026-02-13 14:06:22 +01:00
Matt Aitken bfe417f679 docs: add note about single-issue PRs to contributing guide (#3044)
Add a prominent notice at the top of CONTRIBUTING.md clarifying that we
only accept PRs addressing a single issue, not multiple fixes.

https://claude.ai/code/session_011ZNQd5zkf38piSMhWbgiWt

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-13 10:07:06 +00:00
Eric Allam ba320a4bdb chore(vouch): vouch for gautamsi (#3039) 2026-02-12 22:27:14 +00:00
Matt Aitken bc0d1ff59a Metrics dashboards (#3019)
Summary
- Implemented metrics dashboards with a built-in dashboard and custom
dashboards
- Added a "Big number” display type

What changed
- New data format for metric layouts and saving/editing layouts
(editing, saving, cancel revert)
  - QueryWidget usable on Query page and Metrics dashboards
  - Time filtering, auto-reloading and timeBucket() auto-bin support
- Filters added to metrics; widget popover/improved history and blank
states
- Side menu:
- Metrics/Insights section with icons, colors, padding, collapsible
behavior and reordering of custom dashboards
- Move action logic into service for reuse and API querying; refactor
reordering for reuse
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3019"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2026-02-12 17:48:02 +00:00
Eric Allam 062bcaece8 feat(mcp): add timeout parameter to wait_for_run_to_complete tool (#3035)
## Summary

- Adds an optional `timeoutInSeconds` parameter (default 60s) to the
`wait_for_run_to_complete` MCP tool
- If the run doesn't complete within the timeout, returns the current
run state instead of blocking indefinitely
- Uses `AbortSignal.timeout()` combined with the existing MCP signal

Fixes #3032
2026-02-12 16:14:25 +00:00
nicktrn c2085e6cc6 feat(dashboard): link git sha and ref to GitHub on settings page (#3034)
Make the git SHA and git ref in the org settings sidebar clickable links
to GitHub — SHA links to the commit, ref links to the branch/tag.
2026-02-12 15:31:52 +00:00
James Ritchie d7bc37fdc0 Feat(dashboard): show the Betterstack incident title in the dashboard (#3006)
When the incident panel is displayed, show the title added to
BetterStack as the contents of the incident panel.

I've also brightened the UI so it's more visible.

<img width="536" height="590" alt="CleanShot 2026-02-04 at 20 46 36@2x"
src="https://github.com/user-attachments/assets/040a04f8-5b52-40e8-8892-51c8efd6c08c"
/>

<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3006"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-12 08:58:21 +00:00
DKP 6e3ac8bd91 docs: cursor cli docs update (remove chmod workaround) (#3031)
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3031"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-11 13:32:49 +00:00
Matt Aitken 170fde3498 Move vouch requirement to top of CONTRIBUTING.md (#3029)
Contributors need to be vouched before opening PRs, but this requirement
was buried far down in the document. This change:
- Adds mention of vouches in the intro paragraph
- Moves the "Getting vouched" section to right after the intro

This makes the requirement more visible to new contributors.

Slack thread:
https://triggerdotdev.slack.com/archives/C0A7Q6F62NS/p1770805895370749
https://claude.ai/code/session_01G6VVbgfUAeCpJfedELdqq1
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3029"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-11 10:44:14 +00:00
Iss ddeb9c415e docs: heartbeats, Bun version, troubleshooting, and preview-branch cleanup (#3026)
Doc updates: 
- new Heartbeats page (yield, progress, external updates)
- Bun supported-version note
-  resource_exhausted troubleshooting with native builder link
- GitHub Actions preview-branch example with closed trigger so branches
archive when PRs close
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3026"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-10 21:53:41 +00:00
Saadi Myftija 2feecece88 fix(api): skip external build creation for native builds (#3024)
Native builds don't use depot, but the `/deployments/:id/progress`
endpoint was unconditionally generating depot build tokens. This is now
fixed.

The initialize deployment endpoint was already doing this check.

<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3024"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-10 19:44:44 +01:00
Oskar Otwinowski 48a96efbdc chore(webapp): Expose Vercel errors (#3025) 2026-02-10 18:30:56 +01:00
DKP ebffa1039c docs: added Cursor background agent docs (#3023)
- Adds a new example project guide for running Cursor's headless CLI
agent as a Trigger.dev task with live Realtime Streams output
- New doc page at `guides/example-projects/cursor-background-agent.mdx`
- Added to sidebar nav and example projects table
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3023"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-10 16:47:00 +00:00
Eric Allam bc63edd6bf chore(repo): adopt vouch with issue based workflow and require for PRs (#3022)
Adopting [https://github.com/mitchellh/vouch](vouch) so we can help
potential contributors by requiring a conversation before they can
submit a PR. Too many contributors have been skipping the conversation
part of contributing to an OSS repo and skipping right ahead to
submitting PRs
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3022"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-10 12:03:24 +00:00
Mihai Popescu eaed7d0ba4 fix(webapp): UI/UX improvements for logs, query, and shortcuts (#2997)
##  Checklist

- [X] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [X] The PR title follows the convention.
- [X] I ran and tested the code works

---

## Testing

Manually tested each implementation.

---

## Changelog

* Updated Logs Page with the new implementation in time filter component

* In TRQL editor users can now click on empty/blank spaces in the editor
and the cursor will appear

* Added CMD + / for line commenting in TRQL

* Activated proper undo/redo functionality in CodeMirror (TRQL editor)

* Added a check for new logs button, previously once the user got to the
end of the logs he could not check for newer logs

* Added showing MS in logs page Dates

* Removed LOG_INFO internal logs, they are available with Admin Debug
flag

* Added support for correct timezone render on server side.

* Increased CLICKHOUSE_LOGS_LIST_MAX_MEMORY_USAGE to 1GB

* Changed Previous run/ Next run to J/K, consistent with previous/next
page in Runs list
2026-02-10 12:19:26 +02:00
Oskar Otwinowski 9b21f8d322 feat(webapp): Vercel integration (#2994)
Vercel integration

Desc + Vid coming soon


For human reviewer:
- check the db schema
- check if posthog user attribution call is correct (telemetry.server.ts
& `referralSource`)
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2994"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-10 10:37:09 +01:00
nicktrn e536d35b17 fix(ci): fix docker image publishing and worker builds (#3013)
## Summary
- **Fix Docker publish automation**: The `v.docker.*` tags pushed by the
release workflow using `GITHUB_TOKEN` don't trigger the publish workflow
(GitHub Actions limitation to prevent infinite loops). Added a
`workflow_call` to `publish.yml` directly from the release job so Docker
images are built automatically after npm publish. Tags are still pushed
for reference.
- **Fix worker Containerfiles**: The coordinator, docker-provider, and
kubernetes-provider builds have been failing since the superjson
vendoring change in `@trigger.dev/core` (#2949). The Containerfiles now
run `bundle-vendor` before `build:bundle` to generate the vendor files
that esbuild needs.

### Context
- Docker images on GHCR have been stuck at v4.3.0 — v4.3.1, v4.3.2,
v4.3.3 tags existed on GitHub but never triggered publish runs
- The worker builds (publish-worker) have been failing on every push to
main since Jan 30

## Test plan
- [x] Verified kubernetes-provider Containerfile builds locally with the
fix
- [x] Manually dispatched publish workflow for v4.3.1 — all jobs
succeeded
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3013"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-06 13:56:39 +00:00
DKP b96a0b70d4 Docs: Clarify AI tool compatibility and expand context snippet (#3000)
This pull request overhauls the "Building with AI" documentation
section. It includes a comprehensive restructuring of the main
building-with-ai page with new setup guides and troubleshooting
sections, reorganizes the navigation hierarchy to elevate
mcp-agent-rules as a top-level page, and updates multiple documentation
pages to clarify the relationships between three AI tools: Skills, Agent
Rules, and MCP Server. Changes also include formatting improvements,
such as replacing italicized text with inline code formatting, and
consistent additions of explanatory Note blocks and CardGroup components
across related pages.
2026-02-05 15:22:44 -08:00
James Ritchie 3bb9aac014 Fix(webapp): Prevent big numbers on Queue page from jumping around when animating (#3007) 2026-02-05 07:45:40 -08:00
Saadi Myftija 283f88b203 feat(webapp): add triggered via field to deployment details page (#2850)
Display the deployment trigger source (CLI, CI/CD, Dashboard, GitHub
Integration) with appropriate icons on the deployment details page. The
triggeredVia field was already in the database but not displayed.

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-05 15:24:23 +01:00
James Ritchie c55af7bead fix(webapp): ask ai button missing tooltip (#2964)
Fixes
- the tooltip not displaying on the AskAI button in the side menu
- incorrect AskAI button heights
- Small UI tweaks
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2964">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->

---------

Co-authored-by: Mihai Popescu <mihai.popescu.dev@gmail.com>
2026-02-05 03:17:18 +02:00
Iss db4fb9eeef docs: Add Hookdeck example (#3005)
Add documentation for integrating Hookdeck with Trigger.dev to receive
webhooks and forward them to Trigger.dev tasks.
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/3005">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-04 16:50:59 -08:00
Iss c0595700f8 docs: clarify .env.local loading and idempotency key reset scope (#2996)
Document that .env.local is automatically loaded during dev, and clarify
that backend-triggered idempotency keys should be reset with global
scope
2026-02-04 09:37:35 -05:00
Iss 6a45f5623b docs: multi-tenant applications and concurrency limits (#2961)
Adds an example of multi-tenant applications as alternative to
project/limit increase, and more info about queue times and concurrency
2026-02-04 09:33:05 -05:00
Iss 104f720f6f docs(troubleshooting): add COULD_NOT_FIND_EXECUTOR error and IPv4 support (#2950)
Document COULD_NOT_FIND_EXECUTOR error with dynamic imports and IPv4
database connection limitation in troubleshooting guide.
2026-02-04 09:30:51 -05:00
Iss e017913021 docs(self-hosting): added graphile worker troubleshooting to docs (#2883)
Add troubleshooting documentation for graphile worker schema migration
failures and PostgreSQL SSL certificate issues that prevent worker
initialization.
2026-02-04 09:29:01 -05:00
Matt Aitken 7781e2aad1 docs: usage function examples were missing the imports (#2830)
Closes #2828
2026-02-04 14:05:59 +00:00
Saadi Myftija 8e0034484c feat(supervisor): project-based scheduling affinity for image cache locality (#2995)
⚒️ Publish Worker (v4) / build (supervisor) (push) Has been cancelled
Adds optional pod affinity so pods from the same project prefer
scheduling on the same node. This can help improve image cache hit
rates; subsequent pods benefit from already-pulled image layers,
reducing startup time.

Complements the built-in ImageLocality scheduler plugin by helping
during burst scheduling scenarios. Pod affinity sees scheduled pods
immediately, while ImageLocality only sees images after they're fully
pulled.

Configuration:
- `KUBERNETES_PROJECT_AFFINITY_ENABLED` - Enable/disable (default:
false)
- `KUBERNETES_PROJECT_AFFINITY_WEIGHT` - Scheduler weight 1-100
(default: 50)
- `KUBERNETES_PROJECT_AFFINITY_TOPOLOGY_KEY` - Topology key (default:
kubernetes.io/hostname)

Uses soft (preferred) affinity so pods always schedule even if preferred
node is full.

<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2995">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-02-04 14:39:47 +01:00
Eric Allam b72cacc671 feat(debounce): add maxDelay option to limit total debounce time (#2984) 2026-02-02 20:15:06 +00:00
Mihai Popescu 1ccb8c186f changed schema id (#2983)
Fixed duplicate schema id for clickhouse
2026-02-02 02:43:39 +02:00
nicktrn 279102c17c fix(cli): reject execute() immediately when child process is dead (#2978)
## Summary
- When a child process crashes and a retry (`RETRY_IMMEDIATELY`) is
attempted on the same `TaskRunProcess`, `execute()` hangs forever
because the IPC send is silently skipped and the attempt promise can
never resolve
- This caused runner pods to stay up indefinitely with no heartbeats or
polls
- Fix: reject the attempt promise immediately when the child is not
connected, so the controller can proceed to warm start or exit

## Test plan
- [x] Added `taskRunProcess.test.ts` — verifies `execute()` rejects
promptly instead of hanging when the child process is dead
- [x] Deploy and verify no more stuck runner pods accumulate over time
2026-01-30 16:44:46 +00:00
Eric Allam b221719c09 chore(repo): fixed missing dependency in pnpm lockfile (#2976)
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2976">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-30 10:02:30 +00:00
Matt Aitken e6861f4fe4 Fix: run page logs keep refreshing when a run finishes (#2971)
Closes #2798

When a run finished the logs UI could get stuck and so be pending and
never update again. If you did a hard reload it would be correct.

This happened because when we insert a log/span we ping Redis which
causes a reload of the UI. However there was a race condition – the
insert into ClickHouse can take a while so we were refreshing the UI too
early. Then never refreshing it again.
  
Changes
- Send refresh pings every 5s to keep run page logs live
- Throttle updates so the run UI is never updated more than once per
second
- Stop auto-reloading when a run has been completed for >= 30s
- Add type inference improvements for the throttle function
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2971">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-30 09:47:56 +00:00
Matt Aitken bc7ce78103 fix(sdk): export AnyOnStartAttemptHookFunction type (#2966)
Export AnyOnStartAttemptHookFunction type to allow defining
onStartAttempt hooks for individual tasks.

https://claude.ai/code/session_018jgSVcFtKVyv65ktGNQFFq
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2966">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-30 09:17:37 +00:00
Eric Allam 9937823a7f Standardize @types/node to version 20.14.14 across monorepo (#2970)
##  Checklist

- [ ] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [ ] The PR title follows the convention.
- [ ] I ran and tested the code works

---

## Description

This PR standardizes the `@types/node` dependency across the entire
monorepo to version `20.14.14`. Previously, different packages were
using different versions (ranging from 12.20.55 to 22.13.9), which could
cause type conflicts and inconsistencies.

### Changes Made

1. **tsconfig.json** - Added `"node"` to the `types` array in
`apps/webapp/tsconfig.json` to ensure Node.js types are properly
recognized
2. **package.json overrides** - Added `@types/node` version override to
`20.14.14` in the root `package.json`
3. **pnpm-lock.yaml** - Updated lock file to reflect the standardized
version across all packages and their dependencies
4. **Fixture package.json** - Updated
`packages/cli-v3/e2e/fixtures/emit-decorator-metadata/package.json` to
use the standardized version

This ensures consistent type definitions across the monorepo and
prevents version mismatches that could lead to type errors or unexpected
behavior.

---

## Testing

- Verified that all package references to `@types/node` now point to
version `20.14.14`
- Confirmed that the lock file properly reflects the override across all
transitive dependencies
- Ensured TypeScript configuration includes Node.js types for proper
type checking

---

## Changelog

- Standardized `@types/node` to version `20.14.14` across all packages
in the monorepo
- Added `"node"` to TypeScript compiler types in webapp configuration
- Updated all package dependencies to use the consistent version through
pnpm overrides

💯

https://claude.ai/code/session_018eqp2LvvErkFSN9oK5xBh1
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2970">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
2026-01-30 09:15:35 +00:00
Eric Allam 3925f8cc49 fix(core): vendor superjson to fix ESM/CJS compatibility (#2949)
Bundle superjson and its dependency (copy-anything) during build to
avoid
ERR_REQUIRE_ESM errors on Node.js versions that don't support
require(ESM)
by default (< 22.12.0) and AWS Lambda which intentionally disables it.

- Add scripts/bundle-superjson.mjs to bundle superjson with esbuild
- Update build script to bundle vendor files before tshy compilation
- Move superjson from dependencies to devDependencies
- Update imports to use vendored bundles

Fixes #2937
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2949">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
2026-01-30 09:15:02 +00:00
Iss 01208fde27 chore(docs): Add playwright workaround (#2973)
Adds a workaround to playwright to browser download failures based on
this GH issue: https://github.com/triggerdotdev/trigger.dev/issues/2440
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2973">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-30 08:43:23 +00:00
Eric Allam 5e049cde3a fix(run-engine): avoid NAPI string overflow in getExecutionSnapshotsSince by only fetching waitpoints for latest snapshot (#2972) 2026-01-29 19:03:54 +00:00
Matt Aitken 72c357125b Query enabled via feature flag (#2968)
- Renamed FeatureFlag functions to be singular where it makes sense.
- Added function to handle multiple feature flags
- canAccessQuery now checks the global feature flag and environment
variable as well
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2968">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-29 15:30:56 +00:00
DKP 0674d74bbb Added Trigger.dark theme to the docs (#2967)
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2967">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-29 13:59:27 +00:00
DKP 9e08712749 Add building with ai/skills pages and updated intro (#2962)
Closes #<issue>

##  Checklist

- [ ] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [ ] The PR title follows the convention.
- [ ] I ran and tested the code works

---

## Testing

_[Describe the steps you took to test this change]_

---

## Changelog

_[Short description of what has changed]_

---

## Screenshots

_[Screenshots]_

💯

<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2962">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-29 13:55:43 +00:00
Matt Aitken f53db6fd16 Query: time limits, performance improvements, styling (#2953)
Summary
- Query: add time limits, performance improvements, and styling updates

Changes
- Add ClickHouse output_text and error_text columns with indexes
- Automatically use _text columns for JSON based on query pattern;
support JSON column data prefixes
- Add idempotency key and scope columns
- Add enforcedWhereClause for tenant and time restrictions, instead of
the old tenant stuff.
- Implement basic time filter limiting and set default time period based
on plan; show message when results are clipped
- UX: resizable code area (including vertical splits), collapsible
sidebar, fix table/chart vertical sizing, max height for chart legend in
fullscreen
- Styling and UI tweaks: improved chart legend styling, more chart
colours, thinner line chart stroke, pricing callout color, improved
layout for callouts
- Features: generate and save AI titles
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2953">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-29 13:02:47 +00:00
Oskar Otwinowski c0b86efbd3 feat(webapp): Add MiddleTruncate component for long task names (#2946)
Closes #

##  Checklist

- [ ] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [ ] The PR title follows the convention.
- [ ] I ran and tested the code works

---

## Testing

Tested the MiddleTruncate component in the TasksDropdown by:
1. Verifying that long task names (e.g.,
"namespace:category:subcategory:task-name") are truncated in the middle
2. Confirming the full text appears in a tooltip on hover
3. Testing responsive behavior - truncation adjusts when the container
is resized
4. Verifying that short task names that fit within the container are
displayed in full without truncation

---

## Changelog

Added a new `MiddleTruncate` primitive component that intelligently
truncates text in the middle while preserving the beginning and end
portions. This is particularly useful for long hierarchical identifiers
like task slugs.

**Key features:**
- Truncates text in the middle with an ellipsis (…) when it exceeds
available width
- Shows full text in a tooltip on hover when truncated
- Responsive - recalculates truncation on container resize using
ResizeObserver
- Maintains minimum character visibility (4 chars minimum on each side
for readability)
- Integrated into TasksDropdown to handle long task names

**Changes:**
- Created new `MiddleTruncate.tsx` component with binary search
algorithm for optimal character distribution
- Updated TasksDropdown to use MiddleTruncate for task slug display
- Increased TasksDropdown popover width from 240px to 360px to provide
better space for truncated text

---

## Screenshots
💯


https://github.com/user-attachments/assets/a7a2191a-2e36-437e-ab3f-517fe7620b93


<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2946">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-29 12:51:58 +01:00
Mihai Popescu e29e1c86d9 Fix/tri 7032 logs page feedback (#2947)
##  Changes
### UI & UX
- Normalized log level display across table and detail view
- Fixed table header scroll behavior and sidebar positioning
- Improved loading state with taller segment and disabled resizing
- Added "no more logs" message with count
- Enhanced keyboard shortcuts
### Filtering & Search
- Streamlined filters: RunId and Task only (removed run filters)
- Side panel closes when filters change
- Fixed logs from previous search remaining in table
- Fixed table scroll position when changing filters
### Backend
- Added performance indexes on message and attributes
(`014_add_task_runs_v2_search_indexes.sql`)
- Added DEBUG level logging by default
- Removed internal logs from display
- Fixed ServiceValidationError forwarding to frontend
  - Removed v1 logs API support
2026-01-29 12:47:59 +02:00
James Ritchie 34203d6a6f Fix(webapp) prevent incidents url being called every frame (#2956) 2026-01-27 18:33:36 +00:00
James Ritchie d4e4fbd7fc fix(webapp): Truncate long branch names to prevent breaking the onboarding layout (#2954)
### Before
<img width="1736" height="964" alt="CleanShot 2026-01-21 at 20 11 08@2x"
src="https://github.com/user-attachments/assets/76c6ed42-d2a0-4212-aaad-6fb848025c85"
/>

### After
<img width="1776" height="1032" alt="CleanShot 2026-01-27 at 17 32
47@2x"
src="https://github.com/user-attachments/assets/030ba26e-6aad-4232-a9ff-f2fde9931f8c"
/>

<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2954">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-27 18:26:43 +00:00
James Ritchie 49de105862 Feat(webapp): collapsible side menu (#2939)
- Better separation between main feature pages and manage pages
- Toggle via keyboard shortcut Cmd/Ctrl + B or click collapse button
- Collapsed state persisted to database (survives page refresh)
- All menu items show tooltips when collapsed
- Smooth animations using Framer Motion and CSS transitions
- Impersonation-safe (preferences not modified when impersonating)


https://github.com/user-attachments/assets/35827922-b80a-418e-8341-eb22c9bb5ed4


<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2939">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-27 17:13:21 +00:00
DKP 5fb9cc36bc fix(security): upgrade CLI deps and add overrides (#2952)
- Upgrade @modelcontextprotocol/sdk 1.24.0 → 1.25.2 (CVE-2026-0621
ReDoS)
- Upgrade tar 7.4.3 → 7.5.4+ (CVE-2026-23950 race condition)
- Add pnpm overrides for transitive deps:
  - qs <6.14.0 → 6.14.0 (CVE-2025-15284 DoS)
  - systeminformation <5.27.14 → 5.27.14 (CVE-2025-68154 cmd injection)
  - lodash <4.17.23 → 4.17.23 (CVE-2025-13465 prototype pollution)

---------

Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2026-01-27 16:33:04 +00:00
nicktrn 70c8d6d14b fix(react-hooks): prevent onComplete from firing prematurely when stream disconnects (#2929)
## Summary

Fixes #2856 - The `onComplete` callback in `useRealtimeRun` was firing prematurely

## Root Cause

The callback was triggered when the long-poll stream ended, regardless
of whether the run had actually completed. Reverse proxies often close
idle connections, causing the stream to end prematurely. In this case it
was caused by fetch abort due to React strict mode.

## Fix

Changed the condition from checking if `run` exists to checking if
`run?.finishedAt` exists, ensuring `onComplete` only fires when the run
has reached a terminal state.

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <nicktrn@users.noreply.github.com>
2026-01-27 16:21:56 +00:00
Eric Allam eeab6bdeac fix(run-engine): fix queue cache memory leak and replace MemoryStore with LRU cache (#2945)
- Fix memory leak in RunAttemptSystem queue cache - was keying by runId
instead of queue identifier
- Replace `@unkey/cache` MemoryStore with new LRUMemoryStore for O(1)
operations and better memory bounds

## Problem

### Cache Key Bug
The queue cache in `#resolveTaskRunExecutionQueue` was keyed by `runId`,
creating one cache entry per run instead of per queue. With 1-2 hour
TTLs and 5000 entry soft cap, these accumulated causing memory growth.

### MemoryStore Performance
The `@unkey/cache` MemoryStore uses O(n) synchronous iteration for
eviction, blocking the event loop at high throughput.

## Solution

### Cache Key Fix
Changed cache key from `params.runId` to queue identifier:

```typescript
const cacheKey = params.lockedQueueId ?? `${params.runtimeEnvironmentId}:${params.queueName}`;
```

LRU Cache

Created LRUMemoryStore adapter using lru-cache package:
- O(1) get/set/delete operations
- Strict memory bounds (hard max vs soft cap)
- No event loop blocking

Test Results:

| Metric | Before Fix | After Fix |
|---|---|---|
| Queue cache entries (per 1000 runs) | ~1000 | 1 |
| Old space growth | 32.27 MB | 5.45 MB |
| Heap growth | 7.21 MB (3.9%) | 4.81 MB (2.6%) |


<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2945">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-26 22:23:23 +00:00
Matt Aitken 825219a2f4 Fix: requeue a run if the DB is unavailable during dequeuing (#2938)
In the DequeueSystem if the database is unavailable we were dequeuing
from Redis and then failing to requeue in the error catcher – this was
because the requeuing required DB access.

Now if in the `catch` we encounter a DB error we requeue directly using
Redis, putting it back in the queue.
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2938">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-25 19:23:04 +00:00
bharath kumar b143027d95 Fix/sdk stream root fallback (#2874) 2026-01-25 06:53:26 +00:00
Eric Allam 409388365e fix(fair-queue): ensure concurrency is released when a message reaches visibility timeout to prevent concurrency leaks (#2907)
## Summary

Fixes a concurrency leak in the batch queue where visibility timeout
reclaims do not release concurrency slots.

**The bug:** When a message visibility timeout expires (60s),
`reclaimTimedOut` puts the message back in the queue but does NOT
release the concurrency slot. The messageId stays in the concurrency set
(`engine:batch:concurrency:tenant:{envId}`), counting against the tenant
limit even though the message is no longer in-flight.

This causes:
1. Tenant appears at capacity when checking `SCARD >= limit`
2. New messages get released back to queue instead of being processed
3. Messages stuck in infinite loop, master queue grows indefinitely

**The fix:**
- Modified `reclaimTimedOut` to capture message data (including
tenantId) BEFORE releasing from in-flight
- Returns `ReclaimedMessageInfo[]` with messageId, queueId, tenantId,
and metadata
- `#reclaimTimedOutMessages` now iterates over reclaimed messages and
calls `concurrencyManager.release()` for each

## Test plan

- [x] Added test: `should return reclaimed message info with tenantId
for concurrency release`
- [x] Added test: `should return empty array when no messages have timed
out`
- [x] Added test: `should reclaim multiple timed-out messages and return
all their info`
- [x] Updated `raceConditions.test.ts` for new return type
- [x] All tests passing
- [ ] Monitor production after deploy for concurrency leak recurrence

refs TRI-7049
<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2907">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-24 13:06:35 +00:00
Gautam Singh fe5178f3e8 feat(webapp): add priority to task test and replay options (#2936)
Closes #2934

##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

_[Describe the steps you took to test this change]_

1. make sure there are no worker connected or the queue is paused.
2. run hello world tasks and assign priority
3. notice the priority value in task context.
4. try running a replay for task with priority
5. notice the context priority
---

## Changelog

_[Short description of what has changed]_
Added option to set priority on task test and replay dialog
---

## Screenshots

_[Screenshots]_
<img width="953" height="804" alt="image"
src="https://github.com/user-attachments/assets/d452b872-6c05-4a9e-a1e3-f6a283bb363d"
/>
<img width="958" height="886" alt="image"
src="https://github.com/user-attachments/assets/8f9f3096-da99-4d81-a9c5-2f3004b89ceb"
/>
<img width="1022" height="736" alt="image"
src="https://github.com/user-attachments/assets/233e01ac-a42b-4b4f-ac3e-e9b18638b971"
/>


💯

<!-- devin-review-badge-begin -->

---

<a
href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2936">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-01-24 09:10:14 +00:00
Iss a3f1eb2361 chore(docs): Admin requirements for creating worker groups (#2925)
Adds documentation for creating additional worker groups via the admin
API endpoint, including how to make users admin (new vs existing users),
and clarifies that ADMIN_EMAILS only applies on signup.
2026-01-24 09:00:50 +00:00
Iss ab4b50b95a chore(docs): Add clarifications for delay semantics and payload handling (#2928)
Adds documentation notes clarifying that:
- delayed runs execute on the current deployment version
- guidance for Date objects in payloads
- static IP availability
- version locking behavior for delayed runs
2026-01-24 08:59:55 +00:00
Eric Allam 1859fd0283 chore(docs): Improvements to the idempotency key docs for the user expored itempotency key changes (#2910) 2026-01-23 18:07:12 +00:00
github-actions[bot] 700fe91bec chore: release v4.3.3 (#2893)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and publish to npm
yourself or [setup this action to publish
automatically](https://github.com/changesets/action#with-publishing). If
you're not ready to do a release yet, that's fine, whenever you add more
changesets to main, this PR will be updated.


# Releases
## @trigger.dev/build@4.3.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.3`

## trigger.dev@4.3.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.3`
    -   `@trigger.dev/build@4.3.3`
    -   `@trigger.dev/schema-to-json@4.3.3`

## @trigger.dev/core@4.3.3

### Patch Changes

- Add support for AI SDK v6 (Vercel AI SDK)
([#2919](https://github.com/triggerdotdev/trigger.dev/pull/2919))

    -   Updated peer dependency to allow `ai@^6.0.0` alongside v4 and v5
- Updated internal code to handle async validation from AI SDK v6's
Schema type

- Expose user-provided idempotency key and scope in task context.
`ctx.run.idempotencyKey` now returns the original key passed to
`idempotencyKeys.create()` instead of the hash, and
`ctx.run.idempotencyKeyScope` shows the scope ("run", "attempt", or
"global").
([#2903](https://github.com/triggerdotdev/trigger.dev/pull/2903))

- Fix batch trigger failing with "ReadableStream is locked" error when
network failures occur mid-stream. Added safe stream cancellation that
gracefully handles locked streams during retry attempts.
([#2917](https://github.com/triggerdotdev/trigger.dev/pull/2917))

- Add a maxDepth to flatten/unflattenAttributes to prevent possible
issues ([#2890](https://github.com/triggerdotdev/trigger.dev/pull/2890))

## @trigger.dev/python@4.3.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/sdk@4.3.3`
    -   `@trigger.dev/core@4.3.3`
    -   `@trigger.dev/build@4.3.3`

## @trigger.dev/react-hooks@4.3.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.3`

## @trigger.dev/redis-worker@4.3.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.3`

## @trigger.dev/rsc@4.3.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.3`

## @trigger.dev/schema-to-json@4.3.3

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.3`

## @trigger.dev/sdk@4.3.3

### Patch Changes

- Add support for AI SDK v6 (Vercel AI SDK)
([#2919](https://github.com/triggerdotdev/trigger.dev/pull/2919))

    -   Updated peer dependency to allow `ai@^6.0.0` alongside v4 and v5
- Updated internal code to handle async validation from AI SDK v6's
Schema type

- Expose user-provided idempotency key and scope in task context.
`ctx.run.idempotencyKey` now returns the original key passed to
`idempotencyKeys.create()` instead of the hash, and
`ctx.run.idempotencyKeyScope` shows the scope ("run", "attempt", or
"global").
([#2903](https://github.com/triggerdotdev/trigger.dev/pull/2903))

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.3`

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-23 17:36:11 +00:00
Matt Aitken 6055c7d050 Recover runs that failed to dequeue (#2931)
There’s an edge case that means runs can end up in the
currentConcurrency set when they’re not in the correct state for
execution. This means they will be permanently stuck in queued.

Given an environmentId this will fix those runs.

This is a temporary fix while we permanently fix the issue.

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
2026-01-23 16:25:58 +00:00
Matt Aitken cf1c311dea Use the replica for API auth queries (#2932)
When we auth API keys we get the environment, project and org. This is a
very hot path so even though these queries are fast they contribute a
significant percentage of total load.

This moves them to use the read replica instead.
2026-01-23 16:23:51 +00:00
Eric Allam fb94e1741f fix(dashboard): display correct batch rate limit current token value (#2927) 2026-01-23 16:13:29 +00:00
Eric Allam 022f69c8c8 fix(v3): redesign of batch completion to prevent heavy row-level contention on the BatchTaskRun (#2930) 2026-01-23 15:52:52 +00:00
Eric Allam d893b26ed2 fix(engine): store costInCents and usageDurationMs on the TaskRun table via existing run engine updates (#2926)
Moving usage updates into the run engine to prevent inefficient &
additional incremental updates to the TaskRun table. Read/Modify/Write
pattern is safe inside of the run engine because of the run lock. We can
also now cap the usageDurationMs value from overflowing and causing an
error.

## Why?

This is preventing at least one update per TaskRun and instead updating
these values piggybacking on other updates.

## Aurora PostgreSQL Reader Consistency Notes

### TL;DR
Aurora readers share the same storage as the writer, but maintain
separate in-memory page caches. This means:
- **Storage is always consistent** - writes are synchronously committed
to shared storage
- **Page cache can lag** - typically <100ms, but can cause stale reads
if data is cached

### How It Works
1. Writer commits to shared storage (synchronous 4/6 quorum)
2. Writer sends cache invalidation messages to readers (asynchronous)
3. If reader has data in cache → returns cached (potentially stale)
value
4. If reader has cache miss → fetches from shared storage (always
current)

### Monitoring
```sql
SELECT server_id,
       CASE WHEN session_id = 'MASTER_SESSION_ID' THEN 'Writer' ELSE 'Reader' END AS role,
       replica_lag_in_msec
FROM aurora_replica_status();
```
2026-01-23 12:34:04 +00:00
Eric Allam 6f26acb581 fix(run-engine): use reader for pending version queries (#2924)
Move expensive findMany queries for PENDING_VERSION and
WAITING_FOR_DEPLOY
runs to read replicas to avoid blocking migrations on the primary
database.

Changes:
- Add readOnlyPrisma to SystemResources type
- Pass readOnlyPrisma to systems in RunEngine constructor  
- Update pendingVersionSystem to use readOnlyPrisma for findMany
- Update executeTasksWaitingForDeploy to use _replica for findMany
2026-01-21 15:37:21 +00:00
Eric Allam bd449f75dc fix(migrations): Add IF NOT EXISTS to 20260116154810_add_idempotency_key_options_to_task_run (#2923)
## Summary
- Adds `IF NOT EXISTS` to the migration that adds
`idempotencyKeyOptions` column to prevent errors if the column already
exists

## Migration Checksum Fix

If you've already applied the previous version of this migration, you'll
need to update the checksum in your `_prisma_migrations` table to match
the new migration file.

**Previous checksum:**
`f8876e274e3f7735312275eb24a9c4b40f512ac12a286b2de3add47f66df5b27`
**New checksum:**
`0620a914ddbaf01279576274432e51c41f41502cd4c8de38621625380750e397`

### Fix instructions

Run this SQL command against your database:

```sql
UPDATE "_prisma_migrations"
SET checksum = '0620a914ddbaf01279576274432e51c41f41502cd4c8de38621625380750e397'
WHERE migration_name = '20260116154810_add_idempotency_key_options_to_task_run';
```

This updates the stored checksum to match the modified migration file,
allowing future migrations to proceed without checksum mismatch errors.

## Test plan
- [x] Verified migration applies cleanly on fresh database
- [ ] Verified checksum update works on database with previous migration
applied

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-01-21 14:43:37 +00:00
Saadi Myftija cd2f536620 feat(docker): enable skipping db migrations on container startup (#2922)
Adds support for skipping Postgres migrations on container startup via
the new `SKIP_POSTGRES_MIGRATIONS` environment variable.

Set `SKIP_POSTGRES_MIGRATIONS=1` to skip migrations, matching the
existing behavior of `SKIP_CLICKHOUSE_MIGRATIONS`.
2026-01-21 13:34:00 +00:00
Matt Aitken 3056a51b82 Query improvements (#2905)
What changed
- Upgraded recharts to 2.15.2
- Added multiple chart types and components: big number, line, stacked,
bar (including zoomable & reference line), big dataset bar, and usage
graph
- Implemented custom legend with animated values, tooltip showing x-axis
data, and hover/highlight behaviors for stacks and legend
- Added loading, no-data, and invalid chart states plus loading spinners
and improved loading animations/layout
- Storybook integration: initial charts setup, separate chart files,
alphabetized menu, chart state toggles, and story updates
- Interaction & UX improvements: zooming (drag/select), crosshair
pointer, show/select dates while zooming, prevent text selection on
drag, hide mouse wheel zoom, capped legend items, axis/legend styling
tweaks, better spacing, and min-height for charts
- Data & state handling: moved date data to route for unified zooming,
moved chartState to main Chart component, moved hard-coded/mock data out
of components, and set chart data when zooming to start/end dates
- Performance & animation: turned off/reduced chart animations, sped up
animated numbers, removed hover transitions for bars
- New UI primitives and layout: Card component, small card updates, SVG
icons, improved segmented control and popover variants, table
improvements (resizable columns, filtering, sorting, scrolling fixes)
- Various fixes and polish: tooltip style fixes, legend value updates,
hover/leave state resets, bar width fixes for small datasets,
type/import fixes, and numerous small style/typo tweaks

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2026-01-21 13:07:07 +00:00
Eric Allam 23ec5ff8fa feat(sdk): add support for AI SDK v6 (#2919)
## Summary
- Add support for Vercel AI SDK v6 as a peer dependency
- Update internal code to handle async validation from AI SDK v6's
Schema type

Closes #2918

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
2026-01-20 22:31:41 +00:00
Eric Allam 31e4753122 fix(sdk): handle locked ReadableStream when retrying batch trigger (#2917)
When fetch crashes mid-stream during batch item upload (e.g., connection
reset, timeout), the request stream may remain locked by fetch's
internal reader. Attempting to cancel a locked stream throws 'Invalid
state: ReadableStream is locked', causing the batch operation to fail.

Added safeStreamCancel() helper that gracefully handles locked streams
by catching and ignoring the locked error. The stream will be cleaned up
by garbage collection when fetch eventually releases the reader.

Fixes customer issue where batchTrigger failed with ReadableStream
locked error during network instability.
2026-01-20 15:55:23 +00:00
Eric Allam 8bc6b99285 fix(batch-queue): allow batch queue consumers to run independently from the run engine worker (#2916)
new environment variable `BATCH_QUEUE_WORKER_ENABLED` now can be used
independently from `RUN_ENGINE_WORKER_ENABLED`
2026-01-20 15:26:55 +00:00
Eric Allam 87167524cc fix(api): prevent null idempotency keys in responses, only undefined accepted (#2912) 2026-01-20 14:06:37 +00:00
Eric Allam 36168b3eb6 feat(sdk): expose user-provided idempotency key and scope in task context (#2903)
## Summary
- Store the original user-provided idempotency key and scope alongside
the hash
- Expose `ctx.run.idempotencyKey` as the user-provided key (not the
hash)
- Add `ctx.run.idempotencyKeyScope` to show the scope ("run", "attempt",
or "global")

<img width="539" height="450" alt="CleanShot 2026-01-19 at 11 40 46"
src="https://github.com/user-attachments/assets/b6f42991-697e-4314-a164-aef77b8fd25c"
/>

  ## Problem
Idempotency keys were hashed (SHA-256) before storage, making debugging
difficult since users couldn't see the value they originally set or
search for runs by idempotency key.

  ## Solution
Attach metadata to the `String` object returned by
`idempotencyKeys.create()` using a Symbol, extract it in the SDK before
the API call, and store it in the database alongside the hash.

  ```typescript
const key = await idempotencyKeys.create("my-key", { scope: "global" });
  await childTask.triggerAndWait(payload, { idempotencyKey: key });

  // In child task:
  ctx.run.idempotencyKey      // "my-key" (previously showed the hash)
  ctx.run.idempotencyKeyScope // "global"
```

  Test plan

  - Trigger task with idempotencyKeys.create() using different scopes (run, attempt, global)
  - Verify ctx.run.idempotencyKey returns user-provided key
  - Verify ctx.run.idempotencyKeyScope returns correct scope
  - Verify PostgreSQL stores idempotencyKeyOptions JSON
  - Verify ClickHouse receives idempotency_key_user and idempotency_key_scope via replication

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2026-01-20 11:23:07 +00:00
mintlify[bot] c859be9c53 Document new Limits page in dashboard (#2908)
⚒️ Publish Worker (v4) / build (supervisor) (push) Has been cancelled
Added documentation for the new Limits page feature that allows users to
view their current limits, quotas, and rate limit usage in real-time
from the dashboard. The page displays rate limit token availability,
quota usage, and plan features for organizations.

## Files changed
- `docs/limits.mdx` - Added introductory paragraph about the new Limits
page in the dashboard

Generated from [feat(webapp): New limits
page](https://github.com/triggerdotdev/trigger.dev/pull/2885) @samejr

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
Co-authored-by: James Ritchie <james@trigger.dev>
2026-01-19 11:30:02 +00:00
Saadi Myftija b7f7d88623 feat(supervisor): add per-machine-preset resource request ratios (#2906)
Adds support to configure CPU/memory request ratios per machine preset.
Falls back to the global request ratio configs if no specific override
is specified.

Runs across different machine presets have different usage patters, so
this enables use to manage the available capacity better.
2026-01-19 12:26:05 +01:00
Eric Allam 72594a46ee fix(dashboard): properly cleanup trace pubsub redis clients to redis/memory/elu leaks in the dashboard (#2901) 2026-01-16 15:20:30 +00:00
Matt Aitken 5504e7f8cc Fix schedule limit counting (#2899)
Fix schedule counting
- Inactive TaskSchedule not counted
- Inactive environments (archived preview branches) not counted

Clarified per-project limits descriptions.
2026-01-16 13:56:49 +00:00
James Ritchie 7a7c4b1a82 feat(webapp): New limits page (#2885)
<img width="1381" height="1362" alt="CleanShot 2026-01-14 at 13 41 02"
src="https://github.com/user-attachments/assets/0537dccf-60c7-4ab7-a0e4-3164eac1e97d"
/>

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2026-01-15 18:03:06 +00:00
Dan 733894bb4f Impersonation log (#2896)
Closes #<issue>

##  Checklist

- [ ] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [ ] The PR title follows the convention.
- [ ] I ran and tested the code works

---

## Testing

_[Describe the steps you took to test this change]_

---

## Changelog

_[Short description of what has changed]_

---

## Screenshots

_[Screenshots]_

💯

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2026-01-15 16:54:45 +00:00
Matt Aitken b696bbb1df Add TaskScheduleInstance projectId (#2897)
Summary
- Add nullable projectId field to TaskScheduleInstance.
- Create an index for TaskScheduleInstance.environmentId (added only if
it doesn’t exist, handled concurrently).
- Ensure TaskScheduleInstance.projectId is set everywhere in the
codebase.

Backfilling projectIds, once this is live

```sql
UPDATE "TaskScheduleInstance" tsi
SET "projectId" = ts."projectId"
FROM "TaskSchedule" ts
WHERE tsi."taskScheduleId" = ts."id";
```
2026-01-15 15:06:52 +00:00
Eric Allam aa69b9027d fix(repo): undo node.js supervisor upgrades and use the multiplatform node.js digest in Dockerfile (#2895) 2026-01-15 11:49:37 +00:00
Mihai Popescu 0b0df071bf logs-page-fixes (#2889)
* Removed EVENT_REPOSITORY_CLICKHOUSE_ROLLOUT_PERCENT
* Added hasLogsPageAccess featureFlag for logs page
* Replaced attributes with attributes_text for logs to reduce memory
usage and improve query performance
* Added support for event_v1 for logs, now depending on the settings the
logs are fetched either from `task_events_v1` or `task_events_v2`
* Show an error in the interface in cast the repository store is
`postgres`
2026-01-15 11:07:01 +00:00
Eric Allam 936bddf198 fix: upgrade Node.js to 20.20.0 to address async_hooks DoS vulnerability (#2890)
## Summary

- Upgrades Node.js from 20.19.0 to 20.20.0 (and 22.12.0 to 22.22.0 for
supervisor) to address the async_hooks stack overflow DoS vulnerability
- Adds `maxDepth` parameter (default 128) to `flattenAttributes` and
`unflattenAttributes` to prevent stack overflow on maliciously deep
nested structures

## Details

The vulnerability (patched in Node.js 20.20.0, 22.22.0, 24.13.0, 25.3.0)
causes unrecoverable crashes (exit code 7) when stack overflow occurs
during async_hooks callbacks. Since the webapp uses `AsyncLocalStorage`,
it was theoretically vulnerable.

### Changes

**Node.js version updates:**
- `docker/Dockerfile`: 20.11.1 → 20.20.0
- `apps/supervisor/Containerfile`: 22-alpine → 22.22.0-alpine
- `.nvmrc`: 20.19.0 → 20.20.0
- `apps/supervisor/.nvmrc`: 22.12.0 → 22.22.0
- `references/prisma-7/.nvmrc`: 20.19.0 → 20.20.0
- All GitHub workflows: 20.19.0 → 20.20.0

**Defense in depth:**
- Added `maxDepth` parameter to `flattenAttributes()` and
`unflattenAttributes()` in `packages/core` to prevent stack overflow on
deeply nested user input

## Test plan

- [x] All existing `flattenAttributes` tests pass (50 tests)
- [x] New tests for depth limiting added
- [x] Verify Docker builds work with new base images
2026-01-15 10:47:44 +00:00
Eric Allam b1e21cf03b feat(api): add admin endpoint for updating org feature flags (#2891) 2026-01-15 10:41:34 +00:00
Eric Allam c3f2d07708 chore(repo): remove claude code review (keep claude bot) (#2887) 2026-01-15 09:32:30 +00:00
SHIVA REDDY VANJA 4dc504d9d0 docs: fix waitpoint token completion request body field (#2888)
Fixed documentation examples to use correct 'data' field instead of
'output' for the waitpoint token completion endpoint.

The API schema expects 'data' in the request body, but all code examples
(curl, Python, Ruby, Go) incorrectly showed 'output', causing waitpoints
to complete with empty/undefined output when users followed the docs.

Fixes #2872

Closes #<issue>

##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

_[Describe the steps you took to test this change]_
This is simple doc fix
---

## Changelog

_[Short description of what has changed]_
Documentation example for the specific api route had a wrong field,
fixed that to have correct field

---

## Screenshots

_[Screenshots]_
<img width="780" height="252" alt="Screenshot 2026-01-14 at 10 49 50 PM"
src="https://github.com/user-attachments/assets/50a03f2c-edfb-4bd4-bb72-a0fd79e77216"
/>
The above image shows the correct request format, but docs previously
had incorrect payload.
<img width="723" height="307" alt="Screenshot 2026-01-14 at 11 24 01 PM"
src="https://github.com/user-attachments/assets/b9096225-3f7c-4511-b8c2-e8144c896900"
/>
This is the exact wrong field in docs, that was fixed
https://trigger.dev/docs/wait-for-token#from-another-language


💯

Co-authored-by: appdevelopers9a <appdeveloper@s9alabs.com>
2026-01-14 19:33:39 +00:00
Eric Allam a5339a1bac fix(dashboard): remove span ID to original span ID cache and use a different approach to link to the cached runs (#2886) 2026-01-14 14:36:29 +00:00
Matt Aitken 5b07bd11a0 chore: FeatureFlag add createdAt and updatedAt (#2880)
It’s useful to know when they were modified for debugging and auditing.

For existing rows createdAt and updatedAt are set to now() during the
migration, to avoid a nullable column.
2026-01-14 14:28:06 +00:00
nicktrn 260fb7cd70 fix(helm): support secrets.existingSecret for core secrets (#2860)
When users set `secrets.enabled=false` to use an external secret via
`secrets.existingSecret`, the environment variables `SESSION_SECRET`,
`MAGIC_LINK_SECRET`, `ENCRYPTION_KEY`, and `MANAGED_WORKER_SECRET` were
not being populated from the secret.

Fixes #2859

Also adds automatic helm prereleases for PRs

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <nicktrn@users.noreply.github.com>
2026-01-14 10:44:08 +00:00
Copilot 9934627c0b Revert "Set EVENT_REPOSITORY_DEFAULT_STORE default to clickhouse_v2" (#2881)
Reverts commit 495a2531f0.

Restores `EVENT_REPOSITORY_DEFAULT_STORE` default from `"clickhouse_v2"`
back to `"postgres"`.

##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

Single-line env schema default change; no runtime testing required.

---

## Changelog

- Reverted `EVENT_REPOSITORY_DEFAULT_STORE` default value from
`"clickhouse_v2"` to `"postgres"` in `apps/webapp/app/env.server.ts`

---

## Screenshots

N/A - configuration change only

💯

<!-- START COPILOT CODING AGENT SUFFIX -->



<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> Can you revert the latest commit
495a2531f0 and create a PR for the revert


</details>



<!-- START COPILOT CODING AGENT TIPS -->
---

 Let Copilot coding agent [set things up for
you](https://github.com/triggerdotdev/trigger.dev/issues/new?title=+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ericallam <534+ericallam@users.noreply.github.com>
2026-01-14 10:38:08 +00:00
Matt Aitken 495a2531f0 Set EVENT_REPOSITORY_DEFAULT_STORE default to clickhouse_v2 (#2879)
Change EVENT_REPOSITORY_DEFAULT_STORE default from "postgres" to
"clickhouse_v2" so new deployments favor the ClickHouse v2 event store
by default. This updates runtime behavior to use the newer store
implementation unless explicitly overridden.
2026-01-13 18:06:00 +00:00
Matt Aitken 1bca378000 Query fixes (#2876)
Don’t allow aliased columns to be queried – it was actually safe but
confusing. We call `created_at` -> `triggered_at` but we still allowed
created_at which was confusing.

Now we have nice errors if you try select columns that aren’t
selectable.

Also removed a ClickHouse setting `allow_experimental_object_type` which
worked fine locally but stopped all queries working on ClickHouse Cloud
🤦‍♂️
2026-01-13 17:43:25 +00:00
nicktrn b042b0b2f9 fix(webapp): cancel button in API key regeneration modal (#2878)
The Cancel button was missing an onClick handler to close the modal
dialog. This caused confusing behavior where clicking Cancel would not
dismiss the dialog. Also added type="button" to prevent form submission
since the button is inside a form.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-13 18:26:13 +01:00
Dan 3be55db8f8 Add smart spreadsheet docs (#2877) 2026-01-13 17:21:00 +00:00
Eric Allam bb253400a2 perf(runs-replication): Improve the CPU efficiency and throughput of the runs replication to clickhouse (#2866)
## Summary

Optimizes the runs replication service for better CPU efficiency and
throughput when inserting task runs into ClickHouse.

### Key Changes

- **Switch to compact array format** - Uses
`JSONCompactEachRowWithNames` instead of `JSONEachRow` for ClickHouse
inserts, reducing JSON serialization overhead
- **Type-safe tuple arrays** - Introduces `TaskRunInsertArray` and
`PayloadInsertArray` tuple types with compile-time column order
validation
- **Pre-sorted batch inserts** - Sorts inserts by primary key before
flushing for better ClickHouse insert performance
- **Programmatic index generation** - `TASK_RUN_INDEX` and
`PAYLOAD_INDEX` are generated from column arrays to prevent manual
synchronization errors

### Files Changed

- `runsReplicationService.server.ts` - Core optimization to use compact
array inserts
- `@internal/clickhouse` - Added `insertCompactRaw` method and tuple
types
- `taskRuns.ts` - Column definitions, index constants, and insert
functions

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 12:18:30 +00:00
Mihai Popescu c8686b5f1c feat: tri-6738 Create aggregated logs page (#2862)
Closes #<issue>

##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing
- Verified log detail view displays correctly with message, metadata,
and attributes
- Tested search highlighting functionality in log messages (escapes
special regex characters)
- Confirmed tabs (Details/Run) switch properly with keyboard shortcuts
(d/r)
  - Verified run information loads via async fetcher in Run tab
  - Tested close button and Escape key for dismissing the panel
- Verified log details display correct information: level badges, kind
badges, timestamps, trace IDs, span IDs
  - Confirmed links to parent spans and run pages work correctly
- Tested with various log levels (ERROR, WARN, INFO, DEBUG, TRACE) and
kinds (SPAN, SPAN_EVENT, LOG_*)
- Verified admin-only fields display correctly when user has admin
access
- Tested data loading states and error states (log not found, run not
found)


---

## Changelog

Created new Logs page. 
The information shown is gathered from the spans from each run.
The feature supports all run filters with two new filters for level and
logs text search.


---

## Screenshots

<img width="2059" height="1196" alt="Logs page preview"
src="https://github.com/user-attachments/assets/70b667b4-98cc-4728-855a-2766dd5c1aa5"
/>

💯

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2026-01-13 11:21:13 +00:00
Iss dfb46d8847 chore(docs): add WASM external configuration documentation (#2871)
Adds a WASM block to the External section documenting that WASM packages
must be added to the `external` array in `trigger.config.ts`.
2026-01-13 11:12:54 +00:00
Matt Aitken 9942518e49 TRQL/Query improvements (#2870)
Summary
- Improve query experience and safety across ClickHouse and TSQL.

Changes
- Display JSON columns when in non-pretty mode (no longer show [Object
Object]).
- Sanitize ClickHouse errors originating from TSQL.
- Remove tenant details from errors.
- Add AI-assisted error-fixing for queries.
- Improve code quality and readability.
- Provide autocomplete support for enum values.
- Enforce limits on ClickHouse queries (10s query limit).
- Add org-level and global concurrency limits.
- Warn and train AI to avoid SELECT *; when used, only return core
columns and show info.
- If AI suggests no time range, default to past 7 days.
- Format the default query for readability.
- Add an admin-only EXPLAIN button.
- Prevent impersonation queries from being saved to history.
2026-01-13 11:12:15 +00:00
Saadi Myftija a3c387697e feat(supervisor): add node affinity rules for large machine worker pool scheduling (#2869)
⚒️ Publish Worker (v4) / build (supervisor) (push) Has been cancelled
**Background**
Runs with `large-1x` or `large-2x` machine presets are disproportionally
affected by scheduling delays during peak times. This is in part caused
by the fact that the worker pool is shared for all runs, meaning large
runs compete with smaller runs for available capacity. Because large
runs require significantly more CPU and memory, they are harder for the
scheduler to bin-pack onto existing nodes, often requiring a node with a
significant amount of free resources or waiting for a new node to spin
up entirely. This effect is amplified during peak times when nodes are
already densely packed with smaller workloads, leaving insufficient
contiguous resources for large runs. Also, large runs make up a small
percentage of the total runs.

**Changes**

This PR adds Kubernetes node affinity settings to separate large and
standard machine workloads across node pools.

- Controlled via `KUBERNETES_LARGE_MACHINE_POOL_LABEL` env var (disabled
when not set)
- Large machine presets (large-*) get a soft preference to schedule on
the large pool, with fallback to standard nodes
- Non-large machines are excluded from the large pool via required
anti-affinity
- This ensures the large machine pool is reserved for large workloads
while allowing large workloads to spill over to standard nodes if needed
2026-01-13 10:54:47 +01:00
James Ritchie 7a9490893c fix(webapp): Fix for missing table rows divider lines in safari (#2873) 2026-01-12 21:14:11 +00:00
James Ritchie 768206c91b feat(dashboard): Upgrade to the dateTime filter UI (#2864)
UI/UX improvement to the date/time picker:

- You can now choose a custom duration
- Adds a new DateTimePicker.tsx component, using a new shadcn
Calendar.tsx component
- Clear UI separation between the 2 actions, choosing a duration or
choosing date range
- Adds new quick select options for picking a date range quickly


https://github.com/user-attachments/assets/6b59b49d-2a56-4354-ad72-d8426437e56e

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
2026-01-12 13:01:17 +00:00
Eric Allam 2c30c2defb chore(claude): add CLAUDE.md and claude skill for writing trigger.dev tasks + add 4.3.0 rule set (#2867)
- Add CLAUDE.md providing Claude Code guidance and documenting the
Claude Code skill
- Add trigger-dev-tasks skill to assist writing Trigger.dev tasks
- Add SDK rules version 4.3.0 including batch trigger v2 and debouncing
features
2026-01-12 11:01:06 +00:00
Matt Aitken 839d5e8eba Allow query access when impersonating (#2863)
Co-authored-by: Mihai Popescu <mihai.popescu.dev@gmail.com>
2026-01-09 14:57:09 +00:00
Eric Allam 42dfb87ebb chore(ci): pre-pull test container images to prevent dockerhub rate limiting when running tests (#2861) 2026-01-09 12:15:53 +00:00
Matt Aitken 49df40cb11 TRQL and the Query page (#2843)
TRQL (pronounced Treacle like the delicious British dark sweet syrup) is
the TRiggerQueryLanguage. It allows users to safely write queries on
their data. The queries are safely turned into ClickHouse queries which
are tenant-safe and not SQL injectable.


https://github.com/user-attachments/assets/bbfca473-b3fc-4150-8fe6-79e8840a2d29

This started out as a translation of HogQL by PostHog from Python to
TypeScript.

Features
- Tenant safe queries.
- Many underlying ClickHouse features including functions and
aggregations.
- Virtual columns, which are exposed to users as real columns but are
actually expressions.
- Transformations of data types and where clauses.
- Simple JSON path querying.
- Limits on execution time.
- Reporting of query statistics.

## Query page

There’s a new Query page (currently behind a feature flag) where you can
write TRQL queries and execute them against your environment, project or
organization.

Features
- Executing TRQL queries
- Syntax highlighting and errors
- Autocomplete
- AI generation/editing of queries
- Help and examples
- Table with auto-inferred data types from the table schema
- Table cell renderers for our special types like Run ids, environments,
machines, tasks, queues, etc.
- Copy/export as CSV/JSON
- Line and bar graphs with grouping and stacking
- History of queries
2026-01-09 11:39:36 +00:00
Eric Allam cf0aa9b3ca core(claude): correctly setup repo and deps for claude code agent (#2858) 2026-01-09 10:27:23 +00:00
Eric Allam a8024afd0a chore(claude): add some allowed tools to the claude github workflow agent (#2857) 2026-01-09 10:17:29 +00:00
Eric Allam 57ba2528b2 feat(runs): use metrics instead of spans in the Runs Replication service (#2851) 2026-01-08 15:56:44 +00:00
Eric Allam 7d29f5aac9 fix(webapp): use useFetcher for env var edits to preserve scroll/toggle state (#2847)
Replaces `redirectDocument` with `useFetcher` for editing environment
variables. This allows background form submission without full page
reload, which preserves:

- Scroll position in the env vars list
- "Reveal values" toggle state
- Search filter state

Fixes #2845

Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
2026-01-08 12:51:07 +00:00
Eric Allam 36b0762100 feat(metrics): add observable gauge for batch queue worker length (#2848) 2026-01-08 12:50:46 +00:00
Eric Allam f5b2ccb494 chore(docs): add docs for handling batch trigger errors (#2838) 2026-01-08 11:33:43 +00:00
github-actions[bot] f73138fe6c chore: release v4.3.2 (#2811)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 4s
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and publish to npm
yourself or [setup this action to publish
automatically](https://github.com/changesets/action#with-publishing). If
you're not ready to do a release yet, that's fine, whenever you add more
changesets to main, this PR will be updated.


# Releases
## @trigger.dev/build@4.3.2

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.2`

## trigger.dev@4.3.2

### Patch Changes

- fix(cli): update command should preserve existing package.json order
([#2810](https://github.com/triggerdotdev/trigger.dev/pull/2810))
-   Updated dependencies:
    -   `@trigger.dev/build@4.3.2`
    -   `@trigger.dev/core@4.3.2`
    -   `@trigger.dev/schema-to-json@4.3.2`

## @trigger.dev/python@4.3.2

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/sdk@4.3.2`
    -   `@trigger.dev/build@4.3.2`
    -   `@trigger.dev/core@4.3.2`

## @trigger.dev/react-hooks@4.3.2

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.2`

## @trigger.dev/redis-worker@4.3.2

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.2`

## @trigger.dev/rsc@4.3.2

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.2`

## @trigger.dev/schema-to-json@4.3.2

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.2`

## @trigger.dev/sdk@4.3.2

### Patch Changes

- Improve batch trigger error messages, especially when rate limited
([#2837](https://github.com/triggerdotdev/trigger.dev/pull/2837))
-   Updated dependencies:
    -   `@trigger.dev/core@4.3.2`

## @trigger.dev/core@4.3.2

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-08 11:26:59 +00:00
Eric Allam 7c2e78c9de fix(batch): more high cardinality metric attribute fixes (#2846) 2026-01-08 10:07:49 +00:00
mintlify[bot] 6dfbe1d762 Document spike alerts feature (#2844)
Updated the billing alerts documentation to reflect the new spike alerts
feature added in PR #2829. The documentation now explains both standard
alerts (75%, 90%, 100%, 200%, 500%) and spike alerts (10x, 20x, 50x,
100x) that help catch runaway usage from bugs or errors.

## Files changed
- `docs/how-to-reduce-your-spend.mdx` - Added section explaining the two
types of billing alerts

Generated from [Chore(webapp): Adds additional billing
alerts](https://github.com/triggerdotdev/trigger.dev/pull/2829) @samejr

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
2026-01-07 16:40:04 +00:00
James Ritchie 3f19b98f9f Fix(webapp): Dynamically load spline on 404 on page (#2834)
Remove the spline dependency and load it dynamically on the 404 page.

Uses a web component with a workaround for React.
2026-01-07 15:50:49 +00:00
Eric Allam 09460ab37d feat: add event loop block notifications and env flag (#2842)
Add colored console warnings when the event loop is blocked and wire
a feature flag to enable/disable notifications- Introduce
notifyEventLoopBlocked() in eventLoopMonitor.server.ts to
  log a colored warning with blocked and async type.
- Call notifyEventLoopBlocked() when an event-loop stall is detected.
- Add EVENT_LOOP_MONITOR_NOTIFY_ENABLED to env schema with a default of
  "0" so notifications are off by default.
- Will notify when over the `EVENT_LOOP_MONITOR_THRESHOLD_MS` env var

This makes it easier to spot long event-loop stalls during development
or when notifications are explicitly enabled.

<img width="840" height="132" alt="CleanShot 2026-01-07 at 15 03 24@2x"
src="https://github.com/user-attachments/assets/be20fa6a-be2b-46a1-aa89-d0913ed8b5b3"
/>
2026-01-07 15:04:50 +00:00
Eric Allam 062766e974 fix(batch): optimize processing batch trigger v2 (#2841)
This PR fixes some issues with the new BatchQueue by implementing the
full two-phase dequeue process in the FairQueue, and moving the
responsibility of consuming the worker queue to the BatchQueue and
independently enabling it via the `BATCH_QUEUE_WORKER_QUEUE_ENABLED` env
var. We've also introduced the `BATCH_QUEUE_SHARD_COUNT` env var to
control the count of master queue shards in the FairQueue. We can also
control how many queues are considered in each iteration of the master
queue consumer via the `BATCH_QUEUE_MASTER_QUEUE_LIMIT` env var.

This PR will also now skip trying to dequeue from tenants that are at
concurrency capacity, which should lead to fewer issues with low
concurrency tenants blocking higher concurrency tenants from processing.
2026-01-07 15:00:09 +00:00
James Ritchie c68eb2d951 fix(webapp): concurrency limits modal cancels and resets limit on enter (#2804)
The Override concurrency limit modal has 2 type="submit" buttons. The
first one in the DOM was firing when the "enter" key is hit which
canceled and reset the limit instead which is a bad UX.

### The fix
This fix adds a hidden button above in the DOM order which mirrors the
Update Override button. Having a double submit button is rare in our
modals so feels safe to add this to the specific modal that needs it.

### Alternative solution
Switching the order of the buttons in the main FormButton component,
then using `flex-row-reverse` to flip them back in CSS works, but it
reverses the tab order. Adding a `tabIndex` to fix that issue didn't
seem to work reliably.
2026-01-07 14:14:23 +00:00
James Ritchie 583d299891 chore(webapp): Concurrency page UI improvements (#2825)
### UI Improvements to the Concurrency page: 

- Truncates long branch names and includes a tooltip
- The Tables have a new variant if you don't want the rows to highlight
on hover
- Small fix to pluralize some words in the purchase modal
- Fix to prevent tooltip buttons being `type=submit`
- Updates the /limits docs page to include purchasing more concurrency
- Adds a clear banner when you have a positive balance of unallocated
concurrency



https://github.com/user-attachments/assets/54d927c3-84e3-4d55-8f42-726098f4daf0
2026-01-07 14:13:36 +00:00
James Ritchie 17338050b1 Chore(webapp): Adds additional billing alerts (#2829)
- Adds 4 additional alert thresholds to ensure customers are emailed if
they have runaway usage.
- Separated these into a new section called "Spike alerts" with a
tooltip so it's clear what they are.
- Tooltip message is: "Catch runaway usage from bugs or errors. We
recommend keeping these enabled as a safety net."
- A billing service PR now returns all orgs to populate the email list,
rather than oldest 5.
- Adds `defaultChecked` logic to honour existing orgs who have
configured alerts in the DB. New orgs get all alerts checked on by
default.

<img width="1316" height="1560" alt="CleanShot 2026-01-05 at 09 43
56@2x"
src="https://github.com/user-attachments/assets/ce749407-2b7f-4864-9c09-9333c5ac495a"
/>
2026-01-07 14:10:10 +00:00
James Ritchie c7a238c664 Chore(webapp): Queues page UI improvements (#2826)
Very small UI improvement to increase the spacing between the right hand
table columns. Also a tooltip wording improvement.
2026-01-07 14:07:50 +00:00
Eric Allam 8ba7526d51 fix(batch): rate limiting by token bucket no longer incorrectly goes negative (#2837)
Also improves the BatchTriggerError when a result of getting rate
limited.
2026-01-07 14:02:19 +00:00
nicktrn 47bed15255 docs: fix self-hosting section in deploy docs (#2836)
Fixes #2835

There were still some flags in here we removed, deploying is a lot
simpler now for self-hosters.

Also updates the github actions guide.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-06 20:20:20 +00:00
Eric Allam 752ad32293 Add Claude Code GitHub Workflow (#2839) 2026-01-06 19:26:31 +00:00
James Ritchie db0df17a6a chore(webapp): Run navigation UI improvements (#2802)
**Improvements to the run ID copy button and run navigation buttons for
consistency**

- Adds some x-padding and layout adjustment to the copy ID button.
<img width="664" height="114" alt="CleanShot 2025-12-19 at 16 05 21@2x"
src="https://github.com/user-attachments/assets/ebc8e0de-011b-419c-bdcc-eb4157553d1c"
/>

- New custom navigation icons that work better at tiny sizes
<img width="330" height="196" alt="CleanShot 2025-12-19 at 16 06 38@2x"
src="https://github.com/user-attachments/assets/bfd8d6b8-8a65-4eac-9ce1-d70acf0ad265"
/>

Some other small improvements/fixes:
- Fixes a browser html error where there was a <button> inside a
<button>
- Updates the shortcut description to match the tooltip text for
consistency
- Made the hover states more consistent
- The shortcut bar at the bottom snaps to the list sooner because there
are more items now
2026-01-06 18:20:54 +00:00
Eric Allam edf5b142fc fix(fair-queue): Prevent unbounded memory growth from metrics cardinality explosion (#2819) 2025-12-25 08:51:40 +00:00
Eric Allam 4c3dfac223 fix(fair-queue): prevent unbounded cooloff states growth (#2818) 2025-12-24 16:33:38 +00:00
nicktrn 7ccbbdb368 docs: tidy up sync env vars note blocks (#2817) 2025-12-24 13:02:26 +00:00
Eric Allam 71279a7b12 fix(fair-queue): prevent unbounded memory growth by cleaning up queue descriptor and cooloff state cache (#2816) 2025-12-24 10:40:32 +00:00
Eric Allam 2eba36c086 chore(redis-worker): add otel spans to fair queue processing pipeline (#2815) 2025-12-24 00:37:24 +00:00
Eric Allam 29827e96f2 fix(batch): add batch queue back into master queue after visibility timeout (#2814) 2025-12-24 00:25:46 +00:00
Dan d416f340ad Added example projects link (#2812)
Closes #<issue>

##  Checklist

- [ ] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [ ] The PR title follows the convention.
- [ ] I ran and tested the code works

---

## Testing

_[Describe the steps you took to test this change]_

---

## Changelog

_[Short description of what has changed]_

---

## Screenshots

_[Screenshots]_

💯
2025-12-23 18:37:19 +00:00
nicktrn 7a54a843e2 fix(cli): update command should preserve existing package.json order (#2810)
This fixes a regression introduced in #2778 - stable sort is required
for deterministic builds, but we can safely preserve order for the user
package.json during package updates
2025-12-23 12:52:06 +00:00
nicktrn 52e9baede5 fix(webapp): don't rate limit deployment finalization (#2809)
turns out we also had v2 and v3 routes
2025-12-23 09:22:00 +00:00
Eric Allam deb80890fe chore(otel): add spans to the batch queue processing pipeline (#2808) 2025-12-23 08:40:33 +00:00
Eric Allam d82089686c fix(batch): extract the queue name out of an already nested queue option (#2807) 2025-12-22 21:40:14 +00:00
Oskar Otwinowski acc10e847c chore(docs): add more cost saving tips (#2806)
Co-authored-by: Eric Allam <eallam@icloud.com>
2025-12-22 15:36:54 +00:00
Eric Allam f1a83cffc4 chore(docs): debounce options (#2797) 2025-12-22 15:35:51 +00:00
Eric Allam 61fee91830 chore(docs): upgrade for new batch trigger limits and functionality (#2787) 2025-12-22 15:35:43 +00:00
github-actions[bot] caa40ce925 chore: release v4.3.1 (#2788)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and publish to npm
yourself or [setup this action to publish
automatically](https://github.com/changesets/action#with-publishing). If
you're not ready to do a release yet, that's fine, whenever you add more
changesets to main, this PR will be updated.


# Releases
## @trigger.dev/build@4.3.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.1`

## trigger.dev@4.3.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.1`
    -   `@trigger.dev/build@4.3.1`
    -   `@trigger.dev/schema-to-json@4.3.1`

## @trigger.dev/core@4.3.1

### Patch Changes

- Added support for idempotency reset
([#2777](https://github.com/triggerdotdev/trigger.dev/pull/2777))

## @trigger.dev/python@4.3.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/sdk@4.3.1`
    -   `@trigger.dev/core@4.3.1`
    -   `@trigger.dev/build@4.3.1`

## @trigger.dev/react-hooks@4.3.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.1`

## @trigger.dev/redis-worker@4.3.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.1`

## @trigger.dev/rsc@4.3.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.1`

## @trigger.dev/schema-to-json@4.3.1

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.1`

## @trigger.dev/sdk@4.3.1

### Patch Changes

- feat: Support for new batch trigger system
([#2779](https://github.com/triggerdotdev/trigger.dev/pull/2779))
- feat(sdk): Support debouncing runs when triggering with new debounce
options
([#2794](https://github.com/triggerdotdev/trigger.dev/pull/2794))
- Added support for idempotency reset
([#2777](https://github.com/triggerdotdev/trigger.dev/pull/2777))
-   Updated dependencies:
    -   `@trigger.dev/core@4.3.1`

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-12-22 15:29:18 +00:00
Dan ba9b0e17c1 Added Claude Agent SDK guide and examples (#2803) 2025-12-19 17:10:32 +00:00
Oskar Otwinowski 469808cf09 fix(webapp): Make spans fluid again while task is executing (#2801)
Closes #<issue>

##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

Tested on executing tasks and on moving between tasks

---

## Changelog

Small UI fix for spans on the task runs page

---

## Screenshots



https://github.com/user-attachments/assets/72095b03-c74f-4472-afde-9c63e6e7c224



💯
2025-12-19 15:45:54 +01:00
Mihai Popescu 7574c69c2d feat(webapp): Add support for resetting idempotency keys (#2777)
Add support for resetting idempotency keys both from ui and sdk

##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing
- Created a new run with a idempotency idempotencyKey.
- Started a new run with the same task and got redirected to the first
run.
- Deleted the key from the UI on the run details
- Started a new run with the same task  and it created a new one
- Did the above steps using the SDK


---

## Changelog

- Add new action route for resetting idempotency keys via UI
- Add reset button in Idempotency section of run detail view
- Added API and SDK for resetting imdepotency
- Updated docs page for this feature


---

## Screenshots

_[Screenshots]_
<img width="438" height="363" alt="Screenshot 2025-12-11 at 11 56 37"
src="https://github.com/user-attachments/assets/30b8ef5e-8aac-4d04-b57a-9bf30d085dcb"
/>
2025-12-19 11:55:04 +00:00
Eric Allam 06cbe6e3ca chore(docs): upgrade sentry guide to use new global init and global hooks (#2799) 2025-12-19 00:00:02 +00:00
Eric Allam 3875bb292a feat(engine): run debounce system (#2794)
Adds support for **debounced task runs** - when triggering a task with a
debounce key, subsequent triggers with the same key will reschedule the
existing delayed run instead of creating new runs. This continues until
no new triggers occur within the delay window.

## Usage

```typescript
await myTask.trigger({ userId: "123" }, {
  debounce: {
    key: "user-123-update",
    delay: "5s",
    mode: "leading", // default
  }
});
```

- **key**: Scoped to the task identifier
- **delay**: How long to wait before executing (supports duration
strings like `"5s"`, `"1m"`)
- **mode**: Either `"leading"` or `"trailing"`. Leading debounce will
use the payload and options from the first run created with the debounce
key. Trailing will use payload and options from the last run.

### "trailing" mode overrides

When using `mode: "trailing"` with debounce, the following options are
updated from the **last** trigger:

- **`payload`** - The task input data
- **`metadata`** - Run metadata
- **`tags`** - Run tags (replaces existing tags)
- **`maxAttempts`** - Maximum retry attempts
- **`maxDuration`** - Maximum compute time
- **`machine`**  - Machine preset (cpu/memory)

## Behavior

- **First run wins**: The first trigger creates the run, subsequent
triggers push its execution time later
- **Idempotency keys take precedence**: If both are specified,
idempotency is checked first
- **Max duration**: Configurable via `DEBOUNCE_MAX_DURATION_MS` env var
(default: 10 minutes)

Works with `triggerAndWait` - parent runs correctly block on the
debounced run.
2025-12-18 16:04:43 +00:00
Saadi Myftija ff80742ab7 fix(ci): use workflow_dispatch instead of repository_dispatch for publish.yml (#2791)
Mixed up the trigger in #2790
2025-12-16 16:53:22 +01:00
Saadi Myftija 11366e658c chore(ci): add manual trigger to the image publishing workflow (#2790)
Useful to retry failures manually.
2025-12-16 16:34:57 +01:00
Eric Allam e751f8832e fix(app): incorrectly duplicated env vars for new batch trigger system (#2789) 2025-12-16 15:27:13 +00:00
Eric Allam a999d9ea3f feat(engine): Batch trigger reloaded (#2779)
New batch trigger system with larger payloads, streaming ingestion,
larger batch sizes, and a fair processing system.

This PR introduces a new `FairQueue` abstraction inspired by our own
`RunQueue` that enables multi-tenant fair queueing with concurrency
limits. The new `BatchQueue` is built on top of the `FairQueue`, and
handles processing Batch triggers in a fair manner with per-environment
concurrency limits defined per-org. Additionally, there is a global
concurrency limit to prevent the BatchQueue system from creating too
many runs too quickly, which can cause downstream issues.

For this new BatchQueue system we have a completely new batch trigger
creation and ingestion system. Previously this was a single endpoint
with a single JSON body that defined details about the batch as well as
all the items in the batch.

We're introducing a two-phase batch trigger ingestion system. In the
first phase, the BatchTaskRun record is created (and possibly rate
limited). The second phase is another endpoint that accepts an NDJSON
body with each line being a single item/run with payload and options.

At ingestion time all items are added to a queue, in order, and then
processed by the BatchQueue system.

## New batch trigger rate limits

This PR implements a new batch trigger specific rate limit, configured
on the `Organization.batchRateLimitConfig` column, and defaults using
these environment variables:

- `BATCH_RATE_LIMIT_REFILL_RATE` defaults to 10
- `BATCH_RATE_LIMIT_REFILL_INTERVAL` the duration interval, defaults to
`"10s"`
- `BATCH_RATE_LIMIT_MAX` defaults to 1200

This rate limiter is scoped to the environment ID and controls how many
runs can be submitted via batch triggers per interval. The SDK handles
the retrying side.

## Batch queue concurrency limits

The new column `Organization.batchQueueConcurrencyConfig` now defines an
org specific `processingConcurrency` value, with a backup of the env var
`BATCH_CONCURRENCY_LIMIT_DEFAULT` which defaults to 10. This controls
how many batch queue items are processed concurrently per environment.

There is also a global rate limit for the batch queue set via the
`BATCH_QUEUE_GLOBAL_RATE_LIMIT` which defaults to being disabled. If
set, the entire batch queue system won't process more than
`BATCH_QUEUE_GLOBAL_RATE_LIMIT` items per second. This allows
controlling the maximum number of runs created per second via batch
triggers.

## Batch trigger settings

- `STREAMING_BATCH_MAX_ITEMS` controls the maximum number of items in a
single batch
- `STREAMING_BATCH_ITEM_MAXIMUM_SIZE` controls the maximum size of each
item in a batch
- `BATCH_CONCURRENCY_DEFAULT_CONCURRENCY` controls the default
environment concurrency
- `BATCH_QUEUE_DRR_QUANTUM` how many credits each environment gets each
round for the DRR scheduler
- `BATCH_QUEUE_MAX_DEFICIT` the maximum deficit for the DRR scheduler
- `BATCH_QUEUE_CONSUMER_COUNT` how many queue consumers to run
- `BATCH_QUEUE_CONSUMER_INTERVAL_MS` how frequently they poll for items
in the queue

### Configuration Recommendations by Use Case

**High-throughput priority (fairness acceptable at 0.98+):**

```env
BATCH_QUEUE_DRR_QUANTUM=25
BATCH_QUEUE_MAX_DEFICIT=100
BATCH_QUEUE_CONSUMER_COUNT=10
BATCH_QUEUE_CONSUMER_INTERVAL_MS=50
BATCH_CONCURRENCY_DEFAULT_CONCURRENCY=25
```

**Strict fairness priority (throughput can be lower):**

```env
BATCH_QUEUE_DRR_QUANTUM=5
BATCH_QUEUE_MAX_DEFICIT=25
BATCH_QUEUE_CONSUMER_COUNT=3
BATCH_QUEUE_CONSUMER_INTERVAL_MS=100
BATCH_CONCURRENCY_DEFAULT_CONCURRENCY=5
```
2025-12-16 14:32:49 +00:00
Oskar Otwinowski 28a66ac021 fix(ui): respect rootOnlyDefault, disable adjacent run navigation in inspector views (#2781)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
## Changelog

- Add disableAdjacentRows prop to TaskRunsTable component to control
table state encoding
- Pass rootOnlyDefault prop from loader to TaskRunsTable for proper
state management
- Disable adjacent run navigation in schedule, waitpoint, and other
inspector views
- Preserve adjacent run navigation on main runs list page with rootOnly
filter support
2025-12-12 12:16:29 +00:00
github-actions[bot] 7d34817473 chore: release v4.3.0 (#2770)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and publish to npm
yourself or [setup this action to publish
automatically](https://github.com/changesets/action#with-publishing). If
you're not ready to do a release yet, that's fine, whenever you add more
changesets to main, this PR will be updated.


# Releases
## trigger.dev@4.3.0

### Minor Changes

- feat(cli): deterministic image builds for deployments
([#2778](https://github.com/triggerdotdev/trigger.dev/pull/2778))
- feat(cli): enable zstd compression for deployment images
([#2773](https://github.com/triggerdotdev/trigger.dev/pull/2773))

### Patch Changes

- The new `triggeredVia` field is now populated in deployments via the
CLI. ([#2767](https://github.com/triggerdotdev/trigger.dev/pull/2767))
- fix(dev): stop max listeners exceeded warning messages when running
more than 10 runs concurrently
([#2771](https://github.com/triggerdotdev/trigger.dev/pull/2771))
- Upgrade @modelcontextprotocol/sdk to 1.24.3
([#2768](https://github.com/triggerdotdev/trigger.dev/pull/2768))
-   Updated dependencies:
    -   `@trigger.dev/core@4.3.0`
    -   `@trigger.dev/build@4.3.0`
    -   `@trigger.dev/schema-to-json@4.3.0`

## @trigger.dev/core@4.3.0

### Minor Changes

- feat(cli): deterministic image builds for deployments
([#2778](https://github.com/triggerdotdev/trigger.dev/pull/2778))

### Patch Changes

- The new `triggeredVia` field is now populated in deployments via the
CLI. ([#2767](https://github.com/triggerdotdev/trigger.dev/pull/2767))

## @trigger.dev/build@4.3.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.0`

## @trigger.dev/python@4.3.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.0`
    -   `@trigger.dev/build@4.3.0`
    -   `@trigger.dev/sdk@4.3.0`

## @trigger.dev/react-hooks@4.3.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.0`

## @trigger.dev/redis-worker@4.3.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.0`

## @trigger.dev/rsc@4.3.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.0`

## @trigger.dev/schema-to-json@4.3.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.0`

## @trigger.dev/sdk@4.3.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.3.0`

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-12-12 13:11:56 +01:00
Saadi Myftija 6d6ed471d1 feat(cli): deterministic image builds for deployments (#2778)
⚒️ Publish Worker (v4) / build (supervisor) (push) Has been cancelled
This PR makes our image builds deterministic and reproducible by
ensuring that identical source code always produces the same image
layers and image digest. This means that deployments where nothing has
changed will no longer invalidate the image cache in our worker cluster
nodes, thus avoid making the cold starts for runs worse.

**Context**
New deployments currently increase the cold start times for runs, as
they generate a new image which needs to be pulled in the worker cluster
where runs are executed. It happens also when the source code for the
deployment has not changed due to non-deterministic steps in our build
system. This addresses the latter issue by making builds reproducible.

**Main changes**
- Avoided baking `TRIGGER_DEPLOYMENT_ID` and
`TRIGGER_DEPLOYMENT_VERSION` in the image, we now pass these via the
supervisor instead.
- Used `json-stable-stringify` for consistent key ordering in the files
we generate for the build, e.g., `package.json`, `build.json`,
`index.json`.
- Removed `metafile.json` from the image contents as it is not actually
used in the container. This is only relevant for the `analyze` command.
- Added `SOURCE_DATE_EPOCH=0` and `rewrite-timestamp=true` to Docker
builds to normalize file timestamps.
- Removed some `timings` and `outputHashes` from build outputs and
manifests.

The builds are now reproducible for both native build server and Depot
paths. This should also lead to better image layer cache reuse in
general.
2025-12-12 09:48:04 +01:00
Oskar Otwinowski 7f7f993587 feat(webapp): improve adjacent runs navigation and timeline performance (#2776)
- Add replace prop to LinkButton to use history replacement for adjacent
run navigation
- Preserve span and tab params when navigating between adjacent runs
- Disable animations for completed spans in timeline to improve
performance
- Include spanId in runs list navigation for better context preservation
- Direct link to task test page when filtering by single task with no
runs
- Fix minor styling issue with run friendlyId display padding
2025-12-11 17:26:15 +00:00
Oskar Otwinowski d28707826c feat(webapp): add GitHub onboarding flow to empty Tasks and Deployments pages (#2775)
##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

Set up the local github application, and tested its connection with
trigger.dev

Checked:
- Change is backwards compatible
- Actions/ux are uniform across the pages (empty Tasks, Deployments,
project settings)
- Connecting GH, Connecting Repo, disconnecting Repo, modifying settings

---

## Changelog

- Create new resource route for GitHub settings management with loader
and actions
- Add GitHubSettingsPresenter to fetch connected repos and installations
- Implement GitHubSettingsPanel component for reusable GitHub
configuration UI
- Refactor project settings page to use shared GitHubSettingsPanel
component
- Integrate GitHub connection flow into empty state onboarding for Tasks
and Deployments
- Add support for GitHub repo connection, disconnection, and branch
tracking settings
- Include redirect URL support for seamless navigation after GitHub
actions
- Remove duplicate GitHub connection code from project settings route

---

## Screenshots


https://github.com/user-attachments/assets/8fc24699-640b-4f9e-afd8-b26edc945218

🐐

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2025-12-10 17:03:16 +00:00
Max Strübing 8b00198f99 docs(kubernetes): use v4 helm chart instead of beta (#2671) 2025-12-10 14:52:32 +00:00
nicktrn 74e9246bfa feat(cli): enable zstd compression for deployment images (#2773)
This will speed up ice cold starts (*) for two reasons:
- better compression ratio
- faster decompression

This is a minor release because zstd compression will now be enabled by
default for all deployments.

(*) ice cold starts happen when deploy images are not cached on the
worker node yet. These cold start durations are highly dependent on
image size and as it turns out, also the type of compression used.
2025-12-10 14:49:44 +00:00
Mihai Popescu 07a31d3732 fix(webapp) : fixed Cmd+Left Arrow was intercepted by the TreeView component (#2772)
Fixed the issue where Cmd+Left Arrow was being intercepted by the
TreeView component on task runs screen.

Solution:
Added a check in the getTreeProps keyboard handler to detect when
metaKey (Cmd on macOS) is pressed with Left Arrow. When detected, the
handler returns early without preventing the default browser behavior,
allowing Chrome's native back navigation to work.


Closes #<issue>

##  Checklist

- [ x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [ x] The PR title follows the convention.
- [ x] I ran and tested the code works

---

## Testing

Went to the task details page and confirmed that Cmd + Left Arrow will
navigate back

---

## Changelog

Modified TreeView.tsx to check for e.metaKey before handling Left Arrow
key events
When Cmd+Left is pressed, the event is no longer prevented, allowing
browser default behavior
---

Co-authored-by: Mihai Popescu <mihaipopescu@Mihais-MacBook-Pro.local>
2025-12-10 12:05:16 +00:00
Saadi Myftija da111e220f fix(api): whitelist deployment endpoints from the general API rate limits (#2774)
Deployments are affected by general API rate limits, this is just a
quick fix by whitelisting the deployment related endpoints. In a follow
up PR we'll add a separate rate limiter for this group of endpoints.
2025-12-10 12:03:56 +01:00
Oskar Otwinowski 2c3cb4a43a feat(webapp): UX improvements for TaskRun page and TaskRun table (#2760)
##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

Manual testing of the task run pages

---

## Changelog

- Add previous/next run navigation buttons to run detail page header
- Support [ and ] keyboard shortcuts to jump between adjacent runs
- Preserve runs table state (filters, pagination) when navigating
- Preload adjacent page runs at boundaries for seamless navigation
- Add actions prop to PageTitle component
- Document shortcut in keyboard shortcuts panel

- Store current filter state from runs table as `tableState` search
param when navigating to individual run pages
- Restore filters when navigating back from run detail view to runs list
- Update `v3RunPath` and `v3RunSpanPath` helpers to accept optional
searchParams
- Use `useOptimisticLocation` to capture current search params in
TaskRunsTable
- Parse `tableState` param in run detail route and pass filters to back
button

- This improves UX by remembering filter selections (task, status, date
range, etc.) when users click into a run and then navigate back to the
runs list

- Add new text-below variant that shows "Click to copy" tooltip on hover
and "Copied" on click. Also add controlled open/onOpenChange props to
SimpleTooltip for managing tooltip visibility.

---

## Screenshots


https://github.com/user-attachments/assets/5067bbe0-1bcd-4e75-80a7-f56dabd5ed69
2025-12-09 13:10:11 +00:00
Saadi Myftija b71bf89444 chore(releases): minor improvements to the release workflow (#2764)
Changes in this PR:
- Arbitrary refs are now allowed when triggering the release workflow
manually (ref must be on the main branch).
- Release summary is now displayed in the GH job output; makes for a
nicer experience when approving the release workflow.
2025-12-09 11:29:48 +01:00
Eric Allam 28c0c78257 fix(api): triggering a batch on a v4 project via the v3 SDK no longer results in errors (#2752)
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Updates `BatchTriggerV3Service` to send `batch.id` (not `friendlyId`)
as `batchId` to `TriggerTaskService.call`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
68bf8df4a29bdcac5bfb2806bc417541f69ffd6e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
2025-12-09 09:54:39 +00:00
Eric Allam c021d1db63 fix(dev): stop max listeners exceeded warning messages when running more than 10 runs concurrently (#2771)
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Centralizes SIGTERM handling in `DevSupervisor` and removes per-run
SIGTERM listeners in `DevRunController` to avoid
MaxListenersExceededWarning under high concurrency.
> 
> - **Dev runtime**:
> - **SIGTERM handling**: Add centralized handler in
`packages/cli-v3/src/dev/devSupervisor.ts` to gracefully stop all run
controllers; unregisters on `shutdown()`.
> - **Cleanup**: Remove per-controller `SIGTERM` listener and handler
from `packages/cli-v3/src/entryPoints/dev-run-controller.ts` to reduce
event listeners and warnings.
> - **Changeset**: Add patch note in
`.changeset/fuzzy-ghosts-admire.md`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5ad2f5341829cebf6fd37a3c616a2db5e4ad936a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
2025-12-09 09:54:28 +00:00
Eric Allam f62cdfe00e feat(dashboard): login with google and "last used" indicator (#2746)
<img width="568" height="513" alt="CleanShot 2025-12-05 at 14 27 16"
src="https://github.com/user-attachments/assets/1f44d8b9-8791-4b44-96d5-4a0960a1ab36"
/>

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds Google OAuth login and a cookie-based “last used” indicator on
the login page, with supporting backend, routes, and schema updates.
> 
> - **Auth/Backend**:
> - **Google OAuth**: Integrates `remix-auth-google` via new
`addGoogleStrategy` and enables when `AUTH_GOOGLE_CLIENT_ID/SECRET` are
set (`services/googleAuth.server.ts`, `services/auth.server.ts`).
> - **User handling**: Implements `findOrCreateGoogleUser` with
linking/upsert logic and conflict logging (`models/user.server.ts`).
> - **MFA + session**: Google/GitHub/Magic callbacks now set session,
handle MFA, and set a "last-auth-method" cookie
(`routes/auth.google*.tsx`, `routes/auth.github.callback.tsx`,
`routes/magic.tsx`, `services/lastAuthMethod.server.ts`).
> - **GitHub strategy**: Safer email check
(`services/gitHubAuth.server.ts`).
> - **Routes/UI**:
> - **Login page**: Adds "Continue with Google" button and animated
"Last used" badge based on cookie; keeps GitHub/Email options
(`routes/login._index/route.tsx`).
> - **Redirect safety**: Sanitize redirect paths and persist redirect
via cookies in auth actions (`routes/auth.github.ts`,
`routes/auth.google.ts`).
>   - **Assets**: Adds `GoogleLogo` SVG.
>   - **Avatar**: Set `referrerPolicy="no-referrer"` on profile image.
> - **Config/Schema**:
> - **Env**: Adds `AUTH_GOOGLE_CLIENT_ID`/`AUTH_GOOGLE_CLIENT_SECRET`
(`env.server.ts`).
> - **DB**: Extends `AuthenticationMethod` enum with `GOOGLE` (Prisma
schema + migration).
> - **Dependencies**:
>   - Adds `remix-auth-google` in `package.json`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9f84f974bd6f21f1699c4f69a6aa91616842d1b1. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2025-12-09 09:51:42 +00:00
nicktrn 66c6da7114 security: dependabot alert triage (#2768)
- Upgrade @modelcontextprotocol/sdk to 1.24.3
- Override jws to 3.2.3
2025-12-08 21:02:13 +00:00
Saadi Myftija 7fba9e9f6b feat(deployments): add build server meta and trigger source info (#2767)
This PR applies a small change to the deployments table to keep track
of:
- where the deployment was triggered from
- build server metadata, if the build server was involved
2025-12-08 16:29:26 +00:00
Saadi Myftija cf63fc9cd2 chore: update version requirement hint in build settings (#2757) 2025-12-08 09:27:28 +01:00
Saadi Myftija d1c3bfb9c9 fix(deployments): ecr repo exists check (#2762)
We recently upgraded the ECR sdk version. Our ECR repo exists check
relies on the type of the error thrown and the new ECR sdk version seems
to have broken that behavior. This PR adds a workaround to the issue.
2025-12-05 19:16:28 +01:00
Saadi Myftija d8f5853457 fix(releases): use contents: write permission in the release workflow (#2761)
Needed to push tags
2025-12-05 17:22:24 +01:00
Saadi Myftija a52566d9cc feat(releases): add a manual trigger for the package release workflow (#2759)
The manual trigger is currently enabled only for the prerelease job.
This PR adds it for the normal release flow too, as it is useful to
retrigger failed release workflows.
2025-12-05 17:00:02 +01:00
Saadi Myftija 07a1d04d52 fix(releases): add missing npm upgrade step (#2758)
Accidentally removed this in a previous PR.
2025-12-05 16:41:45 +01:00
github-actions[bot] 185f4ecaf9 chore: release v4.2.0 (#2713)
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 19s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and publish to npm
yourself or [setup this action to publish
automatically](https://github.com/changesets/action#with-publishing). If
you're not ready to do a release yet, that's fine, whenever you add more
changesets to main, this PR will be updated.


# Releases
## trigger.dev@4.2.0

### Minor Changes

- feat(cli): upgrade bun deployments to v1.3.3
([#2756](https://github.com/triggerdotdev/trigger.dev/pull/2756))

### Patch Changes

- fix(otel): exported logs and spans will now have matching trace IDs
([#2724](https://github.com/triggerdotdev/trigger.dev/pull/2724))
- The `--force-local-build` flag is now renamed to just `--local-build`
([#2702](https://github.com/triggerdotdev/trigger.dev/pull/2702))
- fix(cli): header will always print the correct profile
([#2728](https://github.com/triggerdotdev/trigger.dev/pull/2728))
- feat: add ability to set custom resource properties through
trigger.config.ts or via the OTEL_RESOURCE_ATTRIBUTES env var
([#2704](https://github.com/triggerdotdev/trigger.dev/pull/2704))
- feat(cli): implements content-addressable store for the dev CLI build
outputs, reducing disk usage
([#2725](https://github.com/triggerdotdev/trigger.dev/pull/2725))
- Added support for native build server builds in the deploy command
(`--native-build-server`)
([#2702](https://github.com/triggerdotdev/trigger.dev/pull/2702))
-   Updated dependencies:
    -   `@trigger.dev/build@4.2.0`
    -   `@trigger.dev/core@4.2.0`
    -   `@trigger.dev/schema-to-json@4.2.0`

## @trigger.dev/build@4.2.0

### Patch Changes

- syncVercelEnvVars to skip API and read env vars directly from
env.process for Vercel build environments. New syncNeonEnvVars build
extension for syncing environment variablesfrom Neon database projects
to Trigger.dev. The extension automatically detects branches and builds
appropriate PostgreSQL connection strings for non-production, non-dev
environments (staging, preview).
([#2729](https://github.com/triggerdotdev/trigger.dev/pull/2729))
-   Updated dependencies:
    -   `@trigger.dev/core@4.2.0`

## @trigger.dev/core@4.2.0

### Patch Changes

- fix: prevent ERR_IPC_CHANNEL_CLOSED errors from causing an unhandled
exception on TaskRunProcess
([#2743](https://github.com/triggerdotdev/trigger.dev/pull/2743))
- Added support for native build server builds in the deploy command
(`--native-build-server`)
([#2702](https://github.com/triggerdotdev/trigger.dev/pull/2702))

## @trigger.dev/python@4.2.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/build@4.2.0`
    -   `@trigger.dev/sdk@4.2.0`
    -   `@trigger.dev/core@4.2.0`

## @trigger.dev/react-hooks@4.2.0

### Patch Changes

- fix: prevent infinite useEffect when passing an array of tags to
useRealtimeRunsWithTag
([#2705](https://github.com/triggerdotdev/trigger.dev/pull/2705))
-   Updated dependencies:
    -   `@trigger.dev/core@4.2.0`

## @trigger.dev/redis-worker@4.2.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.2.0`

## @trigger.dev/rsc@4.2.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.2.0`

## @trigger.dev/schema-to-json@4.2.0

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.2.0`

## @trigger.dev/sdk@4.2.0

### Patch Changes

- fix(sdk): Re-export schemaTask types to prevent the TypeScript error
TS2742: The inferred type of 'task' cannot be named without a reference
to '@trigger.dev/core/v3'. This is likely not portable.
([#2735](https://github.com/triggerdotdev/trigger.dev/pull/2735))
- feat: add ability to set custom resource properties through
trigger.config.ts or via the OTEL_RESOURCE_ATTRIBUTES env var
([#2704](https://github.com/triggerdotdev/trigger.dev/pull/2704))
-   Updated dependencies:
    -   `@trigger.dev/core@4.2.0`

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-12-05 16:27:21 +01:00
nicktrn 0d764d4c46 feat(cli): upgrade bun deployments to v1.3.3 (#2756)
New deployments with `runtime: "bun"` will now use Bun v1.3.3

Link to Bun release: https://bun.com/blog/bun-v1.3.3
2025-12-05 13:31:27 +00:00
Saadi Myftija beb52b9800 chore(releases): adjust gh workflow title (#2755)
Just a tiny workflow label change
2025-12-05 13:33:35 +01:00
Saadi Myftija 3401a1d0a9 feat(releases): require approval for package releases (#2753)
**Background**
Currently the changeset PR creation and the publishing is handled by the
same workflow. This is not ideal:
- The build steps are executed on every run of the pipeline, even though
they're only needed for the publish case.
- The PR creation workflow does not need permissions to publish to npm,
only the release path needs them.
- Adding an approval step is painful as we'd need to also approve each
changeset PR creation workflow run.

**Changes in this PR**
- Separated the changeset PR creation into its own workflow and minimum
permission set.
- Added a GH environment with an approval step for the package
publishing workflow (also for prereleases).
- New publish workflow runs will not cancel in-progress runs; helps
avoid partial failures in publishing.

These changes also enable hardening the npm OIDC setup by tying it to a
GH environment that requires approval.
2025-12-05 13:25:25 +01:00
nicktrn 3f982ed366 docs: update email regex examples (#2749)
The previous examples lacked start and end anchors
2025-12-04 17:58:25 +00:00
Saadi Myftija 4dc956470d fix(deployments): misc fixes for the native build server deployment flow (#2748)
Improved a couple of error messages.

Also fixed an issue with the s2 token caching.
2025-12-04 17:01:47 +01:00
Oskar Otwinowski 7fddadcce9 chore: Improve Vercel/Neon syncEnvVars build extensions docs (#2747)
chore: Improve Vercel/Neon `syncEnvVars` build extensions docs
2025-12-04 16:34:57 +01:00
Oskar 6e038d4d1e chore: Improve Vercel/Neon syncEnvVars extensions docs 2025-12-04 16:32:15 +01:00
Oskar Otwinowski 05b53967ea feat(build): Add NeonDB branch resolution for Vercel preview environments (#2729)
Vercel's NeonDB integration renders database connection environment
variables at runtime, which means Trigger.dev cannot directly sync these
values during the build process. This change adds support for fetching
branch-specific NeonDB connection strings via the Neon API.

feat(build): Add syncNeonEnvVars extension and improve Vercel env var
syncing

Add a new `syncNeonEnvVars` build extension for syncing environment
variables
from Neon database projects to Trigger.dev. The extension automatically
detects
branches and builds appropriate PostgreSQL connection strings for
non-production
environments (staging, dev, preview).

Features of `syncNeonEnvVars`:
- Fetches branch-specific database credentials from Neon API
- Generates all standard Postgres connection strings (DATABASE_URL,
POSTGRES_URL,
  POSTGRES_PRISMA_URL, etc.) with both pooled and unpooled variants
- Supports custom database name, role name, and env var prefix options
- Skips automatically in Vercel environments (Neon's Vercel integration
handles this)
- Skips for production environments (designed for preview/staging/dev
branches)

Improvements to `syncVercelEnvVars`:
- When running in a Vercel build environment (detected via VERCEL env
var),
values are now read from process.env instead of the Vercel API response
- This ensures the build uses the actual runtime values Vercel provides
- Removed embedded Neon-specific logic (now handled by separate
extension)
- Simplified and cleaned up the extension code

Documentation updates for both extensions with usage examples and
configuration
options.

Closes #2714

##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

---

## Testing

Set up Vercel + Trigger.dev envs, used Vercel's chat-bot-ai template.
2025-12-04 16:26:35 +01:00
Oskar 702f3b4bca chore: Improve changeset message 2025-12-04 16:26:24 +01:00
nicktrn 8fcd93001d chore: insert missing spaces in changeset 2025-12-04 13:42:32 +00:00
Eric Allam b01b8740cc fix(engine): prevent overriding a queue concurrency limit resuming a paused queue (#2745) 2025-12-04 13:33:12 +00:00
Oskar 357aa99309 Add changeset 2025-12-04 14:12:42 +01:00
Oskar 7cbf82a4ae fix: PR feedback, doc improvements for neon/vercel syncEnvVars 2025-12-04 14:07:31 +01:00
Eric Allam e7fec4097f fix(dev): CLI now properly cleans up the store dir on dev CLI exit (#2744) 2025-12-04 13:13:01 +01:00
Eric Allam d279988e38 fix(workers): prevent ERR_IPC_CHANNEL_CLOSED errors from causing an unhandled exception on TaskRunProcess (#2743) 2025-12-04 12:02:30 +00:00
Saadi Myftija 748ae658f7 fix(releases): use npm 11.x for OIDC support in the release workflow (#2742)
Support for OIDC requires npm v11.5.1 or newer.
2025-12-04 12:21:21 +01:00
Oskar Otwinowski 249878ed92 feat(webapp): link to task-specific test page from filtered runs table (#2741)
When viewing runs filtered to a single task, the "Create a test run" and
"Run a test" buttons now navigate directly to the task-specific test
page instead of the generic test page.

This improves UX by pre-populating the test form with the filtered task,
saving users from having to manually select it again.


##  Checklist

- [x] I have followed every step in the [contributing
guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [x] The PR title follows the convention.
- [x] I ran and tested the code works

## Screenshots

<img width="1706" height="1392" alt="image"
src="https://github.com/user-attachments/assets/d8b5d445-73b5-426c-83a4-90ac2a95b955"
/>
2025-12-04 10:56:24 +00:00
Eric Allam 117b1d5a53 chore(dependabot): upgrade next.js for CVE-2025-66478 in d3-chat example project (#2740) 2025-12-04 10:30:37 +00:00
Eric Allam 04173a93b9 fix(replication): detect misconfigered run replication publication and output helpful error messages (#2736)
Add validation for logical replication publication configuration. Helps
diagnose an issue where runs are no longer replicated to clickhouse
because of a configuration issue with the replication publication.

## Problem

The `LogicalReplicationClient` only checked if a publication existed,
not if it was correctly configured. This caused a silent failure where:

- Replication would start successfully
- Transaction boundaries (begin/commit) were received
- **But no actual data changes were replicated**

This happened when a publication existed but:
1. Had no tables associated with it
2. Was missing required actions (e.g., `delete`)

## Solution

Added `#validatePublicationConfiguration()` method that validates:
-  Publication includes the expected table
-  Publication has all required actions configured

When validation fails, error messages include the exact SQL command to
fix the issue:

**Missing table:**
```
Publication 'task_runs_to_clickhouse_v1_publication' exists but has NO TABLES configured. 
Expected table: "public.TaskRun". 
Run: ALTER PUBLICATION task_runs_to_clickhouse_v1_publication ADD TABLE "TaskRun";
```

**Missing actions:**
```
Publication 'task_runs_to_clickhouse_v1_publication' is missing required actions. 
Expected: [insert, update, delete], Current: [insert, update], Missing: [delete]. 
Run: ALTER PUBLICATION task_runs_to_clickhouse_v1_publication SET (publish = 'insert, update, delete');
```

This prevents silent data loss and makes debugging configuration issues
much easier.
2025-12-04 10:29:13 +00:00
Saadi Myftija da4c753b68 fix(releases): add missing GH token in prerelease workflow (#2739)
The `changeset version` command needs the GH token too.
2025-12-04 11:27:11 +01:00
Eric Allam 6ae3b69745 chore(cursor): add deslop command (#2722) 2025-12-04 10:24:09 +00:00
Saadi Myftija 652d95c7eb feat(releases): add a prerelease workflow (#2737)
Adds a manual trigger to the `release.yml` workflow for publishing
prerelease versions. Needs to be in the same workflow file due to a NPM
limitation on how OIDC claims are checked.

Currently there is a validation step on the ref for the prerelease: it
must be merged to the main branch. We can revisit this in the future in
case we find it too limiting.
2025-12-04 10:17:05 +01:00
Saadi Myftija 341e27d213 chore(deployments): lazily update ECR repo cache settings (#2734)
To avoid doing a migration for the ECR repo cache settings, we lazily do
it on the next deployment for that project. Failures to update the repo
settings are just logged and will not cause the deployment to fail.
2025-12-03 17:15:59 +01:00
Eric Allam 9821d02af7 fix(sdk): Re-export schemaTask types to prevent the TypeScript error TS2742 (#2735)
Fixes this type of error when exporting a `schemaTask` in a monorepo:

```
error TS2742: The inferred type of 'helloWorldSchema' cannot be named without a reference to '@trigger.dev/core/v3'. This is likely not portable.
```
2025-12-03 16:12:23 +00:00
Saadi Myftija 255a73a2fe feat(deployments): --native-build-server support for the deploy command (#2702)
This PR adds support for CLI deployments using the native build server.

**Background**

The deployment command currently does the following:
- bundles the code
- submits the build context to our external build provider and waits for
the build
- triggers deployment state transitions using the platform API

Upstream build provider outages cause issue with deployments,
potentially blocking deployments entirely. We recently introduced the
`--force-local-build` flag as a fallback to enable deployment without a
dependency on the upstream build provider, though it requires users to
have docker in their systems. This PR continues that work by providing a
remote build path which uses our own build server and does not rely on
the external provider.

**Changes in this PR**

Introduced the new `--native-build-server` flag, which does the
following:
- scans all files relevant for the Trigger deployment and evaluates
ignore rules
- packages it up in an archive and uploads it as a deployment artifact
- queues the deployment and triggers the build
- streams logs from the build server

This no longer relies on external build services. Also deployment state
transitions happen on the server-side, giving us more flexibility to
evolve the flow and schemas of related deployment API endpoints. In
general it gives us better control of the whole build and deployment
process. This path will eventually become the default.

The `--detach` flag is also new, allowing to trigger deployments without
waiting for the result.

The deployment artifacts are uploaded via pre-signed URLs to avoid
unnecessary load on the platform. The new `/artifacts` endpoint
generates the pre-signed URLs; size limits are enforced on s3. This
endpoint is deliberately generic, we could extend it in the future to
upload other artifacts client-side in a similar way, e.g., large payload
packets.
2025-12-03 16:40:21 +01:00
Saadi Myftija c5f7a8daf7 fix(releases): explicitly use no frozen lockfile in the install step (#2733) 2025-12-03 16:28:06 +01:00
Saadi Myftija 8b0f51b317 chore(releases): automatically update the lockfile in changeset PRs (#2732)
This is a step which we currently need to do manually and it's rather
painful. The lockfile update is necessary due to cross references in our
packages.

Added it as a separate job instead of a step to start from fresh
workspace, as the state that the `changeset` step leaves the workdir is
not explicitly clear to the reader.
2025-12-03 16:04:30 +01:00
Oskar 53f21e1330 feat(build): Add syncNeonEnvVars extension and improve Vercel env var syncing
Add a new `syncNeonEnvVars` build extension for syncing environment variables
from Neon database projects to Trigger.dev. The extension automatically detects
branches and builds appropriate PostgreSQL connection strings for non-production
environments (staging, dev, preview).

Features of `syncNeonEnvVars`:
- Fetches branch-specific database credentials from Neon API
- Generates all standard Postgres connection strings (DATABASE_URL, POSTGRES_URL,
  POSTGRES_PRISMA_URL, etc.) with both pooled and unpooled variants
- Supports custom database name, role name, and env var prefix options
- Skips automatically in Vercel environments (Neon's Vercel integration handles this)
- Skips for production environments (designed for preview/staging/dev branches)

Improvements to `syncVercelEnvVars`:
- When running in a Vercel build environment (detected via VERCEL env var),
  values are now read from process.env instead of the Vercel API response
- This ensures the build uses the actual runtime values Vercel provides
- Removed embedded Neon-specific logic (now handled by separate extension)
- Simplified and cleaned up the extension code

Documentation updates for both extensions with usage examples and configuration
options.
2025-12-03 16:03:41 +01:00
Saadi Myftija 331882f59c chore(releases): add package version in changeset PRs (#2730)
* Add the release version to changeset PRs

* Add missing id-token permission, needed for oidc

* Remove a couple of unnecesary steps

* Reference the `changeset-release/main` branch explicitly
2025-12-03 14:42:40 +01:00
nicktrn 1276491a83 docs: clarify slack channel on pro (#2731) 2025-12-03 13:23:38 +00:00
Eric Allam 5b7dfe23b5 feat(cli): implements content-addressable store for the dev CLI build outputs, reducing disk usage (#2725)
* feat(cli): implements content-addressable store for the dev CLI build outputs, reducing disk usage

* fix a few things
2025-12-03 10:17:35 +00:00
Oskar 49b2f683f4 feat(build): Add NeonDB branch resolution for Vercel preview environments
Vercel's NeonDB integration renders database connection environment
variables at runtime, which means Trigger.dev cannot directly sync
these values during the build process. This change adds support for
fetching branch-specific NeonDB connection strings via the Neon API.

Changes:
- Discover NEON_PROJECT_ID from incoming Vercel environment variables
- Call NeonDB API to search for branches matching the git branch name
- Filter branches to find exact matches with Vercel environment prefix
  (e.g., "preview/branch-name") to avoid false positives from partial
  string matches
- Retrieve branch endpoints and select the write endpoint (or first
  available)
- Build connection strings (DATABASE_URL, POSTGRES_URL, etc.) using
  the branch endpoint host while preserving user/password credentials

Safety measures for non-production environments:
- Filter out all Neon-related env vars (DATABASE_URL, PGHOST, etc.)
  before calling the Neon API to prevent accidental use of production
  database credentials
- Only add branch-specific database env vars if a matching Neon branch
  is found and the API call succeeds
- If neonDbAccessToken is not provided or the API fails, non-production
  environments will not receive any database connection env vars

Usage:
Users must provide a NEON_ACCESS_TOKEN (via options or env var) to
enable automatic branch resolution for preview deployments. Production
environments continue to use Vercel's standard env var sync without
modification.
2025-12-02 19:52:45 +01:00
nicktrn af9b3e1c99 fix(cli): header will always print the correct profile (#2728) 2025-12-02 17:45:35 +00:00
Eric Allam df4ab97d59 fix(otel): fix broken schedule run spans (#2727)
schedule spans can sometimes show as generic spans when using the 
task_events_v2 table because of the inserted_at filter. Increasing the 
buffer for the start time does the trick and doesn’t cause any perf 
Issues (and is in general just more robust)
2025-12-02 17:16:08 +00:00
Eric Allam 9f27422472 fix(otel): exported logs and spans will now have matching trace IDs (#2724)
When using custom OTLP exporters via `telemetry.exporters` and 

This occurred when tasks were triggered **without** a parent trace 
context (e.g., via API or dashboard). In this scenario: - Spans were 
correctly rewritten to use the generated `externalTraceId` - Logs kept 
their original internal trace ID due to a bug in the early return logic

### Root Cause

In `ExternalLogRecordExporterWrapper.transformLogRecord()`, the early 
return condition incorrectly included `!this.externalTraceContext`:

```typescript
if (!logRecord.spanContext || !this.externalTraceId || 
!this.externalTraceContext) {   return logRecord;  // Bug: Returns early
when externalTraceContext is undefined }

// This fallback logic was never reached:
const externalTraceId = this.externalTraceContext
  ? this.externalTraceContext.traceId
  : this.externalTraceId;
```

### Fix

1. **Reordered logic in `transformLogRecord()`**: Move the 
1. `externalTraceId` calculation before the early return, and check the 
1. culated value instead of `this.externalTraceContext`:

```typescript
const externalTraceId = this.externalTraceContext
  ? this.externalTraceContext.traceId
  : this.externalTraceId;

if (!logRecord.spanContext || !externalTraceId) {
  return logRecord;
}
```

2. **Clarified `_isExternallySampled` logic**: Updated both 
2. `ExternalSpanExporterWrapper` and `ExternalLogRecordExporterWrapper` 
2. explicitly handle the case where there's no external trace context 
2. a generated `externalTraceId` exists:

```typescript
this._isExternallySampled = externalTraceContext
  ? isTraceFlagSampled(externalTraceContext.traceFlags)
  : !!externalTraceId;
```

### Impact

Logs and spans from the same task run will now have matching trace IDs 
when exported to external observability tools, enabling proper trace correlation regardless of whether the task was triggered with or without a parent trace context. 
`telemetry.logExporters` in `trigger.config.ts`, logs and spans were 
exported with **different trace IDs**, breaking trace correlation in
external observability tools like Datadog.
2025-12-02 14:16:06 +00:00
nicktrn 2f1a72b109 security: remedy dependabot alerts (#2723)
* security: override js-yaml

* security: upgrade vite

* security: update nodemailer
2025-12-02 12:02:48 +00:00
Eric Allam 3c326a4b4a fix(clickhouse): ensure start_time is never older than X ms to prevent old partition merge issues (#2721) 2025-12-01 15:43:10 +00:00
Saadi Myftija 6ae1317b69 chore(clickhouse): enable dropping run debug events (#2720)
Added a new env var (`EVENT_REPOSITORY_DEBUG_LOGS_DISABLED`) that allows disabling writing run debug logs in the event repository.
2025-12-01 15:42:35 +01:00
Eric Allam 2e1c4f6df6 fix(clickhouse): partition by insertion date to prevent "Too many parts" errors when partitioning by start time (#2719) 2025-12-01 12:01:06 +00:00
nicktrn 2bf86dc20e fix(supervisor): image builds with pnpm v10 (#2718) 2025-12-01 11:28:05 +00:00
nicktrn 485782cae1 feat(ch): optionally disable migrations (#2715) 2025-11-28 19:39:29 +00:00
Eric Allam 61b338bea7 chore(repo): upgrade repo to pnpm@10 to prevent executing dep scripts on install (#2712)
* chore: migrate pnpm lockfile to v9 format via pnpm@9

* Upgrade to pnpm 10.23.0

* update the dockerfile and added a few deps to bundle in remix app
2025-11-27 16:26:19 +00:00
Kim Hallberg 83ddf721a4 docs: update Firecrawl example (#2652)
Update the example to use Firecrawl v2 API
2025-11-24 14:54:51 +00:00
Kim Hallberg a4dd2562d2 docs: format embedding example (#2656) 2025-11-24 14:51:53 +00:00
Felipe Martinez Albeche 5ff21a758c fix(docs): tooltip color contrast accessibility (#2662)
* fix(docs): color contrast accessibility on tooltip

* add changeset

* Delete .changeset/tough-feet-accept.md

---------

Co-authored-by: Eric Allam <eric@trigger.dev>
2025-11-24 14:39:14 +00:00
Lindsey 47a64c0335 docs: improve env var documentation with .env upload + ctx environment details (#2680) 2025-11-24 14:37:04 +00:00
Eric Allam fc351cb6c4 chore(repo): remove GITHUB_TOKEN requirement for publishing prerelease packages (#2679) 2025-11-24 14:33:40 +00:00
Eric Allam c4f2a9d065 chore(references): added prisma-generator-ts-enums to prisma ref project as an example (#2701) 2025-11-24 14:33:22 +00:00
Eric Allam 2762c542c2 chore(repo): remove format script to AI stops calling it (#2703) 2025-11-24 14:33:14 +00:00
Eric Allam 72e286af2f feat(otel): support for custom resource attributes via config#telemetry.resource and OTEL_RESOURCE_ATTRIBUTES env var (#2704) 2025-11-24 14:33:07 +00:00
Eric Allam f7240a99e7 fix(react): prevent infinite useEffect when passing an array of tags to useRealtimeRunsWithTag (#2705) 2025-11-24 14:32:57 +00:00
github-actions[bot] 6e47377766 chore: Update version for release (#2700)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 21s
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-24 10:30:01 +00:00
nicktrn a8563ca534 fix(docker): support the latest docker version (#2686) 2025-11-21 15:24:31 +00:00
Eric Allam 5e5c97ea4c fix(cli): stop dev runs stuck in dequeued status (fix #2639) (#2699)
* stop deleting the first dev version files on the first change, prevents system failures

* prevent dev runs getting stuck in dequeued status by deleting workers

* add changeset
2025-11-21 15:24:07 +00:00
Matt Aitken abd99aa27f Don't show (or count) archived branches/projects against allocated concurrency (#2698)
Archived preview branches were being counted. Also archived projects.
2025-11-20 11:41:12 +00:00
Eric Allam 4347499799 fix(api): Fix preview branch targeting in environment variable API routes (#2697)
This PR fixes the `x-trigger-branch` header support for targeting specific preview branches when managing environment variables. The header was documented but not actually being extracted or used in the environment variable API routes. Additionally, the query logic in `authenticatedEnvironmentForAuthentication` was fundamentally broken—it searched for environments with both `slug: "preview"` (parent environment property) AND a specific `branchName` (child environment property), which no environment could satisfy simultaneously. The fix extracts the branch name using `branchNameFromRequest()` and correctly queries for child branch environments using `type: "PREVIEW"` and the specific `branchName`. This ensures that environment variable operations (create, update, get, list) properly target individual preview branches instead of affecting all preview environments.
2025-11-19 18:01:12 +00:00
Eric Allam abee783d3f chore(logs): remove unnecessary debug logs (#2696) 2025-11-19 13:56:15 +00:00
Eric Allam 6464eeed53 fix(webapp): correctly generate JWT tokens for preview branches after triggering a run (fix #2678) (#2695) 2025-11-19 13:42:12 +00:00
Matt Aitken bee59de3a0 Concurrency self serve (#2681)
* Don't use the organization max concurrency anymore

* Early draft of the concurrency page

* WIP adding a new stepper input component

* Move stepper to be alphabetical

* When max value is reached, disabled the + button

* Show placeholder if you delete all numbers

* Make all the html input values available to the component

* Adds size variants

* Move stepper into its own component

* Work on showing the extra concurrency

* The purchase form styling and functionality (minus actually purchasing)

* New style for outline input fields

* Concurrency purchasing working

* Purchasing concurrency and quota emails working

* Improvements to the modal

* Show cost breakdown in the modal

* Fix for allocated concurrency including DEV

* Improved types

* Allocating concurrency is working

* Live updates total env concurrency

* Implemented reset

* Fix for concurrency allocation editing across multiple projects

* Tabular numbers

* Added an error from allocating concurrency

* Fixes for allocating concurrency where it didn't calculate correctly

* "Increase limit" link to concurrency page

* Indent environments

* Added Preview limit when updating concurrency for an org

* Show error when changing plan fails

* Added maximumProjectCount column to Org

* Limit project count and display a rich error toast (with title and button now)

* Added title and button to toasts. Use it for new project error

* @trigger.dev/platform 1.0.20

* Allow submitting zero concurrency so you can downgrade back to nothing

* Use the server as the truth for omitted environments

* Updated the pricing panels

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2025-11-19 11:22:23 +00:00
Eric Allam 3af7303156 feat(docs): update prismaExtension for new mode functionality in 4.1.1 (#2690) 2025-11-19 11:16:35 +00:00
github-actions[bot] 6231ddc67a Release v4.1.1
* chore: Update version for release

* chore: Update pnpm-lock.yaml (#2694)

* Initial plan

* Update pnpm-lock.yaml

Co-authored-by: ericallam <534+ericallam@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ericallam <534+ericallam@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ericallam <534+ericallam@users.noreply.github.com>
2025-11-19 11:09:26 +00:00
Eric Allam 15fef916f6 feat(build): update prisma extension to work with generated clients and rust-free clients (#2689)
* prisma extension fixes WIP

* More prisma stuff

* more prisma stuff

* remove changelog

* upgrade github workflows to use node 20.19 because installing prisma@7 breaks with lower versions

* Don't use generate for the prisma reference projects

* make sure it works if no mode is passed in
2025-11-19 10:48:15 +00:00
Eric Allam e2a703bfa8 fix(dashboard): continuously apply log filter during live run (#2692) 2025-11-18 17:00:29 +00:00
Saadi Myftija 1a7ee24b9e fix(ui): refresh deployments logs stream on status change (#2688)
The logs stream is created after the deployment moves from `PENDING` status to `INSTALLING`.
2025-11-17 14:50:05 +01:00
Saadi Myftija bb99af52cb feat(deployments): expose native build server option in build settings (#2685)
Adds a build setting about using our build server for remote builds.
2025-11-17 12:46:57 +01:00
Saadi Myftija 01797a1668 feat(deployments): ECR repo adaptations to enable external build cache (#2684)
* Update aws sdk ecr client to the latest version

* Exlude the cache tag from the immutability enforcement

* Attach a policy to ECR repos to expire untagged images

* Fix filterType
2025-11-17 12:34:54 +01:00
Eric Allam 19fa669318 Release v4.1.0 (#2683) 2025-11-14 09:55:01 +00:00
github-actions[bot] 78fcba518a chore: Update version for release (#2666)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-14 09:52:22 +00:00
Saadi Myftija 53047ab648 feat(deployments): external cache support for local builds (#2682)
* Add registry cache support for local builds

* Add changeset
2025-11-14 10:46:31 +01:00
Eric Allam bb5cefa92c docs: realtime streams v2 (#2673) 2025-11-14 09:42:20 +00:00
Eric Allam b8b198579c chore(rules): upgrade rules for 4.1.0 (#2676) 2025-11-14 09:42:15 +00:00
Eric Allam 892bed8c4c Upgrade to electricsql 1.2.4 (#2668) 2025-11-13 15:19:59 +00:00
Eric Allam a94a11f44d feat(sdk): replace onStart lifecycle hook with onStartAttempt (#2515)
* fix(sdk): prevent uncaught errors thrown onSuccess, onComplete, and onFailure hooks to fail attempts & in some cases runs

* Add onStartAttempt hook and deprecate onSuccess

* Add onStartAttempt hook and deprecate onStart hook

* Fix onStartAttempt overload types

* Update lifecycle functions diagram
2025-11-13 14:51:13 +00:00
Matt Aitken f116e93e01 Docs: tags can be up to 128 chars (#2678) 2025-11-13 14:43:31 +00:00
Eric Allam 6137338da9 feat(streams): make v2 streams the default when using 4.1.0+ if they are supported (#2677) 2025-11-13 13:53:42 +00:00
Lindsey 8cec3b763b docs: add section on using .env.production and dotenvx for environmen… (#2674)
* docs: add section on using .env.production and dotenvx for environment variables

* fix: correct dotenvx API usage in documentation example
2025-11-13 11:28:26 +00:00
Eric Allam 343ba54c69 fix(streams): restore realtime stream writing for v3 tasks (#2675) 2025-11-13 11:21:48 +00:00
Eric Allam a70ab10809 fix(streams): fixed broken wrapping in streams inspector (#2672) 2025-11-12 16:00:54 +00:00
Eric Allam f7cb637b32 fix(streams): scope s2 access token to environment and fix streams v1 appends (#2670)
* fix(streams): scope s2 access token to environment and fix streams v1 appends

* Less stale time
2025-11-12 12:34:15 +00:00
Eric Allam 668559ec1a fix(streams): buffer v1 streams on read to prevent split chunks (#2669) 2025-11-11 21:08:49 +00:00
Eric Allam d0ad38d684 chore(docker): remove unused seed copy from dockerfile (#2667) 2025-11-11 15:13:10 +00:00
Eric Allam 536d9fa217 feat(realtime): Realtime streams v2 (#2632) 2025-11-11 14:54:00 +00:00
github-actions[bot] d75c3aeadd chore: Update version for release (#2665)
* chore: Update version for release

* Release 4.0.7

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matt Aitken <matt@mattaitken.com>
2025-11-11 14:29:24 +00:00
Matt Aitken a342332146 Fix for the MCP tool that gets logs for debugging runs (#2653)
* Fix for the MCP tool that gets logs for debugging runs

This was broken when we changed the data on the backend that returns 
log/span data from runs. We changed the data structured and the internal
API that the MCP client uses was failing to parse with the Zod schema

* add changeset

* Revert "add changeset"

This reverts commit 86eca836d5907fa0d0f8ac595d4d5ebade140514.

---------

Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-11-11 13:26:07 +00:00
Saadi Myftija 9624465ee2 fix: error handling issue with s2 streams (#2664)
* Fix logger import

*old man yells at auto-import*

* Fix s2 error handling for non-existing streams
2025-11-11 09:44:54 +01:00
Saadi Myftija 42f53b12b7 feat(deployments): stream build server logs (#2663)
* Use read-only project-scoped s2 tokens for streaming deployment logs

* Add http2 to remix polyfills

Needed for using s2 client-side.

* Stream build-server logs in the deployment details page

* Disable 12-hour format in the DateTime component

* Enable collapsing the logs panel

* Auto-collapse logs for succesful/timedout/queued deployments

* Make S2 env vars optional

* Show the logs section only for gh-triggered deployments

* Cache s2 access tokens in redis

* Reset streaming state

* Expose 12h format as a param for the Datetime components
2025-11-10 12:42:40 +01:00
github-actions[bot] 9fdf91a1c4 Release v4.0.6 (#2647)
* chore: Update version for release

* Update lock file

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: myftija <saadi.myftija@gmail.com>
2025-11-03 14:42:02 +01:00
nicktrn 9593a46364 fix(extensions): prevent audiowaveform binary removal (#2643)
* fix(extensions): prevent audiowaveform binary removal

* add changeset
2025-11-03 14:17:38 +01:00
Saadi Myftija 27376df903 fix(cli): show a useful error message when config file is missing (#2650)
* fix(cli): show a useful error message when config file is missing

* Add changeset
2025-10-31 16:34:48 +01:00
Saadi Myftija e0cece72ae docs: deployments with local builds (#2645)
* docs: deployments with local builds

Adds a section to the deployment docs page about the option to deploy using a locally built image.

* Update installation link
2025-10-30 18:10:23 +01:00
Saadi Myftija 2f3f82f3a9 feat(deployments): show local build hint during depot outages (#2646)
* Add an API endpoint to query remote build provider status

* Show local build hint for failed deployments when Depot is down

* Show the local build flag in the help output

* Add changeset

* Fix import

* Fix docs link
2025-10-30 18:09:54 +01:00
Dan 4264bdf429 Added use cases section in the docs (#2641)
* Started adding use cases pages

* Updates

* More improvements

* Improved diagrams

* Added overview page

* More copy + diagram updates

* Improved diagram titles

* Further diagram improvements

* Corrected workflow

* Updated copy

* Typos

* Updated intro file

* Reverted aiRunFilterService.server.ts
2025-10-30 09:21:31 +00:00
nicktrn bf6735bd56 fix(webapp): concurrency override upper bound should be env not org (#2642) 2025-10-29 19:16:42 +00:00
James Ritchie dacd53b906 Fix for showing the incident UI in the side menu (#2638) 2025-10-28 21:13:23 +00:00
github-actions[bot] d4fe71df34 Release v4.0.5 (#2531)
* chore: Update version for release

* Release v4.0.5

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-10-28 14:20:20 +00:00
nicktrn ae8e83b2d0 chore(runner): move max duration logic into parent process (#2637)
* chore(runner): move max duration logic into parent process

* chore(rsc): remove type-marker package.json

* add changeset

* chore(core): remove irrelevant test after our changes

* chore(core): clarify we don't care about the timeout promise
2025-10-28 13:49:59 +00:00
nicktrn 2283ca6ad3 fix(webapp): persist concurrency overrides on deploy (#2636)
* fix(webapp): display correct concurrency override base value

* fix(webapp): persist concurrency overrides on deploy

* fix(webapp): use correct override base value type

* fix(webapp): override input is bounded by env concurrency
2025-10-28 11:28:38 +00:00
nicktrn 8fdbbeb02f chore(helm): increase default clickhouse resources (#2635) 2025-10-27 13:45:09 +00:00
Marcus Nerløe 255ea0a4b3 fix(supervisor): prevent escalating duplicate reconnections in failedPodHandler (#2627)
⚒️ Publish Worker (v4) / build (supervisor) (push) Has been cancelled
* fix(supervisor): prevent escalating duplicate reconnections in failedPodHandler

* fix: added catch handler for informer.start() failures

* fix: removed 'errorStack' from error log
2025-10-23 11:13:45 +01:00
Saadi Myftija 7f25e82299 feat(deployments): support local builds in cloud (#2628)
* Enable skipping image push during deployment finalization step

* Add endpoint to generate registry credentials for a deployment

* Add a --force-local-build flag to the deployment command to skip remote build

* Do not show the new flag in the help output

* Add changeset

* Remove registry login logs from onLog, not useful

* Rename var

* Update platform package to the latest version
2025-10-23 10:57:36 +02:00
Eric Allam d90da7abf7 fix(replication): allow disabling of task run payload inserts via env var (#2626) 2025-10-22 11:22:14 +01:00
Matt Aitken 2affe541e8 Dev concurrency limit by env (with optional global limit) (#2625)
* Limit local dev concurrency using the dev environment concurrency limit

Previously it was limited to max of 25, no matter the environment limit

* Have global dev limit
2025-10-22 10:55:05 +01:00
Matt Aitken 3157b657c7 Test page recent payload: use ClickHouse to get the latest run ids (#2614)
The Postgres query to get the latest run ids for the test page was very 
slow when there were a lot of runs and/or versions.

This now uses the standard runs list we use everywhere else.
2025-10-17 17:17:36 +01:00
Matt Aitken 41bdab58d5 Document the dev --analyze command (#2613) 2025-10-17 13:00:30 +01:00
James Ritchie fe3fe01fe8 feat(queues): Override queue concurrency limits from the dashboard or API (#2609)
* feat(queues): add ability to override concurrency limit via API and dashboard

* Updates the modal layout and tweaks copy

* Improves the dropdown menu item

* Popover supports both Button and LinkButton

* Right align the columns and fix the dropdown menu item styles

* Organize imports,

* Fix spinner icon in dropdown menu

* Remove unused props

* Adds a tooltip to the Concurrency override badge

* Fixes console error with popover menu

* typo

* Fixes incorrect className

* Minimal buttons to view runs

---------

Co-authored-by: Eric Allam <eallam@icloud.com>
2025-10-17 12:58:25 +01:00
Matt Aitken 68d0037e60 fix(dev): dotenv issues when getting setup with the repo (#2612)
- The .env.example was missing required Clickhouse values.
- A symlink was needed for .env from the root to the apps/webapp folder
2025-10-17 11:49:40 +01:00
Matt Aitken 885d2d3560 Tags listing now uses ClickHouse (#2576)
* WIP using ClickHouse for the tags filter list

* WIP on tags listing

* Webapp: exclude test files when typechecking

* Tags filtering working with CH

* Remove unused import

* The AI filter should only look at the last past 30d of tags

* Do the text query in ClickHouse

* Deal with encoded characters better

* More encoding fixes

* Fix for wrong items being checked

* Put applied tags back

* Add the env.id to the dependencies array
2025-10-15 12:56:08 +01:00
Eric Allam a445af1b79 feat(otel): allow clickhouse task events to be inserted using async_insert via env vars (#2608) 2025-10-15 10:37:17 +01:00
nicktrn 5781783c74 fix(engine): default to paid placement on billing errors (#2604)
* chore(billing): improve logs to distinguish between failure modes

* fix(engine): default to paid placement on billing errors

* chore(engine): set plan type according to paying field when missing
2025-10-15 10:32:27 +01:00
nicktrn cca10c22d3 chore(supervisor): add machine label (#2603) 2025-10-15 10:31:37 +01:00
Leonardo Kaynan 63b6fc93fa fix(helm): align values-production-example.yaml with values.yaml (#2606)
- Move S3 credentials from secrets.objectStore to s3.auth
- Update external PostgreSQL config to use databaseUrl/directUrl approach
- Add existingSecret support for PostgreSQL with secretKeys
- Add TLS configuration for external Redis
- Add existingSecret support for Redis, ClickHouse and S3
- Add complete external S3 configuration example
- Improve secure credential management documentation

These changes align the production example file with the current values.yaml
structure, making it easier to configure external services with better
support for secret management.
2025-10-14 23:16:58 +01:00
Saadi Myftija aa66462971 docs(build-server): adjust build env vars section (#2605)
Adds a clarification about the env var prefix stripping.
2025-10-14 17:29:42 +02:00
James Ritchie f6461684ad chore(webapp): adds shortcut key for admin area (#2570)
* Allow shortcuts hook to work if undefined

* Conditionally show shortcut button if only 1 result

* LinkButton can accept conditionally shown shortcuts
2025-10-13 13:26:00 +01:00
James Ritchie a6896b411a Adds a link to edit the profile icon from the main menu (#2572) 2025-10-13 13:25:06 +01:00
Saadi Myftija 0cabbdd31f docs: deploying using the github integration (#2598)
* docs: deploying using the github integration

* Add hint in the gh actions docs page

* Remove extra space

* Add a couple of hints to the build config fields
2025-10-13 14:15:48 +02:00
Eric Allam f8977a7b70 chore(db): remove unnecessary FK constraints on TaskRunExecutionSnapshot (#2533) 2025-10-09 14:07:45 +01:00
Saadi Myftija f0643f76f5 feat(build-server): add option to specify pre-build command (#2596)
* feat(build-server): add option to specify pre-build command

Adds an option to specify a pre-build command in the build settings. Can
be useful for projects that need a step before the build, e.g., to
generate a prisma client.

Also, remove the install directory in favor of simplicity. Both
pre-build and install commands are run from the root of the repo. Users
that need to run the commands in a different dir can just prepend to the
command, e.g., `cd apps/web && pnpm run primsa:migrate`

* Fix spelling
2025-10-08 17:25:44 +02:00
Saadi Myftija 416dbcd536 fix(webapp): disable gh-triggered preview deployments if the preview env is disabled (#2595)
* Show hint if preview branches are disabled in the project

* Enable preview deployments only if the preview environemtn is enabled

* Fix prisma reference
2025-10-08 16:59:25 +02:00
Eric Allam 679b41dc7e chore(electric): upgrade server to 1.1.14 (#2590) 2025-10-08 14:33:10 +01:00
Eric Allam be98aecbfd fix(otel): prevent unpaired unicode surrogate pairs from causing insert errors (#2594)
* fix(otel): prevent unpaired unicode surrogate pairs from causing insert errors

* only check parts of the string that are not going to get truncated
remove unnecessary taks
2025-10-08 14:32:35 +01:00
nicktrn 129dc02f2a chore: add deepwiki badge to main readme (#2587)
This means DeepWiki will automatically re-index our repo and keep our page fresh
2025-10-08 13:15:06 +01:00
nicktrn 8917478d3c fix(runner): SIGTERM handling during warm start long poll (#2593) 2025-10-08 12:51:10 +01:00
Leonardo Kaynan f5caa66348 fix(helm): use bitnami legacy repo for minio console (#2592)
🧭 Helm Chart Release / lint-and-test (push) Has been cancelled
🧭 Helm Chart Release / release (push) Has been cancelled
* fix(charts): use bitnamilegacy repo for MinIO Object Browser

The Bitnami `minio-object-browser` image has been removed from Docker
Hub. This patch updates the Trigger Helm chart to reference the
`bitnamilegacy/minio-object-browser` repository under the
`s3.console.image` section, ensuring that the legacy MinIO browser pod
can still be deployed without image pull errors.

All other MinIO components continue using the `bitnamilegacy/minio`
image for consistency across Bitnami Legacy dependencies.

* chore(helm): bump Helm chart version to 4.0.4
2025-10-07 22:17:37 +01:00
Eric Allam 64fcc88fa7 fix(otel): spans with entities (like waitpoints) now correctly returned from clickhouse repo (#2591) 2025-10-07 16:55:00 +01:00
nicktrn 23dbe282ed security: upgrade transitive axios dep (CVE-2025-58754) (#2589) 2025-10-07 14:56:16 +01:00
Eric Allam 692316e82a fix(realtime): Upgrade to @electric-sql/client@1.0.14 to prevent cached 409 Conflict errors from breaking realtime updates (#2588) 2025-10-07 14:26:03 +01:00
Saadi Myftija 107f4dc87c fix(deployments): retry transient depot build init failures (#2586)
The Depot build init with `depot.build.v1.BuildService.createBuild` fails surprisingly often due to transient errors, causing the whole deployment to fail. This PR adds a simple retry mechanism with backoff using p-retry. This should improve the failure rate.
2025-10-06 11:33:31 +02:00
Eric Allam b90f3e2173 fix(otel): remove clickhouse event repo feature flag support from v3, now v4 only (#2585) 2025-10-06 09:54:23 +01:00
Eric Allam b3b2553651 fix(otel): propagate the task event store to run descendants (#2583) 2025-10-04 07:28:16 -07:00
Eric Allam cdd1a8838c fix(otel): prevent spans with negative durations (#2582) 2025-10-03 06:50:16 -07:00
Eric Allam 200b7354d0 fix(otel): clickhouse logs/span metrics now exclude partials and debug events (#2581) 2025-10-02 13:51:50 -07:00
Eric Allam eeed38d223 fix(clickhouse): correctly format datetime64(9) input format (#2580) 2025-10-02 11:32:32 -07:00
nicktrn 0ca092651b feat(supervisor): optional custom scheduler (#2579) 2025-10-02 16:22:53 +01:00
Eric Allam 53acdf8ef5 fix(otel): don't pass isDebug when creating postgresql task events (#2578) 2025-10-01 21:57:35 -07:00
Eric Allam 128bc437f6 feat(otel): Add support for storing run spans and log data in Clickhouse (#2567) 2025-10-01 12:41:18 -07:00
James Ritchie 0597691001 Adds 200 and 500 % billing alert options (#2571) 2025-09-30 13:59:44 -07:00
mintlify[bot] dae84a0d29 Update docs/idempotency.mdx (#2575)
Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
2025-09-30 13:50:02 -07:00
nicktrn f72d63aac2 chore(helm): migrate to bitnami legacy registry and add configurable utility images (#2574)
🧭 Helm Chart Release / lint-and-test (push) Has been cancelled
🧭 Helm Chart Release / release (push) Has been cancelled
* chore(docker): use bitnami legacy repo

* chore(helm): use bitnami legacy repo

* Make Helm webapp chart images configurable

Adds configurability for init and token syncer container images through
new values in the Helm chart configuration

* chore(helm): refactor utility image config

* chore(helm): bump chart version to 4.0.3

---------

Co-authored-by: LeoKaynan <leokaynan@hotmail.com>
2025-09-30 16:02:08 +01:00
nicktrn 12cceaa779 feat(helm): support topology spread constraints for webapp (#2560)
* feat(helm): support topology spread constraints

* chore(helm): update topology env var

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* chore(helm): limit spread constraints to webapp for now

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-09-30 15:31:04 +01:00
Saadi Myftija ddebe4dce0 feat(webapp): rate limit magic-link login attempts (#2568)
* feat(webapp): rate limit magic-link login attempts

Adds a simple rate limiter to the login with magic link flow. Similar implementation to the MFA rate limits.

* Fix error message

* Add an env var feature flags for login rate limiting

* Use BoolEnv instead of `0`/`1`

* Parse xff properly
2025-09-29 17:28:36 +02:00
Saadi Myftija 09d51c6d24 fix(webapp): add recommended security headers (#2569)
Sets `Referrer-Policy`, `X-Content-Type-Options` and `Permissions-Policy` headers.
Relevant against certain types of attacks.
2025-09-29 16:55:22 +02:00
Saadi Myftija 3ceea774a8 fix(run-engine): waitpoint update misleading error logs (#2566) 2025-09-26 21:16:12 +02:00
Eric Allam 05b6a26c4f fix(run-engine): pass through engine fair dequeue selection strategy options instead of using defaults (#2565) 2025-09-26 17:12:36 +01:00
Eric Allam 558fb11b89 feat(run-engine): ability to repair runs in QUEUED, SUSPENDED, and FINISHED execution status (#2564)
* feat(server): add two admin endpoints for queue and environment concurrency debugging and repairing
feat(run-engine): ability to repair runs in QUEUED, SUSPENDED, and FINISHED execution status

* Handle FINISHED snapshot in the repair
2025-09-26 15:16:10 +01:00
nicktrn 9aedda23a4 fix(run-engine): carryover batchId after PENDING_EXECUTING stalls (#2563) 2025-09-26 14:14:28 +01:00
Eric Allam 743b8dbe0c chore(run-engine): add additional logging around dequeueing and worker queues (#2562) 2025-09-26 11:50:21 +01:00
Eric Allam eb0263e942 feat(server): add two admin endpoints for queue and environment concurrency debugging and repairing (#2559) 2025-09-25 19:33:10 +01:00
Saadi Myftija 7bf579fa50 fix: use higher entropy invite tokens (#2558)
* fix: use higher entropy invite tokens

We currently use CUIDs for invite tokens, which are generated using
a pattern and are not cryptographically secure. This PR switches to
a higher entropy string generated with `nanoid`.

* Dedupe the invite emails in the application
2025-09-25 19:42:59 +02:00
Saadi Myftija 69d52db856 fix(webapp): org scoping issues in plan selection, alerts, pats and usage (#2549)
* fix: org scoping in the select plan flow

Adds proper org scoping in the loader and action in the plans page.

* Fix billing alerts scope

* Fix org usage page scope

* Fix token revoking flow scope check

* Throw error for failed PAT revokes instead of silent failure
2025-09-25 19:17:51 +02:00
Saadi Myftija a3cea1302e fix(webapp): org invite scoping (#2554)
* fix: org invite scoping

Fixes some scoping issues with team invites.

* Fix invite flow changes
2025-09-25 19:17:19 +02:00
Eric Allam a3bdd3c64b chore(run-engine): improve concurrency sweeper logging to get better visibility (#2557) 2025-09-25 16:43:43 +01:00
Saadi Myftija 6d6e98aa11 fix(webapp): project scoping for runs (#2553)
* fix: project scoping for runs

* Apply some 🐰 suggestions
2025-09-25 17:43:13 +02:00
Eric Allam e22c321dd1 fix(engine) truncate errors before storing them on a run and waitpoint output (#2552) 2025-09-25 13:39:51 +01:00
Eric Allam 59df4af1eb chore(engine): add additional logging when we fail to get snapshots since (#2551) 2025-09-25 12:59:02 +02:00
Eric Allam 8863ff05c9 fix(engine): limit the number of snapshots returned when getting latest snapshots since (#2550) 2025-09-25 11:53:35 +01:00
Matt Aitken d10281e655 Additional files docs with legacyDevProcessCwdBehaviour (#2543) 2025-09-24 14:32:02 +01:00
nicktrn 6798d57e72 chore(helm): bump image versions to 4.0.4 (#2537) 2025-09-24 14:31:30 +01:00
Saadi Myftija 480c0d34d3 fix(webapp): toast message issue after gh app installation (#2546)
* fix(webapp): toast message issue after gh app installation

Fixes an issue with displaying toasts messages in the project settings
page. The github callback cookie was interfering with the flash cookie used
for toast messages.

* Do not set a tracking branch in the staging env by default
2025-09-24 15:20:03 +02:00
Saadi Myftija 700a6ea598 feat: enable canceling deployments (#2545)
* Add canceledAt to the deployment db schema

* Expose an api endpoint to cancel deployments

* Show the canceled status description in the dashboard

* Enable canceling deployments from the dashboard

* Show cancelation reason in the deployment details

* Make verifyProjectMembership a function for consistency

* Apply some good 🐰 suggestions
2025-09-24 11:14:29 +02:00
Saadi Myftija cc94d121f2 feat: installing status for deployments (#2544)
* Add installing status to the deployment db schema

* Replace the deployments /start endpoint with /progress

* Show the installing status in the dashboard

* Add installing status to the api schema and cli

* Add changeset
2025-09-24 10:27:43 +02:00
Saadi Myftija 412e80fdde fix(webapp): hide outdated connected repos from deleted installations (#2538) 2025-09-23 13:24:58 +01:00
Saadi Myftija 49728b5a5f feat(api): defer remote build creation for pending deployments (#2536)
Depot builds have short-lived tokens and their TTL is not exposed in the SDK. As queued deployments can stay in the queue for an arbitrary amount of time, deferring the remote build creation helps avoid expired Depot token issues.
2025-09-22 13:01:56 +02:00
Saadi Myftija d45696c000 fix(api): 204 response issue in deployment start endpoint (#2534) 2025-09-19 19:05:18 +02:00
Eric Allam 8313800746 fix(webapp): don't override spans from ancestors unless the span is partial (#2532) 2025-09-19 14:58:53 +01:00
James Ritchie 28f8cee3a4 Fix for errors returned from searching time specific queries (#2525)
* Fix for errors returned from searching time specific queries

* Adds prompt patterns
2025-09-19 13:49:43 +01:00
Eric Allam 87b3603b23 feat(webapp): completing spans server-side no longer write-after-read, improving efficiency and perf (#2530)
* Cancel run events which then propogate cancellation status to span ancestors

* WIP

* convert closing cached run spans to new system

* converted expired complete span event to new method

* move v3 over to new methods

* Convert getDetailedTraceSummary to use the new ancestor override stuff

* remove debug logs

* Don't return UNSPECIFIED task events in getRunEvents

* fix the call site for cancelling run event in v3

* Add changeset

* remove methods
2025-09-19 13:39:48 +01:00
James Ritchie 365adc24a6 Chore(webapp): adds more copy buttons (#2529)
* Pass up asChild

* Include padding when asChild specified

* Adds copy buttons to useful data in Details tab

* Improve view batch tooltip message
2025-09-19 13:02:10 +01:00
Saadi Myftija 7d17730b52 feat(api): handle build server deployment init gracefully for older cli versionsi (#2526)
This PR adapts the deployment initialization endpoint to handle build server deployments with older CLI versions gracefully.

When we introduced automatic deployments via the build server, we slightly changed the deployment flow
mainly in the initialization and starting step: now deployments are first initialized in the `PENDING` status
and updated to `BUILDING` once the build server dequeues the build job.
Newer versions of the `deploy` command in the CLI will automatically attach to the existing deployment
and continue with the build process. For older versions, we can't change the command's client-side behavior,
so we need to handle this case here in the initialization endpoint. As we control the env variables which
the git meta is extracted from in the build server, we can use those to pass the existing deployment ID
to this endpoint. This doesn't affect the git meta on the deployment as it is set prior to this step using the
/start endpoint. It's a rather hacky solution, but it will do for now as it enables us to avoid degrading the
build server experience for users with older CLI versions. We'll eventually be able to remove this workaround
once we stop supporting 3.x CLI versions.
2025-09-19 10:40:59 +02:00
Saadi Myftija e4982bfd6d feat(webapp): deployments page live reloading (#2524)
* Fix `current` badge inconsistency in the deployment details page

* Add custom hook for auto revalidation based on an interval and/or focus change

* Use the autoRevalidate hook for live reloading of the deployments page

* Extract autoReloadPollIntervalMs to an env var

* Replace the sse-based autoreload in bulk actions and queues page with the simpler autoRevalidate hook
2025-09-19 10:40:07 +02:00
github-actions[bot] a03783d1a0 Release v4.0.4
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 19s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 19s
* chore: Update version for release

* Release v4.0.4

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <eallam@icloud.com>
2025-09-18 23:18:59 +01:00
Eric Allam 0178bdbb00 fix(packages): remove effect from optional peer dependencies (#2527)
Fixes ERROR: Could not resolve "effect"
2025-09-18 23:09:37 +01:00
github-actions[bot] ad51168181 Release v4.0.3 (#2486)
* chore: Update version for release

* Release v4.0.3

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-09-18 21:28:30 +01:00
nicktrn db87295049 fix(runner): reduce restore recovery time and deprecated runner false positives (#2523)
* fix(runner): improve restore detection

* chore(supervisor): skip schema parsing when debug logs disabled

* fix(runner): deprecation race condition

* add changeset
2025-09-18 16:59:44 +01:00
Saadi Myftija a3ef6ea236 feat: separate deployment initialize and start steps (#2522)
* Enable setting the initial status on deployment creation

* Expose endpoint to start deployments

* Extend build timeout on deployment start

* Use separate timeout value for queued deployments

* Add startedAt to the deployment schema

* Show the new startedAt instead of createdAt in the dashboard

* Show github user tag also in the deployment details page

* Show `pending` deployment status as `queued` in the dashboard

* Apply some good 🐰 suggestions

* Add missing return
2025-09-18 16:12:17 +02:00
James Ritchie ae22000409 chore(webapp): pricing page improvements (#2457)
* Improve styling of onboarding pricing plans

* type only import

* Improve the onboarding plan page so it scrolls on smaller screens

* Adds additional pricing for bolt-ons for the Pro plan

* fix text wrapping issue

* add bg color back in
2025-09-18 14:31:06 +01:00
James Ritchie 2bbf8ec6cd chore(webapp): a new cancelation reason (#2465)
* Adds a new cancelation option

* Better wording
2025-09-18 14:30:25 +01:00
James Ritchie c8858edf0a New jump to parent or root run buttons (#2067)
* Change the color to indigo

* Pro tier pricing information now matches the marketing site

* Update the button styles to secondary

* WIP adding separate links to Parent and Root runs

* TextLink now supports optional shortcuts

* Adds shortcut keys to the root and parent links + the shortcut help panel

* Adds new icons for root and parent

* root friendlyId works

* Updates icons for jump to root and parent

* Copy tweak

* Improve how the Free tier shows no preview branches

* Improve the wording in the tooltip

* Align the x icon better

* Show price for additional preview branches

* Change the shortcut key

* Fixes button alignment

* Adds nested dependencies task hello-world

* Fixes typo “Cancelled”

* Removes taskIdentifier, not needed

* Removes unused taskIdentifier
2025-09-18 14:29:47 +01:00
Eric Allam 9c087646bf fix(engine): prevent race condition that prevents triggerAndWait runs from resuming by atomically creating associated waitpoint records (#2519) 2025-09-17 13:58:17 +01:00
Saadi Myftija 691903cf58 feat(api): accept OATs in preview branch related endpoints (#2517)
Adjusts the authentication in a couple of endpoints to accept OATs too.
2025-09-17 14:10:25 +02:00
nicktrn 885ae5e06f fix(runner): immediate poll to decrease restore time (#2516)
* fix(runner): immediate poll to decrease restore time

* chore: bump default prerelease tag

* fix(cli): s is not a function

* add changeset
2025-09-16 16:17:04 +01:00
Saadi Myftija 501a383bcd feat: expose project build settings (#2507)
This PR enables setting project build settings in the settings page:
root directory, install command and trigger config file path.

For most cases there should be no need to set these explicitly.
2025-09-16 15:02:09 +02:00
nicktrn 3c199e6d9c chore(supervisor): remove deprecated route (#2513) 2025-09-16 13:47:07 +01:00
nicktrn a55294b7dd fix(run-engine): retry SIGSEGV errors (#2514) 2025-09-16 13:46:58 +01:00
Eric Allam c9d1aadfc3 core(docs): link to the v4 self-hosting in the introduction (#2512) 2025-09-16 13:26:55 +02:00
Eric Allam 08702cd710 chore(mcp): Add our MCP server to the official MCP registry (#2510)
See: 
https://blog.modelcontextprotocol.io/posts/2025-09-08-mcp-registry-preview/
2025-09-16 10:44:41 +01:00
Dan 04dcb81496 Added product image generator and replicate examples (#2511)
* Added nano banana task

* Renamed the file and updated docs.json

* Added product imgae generator demo project

* Removed old section

* Code tweak
2025-09-16 10:26:11 +01:00
Eric Allam 0f9b83db09 fix(core): prettyPrintingPacket will now do a structuredClone on non-circular references instead of outputting [Circular] (#2508)
* Mo-Stashed changes

* fix(core): prettyPrintingPacket will now do a structuredClone on non-circular references instead of outputting [Circular]

This also fixes an issue with replaying of runs that include 
non-circular references
2025-09-15 17:43:46 +01:00
Saadi Myftija 7d333e5b3c feat(cli): attach to existing deployments in the build server (#2501)
* Add external build data and image platform to the get deployment endpoint

* If provided, attach to an existing deployment in the deploy command

* Check status for existing deployments

* Add changeset
2025-09-15 17:16:26 +02:00
nicktrn 7c4ce6f76b feat(supervisor): add optional memory limit overhead (#2506) 2025-09-15 16:09:05 +01:00
Eric Allam dc42ae7aa4 chore(repo): update changeset snapshot instructions (#2505) 2025-09-15 15:27:54 +02:00
Saadi Myftija b0b88f1e05 fix(webapp): show deployments where triggeredById is missing (#2504)
Small fix for the sql query used in the deployments list page.
2025-09-15 14:12:48 +01:00
Eric Allam 6483a0f1c6 fix(core): Improves our schema to JSON Schema conversion (fix for zod 4) (#2483) 2025-09-15 14:11:40 +01:00
Eric Allam 6f1abe058b chore(docs): heartbeat timeout is now 5 minutes (#2500) 2025-09-15 15:11:32 +02:00
Eric Allam 83bd6f5f9e fix(engine): carry over completed waitpoints on PENDING_EXECUTING stalls (#2503) 2025-09-15 12:19:46 +01:00
Eric Allam e36d78e4fc fix: don't carry over the checkpoint ID when nack and requeuing (#2502) 2025-09-15 12:06:52 +01:00
Eric Allam 3188dc9b28 perf(webapp): Add BatchTaskRun index to speed up the batch list dashboard page (#2499) 2025-09-12 17:23:52 +01:00
Eric Allam 10e7985fbc Add index for waitpoint tokens dashboard query (#2498) 2025-09-12 16:48:42 +01:00
Eric Allam 2eddda1233 fix(webapp): worker actions now catch service validation errors and respond properly (#2481)
This also stops all the unnecessary error logging when throwing 
ServiceValidationErrors
2025-09-12 14:56:54 +01:00
HUORT Louis 49f2c54031 fix: webapp crash on clickhouse data corruption (#2491) 2025-09-12 14:55:29 +01:00
Eric Allam f077d49291 feat(engine): Improve execution stalls troubleshooting, align dev and prod behavior, adding heartbeats.yield utility (#2489)
* feat(engine): Improve execution stalls troubleshooting, align dev and prod behavior, adding heartbeats.yield utility

* A few improvements via the 🐇 review

* Allow treating EXECUTION stalls as OOM errors, improve the error message, add more information to the docs, improve resource monitor and add it to the docs

* Add changeset
2025-09-12 14:54:39 +01:00
Eric Allam 5db583b6cd docs: add machine option in triggering docs (#2487) 2025-09-11 15:28:26 +02:00
Matt Aitken 1227e5463e Fix for broken retrieve runs docs page (#2496)
The API path was accidentally edited as part of a /v3 purge
2025-09-10 16:59:37 +01:00
Eric Allam 8e66913e59 fix(run-engine): Preserve snapshot checkpoint ID when a PENDING_EXECUTING snapshot stalls (#2493) 2025-09-10 14:55:57 +01:00
Dan b9b17e24ac Added anchor browser example (#2488)
* Added anchor browser example project

* Updated node ver
2025-09-09 14:32:26 +01:00
Saadi Myftija 12bef0a938 feat: env command in the cli (#2485)
* Add a CLI command to list and view env vars

* Add changeset

* Restrict pemissions on env files created with `env pull`

* Escape env vars when exporting to file

* Switch changeset to patch
2025-09-09 13:13:24 +02:00
Saadi Myftija 5567f49846 feat(webapp): expose project git settings (#2464)
* Fix settigns page delete project width issue

* Apply a couple of touch-ups to the project settings page

* Add UI flow to connect gh repos

* Enabling adding another gh account in the ui

* Enable connecting a repo to a project

* Enable updating git settings

* Enable disconnecting gh repos from a project

* Remove prisma migration drifts

* Hide git settings when github app is disabled

* Fix migration order

* Avoid using `location` to avoid SSR issues

* Make branch tracking optional

* Disable save buttons when there are no field changes

* Disable delete project button unless the input matches the project slug

* Show connected repo connectedAt date

* Check that tracking branch exists when updating git settings

* Show tracking branch hint in the deployments page

* Fix positioning issue of the pagination pane in the deployments page

* Use mono font for branch names

* Add link to git settings

* Show tracking branch hint for the preview env too

* Add a confirmation prompt on repo disconnect

* Add link to configure repo access in gh

* Add rel prop to github links

* Automatically open repo connection modal after app installation

* Apply some fixes suggested by mr rabbit

* Fix flash cookie issue

* Extract project settings actions into a service

* Extract project settings loader into a presenter service

* Introduce neverthrow for error handling

* Try out neverthrow for error handling in the project setting flows

* Move env gh branch resolution to the presenter service
2025-09-09 13:03:43 +02:00
Dan 71060d93b1 Removed some remaining /v3’s from the docs (#2478)
* Removed /v3 from numerous files

* Fix AWS SDK v3 documentation link for S3 uploads
2025-09-08 10:01:09 +01:00
Eric Allam 89b1d8ba13 fix all lifecycle hooks (#2480) 2025-09-05 11:17:38 +01:00
Eric Allam 97015ba8c8 fix(docs): update sentry error tracking guide for v4 (#2479) 2025-09-05 11:13:13 +01:00
nicktrn 99660112bd feat(supervisor): add configurable resource requests (#2474) 2025-09-04 17:09:34 +01:00
Matt Aitken e6586d3c1a Remove deprecated releaseConcurrency from wait.forToken() docs (#2477) 2025-09-04 14:57:17 +01:00
Eric Allam 00d32ed4ee feat(webapp): add support for running web services (api, engine, webapp) in cluster mode for better perf (#2472)
* feat(webapp): add support for running web services (api, engine, webapp) in cluster mode for better perf

* cleaned up signal handling and resolved some valid 🐇 issues
2025-09-04 09:53:15 +01:00
nicktrn a1e9738faa fix(webapp): prevent duplicate preview env image tags (#2475)
* fix(webapp): prevent duplicate preview env image tags

* use deploy shortcode instead of new nanoid

* replace regexps in tests
2025-09-04 09:37:22 +01:00
nicktrn 59c17e04e9 feat(run-engine): worker queue resolver (#2476) 2025-09-04 09:27:06 +01:00
Eric Allam ed23615aa4 perf(webapp): add event loop utilization metric (#2471)
* perf(webapp): add event loop utilization metric

* add event loop utilization logging as well
2025-09-03 11:39:03 +01:00
Saadi Myftija 436d951b65 feat(webapp): github app installation flow (#2463)
* Add schemas for gh app installations

* Implement gh app installation flow

* Make the gh app configs optional

* Add additional org check on gh app installation callback

* Save account handle and repo default branch on install

* Do repo hard deletes in favor of simplicity

* Disable github app by default

* Fix gh env schema union issue

* Use octokit's iterator for paginating repos

* Parse gh app install callback with a discriminated union

* Remove duplicate env vars

* Use bigint for github integer IDs

* Sanitize redirect paths in the gh installation and auth flow

* Regenerate migration after rebase on main to fix ordering

* Handle gh install updates separately from new installs
2025-09-02 16:35:33 +02:00
nicktrn cf9398b56e fix(run-engine): retry SIGTERM errors (#2468) 2025-09-02 15:18:16 +01:00
Eric Allam 9b1877bef2 fix(run-engine): retry non-zero exit code errors (#2467)
We’re also now saving the retryConfig from the BackgroundWorkerTask on 
TaskRun.lockedRetryConfig when the run is first locked to the version
2025-09-02 14:12:14 +01:00
Eric Allam 0b2b73fc52 chore(docs): improve version pinning advise to use installed trigger.dev CLI (#2466) 2025-09-02 14:10:01 +01:00
nicktrn 0d1eac9406 feat(supervisor): dynamic queue consumer pool (#2461)
* feat(supervisor): dynamic queue consumer pool

* add changeset

* fix: correctly handle zero median and even samples

* feat(supervisor): consumer pool metrics

* fix tests

* more tests and fixes

* decrease default scaling cooldowns

* don't treat initial pool size as scale up

* handle scale down when queue length drops to zero

* remove changeset, supervisor changes only

* add damping factor env var
2025-09-02 13:52:42 +01:00
Willow (GHOST) ddbae6b6b4 fix(docker): clickhouse healthcheck (#2462) 2025-09-01 20:20:17 +01:00
nicktrn 2b095b1072 chore(webapp): upgrade otel packages and add more metrics (#2458)
* feat(webapp): upgrade otel packages and add more metrics

* add env var to disable additional detectors

* expose more prisma metrics

* chore(webapp): drop node 16 support
2025-09-01 16:24:12 +01:00
Dan 847ea866b6 Various docs improvements (#2456)
* Added MCP to the intro

* Added human-in-the-loop and new build extensions

* Waitpoint notes

* Moved openai guardrails example to Python

* Added a connection limit note

* Added Supabase + Prisma note to supabase auth

* Updates based on what the rabbit said

* Moved the supavisor section to the prismaExtension docs
2025-08-29 16:48:04 +01:00
James Ritchie fee31f2dc0 chore(webapp): update region message to say we are GDPR compliant (#2455)
* Updates the Region message to say we are GDPR compliant

* Hide the message if not on cloud
2025-08-29 14:33:46 +01:00
github-actions[bot] 10baa396d8 Release v4.0.2 (#2447)
* chore: Update version for release

* Release v4.0.2

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-08-29 12:58:22 +01:00
James Ritchie 27bc2ad232 chore(webapp): show a regions info panel to explain about data residency (#2428) 2025-08-29 11:35:54 +01:00
James Ritchie 3a3e863daf chore(webapp): bulk action cancel as default (#2437)
* Switches “replay” and “cancel” options in the list

* Fixed incorrect cancel icon being used

* Fixes the alignment of the radiobuttons
2025-08-29 11:30:46 +01:00
Eric Allam f5f14c4206 chore(webapp): fix @trigger.dev/database imports so it doesn't end up in the frontend bundle (#2452) 2025-08-29 11:27:01 +01:00
Eric Allam 892adfe81c fix(mcp): don't require a trigger.config.ts file to be present when installing rules (#2453) 2025-08-29 11:20:45 +01:00
nicktrn 73e7378459 feat(webapp): add ecs otel resource attributes (#2454)
* add attributes to runlock dequeue span

* feat(webapp): add ecs otel resource attributes
2025-08-29 11:05:47 +01:00
Eric Allam b0b0df69be fix(run-engine): prevent stalled SUSPENDED snapshots from endlessly retrying (#2448) 2025-08-28 14:25:50 +01:00
Saadi Myftija e629810e96 fix: dev env connection issue (#2449)
This PR fixes an issue introduced in #2391 where the dev runtime env was not being resolved correctly.
2025-08-28 14:05:10 +01:00
Ognjen Simic e6f6d93e59 docs: update triggering.mdx fixing wrongly stated argument position for options (#2283)
* docs: update triggering.mdx fixing wrong argument numeration for options

Update the docs triggering.mdx: text indicating options argument position inside `tasks.trigger` function.

Options object is a third argument instead of stated second argument.

* update triggering.mdx to change options argument position in batchTrigger
2025-08-28 10:16:42 +01:00
Eric Allam 6f6ca01584 feat(mcp): add wait_for_run_to_complete tool so agents don't spam the get_run_details call after triggering (#2445)
* feat(mcp): add wait_for_run_to_complete tool so agents don't spam the get_run_details call after triggering

This also fixes the search docs MCP tool

* Install mcp using the latest tag, not the specific version
2025-08-28 10:13:46 +01:00
James Ritchie 11cbd1b5a0 Docs: Fixes incorrect retrieving runs from batchTrigger (#2427)
* Docs: fix for retrieving runs in batchTrigger

* Removes old v3-to-v4 migration guide (we have a redirect)

* Corrects tag limit from 5 to 10
2025-08-28 10:11:42 +01:00
Eric Allam 82401ec4fe fix(run-engine): dequeue performance improvements and improved telemetry (#2446)
* more eager dequeuing, queue cooloff periods, return workerQueueLength when dequeueing

* Cache worker group authentication and remove old self-hosted worker code (only managed is currently supported)

* add additional spans during dequeue

* Add env vars and additional spans
2025-08-27 21:22:10 +01:00
Matt Aitken 24a915133e Prisma 6.14.0 upgrade (#2444)
* Initial work on upgrading to 6.14.0

Set the output to node_modules still to make it easier

* Use ./generated Prisma folder, update types to fix issues

* Docker compose restart Clickhouse

* Prisma instrumentation update

* Docker

* Removed database dockerignore file, add generated prisma client to the top-level one

* Delete v3-catalog package.json

* Resolved pnpm lock file

* Log errors for very slow queries
2025-08-27 16:52:58 +01:00
Eric Allam 688b108ec3 chore(references): remove v3-catalog (#2443) 2025-08-27 14:35:55 +01:00
Saadi Myftija 1cc62230ab feat: introduce organization access tokens (#2391)
* Create schema and migration for organization access tokens

* Add helpers for creating and authenticating OATs

* Adapt the auth service to also accept OATs

* Accept OATs in the whoami v2 endpoint

* Enable deployments with the CLI using OATs

* Avoid reading env variables directly in the token utils

* Remove duplicate cli token utils

* Validate ENCRYPTION_KEY length when parsing env vars

* Make token utils a server-only module

* Disallow revoking already revoked OATs

* Simplify generics in authenticateRequest

* Use 32 bytes mock encryption key in the test setup

* Update dummy encryption key values in tests and templates

* Add a column in the OATs table to differentiate between user and system generated

* Simplify args for v3ProjectPath

Co-authored-by: Matt Aitken <matt@mattaitken.com>

* Add index on org id and createdAt

* Avoid storing the encrypted oat token and its obfuscated version in the DB at all

It is a safer approach. Also we do not need to ever read the decrypted token value after creation.

* Fix prisma update condition

* Add token type to the OAT table index

* Accept OATs in the mcp auth flow

* Simplify env auth flow around the /projects endpoints

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2025-08-27 13:23:45 +02:00
Eric Allam 96243efe16 docs: MCP Server 2.0 (#2385)
* Add MCP Server documentation to documentation site

This change introduces comprehensive documentation for the Trigger.dev MCP Server, covering its installation, usage, and available tools. The addition is necessary to provide users with detailed guidance on leveraging the MCP Server for managing Trigger.dev projects, tasks, and deployment processes.

- Updated `docs.json` to include a new section for the MCP Server documentation, improving navigation and accessibility.
- Added `mcp-introduction.mdx` as an introductory guide to the MCP Server, detailing its purpose and installation steps.
- Included `mcp-tools.mdx`, a document outlining each tool available in the MCP Server, complete with descriptions and example usages.
- The new content is aimed at improving user understanding and efficiency in using Trigger.dev's MCP Server capabilities.

* Refactor MCP installation documentation

The changes were necessary to streamline the MCP installation guidance and align our documentation with the latest client support capabilities. Removing the manual installation section and redundant information helps reduce confusion for users.

- Updated installation instructions to lead with auto-configuration for supported clients.
- Cleaned up the options and examples sections to enhance clarity.
- Reformatted client configuration details for better readability.
- Removed outdated links in the "Next Steps" section, focusing on more direct resources such as available MCP tools.

* mcp docs edits

* Add debugMode to get_run_details

* add cancel_run

* Add list deployments tools

* Add list preview branches tool

* Docs: adds agent rules page

* Adds redirect for the CLI path to work

* Adds subagent install image

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2025-08-22 15:37:35 +01:00
Eric Allam ad26cded99 fix(v3): prevent saturated queues from dominating dequeue attempts by adding a cooloff period of successive failed dequeues (#2439)
* fix(v3): prevent saturated queues from dominating dequeue attempts by adding a cooloff period of successive failed dequeues

* Add env vars and add a marqs shutdown on SIGTERM/INT
2025-08-22 14:37:21 +01:00
Eric Allam 5e4756f8b7 fix(v3): eagerly dequeue messages from a queue when that queue is added to or removed from (v4 backport) (#2438)
* fix(v3): eagerly dequeue messages from a queue when that queue is added to or removed from (v4 backport)

* fixed configuration
2025-08-22 13:23:34 +01:00
Eric Allam c16cc577b0 fix(v3): adopt v4 dequeue strategy to increase perf (#2436) 2025-08-22 07:40:59 +01:00
github-actions[bot] 5b40c44ca6 Release v4.0.1
* chore: Update version for release

* Release v4.0.1

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <eallam@icloud.com>
2025-08-21 17:41:58 +01:00
Eric Allam c7e3811794 fix(webapp): correctly associate event-loop-blocked spans with parent span context (#2435) 2025-08-21 16:21:26 +01:00
Eric Allam bf2120d5a7 fix(runengine): remove dev worker queues from metrics (#2434) 2025-08-21 14:11:22 +01:00
Eric Allam 895e24a0d7 fix(cli): various mcp server fixes (#2430)
* fix: span events are optional, as logs don't have them

* remove CI: true env var to prevent massive tool responses

* fix github resolver relative path

* prevent the dev command from asking for user input when not interactive

* Remove lodash.get because it's deprecated

* span output can be object other than an object, like a string

* prevent large traces from causing get_run_details failures

* Decreased max log lines, made it a tool input property

* Some install mcp tweaks
2025-08-21 13:57:14 +01:00
Matt Aitken 58ff034325 Add attemptDequeue span to marqs (#2433)
* Add attemptDequeue span to marqs

More telemetry to figure out why dequeuing is slow

* More spans

* use "receive" for all operation names
2025-08-21 13:09:08 +01:00
Dan 84750f68a4 Updated main README (#2432)
* readme wip

* Added new commands

* Simplified readme

* Added docs links and improved about

* Added nice header and updated links

* Consistent headers

* Copy update

* Updated badges

* Added features / agents section

* Updated list

* Added links

* Updated links

* Minor readme tweaks

* Updated banner

* removed /v3/

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2025-08-21 12:28:52 +01:00
Matt Aitken 1087e5ede0 When replaying a v3 run on v4, don't pass the region (#2431) 2025-08-21 10:15:26 +01:00
Eric Allam f086626a41 feat(cli): MCP server 2.0 (#2384) 2025-08-20 16:04:50 +01:00
Matt Aitken 8483900832 Updated queue/concurrency docs for v4 (#2418) 2025-08-20 11:47:56 +01:00
Matt Aitken 4264fc066e chore(webapp): More false errors turned to logs (#2422)
* Remove variables from dequeue log message

* Continue snapshot throw json

* Waiting for deploy error removed

* Realtime ECONNRESET is expected

* Redis worker logErrors changes, removed ids

* Preview branch without a branch shouldn't log an error, it's a user provided issue

* "Task run is not in a cancellable state" isn't an error, it's expected

* "CreateCheckpointService: Child run already resumed" is expected

* "CreateCheckpointService: Batch already resumed" is expected

* "Failed to insert events, will attempt bisection" changed to info, we have errors for complete failures

* Ignore "PrismaClient error"

* Don't log Redis worker DLQ errors if we're ignoring

* "Failed to parse machine config" is fine, sometimes a config is null or undefined

* "Failed to parse machine config" for v3

* MetadataTooLargeError shouldn't log an error
2025-08-20 11:44:26 +01:00
nicktrn da79c2b185 chore(docker): add registry namespace var to .env.example (#2426) 2025-08-20 11:03:30 +01:00
nicktrn 677b7aed9c chore(docs): update bun guide (#2425)
* chore(docs): remove missing snippet references

* chore(docs): update bun guide
2025-08-20 11:03:23 +01:00
nicktrn 9092ca863f feat(supervisor): add ecr support to docker client (#2424) 2025-08-20 10:49:19 +01:00
James Ritchie b41129a24f Tabular-nums for the individually selected runs number (#2421) 2025-08-19 16:24:02 +01:00
James Ritchie 0261ccbc68 Fixes conflicting shortcut keys (#2420) 2025-08-19 15:38:53 +01:00
nicktrn 32e3fab5ea feat(helm): release 4.0.0 chart version (#2416)
* feat(helm): release 4.0.0 chart version

* chore(helm): remove last few beta references

* fix(docker): use latest tag for commands shown in webapp
2025-08-19 11:06:35 +02:00
Matt Aitken 0ee4234117 Reduce false error logging (round 1) (#2415)
* Don't log an error when the snapshot shouldn't be created, it's normal for this to happen

* Slack alerts, skip `account_inactive` errors

* v3 finalize run with no locked isn't an error

* Another false error

* Finalize run CRASHED runs were logging errors

* All slack alert errors are warnings except invalid blocks
2025-08-19 09:58:21 +01:00
Matt Aitken 471c96079a Some more queue docs changes for v4 (#2414) 2025-08-18 16:49:43 +01:00
Eric Allam 0ae59cf7b9 fix appEnv on undefined error and useShortcuts error on ErrorBoundary (#2412) 2025-08-18 15:42:16 +01:00
Matt Aitken 49e6470b6b Added missing trigger.config options to the docs (#2409) 2025-08-18 15:11:34 +01:00
Matt Aitken 9dd831f68a Fix for v4 pending versions not getting dequeued after a deploy (#2411)
We didn’t call `scheduleEnqueueRunsForBackgroundWorker` in the right 
place…
2025-08-18 15:09:12 +01:00
nicktrn 112f6f602e feat(supervisor): optionally strip digests from image refs (#2410) 2025-08-18 15:08:49 +01:00
github-actions[bot] 0b35cc35e0 Release v4.0.0 🚀
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 4s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
2025-08-18 12:35:03 +01:00
James Ritchie fade22015f Docs – v4 GA updates (#2298)
* Adds new features table to top of v4 upgrade guide

* Adds wait idempotency to wait-until, wait-for, and wait-for-token pages

* Adds new priority docs page and updates the v4 upgrade guide

* Adds new task lifecycle hooks

* Removes the message about requiring tasks to be exported

* Adds new global lifecycle hooks section

* Moves sections from upgrade guide into the table

* Adds hidden task page

* Improves the global lifecycle hooks section

* Updates middleware and locals section

* Adds new useWaitToken page to the react hooks section

* Adds a new ai.tool section

* Moves Docker (legacy) page into self-hosting section

* Removes known issues from v4 upgrade guide

* Replace “toolTask” with “ai.tool” in the Streams page example

* Renames guide to “Migrating from v3” and adds redirect

* Remove references to v4

* Removes changelog from migration guide

* The installation guide now references `@latest update`

* Changes all references from `/sdk/v3` to `/sdk`

* Updates @v4-beta to @latest

* Fixed broken link

* Fixes broken link

* Adds an upgrade to v4 using AI section

* Fixes 2 broken links

* Adds an entry for targetting preview branches

* Updates the run statuses

* Adds boolean helpers section to the runs and realtime pages

* Updates the concurrency page

* Updates the test page to include the new options

* Adds SDK and curl options for the preview branch targeting

* Updates new bulk actions page

* Remove the releasing concurrency section

* Got rid of some more @v4-beta mentions

* Improved rate limit docs

* Improved migrating docs

* Removed commented sections of the docs

* useWaitToken hook

* Fixed the description

* Fix for missing test image

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
Co-authored-by: Dan <8297864+D-K-P@users.noreply.github.com>
2025-08-18 12:34:55 +01:00
Dan 78af477efc Updated readmes (#2408)
* readme wip

* Added new commands

* Simplified readme

* Added docs links and improved about

* Added nice header and updated links

* Consistent headers

* Copy update
2025-08-18 12:10:15 +01:00
Eric Allam e864973e01 chore(packages): leave changesets prerelease mode (#2406) 2025-08-18 11:06:31 +01:00
github-actions[bot] 132008ff64 Release 4.0.0-v4-beta.28 (#2386)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.28

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-08-17 20:30:33 +01:00
nicktrn 26d4d08bdc chore: move all placement tag helpers to core (#2403)
* chore: move all placement tag helpers to core

* move placement tag utils into server-only
2025-08-15 17:19:39 +01:00
Eric Allam 1a8880971d fix(runner): prevent retry immediately race condition which can cause stuck runs that end up being system failures (#2402) 2025-08-15 17:05:02 +01:00
Eric Allam 3d17ce5559 feat: AI SDK 5.0 support (#2396)
* feat: AI SDK 5.0 support

* Add changeset
2025-08-15 17:03:39 +01:00
nicktrn a76905e272 chore(bun): upgrade to bun v1.2.20 (#2398) 2025-08-15 17:01:06 +01:00
Eric Allam 1c73ab930b fix(realtime): waitUntil now correctly waits for metadata.streams to finish (#2399) 2025-08-15 17:00:45 +01:00
Eric Allam 816c7ad56e fix(webapp): remove unnecessary log (#2401) 2025-08-15 12:47:55 +01:00
Eric Allam 4d975b19e7 fix: external traces now respect parent sampling, and prevent broken traces when there is no external trace context (#2395)
* fix: external traces now respect parent sampling, and prevent broken traces when there is no external trace context

* Add changeset

* improve trace flag handling and better internal host checking

* the traceFlags are now being properly passed through as a number
2025-08-15 10:12:38 +01:00
Eric Allam 4c4b774bab fix(webapp): Don't propogate region when replaying a run from or to development (#2400) 2025-08-15 10:07:59 +01:00
nicktrn fa7f4b1fed feat(k8s): add placement tags for flexible node selection (#2390)
* add tier scheduling support to supervisor

* add billing info to dequeued message w/o cache

* add cache with best effort invalidation

* fix invalidate circular dep

* add changeset

* use new plan type on runs as fallback during dequeue

* tidy up

* be more explicit with plan type fallback

* remove additional billing check from hot path

* switch to placement tags

* update changeset

* update platform package

* start using new entitlement response

* ensure skipChecks optimization validates at batch level

* add optional items to add to queue manager limits

* make the bool env helper only accept boolean defaults

* remove redundant private field

* update placement tag helper to prevent unsupported tags
2025-08-15 09:52:14 +01:00
Saadi Myftija f76765448b feat: show gh username and avatar for deployments triggerd by the github app integration (#2394)
Small change that shows the github user in the deployments page in cases
where it was triggered by the github app integration.

These deployments are not triggered using a PAT, so we cannot associate
them with a Trigger user ID.
2025-08-14 18:20:59 +02:00
Saadi Myftija 944b1875f1 feat: gather deployment git meta from the build server (#2392)
This PR adapts the deployment command to also evaluate build server env
variables when creating the git meta. The build server will initially
only support deployments triggered by the github app, but we might add
other git providers in the future.

Sticking to the GH actions naming convention for the env variables set
by the build server in favor of consistency.
2025-08-14 16:07:36 +02:00
Eric Allam a5dd6389b2 fix: sentry memory leak by patching @sentry/remix to stop cloning request (#2389)
* fix: sentry memory leak by disabling includeLocalVariables

* Enhance heap snapshot consistency and labeling

To facilitate more accurate and consistent heap memory snapshots, a new function forceConsistentGC was added before taking a snapshot. This ensures the garbage collector (GC) runs multiple times, stabilizing the heap state for more reliable analysis. This is particularly helpful when debugging memory-related issues.

Updates to the memory-leak-detector script now allow labeling of snapshot runs using the --label flag. This helps in distinguishing different runs for easier tracking and comparison of memory usage across test sessions. Additionally, the --expose-gc flag ensures that the GC can be manually triggered during test runs, leading to more consistent memory states and potentially uncovering hidden memory leaks.

* Refactor forceConsistentGC for improved readability

The function forceConsistentGC was refactored to enhance code readability and consistency. The main improvements include:

- Updated syntax for consistent string quotation and spacing.
- Simplified garbage collection by removing specific major/minor GC calls, as the distinction isn't necessary.
- Implemented minor changes to arrow function formatting for consistency.

These changes neither impact the program logic nor the function behavior but help maintain code quality standards and readability.

* Fix memory leak by removing request.clone() usage

Identified that the memory leak in the project was linked to the usage of request.clone() within the `@sentry/remix` package's callRouteAction handler. Although initially suspected as a Sentry issue, the problem appears to arise from the handling of request.clone() in Remix version 2.1.0. By removing the call to request.clone(), the memory leak has been resolved.

- Introduced garbage collection execution before snapshot to manage memory allocation effectively.
- Improved error handling and timeout mechanisms in the memory leak detector to enhance its resilience during runtime.
- Expanded testing for both GET and POST requests to monitor and validate potential memory leaks better. The POST requests involve sending large payloads to stress-test the system.
- The modification particularly focuses on enhancing robust memory tracking and providing detailed progress reporting during request phases.

* patch @sentry/remix to prevent memory leaks

* Fix pnpm lock

* undo some unrelated changes
2025-08-14 14:50:20 +01:00
Saadi Myftija 3ec95cd72d fix: code editor/block theme inconsistency (#2393)
Tiny fix to make the themes across code blocks and editor components across the app consistent.
2025-08-14 11:41:36 +02:00
Eric Allam 6f29b7dc34 fix: legacyDevProcessCwdBehaviour defaults to true (#2387)
This fixes an issue with prisma not being able to locate the native 
add-on binary
2025-08-13 14:30:10 +01:00
Eric Allam ed07bf9306 fix: prevent circular reference errors on task indexing when using schemaTask (#2383)
* fix: prevent circular reference errors on task indexing when using schemaTask

* add changeset
2025-08-13 14:10:57 +01:00
Matt Aitken cd6a0b3a3e fix: heartbeat race condition (acking) (#2380)
* The logger now supports metadata

* Added metadata to ServiceValidationError in some critical places

* Don't ack the heartbeat if there's a mismatch, it might prevent a brand new one

* Don't ack the heartbeat inside stalled. By returning it will be acked IF the deduplication key matches
2025-08-12 10:35:21 +02:00
Eric Allam e9cc7de8ea docs: Add beta.27 changelog (#2381) 2025-08-11 22:06:12 +01:00
github-actions[bot] 0448f3603a Release 4.0.0-v4-beta.27
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.27

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matt Aitken <matt@mattaitken.com>
2025-08-11 15:39:59 +01:00
Matt Aitken dd4515a2eb Merge pull request #2379 from triggerdotdev/remove-trigger-and-poll
Remove triggerAndPoll()
2025-08-11 15:11:58 +01:00
Matt Aitken 97e5c22051 Added a changeset 2025-08-11 13:42:14 +01:00
Matt Aitken b8d2fb215f Remove triggerAndPoll() 2025-08-11 13:40:37 +01:00
Takeoff 21c2c136be test coverage for utils (#2057) 2025-08-11 11:53:03 +01:00
Matt Aitken ae19d0f491 Only start an attempt if not finished. Send message to worker if pending executing (#2377)
* Only start an attempt if not finished. Send message to worker if pending executing

* Fix the exit process reason tet

* Fixed cancelling test since bug fix

The old behaviour was wrong for pending executing in the test
2025-08-11 11:46:10 +01:00
Matt Aitken c58b78f43f Exit the process if status is finished and not in the middle of completing (#2378)
This solves an issue where a run is system failed from the platform and 
the worker is never shut down in the cluster.
2025-08-11 11:22:26 +01:00
Matt Aitken a968c23678 Don't use a failed run with idempotency in v4 (#2376) 2025-08-08 14:01:18 +01:00
nicktrn 4b08597c77 feat: optional v4 deploy registry overrides (#2370)
* feat: optional v4 deploy registry overrides

* only require credentials for non-ecr registries
2025-08-07 17:02:01 +01:00
Matt Aitken 9ce4f57a6a Upgraded v4 experimental flags. keepNames and autoDetectExternal now default to true. (#2371)
* keepNames default true, not experimental now

* Added docs for the `environments` declarative schedules feature

* minify and autoDetectExternal (true now)

* processKeepAlive

* devProcessCwdInBuildDir

* Changeset

* Switch to legacyDevProcessCwdBehaviour
2025-08-07 16:47:45 +01:00
nicktrn 363b9b15b4 fix(engine): set correct run status after requeue and snapshot status after dequeue (#2367)
* set correct run status on snapshot after dequeue

* set run status back to PENDING when we requeue

* remove retrying after failure status from v4 and fix tests

* fix one last test
2025-08-07 16:46:27 +01:00
James Ritchie 51305b6023 Onboarding dashboard background (#2346)
* Adds a background image dashboard wrapper

* Dashboard background image

* Adds a background image to the welcome onboarding page

* Background is constructed of 3 images

* Adds the background to the create org page

* Adds a background to the choose plan page

* Change the default button spinner color to white

* Adds the background to the create new project page

* Updates the invite team member page

* Adds background image to received invite page
2025-08-07 16:13:42 +01:00
Dan 9e41e83818 Restructured the realtime docs (#2317)
* Reordered react hooks + frontend sections

* Updated the overview and nav

* Separated out SWR hooks

* Restructured metadata sections

* Improved backend docs

* Fixed broken link

* Fixed broken links

* Updated the structure

* Restructured overview

* Updated examples cards

* Improved overview

* Updated how it works

* Updated auth

* Added type safety to the run object page

* made the subscribe description clearer

* Fixed links in triggering

* Fixed link

* Removed examples footers

* Copy tweak

* Consolidated metadata and subscribe pages

* moved metadata task examples to metadata

* Fixed links

* Fixing links like zelda

* Removed dead import

* Clearer titles

* Cap R for Realtime

* Fixes broken link

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2025-08-07 16:02:52 +01:00
Matt Aitken da7dc74fa4 Replaying keeps the original run region (#2368) 2025-08-07 14:43:28 +01:00
Matt Aitken af14621683 Specify a region when triggering (#2366)
* Map new allowedMasterQueues → allowedWorkerQueues

* ClickHouse worker_queue on task runs

* Added the Region to the run inspector

* Pass a region in when triggering

* Added a changeset

* Added triggering regions docs

* Added region to the ctx

* Fix for backfiller masterQueue/workerQueue
2025-08-07 12:41:39 +01:00
Matt Aitken 9787120cfb We need to set TRIGGER_OTEL_EXPORTER_OTLP_ENDPOINT for deployed runs (#2365) 2025-08-07 11:40:14 +01:00
Eric Allam e46e9bd30f docs: Manual setup guide (#2358)
* Add manual monorepo setup guide for Trigger.dev

This commit introduces a new "Manual setup" guide for setting up Trigger.dev in projects, specifically focused on monorepo configurations. The guide outlines two primary approaches for monorepos: creating a dedicated tasks package and integrating tasks directly within apps. This detailed documentation aims to help developers manually configure their projects, bypassing automated steps, and understanding the setup better.

- Provides step-by-step instructions for both 'Tasks as a package' and 'Tasks in apps' approaches.
- Includes example configurations for various package managers, environment setups, and runtime options.
- Enhances user understanding of Trigger.dev's configuration requirements in complex monorepo environments.

The purpose of adding this guide is to enable developers to seamlessly integrate Trigger.dev into their monorepos, whether they choose to abstract tasks into packages or embed them within individual applications. This flexibility supports diverse project structures while maintaining consistency with Trigger.dev's operational prerequisites.

* Correct tasks usage in documentation

The 'tasks as package' section in the documentation had an incorrect example under 'Use tasks in your apps' which needed correction to align with the actual package usage.

- Fixed incorrect import of tasks by updating to the correct import from '@repo/tasks/trigger'.
- Updated the syntax to use 'tasks.trigger' with type parameters, following the new pattern established for triggering tasks with TypeScript.
- Added error handling to catch and log errors during task execution, returning a meaningful error message instead of just failing silently.

This update ensures developers have an accurate reference when implementing tasks in their applications, especially given the breaking changes in TypeScript compatibility due to recent package updates.

* Update package configuration for Zod 3-4 compatibility

The recent Zod package updates from version 3 to 4 introduce breaking changes in TypeScript compatibility that require adjustments in our project configuration files. The primary updates involve adding type annotations and modifying import statements to support the shift without breaking existing functionality.

- Updated `package.json` and initialization files to align with new compatibility requirements.
- Modified server task examples to explicitly use type imports for improved error handling and consistency.
- Adjusted workspace and project settings to maintain compatibility and improve configuration clarity.
- Provided references to current examples for better implementation guidance.

* More manual setup guide steps

* Fix bun docs link
2025-08-07 10:22:37 +01:00
James Ritchie 3cd7dd86d4 Fixed code example in reduce spend docs page (#2350) 2025-08-06 17:18:59 +01:00
Matt Aitken a782813c6c Regions – dashboard page, switching default, allowedMasterQueues (#2354)
* Initial Regions page

* Fix for bad attribute name

* Switching regions is working. Some style improvements

* Use a dialog for confirmation, not great yet

* Added allowedMasterQueues

* Improves flag icons

* Improves the region switch modal with more info

* Adds “suggest a region” table row

* New icons for the buttons

* Improved the tooltip information

* New “small” badge style

* Make the default badge live in its column

* Better DO icon size

* Remove unused export of regions options

* Show upgrade message for free users to get static IPs

* Admins can view all regions and switch at will

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2025-08-06 15:56:01 +01:00
Eric Allam d950a969bd Update zod package to version 3.25.76 across all modules (#2352)
* Update zod package to version 3.25.76 across all modules

Update the zod library from version 3.23.8 to 3.25.76 in multiple package files to ensure compatibility and take advantage of new features or bug fixes introduced in recent releases. Keeping all modules synchronized with the latest version of zod helps maintain consistency across the project and reduces potential compatibility issues.

- Modified zod version in apps/supervisor, webapp, and various internal packages.
- Updated zod references in pnpm-lock.yaml to reflect the new version.
- Ensure dependencies that rely on zod are using the updated version to avoid mismatches.

* Add changeset
2025-08-06 14:48:43 +01:00
Eric Allam 8eecc7e548 chore: json schema missing changeset (#2353) 2025-08-06 13:56:57 +01:00
Eric Allam 1294076484 feat: index json schemas on tasks and schemaTask (#2351)
* Add payload schema handling for task indexing

This change introduces support for handling payload schemas during task indexing. By incorporating the `payloadSchema` attribute into various components, we ensure that each task's payload structure is clearly defined and can be validated before processing.

- Updated the TaskManifest and task metadata structures to include an optional `payloadSchema` attribute. This addition allows for more robust validation and handling of task payloads.
- Enhanced several core modules to export and utilize the new `getSchemaToJsonSchema` function, providing easier conversion of schema types to JSON schemas.
- Modified the database schema to store the `payloadSchema` attribute, ensuring that the payload schema information is persisted.
- The change helps in maintaining consistency in data handling and improves the integrity of task data across the application.

* Refactor: Remove getSchemaToJsonSchema in favor of schemaToJsonSchema

The `getSchemaToJsonSchema` function was removed and replaced with `schemaToJsonSchema` across the codebase. This update introduces a new `@trigger.dev/schema-to-json` package to handle conversions of schema validation libraries to JSON Schema format, centralizing the functionality and improving maintainability.

- Removed `getSchemaToJsonSchema` exports and references.
- Added new schema conversion utility `@trigger.dev/schema-to-json`.
- Updated `trigger-sdk` package to utilize `schemaToJsonSchema` for payloads.
- Extensive testing coverage included to ensure conversion accuracy across various schema libraries including Zod, Yup, ArkType, Effect, and TypeBox.
- The update ensures consistent and reliable schema conversions, facilitating future enhancements and supporting additional schema libraries.

* Add support for Zod 4 in schema-to-json

This change enhances the schema-to-json package by adding support for Zod version 4, which introduces the native `toJsonSchema` method. This method facilitates a direct conversion of Zod schemas to JSON Schema format, improving performance and reducing reliance on the `zod-to-json-schema` library.

- Updated README to reflect Zod 4 support with native method and retained support for Zod 3 via existing library.
- Modified package.json to allow installation of both Zod 3 and 4 versions.
- Implemented handling for Zod 4 schemas in `src/index.ts` using their native method.
- Added a test case to verify the proper conversion of Zod 4 schemas to JSON Schema.
- Included a script for updating the package version based on the root package.json.
- Introduced a specific TypeScript config for source files.

* Revise schema-to-json for bundle safety and tests

The package @trigger.dev/schema-to-json has been revised to ensure bundle safety by removing direct dependencies on schema libraries such as Zod, Yup, and Effect. This change minimizes bundle size and enhances tree-shaking by allowing external conversion libraries to be utilized only at runtime if necessary. As a result, the README was updated to reflect this usage pattern.

- Introduced `initializeSchemaConverters` function to load necessary conversion libraries at runtime, keeping the base package slim.
- Adjusted test suite to initialize converters before tests, ensuring accurate testing of schema conversion capabilities.
- Updated `schemaToJsonSchema` function to dynamically check for availability of conversion libraries, improving flexibility without increasing the package size.
- Added configuration files for Vitest to support the new testing framework, reflecting the transition from previous test setups.

These enhancements ensure that only the schema libraries actively used in an application are bundled, optimizing performance and resource usage.

* Refine JSON Schema typing across packages

The changes introduce stricter typing for JSON Schema-related definitions, specifically replacing vague types with more precise ones, such as using `z.record(z.unknown())` instead of `z.any()` and `Record<string, unknown>` in place of `any`. This is part of an effort to better align with common practices and improve type safety in the packages.

- Updated the `payloadSchema` in several files to use `z.record(z.unknown())`, enhancing the type strictness and consistency with JSON Schema Draft 7 recommendations.
- Added `@types/json-schema` as a dependency, utilizing its definitions for improved type clarity and adherence to best practices in TypeScript.
- Modified various comments to explicitly mention JSON Schema Draft 7, ensuring developers are aware of the JSON Schema version being implemented.
- These adjustments are informed by research into how popular libraries and tools handle JSON Schema typing, aiming to integrate best practices for improved maintainability and interoperability.

* Add JSON Schema examples using various libraries

The change introduces extensive examples of using JSON Schemas in the 'references/hello-world' project within the 'trigger.dev' repository. These examples utilize libraries like Zod, Yup, and TypeBox for JSON Schema conversion and validation. The new examples demonstrate different use cases, including automatic conversion with schemaTask, manual schema provision, and schema conversion at build time. We also updated the dependencies in 'package.json' to include the necessary libraries for schema conversion and validation.

- Included examples of processing tasks with JSON Schema using libraries such as Zod, Yup, TypeBox, and ArkType.
- Showcased schema conversion techniques and type-safe JSON Schema creation.
- Updated 'package.json' to ensure all necessary dependencies for schema operations are available.
- Created illustrative scripts that cover task management from user processing to complex schema implementations.

* Refactor SDK to encapsulate schema-to-json package

The previous implementation required users to directly import and initialize functions from the `@trigger.dev/schema-to-json` package, which was not the intended user experience. This change refactors the SDK so that all necessary functions and types from `@trigger.dev/schema-to-json` are encapsulated within the `@trigger.dev/*` packages.

- The examples in `usage.ts` have been updated to clearly mark `@trigger.dev/schema-to-json` as an internal-only package.
- Re-export JSON Schema types and conversions in the SDK to improve developer experience (DX).
- Removed unnecessary direct dependencies on `@trigger.dev/schema-to-json` from user-facing code, ensuring initialization and conversion logic is handled internally.
- Replaced instances where users were required to manually perform schema conversions with automatic handling within the SDK for simplification and better maintainability.

* Add JSONSchema type for payloadSchema in tasks

The change was necessary to improve type safety by using a proper JSONSchema type definition instead of a generic Record<string, unknown>. This enhances the developer experience and ensures that task payloads conform to the JSON Schema Draft 7 specification. The JSONSchema type is now re-exported from the SDK for user convenience, hiding internal complexity and maintaining a seamless developer experience.

- Added JSONSchema type based on Draft 7 specification
- Updated task metadata and options to use JSONSchema type
- Hid internal schema conversion logic from users by re-exporting types from SDK
- Improved bundle safety and dependency management

* Add JSON schema testing and revert package dependencies

This commit introduces a comprehensive set of JSON schema testing within the monorepo, specifically adding a new test project in `references/json-schema-test`. This includes a variety of schema definitions and tasks utilizing multiple validation libraries to ensure robust type-checking and runtime validation.

Additionally, the dependency versions for `@effect/schema` have been adjusted from `^0.76.5` to `^0.75.5` to maintain compatibility across the project components. This ensures consistent behavior and compatibility with existing code bases without introducing breaking changes or unexpected behavior due to version discrepancies.

Key updates include:
- Added new test project with extensive schema validation tests.
- Ensured type safety across various task implementations.
- Reverted dependency versions to ensure compatibility.
- Created multiple schema tasks using libraries like Zod, Yup, and others for thorough testing.

* Refactor JSON Schema test files for clarity

Whitespace and formatting changes were applied across the `json-schema-test` reference project to enhance code readability and cohesion. This included removing unnecessary trailing spaces and ensuring consistent indentation patterns, which improves maintainability and readability by following the project's code style guidelines.

- Renamed JSONSchema type annotations to adhere to TypeScript conventions, ensuring that all schema definitions properly satisfy the JSONSchema interface.
- Restructured some object declarations for improved clarity, especially within complex schema definitions.
- These adjustments are crucial for better future maintainability, reducing potential developer errors when interacting with these test schemas.

* Fixed some stuff

* WIP

* we now convert schema to jsonSchema on the CLI side via the indexing

* Remove the json-schema-test reference project

* Improve schema-to-json peer deps and fix effect schema

* Explain the casting and match the version numbers

* Fixed a bunch more schema stuff

* Don't clean files that might be written to

* Don't use a custom version of vitest in the new package

* fix attw in schema-to-json
2025-08-06 13:44:56 +01:00
nicktrn f82a4e9651 fix(playwright): improve chrome installation and fix spinner duplication on narrow terminals (#2347)
* headless: false will now install binaries for headless mode too

* fix spinner message duplication on narrow terminals

* add changeset
2025-08-06 12:08:33 +02:00
Eric Allam 1f4434035e latest @opentelemetry packages and correlate external traces (#2334) 2025-08-06 08:10:46 +01:00
Dan 7bb88451be Sidebar fix (#2349)
* Commented out tooltip style

* Deleted stylesheet
2025-08-05 11:08:44 +01:00
James Ritchie be70f42bec Adds a link to the reduce spend docs page from the billing alerts page (#2345)
* Adds a link to the reduce spend docs page from the billing alerts page

* Copy tweak
2025-08-04 13:22:18 +01:00
James Ritchie bb54e97806 Show text wrapping on code blocks (#2338)
* Show text wrapping on deployment code blocks

* Show textWrapping on some more CodeBlocks

* Adds missing margins to the error block
2025-08-04 13:21:30 +01:00
James Ritchie edafc71142 Explain run status on run inspector panel (#2342) 2025-08-04 13:21:03 +01:00
James Ritchie 792c97339e Force-wrap long strings in the run error callout (#2340) 2025-08-04 13:19:57 +01:00
James Ritchie 0fc234b970 Fixes incorrect icon colors (#2339) 2025-08-04 13:18:32 +01:00
James Ritchie f8126871f3 Improves large output messaging (#2341)
* Adds more information to the large payloads/outputs

* Changes the Download logs button to secondary
2025-08-04 13:18:07 +01:00
James Ritchie df0dc07678 New Task page deploy blank state (#2344)
* Adds a step by step deploy blank state to Tasks page

* Adds links to Ask AI, docs and troubleshooting
2025-08-04 13:17:06 +01:00
James Ritchie 63857b0445 Makes it clear you only get preview branches if you’re on v4 (#2343) 2025-08-04 13:13:38 +01:00
James Ritchie b985843642 Prevents long project menu titles pushing the admin buttons out of bounds (#2332) 2025-08-04 13:13:03 +01:00
Boon Kai 9ecda816dc fix(cli): improve contrast for chalkWorker yellow in light mode (#2239)
* fix(cli-output): improve color contrast for chalkWorker on light mode

* add changeset

---------

Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-08-04 12:09:38 +01:00
nicktrn 7b54c3527e fix(otel): prevent infinite retry loops on unicode hex escape errors (#2337)
* prevent infinite retry loop for unicode errors

* structured logs for prisma events

* preserve all prisma event fields

* either use structured logs or stdout, never both

* split runs repo tests

* decrease test shards to 8
2025-08-02 16:54:11 +01:00
nicktrn 60b8c76adc fix(hosting): pass registry namespace env var to webapp, bump helm (#2336)
* pass deploy registry namespace to webapp

* bump helm chart and images
2025-08-02 14:20:55 +01:00
Eric Allam 3fd8ea80da fix: backwards compatible snapshot runStatus to prevent DEQUEUED status from breaking older runners (#2335)
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 3s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
2025-08-01 17:19:58 +01:00
Matt Aitken c576e98dbc Fix v4 changelog latest date (#2333) 2025-08-01 15:23:55 +01:00
Matt Aitken b9e62139ff v4 docs upgrade changelog (#2331) 2025-08-01 14:17:40 +01:00
github-actions[bot] 44af80e055 Release v4.0.0-v4-beta.26
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 4s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
* chore: Update version for release (v4-beta)

* Release v4.0.0-v4-beta.26

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matt Aitken <matt@mattaitken.com>
2025-08-01 12:48:08 +01:00
James Ritchie 1feabd732e Docs: Adds a Reduce your spend docs page (#2330) 2025-08-01 09:20:10 +01:00
Eric Allam 134942b2dd The schedule HTTP API now accepts deduplicationKeys as well as schedule IDs in the URL (#2329) 2025-07-31 14:12:31 +01:00
Eric Allam b153324cd9 fix: importing from runEngine/index.js breaks non-node runtimes (#2328) 2025-07-31 13:22:02 +01:00
James Ritchie 59bfce86db Docs: Fixes incorrect concurrency pricing on the limits page (#2324) 2025-07-31 12:07:42 +01:00
Eric Allam 748565c9db Fix backwards compatible execution by allowing additional properties to passthrough (#2327) 2025-07-31 11:14:46 +01:00
Matt Aitken 8b31871998 Usage billing alerts (#2323)
* First draft billing alerts page

* Budget alert form working

* Don't let free plan users change the billing alert amount

* Fix missing key in map in the form

* Disable queues/org from admin API endpoint

* Don't allow resuming if runsEnabled is false

* Refer to "Billing alerts" not "Plans"

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Form missing dependencies fix

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Deal with thrown errors, fix for duplicating email fields

* Added a RuntimeEnvironment organizationId index

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-07-30 13:48:02 +01:00
Eric Allam 14dcc76f93 feat: run.ctx tidying and additions (#2322)
* Cleanup context and execution creation, cache stuff, add parent and root task run ids

* more efficient by using friendly IDs instead of doing joins

* metadata.root/parent now reference current run when run has no root/parent

* Adding changeset

* try to make test less flaky

* Clean imports

* Another attempt to fix the flaky test

* Fix usage by still passing durationMs and costInCents to the execution, just not the run.ctx
2025-07-30 13:47:12 +01:00
Nicolas Rigaudière 5ea6605ec6 feat(extensions): add lightpanda (#2192)
* feat: add lightpanda structure

* chore: add lightpanda doc links

* fix: lightpanda extension instructions

* feat: add Lightpanda guide and examples

* feat: lightpanda - add 3rd example

* feat: add lightpandaTask

* fix: lightpanda 3rd example

* fix: lightpanda 1st example

* chore: add changeset

* add v4 tag to guide

* fix: merge lightpanda docker instructions

* fix: add failsafes

* add scrape warning

* lint

* successful login also switches to that profile

* update docs and links as this is v4 only

* extension tweaks

* simplify extension

* update examples

* update docs

* remove from extensions list as v4 only

* remove from catalog

* update changeset

---------

Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-07-28 18:38:13 +01:00
nicktrn 3e1cc69db9 feat(ecr): make assume role optional (#2321) 2025-07-28 14:47:30 +01:00
nicktrn 2ea52da628 fix(runner): disable warm starts after SIGTERM (#2316)
* security: bump form-data to latest patch versions (CVE-2025-7783)

* disable warm starts on sigterm

* add changeset
2025-07-28 11:29:49 +01:00
Saadi Myftija 3493b9464f Cancel readonly ClickHouse queries on client close (#2319) 2025-07-28 11:00:35 +01:00
Eric Allam a7ff6de388 fix: otel logs better DynamicFlushScheduler (#2318)
* Improve dynamic flush scheduler for otel data

The changes introduce a more flexible and adaptive dynamic flush scheduler to address production issues where the system wasn't flushing data fast enough, causing memory growth and crashes. This issue arises from the existing scheduler handling only a single flush at a time, limiting concurrency and failing to cope with the influx of logs.

- Added configuration options for setting minimum and maximum concurrency levels, maximum batch size, and memory pressure threshold. These parameters ensure that flush operations adjust dynamically based on workload and pressure.
- Implemented `pLimit` to facilitate concurrent flush operations, with adjustments made according to batch queue length and memory pressure.
- Metrics reporting improvements were added to monitor the dynamic behavior of the flush scheduler, aiding in identifying performance issues and optimizing the operation accordingly.

* Implement load shedding for TaskEvent records

This change introduces load shedding mechanisms to manage TaskEvent
records, particularly those of kind LOG, when the system experiences
high volumes and is unable to flush to the database in a timely
manner. The addition aims to prevent overwhelming the system and
ensure critical tasks are prioritized.

- Added configuration options for `loadSheddingThreshold` and
  `loadSheddingEnabled` in multiple modules to activate load shedding.
- Introduced `isDroppableEvent` function to allow specific events to
  be dropped when load shedding is enabled.
- Ensured metrics are updated to reflect dropped events and load
  shedding status, providing visibility into system performance
during high load conditions.
- Updated loggers to inform about load shedding state changes,
  ensuring timely awareness of load management activities.

* Fix undefined 'queuePressure' variable in DynamicFlushScheduler

The 'queuePressure' variable was being used without being defined
in the DynamicFlushScheduler class, causing potential runtime
errors. This commit adds the missing definition and ensures that
the variable is correctly calculated based on the 'totalQueuedItems'
and 'memoryPressureThreshold'.

- Addressed code inconsistencies and improved formatting.
- Defined 'queuePressure' in the 'adjustConcurrency' method
  to prevent potential undefined errors.
- Enhanced readability by maintaining consistent spacing and
  format across the file, contributing to the stability and
  maintainability of the code.
- Adjusted batch size logic based on the newly defined 'queuePressure'
  variable.

* Refactor concurrency adjustment logic in scheduler

The concurrency adjustment logic in the dynamic flush scheduler has been refactored to improve clarity and maintainability. This change moves the calculation of pressure metrics outside of the conditional blocks to ensure they are always determined prior to decision-making.

- The queue pressure and time since last flush calculations were moved up in the code to be independent of the 'backOff' condition.
- This refactor sets up the groundwork for more reliable concurrency scaling and better performance monitoring capabilities. The overall logic of adjusting concurrency based on system pressure metrics remains unchanged.

This adjustment addresses ongoing issues with the scheduler that were not resolved by previous changes.

* Some tweaks
2025-07-26 11:06:56 +01:00
Eric Allam 0d136a3e0c fix runs.retrieve when the payload or output has unstringifiable JSON (#2315) 2025-07-25 12:00:05 +01:00
nicktrn c8165ccd44 security: bump form-data to latest patch versions (CVE-2025-7783) (#2314) 2025-07-24 17:44:19 +01:00
Eric Allam 00cc07dad3 Ignore queryRoute() call aborted errors (#2313) 2025-07-24 16:22:21 +01:00
Eric Allam 71693eb9b3 stop double reporting errors to sentry (#2312) 2025-07-24 16:02:26 +01:00
Eric Allam fb59bfd8f8 sentry: remove node native integration because it breaks (#2311) 2025-07-24 15:37:06 +01:00
Matt Aitken 038ee75c28 Queue "View runs" buttons turn off root only (#2310) 2025-07-24 15:26:56 +01:00
Eric Allam 09d0e80804 Add sentry error reporting (#2309)
* Sentry WIP

* Configure sentry for uploading and releasing during the publish webapp step

* Delete source maps after uploading

* Forward logger.error calls to sentry through Logger.onError

* Couple tweaks to the dockerfile
2025-07-24 15:09:50 +01:00
Saadi Myftija 74808d7400 Pre-merge and pre-sort run batches before sending to clickhouse (#2308)
* Premerge run batch before sending it to clickhouse

* Pre-order batch items before sending to clickhouse in favor of performance

* existing

* Emit event on batch flushes

* When merging batches, keep the last occurrence items with the same version

* Add a couple of tests
2025-07-24 14:17:26 +01:00
Matt Aitken 6791328a94 Queues dashboard update (burst concurrency) (#2293)
* Initial burst changes to queue page

* Added tooltip and changed wording around

* View runs from Queues page

* Fix for ugly Version filter "Current" badge
2025-07-24 10:17:54 +01:00
Eric Allam 3dce1f66f7 docs: beta.25 changelog entry (#2306) 2025-07-24 09:38:24 +01:00
github-actions[bot] 17bb0c0cef Release v4.0.0-v4-beta.25
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 3s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
* chore: Update version for release (v4-beta)

* Release v4.0.0-v4-beta.25

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <eallam@icloud.com>
2025-07-23 20:22:33 +01:00
Eric Allam ef59a62368 Ability to perform bulk run backfills (#2304)
* Ability to perform bulk run backfills

* Fix tests

* Allow controlling the delay interval when creating the batch
2025-07-23 20:12:35 +01:00
Eric Allam b447a8040f Use sync insert strategy since we are already batching client-side (#2303) 2025-07-23 17:17:13 +01:00
Matt Aitken ed86b4f5db Run repository test fix (#2302)
The normal database needs to be mocked because an import somewhere is 
using it which causes issues with the test container dbs and hanging at 
the end. 

Strategy copied from the trigger test file.
2025-07-23 17:10:20 +01:00
Matt Aitken 9b0eb64035 Fallback from ClickHouse to Postgres (#2300)
* Set the default replication concurrency to 2 for self-hosters

100 was a bit crazy

* Made the run repository an interface, deferring just to CH for now

* Added run repository feature flag, allowing passing a default when getting a flag

* Switch run repository using a feature flag

* Added spans

* Pass the default repository in, so we can try Postgres in the tests

* Fallback to Postgres if ClickHouse errors

* Update feature flags API endpoint
2025-07-23 16:30:30 +01:00
Eric Allam c927fbc8e4 Gracefully shutdown task run processes (#2299)
* Gracefully shutdown task run processes

* better log, thanks coderabbit
2025-07-23 16:11:26 +01:00
Matt Aitken bf4fff9cca The tasks page shows an error rather than breaking the entire page (#2297) 2025-07-23 12:28:06 +01:00
Saadi Myftija ad1672d95f Fail gracefully when runs cannot be loaded (#2296) 2025-07-23 11:21:54 +01:00
Eric Allam 6df7eb2bb5 docs: new release concurrency system and run statuses (#2287)
* WIP new docs for the new release concurrency and run statuses

* Fixed status description

* Add the beta.24 changelog entry
2025-07-22 11:30:28 +01:00
github-actions[bot] 36ced50c04 Release 4.0.0-v4-beta.24
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.24

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <eallam@icloud.com>
2025-07-22 10:42:59 +01:00
Eric Allam 684e02c8c8 fix: prevent large root/parent metadata updates from endlessly retrying (#2290)
* fixing metadata WIP

* WIP

* fix: prevent large root/parent metadata updates from endlessly retrying

* Fixed other calls to handleMetadataPacket
2025-07-21 23:04:44 +01:00
Matt Aitken 4b9f33082e AI run filtering (#2285)
* Queue in run table and filtering

* Debounce the filter changes

* Remove console log

* Added machine filtering

* Added version filtering

* Filter by version in the db

* Removed duplicate classes

* Version filtering hasFilters consistency

* Added queues and machines to the bulk action summary

* runs.list filtering for queue and machine

* Fix for machine errors

* Input field now has accessory instead of shortcut

* First experiments with the UI

* Got the fake filtering working

* AI filtering is working pretty well 

* Started working on tool calling

* Tool calling is working

* Styling progress

* Working on the error

* Errors work, improved the styling

* Nice glow effect

* Tweak the darkness of the text field

* Re-ordered the UI, set AI settings to use system prompt and telemetry

* Refactored to make it testable

* Added basic evals

* Better time inputs and evals

* Removed some code comments

* Remove unused useSearchParam change

* Tidy imports

* If no OpenAI API key send json back

* Fix for merge conflict with duplicate query filters

* Another conflict resolved

* Another merge conflict resolved

* Pass the model in, allow changing it
2025-07-21 17:53:43 +01:00
Matt Aitken a90b73c7ca Filter runs by queue, machine, version (#2277)
* Queue in run table and filtering

* Debounce the filter changes

* Remove console log

* Added machine filtering

* Added version filtering

* Filter by version in the db

* Removed duplicate classes

* Version filtering hasFilters consistency

* Added queues and machines to the bulk action summary

* runs.list filtering for queue and machine

* Fix for machine errors
2025-07-21 16:21:46 +01:00
Eric Allam ff018718f7 Added experimental_devProcessCwdInBuildDir config option (#2269)
* Added experimental_devProcessCwdInBuildDir config option

Added experimental_devProcessCwdInBuildDir config option to opt-in to new process.cwd behavior when executing tasks in the dev CLI. Currently process.cwd maps to the "root" of your trigger.dev project (the directory that contains your trigger.config.ts file). Setting experimental_devProcessCwdInBuildDir to true changes process.cwd to instead be the temporary build directory inside of the .trigger directory.

This makes it so the files added via the additionalFiles extension can be read using the same path in dev and deployed tasks.

* Remove claude code reference because it breaks windows tests 😡
2025-07-21 16:06:25 +01:00
Eric Allam 07980f8ebd fix: allow updating run metadata up to 1 hour after completion (#2288) 2025-07-21 16:05:29 +01:00
Eric Allam 8d5c86fea0 v4: simplified release concurrency system and status changes (#2284)
* WIP

* Make release concurrency system extremely simple, everything just releases all the time

* update the deadlock detection to use the new lockedQueueReleaseConcurrencyOnWaitpoint column

* WIP new release concurrency system

* Remove releaseConcurrency and releaseConcurrencyOnWaitpoint

Also removed deadlock detection, and added environment burst concurrency

* Added new DEQUEUED status

Cleaned up the API run statuses, including now detecting new clients and not breaking older clients by adding an API version header to all requests

* Introduce the new "current dequeued concurrency set"

* Remove QUEUED_EXECUTING because we no longer "eagerly" release before checkpointing

* Remove waitpoint test for QUEUED_EXECUTING

* Add isWaiting

* Add changeset

* Use createdAt for ordering realtime runs instead of number

* Clarify the envCurrentDequeuedKey usage

* mock the db.server file to fix the tests

* Updated changset "EXECUTED" -> "EXECUTING"

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2025-07-21 15:45:27 +01:00
Eric Allam a9b0b4f7c9 Add beta.23 changelog entry (#2286) 2025-07-21 14:34:59 +01:00
nicktrn 4dee2c360e fix(helm): allow electric db url var to be set from secret (#2282)
* correctly use db url from secret for electric

* bump app and chart version

* bump electric version
2025-07-21 13:57:23 +01:00
James Ritchie 4565f19d3a Copyable admin area table fields and autofocus search (#2280) 2025-07-18 18:48:56 +01:00
github-actions[bot] 0796df2aa9 Release 4.0.0-v4-beta.23
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 3s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
* Flatten undefined properties correctly (#2276)

* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.23

---------

Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matt Aitken <matt@mattaitken.com>
2025-07-18 11:53:43 +01:00
Eric Allam 6bf580ac21 Flatten undefined properties correctly (#2276) 2025-07-17 18:15:57 +01:00
James Ritchie 3ad4b8b32d Add machine to run list (#2275)
* Access machinePreset from the run list presenter

* New icons for machine presets

* New icon + name combo label for the machine preset

* Adds new “Machine” column to the runs list

* Make a separate component for the machine tooltip info

* add machinePreset to the span presenter

* Show the Machine in the Details tab in the Run inspector

* Show an admin only separator

* Fix docs icon in the button

* Small padding tweak

* Move the Machine nearer the costs

* Don't cast the machine preset

* Remove typecast, better to have a bad label if we add a new machine and don't update thos

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2025-07-17 14:26:52 +01:00
Dan f685c6637d Added Mastra + Trigger example (#2278)
* Added mastra agent docs

* Added links in the ai agents section

* Caught typos all thanks to coderabbit. Thanks coderabbit
2025-07-17 13:58:59 +01:00
Dan 1dbcf661f3 Added openai agents sdk for typescript playground docs (#2194)
* Added openai agents sdk typescript playground docs and updated guardrails

* Removed broken link and import

* Typo fix
2025-07-17 13:39:18 +01:00
Matt Aitken 6f6852621d Bundle p-map (#2274) 2025-07-16 16:36:36 +01:00
nicktrn aa3a56a85d fix(docker): apply max old space size env var to webapp (#2273) 2025-07-16 16:36:05 +01:00
Matt Aitken 5e999c8992 Use p-map to speed up bulk actions (#2272) 2025-07-16 15:52:42 +01:00
Matt Aitken 569cecb675 The email counts should come from the completed bulk action… not this iteration (#2271) 2025-07-16 13:46:48 +01:00
Saadi Myftija c0b6c41afc Disable payload editing for run replays with large payloads (#2268)
* Use sexy scrollbars for templates and recent runs popover content

@Nick this is for you!!1

* Fix TabButton component disabled state

* Disable payload tab when replaying runs with large payloads
2025-07-15 21:54:43 +01:00
Matt Aitken 35c7a1ecb0 Bulk action 2 fixes (#2267)
* Fix for filtering by run id

Simplified to have a single filter for runId which accepts an array. This unifies the filtering by multiple runs (used by the waitpoint page) and the individual run filtering. It fixes a bug with bulk actions

* Truncate long bulk action titles
2025-07-15 14:43:19 +01:00
Saadi Myftija a64875a297 fix: regression affecting replayed runs with superjson payloads (#2266)
* Fix regression that broke superjson behavior for the replay flow

* Ignore undefined type metadata when overriding superjson payloads

Addresses https://github.com/triggerdotdev/trigger.dev/issues/1968

* Add a few unit tests for replaceSuperJsonPayload
2025-07-15 12:30:33 +01:00
Matthieu Mordrel 8690878a86 Updated generatedCopy to generatedCopy.text (#2247)
I believe the generatedCopy is the object that the AI SDK returns and we want to pass the text of the object rather in our template literal.
2025-07-14 15:58:55 +01:00
Saadi Myftija b78b3dceb2 feat: link the original run from replayed runs (#2262)
* Add ID of the replayedFrom run to the TaskRun schema

* Propagate the replayedFrom run ID in the replay flow

* Link the replayed run in the run details pane
2025-07-14 15:57:54 +01:00
Matt Aitken 630e9556b0 Bulk actions 2.0 (and switch all run listing to ClickHouse) (#2264)
* useSearchParams has

* useSearchParams has

* useSearchParams has

* Consistent way to get the run filters

* Consistent way to get the run filters

* Consistent way to get the run filters

* Initial work on the new bulk actions

* Initial work on the new bulk actions

* Initial work on the new bulk actions

* WIP actions and filtering

* WIP actions and filtering

* WIP actions and filtering

* Empty filter arrays are set to undefined

* Empty filter arrays are set to undefined

* Empty filter arrays are set to undefined

* WIP prisma schema

Removed extra runtimeEnvironmentId

* WIP prisma schema

Removed extra runtimeEnvironmentId

* WIP prisma schema

Removed extra runtimeEnvironmentId

* Migrations

* Migrations

* Migrations

* BulkActionGroup changed some columns around

* BulkActionGroup changed some columns around

* BulkActionGroup changed some columns around

* New badge variant, removed unused ones

* New badge variant, removed unused ones

* New badge variant, removed unused ones

* Bulk action button

* Bulk action button

* Bulk action button

* Make the next runs page the default now

* Make the next runs page the default now

* Make the next runs page the default now

* Improved the RadioButton style

* Improved the RadioButton style

* Improved the RadioButton style

* Remove the old bulk action bar

* Remove the old bulk action bar

* Remove the old bulk action bar

* More UI progress

* More UI progress

* More UI progress

* Lots of UI changes to the Runs page

* Lots of UI changes to the Runs page

* Lots of UI changes to the Runs page

* Fixed period filter resetting everything

* Fixed period filter resetting everything

* Fixed period filter resetting everything

* Improved the Switch secondary style

* Improved the Switch secondary style

* Improved the Switch secondary style

* Buggy filter fixes

* Buggy filter fixes

* Buggy filter fixes

* Improved the filter display and fixed a bug with search param from object

* Improved the filter display and fixed a bug with search param from object

* Improved the filter display and fixed a bug with search param from object

* Clear button is minimal

* Clear button is minimal

* Clear button is minimal

* Using a presenter now

* Using a presenter now

* Using a presenter now

* Bulk actions are created, but not actually processed (yet)

* Bulk actions are created, but not actually processed (yet)

* Bulk actions are created, but not actually processed (yet)

* Bulk replay/cancel is working

* Bulk replay/cancel is working

* Bulk replay/cancel is working

* Multiple fixes, added bulk column to PG

* Multiple fixes, added bulk column to PG

* Multiple fixes, added bulk column to PG

* Bulk action run filtering working using CH

* Bulk action run filtering working using CH

* Bulk action run filtering working using CH

* Replay setting the bulk id on the runs

* Replay setting the bulk id on the runs

* Replay setting the bulk id on the runs

* Properly cap the time when doing a bulk action

* Properly cap the time when doing a bulk action

* Properly cap the time when doing a bulk action

* If the bulk action isn't recent, add it to the dropdown anyway

* If the bulk action isn't recent, add it to the dropdown anyway

* If the bulk action isn't recent, add it to the dropdown anyway

* Blank version of the bulk actions page

* Blank version of the bulk actions page

* Blank version of the bulk actions page

* Individually selected runs working

* Individually selected runs working

* Individually selected runs working

* Use selected mode if runs are checked

* Use selected mode if runs are checked

* Use selected mode if runs are checked

* Added the modal

* Added the modal

* Added the modal

* Marked the old bulk actions stuff as deprecated

* Marked the old bulk actions stuff as deprecated

* Marked the old bulk actions stuff as deprecated

* Renamed bulk action file

* Renamed bulk action file

* Renamed bulk action file

* Bulk run filter with the name and a default

* Bulk run filter with the name and a default

* Bulk run filter with the name and a default

* WIP on bulk actions page

* WIP on bulk actions page

* WIP on bulk actions page

* Updated panel, added new truncated id component

* Updated panel, added new truncated id component

* Updated panel, added new truncated id component

* Style improvements to the radio buttons

* Style improvements to the radio buttons

* Style improvements to the radio buttons

* Added an option action completion email

* Added an option action completion email

* Added an option action completion email

* Adds a blank state for the bulk actions page

* Adds a blank state for the bulk actions page

* Adds a blank state for the bulk actions page

* Nicer completed email

* Nicer completed email

* Nicer completed email

* Don't open the bulk action panel if there are no runs

* Don't open the bulk action panel if there are no runs

* Don't open the bulk action panel if there are no runs

* Runs blank state and bulk action accordion

* Runs blank state and bulk action accordion

* Runs blank state and bulk action accordion

* Updates secondary/small switch style

* Updates secondary/small switch style

* Updates secondary/small switch style

* Pagination buttons no longer split in twain (WIP)

* Pagination buttons no longer split in twain (WIP)

* Pagination buttons no longer split in twain (WIP)

* Aborting working

* Aborting working

* Aborting working

* Bulk action live reloading

* Bulk action live reloading

* Bulk action live reloading

* ListPagination works correctly in all states

* ListPagination works correctly in all states

* ListPagination works correctly in all states

* Run page, show friendlyId instead of number

* Run page, show friendlyId instead of number

* Run page, show friendlyId instead of number

* Bulk action help open by default if you have none

* Bulk action help open by default if you have none

* Bulk action help open by default if you have none

* Extra status filtering step because of replication delay

* Extra status filtering step because of replication delay

* Extra status filtering step because of replication delay

* Wider bulk action onboarding

* Wider bulk action onboarding

* Wider bulk action onboarding

* More sensible widths on the bulk action side panel

* More sensible widths on the bulk action side panel

* More sensible widths on the bulk action side panel

* Border color tweak to the RadioButton

* Border color tweak to the RadioButton

* Border color tweak to the RadioButton

* Improved the accordion component hover states

* Improved the accordion component hover states

* Improved the accordion component hover states

* Updates the bulk action blank state images to the latest UI

* Updates the bulk action blank state images to the latest UI

* Updates the bulk action blank state images to the latest UI

* Added R and C shortcuts back in

* Added R and C shortcuts back in

* Added R and C shortcuts back in

* Fix for selecting a single run

* Fix for selecting a single run

* Fix for selecting a single run

* Improved exit icon, added shortcut to modal

* Improved exit icon, added shortcut to modal

* Improved exit icon, added shortcut to modal

* Tidy imports

* Tidy imports

* Tidy imports

* Tidy imports

* Tidy imports

* Tidy imports

* Tidy imports

* Tidy imports

* Tidy imports

* Tidy imports

* Fix for grid layout when 1 page of bulk actions visible

* Fix for grid layout when 1 page of bulk actions visible

* Fix for grid layout when 1 page of bulk actions visible

* Removed the ... on the abort button

* Removed the ... on the abort button

* Removed the ... on the abort button

* Removed the ... on the abort button

* Animate the progress bar

* Set TZ="UTC" in the env example

* Filter summary in the bulk inspector

* Improves the pagination styling

* Improves the pagination styling

* Delete old bulk action routes

* Removed old Postgres RunListPresenter

* Retry any replication error where the message contains "timeout"

* Increase wait to make test less flaky

* The test was using run id instead of friendly id

* Safer array access

* Remove error log if there's a bad status

* Nicer frontend type safety with the bulk action and mode

* Switched a log to a debug log

* Retry replication unless the error is a known non-retry error

Flip the strategy to retry by default

* Make ClickHouse required

* Backfill run replication admin API endpoint

* Set a CLICKHOUSE_URL for unit tests

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2025-07-14 15:50:01 +01:00
Eric Allam 6db1b71202 fix: prevent stuck batchTriggerAndWait by finalizing runs when they are cancelled (#2265) 2025-07-14 14:29:14 +01:00
Eric Allam 70b4b1257e fix: Logging large objects is now much more performant and uses less memory (#2263)
* Logging large objects performance fixes

* Add changeset

* docs: new otel attribute count defaults

* Scope the switch/case statement with braces

* Add tests for nested map and sets

---------

Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-07-14 13:16:04 +01:00
Saadi Myftija 87c21ab50a feat: enable overriding run options when replaying (#2260)
* Rearrange the layout of the replay modal

* Add run options to the replay modal

* Handle payload and metadata correctly in the shared json editor

* Apply run options in replays

* Fix clear button issue in json editor

Memoization of the clear function caused some problems. Removing it should not cause performance issues.

* Update replay modal hint

* Move machine and version fields to the top for visibility

* Use the same field ordering in the test page

* Reload queues and versions on env override

* Adapt json editor to fill full height

* Clean up a few excessive ternaries

* Avoid ui jump on env selection

* Switch to sexy scrollbars for scheduled tasks in the test page
2025-07-11 16:54:20 +02:00
Matt Aitken 4c635f72a2 Fixed queues SSE live reloading (#2259) 2025-07-11 12:53:28 +01:00
Eric Allam 46dad7dc76 fix: prevent processKeepAlive OOM error process reuse (#2261)
* Improve TaskRunProcess health detection so we don't try and reuse an unhealthy process

This was happening after the process was killed internally, like by an OOM error

* Add changeset
2025-07-11 10:50:05 +01:00
nicktrn 4fdf23b38b fix(deploy): fail in CI with descriptive message and instructions if no access token set (#2258)
* don't try interactive login in ci, link to docs

* add ci note to cli deploy docs

* add ci note to github actions

* add changeset

* make cron test less strict
2025-07-10 17:28:12 +01:00
nicktrn 0c71dc74df feat: add node 22 and bun runtime support with version display (#2254)
* update node-22 image

* update bun image

* disable io_uring

* fix fallback bun path

* prevent duplicate warnings

* add runtime and version to deployments

* runtime icons

* fallback to nodejs

* prevent empty table cell menu

* log if local build on deploy

* pass io_uring env var to child

* denormalize runtime and version, display on run details

* add changesets

* disable pr checks for changeset commits..

* add runtime data to deployed bg workers
2025-07-10 16:43:10 +01:00
Eric Allam 6ff0b923e1 New internal idempotency implementation for trigger and batch trigger (#2256)
* Introduce request idempotency to prevent duplicate triggers

* Implement request idempotency on trigger

* Use x-trigger-request-idempotency-key header instead

Plus cleanup shared logic in the routes

* Add changeset

* Oops, lets not hardcode a 408

* A couple of improvements
2025-07-10 16:42:32 +01:00
nicktrn 1a64013825 fix(helm): external config and secret support (#2245)
* fix postgres and redis external config, incl redis tls

* external secret support for postgres, redis, clickhouse, plus fixes

* s3: full existing secret support, external fixes

* bump chart version

* add subchart links

* update external config docs

* tidy up validation and helper
2025-07-10 10:08:00 +02:00
nicktrn f456f68f88 fix(docs): force latest buildx version in sample gh action (#2252) 2025-07-09 19:41:02 +02:00
Saadi Myftija 28b6be2491 feat: introduce run templates for reusing test run configs (#2253)
* Add new prisma model for task run templates

* Create run templates in a new service

* Add modal to create run templates in the test page

* Show templates list and apply values when selected

* Hide template creation time in the dropdown list, only show date

* Enable deleting run templates

* Show success toast on template creation

* Validate template label length

* Improve the template creation success indicator

* Use formAction consistently to differentiate submissions

* Type formAction for better editor support

* Prettify run template payload and metadata

* Add triggerSource, concurrencyKey and ttl to run templates
2025-07-09 19:09:25 +02:00
Saadi Myftija dbcf632b4e fix: add missing field descriptions in the test page (#2251)
* Switch to sexy scrollbars in the options pane

* Add missing field descriptions

* Add a run options link to the docs

* Make the copy for the field descriptions more concise

* Fix tooltip issue in the Select component
2025-07-09 16:25:06 +02:00
Saadi Myftija 3cfde48bfd feat: expose all run options in the test run page (#2227)
* Implement a new primitive UI component for picking durations

* Implement a new component to input run tags

* Expose all run options in the test run page

* Add subtle animations when adding/removing run tags in the test page

* Add a new resource endpoint for fetching queues

* Fetch usable queues for the selected task

* Fix width display issue in the select component

* Enable locking a run to a version from the test page

* Disable entering max attemps <0

* Validate tags

* Add recent runs popover

* Only show latest version for development environments

* Update run options when selecting a recent run

* Rearrange the test page layout

* Add subtle animation to the duration picker segments on focus

* Improve queue selection dropdown styling

* Fix disabled state issue for the SelectTrigger component

* Disable version selection field for dev envs

* Add usage hints next to the run option fields

* Add machine preset to the run options list

* Allow arbitrary queue inputs for v1 engine runs

* Show truncated run ID instead of run numbers for recent runs

Run numbers will soon get deprecated due to contention issues

* Fix duplicate queue issue

* Extract common elements across the standard and scheduled test task forms

* Apply values from recent runs to scheduled tasks too

* Add additional run options for scheduled tasks

* Use a slightly smaller font size for run option labels

* Disallow commas in the run tag input field

* Switch to a custom icon for recent runs button

* Flatten the load function test task result object

* Avoid redefining machine presets, use zod schema instead

* Fix ClockRotateLeftIcon jsx issues

* Remove recent runs button tooltip as it causes nesting errors

* Adjust the page layout to make it clear which task is currently selected

* Inline the tab group with the copy/clear buttons
2025-07-09 10:40:10 +01:00
Eric Allam ba2e0cc1c6 Prevent circular references from breaking run logs in task outputs (#2249) 2025-07-09 10:28:12 +01:00
Eric Allam b113e5a99c Fix non-MFA login (#2246)
* Fix non-MFA login

* fixed typecheck errors
2025-07-08 14:59:31 +01:00
Eric Allam b119a52e08 Implement MFA (#2244)
* Adds a new route for logging in with mfa

* New path for security page

* Adds “Security” link to account side menu

* Update the Switch component to allow label positions left and right

* Optionally hide the Close button in the Dialog title bar

* Installs `qrcode` react package for generating QR codes.

* CopyButton component now takes children

* New Security route for setting up MFA

* Adds new OTP package for the chadcn InputOTP component

* Adds new InputOTP chadcn component

* Adds InputOTP chadcn component to the MFA login screen

* InputOTP component supports variant styles

* Improvements to form handling

* Show a confirmation modal before you can disable MFA

* Revert redirect back to the dashboard for now

* Implement MFA enabling and disabling

* Refactor and cleanup mfa management code

* More cleanup

* Handle errors in the management action

* Implement mfa login flow

* recovery code input should be password

* Implement rate limiting on the mfa validation endpoint

* Better error ux

* Implement mfa emails and apply James' updates

* Use latest @better-auth/utils

* Improvements via CodeRabbit review

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2025-07-08 13:44:47 +01:00
nicktrn e02c90a4ea Update self hosting images to beta.22 (#2241)
* docker: set new cli tag env var

* helm: update app and chart versions
2025-07-08 09:33:27 +01:00
Eric Allam 493ca11c43 Add ability to disable the prisma query in the healthcheck endpoint (#2242) 2025-07-07 16:41:55 +01:00
Eric Allam b36d81a622 Add v4 changelog to v4 docs (#2240)
* Add v4-beta changelog docs

* Add beta.22 changelog entry
2025-07-06 11:38:10 +01:00
Eric Allam 275ce9f290 Release 4.0.0-v4-beta.22 (#2238)
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 4s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
2025-07-04 16:15:15 +01:00
github-actions[bot] 5cff5c45e9 chore: Update version for release (v4-beta) (#2159)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-07-04 16:13:20 +01:00
Eric Allam 47e583c19d Properly scope the batch list to the selected environment (#2236)
Prevents showing batch runs from environments that are not in the selected environment
2025-07-04 14:41:10 +01:00
nicktrn 1019c9cdea Switch trigger Helm chart RBAC from cluster to namespace scope and bump version (#2232)
* replace supervisor cluster role with ns-scoped role

* fix cross-ns binding

* bump chart version
2025-07-04 13:54:25 +01:00
Eric Allam 469a8df0cf Prevent redis worker from enqueuing pending jobs (#2235) 2025-07-04 13:53:32 +01:00
Eric Allam 922c7cb3a6 Increase batch trigger processing job visibility timeout (#2234) 2025-07-04 13:43:26 +01:00
nicktrn 0fcb9705ae Document new otel limits (#2196)
* update webapp env vars

* update limits
2025-07-04 13:41:54 +01:00
nicktrn 74fdfa93c5 Show project details when running the whoami command (#2231)
* add project details to whoami

* findFirst

* skip project check if no orgs found

* add changeset
2025-07-04 13:40:41 +01:00
Eric Allam bdaa2ed15a Move batch trigger processing jobs to a dedicated redis worker (#2233) 2025-07-04 12:16:05 +01:00
nicktrn afc9a6ade1 Add ECR support for remote builds (#2224)
* create repo if doesn't exist

* fresh auth token for each deploy

* optional assume role

* log when machine overrides enabled

* make test repo namespace configurable

* assume role fix and env var changes

* improve ecr check

* improve tag parsing

* tag parsing tests

* track if repo created and fix test

* missing tryCatch for sts call
2025-07-03 14:25:30 +01:00
Eric Allam 7bb7e7aedc When sharding, use the where clause in the shard key to distribute requests more evenly (#2229) 2025-07-03 14:21:58 +01:00
Eric Allam e90235b317 fix processKeepAlive disabled performance regression (#2228)
* processKeepAlive disabled performance fix

When processKeepAlive was disabled, the eagerly created TaskRunProcess being discarded and a whole new TaskRunProcess created at execution time.

* Don't use a TaskRunProcess if it's being killed, fixes retryImmediately
2025-07-03 14:21:49 +01:00
James Ritchie b7134dd769 Docs: Adds 2 references to the node.js versions we use for v3 and v4 (#2118)
* Adds 2 snippets to reference node.js version for v3 and v4

* Updated the node versions we support

* Remove specific node version from title
2025-07-02 13:08:49 +01:00
nicktrn 6fea802505 helm: set default webapp container and add extraVolumes (#2222)
* set default webapp container

* bump version

* add webapp extraVolumes and extraVolumeMounts

* bump version
2025-07-02 13:03:02 +01:00
Eric Allam 09ef7625ff Merge pull request #2219 from triggerdotdev/metadata-serialization
Serialize metadata to prevent invalid data from breaking run completions
2025-07-02 12:49:08 +01:00
Eric Allam 5cf37e9f8a Merge pull request #2189 from triggerdotdev/increased-and-configurable-attribute-limits
Increase otel attribute limits and make them configurable
2025-07-02 12:48:38 +01:00
Eric Allam e7b6c2fab6 Merge pull request #2183 from triggerdotdev/process-keep-alive
v4: Experimental process keep alive
2025-07-02 12:39:43 +01:00
nicktrn d619e79f74 helm: increase default postgres resource preset (#2221)
* switch to small preset for postgres

* lint

* bump version
2025-07-02 11:57:14 +01:00
Eric Allam 38a94b3b70 Add changeset 2025-07-02 11:30:13 +01:00
Eric Allam 0c2af6d87c Increase otel attribute limits and make them configurable 2025-07-02 11:30:13 +01:00
Eric Allam 0deb2c640d remove change from process-keep-alive 2025-07-02 11:30:13 +01:00
Eric Allam 21c70ad673 Serialize metadata to prevent invalid data from breaking run completions 2025-07-02 11:30:13 +01:00
Eric Allam 0793c2b0f4 address some nick comments in the review 2025-07-02 11:30:13 +01:00
Eric Allam 8dc90d61b4 increase run engine test timeouts 2025-07-02 11:30:13 +01:00
Eric Allam 57f3a89a86 Fix timeline span events tests 2025-07-02 11:30:13 +01:00
Eric Allam ceb737e9f1 Fix broken webapp test 2025-07-02 11:30:13 +01:00
Eric Allam 632d6b91e9 Fix taskSlug extraction 2025-07-02 11:30:13 +01:00
Eric Allam b548561220 Remvoe the sometimes incorrect import file name 2025-07-02 11:30:13 +01:00
Eric Allam aecee4d35f Don't reset task lifecycle hooks between executions 2025-07-02 11:30:13 +01:00
Eric Allam 9ab590bead Better handle snapshot changes with the new persistent task run process,
Also don’t re-import the task file if the task is already in the resourceCatalog
2025-07-02 11:30:13 +01:00
Eric Allam 2cc1453f25 Always set the cold/warm variant on attempt spans, even in dev 2025-07-02 11:30:13 +01:00
Eric Allam 82f3db6825 Only bootstrap on the cold start execution, and record how many executions in the attempt span 2025-07-02 11:30:13 +01:00
Eric Allam f0bc4ad2bd Don't delete env vars with falsy values 2025-07-02 11:30:13 +01:00
Eric Allam 4d15c8f7cf Better reset in the prod usage manager 2025-07-02 11:30:13 +01:00
Eric Allam 7f3b1c1735 Ensure the usage interval is cleared when resetting 2025-07-02 11:30:13 +01:00
Eric Allam 707bc09dac Make sure maxExecutionsPerProcess is a positive integer 2025-07-02 11:30:13 +01:00
Eric Allam a0f2c982f9 Make sure to clear existing metadata flush timer when resetting 2025-07-02 11:30:13 +01:00
Eric Allam bffd18a6b8 Properly reset listener arrays by setting length to 0 2025-07-02 11:30:13 +01:00
Eric Allam 2018b41d22 TRIGGER -> TRIGGERDOTDEV 2025-07-02 11:30:13 +01:00
Eric Allam c41d63497b Handle immediate retries better 2025-07-02 11:30:13 +01:00
Eric Allam 56146afcb6 TaskRunProcessProvider cleanup is async 2025-07-02 11:30:13 +01:00
Eric Allam 020565c009 Handle dev process pool shutdown errors 2025-07-02 11:30:13 +01:00
Eric Allam 58d56f8381 Use hostname instead of host 2025-07-02 11:30:13 +01:00
Eric Allam 5b49b420cb Add changeset 2025-07-02 11:30:13 +01:00
Eric Allam 3fb68b784a couple of tweaks for testing stuff 2025-07-02 11:30:13 +01:00
Eric Allam a414e65efe handle env vars that have been removed between executions 2025-07-02 11:30:13 +01:00
Eric Allam 38fe854559 Make refreshing a task run process work correctly 2025-07-02 11:30:13 +01:00
Eric Allam c24f3a56cc Reset deployed run worker and also get the warm start stuff to work properly 2025-07-02 11:30:13 +01:00
Eric Allam 8798352be3 Super-warm starts in deployed tasks proof 2025-07-02 11:30:13 +01:00
Eric Allam 1a1e70ae3d WIP deployed processKeepAlive 2025-07-02 11:30:13 +01:00
Eric Allam 19bdf3b6ea scope the pool by background version, allow configuring pool params in dev/prod 2025-07-02 11:30:13 +01:00
Eric Allam 427c450391 Fixed metrics, reusing a process counts as a warm start 2025-07-02 11:30:13 +01:00
Eric Allam 9374aea401 Split resource and span attributes 2025-07-02 11:30:13 +01:00
Eric Allam fd3db5f77b Reset execution environment between runs 2025-07-02 11:30:13 +01:00
Eric Allam e2049fcfbf Initial dev process keep alive. moved resource attributes to span attributes because resource attributes are global and immutable 2025-07-02 11:30:13 +01:00
Eric Allam 1be4fcbb82 Fixes the jitter option for the scanConcurrencySets cron job (#2220) 2025-07-02 11:29:54 +01:00
Eric Allam 124435e5e7 Eliminate race conditions in continueRunIfUnblocked to prevent stuck runs (#2217)
* Eliminate race conditions in continueRunIfUnblocked to prevent stuck runs

* Use assertNever for typecheck friendliness
2025-07-01 16:34:12 +01:00
Matt Aitken 4a79b3b35b Fixed retrying on run replication inserts on connection errors (#2216) 2025-07-01 13:35:13 +01:00
Boon Kai 0da6a19987 docs: Update triggering.mdx import for triggering from inside another task (#2215)
When triggering from inside another task, `runs` and `batch` should be imported from `@trigger.dev/sdk/v3`
2025-07-01 08:03:02 +01:00
Eric Allam 08d84eb596 Fix v4 concurrency sweeper flaky test (#2213) 2025-06-30 16:37:52 +01:00
Matt Aitken f38d35e9f6 ClickHouse replication improvements (retrying, strip bad unicode chars) (#2205)
* Add retry logic for insert operations

Add a generic retry mechanism for task run and payload inserts to handle
transient connection errors. The new #insertWithRetry method retries up to
three times with exponential backoff and jitter on retryable connection
errors such as connection resets or timeouts. Errors are logged and
recorded in tracing spans to improve observability and robustness of the
replication service.

* Replication settings are configurable

* Log out the runIds for failed batches

* Detecting bad JSON in run replication and ignoring it

* Reproduced split unicode error

* Move output file

* Massively improved the performance

* Minor performance improvements

* Unskip tests

* Remove unused test in CH package

* Fix for the ClickHouse UI explorer

* RunReplication keepAlive defaults to false

* Add concurrency_key and bulk_action_group_ids to ClickHouse task runs

* ClickHouse package doesn't need to be built anymore for the webapp

* Set the concurrency_key from the run replication service
2025-06-30 16:32:02 +01:00
Eric Allam 1b4dabb8ba v4: current concurrency sweeper (#2206)
* v4: current concurrency sweeper

* Fix webapp tests

* Ensure only a single instance performs concurrency sweeping by using redis-worker cron jobs

* Improved the mark phase

* Ensure cron jobs get rescheduled even if the handler throws an error

* Better property names
2025-06-30 16:22:19 +01:00
nicktrn aa24a9aae6 Fix external registry config and other helm tweaks (#2212)
* fix both internal and external registry host

* add next steps to self-hosting overview

* separate into webapp and registry ingress

* fix external registry config check

* fix localhost registry warning

* bump chart version
2025-06-30 14:21:00 +01:00
nicktrn dc568e7f3e Self-hosting: improved worker and bucket bootstrap (#2209) 2025-06-29 10:42:52 +01:00
nicktrn fa6675eb00 Helm chart improvements (#2207)
* add helm deps

* configurablecli tag for setup commands

* enabled -> deploy

* extraEnv -> extraEnvVars

* update docs

* minio -> s3

* improve persistence config

* set cli tag to v4-beta

* chart and image bump

* fix tests

* lock chart

* workflow hotfix

* quote for niels

* make probes configurable

* fix webapp and supervisor templates

* bump chart
2025-06-28 12:59:29 +01:00
Eric Allam 8a86e7b41d Remove deprecated schedule trigger jobs when registering with the schedule engine (#2204)
* Remove deprecated schedule trigger jobs when registering with the schedule engine

* Use a tryCatch just to be absolutely sure
2025-06-27 12:32:02 +01:00
nicktrn 119bfc0068 Fix update command version detection (#2199)
* fix root package.json resolution

* add changeset
2025-06-27 10:06:36 +01:00
nicktrn 7a6d9dc225 v4 self-hosting docs updates (#2202)
* quote version strings

* Update architecture diagram to include kubernetes

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2025-06-26 16:53:10 +01:00
Eric Allam 0f3179f493 Provide realtime skipColumns option via untamperable public access tokens (#2201)
* Provide realtime skipColumns option via untamperable public access tokens

* Fixed realtime client tests

* Create red-rings-marry.md
2025-06-26 15:13:26 +01:00
Eric Allam b87e1c4630 Improve clickhouse client debug logging (#2197)
* Improve clickhouse client debug logging

* Stop hardcoding ScheduleEngineWorker log level

* Add DLQ debug log message
2025-06-26 15:12:54 +01:00
Eric Allam 14058d557f fix: queues no longer unpaused on deploy (#2198) 2025-06-26 15:08:52 +01:00
nicktrn 6535cf918b v4 helm chart and docs (#2195)
* v4 helm chart

* ignore packaged chart archives

* chart publish prep

* add helm chart release workflow

* enable draft gh release

* stateful services should be statefulsets

* expose internal otel config

* podAnnotations for all services

* postgresql.extraArgs

* postgresql -> postgres

* add clickhouse vars as extraEnv examples

* support external secrets

* improve clickhouse config

improve clickhouse config

* disable internal otel config by default

* allow nil internal config

* fix gh release permission

* fix validation step for ci

* secrets.enabled

* simplify secret keys

* bump chart version

* fix contents permission

* remove redundant print steps

* remove helm release heading

* optimise clickhouse config

* support wait-for-it.sh

* fix ch overrides

* add low-resource ch overrides to compose setup

* supervisor bootstrap config

* disable otel trace logging

* retain shared volume

* enable clickhouse for compose setup

* disable trace logging

* bump chart

* add extraManifests

* telemetry config

* add repo namespace config

* scope cluster role to namespace to support multiple installs

* external s3 config

* values tweaks

* helm docs

* bump chart

* set contents read permission

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* add object store root credentials warning

* run init containers as uid 1000

* pass ch user creds with explicit flag

* improve ingress anotation handling

* remove duplicate colume claim block

* trim htpasswd auth

* lock curl images used for tests

* add v4-beta package version warning

* make schema and sslmode configurable

* package tag info -> warning

* improve secrets config example

* update docs

* bump version

* bump webapp reqs to account for ch

* make ch creds more easily configurable

* publish ch http port

* example point at latest beta chart

* small docs tweaks

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-06-25 23:57:51 +01:00
Eric Allam aaf40c3be3 Fix "Duplicate path found during parsing JSON object" clickhouse error (#2193) 2025-06-24 14:34:32 +01:00
James Ritchie 35dedee1eb Update number of allowed tags (#2187) 2025-06-24 10:38:59 +01:00
Eric Allam 485f71c8d4 Improve schedule engine performance (#2191)
* Improve schedule engine performance

* Convert an info log to a debug log
2025-06-23 16:55:18 +01:00
nicktrn ec2175fec8 Some docs tweaks (#2190)
* add v4 tag to playwright extension

* add self-hosting architecture section

* add v4-beta tag warning
2025-06-23 10:25:07 +01:00
Eric Allam fb9abe5289 fix: Incorrect/missing logs on new schedule engine runs (#2185)
* Fix incorrect logs on new schedule engine triggered taskss

Also added the ability to recover schedules in the schedule engine via an Admin API endpoint in the new schedule engine

* Fixed schedule recovery failing test
2025-06-19 15:37:50 +01:00
Eric Allam f2db1b8aa5 Create dedicated alerts worker (#2184)
* Add a new alerts worker that just handle alerts

* fallback to graphile worker when a tx is required
2025-06-19 11:54:49 +01:00
nicktrn 3c93783e8b remove nodetype label requirement (#2182) 2025-06-18 11:34:35 +01:00
nicktrn 55f41a2168 Ensure webapp container does not fetch pnpm at runtime (#2181)
* install pnpm during build

* install pnpm for node user as well
2025-06-18 11:31:36 +01:00
Matt Aitken 4ca6506655 Delay reschedule fix (v3 & v4) (#2180)
* Fix for v3 rescheduling bug…

* v4 rescheduling working
2025-06-17 18:22:15 +01:00
Matt Aitken 9f9e74b0b6 Fix hydration error (#2179)
* Remove unused hook

* The Impersonation button was causing DOM hydration issues
2025-06-17 11:17:17 +01:00
Eric Allam ea6f66bdfc Improved schedule engine (#2174) 2025-06-17 06:48:05 +01:00
Eric Allam a42c9acf44 v4: Improved run locking (#2173) 2025-06-17 06:45:59 +01:00
nicktrn f7f8bc28c5 Docker self-hosting improvements (#2177)
* shallow clone

* fix image tag locking example

* electric should use db url env var

* add htpasswd note

* use local driver with log rotation by default

* make worker urls more easily configurable

* configure dev otel endpoint via .env

* increase min recommended worker specs

* move worker url section
2025-06-16 22:22:02 +01:00
Matt Aitken 5f6fd8e235 Tasks page didn't include Delayed runs (#2176)
* Delayed runs weren’t shown in the Tasks page mini graph

* The Tasks page Queued count didn’t include Delayed runs (since ClickHouse switchover)
2025-06-16 14:14:09 +01:00
James Ritchie 33e1008d83 Adds a docker error entry to common problems docs page (#2172) 2025-06-14 11:11:24 +01:00
Matt Aitken a0815c8e3e Clickhouse performance improvements (#2175)
* Runs filter by org id and add created at to ordering

* CopyableText can accept an alternative value for copying

* The runs table now shows the ID instead of run number

* Paginating back/forwards fix

* The task stats need org id and project id too
2025-06-14 11:10:28 +01:00
James Ritchie 8a5e7f34b1 Added more limits and information to the limits page (#2171) 2025-06-13 10:32:44 +01:00
Matt Aitken c3dca5835d Fix for the Kapa widget not working with SSR (#2170)
* Move all the logic into a single component, preparing for client only

* Use ClientOnly

* Fix for search param not working
2025-06-12 22:17:22 +01:00
James Ritchie 20a8e7c6c1 Updated kapa sdk to 0.1.3 (#2169) 2025-06-12 16:21:34 +01:00
Eric Allam cc5514e57b Add status-first TaskRun index to speed up uncommon status filters (#2168) 2025-06-12 15:02:40 +01:00
Eric Allam ab432a2d7d Fix realtime re-subscribing stale data issue (#2162)
* Fix realtime re-subscribing stale data issue

Fixes an issue with realtime when re-subscribing to a run, that would temporarily display stale data and the changes. Now when re-subscribing to a run only the latest changes will be vended

* removed logs
2025-06-12 14:58:01 +01:00
James Ritchie e12c82b444 Use the Kapa AI SDK instead of the Kapa AI widget (#2113)
* Install the kapa sdk

* WIP using the SDK for the Kapa Ask AI widget

* Removes old kapa from root

* Now rendering everything inside the dialog component

* Fixes min-height of dialog content

* Remove kapa from root

* prevents kapa using reCaptcha

* Adds more functionailty with temporary UI placement for now

* Reset conversation button

* Adds a new sparkle list icon

* Adds some example questions as a blank state

* Animate in the example questions

* use “marked” package to render markdown

* Improve some animations

* Submit a question from the URL param

* adds custom scroll bar styling

* fixes modal to correct height after re-opening it

* Add button to stop generating answer mid-stream

* Adds buttons states to show submitting, generating, submittable

* Adds a helpfull sentence in the blank state

* Show a message if the chat returns an error

* Adds reset chat and feedback buttons to the bottom of an answer

* Makes sure you can give feedback in the different states of chat

* Adds a suble background to the dialog

* Fix a button inside button error

* Improve the shortcut esc key on dialog and sheet component

* Fix classname error

* organize imports

* Use our custom focus-visible

* Move the Tooltip for the button into the AskAI component

* Improved error message

* Organize imports

* Animated the modal gradient

* Small layout improvements

* Adds most asked questions from Kapa

* border glow tweak

* AskAI component is now a hook that can take a question

* remove kapa script

* Add a delay before the modal opens when usign the URL params

* Remove old component

* Update to the latest Kapa version

* Rephrased error message

* Use correct types for conversation

* Fixed types for addFeedback

* Adds DOMPurify package

* removed unused const

* Removed unnecessary platform specification

* Reset the timeout when the ai panel pops up

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Fix for coderabbit bad commit

* Clean up imports

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-06-12 14:09:03 +01:00
Dan 808c299008 Added deep research example (#2166)
* Added docs

* Improved docs and added video

* Added upgrade badge
2025-06-11 16:19:25 +01:00
Eric Allam 498b9a21af Improved TaskRun environment indexes (#2164)
### PR: Optimize **TaskRun** indexes for hot-path queries

**What changed**

| Object                          | Type                                                            | Purpose                                                                                                    |
| ------------------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `taskrun_runtime_id_desc_idx`   | **BTREE** `(runtimeEnvironmentId, id DESC) INCLUDE (createdAt)` | Eliminates explicit sort for the “latest task runs” query (`ORDER BY id DESC`) while remaining index-only. |
| `taskrun_runtime_createdat_idx` | **BTREE** `(runtimeEnvironmentId, createdAt DESC) INCLUDE (id)` | Accelerates the filter-only path that scans by `createdAt >= …` without any ordering requirement.          |
| `taskrun_createdat_brin`        | **BRIN** on `createdAt` (`pages_per_range = 128`)               | Lets the planner skip whole blocks older than the time window for both queries at < 100 MB cost.           |
| *(cleanup)*                     | **DROP** `TaskRun_runtimeEnvironmentId_createdAt_id_idx`        | Retires the 3-column index once the new ones are built.                                                    |

**Key details**

* All indexes created **CONCURRENTLY** to avoid write blocking.
* `fillfactor = 90` on b-trees for balanced space vs. future growth.
* Net disk usage drops **≈ 15–20 GB** while each query now gets a purpose-built access path.

**Why**

* Remove planner Sort nodes for the top-N “latest runs” view.
* Speed up environment-filtered range scans.
* Shrink index bloat and improve cache efficiency.
2025-06-11 09:24:11 +01:00
Eric Allam 48e1e7250b v4: fix stuck batch issue when processing happens before transaction commits (#2163)
* v4: fix stuck batch issue when processing happens before transaction commits

* Fix flaky test
2025-06-10 17:02:34 +01:00
Eric Allam 3f2b748a80 Delete the secure param before passing it to the ClickHouse client (#2161) 2025-06-10 13:55:19 +01:00
Eric Allam a060ceef0b Fix clickhouse migrations by adding the secure=true query param (#2160) 2025-06-10 13:45:24 +01:00
Eric Allam e6fb32194e Add environment filter to declarative schedules (#2148) 2025-06-10 12:11:11 +01:00
Eric Allam b38405cb88 Realtime and task run performance improvements (#2158)
* Add createdAt filter to realtime subscribing with tags

* Filter realtime colums and expose ability to skip some columns

* Add sharding support for electric

* Use unkey cache for the created at filter caching

* Remove 2 unused indexes on TaskRun

* Run list now filters by a single runtime environment

* Remove project ID indexes

* Use clickhouse in task list aggregation queries instead of pg (keep pg for self-hosters)

* WIP clickhouse powered runs list
stuff

* Improve the query to get the latest tasks for the task list presenter

* Update the usage task list to use clickhouse

* Implement next runs list powered by clickhouse

* Add new index for TaskRun for the runs list, by environment ID

* Add runTags gin index

* Handle possibly malicious inputs

* Ignore claude settings

* Better handling not finding an environment on the schedule page

* Use ms since epoch in test, not seconds

* Remove unused function

* Fix test

* Use an env var for the realtime maximum createdAt filter duration (defaults to 1 day)

* Fixed the query builder to correct the group by / order by order

* Make sure runs.list still works

* Create small-birds-arrive.md
2025-06-10 12:11:01 +01:00
James Ritchie e617c14456 Adds a troubleshooting entry for react.email not being bundled correctly (#2117) 2025-06-09 16:43:32 +01:00
James Ritchie 15fd731f3d Fixes embeded video width (#2121) 2025-06-09 16:40:59 +01:00
Eric Allam 4c7742c258 Enable docs AI contextual menu (#2157) 2025-06-09 10:04:56 +01:00
nicktrn e72820c080 Docs improvements for v4 self hosting (#2156)
* add switch command

* couple of changes
2025-06-07 19:51:47 +01:00
nicktrn 7a34c1102b Feat: v4 self-hosting (#2155)
* self-hosting stuff goes in /hosting

* add v4 tags

* add main compose file

* draft overview

* add webapp env vars

* overview tweaks

* add supervisor env vars

* move old docker guide

* new sidebar structure

* update github actions docs

* docker draft

* use env vars for s3 creds

* this might just work

* split into multiple files

* update guide

* document machine overrides

* split legacy docs into different section

* some fixes

* some tweaks

* add login and init instructions

* don't cursorignore .env.example
2025-06-07 00:57:47 +01:00
Eric Allam 2b3d54aff5 Make removing the httpEndpointEnvironmentId column migration correctly idempotent (#2154) 2025-06-06 11:52:14 +01:00
github-actions[bot] bb1f0a711a Release 4.0.0-v4-beta.21 (#2149)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 4s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 3s
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.21

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-06-06 10:50:28 +01:00
nicktrn 47b19a49d4 A few small v4 fixes (#2153)
* remove unused env vars

* actually use ALERT_REPLY_TO_EMAIL for alerts (non-breaking)

* increase fallback branch limit to 100M

* more unused env vars and example

* hide usage page when self-hosted

* fix for init flow

* set default or concurrency to 300 to match 100 on env

* fail fast when registry env vars are empty strings
2025-06-06 10:15:07 +01:00
Eric Allam 5301239e09 chore: remove v2 models from schema (#2107)
* Round 1 of v2 model removals

* Round 2

* Remove trigger http endpoint env

* Round 3

* Round 4

* Round 5

* Round 6

* Round 7

* Round 8

* Round 9

* Round 10

* Removed the remainder v2 code from the webapp

* GitButler WIP Commit

---------

Co-authored-by: GitButler <gitbutler@gitbutler.com>
2025-06-05 22:57:29 +01:00
Eric Allam 261dce102a v4: fix batchTriggerAndWait completion issues by processing batch chunks sequentially (#2152)
* v4: fix batchTriggerAndWait completion issues by processing batch chunks sequentially

* Remove unnecessary test
2025-06-05 17:56:56 +01:00
Eric Allam 575413c414 fix: moved dequeuing from a worker queue out of lua to be able to use blpop (#2151) 2025-06-04 22:04:30 +01:00
nicktrn e7795a06ad Fix: fixes and prerequisites for v4 self-hosting (#2150)
* remove pgadmin

* remove V3_ENABLED

* v3 is always enabled

* enfore docker machine presets by default

* rename autoremove env var

* prefix more k8s-specific env vars

* same prefix for all docker settings

* improve profile switcher copy

* supervisor can load token from file

* optional webapp worker group bootstrap

* fix error message

* fix app origin fallback for otlp endpoint

* use pnpm cache for webapp docker builds

* increase default org and env concurrency limit to 100

* optional machine preset overrides

* improve s3 pre-signing errors

* fix DOCKER_ENFORCE_MACHINE_PRESETS bool coercion

* shard unit tests

* fix for s3-compatible services

* optional object store region

* Update apps/supervisor/src/workerToken.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix DEPLOY_REGISTRY_HOST example

* fix platform mock

* remove remaining v3Enabled refs

* fix error type.. bad bot

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-06-04 18:02:38 +01:00
Eric Allam 2b3ea692fe v4: dequeue performance improvements (split concurrency from dequeue) (#2127)
* WIP

* Run queue now works with the worker queue / master queue split

* Acking should also cause the master queue to be processed

* Convert run engine tests and run engine to use runQueue changes

* Include the util files in the test tsconfig

* coordinator target should be es2020 as well

* providers target 2020

* Fix the triggerTask tests in the webapp

* v4 now working with the new worker queues, and added the legacy master queue migration stuff

* report worker queue lengths via opentelemetry metrics

* Adding lock metrics

* Release concurrency bucket metrics

* • Updated RunQueue.removeEnvironmentQueuesFromMasterQueue() method signature to take runtimeEnvironmentId instead of masterQueue parameter
• Added automatic master queue shard calculation using this.keys.masterQueueKeyForEnvironment(runtimeEnvironmentId, this.shardCount) 
• Updated RunEngine wrapper method to use new runtimeEnvironmentId parameter
• Updated DeleteProjectService to call the method once per environment instead of once per master queue
• Simplified API by encapsulating master queue sharding logic within RunQueue class

* metrics now working, configure the run queue settings, additional metrics for run engine and redis-worker

* Fix CodeRabbit suggestions

* return undefined from dequeueFromWorkerQueue, not null

* Remove message from worker queue in certain circumstances when acking

* Update log

* Ensure master queue consumers cannot stop from a processing error, and make the consumer interval configurable via an env var

* Change how the run queue master queue consumers are disabled internally

* Fixed tests

* process the queue on nack

* Fix more tests

* Fix priority tests

* Fixed dequeueing test
2025-06-04 17:18:46 +01:00
nicktrn f603725393 Feat: unified deploys for self-hosted and cloud users incl. multi-platform support (#2138)
* remove registry proxy

* remove --self-hosted flag

* automatically set network build flag

* update syncEnvVars debug log

* improve switch command

* always display deploy errors if they exist

* fix stuck deploy command after finalize error

* webapp-driven deploys, multi-platform support, lots of fixes

* add worker deployment migration

* rename image platform env var

* only try to sync parent env vars for preview deployments

* add KEEP_TMP_DIRS

* supervisor: docker api version lock, auth, multi-platform

* set image ref on create, validate digest

* use metadata for digest, fix local multi-platform builds

* print git meta branch before commit

* improve push and load flag handling

* make runs after local builds compatible with load and push

* small improvement for platform overrides

* add image platform to dequeued message

* remove deprecated init request body fields

* fix fail deployment id param

* remove build debug logs

* pass report merge with no tests

* structured run debug logs

* add required env var for tests

* should not be an error log

* add changeset
2025-06-04 15:54:10 +01:00
nicktrn a61951049f Enhance webapp version with build info (#2146)
* improve app version output

* set build info

* fix typo

* always show additional build info when self-hosting

* Update apps/webapp/app/routes/_app.orgs.$organizationSlug.settings/route.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update apps/webapp/app/components/navigation/OrganizationSettingsSideMenu.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix build timestamp name

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-06-04 15:49:07 +01:00
nicktrn 7ee0992a2f Runtime agnostic SDK configuration via env vars (#2132)
* use std-env in getEnvVar

* add changeset
2025-06-04 15:48:52 +01:00
nicktrn eee0fb2198 Fix tar-fs dependabot alerts v3 (#2145)
* update testcontainers

* override tar-fs used by testcontainers
2025-06-03 14:29:54 +01:00
nicktrn 1b62b348a9 Fix tar-fs dependabot alerts (#2143)
* update dockerode

* override tar-fs for remix dev
2025-06-03 14:10:35 +01:00
github-actions[bot] a2a5204ac5 chore: Update version for release (v4-beta) (#2144)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.20

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matt Aitken <matt@mattaitken.com>
2025-06-03 13:40:04 +01:00
Matt Aitken d4a9cefd78 syncVercelEnvVars fix for syncing the wrong preview branch env vars (#2141)
* syncVercelEnvVars fix for syncing the wrong preview branch env vars

* syncVercelEnvVars() fix for syncing the wrong preview branch env vars
2025-06-03 13:15:03 +01:00
nicktrn 9fca9e0508 Release 4.0.0-v4-beta.19 (#2140) 2025-06-02 15:32:25 +01:00
Matt Aitken d6dd2c9210 Preview branches docs (#2130)
* Draft preview branches docs

* More wip on docs

* Explain what the GH action does

* Added manual deploy/archive instructions

* Added dashboard section to the docs

* More wip on the preview branch docs

* Added preview/branch to the CLI deploy docs

* Add preview branch note to triggering docs

* Added preview branch notes to the API keys docs

* Added preview stuff to the Context docs

* CLI preview archive command

* Add a better explanation and details about env vars

* Fix for weird reference to the dashboard
2025-06-02 15:31:48 +01:00
github-actions[bot] 01e7ef3d04 chore: Update version for release (v4-beta) (#2110)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-06-02 15:21:16 +01:00
nicktrn e84d8cfa1d Fix: lock vitest version in CI (#2139) 2025-06-02 15:14:33 +01:00
Matt Aitken 26b0523cd0 Support passing “production” when deploying (#2137) 2025-06-02 14:18:36 +01:00
nicktrn 84d8fb575f Fix syncing parent env vars for non-preview deployments (#2131)
* only try to sync parent env vars for preview deployments

* add changeset
2025-06-02 10:40:06 +01:00
Matt Aitken 80d449bfdb Preview branch alerts (#2136)
* Preview branch alerts

* Show “Preview” not the branch for new alert modal
2025-06-02 10:37:37 +01:00
Matt Aitken ff157e51a1 If the run is already PENDING_EXECUTING, log an error and ack but don’t fail the run (#2129) 2025-05-30 11:44:40 +01:00
Matt Aitken a027e6a1bb Set the branch header for the SDK realtime functions (#2128) 2025-05-30 09:27:47 +01:00
Matt Aitken 5fdc7e66af Preview branch fixes (#2126)
* SDK: auto-detect the branch using the VERCEL_GIT_COMMIT_REF env var

* Waitpoint token completion with HTTP is now working
2025-05-29 21:23:11 +01:00
Matt Aitken ea853b243e Remove onsole.log… oops (#2125) 2025-05-29 14:39:36 +01:00
Matt Aitken 12f4653cd6 Fix long preview branch names (#2124)
* Truncate long branch names, don’t let the icon shrink

* Truncate and show tooltip for long branch names
2025-05-29 14:36:24 +01:00
Matt Aitken 47f4726515 Remove log that actually appears to users (#2123) 2025-05-29 13:47:19 +01:00
Matt Aitken 7ecaf2ce53 Sync env vars (parent env vars) (#2120)
* Prefer branch variables, but load preview envs too

* WIP with vercel preview env var syncing

* Return success if either child or parent env vars are synced

* Removed log of env vars

* Remove another log
2025-05-29 12:18:25 +01:00
nicktrn 7b463710f5 Fix metrics format (#2119)
* ensure eof marker is always at the end

* strip empty lines from prisma metrics
2025-05-29 09:52:42 +01:00
nicktrn fda9565eb0 Optionally disable run debug logs (#2116)
* disable run debug logs by default

* lightweight webapp health check

* disable debug logs for dev runs

* disable run debug logs for supervisor client

* add changeset
2025-05-29 09:27:08 +01:00
nicktrn 82e7484da8 Feat: import timings and bundle size analysis (#2114)
* cursor should ignore .env files

* fix for duplicate builds when starting dev

* output metafile in dev

* attach metafile to background worker

* attach import timings to worker manifest

* warn during dev if imports take more than 1s

* add analyze command

* update disable warnings flag message

* add changeset
2025-05-28 15:01:25 +01:00
Eric Allam 0f66023b54 v4: metadata collapsing now preserves operation order for correctness (#2115)
* v4: metadata collapsing now preserves operation order for correctness

* Add changeset
2025-05-28 14:52:06 +01:00
Eric Allam 021d6d8f20 Improve efficiency of cancelling in progress TaskEvent records in v3 and v4 (#2112) 2025-05-28 11:06:19 +01:00
Matt Aitken 068c024477 Preview branches (#2086)
* Initial preview migrations

* Modified the staging endpoint to create preview environments

* Added isBranchableEnvironment to RuntimeEnvironment

* Staging = yellow Preview = orange

* Changed the env sort order

* Set isBranchableEnvironment correctly. Create preview for new projects

* Very basic branch menu

* Creating branches from the dashboard

* Fix for string icons on project delete page

* Don’t show branch API keys

* WIP on the manage branches page

* RuntimeEnvironment added projectId index

* Only create the parentEnvironmentId column if it doesn’t exist already

* Improved the limit wording

* Add search to the branch list

* contains in both places

* Many style improvements

* Branch dropdown and v4 badge

* Arching/unarchive branches working in the dashboard

* Tidied imports

* Change preview slug from `prev` to `preview`

* Use correct color for side menu preview branch icon

* Upsert the branch and use the shortcode as a unique constraint

* Upserting working with nice messages in the dashboard

* Better errors when upserting branches

* Button shortcut, don’t allow event to propagate

* Better duplicate error message

* Filter out archived branches from the env selector

* Archiving/creating tweaked some more

* Add an archived banner to the app, fixes for archived branches and upsells

* Fixed pagination

* Disable editing schedules, pausing queues, testing tasks

* Don’t allow replaying if the env is archived

* When deploying detect the correct environment

* Get the projectClient when there’s a branch

* createGitMeta function, most code from the vercel CLI repo

* Deploy, getting the correct environment client

* Added git column to WorkerDeployment

* Add GitMeta to core schemas

* Create branch when deploying

* WIP on branch support in the API

* Delete old createTaskRunAttempt fn

* apiAuth remove export from internal functions

* Rename env var to “TRIGGER_PREVIEW_BRANCH”

* Add TRIGGER_PREVIEW_BRANCH to resolved env vars for runs

* First preview deploy and run working

* Set the preview branch in the main SDK

* Added git links to the preview branches table

* Better errors when replaying/testing archived branches

* Don’t dequeue archived environments

* Env var resolution with parent environment

* Hello world default machine small-2x to save my memory

* Fix for more env var functions

* Only return non-archived envs

* Switch to controlled state for the checkboxes

* Uncheck everything when PREVIEW is checked

* WIP on branch UI

* Show the preview branch label on the env vars list

* Fix for overriding env vars

* Adding preview branch env vars working

* Progress on new env vars

* Only allow selecting a single branch

* Layout fix when there are errors

* Set the defaultValue so there are some fields

* Conform fix for team invite page

* Archived environments don’t run scheduled tasks

* Added Git data to deployments

* Added git data to the deployment inspector

* Don’t allow upserting schedules when archived

* Deduplicate and blacklist some env vars

* Fix for wrong conform function being used

* Show a better error if all vars were blacklisted

* Added environment variable search (by key and value)

* Improved preview branch icon

* Replay now supports branches

* Schedule page render branches properly

* Show the env icon in bottom-left of the test page

* When editing older schedules (that have multi-env) show preview branches correctly

* Fix for incorrect disallowed branch name character

* Extract and improve the directory verification code

* WIP for CLI preview archive command

* Improved the preview branch action buttons

* Redirect to the project if we don’t find a matching env

* Archiving branch via the CLI working

* Fix for archiving branches

* Public access token test task

* JWTs working are with preview branches

* Add branch and git data to the Run ctx

* Updated GitMeta functions to work in CI

* Added pullRequestState

* Archive when deploying if the PR is closed/merged

* Fix for the changesets guide

* Fix for CLI dev bug introduced

* CLI promote now supports preview branches

* Add PR title. Reordered them and added tooltips

* syncEnvVars working with branches

* Added preview branch support to syncVercelEnvVars()

* Detect the branch from Vercel env var (set during build)

* Allow passing a branch in

* Use process.env.VERCEL_TOKEN as well… this used in Vercel CI

* Temp delete

* Improved regenerate api key modal

* Added Accordion component (with styles)

* Redesigned the API keys page

* Revert "Temp delete"

This reverts commit 177b92cd935a6161456bde65d01294e23ecfd47f.

* Changeset

* Fixed docs link

* The new branch panel closes when a branch is created

* Update apps/webapp/app/services/upsertBranch.server.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Removed findUniques from WorkerGroupTokenService

* Made the parentEnvironmentId migrations safe

* Latest lockfile

* Update packages/cli-v3/src/commands/workers/build.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Move isValidGitBranchName to a separate file

* Move the sanitize fn too

* removeBlacklistedVariables moved to a separate file

* Moved deduplicateVariableArray to a separate file…

* Fix broken sanitizeBranchName import

* Another import fix…

* Improved blacklisted error message

* SImplified migration to use `ADD COLUMN IF NOT EXISTS "parentEnvironmentId" TEXT`

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-05-28 11:02:56 +01:00
Eric Allam b74c000fb6 Improve metadata flushing efficiency by collapsing operations (fix #2104) (#2106)
* Improve metadata flushing efficiency by collapsing operations (fix #2104)

* Add changeset

* A couple of style tweaks
2025-05-27 14:08:15 +01:00
Eric Allam 0410316e14 Enable prisma metrics and add them to the /metrics endpoint (#2111)
* Enable prisma metrics and add them to the /metrics endpoint

* Add support for bearer token auth on metrics endpoint
2025-05-27 13:28:45 +01:00
Eric Allam c571c5ef32 v4: Can now set project ref using the TRIGGER_PROJECT_REF env var (#2109)
* v4: Can now set project ref using the TRIGGER_PROJECT_REF env var

* Add changeset

* Improve the name of the resolvEnvVars function and move setting NODE_ENV into the dev supervisor

* Removed moved function
2025-05-27 12:51:04 +01:00
Eric Allam e84ede9599 Upgrade to electric@1.0.13 (#2089)
* Upgrade to electric@1.0.13

* Add ELECTRIC_INSECURE env var to test container
2025-05-23 16:59:53 +01:00
Eric Allam 3fc5630be7 fix: calculating next schedule should always just be from now (#2102) 2025-05-23 16:55:52 +01:00
Eric Allam 13d378f6df v4: batches can only complete when all their runs have been created (#2101)
* v4: batches can only complete when all their runs have been created

* Fix flaky runs replication test
2025-05-23 16:53:50 +01:00
Eric Allam 1a6a9ca97a perf fix: calculateNextScheduledTimestamp speed improvement (#2099)
* Simulate "next steps" when calculating the next timestamp to prevent millions of iterations on dev schedues

* Add additional tests

* Fix typescript issue
2025-05-23 16:24:33 +01:00
Dan 6cb57b803c Added openai agent sdk guardrails docs (#2100) 2025-05-23 16:09:12 +01:00
nicktrn 7c791dd519 Improve unit test workflow performance (#2096)
* shard unit tests

* temp enable for all pushes

* fix test workflow

* update to latest vitest and only add to root package.json

* additionally use default reporter

* gather reports before uploading

* split up slow replication tests

* split up unit tests workflow

* move workflows to parent dir

* use new paths in parent workflow

* prevent artifact clashes

* we always need to create the reports dir

* speed up merge reports

* gather reports even when tests fail

* fix artifact patterns

* increase shards

* disable push trigger again

* improve dequeue snapshot test reliability
2025-05-23 12:22:14 +01:00
github-actions[bot] cf3735976e Release 4.0.0-v4-beta.18 (#2095)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.18

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-05-22 21:59:11 +01:00
nicktrn a9a40b5184 Fix dev indexing (#2094)
* save build manifest for dev runs again

* add changeset
2025-05-22 21:54:00 +01:00
github-actions[bot] 0f928e224b Release 4.0.0-v4-beta.17 (#2071)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.17

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-05-22 19:51:18 +01:00
Eric Allam a306545952 Always find debug logs when in the span sidebar (#2093) 2025-05-22 14:22:12 +01:00
Eric Allam 1bb1fc4c8f v4 run engine debug logs now filtered out in SQL by default (#2092) 2025-05-22 10:44:06 +01:00
nicktrn 1ca37f5745 Expose esbuild keepNames and minify options (experimental) (#2091)
* Expose esbuild `keepNames` option (experimental)

* Expose esbuild `minify` option (experimental)

* test new experimental options
2025-05-22 10:42:48 +01:00
nicktrn 8112c12092 Improve email whitelisting and extend to GitHub auth (#2090)
* make github auth respect email whitelist

* display github login errors

* fix smtp secure env vars

* prevent sending magic link if email not allowed

* fix MARQS_DISABLE_REBALANCING and RUN_ENGINE_DEBUG_WORKER_NOTIFICATIONS
2025-05-22 10:30:00 +01:00
nicktrn c8d252e300 Add experimental externals detection (#2083)
* add auto detect externals

* stop spinner on esbuild errors

* test problematic packages

* fix braces types

* improve detection 10x

* ignore sentry stub

* improve main package json detection

* rename to experimental_autoDetectExternal
2025-05-21 16:40:37 +01:00
nicktrn d89f740d18 Write esbuild metafile to output dir (#2087)
* write esbuild metafile to output dir

* add changeset
2025-05-21 16:17:10 +01:00
Eric Allam 41a3bdec68 Add id-token permission to the publish webapp workflow (#2088) 2025-05-21 14:30:03 +01:00
Eric Allam a9a937dd25 Implement example of streamText fallback using an AI data stream (#2068) 2025-05-21 13:22:06 +01:00
Eric Allam 14e081e17d release concurrency system reliability improvements (#2081)
* Refill release concurrency tokens when a run is cancelled

* Improved release concurrency accounting system + a sweeper to auto-refill tokens for snapshots that are no longer the latest snapshot on a run (e.g. the run has moved to a new snapshot state)

* Fix order of arguments to the releasings sweeper

* Add a heartbeat for SUSPENDED snapshots, where when stalled will attempt to continue the run if unblocked
2025-05-21 13:21:17 +01:00
Eric Allam 500a173d67 Set default values on the invite and new env var forms to fix an issue after updating conform (#2084) 2025-05-21 13:20:16 +01:00
Eric Allam cc562c58fa Remove unused publish job from the release github workflow to fix permissions error (#2085) 2025-05-21 13:19:49 +01:00
Eric Allam 0334df70ad Prevent socket hangup error by removing the aggressive clickhouse keep alive ttl env var default (#2082) 2025-05-21 13:15:15 +01:00
Dan e08e493b3c Potential fix for code scanning alert no. 2: Workflow does not contain permissions (#2078)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-05-19 21:17:35 +01:00
Dan f667d61d4c Potential fix for code scanning alert no. 3: Workflow does not contain permissions (#2077)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-05-19 21:16:58 +01:00
Dan 325ef04c7f Potential fix for code scanning alert no. 6: Workflow does not contain permissions (#2076)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-05-19 21:15:42 +01:00
Dan 79f0a6a662 Potential fix for code scanning alert no. 42: Workflow does not contain permissions (#2074)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-05-19 21:14:26 +01:00
Dan ad5027b5fd Potential fix for code scanning alert no. 1: Workflow does not contain permissions (#2079)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-05-19 20:59:50 +01:00
Dan f0809e6ad6 Potential fix for code scanning alert no. 38: Workflow does not contain permissions (#2075)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-05-19 20:48:58 +01:00
Eric Allam c63559f55d v4: fix race condition when continuing run when blocked at the same time (#2073)
* v4: fix race condition when continuing run when blocked at the same time

* Attempt to fix flaky e2e test

* Make waitpoint race condition test less flaky
2025-05-19 16:50:36 +01:00
Eric Allam 8471169b30 Fix various dependabot alerts (#2063)
* Upgrade posthog-node to clear axios vulns

* Upgrade @slack/web-api to use a secure version of axios

* Update parse-duration to fix security vulns

* Mitigate against the ws DoS vuln

* Upgrade body-parser to 1.20.3 in the webapp

* Upgrade react-use to 17.5.1 to remove the fast-loops transitive dep

* Remove unused babel dev deps and config file that's no longer used

* Upgrade prismjs to 1.30.0 and bundle parse-duration now

* upgrade express to 4.20.0 to fix issue with XSS when redirecting

* Upgrade @conform/zod to 0.9.2
2025-05-19 12:01:51 +01:00
nicktrn 558a39c644 Remove supervisor docker binary requirement and other tweaks (#2062)
* don't require docker binary

* more structured logs

* remove docker type dep

* add core changeset

* use implicit DOCKER_HOST instead

* disable resource monitor for now

* support attaching docker runners to multiple networks

* warn if dequeue interval > idle dequeue interval

* verbose logs

* add changeset
2025-05-17 12:33:41 +01:00
Eric Allam b4ab06600b Create AGENTS.md file (#2070) 2025-05-17 07:54:04 +01:00
Eric Allam c8e8bc9306 engine v2: Fix selectTopEnvs missing queues (#2069) 2025-05-17 07:53:48 +01:00
Eric Allam a69621bdcc Allow self-hosted deploys locally by pointing to docker.host.internal on macOS (#2064) 2025-05-16 15:20:48 +01:00
Eric Allam ad4daa3301 Fix run replication payloads/outputs trying to send invalid types like BigInt to clickhouse (#2065) 2025-05-16 11:02:30 +01:00
Eric Allam bb7173b4ab Improve run replication logging (#2060)
* Remove the tcp buffer monitors

* Improve run replication logging
2025-05-15 14:12:01 +01:00
Eric Allam 2aee3debc0 Docs: 3rd party log exporters (#2058) 2025-05-15 10:50:15 +01:00
Eric Allam d1e40643fc Allow creating and monitoring run replication services with different settings (#2055)
* Allow creating and monitoring run replication services with different settings

* Fix test
2025-05-14 20:40:47 +01:00
Eric Allam a8e38d9231 chore: Skip unit tests dependency when running publish image workflow (#2054) 2025-05-14 19:31:50 +01:00
github-actions[bot] 2ae0e22d81 Release 4.0.0-v4-beta.16 (#2053)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.16

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-05-14 16:26:28 +01:00
nicktrn 206a2c3245 Fix init.ts detection for sentry plugin users (#2051)
* fix init.ts detection when using the sentry plugin

* add changeset
2025-05-14 16:20:05 +01:00
Eric Allam eb3929880f runs replication leader lock expiration fix (#2050)
* runs replication leader lock expiration fix

* Allow configuring the container image --max-old-space-size using NODE_MAX_OLD_SPACE_SIZE

* Ability to configure the clickhouse keep alive settings

* Add some logging because we might not be able to do telemetry
2025-05-14 15:49:48 +01:00
github-actions[bot] 0661ee5fdd Release 4.0.0-v4-beta.15 (#2040)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.15

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-05-14 12:33:37 +01:00
Eric Allam 2deef00d48 Improvements to the runs replication service to prevent buffer exhaustion (#2047) 2025-05-14 11:35:51 +01:00
nicktrn fa5360a99d Feat: supervisor ARM builds (#2046)
* v4 worker multi-arch builds

* v4-beta tag for webapp

* add oidc permission

* deps fetcher needs python

* node-gyp needs complete toolchain

* fix headers

* bust pnpm cache

* add setuptools

* switch back to old cache id

* push worker images

* pass the correct tags
2025-05-14 11:23:41 +01:00
Eric Allam 7ace1c3e25 Fix run replication telemetry by passing in a tracer (#2045) 2025-05-14 09:52:09 +01:00
Eric Allam a815633712 Add external log exporters and fix missing external trace exporters in deployed tasks (#2038)
* Add external log exporters and fix missing external trace exporters in deployed tasks

* Generate the external traceID correctly and exporter 3rd party logs with the external traceID as well
2025-05-13 16:54:24 +01:00
Eric Allam 84a0336bdd Fix #1955: schemaTask parse payload failures handled gracefully (#2043) 2025-05-13 16:47:21 +01:00
Eric Allam 7be07b4d0e allow configuring the replication leader lock settings (#2042) 2025-05-13 14:17:36 +01:00
nicktrn bb96e848de Fix init.ts import for deployed workers (#2041)
* import init file in managed worker

* refactor for easier diff

* managed worker: attach configured incorrectly error details

* add changeset

* disable pre

* we also didn't rewrite the output path

* Revert "disable pre"

This reverts commit 89afe44f6c42d4bd7b5a51f7fda1caec6cab8a24.
2025-05-13 13:27:49 +01:00
Rudra Sankha Sinhamahapatra 39f03085b4 feat: ffmpeg v7 (#1777)
* adding ffmpeg v7

* Renaming id ffmpeg to ffmpeg7

* added space

* fixing formatting issue

* fix unit test workflow for forks

* merge ffmpeg v7 into existing extension

* verify md5 checksum

* fix dns resolution

* fix v7 install

* remove redundant code

* add changeset

* mark fluent-ffmpeg as external

* add docs

* Revert "mark fluent-ffmpeg as external"

This reverts commit 74cd317ae69c7453a22d3fa412ff00b402840b87.

---------

Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-05-13 12:27:35 +01:00
Mendy Landa 21c0dc619e feat: playwright extension (#1764)
* feat: playwright build extension

* feat: add playwright task

* full dep list & added some comments

* fix v3-catalog

* log image size for local builds

* detect playwright version

* add changesets

* add docs

* additional checks

* fix unit test workflow for forks

* use middleware and update docs

* update jsdoc

---------

Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-05-13 12:22:01 +01:00
James Ritchie da0ef73724 Docs: Removes an issue listed in ‘known issues’ in the v4 migration guide (#2039) 2025-05-13 10:14:27 +01:00
Eric Allam 65da20c225 feat: replicate task runs to clickhouse to power dashboard improvements (#2035)
* WIP clickhouse package with test containers setup

* More clickhouse client setup now with otel and real tests, and the v1 of raw run events

* Add some additional columns to raw_run_events_v1

* WIP runs dashboard service

* Create a new run engine event bus event for the runs dashboard to hook into

* Track run events in the run engine

* make sure engine v1 runs get synced to CH

* Update the attemptNumber of v3 task runs

* Restructure the run events to be more sparse

* emit more stuff

* Setup replication package

* scaffold the replication package

* replication wip

* resolve conflicts

* more replication stuff

* Add ability to drop the replication slot completely on teardown

* Use the new single replacingmergetree task events table for replication

* get it working

* insert payloads into their own table only on insert and then join

* prepare for using clickhouse cloud and now running ch migrations during boot in the entrypoint.sh

* Handover WIP and tests

* Testing the replication service

* Remove the runs dashboard stuff that we aren't using anymore

* Added a test for large payloads

* hacky typecheck fix

* Fix new internal package typecheck issues and start adding telemetry to the replication service

* tracing over spans, some other improvements

* Improvements to the runs replication service, now ready for testing

* Some fixes and cleanups

* Don't need this code anymore

* move transaction types into the runs replication service

* only send spans where there are transaction events

* A couple of suggested tweaks
2025-05-12 22:12:36 +01:00
James Ritchie ccc9764383 Active incident status panel in the side menu (#2033)
* WIP adding a side menu panel to display incident statuses

* Fixes re-rendering bug and copy tweak

* cache the betterstack response using unkey

* Style the button to fit the panel colors
2025-05-09 15:52:17 +01:00
Matt Aitken 584722d48b [v4] Complete a waitpoint and then get affected runs (#2034)
* Complete waitpoint before getting affected runs. Added more logging

* Added another error log
2025-05-09 15:46:41 +01:00
nicktrn 1b1ad16d94 Improve worker management admin route (#2032)
* improve route to add worker group, handles existing groups gracefully

* add option to remove default worker group from project

* separate project id field

* update supervisor readme with route changes
2025-05-09 10:43:31 +01:00
Matt Aitken 37aadfc80b We can use TaskRun error instead of attempt. Faster and works across v3/v4 (#2031) 2025-05-09 09:36:40 +01:00
github-actions[bot] 6736cb5ae9 Release 4.0.0-v4-beta.14 (#2029)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.14

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matt Aitken <matt@mattaitken.com>
2025-05-08 11:12:25 +01:00
Matt Aitken 87630bc64f Fix for TS issue with old DB type (#2030) 2025-05-07 20:51:36 +01:00
Matt Aitken d23fa38a0a Waitpoint token callback URLs (#2025)
* Initial commit with a plan for what we’re going to do

* Some initial types and improved plan

* Add Waitpoint resolver

* Add resolver + status index

* Remove type + status index

* Only drop if exists

* Remove type index

* Update waitpoint list presenter to use resolver

* Added resolver to the engine

* Made the existing waitpoint list presenter more flexible

* Initial implentation ofr wait.forHttpCallback()

* Added the callback endpoint (no API rate limit)

* schema version

* Added jsdocs, removed schema version because of errors

* Show callback URL if it’s set

* Dashboard pages and panels

* Remove todos

* Added temporary icon

* Added a blank state

* Some tweaks and added a Replicate example

* Implement unwrap() for httpCallback

* Added unwrap to wait.forToken() as well

* Improved jsdocs

* Added docs

* Added unwrap to the token docs

* Show a dash if there are no tags

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Make the timeout error safer

* Fixed migrations… should use id desc not createdAt desc

* Fixed page title

* Fixed migration so it only adds them if they don’t exist. This allows us to manuall run in cloud first

* Respect the max content length by getting the length of the body

* Added more docs details about the callback format

* Remove code comment

* Improved the error

* Added a hash to the HTTP callback URLs

* Add the apiKey to the API input type to fix TS error

* Return the error responses. They were being caught and not preserved

* The content-length header is required. Deal with an empty body

* Removed unused types

* Added some new span icons

* Reworked http callback to be a create call then just use wait.forToken()

* Added a changeset

* Updated the docs

* Updated the wait overview docs

* Simplify to just a call

* WIP stripping right back to waitpoints just having a URL associated with them…

* More deletions

* Remove missing icon

* Updated the changeset

* Add URL to the token return types

* Remove wait for http callback page

* Updated docs

* More tidying

* Type and import fix

* Remove unused import

* Some type fixes for the retrieve

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-05-07 19:55:29 +01:00
James Ritchie 4ec0395424 Fixes a console error introduced when updating the loading animation (#2019) 2025-05-07 18:40:04 +01:00
James Ritchie e94558a0d5 Stop indexing the test-cloud domain (#2026) 2025-05-07 18:39:38 +01:00
James Ritchie 6f4af89adb Docs: Adds Yarn ‘Plug’n’Play” conflicts fix to troubleshooting page (#2028) 2025-05-07 18:38:40 +01:00
James Ritchie 3e45f785a0 Dashboard: Org menu improvements for admins (#1969)
* Adds path for admin route

* Updates impersonation banner and show new org button if only 1 org

* Simpler UI for displaying admin access
2025-05-07 18:38:00 +01:00
James Ritchie 04b9973f20 Shows the tooltip date time on DateTImeAccurate component (#2021) 2025-05-07 18:35:48 +01:00
github-actions[bot] 8da3043111 Release 4.0.0-v4-beta.13 (#2027)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.13

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-05-07 15:10:50 +01:00
nicktrn 2b586c87a0 Fix controller waitpoint resolution, suspendable state, and snapshot race conditions (#2006)
* remove dead code

* rename managed to shared runtime manager

* rename to resolve waitpoint for clarity

* add resolver id helper

* store and correctly resolve waipoints that come in early

* fix ipc message type change

* branded type for resolver ids

* add fixme comments

* remove more unused ipc schemas

* fix entitlement validation when client doesn't exist

* restore hello world reference workspace imports

* runtime manager debug logs

* prefix engine run logs

* managed run logger accepts nested props

* runtime suspendable state and improved logs

* require suspendable state for checkpoints, fix snapshot processing queue

* add terminal link as cli module so we can more easily patch it

* apply cursor patch

* add license info

* remove terminal-link package and add deprecation notice

* remove old patch

* remove terminal-link from sdk

* rename snapshot module

* add cli test tsconfig

* add run logger base type

* add snapshot manager tests

* fix cli builds

* improve QUEUED_EXECUTING test

* changeset

* make testcontainers wait until container has stopped

* require unit tests for publishing again

* avoid mutation during iteration when resolving pending waitpoints

* improve debug logs and make them less noisy

* always update poller snapshot id for accurate logs

* detach task run process handlers

* check for env overrides in a few more places and add verbose logs

* log when poller is still executing when we stop it

* add supervisor to publish workflow

* always print full deploy logs in CI

* Revert "avoid mutation during iteration when resolving pending waitpoints"

This reverts commit 87b0ce1e5b.

* disable pre

* print prerelease script errors

* Revert "disable pre"

This reverts commit 9403409637.

* misc fixes

* better debug logs

* add snapshots since methods and route

* prep for snapshots since

* improve deprecated execution detection

* update supervisor and schema

* properly log http server errors

* detect restore after failed snapshot fetch

* run and snapshot id can be overridden

* fix restore detection

* fix deprecation checks, move into snapshot manager

* less logs

* rename snapshot manager stop

* restore detection was moved into snapshot manager

* fix notifier logs

* make runtime manager status a debug log

* no need to attach runtime status twice

* findUnique -> findFirst

* sort snapshots by created at everywhere
2025-05-07 13:02:32 +01:00
nicktrn 053389d9b3 Fix testcontainers cleanup (#2023)
* update testcontainers packages

* increase cleanup timeout and add better logs

* small tweaks

* decrease docker network size so we can have more of them

* add a test flow to check this all works

* await all engine.quit calls

* add docker diagnostics

* reduce number of test runs

* improve network attachment output

* add setup logs

* log redis setup errors

* add cleanup log type

* stop redis container if setup fails

* disable ipv6

* tidy things up a bit

* fix unit tests workflow

* decrease container cleanup timeout

* fix types

* fix webapp typecheck
2025-05-06 08:56:34 +01:00
Eric Allam 43a4139424 docs: onCancel (#2024)
* docs: onCancel

* Add availability note
2025-05-03 21:40:03 +01:00
github-actions[bot] 7b509849e9 chore: Update version for release (v4-beta) (#1996)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.12

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <eallam@icloud.com>
2025-05-03 21:26:12 +01:00
Eric Allam 13f750a18b v4: implement onCancel callbacks (#2022)
* v4: implement onCancel callbacks

* chat example

* Add changeset

* A few improvements
2025-05-03 20:50:11 +01:00
nicktrn 15816e9955 Fix long retry delays (#2020)
* make testcontainers wait until container has stopped

* require unit tests for publishing again

* add failing test case

* make it pass

* add retry threshold ms env var and use it
2025-05-02 16:57:21 +01:00
nicktrn a10e2a8b16 Small fixes in prep for v4 self-hosting (#2018)
* fix entitlement validation when client doesn't exist

* add supervisor to publish workflow

* fix v4 publish workflow name
2025-05-02 14:33:20 +01:00
Matt Aitken 423209661b Give helpful hint if you pass a bad directory when deploying (#2013) 2025-05-02 10:54:26 +01:00
James Ritchie 73f363f9d5 Changes the spinner to white now we have purple primary buttons (#2014) 2025-05-02 10:50:22 +01:00
James Ritchie 4456184f37 Fix task and schedule icons squishing (#2017) 2025-05-02 10:47:57 +01:00
James Ritchie 2448242be3 Small improvement to the loading animation so it moves left to right only (#2012) 2025-05-01 19:24:03 +01:00
James Ritchie 9c3aeb3efb Adds friendly formatting for max duration values (#2011) 2025-05-01 19:22:56 +01:00
James Ritchie df0bce3a8f Code blocks have an optional text-wrap toggle (#2009)
* Code blocks have an optional text-wrap button

* Wrap “words”, not “all”

* wrapping is default false

* Change the wording in the tooltip
2025-05-01 17:44:17 +01:00
James Ritchie 0fe85eaec4 Highlight queues when concurrency limit reached and new table col (#2008)
* Combines the Running and Concurrency limit cols into 1

* Display a badge when a queue is at the concurrency limit

* Colors the Running/Limit column text amber if the concurrency limit is hit

* Turns the “Running” big number amber and shows “At concurrency limit” text

* BigNumber now handles big values using formatNumber and formatNumberCompact

Also includes some responsive improvements to make sure things wrap when it gets tight

* Adds a new col for showing how the queue is limited

* Reinstates a threshold for making very big numbers compact

* Added border to make the search bar not float
2025-05-01 17:40:54 +01:00
Matt Aitken d2dde0a844 formatDateTimeISO() fix (#2010)
* Fix for the DateTime ISO function

* Fix implementation and added unit tests

* Preserve milliseconds properly
2025-05-01 17:35:55 +01:00
Dan aacec569d0 Added Python MarkItDown docs (#1977)
* Added Python MarkItDown docs

* Simplified the task

* Update example to use fetch and improved sidebar titles

* Fixed link
2025-05-01 14:18:12 +01:00
nicktrn 0df7af4403 Add idle dequeue interval to supervisor (#2007)
* supervisor uses new idle interval after empty dequeues and errors

* make supervisor heartbeat interval configurable
2025-05-01 10:53:19 +01:00
James Ritchie 553a03580f Show a tooltip when hovering over any DateTime (#2003)
* Adds a tooltip to display the UTC, timezone and local time for DateTime

* Made it safer for SSR

* Makes the copy function into a hook and separate button + adds copy dateTime button to the date tooltip

* Adds an extra-small size copy button

* Show the offset (UTC +1) next to your local time

* Optionally don’t show the date tooltip. Defaults to true (always show)

* Tidy imports

* Refactor the tooltip content to remove duplicated markup

* Coderabbit suggestion to include support for minutes for some timezones like Nepal
2025-05-01 10:00:42 +01:00
Matt Aitken af019473cd Get data for the last day of the month for usage graphs (#1999) 2025-05-01 09:53:06 +01:00
Matt Aitken cb47200d34 Added search to the Queues page (#2000)
* Added search to the queues page

* Fix for empty state copy
2025-05-01 09:33:03 +01:00
James Ritchie 98fd8045e9 Tooltip to explain dev schedules not counting towards your limit (#2004) 2025-05-01 09:32:13 +01:00
James Ritchie 44184a61c7 Updates the secret key text to be more explicit what you have to do to start triggering tasks (#2005) 2025-05-01 09:31:37 +01:00
nicktrn c0807ad0d0 Display terminal links in cursor (#1998)
* add terminal link as cli module so we can more easily patch it

* apply cursor patch

* add license info

* remove terminal-link package and add deprecation notice

* remove old patch

* remove terminal-link from sdk

* changeset
2025-05-01 08:53:11 +01:00
James Ritchie cf9460afee Post new sign up reasons to slack, not plain (#1995)
* Post new sign up reasons to slack, not plain

* Makes the Slack env vars optional

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2025-04-30 14:02:02 +01:00
Matt Aitken 7fe111abe9 AI dashboard widget + CLI AI generate fix suggestions (#1925)
* Made a better AI icon and improved how it looks on the create new schedules inspector

* WIP adding kapa ai to the app

* WIP adding a new Ask AI button to the side menu

* WIP using the react example from the docs

* Align the AI button in the bottom bar

* Kapa widget now works

* Trigger the Kapa modal from the custom button

* Fix imports

* Adds Ask AI shortcut to Shortcuts panel

* Adds a new enter shortcut key

* Adds a prop so you can optionally hide the shortcut key

* Latest

* Moved the Kapa/Help stuff into a component, out of root

* WIP using onModalClose

* Creates a wrapper provider to block shortcuts while kapa modal is open (has bugs)

* Fixes button alignment

* Hide the shortcut key at the button layer

* Fix for enable/disable shortcut keys globally

* Kapa is working

* You can bring up the shortcut keys without opening the help panel

* TODO remove listeners

* remove imports and fix invalid tailwind class

* style kapa widget as best i can

* Remove Kapa event listeners

* Allow passing in a query

* Open the AI widget if there’s a URL param

* Much cleaner implementation for Kapa

* Trying to auto-open the Kapa widget when the page loads

* Delay opening the widget because it was causing issues

* Improved Kapa widget colors

* Added an AI help link to the CLI

* We don’t need this anymore

* Exit with 1, indicating an error. This is important for CI

* Removed old auto-opening code

* Added some code comments to explain some of the annoying stuff

---------

Co-authored-by: James Ritchie <james@trigger.dev>
2025-04-30 11:11:42 +01:00
github-actions[bot] 525285da7f chore: Update version for release (v4-beta) (#1994)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.11

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matt Aitken <matt@mattaitken.com>
2025-04-29 16:48:57 +01:00
Eric Allam 07365cd405 realtime: fix streams missing chunks when streams are longer than 5 minutes and receive 408 Request Timeout errors. Also now support multiple client streams being sent to a single stream key (#1993)
* realtime: fix streams missing chunks when streams are longer than 5 minutes and receive 408 Request Timeout errors. Also now support multiple client streams being sent to a single stream key

* Safely release the reader lock
2025-04-29 12:42:38 +01:00
Matt Aitken 83d0e8710d Fix for Schedules list page slow loading (#1992)
* Fix for Schedules list page slow loading

Getting BackgroundWorkerTask was very slow (Prisma was getting every single one…)

* Same fix for the upserting of schedules in the dashboard
2025-04-29 12:40:56 +01:00
Matt Aitken 280a6d0297 V4 dequeue test fixes (#1991)
* Fix priority tests by dequeuing in sequence

* Expect this test to fail until we support parallel dequeuing of an env with streaming

* Fix one and expect fail from the other

* Fix for batch trigger test dequeuing

* Fixed pending version test
2025-04-29 12:40:22 +01:00
Matt Aitken f579afb4cc V4 dequeue performance (return faster) (#1989)
* Loop through tenants only once, return as soon as we have enough.

* Hello world deadlock task set back to triggerAndWait
2025-04-28 14:49:38 +01:00
James Ritchie 3d744c6ecc Mergent migration guide (#1988)
* Adds a migration guide for converting mergent tasks to trigger.dev

* Adds link to migration guide in the docs side bar
2025-04-28 14:18:09 +01:00
github-actions[bot] 5691480dac Release 4.0.0-v4-beta.10 (#1984)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.10

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-04-28 13:34:34 +01:00
nicktrn 09a859d056 Fix managed run controller edge cases (#1987)
* parse disconnect description

* decrease snapshot poller logs

* remove another useless log

* attempt number change detection

* ensure no executions or child processes are being reused

* prevent snapshot change handler from running after execution stopped

* prevent creating zombie intervals on reset

* add changeset

* add enabled poller check before getting latest snapshot

* make attempt number update more explicit, improve logs

* remove deprecated heartbeat service

* ..also remove the import
2025-04-28 13:22:30 +01:00
Saadi Myftija 7bdbbdc433 Handle rate limit errors from Slack on new alert creation (#1986) 2025-04-28 11:07:59 +01:00
Matt Aitken 8b0e4f2367 Fix for completing batches (when there are idempotent runs) (#1985) 2025-04-25 18:41:20 +01:00
Eric Allam e837500486 feat: v4 deadlock detection (#1970)
* Locked task runs will now require queues and tasks to be in the locked version

* Client errors caught in a run function now will skip retrying

* Extracted out the trigger queues logic

* extract validation, idempotency keys, payloads to concerns

* Extracted out a bunch of more stuff and getting trigger tests to work

* Add queue and locked version tests

* Deadlock detection WIP

* more deadlock detection

* Only detect deadlocks when the parent run is waiting on the child run

* Improve the error experience around deadlocks

* A couple tweaks to make CodeRabbit happy and fixing the tests in CI

* Fixed failing test

* Changeset

* wip

* Make sure to scope queries to the runtime env
2025-04-25 12:56:54 +01:00
github-actions[bot] 60fcf5fdac Release 4.0.0-v4-beta.9 (#1980)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.9

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-04-25 12:43:32 +01:00
Eric Allam 3a62ee36d9 v3: prevent envs with excess queues from degrading dequeue performance (#1982)
* v3: WIP maximum queues per env implementation

* Add a queue distribution test

* Add edge case tests

* Set the marqs maximumQueuePerEnvCount
2025-04-24 18:02:49 +01:00
Matt Aitken bb606a1fcd Don’t allowed canceled delayed runs to be put into the queue (#1981) 2025-04-24 15:10:47 +01:00
Matt Aitken e9c6cc71f0 New batch id length is longer (#1944) 2025-04-24 13:38:15 +01:00
Eric Allam 30f93521c8 fix: default machine config indexing now works (#1979) 2025-04-24 13:38:03 +01:00
Matt Aitken 18f77660e0 Runlock telemetry (#1974)
* Added error throwing tests to runlock

* Added some more run lock tests

* Added customConditions so the test can use the Logger

* Fix for JSON error

* Added a span to the run lock with a name
2025-04-24 13:37:33 +01:00
Matt Aitken aa1027969b Increase v4 visibility timeouts & don't try continue finished runs (#1978)
* Increase v4 visibility timeouts

* Added some logging for #continueRunIfUnblocked: run has no checkpoint

* If a run is finished or pending cancel, don’t try and continue it
2025-04-24 13:36:18 +01:00
James Ritchie 32ff569844 Fixes bug on Safari preventing Queues and Schedules tables from scrolling (#1973) 2025-04-24 11:40:47 +01:00
James Ritchie dfca04aaea Docs: Updates the run function params syntax + adds new run.list() example (#1976) 2025-04-24 11:31:22 +01:00
Matt Aitken 672a6b8be7 RedisWorker clean up orphaned items when dequeuing (#1975)
* Remove setting the invisibility timeout because it’s already done in the dequeue Lua script

* Remove orphaned queue items when dequeuing

* Added an ack to the visibility timeout test
2025-04-24 11:15:42 +01:00
github-actions[bot] 56ec0523b5 Release 4.0.0-v4-beta.8 (#1972)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.8

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-04-23 19:30:49 +01:00
nicktrn 73214d760e Prevent large outputs from overwriting each other (#1971)
* large outputs now get unique keys again

* replace other attempt id occurences

* add changeset
2025-04-23 19:21:21 +01:00
James Ritchie 853a7ef7e4 Updates button copy and layout tweaks (#1941) 2025-04-23 16:33:46 +01:00
HUORT Louis 0726620525 Switch to docker compose v2 (#1692)
* refactor: docker compose migration

* fix compose download link

* set static name for electric container

---------

Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-04-23 14:29:26 +01:00
github-actions[bot] cfb77159d7 Release 4.0.0-v4-beta.7 (#1954)
* chore: Update version for release (v4-beta)

* Release 4.0.0-v4-beta.7

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2025-04-23 13:34:26 +01:00
Saadi Myftija 2dbc085bb3 Fix alert creation bug related to the Slack integration (#1967)
* Fix alert creation bug related to the Slack integration

* Handle token_expired error from slack gracefully
2025-04-23 11:11:17 +01:00
Saadi Myftija 26aad58abd Add fuzzy matching to the tasks filter (#1960)
* Add a custom react hook to enable fuzzy searching in item lists

* Use fuzzy filtering in the tasks view list

* Use fuzzy filtering in the test tasks list

* Remove the old tasks filtering react hook
2025-04-22 16:34:56 +01:00
Saadi Myftija b62c17bec1 Show more recent payloads in the test task page (#1961) 2025-04-22 16:24:15 +01:00
Saadi Myftija fab565256e Allow empty payloads in test runs (#1962)
* Allow empty payloads in test runs

* Expose a basic linter configs in the code editor component

* Touch up the linting error elements in the code editor component
2025-04-22 16:23:52 +01:00
nicktrn cedd932f99 Fix queued snapshot status handler (#1963)
* handle queued status change gracefully

* add resource monitor to references

* add resource monitor example

* improve runtime manager debug logs

* fix resource monitor example

* add changeset
2025-04-22 15:32:16 +01:00
Matt Aitken e379fc15be Fix redis worker debounce (#1966)
* Added some Redis worker debounce tests (one failing that reproduces a bug)

* Added some tests for acking

* Added a deduplicationKey to prevent acking when items are queued

* The worker passes the deduplicationKey back in for acking

* Improved logs and removed events from test
2025-04-22 15:24:39 +01:00
Dan c0172d428d added cursor rules docs page (#1965) 2025-04-22 15:23:47 +01:00
Dmitry Sabanin 2c19693cfc Fixes runLimiter check on #dequeueRuns (#1953)
* Fixes runLimiter check on #dequeueRuns

This was causing issues in the dev environment with logs being spammed with `[DevSupervisor] dequeueRuns. Run limit reached, trying again later` and making the worker unresponsive and lose connection.

* Create polite-impalas-care.md

---------

Co-authored-by: Eric Allam <eallam@icloud.com>
2025-04-19 21:45:27 +01:00
2620 changed files with 415582 additions and 67956 deletions
-6
View File
@@ -1,6 +0,0 @@
---
"trigger.dev": patch
"@trigger.dev/core": patch
---
The dev command will now use the platform-provided engine URL
-10
View File
@@ -1,10 +0,0 @@
---
"@trigger.dev/react-hooks": patch
"@trigger.dev/sdk": patch
"trigger.dev": patch
"@trigger.dev/build": patch
"@trigger.dev/core": patch
"@trigger.dev/rsc": patch
---
Run Engine 2.0 (alpha)
-5
View File
@@ -1,5 +0,0 @@
---
"@trigger.dev/core": patch
---
Configurable queue consumer count in supervisor session
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/core": patch
---
Fixed TracingSDK.flush() and shutdown() to use Promise.allSettled instead of Promise.all, preventing one provider's rejection from abandoning the other providers' in-flight exports. This fixes an issue where user-emitted trace data (logger.info calls, child spans) could be silently dropped on shutdown when any provider fails to flush.
-12
View File
@@ -1,12 +0,0 @@
---
"@trigger.dev/redis-worker": major
"@trigger.dev/react-hooks": major
"@trigger.dev/sdk": major
"trigger.dev": major
"@trigger.dev/python": major
"@trigger.dev/build": major
"@trigger.dev/core": major
"@trigger.dev/rsc": major
---
Trigger.dev v4 release. Please see our upgrade to v4 docs to view the full changelog: https://trigger.dev/docs/upgrade-to-v4
-5
View File
@@ -1,5 +0,0 @@
---
"@trigger.dev/sdk": patch
---
The envvars.list() and retrieve() functions receive isSecret for each value. Secret values are always redacted.
-5
View File
@@ -1,5 +0,0 @@
---
"@trigger.dev/sdk": patch
---
Fix issue where realtime streams would cut off after 5 minutes
-5
View File
@@ -1,5 +0,0 @@
---
"@trigger.dev/sdk": patch
---
Deprecate toolTask and replace with `ai.tool(mySchemaTask)`
-5
View File
@@ -1,5 +0,0 @@
---
"trigger.dev": patch
---
Fix init.ts in custom trigger dirs
-5
View File
@@ -1,5 +0,0 @@
---
"trigger.dev": patch
---
Init command will now correctly install v4-beta packages
-5
View File
@@ -1,5 +0,0 @@
---
"trigger.dev": patch
---
Improve warm start times by eagerly creating the child TaskRunProcess when a previous run as completed
-5
View File
@@ -1,5 +0,0 @@
---
"trigger.dev": patch
---
Update nypm package to support test-based bun.lock files
-40
View File
@@ -1,40 +0,0 @@
{
"mode": "pre",
"tag": "v4-beta",
"initialVersions": {
"coordinator": "0.0.1",
"docker-provider": "0.0.1",
"kubernetes-provider": "0.0.1",
"supervisor": "0.0.1",
"webapp": "1.0.0",
"@trigger.dev/build": "3.3.17",
"trigger.dev": "3.3.17",
"@trigger.dev/core": "3.3.17",
"@trigger.dev/python": "3.3.17",
"@trigger.dev/react-hooks": "3.3.17",
"@trigger.dev/redis-worker": "3.3.17",
"@trigger.dev/rsc": "3.3.17",
"@trigger.dev/sdk": "3.3.17"
},
"changesets": [
"blue-eyes-tickle",
"breezy-turtles-talk",
"eighty-rings-divide",
"four-needles-add",
"green-lions-relate",
"hip-cups-wave",
"honest-files-decide",
"late-chairs-ring",
"moody-squids-count",
"nice-colts-boil",
"polite-lies-fix",
"red-wasps-cover",
"shiny-kiwis-beam",
"smart-coins-hammer",
"sour-mirrors-accept",
"tiny-buckets-teach",
"tricky-houses-invite",
"two-tigers-dream",
"weak-jobs-hide"
]
}
-5
View File
@@ -1,5 +0,0 @@
---
"@trigger.dev/core": patch
---
Suppress external instrumentation for fetch calls from ApiClient
-5
View File
@@ -1,5 +0,0 @@
---
"trigger.dev": patch
---
Handle flush errors gracefully in dev
-5
View File
@@ -1,5 +0,0 @@
---
"@trigger.dev/core": patch
---
fix: Realtime streams: prevent enqueuing into closed ReadableStream
-6
View File
@@ -1,6 +0,0 @@
---
"trigger.dev": patch
"@trigger.dev/core": patch
---
Improve usage flushing
-5
View File
@@ -1,5 +0,0 @@
---
"trigger.dev": patch
---
Fix stalled run detection
-6
View File
@@ -1,6 +0,0 @@
---
"trigger.dev": patch
"@trigger.dev/core": patch
---
Managed run controller performance and reliability improvements
-5
View File
@@ -1,5 +0,0 @@
---
"@trigger.dev/sdk": patch
---
maintain proper context in metadata.root and parent getters
-7
View File
@@ -1,7 +0,0 @@
---
"@trigger.dev/sdk": patch
"trigger.dev": patch
"@trigger.dev/core": patch
---
v4: New lifecycle hooks
+13
View File
@@ -0,0 +1,13 @@
---
paths:
- "internal-packages/database/**"
---
# Database Migration Safety
- When adding indexes to **existing tables**, use `CREATE INDEX CONCURRENTLY IF NOT EXISTS` to avoid table locks. These must be in their own separate migration file (one index per file).
- Indexes on **newly created tables** (same migration as `CREATE TABLE`) do not need CONCURRENTLY.
- When indexing a **new column on an existing table**, split into two migrations: first `ADD COLUMN IF NOT EXISTS`, then `CREATE INDEX CONCURRENTLY IF NOT EXISTS` in a separate file.
- After generating a migration with Prisma, remove extraneous lines for: `_BackgroundWorkerToBackgroundWorkerFile`, `_BackgroundWorkerToTaskQueue`, `_TaskRunToTaskRunTag`, `_WaitpointRunConnections`, `_completedWaitpoints`, `SecretStore_key_idx`, and unrelated TaskRun indexes.
- Never drop columns or tables without explicit approval.
- New code should target `RunEngineVersion.V2` only.
+14
View File
@@ -0,0 +1,14 @@
---
paths:
- "docs/**"
---
# Documentation Writing Rules
- Use Mintlify MDX format. Frontmatter: `title`, `description`, `sidebarTitle` (optional).
- After creating a new page, add it to `docs.json` navigation under the correct group.
- Use Mintlify components: `<Note>`, `<Warning>`, `<Info>`, `<Tip>`, `<CodeGroup>`, `<Expandable>`, `<Steps>`/`<Step>`.
- Code examples should be complete and runnable where possible.
- Always import from `@trigger.dev/sdk`, never `@trigger.dev/sdk/v3`.
- Keep paragraphs short. Use headers to break up content.
- Link to related pages using relative paths (e.g., `[Tasks](/tasks/overview)`).
+33
View File
@@ -0,0 +1,33 @@
---
paths:
- "apps/webapp/app/v3/**"
---
# Legacy V1 Engine Code in `app/v3/`
The `v3/` directory name is misleading - most code here is actively used by the current V2 engine. Only the specific files below are legacy V1-only code.
## V1-Only Files - Never Modify
- `marqs/` directory (entire MarQS queue system: sharedQueueConsumer, devQueueConsumer, fairDequeuingStrategy, devPubSub)
- `legacyRunEngineWorker.server.ts` (V1 background job worker)
- `services/triggerTaskV1.server.ts` (deprecated V1 task triggering)
- `services/cancelTaskRunV1.server.ts` (deprecated V1 cancellation)
- `authenticatedSocketConnection.server.ts` (V1 dev WebSocket using DevQueueConsumer)
- `sharedSocketConnection.ts` (V1 shared queue socket using SharedQueueConsumer)
## V1/V2 Branching Pattern
Some services act as routers that branch on `RunEngineVersion`:
- `services/cancelTaskRun.server.ts` - calls V1 service or `engine.cancelRun()` for V2
- `services/batchTriggerV3.server.ts` - uses marqs for V1 path, run-engine for V2
When editing these shared services, only modify V2 code paths.
## V2 Modern Stack
- **Run lifecycle**: `@internal/run-engine` (internal-packages/run-engine)
- **Background jobs**: `@trigger.dev/redis-worker` (not graphile-worker/zodworker)
- **Queue operations**: RunQueue inside run-engine (not MarQS)
- **V2 engine singleton**: `runEngine.server.ts`, `runEngineHandlers.server.ts`
- **V2 workers**: `commonWorker.server.ts`, `alertsWorker.server.ts`, `batchTriggerWorker.server.ts`
+12
View File
@@ -0,0 +1,12 @@
---
paths:
- "packages/**"
---
# Public Package Rules
- Changes to `packages/` are **customer-facing**. Always add a changeset: `pnpm run changeset:add`
- Default to **patch**. Get maintainer approval for minor. Never select major without explicit approval.
- `@trigger.dev/core`: **Never import the root**. Always use subpath imports (e.g., `@trigger.dev/core/v3`).
- Do NOT update `rules/` or `.claude/skills/trigger-dev-tasks/` unless explicitly asked. These are maintained in separate dedicated passes.
- Test changes using `references/hello-world` reference project.
+23
View File
@@ -0,0 +1,23 @@
---
paths:
- "apps/**"
---
# Server App Changes
When modifying server apps (webapp, supervisor, coordinator, etc.) with **no package changes**, add a `.server-changes/` file instead of a changeset:
```bash
cat > .server-changes/descriptive-name.md << 'EOF'
---
area: webapp
type: fix
---
Brief description of what changed and why.
EOF
```
- **area**: `webapp` | `supervisor` | `coordinator` | `kubernetes-provider` | `docker-provider`
- **type**: `feature` | `fix` | `improvement` | `breaking`
- If the PR also touches `packages/`, just the changeset is sufficient (no `.server-changes/` needed).
@@ -0,0 +1,78 @@
---
name: span-timeline-events
description: Use when adding, modifying, or debugging OTel span timeline events in the trace view. Covers event structure, ClickHouse storage constraints, rendering in SpanTimeline component, admin visibility, and the step-by-step process for adding new events.
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
---
# Span Timeline Events
The trace view's right panel shows a timeline of events for the selected span. These are OTel span events rendered by `app/utils/timelineSpanEvents.ts` and the `SpanTimeline` component.
## How They Work
1. **Span events** in OTel are attached to a parent span. In ClickHouse, they're stored as separate rows with `kind: "SPAN_EVENT"` sharing the parent span's `span_id`. The `#mergeRecordsIntoSpanDetail` method reassembles them into the span's `events` array at query time.
2. The timeline only renders events whose `name` starts with `trigger.dev/` - all others are silently filtered out.
3. The **display name** comes from `properties.event` (not the span event name), mapped through `getFriendlyNameForEvent()`.
4. Events are shown on the **span they belong to** - events on one span don't appear in another span's timeline.
## ClickHouse Storage Constraint
When events are written to ClickHouse, `spanEventsToTaskEventV1Input()` filters out events whose `start_time` is not greater than the parent span's `startTime`. Events at or before the span start are silently dropped. This means span events must have timestamps strictly after the span's own `startTimeUnixNano`.
## Timeline Rendering (SpanTimeline component)
The `SpanTimeline` component in `app/components/run/RunTimeline.tsx` renders:
1. **Events** (thin 1px line with hollow dots) - all events from `createTimelineSpanEventsFromSpanEvents()`
2. **"Started"** marker (thick cap) - at the span's `startTime`
3. **Duration bar** (thick 7px line) - from "Started" to "Finished"
4. **"Finished"** marker (thick cap) - at `startTime + duration`
The thin line before "Started" only appears when there are events with timestamps between the span start and the first child span. For the Attempt span this works well (Dequeued -> Pod scheduled -> Launched -> etc. all happen before execution starts). Events all get `lineVariant: "light"` (thin) while the execution bar gets `variant: "normal"` (thick).
## Trace View Sort Order
Sibling spans (same parent) are sorted by `start_time ASC` from the ClickHouse query. The `createTreeFromFlatItems` function preserves this order. Event timestamps don't affect sort order - only the span's own `start_time`.
## Event Structure
```typescript
// OTel span event format
{
name: "trigger.dev/run", // Must start with "trigger.dev/" to render
timeUnixNano: "1711200000000000000",
attributes: [
{ key: "event", value: { stringValue: "dequeue" } }, // The actual event type
{ key: "duration", value: { intValue: 150 } }, // Optional: duration in ms
]
}
```
## Admin-Only Events
`getAdminOnlyForEvent()` controls visibility. Events default to **admin-only** (`true`).
| Event | Admin-only | Friendly name |
|-------|-----------|---------------|
| `dequeue` | No | Dequeued |
| `fork` | No | Launched |
| `import` | No (if no fork event) | Importing task file |
| `create_attempt` | Yes | Attempt created |
| `lazy_payload` | Yes | Lazy attempt initialized |
| `pod_scheduled` | Yes | Pod scheduled |
| (default) | Yes | (raw event name) |
## Adding New Timeline Events
1. Add OTLP span event with `name: "trigger.dev/<scope>"` and `properties.event: "<type>"`
2. Event timestamp must be strictly after the parent span's `startTimeUnixNano` (ClickHouse drops earlier events)
3. Add friendly name in `getFriendlyNameForEvent()` in `app/utils/timelineSpanEvents.ts`
4. Set admin visibility in `getAdminOnlyForEvent()`
5. Optionally add help text in `getHelpTextForEvent()`
## Key Files
- `app/utils/timelineSpanEvents.ts` - filtering, naming, admin logic
- `app/components/run/RunTimeline.tsx` - `SpanTimeline` component (thin line + thick bar rendering)
- `app/presenters/v3/SpanPresenter.server.ts` - loads span data including events
- `app/v3/eventRepository/clickhouseEventRepository.server.ts` - `spanEventsToTaskEventV1Input()` (storage filter), `#mergeRecordsIntoSpanDetail` (reassembly)
+200
View File
@@ -0,0 +1,200 @@
---
name: trigger-dev-tasks
description: Use this skill when writing, designing, or optimizing Trigger.dev background tasks and workflows. This includes creating reliable async tasks, implementing AI workflows, setting up scheduled jobs, structuring complex task hierarchies with subtasks, configuring build extensions for tools like ffmpeg or Puppeteer/Playwright, and handling task schemas with Zod validation.
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
---
# Trigger.dev Task Expert
You are an expert Trigger.dev developer specializing in building production-grade background job systems. Tasks deployed to Trigger.dev run in Node.js 21+ and use the `@trigger.dev/sdk` package.
## Critical Rules
1. **Always use `@trigger.dev/sdk`** - Never use `@trigger.dev/sdk/v3` or deprecated `client.defineJob` pattern
2. **Never use `node-fetch`** - Use the built-in `fetch` function
3. **Export all tasks** - Every task must be exported, including subtasks
4. **Never wrap wait/trigger calls in Promise.all** - `triggerAndWait`, `batchTriggerAndWait`, and `wait.*` calls cannot be wrapped in `Promise.all` or `Promise.allSettled`
## Basic Task Pattern
```ts
import { task } from "@trigger.dev/sdk";
export const processData = task({
id: "process-data",
retry: {
maxAttempts: 10,
factor: 1.8,
minTimeoutInMs: 500,
maxTimeoutInMs: 30_000,
},
run: async (payload: { userId: string; data: any[] }) => {
console.log(`Processing ${payload.data.length} items`);
return { processed: payload.data.length };
},
});
```
## Schema Task (with validation)
```ts
import { schemaTask } from "@trigger.dev/sdk";
import { z } from "zod";
export const validatedTask = schemaTask({
id: "validated-task",
schema: z.object({
name: z.string(),
email: z.string().email(),
}),
run: async (payload) => {
// Payload is automatically validated and typed
return { message: `Hello ${payload.name}` };
},
});
```
## Triggering Tasks
### From Backend Code (type-only import to prevent dependency leakage)
```ts
import { tasks } from "@trigger.dev/sdk";
import type { processData } from "./trigger/tasks";
const handle = await tasks.trigger<typeof processData>("process-data", {
userId: "123",
data: [{ id: 1 }],
});
```
### From Inside Tasks
```ts
export const parentTask = task({
id: "parent-task",
run: async (payload) => {
// Trigger and wait - returns Result object, NOT direct output
const result = await childTask.triggerAndWait({ data: "value" });
if (result.ok) {
console.log("Output:", result.output);
} else {
console.error("Failed:", result.error);
}
// Or unwrap directly (throws on error)
const output = await childTask.triggerAndWait({ data: "value" }).unwrap();
},
});
```
## Idempotency (Critical for Retries)
Always use idempotency keys when triggering tasks from inside other tasks:
```ts
import { idempotencyKeys } from "@trigger.dev/sdk";
export const paymentTask = task({
id: "process-payment",
run: async (payload: { orderId: string }) => {
// Scoped to current run - survives retries
const key = await idempotencyKeys.create(`payment-${payload.orderId}`);
await chargeCustomer.trigger(payload, {
idempotencyKey: key,
idempotencyKeyTTL: "24h",
});
},
});
```
## Trigger Options
```ts
await myTask.trigger(payload, {
delay: "1h", // Delay execution
ttl: "10m", // Cancel if not started within TTL
idempotencyKey: key,
queue: "my-queue",
machine: "large-1x", // micro, small-1x, small-2x, medium-1x, medium-2x, large-1x, large-2x
maxAttempts: 3,
tags: ["user_123"], // Max 10 tags
debounce: { // Consolidate rapid triggers
key: "unique-key",
delay: "5s",
mode: "trailing", // "leading" (default) or "trailing"
},
});
```
## Debouncing
Consolidate multiple triggers into a single execution:
```ts
// Rapid triggers with same key = single execution
await myTask.trigger({ userId: "123" }, {
debounce: {
key: "user-123-update",
delay: "5s",
},
});
// Trailing mode: use payload from LAST trigger
await myTask.trigger({ data: "latest" }, {
debounce: {
key: "my-key",
delay: "10s",
mode: "trailing",
},
});
```
Use cases: user activity updates, webhook deduplication, search indexing, notification batching.
## Batch Triggering
Up to 1,000 items per batch, 3MB per payload:
```ts
const results = await myTask.batchTriggerAndWait([
{ payload: { userId: "1" } },
{ payload: { userId: "2" } },
]);
for (const result of results) {
if (result.ok) console.log(result.output);
}
```
## Machine Presets
| Preset | vCPU | Memory |
|-------------|------|--------|
| micro | 0.25 | 0.25GB |
| small-1x | 0.5 | 0.5GB |
| small-2x | 1 | 1GB |
| medium-1x | 1 | 2GB |
| medium-2x | 2 | 4GB |
| large-1x | 4 | 8GB |
| large-2x | 8 | 16GB |
## Design Principles
1. **Break complex workflows into subtasks** that can be independently retried and made idempotent
2. **Don't over-complicate** - Sometimes `Promise.allSettled` inside a single task is better than many subtasks (each task has dedicated process and is charged by millisecond)
3. **Always configure retries** - Set appropriate `maxAttempts` based on the operation
4. **Use idempotency keys** - Especially for payment/critical operations
5. **Group related subtasks** - Keep subtasks only used by one parent in the same file, don't export them
6. **Use logger** - Log at key execution points with `logger.info()`, `logger.error()`, etc.
## Reference Documentation
For detailed documentation on specific topics, read these files:
- `basic-tasks.md` - Task basics, triggering, waits
- `advanced-tasks.md` - Tags, queues, concurrency, metadata, error handling
- `scheduled-tasks.md` - Cron schedules, declarative and imperative
- `realtime.md` - Real-time subscriptions, streams, React hooks
- `config.md` - trigger.config.ts, build extensions (Prisma, Playwright, FFmpeg, etc.)
@@ -0,0 +1,485 @@
# Trigger.dev Advanced Tasks (v4)
**Advanced patterns and features for writing tasks**
## Tags & Organization
```ts
import { task, tags } from "@trigger.dev/sdk";
export const processUser = task({
id: "process-user",
run: async (payload: { userId: string; orgId: string }, { ctx }) => {
// Add tags during execution
await tags.add(`user_${payload.userId}`);
await tags.add(`org_${payload.orgId}`);
return { processed: true };
},
});
// Trigger with tags
await processUser.trigger(
{ userId: "123", orgId: "abc" },
{ tags: ["priority", "user_123", "org_abc"] } // Max 10 tags per run
);
// Subscribe to tagged runs
for await (const run of runs.subscribeToRunsWithTag("user_123")) {
console.log(`User task ${run.id}: ${run.status}`);
}
```
**Tag Best Practices:**
- Use prefixes: `user_123`, `org_abc`, `video:456`
- Max 10 tags per run, 1-64 characters each
- Tags don't propagate to child tasks automatically
## Batch Triggering v2
Enhanced batch triggering with larger payloads and streaming ingestion.
### Limits
- **Maximum batch size**: 1,000 items (increased from 500)
- **Payload per item**: 3MB each (increased from 1MB combined)
- Payloads > 512KB automatically offload to object storage
### Rate Limiting (per environment)
| Tier | Bucket Size | Refill Rate |
|------|-------------|-------------|
| Free | 1,200 runs | 100 runs/10 sec |
| Hobby | 5,000 runs | 500 runs/5 sec |
| Pro | 5,000 runs | 500 runs/5 sec |
### Concurrent Batch Processing
| Tier | Concurrent Batches |
|------|-------------------|
| Free | 1 |
| Hobby | 10 |
| Pro | 10 |
### Usage
```ts
import { myTask } from "./trigger/myTask";
// Basic batch trigger (up to 1,000 items)
const runs = await myTask.batchTrigger([
{ payload: { userId: "user-1" } },
{ payload: { userId: "user-2" } },
{ payload: { userId: "user-3" } },
]);
// Batch trigger with wait
const results = await myTask.batchTriggerAndWait([
{ payload: { userId: "user-1" } },
{ payload: { userId: "user-2" } },
]);
for (const result of results) {
if (result.ok) {
console.log("Result:", result.output);
}
}
// With per-item options
const batchHandle = await myTask.batchTrigger([
{
payload: { userId: "123" },
options: {
idempotencyKey: "user-123-batch",
tags: ["priority"],
},
},
{
payload: { userId: "456" },
options: {
idempotencyKey: "user-456-batch",
},
},
]);
```
## Debouncing
Consolidate multiple triggers into a single execution by debouncing task runs with a unique key and delay window.
### Use Cases
- **User activity updates**: Batch rapid user actions into a single run
- **Webhook deduplication**: Handle webhook bursts without redundant processing
- **Search indexing**: Combine document updates instead of processing individually
- **Notification batching**: Group notifications to prevent user spam
### Basic Usage
```ts
await myTask.trigger(
{ userId: "123" },
{
debounce: {
key: "user-123-update", // Unique identifier for debounce group
delay: "5s", // Wait duration ("5s", "1m", or milliseconds)
},
}
);
```
### Execution Modes
**Leading Mode** (default): Uses payload/options from the first trigger; subsequent triggers only reschedule execution time.
```ts
// First trigger sets the payload
await myTask.trigger({ action: "first" }, {
debounce: { key: "my-key", delay: "10s" }
});
// Second trigger only reschedules - payload remains "first"
await myTask.trigger({ action: "second" }, {
debounce: { key: "my-key", delay: "10s" }
});
// Task executes with { action: "first" }
```
**Trailing Mode**: Uses payload/options from the most recent trigger.
```ts
await myTask.trigger(
{ data: "latest-value" },
{
debounce: {
key: "trailing-example",
delay: "10s",
mode: "trailing",
},
}
);
```
In trailing mode, these options update with each trigger:
- `payload` — task input data
- `metadata` — run metadata
- `tags` — run tags (replaces existing)
- `maxAttempts` — retry attempts
- `maxDuration` — maximum compute time
- `machine` — machine preset
### Important Notes
- Idempotency keys take precedence over debounce settings
- Compatible with `triggerAndWait()` — parent runs block correctly on debounced execution
- Debounce key is scoped to the task
## Concurrency & Queues
```ts
import { task, queue } from "@trigger.dev/sdk";
// Shared queue for related tasks
const emailQueue = queue({
name: "email-processing",
concurrencyLimit: 5, // Max 5 emails processing simultaneously
});
// Task-level concurrency
export const oneAtATime = task({
id: "sequential-task",
queue: { concurrencyLimit: 1 }, // Process one at a time
run: async (payload) => {
// Critical section - only one instance runs
},
});
// Per-user concurrency
export const processUserData = task({
id: "process-user-data",
run: async (payload: { userId: string }) => {
// Override queue with user-specific concurrency
await childTask.trigger(payload, {
queue: {
name: `user-${payload.userId}`,
concurrencyLimit: 2,
},
});
},
});
export const emailTask = task({
id: "send-email",
queue: emailQueue, // Use shared queue
run: async (payload: { to: string }) => {
// Send email logic
},
});
```
## Error Handling & Retries
```ts
import { task, retry, AbortTaskRunError } from "@trigger.dev/sdk";
export const resilientTask = task({
id: "resilient-task",
retry: {
maxAttempts: 10,
factor: 1.8, // Exponential backoff multiplier
minTimeoutInMs: 500,
maxTimeoutInMs: 30_000,
randomize: false,
},
catchError: async ({ error, ctx }) => {
// Custom error handling
if (error.code === "FATAL_ERROR") {
throw new AbortTaskRunError("Cannot retry this error");
}
// Log error details
console.error(`Task ${ctx.task.id} failed:`, error);
// Allow retry by returning nothing
return { retryAt: new Date(Date.now() + 60000) }; // Retry in 1 minute
},
run: async (payload) => {
// Retry specific operations
const result = await retry.onThrow(
async () => {
return await unstableApiCall(payload);
},
{ maxAttempts: 3 }
);
// Conditional HTTP retries
const response = await retry.fetch("https://api.example.com", {
retry: {
maxAttempts: 5,
condition: (response, error) => {
return response?.status === 429 || response?.status >= 500;
},
},
});
return result;
},
});
```
## Machines & Performance
```ts
export const heavyTask = task({
id: "heavy-computation",
machine: { preset: "large-2x" }, // 8 vCPU, 16 GB RAM
maxDuration: 1800, // 30 minutes timeout
run: async (payload, { ctx }) => {
// Resource-intensive computation
if (ctx.machine.preset === "large-2x") {
// Use all available cores
return await parallelProcessing(payload);
}
return await standardProcessing(payload);
},
});
// Override machine when triggering
await heavyTask.trigger(payload, {
machine: { preset: "medium-1x" }, // Override for this run
});
```
**Machine Presets:**
- `micro`: 0.25 vCPU, 0.25 GB RAM
- `small-1x`: 0.5 vCPU, 0.5 GB RAM (default)
- `small-2x`: 1 vCPU, 1 GB RAM
- `medium-1x`: 1 vCPU, 2 GB RAM
- `medium-2x`: 2 vCPU, 4 GB RAM
- `large-1x`: 4 vCPU, 8 GB RAM
- `large-2x`: 8 vCPU, 16 GB RAM
## Idempotency
```ts
import { task, idempotencyKeys } from "@trigger.dev/sdk";
export const paymentTask = task({
id: "process-payment",
retry: {
maxAttempts: 3,
},
run: async (payload: { orderId: string; amount: number }) => {
// Automatically scoped to this task run, so if the task is retried, the idempotency key will be the same
const idempotencyKey = await idempotencyKeys.create(`payment-${payload.orderId}`);
// Ensure payment is processed only once
await chargeCustomer.trigger(payload, {
idempotencyKey,
idempotencyKeyTTL: "24h", // Key expires in 24 hours
});
},
});
// Payload-based idempotency
import { createHash } from "node:crypto";
function createPayloadHash(payload: any): string {
const hash = createHash("sha256");
hash.update(JSON.stringify(payload));
return hash.digest("hex");
}
export const deduplicatedTask = task({
id: "deduplicated-task",
run: async (payload) => {
const payloadHash = createPayloadHash(payload);
const idempotencyKey = await idempotencyKeys.create(payloadHash);
await processData.trigger(payload, { idempotencyKey });
},
});
```
## Metadata & Progress Tracking
```ts
import { task, metadata } from "@trigger.dev/sdk";
export const batchProcessor = task({
id: "batch-processor",
run: async (payload: { items: any[] }, { ctx }) => {
const totalItems = payload.items.length;
// Initialize progress metadata
metadata
.set("progress", 0)
.set("totalItems", totalItems)
.set("processedItems", 0)
.set("status", "starting");
const results = [];
for (let i = 0; i < payload.items.length; i++) {
const item = payload.items[i];
// Process item
const result = await processItem(item);
results.push(result);
// Update progress
const progress = ((i + 1) / totalItems) * 100;
metadata
.set("progress", progress)
.increment("processedItems", 1)
.append("logs", `Processed item ${i + 1}/${totalItems}`)
.set("currentItem", item.id);
}
// Final status
metadata.set("status", "completed");
return { results, totalProcessed: results.length };
},
});
// Update parent metadata from child task
export const childTask = task({
id: "child-task",
run: async (payload, { ctx }) => {
// Update parent task metadata
metadata.parent.set("childStatus", "processing");
metadata.root.increment("childrenCompleted", 1);
return { processed: true };
},
});
```
## Logging & Tracing
```ts
import { task, logger } from "@trigger.dev/sdk";
export const tracedTask = task({
id: "traced-task",
run: async (payload, { ctx }) => {
logger.info("Task started", { userId: payload.userId });
// Custom trace with attributes
const user = await logger.trace(
"fetch-user",
async (span) => {
span.setAttribute("user.id", payload.userId);
span.setAttribute("operation", "database-fetch");
const userData = await database.findUser(payload.userId);
span.setAttribute("user.found", !!userData);
return userData;
},
{ userId: payload.userId }
);
logger.debug("User fetched", { user: user.id });
try {
const result = await processUser(user);
logger.info("Processing completed", { result });
return result;
} catch (error) {
logger.error("Processing failed", {
error: error.message,
userId: payload.userId,
});
throw error;
}
},
});
```
## Hidden Tasks
```ts
// Hidden task - not exported, only used internally
const internalProcessor = task({
id: "internal-processor",
run: async (payload: { data: string }) => {
return { processed: payload.data.toUpperCase() };
},
});
// Public task that uses hidden task
export const publicWorkflow = task({
id: "public-workflow",
run: async (payload: { input: string }) => {
// Use hidden task internally
const result = await internalProcessor.triggerAndWait({
data: payload.input,
});
if (result.ok) {
return { output: result.output.processed };
}
throw new Error("Internal processing failed");
},
});
```
## Best Practices
- **Concurrency**: Use queues to prevent overwhelming external services
- **Retries**: Configure exponential backoff for transient failures
- **Idempotency**: Always use for payment/critical operations
- **Metadata**: Track progress for long-running tasks
- **Machines**: Match machine size to computational requirements
- **Tags**: Use consistent naming patterns for filtering
- **Debouncing**: Use for user activity, webhooks, and notification batching
- **Batch triggering**: Use for bulk operations up to 1,000 items
- **Error Handling**: Distinguish between retryable and fatal errors
Design tasks to be stateless, idempotent, and resilient to failures. Use metadata for state tracking and queues for resource management.
@@ -0,0 +1,199 @@
# Trigger.dev Basic Tasks (v4)
**MUST use `@trigger.dev/sdk`, NEVER `client.defineJob`**
## Basic Task
```ts
import { task } from "@trigger.dev/sdk";
export const processData = task({
id: "process-data",
retry: {
maxAttempts: 10,
factor: 1.8,
minTimeoutInMs: 500,
maxTimeoutInMs: 30_000,
randomize: false,
},
run: async (payload: { userId: string; data: any[] }) => {
// Task logic - runs for long time, no timeouts
console.log(`Processing ${payload.data.length} items for user ${payload.userId}`);
return { processed: payload.data.length };
},
});
```
## Schema Task (with validation)
```ts
import { schemaTask } from "@trigger.dev/sdk";
import { z } from "zod";
export const validatedTask = schemaTask({
id: "validated-task",
schema: z.object({
name: z.string(),
age: z.number(),
email: z.string().email(),
}),
run: async (payload) => {
// Payload is automatically validated and typed
return { message: `Hello ${payload.name}, age ${payload.age}` };
},
});
```
## Triggering Tasks
### From Backend Code
```ts
import { tasks } from "@trigger.dev/sdk";
import type { processData } from "./trigger/tasks";
// Single trigger
const handle = await tasks.trigger<typeof processData>("process-data", {
userId: "123",
data: [{ id: 1 }, { id: 2 }],
});
// Batch trigger (up to 1,000 items, 3MB per payload)
const batchHandle = await tasks.batchTrigger<typeof processData>("process-data", [
{ payload: { userId: "123", data: [{ id: 1 }] } },
{ payload: { userId: "456", data: [{ id: 2 }] } },
]);
```
### Debounced Triggering
Consolidate multiple triggers into a single execution:
```ts
// Multiple rapid triggers with same key = single execution
await myTask.trigger(
{ userId: "123" },
{
debounce: {
key: "user-123-update", // Unique key for debounce group
delay: "5s", // Wait before executing
},
}
);
// Trailing mode: use payload from LAST trigger
await myTask.trigger(
{ data: "latest-value" },
{
debounce: {
key: "trailing-example",
delay: "10s",
mode: "trailing", // Default is "leading" (first payload)
},
}
);
```
**Debounce modes:**
- `leading` (default): Uses payload from first trigger, subsequent triggers only reschedule
- `trailing`: Uses payload from most recent trigger
### From Inside Tasks (with Result handling)
```ts
export const parentTask = task({
id: "parent-task",
run: async (payload) => {
// Trigger and continue
const handle = await childTask.trigger({ data: "value" });
// Trigger and wait - returns Result object, NOT task output
const result = await childTask.triggerAndWait({ data: "value" });
if (result.ok) {
console.log("Task output:", result.output); // Actual task return value
} else {
console.error("Task failed:", result.error);
}
// Quick unwrap (throws on error)
const output = await childTask.triggerAndWait({ data: "value" }).unwrap();
// Batch trigger and wait
const results = await childTask.batchTriggerAndWait([
{ payload: { data: "item1" } },
{ payload: { data: "item2" } },
]);
for (const run of results) {
if (run.ok) {
console.log("Success:", run.output);
} else {
console.log("Failed:", run.error);
}
}
},
});
export const childTask = task({
id: "child-task",
run: async (payload: { data: string }) => {
return { processed: payload.data };
},
});
```
> Never wrap triggerAndWait or batchTriggerAndWait calls in a Promise.all or Promise.allSettled as this is not supported in Trigger.dev tasks.
## Waits
```ts
import { task, wait } from "@trigger.dev/sdk";
export const taskWithWaits = task({
id: "task-with-waits",
run: async (payload) => {
console.log("Starting task");
// Wait for specific duration
await wait.for({ seconds: 30 });
await wait.for({ minutes: 5 });
await wait.for({ hours: 1 });
await wait.for({ days: 1 });
// Wait until specific date
await wait.until({ date: new Date("2024-12-25") });
// Wait for token (from external system)
await wait.forToken({
token: "user-approval-token",
timeoutInSeconds: 3600, // 1 hour timeout
});
console.log("All waits completed");
return { status: "completed" };
},
});
```
> Never wrap wait calls in a Promise.all or Promise.allSettled as this is not supported in Trigger.dev tasks.
## Key Points
- **Result vs Output**: `triggerAndWait()` returns a `Result` object with `ok`, `output`, `error` properties - NOT the direct task output
- **Type safety**: Use `import type` for task references when triggering from backend
- **Waits > 5 seconds**: Automatically checkpointed, don't count toward compute usage
- **Debounce + idempotency**: Idempotency keys take precedence over debounce settings
## NEVER Use (v2 deprecated)
```ts
// BREAKS APPLICATION
client.defineJob({
id: "job-id",
run: async (payload, io) => {
/* ... */
},
});
```
Use SDK (`@trigger.dev/sdk`), check `result.ok` before accessing `result.output`
+346
View File
@@ -0,0 +1,346 @@
# Trigger.dev Configuration
**Complete guide to configuring `trigger.config.ts` with build extensions**
## Basic Configuration
```ts
import { defineConfig } from "@trigger.dev/sdk";
export default defineConfig({
project: "<project-ref>", // Required: Your project reference
dirs: ["./trigger"], // Task directories
runtime: "node", // "node", "node-22", or "bun"
logLevel: "info", // "debug", "info", "warn", "error"
// Default retry settings
retries: {
enabledInDev: false,
default: {
maxAttempts: 3,
minTimeoutInMs: 1000,
maxTimeoutInMs: 10000,
factor: 2,
randomize: true,
},
},
// Build configuration
build: {
autoDetectExternal: true,
keepNames: true,
minify: false,
extensions: [], // Build extensions go here
},
// Global lifecycle hooks
onStartAttempt: async ({ payload, ctx }) => {
console.log("Global task start");
},
onSuccess: async ({ payload, output, ctx }) => {
console.log("Global task success");
},
onFailure: async ({ payload, error, ctx }) => {
console.log("Global task failure");
},
});
```
## Build Extensions
### Database & ORM
#### Prisma
```ts
import { prismaExtension } from "@trigger.dev/build/extensions/prisma";
extensions: [
prismaExtension({
schema: "prisma/schema.prisma",
version: "5.19.0", // Optional: specify version
migrate: true, // Run migrations during build
directUrlEnvVarName: "DIRECT_DATABASE_URL",
typedSql: true, // Enable TypedSQL support
}),
];
```
#### TypeScript Decorators (for TypeORM)
```ts
import { emitDecoratorMetadata } from "@trigger.dev/build/extensions/typescript";
extensions: [
emitDecoratorMetadata(), // Enables decorator metadata
];
```
### Scripting Languages
#### Python
```ts
import { pythonExtension } from "@trigger.dev/build/extensions/python";
extensions: [
pythonExtension({
scripts: ["./python/**/*.py"], // Copy Python files
requirementsFile: "./requirements.txt", // Install packages
devPythonBinaryPath: ".venv/bin/python", // Dev mode binary
}),
];
// Usage in tasks
const result = await python.runInline(`print("Hello, world!")`);
const output = await python.runScript("./python/script.py", ["arg1"]);
```
### Browser Automation
#### Playwright
```ts
import { playwright } from "@trigger.dev/build/extensions/playwright";
extensions: [
playwright({
browsers: ["chromium", "firefox", "webkit"], // Default: ["chromium"]
headless: true, // Default: true
}),
];
```
#### Puppeteer
```ts
import { puppeteer } from "@trigger.dev/build/extensions/puppeteer";
extensions: [puppeteer()];
// Environment variable needed:
// PUPPETEER_EXECUTABLE_PATH: "/usr/bin/google-chrome-stable"
```
#### Lightpanda
```ts
import { lightpanda } from "@trigger.dev/build/extensions/lightpanda";
extensions: [
lightpanda({
version: "latest", // or "nightly"
disableTelemetry: false,
}),
];
```
### Media Processing
#### FFmpeg
```ts
import { ffmpeg } from "@trigger.dev/build/extensions/core";
extensions: [
ffmpeg({ version: "7" }), // Static build, or omit for Debian version
];
// Automatically sets FFMPEG_PATH and FFPROBE_PATH
// Add fluent-ffmpeg to external packages if using
```
#### Audio Waveform
```ts
import { audioWaveform } from "@trigger.dev/build/extensions/audioWaveform";
extensions: [
audioWaveform(), // Installs Audio Waveform 1.1.0
];
```
### System & Package Management
#### System Packages (apt-get)
```ts
import { aptGet } from "@trigger.dev/build/extensions/core";
extensions: [
aptGet({
packages: ["ffmpeg", "imagemagick", "curl=7.68.0-1"], // Can specify versions
}),
];
```
#### Additional NPM Packages
Only use this for installing CLI tools, NOT packages you import in your code.
```ts
import { additionalPackages } from "@trigger.dev/build/extensions/core";
extensions: [
additionalPackages({
packages: ["wrangler"], // CLI tools and specific versions
}),
];
```
#### Additional Files
```ts
import { additionalFiles } from "@trigger.dev/build/extensions/core";
extensions: [
additionalFiles({
files: ["wrangler.toml", "./assets/**", "./fonts/**"], // Glob patterns supported
}),
];
```
### Environment & Build Tools
#### Environment Variable Sync
```ts
import { syncEnvVars } from "@trigger.dev/build/extensions/core";
extensions: [
syncEnvVars(async (ctx) => {
// ctx contains: environment, projectRef, env
return [
{ name: "SECRET_KEY", value: await getSecret(ctx.environment) },
{ name: "API_URL", value: ctx.environment === "prod" ? "api.prod.com" : "api.dev.com" },
];
}),
];
```
#### ESBuild Plugins
```ts
import { esbuildPlugin } from "@trigger.dev/build/extensions";
import { sentryEsbuildPlugin } from "@sentry/esbuild-plugin";
extensions: [
esbuildPlugin(
sentryEsbuildPlugin({
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
}),
{ placement: "last", target: "deploy" } // Optional config
),
];
```
## Custom Build Extensions
```ts
import { defineConfig } from "@trigger.dev/sdk";
const customExtension = {
name: "my-custom-extension",
externalsForTarget: (target) => {
return ["some-native-module"]; // Add external dependencies
},
onBuildStart: async (context) => {
console.log(`Build starting for ${context.target}`);
// Register esbuild plugins, modify build context
},
onBuildComplete: async (context, manifest) => {
console.log("Build complete, adding layers");
// Add build layers, modify deployment
context.addLayer({
id: "my-layer",
files: [{ source: "./custom-file", destination: "/app/custom" }],
commands: ["chmod +x /app/custom"],
});
},
};
export default defineConfig({
project: "my-project",
build: {
extensions: [customExtension],
},
});
```
## Advanced Configuration
### Telemetry
```ts
import { PrismaInstrumentation } from "@prisma/instrumentation";
import { OpenAIInstrumentation } from "@langfuse/openai";
export default defineConfig({
// ... other config
telemetry: {
instrumentations: [new PrismaInstrumentation(), new OpenAIInstrumentation()],
exporters: [customExporter], // Optional custom exporters
},
});
```
### Machine & Performance
```ts
export default defineConfig({
// ... other config
defaultMachine: "large-1x", // Default machine for all tasks
maxDuration: 300, // Default max duration (seconds)
enableConsoleLogging: true, // Console logging in development
});
```
## Common Extension Combinations
### Full-Stack Web App
```ts
extensions: [
prismaExtension({ schema: "prisma/schema.prisma", migrate: true }),
additionalFiles({ files: ["./public/**", "./assets/**"] }),
syncEnvVars(async (ctx) => [...envVars]),
];
```
### AI/ML Processing
```ts
extensions: [
pythonExtension({
scripts: ["./ai/**/*.py"],
requirementsFile: "./requirements.txt",
}),
ffmpeg({ version: "7" }),
additionalPackages({ packages: ["wrangler"] }),
];
```
### Web Scraping
```ts
extensions: [
playwright({ browsers: ["chromium"] }),
puppeteer(),
additionalFiles({ files: ["./selectors.json", "./proxies.txt"] }),
];
```
## Best Practices
- **Use specific versions**: Pin extension versions for reproducible builds
- **External packages**: Add modules with native addons to the `build.external` array
- **Environment sync**: Use `syncEnvVars` for dynamic secrets
- **File paths**: Use glob patterns for flexible file inclusion
- **Debug builds**: Use `--log-level debug --dry-run` for troubleshooting
Extensions only affect deployment, not local development. Use `external` array for packages that shouldn't be bundled.
@@ -0,0 +1,244 @@
# Trigger.dev Realtime
**Real-time monitoring and updates for runs**
## Core Concepts
Realtime allows you to:
- Subscribe to run status changes, metadata updates, and streams
- Build real-time dashboards and UI updates
- Monitor task progress from frontend and backend
## Authentication
### Public Access Tokens
```ts
import { auth } from "@trigger.dev/sdk";
// Read-only token for specific runs
const publicToken = await auth.createPublicToken({
scopes: {
read: {
runs: ["run_123", "run_456"],
tasks: ["my-task-1", "my-task-2"],
},
},
expirationTime: "1h", // Default: 15 minutes
});
```
### Trigger Tokens (Frontend only)
```ts
// Single-use token for triggering tasks
const triggerToken = await auth.createTriggerPublicToken("my-task", {
expirationTime: "30m",
});
```
## Backend Usage
### Subscribe to Runs
```ts
import { runs, tasks } from "@trigger.dev/sdk";
// Trigger and subscribe
const handle = await tasks.trigger("my-task", { data: "value" });
// Subscribe to specific run
for await (const run of runs.subscribeToRun<typeof myTask>(handle.id)) {
console.log(`Status: ${run.status}, Progress: ${run.metadata?.progress}`);
if (run.status === "COMPLETED") break;
}
// Subscribe to runs with tag
for await (const run of runs.subscribeToRunsWithTag("user-123")) {
console.log(`Tagged run ${run.id}: ${run.status}`);
}
// Subscribe to batch
for await (const run of runs.subscribeToBatch(batchId)) {
console.log(`Batch run ${run.id}: ${run.status}`);
}
```
### Realtime Streams v2
```ts
import { streams, InferStreamType } from "@trigger.dev/sdk";
// 1. Define streams (shared location)
export const aiStream = streams.define<string>({
id: "ai-output",
});
export type AIStreamPart = InferStreamType<typeof aiStream>;
// 2. Pipe from task
export const streamingTask = task({
id: "streaming-task",
run: async (payload) => {
const completion = await openai.chat.completions.create({
model: "gpt-4",
messages: [{ role: "user", content: payload.prompt }],
stream: true,
});
const { waitUntilComplete } = aiStream.pipe(completion);
await waitUntilComplete();
},
});
// 3. Read from backend
const stream = await aiStream.read(runId, {
timeoutInSeconds: 300,
startIndex: 0, // Resume from specific chunk
});
for await (const chunk of stream) {
console.log("Chunk:", chunk); // Fully typed
}
```
## React Frontend Usage
### Installation
```bash
npm add @trigger.dev/react-hooks
```
### Triggering Tasks
```tsx
"use client";
import { useTaskTrigger, useRealtimeTaskTrigger } from "@trigger.dev/react-hooks";
import type { myTask } from "../trigger/tasks";
function TriggerComponent({ accessToken }: { accessToken: string }) {
// Basic trigger
const { submit, handle, isLoading } = useTaskTrigger<typeof myTask>("my-task", {
accessToken,
});
// Trigger with realtime updates
const {
submit: realtimeSubmit,
run,
isLoading: isRealtimeLoading,
} = useRealtimeTaskTrigger<typeof myTask>("my-task", { accessToken });
return (
<div>
<button onClick={() => submit({ data: "value" })} disabled={isLoading}>
Trigger Task
</button>
<button onClick={() => realtimeSubmit({ data: "realtime" })} disabled={isRealtimeLoading}>
Trigger with Realtime
</button>
{run && <div>Status: {run.status}</div>}
</div>
);
}
```
### Subscribing to Runs
```tsx
"use client";
import { useRealtimeRun, useRealtimeRunsWithTag } from "@trigger.dev/react-hooks";
import type { myTask } from "../trigger/tasks";
function SubscribeComponent({ runId, accessToken }: { runId: string; accessToken: string }) {
// Subscribe to specific run
const { run, error } = useRealtimeRun<typeof myTask>(runId, {
accessToken,
onComplete: (run) => {
console.log("Task completed:", run.output);
},
});
// Subscribe to tagged runs
const { runs } = useRealtimeRunsWithTag("user-123", { accessToken });
if (error) return <div>Error: {error.message}</div>;
if (!run) return <div>Loading...</div>;
return (
<div>
<div>Status: {run.status}</div>
<div>Progress: {run.metadata?.progress || 0}%</div>
{run.output && <div>Result: {JSON.stringify(run.output)}</div>}
<h3>Tagged Runs:</h3>
{runs.map((r) => (
<div key={r.id}>
{r.id}: {r.status}
</div>
))}
</div>
);
}
```
### Realtime Streams with React
```tsx
"use client";
import { useRealtimeStream } from "@trigger.dev/react-hooks";
import { aiStream } from "../trigger/streams";
function StreamComponent({ runId, accessToken }: { runId: string; accessToken: string }) {
// Pass defined stream directly for type safety
const { parts, error } = useRealtimeStream(aiStream, runId, {
accessToken,
timeoutInSeconds: 300,
throttleInMs: 50, // Control re-render frequency
});
if (error) return <div>Error: {error.message}</div>;
if (!parts) return <div>Loading...</div>;
const text = parts.join(""); // parts is typed as AIStreamPart[]
return <div>Streamed Text: {text}</div>;
}
```
### Wait Tokens
```tsx
"use client";
import { useWaitToken } from "@trigger.dev/react-hooks";
function WaitTokenComponent({ tokenId, accessToken }: { tokenId: string; accessToken: string }) {
const { complete } = useWaitToken(tokenId, { accessToken });
return <button onClick={() => complete({ approved: true })}>Approve Task</button>;
}
```
## Run Object Properties
Key properties available in run subscriptions:
- `id`: Unique run identifier
- `status`: `QUEUED`, `EXECUTING`, `COMPLETED`, `FAILED`, `CANCELED`, etc.
- `payload`: Task input data (typed)
- `output`: Task result (typed, when completed)
- `metadata`: Real-time updatable data
- `createdAt`, `updatedAt`: Timestamps
- `costInCents`: Execution cost
## Best Practices
- **Use Realtime over SWR**: Recommended for most use cases due to rate limits
- **Scope tokens properly**: Only grant necessary read/trigger permissions
- **Handle errors**: Always check for errors in hooks and subscriptions
- **Type safety**: Use task types for proper payload/output typing
- **Cleanup subscriptions**: Backend subscriptions auto-complete, frontend hooks auto-cleanup
@@ -0,0 +1,113 @@
# Scheduled Tasks (Cron)
Recurring tasks using cron. For one-off future runs, use the **delay** option.
## Define a Scheduled Task
```ts
import { schedules } from "@trigger.dev/sdk";
export const task = schedules.task({
id: "first-scheduled-task",
run: async (payload) => {
payload.timestamp; // Date (scheduled time, UTC)
payload.lastTimestamp; // Date | undefined
payload.timezone; // IANA, e.g. "America/New_York" (default "UTC")
payload.scheduleId; // string
payload.externalId; // string | undefined
payload.upcoming; // Date[]
payload.timestamp.toLocaleString("en-US", { timeZone: payload.timezone });
},
});
```
> Scheduled tasks need at least one schedule attached to run.
## Attach Schedules
**Declarative (sync on dev/deploy):**
```ts
schedules.task({
id: "every-2h",
cron: "0 */2 * * *", // UTC
run: async () => {},
});
schedules.task({
id: "tokyo-5am",
cron: { pattern: "0 5 * * *", timezone: "Asia/Tokyo", environments: ["PRODUCTION", "STAGING"] },
run: async () => {},
});
```
**Imperative (SDK or dashboard):**
```ts
await schedules.create({
task: task.id,
cron: "0 0 * * *",
timezone: "America/New_York", // DST-aware
externalId: "user_123",
deduplicationKey: "user_123-daily", // updates if reused
});
```
### Dynamic / Multi-tenant Example
```ts
// /trigger/reminder.ts
export const reminderTask = schedules.task({
id: "todo-reminder",
run: async (p) => {
if (!p.externalId) throw new Error("externalId is required");
const user = await db.getUser(p.externalId);
await sendReminderEmail(user);
},
});
```
```ts
// app/reminders/route.ts
export async function POST(req: Request) {
const data = await req.json();
return Response.json(
await schedules.create({
task: reminderTask.id,
cron: "0 8 * * *",
timezone: data.timezone,
externalId: data.userId,
deduplicationKey: `${data.userId}-reminder`,
})
);
}
```
## Cron Syntax (no seconds)
```
* * * * *
| | | | └ day of week (07 or 1L7L; 0/7=Sun; L=last)
| | | └── month (112)
| | └──── day of month (131 or L)
| └────── hour (023)
└──────── minute (059)
```
## When Schedules Won't Trigger
- **Dev:** only when the dev CLI is running.
- **Staging/Production:** only for tasks in the **latest deployment**.
## SDK Management
```ts
await schedules.retrieve(id);
await schedules.list();
await schedules.update(id, { cron: "0 0 1 * *", externalId: "ext", deduplicationKey: "key" });
await schedules.deactivate(id);
await schedules.activate(id);
await schedules.del(id);
await schedules.timezones(); // list of IANA timezones
```
+11
View File
@@ -0,0 +1,11 @@
# Remove AI code slop
Check the diff against main, and remove all AI generated slop introduced in this branch.
This includes:
- Extra comments that a human wouldn't add or is inconsistent with the rest of the file
- Extra defensive checks or try/catch blocks that are abnormal for that area of the codebase (especially if called by trusted / validated codepaths)
- Casts to any to get around type issues
- Any other style that is inconsistent with the file
Report at the end with only a 1-3 sentence summary of what you changed
+2 -6
View File
@@ -1,7 +1,3 @@
{
"mcpServers": {
"trigger.dev": {
"url": "http://localhost:3333/sse"
}
}
}
"mcpServers": {}
}
+6
View File
@@ -0,0 +1,6 @@
---
description: how to create and apply database migrations
alwaysApply: false
---
Follow our [migrations.md](mdc:ai/references/migrations.md) guide for how to create and apply database migrations.
+66
View File
@@ -0,0 +1,66 @@
---
description: Guidelines for creating OpenTelemetry metrics to avoid cardinality issues
globs:
- "**/*.ts"
---
# OpenTelemetry Metrics Guidelines
When creating or editing OTEL metrics (counters, histograms, gauges), always ensure metric attributes have **low cardinality**.
## What is Cardinality?
Cardinality refers to the number of unique values an attribute can have. Each unique combination of attribute values creates a new time series, which consumes memory and storage in your metrics backend.
## Rules
### DO use low-cardinality attributes:
- **Enums**: `environment_type` (PRODUCTION, STAGING, DEVELOPMENT, PREVIEW)
- **Booleans**: `hasFailures`, `streaming`, `success`
- **Bounded error codes**: A finite, controlled set of error types
- **Shard IDs**: When sharding is bounded (e.g., 0-15)
### DO NOT use high-cardinality attributes:
- **UUIDs/IDs**: `envId`, `userId`, `runId`, `projectId`, `organizationId`
- **Unbounded integers**: `itemCount`, `batchSize`, `retryCount`
- **Timestamps**: `createdAt`, `startTime`
- **Free-form strings**: `errorMessage`, `taskName`, `queueName`
## Example
```typescript
// BAD - High cardinality
this.counter.add(1, {
envId: options.environmentId, // UUID - unbounded
itemCount: options.runCount, // Integer - unbounded
});
// GOOD - Low cardinality
this.counter.add(1, {
environment_type: options.environmentType, // Enum - 4 values
streaming: true, // Boolean - 2 values
});
```
## Prometheus Metric Naming
When metrics are exported via OTLP to Prometheus, the exporter automatically adds unit suffixes to metric names:
| OTel Metric Name | Unit | Prometheus Name |
|------------------|------|-----------------|
| `my_duration_ms` | `ms` | `my_duration_ms_milliseconds` |
| `my_counter` | counter | `my_counter_total` |
| `items_inserted` | counter | `items_inserted_inserts_total` |
| `batch_size` | histogram | `batch_size_items_bucket` |
Keep this in mind when writing Grafana dashboards or Prometheus queries—the metric names in Prometheus will differ from the names defined in code.
## Reference
See the schedule engine (`internal-packages/schedule-engine/src/engine/index.ts`) for a good example of low-cardinality metric attributes.
High cardinality metrics can cause:
- Memory bloat in metrics backends (Axiom, Prometheus, etc.)
- Slow queries and dashboard timeouts
- Increased costs (many backends charge per time series)
- Potential data loss or crashes at scale
+7 -4
View File
@@ -4,9 +4,9 @@ globs: apps/webapp/**/*.tsx,apps/webapp/**/*.ts
alwaysApply: false
---
The main trigger.dev webapp, which powers it's API and dashboard and makes up the docker image that is produced as an OSS image, is a Remix 2.1.0 app that uses an express server, written in TypeScript. The following subsystems are either included in the webapp or are used by the webapp in another part of the monorepo:
The main trigger.dev webapp, which powers it's API and dashboard and makes up the docker image that is produced as an OSS image, is a Remix 2.17.4 app that uses an express server, written in TypeScript. The following subsystems are either included in the webapp or are used by the webapp in another part of the monorepo:
- `@trigger.dev/database` exports a Prisma 5.4.1 client that is used extensively in the webapp to access a PostgreSQL instance. The schema file is [schema.prisma](mdc:internal-packages/database/prisma/schema.prisma)
- `@trigger.dev/database` exports a Prisma 6.14.0 client that is used extensively in the webapp to access a PostgreSQL instance. The schema file is [schema.prisma](mdc:internal-packages/database/prisma/schema.prisma)
- `@trigger.dev/core` is a published package and is used to share code between the `@trigger.dev/sdk` and the webapp. It includes functionality but also a load of Zod schemas for data validation. When importing from `@trigger.dev/core` in the webapp, we never import the root `@trigger.dev/core` path, instead we favor one of the subpath exports that you can find in [package.json](mdc:packages/core/package.json)
- `@internal/run-engine` has all the code needed to trigger a run and take it through it's lifecycle to completion.
- `@trigger.dev/redis-worker` is a custom redis based background job/worker system that's used in the webapp and also used inside the run engine.
@@ -31,7 +31,10 @@ We originally the Trigger.dev "Run Engine" not as a single system, but just spre
- The batch trigger API endpoint is [api.v1.tasks.batch.ts](mdc:apps/webapp/app/routes/api.v1.tasks.batch.ts)
- Setup code for the prisma client is in [db.server.ts](mdc:apps/webapp/app/db.server.ts)
- The run engine is configured in [runEngine.server.ts](mdc:apps/webapp/app/v3/runEngine.server.ts)
- All the "services" that are found in app/v3/services/**/*.server.ts
- All the "services" that are found in app/v3/services/\*_/_.server.ts
- The code for the TaskEvent data, which is the otel data sent from tasks to our servers, is in both the [eventRepository.server.ts](mdc:apps/webapp/app/v3/eventRepository.server.ts) and also the [otlpExporter.server.ts](mdc:apps/webapp/app/v3/otlpExporter.server.ts). The otel endpoints which are hit from production and development otel exporters is [otel.v1.logs.ts](mdc:apps/webapp/app/routes/otel.v1.logs.ts) and [otel.v1.traces.ts](mdc:apps/webapp/app/routes/otel.v1.traces.ts)
- We use "presenters" to move more complex loader code into a class, and you can find those are app/v3/presenters/**/*.server.ts
- We use "presenters" to move more complex loader code into a class, and you can find those are app/v3/presenters/\*_/_.server.ts
- All the "services" that are found in app/v3/services/\*_/_.server.ts
- The code for the TaskEvent data, which is the otel data sent from tasks to our servers, is in both the [eventRepository.server.ts](mdc:apps/webapp/app/v3/eventRepository.server.ts) and also the [otlpExporter.server.ts](mdc:apps/webapp/app/v3/otlpExporter.server.ts). The otel endpoints which are hit from production and development otel exporters is [otel.v1.logs.ts](mdc:apps/webapp/app/routes/otel.v1.logs.ts) and [otel.v1.traces.ts](mdc:apps/webapp/app/routes/otel.v1.traces.ts)
- We use "presenters" to move more complex loader code into a class, and you can find those are app/v3/presenters/\*_/_.server.ts
+19 -41
View File
@@ -14,7 +14,7 @@ alwaysApply: false
## Essential requirements when generating task code
1. You MUST use `@trigger.dev/sdk/v3`
1. You MUST import from `@trigger.dev/sdk` (NEVER `@trigger.dev/sdk/v3`)
2. You MUST NEVER use `client.defineJob`
3. YOU MUST `export` every task, including subtasks
4. If you are able to generate an example payload for a task, do so.
@@ -53,7 +53,7 @@ Instead, you MUST ALWAYS generate ONLY this pattern:
```ts
// ✅ ALWAYS GENERATE THIS EXACT PATTERN
import { task } from "@trigger.dev/sdk/v3";
import { task } from "@trigger.dev/sdk";
//1. You need to export each task, even if it's a subtask
export const helloWorld = task({
@@ -71,7 +71,7 @@ export const helloWorld = task({
A task is a function that can run for a long time with resilience to failure:
```ts
import { task } from "@trigger.dev/sdk/v3";
import { task } from "@trigger.dev/sdk";
export const helloWorld = task({
id: "hello-world",
@@ -271,7 +271,7 @@ Global lifecycle hooks can also be defined in `trigger.config.ts` to apply to al
## Correct Schedules task (cron) implementations
```ts
import { schedules } from "@trigger.dev/sdk/v3";
import { schedules } from "@trigger.dev/sdk";
export const firstScheduledTask = schedules.task({
id: "first-scheduled-task",
@@ -312,7 +312,7 @@ export const firstScheduledTask = schedules.task({
### Attach a Declarative schedule
```ts
import { schedules } from "@trigger.dev/sdk/v3";
import { schedules } from "@trigger.dev/sdk";
// Sepcify a cron pattern (UTC)
export const firstScheduledTask = schedules.task({
@@ -326,7 +326,7 @@ export const firstScheduledTask = schedules.task({
```
```ts
import { schedules } from "@trigger.dev/sdk/v3";
import { schedules } from "@trigger.dev/sdk";
// Specify a specific timezone like this:
export const secondScheduledTask = schedules.task({
@@ -375,7 +375,7 @@ const createdSchedule = await schedules.create({
Schema tasks validate payloads against a schema before execution:
```ts
import { schemaTask } from "@trigger.dev/sdk/v3";
import { schemaTask } from "@trigger.dev/sdk";
import { z } from "zod";
const myTask = schemaTask({
@@ -400,7 +400,7 @@ When you trigger a task from your backend code, you need to set the `TRIGGER_SEC
Triggers a single run of a task with specified payload and options without importing the task. Use type-only imports for full type checking.
```ts
import { tasks } from "@trigger.dev/sdk/v3";
import { tasks } from "@trigger.dev/sdk";
import type { emailSequence } from "~/trigger/emails";
export async function POST(request: Request) {
@@ -418,7 +418,7 @@ export async function POST(request: Request) {
Triggers multiple runs of a single task with different payloads without importing the task.
```ts
import { tasks } from "@trigger.dev/sdk/v3";
import { tasks } from "@trigger.dev/sdk";
import type { emailSequence } from "~/trigger/emails";
export async function POST(request: Request) {
@@ -431,34 +431,12 @@ export async function POST(request: Request) {
}
```
### tasks.triggerAndPoll()
Triggers a task and polls until completion. Not recommended for web requests as it blocks until the run completes. Consider using Realtime docs for better alternatives.
```ts
import { tasks } from "@trigger.dev/sdk/v3";
import type { emailSequence } from "~/trigger/emails";
export async function POST(request: Request) {
const data = await request.json();
const result = await tasks.triggerAndPoll<typeof emailSequence>(
"email-sequence",
{
to: data.email,
name: data.name,
},
{ pollIntervalMs: 5000 }
);
return Response.json(result);
}
```
### batch.trigger()
Triggers multiple runs of different tasks at once, useful when you need to execute multiple tasks simultaneously.
```ts
import { batch } from "@trigger.dev/sdk/v3";
import { batch } from "@trigger.dev/sdk";
import type { myTask1, myTask2 } from "~/trigger/myTasks";
export async function POST(request: Request) {
@@ -643,7 +621,7 @@ const handle = await myTask.trigger(
Access metadata inside a run:
```ts
import { task, metadata } from "@trigger.dev/sdk/v3";
import { task, metadata } from "@trigger.dev/sdk";
export const myTask = task({
id: "my-task",
@@ -735,7 +713,7 @@ Trigger.dev Realtime enables subscribing to runs for real-time updates on run st
Subscribe to a run after triggering a task:
```ts
import { runs, tasks } from "@trigger.dev/sdk/v3";
import { runs, tasks } from "@trigger.dev/sdk";
async function myBackend() {
const handle = await tasks.trigger("my-task", { some: "data" });
@@ -757,7 +735,7 @@ async function myBackend() {
You can infer types of run's payload and output by passing the task type:
```ts
import { runs } from "@trigger.dev/sdk/v3";
import { runs } from "@trigger.dev/sdk";
import type { myTask } from "./trigger/my-task";
for await (const run of runs.subscribeToRun<typeof myTask>(handle.id)) {
@@ -774,7 +752,7 @@ for await (const run of runs.subscribeToRun<typeof myTask>(handle.id)) {
Stream data in realtime from inside your tasks using the metadata system:
```ts
import { task, metadata } from "@trigger.dev/sdk/v3";
import { task, metadata } from "@trigger.dev/sdk";
import OpenAI from "openai";
export type STREAMS = {
@@ -969,7 +947,7 @@ For most use cases, Realtime hooks are preferred over SWR hooks with polling due
For client-side usage, generate a public access token with appropriate scopes:
```ts
import { auth } from "@trigger.dev/sdk/v3";
import { auth } from "@trigger.dev/sdk";
const publicToken = await auth.createPublicToken({
scopes: {
@@ -989,7 +967,7 @@ Idempotency ensures that an operation produces the same result when called multi
Provide an `idempotencyKey` when triggering a task to ensure it runs only once with that key:
```ts
import { idempotencyKeys, task } from "@trigger.dev/sdk/v3";
import { idempotencyKeys, task } from "@trigger.dev/sdk";
export const myTask = task({
id: "my-task",
@@ -1080,7 +1058,7 @@ function hash(payload: any): string {
```ts
// onFailure executes after all retries are exhausted; use for notifications, logging, or side effects on final failure:
import { task, logger } from "@trigger.dev/sdk/v3";
import { task, logger } from "@trigger.dev/sdk";
export const loggingExample = task({
id: "logging-example",
@@ -1100,7 +1078,7 @@ export const loggingExample = task({
The `trigger.config.ts` file configures your Trigger.dev project, specifying task locations, retry settings, telemetry, and build options.
```ts
import { defineConfig } from "@trigger.dev/sdk/v3";
import { defineConfig } from "@trigger.dev/sdk";
export default defineConfig({
project: "<project ref>",
@@ -1248,7 +1226,7 @@ await myTask.trigger({ name: "Alice", age: 30 });
Before generating any code, you MUST verify:
1. Are you importing from `@trigger.dev/sdk/v3`? If not, STOP and FIX.
1. Are you importing from `@trigger.dev/sdk` (NOT `@trigger.dev/sdk/v3`)? If not, STOP and FIX.
2. Have you exported every task? If not, STOP and FIX.
3. Have you generated any DEPRECATED code patterns? If yes, STOP and FIX.
+3 -1
View File
@@ -4,4 +4,6 @@ apps/proxy/
apps/coordinator/
packages/rsc/
.changeset
.zed
.zed
.env
!.env.example
+2
View File
@@ -16,6 +16,8 @@
**/dist
**/node_modules
**/generated/prisma
apps/webapp/build
apps/webapp/public/build
+43 -34
View File
@@ -12,7 +12,14 @@ APP_ENV=development
APP_ORIGIN=http://localhost:3030
ELECTRIC_ORIGIN=http://localhost:3060
NODE_ENV=development
V3_ENABLED=true
# Clickhouse
CLICKHOUSE_URL=http://default:password@localhost:8123
RUN_REPLICATION_CLICKHOUSE_URL=http://default:password@localhost:8123
RUN_REPLICATION_ENABLED=1
# Set this to UTC because Node.js uses the system timezone
TZ="UTC"
# Redis is used for the v3 queuing and v2 concurrency control
REDIS_HOST="localhost"
@@ -22,11 +29,14 @@ REDIS_TLS_DISABLED="true"
DEV_OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:3030/otel"
DEV_OTEL_BATCH_PROCESSING_ENABLED="0"
# When the domain is set to `localhost` the CLI deploy command will only --load the image by default and not --push it
DEPLOY_REGISTRY_HOST=localhost:5000
# OPTIONAL VARIABLES
# This is used for validating emails that are allowed to log in. Every email that do not match this regex will be rejected.
# WHITELISTED_EMAILS="authorized@yahoo\.com|authorized@gmail\.com"
# WHITELISTED_EMAILS="^(authorized@yahoo\.com|authorized@gmail\.com)$"
# Accounts with these emails will get global admin rights. This grants access to the admin UI.
# ADMIN_EMAILS="admin@example\.com|another-admin@example\.com"
# ADMIN_EMAILS="^(admin@example\.com|another-admin@example\.com)$"
# This is used for logging in via GitHub. You can leave these commented out if you don't want to use GitHub for authentication.
# AUTH_GITHUB_CLIENT_ID=
# AUTH_GITHUB_CLIENT_SECRET=
@@ -60,45 +70,44 @@ DEV_OTEL_BATCH_PROCESSING_ENABLED="0"
# FROM_EMAIL=
# REPLY_TO_EMAIL=
# Remove the following line to enable logging telemetry traces to the console
LOG_TELEMETRY="false"
# CLOUD VARIABLES
POSTHOG_PROJECT_KEY=
PLAIN_API_KEY=
CLOUD_AIRTABLE_CLIENT_ID=
CLOUD_AIRTABLE_CLIENT_SECRET=
CLOUD_GITHUB_CLIENT_ID=
CLOUD_GITHUB_CLIENT_SECRET=
CLOUD_LINEAR_CLIENT_ID=
CLOUD_LINEAR_CLIENT_SECRET=
CLOUD_SLACK_APP_HOST=
CLOUD_SLACK_CLIENT_ID=
CLOUD_SLACK_CLIENT_SECRET=
# v3 variables
PROVIDER_SECRET=provider-secret # generate the actual secret with `openssl rand -hex 32`
COORDINATOR_SECRET=coordinator-secret # generate the actual secret with `openssl rand -hex 32`
# Uncomment the following line to enable the registry proxy
# ENABLE_REGISTRY_PROXY=true
# DEPOT_ORG_ID=<Depot org id>
# DEPOT_TOKEN=<Depot org token>
# DEPOT_PROJECT_ID=<Depot project id>
# DEPLOY_REGISTRY_HOST=${APP_ORIGIN} # This is the host that the deploy CLI will use to push images to the registry
# CONTAINER_REGISTRY_ORIGIN=<Container registry origin e.g. https://registry.digitalocean.com>
# CONTAINER_REGISTRY_USERNAME=<Container registry username e.g. Digital ocean email address>
# CONTAINER_REGISTRY_PASSWORD=<Container registry password e.g. Digital ocean PAT>
# DEV_OTEL_EXPORTER_OTLP_ENDPOINT="http://0.0.0.0:4318"
# These are needed for the object store (for handling large payloads/outputs)
# OBJECT_STORE_BASE_URL="https://{bucket}.{accountId}.r2.cloudflarestorage.com"
# OBJECT_STORE_ACCESS_KEY_ID=
# OBJECT_STORE_SECRET_ACCESS_KEY=
#
# Default provider
# OBJECT_STORE_BASE_URL=http://localhost:9005
# OBJECT_STORE_BUCKET=packets
# OBJECT_STORE_ACCESS_KEY_ID=minioadmin
# OBJECT_STORE_SECRET_ACCESS_KEY=minioadmin
# OBJECT_STORE_REGION=us-east-1
# OBJECT_STORE_SERVICE=s3
#
# OBJECT_STORE_DEFAULT_PROTOCOL=s3 # Only specify this if you're going to migrate object storage and set protocol values below
# Named providers (protocol-prefixed data) - optional for multi-provider support
# OBJECT_STORE_S3_BASE_URL=https://s3.amazonaws.com
# OBJECT_STORE_S3_ACCESS_KEY_ID=
# OBJECT_STORE_S3_SECRET_ACCESS_KEY=
# OBJECT_STORE_S3_REGION=us-east-1
# OBJECT_STORE_S3_SERVICE=s3
#
# OBJECT_STORE_R2_BASE_URL=https://{bucket}.{accountId}.r2.cloudflarestorage.com
# OBJECT_STORE_R2_ACCESS_KEY_ID=
# OBJECT_STORE_R2_SECRET_ACCESS_KEY=
# OBJECT_STORE_R2_REGION=auto
# OBJECT_STORE_R2_SERVICE=s3
# CHECKPOINT_THRESHOLD_IN_MS=10000
# These control the server-side internal telemetry
# INTERNAL_OTEL_TRACE_EXPORTER_URL=<URL to send traces to>
# INTERNAL_OTEL_TRACE_EXPORTER_AUTH_HEADER_NAME=<Header name for the auth token>
# INTERNAL_OTEL_TRACE_EXPORTER_AUTH_HEADER_VALUE=<Auth token value>
# INTERNAL_OTEL_TRACE_LOGGING_ENABLED=1
# INTERNAL_OTEL_TRACE_SAMPING_RATE=20 # this means 1/20 traces or 5% of traces will be sampled (sampled = recorded)
# INTERNAL_OTEL_TRACE_INSTRUMENT_PRISMA_ENABLED=0,
# INTERNAL_OTEL_TRACE_INSTRUMENT_PRISMA_ENABLED=0
# Enable local observability stack (requires `pnpm run docker` to start otel-collector)
# Uncomment these to send metrics to the local Prometheus via OTEL Collector:
# INTERNAL_OTEL_METRIC_EXPORTER_ENABLED=1
# INTERNAL_OTEL_METRIC_EXPORTER_URL=http://localhost:4318/v1/metrics
# INTERNAL_OTEL_METRIC_EXPORTER_INTERVAL_MS=15000
+28
View File
@@ -0,0 +1,28 @@
name: Vouch Request
description: Request to be vouched as a contributor
labels: ["vouch-request"]
body:
- type: markdown
attributes:
value: |
## Vouch Request
We use [vouch](https://github.com/mitchellh/vouch) to manage contributor trust. PRs from unvouched users are automatically closed.
To get vouched, fill out this form. A maintainer will review your request and vouch for you by commenting on this issue.
- type: textarea
id: context
attributes:
label: Why do you want to contribute?
description: Tell us a bit about yourself and what you'd like to work on.
placeholder: "I'd like to fix a bug I found in..."
validations:
required: true
- type: textarea
id: prior-work
attributes:
label: Prior contributions or relevant experience
description: Links to previous open source work, relevant projects, or anything that helps us understand your background.
placeholder: "https://github.com/..."
validations:
required: false
+24
View File
@@ -0,0 +1,24 @@
# Vouched contributors for Trigger.dev
# See: https://github.com/mitchellh/vouch
#
# Org members
0ski
D-K-P
ericallam
matt-aitken
mpcgrid
myftija
nicktrn
samejr
isshaddad
# Bots
devin-ai-integration[bot]
dependabot[bot]
# Outside contributors
gautamsi
capaj
chengzp
bharathkumar39293
bhekanik
jrossi
ThullyoCunha
+16 -14
View File
@@ -23,35 +23,37 @@ runs:
id: get_tag
shell: bash
run: |
if [[ -n "${{ inputs.tag }}" ]]; then
tag="${{ inputs.tag }}"
elif [[ "${{ github.ref_type }}" == "tag" ]]; then
if [[ "${{ github.ref_name }}" == infra-*-* ]]; then
env=$(echo ${{ github.ref_name }} | cut -d- -f2)
sha=$(echo ${{ github.sha }} | head -c7)
if [[ -n "${INPUTS_TAG}" ]]; then
tag="${INPUTS_TAG}"
elif [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
if [[ "${GITHUB_REF_NAME}" == infra-*-* ]]; then
env=$(echo ${GITHUB_REF_NAME} | cut -d- -f2)
sha=$(echo "${GITHUB_SHA}" | head -c7)
ts=$(date +%s)
tag=${env}-${sha}-${ts}
elif [[ "${{ github.ref_name }}" == re2-*-* ]]; then
env=$(echo ${{ github.ref_name }} | cut -d- -f2)
sha=$(echo ${{ github.sha }} | head -c7)
elif [[ "${GITHUB_REF_NAME}" == re2-*-* ]]; then
env=$(echo ${GITHUB_REF_NAME} | cut -d- -f2)
sha=$(echo "${GITHUB_SHA}" | head -c7)
ts=$(date +%s)
tag=${env}-${sha}-${ts}
elif [[ "${{ github.ref_name }}" == v.docker.* ]]; then
elif [[ "${GITHUB_REF_NAME}" == v.docker.* ]]; then
version="${GITHUB_REF_NAME#v.docker.}"
tag="v${version}"
elif [[ "${{ github.ref_name }}" == build-* ]]; then
elif [[ "${GITHUB_REF_NAME}" == build-* ]]; then
tag="${GITHUB_REF_NAME#build-}"
else
echo "Invalid git tag: ${{ github.ref_name }}"
echo "Invalid git tag: ${GITHUB_REF_NAME}"
exit 1
fi
elif [[ "${{ github.ref_name }}" == "main" ]]; then
elif [[ "${GITHUB_REF_NAME}" == "main" ]]; then
tag="main"
else
echo "Invalid git ref: ${{ github.ref }}"
echo "Invalid git ref: ${GITHUB_REF}"
exit 1
fi
echo "tag=${tag}" >> "$GITHUB_OUTPUT"
env:
INPUTS_TAG: ${{ inputs.tag }}
- name: 🔍 Check for validity
id: check_validity
+12
View File
@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
cooldown:
default-days: 7
groups:
github-actions:
patterns:
- "*"
+74
View File
@@ -0,0 +1,74 @@
name: 🦋 Changesets PR
on:
push:
branches:
- main
paths:
- "packages/**"
- ".changeset/**"
- ".server-changes/**"
- "package.json"
- "pnpm-lock.yaml"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
release-pr:
name: Create Release PR
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
if: github.repository == 'triggerdotdev/trigger.dev'
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # zizmor: ignore[artipacked] changesets/action pushes the release branch; no artifact upload here so no leak path
with:
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
- name: Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Create release PR
id: changesets
uses: changesets/action@6a0a831ff30acef54f2c6aa1cbbc1096b066edaf # v1.7.0
with:
version: pnpm run changeset:version
commit: "chore: release"
title: "chore: release"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Update PR title and enhance body
if: steps.changesets.outputs.published != 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER=$(gh pr list --head changeset-release/main --json number --jq '.[0].number')
if [ -n "$PR_NUMBER" ]; then
git fetch origin changeset-release/main
# we arbitrarily reference the version of the cli package here; it is the same for all package releases
VERSION=$(git show origin/changeset-release/main:packages/cli-v3/package.json | jq -r '.version')
gh pr edit "$PR_NUMBER" --title "chore: release v$VERSION"
# Enhance the PR body with a clean, deduplicated summary
RAW_BODY=$(gh pr view "$PR_NUMBER" --json body --jq '.body')
ENHANCED_BODY=$(CHANGESET_PR_BODY="$RAW_BODY" node scripts/enhance-release-pr.mjs "$VERSION")
if [ -n "$ENHANCED_BODY" ]; then
gh api repos/triggerdotdev/trigger.dev/pulls/"$PR_NUMBER" \
-X PATCH \
-f body="$ENHANCED_BODY"
fi
fi
+73
View File
@@ -0,0 +1,73 @@
name: 📝 CLAUDE.md Audit
on:
pull_request:
types: [opened, ready_for_review, synchronize]
paths-ignore:
- "docs/**"
- ".changeset/**"
- ".server-changes/**"
- "**/*.md"
- "references/**"
concurrency:
group: claude-md-audit-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
audit:
if: >-
github.event.pull_request.draft == false &&
github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@fefa07e9c665b7320f08c3b525980457f22f58aa # v1.0.111
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
use_sticky_comment: true
allowed_bots: "devin-ai-integration[bot]"
claude_args: |
--max-turns 15
--allowedTools "Read,Glob,Grep,Bash(git diff:*)"
prompt: |
You are reviewing a PR to check whether any CLAUDE.md files or .claude/rules/ files need updating.
## Your task
1. Run `git diff origin/main...HEAD --name-only` to see which files changed in this PR.
2. For each changed directory, check if there's a CLAUDE.md in that directory or a parent directory.
3. Determine if any CLAUDE.md or .claude/rules/ file should be updated based on the changes. Consider:
- New files/directories that aren't covered by existing documentation
- Changed architecture or patterns that contradict current CLAUDE.md guidance
- New dependencies, services, or infrastructure that Claude should know about
- Renamed or moved files that are referenced in CLAUDE.md
- Changes to build commands, test patterns, or development workflows
## Response format
If NO updates are needed, respond with exactly:
✅ CLAUDE.md files look current for this PR.
If updates ARE needed, respond with a short list:
📝 **CLAUDE.md updates suggested:**
- `path/to/CLAUDE.md`: [what should be added/changed]
- `.claude/rules/file.md`: [what should be added/changed]
Keep suggestions specific and brief. Only flag things that would actually mislead Claude in future sessions.
Do NOT suggest updates for trivial changes (bug fixes, small refactors within existing patterns).
Do NOT suggest creating new CLAUDE.md files - only updates to existing ones.
+71
View File
@@ -0,0 +1,71 @@
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 1
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: ⎔ Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
cache: "pnpm"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
run: pnpm run generate
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@fefa07e9c665b7320f08c3b525980457f22f58aa # v1.0.111
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read
claude_args: |
--model claude-opus-4-5-20251101
--allowedTools "Bash(pnpm:*),Bash(turbo:*),Bash(git:*),Bash(gh:*),Bash(npx:*),Bash(docker:*),Edit,MultiEdit,Read,Write,Glob,Grep,LS,Task"
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'
# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr:*)'
+4 -2
View File
@@ -26,10 +26,12 @@ jobs:
working-directory: ./docs
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: 📦 Cache npm
uses: actions/cache@v4
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: |
~/.npm
+97
View File
@@ -0,0 +1,97 @@
name: "🧪 E2E Tests: Webapp"
permissions:
contents: read
on:
workflow_call:
secrets:
DOCKERHUB_USERNAME:
required: false
DOCKERHUB_TOKEN:
required: false
jobs:
e2eTests:
name: "🧪 E2E Tests: Webapp"
runs-on: ubuntu-latest
timeout-minutes: 20
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
steps:
- name: 🔧 Disable IPv6
run: |
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=1
- name: 🔧 Configure docker address pool
run: |
CONFIG='{
"default-address-pools" : [
{
"base" : "172.17.0.0/12",
"size" : 20
},
{
"base" : "192.168.0.0/16",
"size" : 24
}
]
}'
mkdir -p /etc/docker
echo "$CONFIG" | sudo tee /etc/docker/daemon.json
- name: 🔧 Restart docker daemon
run: sudo systemctl restart docker
- name: ⬇️ Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: ⎔ Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
cache: "pnpm"
# ..to avoid rate limits when pulling images
- name: 🐳 Login to DockerHub
if: ${{ env.DOCKERHUB_USERNAME }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 🐳 Skipping DockerHub login (no secrets available)
if: ${{ !env.DOCKERHUB_USERNAME }}
run: echo "DockerHub login skipped because secrets are not available."
- name: 🐳 Pre-pull testcontainer images
if: ${{ env.DOCKERHUB_USERNAME }}
run: |
echo "Pre-pulling Docker images with authenticated session..."
docker pull postgres:14
docker pull redis:7.2
docker pull testcontainers/ryuk:0.11.0
echo "Image pre-pull complete"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
run: pnpm run generate
- name: 🏗️ Build Webapp
run: pnpm run build --filter webapp
- name: 🧪 Run Webapp E2E Tests
run: cd apps/webapp && pnpm exec vitest run --config vitest.e2e.config.ts --reporter=default
env:
WEBAPP_TEST_VERBOSE: "1"
+10 -6
View File
@@ -1,5 +1,8 @@
name: "E2E"
permissions:
contents: read
on:
workflow_call:
inputs:
@@ -21,19 +24,20 @@ jobs:
package-manager: ["npm", "pnpm"]
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 8.15.5
version: 10.33.2
- name: ⎔ Setup node
uses: buildjet/setup-node@v4
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.11.1
node-version: 20.20.0
- name: 📥 Download deps
run: pnpm install --frozen-lockfile --filter trigger.dev...
@@ -45,7 +49,7 @@ jobs:
run: pnpm run build --filter trigger.dev^...
- name: 🔧 Build worker template files
run: pnpm --filter trigger.dev run build:workers
run: pnpm --filter trigger.dev run --if-present build:workers
- name: Enable corepack
run: corepack enable
+200
View File
@@ -0,0 +1,200 @@
name: 🧭 Helm Chart Prerelease
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- "hosting/k8s/helm/**"
push:
branches:
- main
paths:
- "hosting/k8s/helm/**"
workflow_dispatch:
inputs:
app_version:
description: "Override appVersion (e.g. 'main', 'v4.4.4'). Leave empty to keep Chart.yaml value."
required: false
type: string
default: ""
concurrency:
group: helm-prerelease-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
REGISTRY: ghcr.io
CHART_NAME: trigger
jobs:
lint-and-test:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Set up Helm
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
with:
version: "3.18.3"
- name: Build dependencies
run: helm dependency build ./hosting/k8s/helm/
- name: Extract dependency charts
run: |
cd ./hosting/k8s/helm/
for file in ./charts/*.tgz; do echo "Extracting $file"; tar -xzf "$file" -C ./charts; done
- name: Lint Helm Chart
run: |
helm lint ./hosting/k8s/helm/
- name: Render templates
run: |
helm template test-release ./hosting/k8s/helm/ \
--values ./hosting/k8s/helm/values.yaml \
--output-dir ./helm-output
- name: Validate manifests
uses: docker://ghcr.io/yannh/kubeconform:v0.7.0@sha256:85dbef6b4b312b99133decc9c6fc9495e9fc5f92293d4ff3b7e1b30f5611823c
with:
entrypoint: "/kubeconform"
args: "-summary -output json ./helm-output"
prerelease:
needs: lint-and-test
if: |
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) ||
github.event_name == 'push' ||
github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Set up Helm
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
with:
version: "3.18.3"
- name: Build dependencies
run: helm dependency build ./hosting/k8s/helm/
- name: Extract dependency charts
run: |
cd ./hosting/k8s/helm/
for file in ./charts/*.tgz; do echo "Extracting $file"; tar -xzf "$file" -C ./charts; done
- name: Log in to Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Generate prerelease version
id: version
run: |
BASE_VERSION=$(grep '^version:' ./hosting/k8s/helm/Chart.yaml | awk '{print $2}')
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
PR_NUMBER=${{ github.event.pull_request.number }}
SHORT_SHA=$(echo "${{ github.event.pull_request.head.sha }}" | cut -c1-7)
PRERELEASE_VERSION="${BASE_VERSION}-pr${PR_NUMBER}.${SHORT_SHA}"
elif [[ "${{ github.event_name }}" == "push" ]]; then
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
PRERELEASE_VERSION="${BASE_VERSION}-main.${SHORT_SHA}"
else
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
REF_SLUG=$(echo "${GITHUB_REF_NAME}" | tr '/' '-' | tr -cd 'a-zA-Z0-9-')
if [[ -z "$REF_SLUG" ]]; then
REF_SLUG="manual"
fi
PRERELEASE_VERSION="${BASE_VERSION}-${REF_SLUG}.${SHORT_SHA}"
fi
echo "version=$PRERELEASE_VERSION" >> "$GITHUB_OUTPUT"
echo "Prerelease version: $PRERELEASE_VERSION"
- name: Update Chart.yaml with prerelease version
run: |
sed -i "s/^version:.*/version: ${STEPS_VERSION_OUTPUTS_VERSION}/" ./hosting/k8s/helm/Chart.yaml
env:
STEPS_VERSION_OUTPUTS_VERSION: ${{ steps.version.outputs.version }}
- name: Override appVersion
if: github.event_name == 'workflow_dispatch' && inputs.app_version != ''
env:
APP_VERSION: ${{ inputs.app_version }}
run: |
yq -i '.appVersion = strenv(APP_VERSION)' ./hosting/k8s/helm/Chart.yaml
- name: Package Helm Chart
run: |
helm package ./hosting/k8s/helm/ --destination /tmp/
- name: Push Helm Chart to GHCR
run: |
VERSION="${STEPS_VERSION_OUTPUTS_VERSION}"
CHART_PACKAGE="/tmp/${{ env.CHART_NAME }}-${VERSION}.tgz"
# Push to GHCR OCI registry
helm push "$CHART_PACKAGE" "oci://${{ env.REGISTRY }}/${{ github.repository_owner }}/charts"
env:
STEPS_VERSION_OUTPUTS_VERSION: ${{ steps.version.outputs.version }}
- name: Write run summary
run: |
{
echo "### 🧭 Helm Chart Prerelease Published"
echo ""
echo "**Version:** \`${STEPS_VERSION_OUTPUTS_VERSION}\`"
echo ""
echo "**Install:**"
echo '```bash'
echo "helm upgrade --install trigger \\"
echo " oci://${{ env.REGISTRY }}/${{ github.repository_owner }}/charts/${{ env.CHART_NAME }} \\"
echo " --version \"${STEPS_VERSION_OUTPUTS_VERSION}\""
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
env:
STEPS_VERSION_OUTPUTS_VERSION: ${{ steps.version.outputs.version }}
- name: Find existing comment
if: github.event_name == 'pull_request'
uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4.0.0
id: find-comment
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: "github-actions[bot]"
body-includes: "Helm Chart Prerelease Published"
- name: Create or update PR comment
if: github.event_name == 'pull_request'
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
with:
comment-id: ${{ steps.find-comment.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body: |
### 🧭 Helm Chart Prerelease Published
**Version:** `${{ steps.version.outputs.version }}`
**Install:**
```bash
helm upgrade --install trigger \
oci://ghcr.io/${{ github.repository_owner }}/charts/trigger \
--version "${{ steps.version.outputs.version }}"
```
> ⚠️ This is a prerelease for testing. Do not use in production.
edit-mode: replace
+9 -4
View File
@@ -5,6 +5,9 @@ on:
types: [opened, synchronize, reopened]
paths-ignore:
- "docs/**"
- ".changeset/**"
- "hosting/**"
- ".github/workflows/helm-prerelease.yml"
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -12,19 +15,21 @@ concurrency:
permissions:
contents: read
id-token: write
jobs:
typecheck:
uses: ./.github/workflows/typecheck.yml
secrets: inherit
units:
uses: ./.github/workflows/unit-tests.yml
secrets: inherit
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
e2e:
uses: ./.github/workflows/e2e.yml
with:
package: cli-v3
secrets: inherit
sdk-compat:
uses: ./.github/workflows/sdk-compat.yml
+69 -9
View File
@@ -1,5 +1,11 @@
name: "🐳 Publish Webapp"
permissions:
contents: read
packages: write
id-token: write
attestations: write
on:
workflow_call:
inputs:
@@ -8,6 +14,9 @@ on:
type: string
required: false
default: ""
secrets:
SENTRY_AUTH_TOKEN:
required: false
jobs:
publish:
@@ -19,12 +28,13 @@ jobs:
short_sha: ${{ steps.get_commit.outputs.sha_short }}
steps:
- name: 🏭 Setup Depot CLI
uses: depot/setup-action@v1
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1
- name: ⬇️ Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: recursive
persist-credentials: false
- name: "#️⃣ Get the image tag"
id: get_tag
@@ -35,32 +45,82 @@ jobs:
- name: 🔢 Get the commit hash
id: get_commit
run: |
echo "sha_short=$(echo ${{ github.sha }} | cut -c1-7)" >> "$GITHUB_OUTPUT"
echo "sha_short=$(echo "${GITHUB_SHA}" | cut -c1-7)" >> "$GITHUB_OUTPUT"
- name: 📛 Set the tags
id: set_tags
run: |
ref_without_tag=ghcr.io/triggerdotdev/trigger.dev
image_tags=$ref_without_tag:${{ steps.get_tag.outputs.tag }}
image_tags=$ref_without_tag:${STEPS_GET_TAG_OUTPUTS_TAG}
# if tag is a semver, also tag it as v3
if [[ "${{ steps.get_tag.outputs.is_semver }}" == true ]]; then
image_tags=$image_tags,$ref_without_tag:v3
# if tag is a semver, also tag it as v4
if [[ "${STEPS_GET_TAG_OUTPUTS_IS_SEMVER}" == true ]]; then
# TODO: switch to v4 tag on GA
image_tags=$image_tags,$ref_without_tag:v4-beta
fi
# when pushing the mutable main tag, also push an immutable-by-convention
# full-commit-sha tag so a commit can be resolved to a specific digest
if [[ "${STEPS_GET_TAG_OUTPUTS_TAG}" == "main" ]]; then
image_tags=$image_tags,$ref_without_tag:${GITHUB_SHA}
fi
echo "image_tags=${image_tags}" >> "$GITHUB_OUTPUT"
env:
STEPS_GET_TAG_OUTPUTS_TAG: ${{ steps.get_tag.outputs.tag }}
STEPS_GET_TAG_OUTPUTS_IS_SEMVER: ${{ steps.get_tag.outputs.is_semver }}
- name: 📝 Set the build info
id: set_build_info
run: |
{
tag="${STEPS_GET_TAG_OUTPUTS_TAG}"
if [[ "${STEPS_GET_TAG_OUTPUTS_IS_SEMVER}" == true ]]; then
echo "BUILD_APP_VERSION=${tag}"
fi
echo "BUILD_GIT_SHA=${GITHUB_SHA}"
echo "BUILD_GIT_REF_NAME=${GITHUB_REF_NAME}"
echo "BUILD_TIMESTAMP_SECONDS=$(date +%s)"
echo "BUILD_TIMESTAMP_RFC3339=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
} >> "$GITHUB_OUTPUT"
env:
STEPS_GET_TAG_OUTPUTS_TAG: ${{ steps.get_tag.outputs.tag }}
STEPS_GET_TAG_OUTPUTS_IS_SEMVER: ${{ steps.get_tag.outputs.is_semver }}
- name: 🐙 Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 🐳 Build image and push to GitHub Container Registry
uses: depot/build-push-action@v1
id: build_push
uses: depot/build-push-action@5f3b3c2e5a00f0093de47f657aeaefcedff27d18 # v1.17.0
with:
file: ./docker/Dockerfile
platforms: linux/amd64,linux/arm64
tags: ${{ steps.set_tags.outputs.image_tags }}
push: true
build-args: |
BUILD_APP_VERSION=${{ steps.set_build_info.outputs.BUILD_APP_VERSION }}
BUILD_GIT_SHA=${{ steps.set_build_info.outputs.BUILD_GIT_SHA }}
BUILD_GIT_REF_NAME=${{ steps.set_build_info.outputs.BUILD_GIT_REF_NAME }}
BUILD_TIMESTAMP_SECONDS=${{ steps.set_build_info.outputs.BUILD_TIMESTAMP_SECONDS }}
BUILD_TIMESTAMP_RFC3339=${{ steps.set_build_info.outputs.BUILD_TIMESTAMP_RFC3339 }}
SENTRY_RELEASE=${{ steps.set_build_info.outputs.BUILD_GIT_SHA }}
SENTRY_ORG=triggerdev
SENTRY_PROJECT=trigger-cloud
secrets: |
sentry_auth_token=${{ secrets.SENTRY_AUTH_TOKEN }}
- name: 🪪 Attest build provenance
# Image is already pushed by this point — don't fail releases (and the
# downstream publish-helm job) on a Sigstore/GHCR-referrer hiccup. Real
# config errors still surface as a step warning in the workflow run.
continue-on-error: true
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
with:
subject-name: ghcr.io/triggerdotdev/trigger.dev
subject-digest: ${{ steps.build_push.outputs.digest }}
push-to-registry: true
-95
View File
@@ -1,95 +0,0 @@
name: "⚒️ Publish Worker RE2"
on:
workflow_call:
inputs:
image_tag:
description: The image tag to publish
type: string
required: false
default: ""
push:
tags:
- "re2-test-*"
- "re2-prod-*"
permissions:
packages: write
contents: read
jobs:
# check-branch:
# runs-on: ubuntu-latest
# steps:
# - name: Fail if re2-prod-* is pushed from a non-main branch
# if: startsWith(github.ref_name, 're2-prod-') && github.base_ref != 'main'
# run: |
# echo "🚫 re2-prod-* tags can only be pushed from the main branch."
# exit 1
build:
# needs: check-branch
strategy:
matrix:
package: [supervisor]
runs-on: ubuntu-latest
env:
DOCKER_BUILDKIT: "1"
steps:
- name: ⬇️ Checkout git repo
uses: actions/checkout@v4
- name: 📦 Get image repo
id: get_repository
run: |
if [[ "${{ matrix.package }}" == *-provider ]]; then
provider_type=$(echo "${{ matrix.package }}" | cut -d- -f1)
repo=provider/${provider_type}
else
repo="${{ matrix.package }}"
fi
echo "repo=${repo}" >> "$GITHUB_OUTPUT"
- id: get_tag
uses: ./.github/actions/get-image-tag
with:
tag: ${{ inputs.image_tag }}
- name: 🐋 Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# ..to avoid rate limits when pulling images
- name: 🐳 Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 🚢 Build Container Image
run: |
docker build -t infra_image -f ./apps/${{ matrix.package }}/Containerfile .
# ..to push image
- name: 🐙 Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 🐙 Push to GitHub Container Registry
run: |
docker tag infra_image "$REGISTRY/$REPOSITORY:$IMAGE_TAG"
docker push "$REGISTRY/$REPOSITORY:$IMAGE_TAG"
env:
REGISTRY: ghcr.io/triggerdotdev
REPOSITORY: ${{ steps.get_repository.outputs.repo }}
IMAGE_TAG: ${{ steps.get_tag.outputs.tag }}
- name: 🐙 Push 'v3' tag to GitHub Container Registry
if: steps.get_tag.outputs.is_semver == 'true'
run: |
docker tag infra_image "$REGISTRY/$REPOSITORY:v3"
docker push "$REGISTRY/$REPOSITORY:v3"
env:
REGISTRY: ghcr.io/triggerdotdev
REPOSITORY: ${{ steps.get_repository.outputs.repo }}
+96
View File
@@ -0,0 +1,96 @@
name: "⚒️ Publish Worker (v4)"
on:
workflow_call:
inputs:
image_tag:
description: The image tag to publish
type: string
required: false
default: ""
push:
tags:
- "re2-test-*"
- "re2-prod-*"
permissions:
id-token: write
packages: write
contents: read
jobs:
# check-branch:
# runs-on: ubuntu-latest
# steps:
# - name: Fail if re2-prod-* is pushed from a non-main branch
# if: startsWith(github.ref_name, 're2-prod-') && github.base_ref != 'main'
# run: |
# echo "🚫 re2-prod-* tags can only be pushed from the main branch."
# exit 1
build:
# needs: check-branch
strategy:
matrix:
package: [supervisor]
runs-on: ubuntu-latest
env:
DOCKER_BUILDKIT: "1"
steps:
- name: 🏭 Setup Depot CLI
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1
- name: ⬇️ Checkout git repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: 📦 Get image repo
id: get_repository
env:
PACKAGE: ${{ matrix.package }}
run: |
if [[ "$PACKAGE" == *-provider ]]; then
repo="provider/${PACKAGE%-provider}"
else
repo="$PACKAGE"
fi
echo "repo=${repo}" >> "$GITHUB_OUTPUT"
- name: "#️⃣ Get image tag"
id: get_tag
uses: ./.github/actions/get-image-tag
with:
tag: ${{ inputs.image_tag }}
- name: 📛 Set tags to push
id: set_tags
run: |
ref_without_tag=ghcr.io/triggerdotdev/${STEPS_GET_REPOSITORY_OUTPUTS_REPO}
image_tags=$ref_without_tag:${STEPS_GET_TAG_OUTPUTS_TAG}
# if tag is a semver, also tag it as v4
if [[ "${STEPS_GET_TAG_OUTPUTS_IS_SEMVER}" == true ]]; then
# TODO: switch to v4 tag on GA
image_tags=$image_tags,$ref_without_tag:v4-beta
fi
echo "image_tags=${image_tags}" >> "$GITHUB_OUTPUT"
env:
STEPS_GET_REPOSITORY_OUTPUTS_REPO: ${{ steps.get_repository.outputs.repo }}
STEPS_GET_TAG_OUTPUTS_TAG: ${{ steps.get_tag.outputs.tag }}
STEPS_GET_TAG_OUTPUTS_IS_SEMVER: ${{ steps.get_tag.outputs.is_semver }}
- name: 🐙 Login to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 🐳 Build image and push to GitHub Container Registry
uses: depot/build-push-action@5f3b3c2e5a00f0093de47f657aeaefcedff27d18 # v1.17.0
with:
file: ./apps/${{ matrix.package }}/Containerfile
platforms: linux/amd64,linux/arm64
tags: ${{ steps.set_tags.outputs.image_tags }}
push: true
+26 -16
View File
@@ -8,6 +8,11 @@ on:
type: string
required: false
default: ""
secrets:
DOCKERHUB_USERNAME:
required: false
DOCKERHUB_TOKEN:
required: false
push:
tags:
- "infra-dev-*"
@@ -26,18 +31,22 @@ jobs:
runs-on: ubuntu-latest
env:
DOCKER_BUILDKIT: "1"
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
steps:
- name: ⬇️ Checkout git repo
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: 📦 Get image repo
id: get_repository
env:
PACKAGE: ${{ matrix.package }}
run: |
if [[ "${{ matrix.package }}" == *-provider ]]; then
provider_type=$(echo "${{ matrix.package }}" | cut -d- -f1)
repo=provider/${provider_type}
if [[ "$PACKAGE" == *-provider ]]; then
repo="provider/${PACKAGE%-provider}"
else
repo="${{ matrix.package }}"
repo="$PACKAGE"
fi
echo "repo=${repo}" >> "$GITHUB_OUTPUT"
@@ -47,11 +56,12 @@ jobs:
tag: ${{ inputs.image_tag }}
- name: 🐋 Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
# ..to avoid rate limits when pulling images
- name: 🐳 Login to DockerHub
uses: docker/login-action@v3
if: ${{ env.DOCKERHUB_USERNAME }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -62,7 +72,7 @@ jobs:
# ..to push image
- name: 🐙 Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -77,11 +87,11 @@ jobs:
REPOSITORY: ${{ steps.get_repository.outputs.repo }}
IMAGE_TAG: ${{ steps.get_tag.outputs.tag }}
- name: 🐙 Push 'v3' tag to GitHub Container Registry
if: steps.get_tag.outputs.is_semver == 'true'
run: |
docker tag infra_image "$REGISTRY/$REPOSITORY:v3"
docker push "$REGISTRY/$REPOSITORY:v3"
env:
REGISTRY: ghcr.io/triggerdotdev
REPOSITORY: ${{ steps.get_repository.outputs.repo }}
# - name: 🐙 Push 'v3' tag to GitHub Container Registry
# if: steps.get_tag.outputs.is_semver == 'true'
# run: |
# docker tag infra_image "$REGISTRY/$REPOSITORY:v3"
# docker push "$REGISTRY/$REPOSITORY:v3"
# env:
# REGISTRY: ghcr.io/triggerdotdev
# REPOSITORY: ${{ steps.get_repository.outputs.repo }}
+34 -6
View File
@@ -1,12 +1,20 @@
name: 🚀 Publish Trigger.dev Docker
on:
workflow_dispatch:
workflow_call:
inputs:
image_tag:
description: The image tag to publish
required: true
type: string
secrets:
DOCKERHUB_USERNAME:
required: false
DOCKERHUB_TOKEN:
required: false
SENTRY_AUTH_TOKEN:
required: false
push:
branches:
- main
@@ -36,8 +44,6 @@ on:
- "tests/**"
permissions:
id-token: write
packages: write
contents: read
concurrency:
@@ -49,22 +55,44 @@ env:
jobs:
typecheck:
uses: ./.github/workflows/typecheck.yml
secrets: inherit
units:
uses: ./.github/workflows/unit-tests.yml
secrets: inherit
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
publish-webapp:
needs: [typecheck]
permissions:
contents: read
packages: write
id-token: write
attestations: write
uses: ./.github/workflows/publish-webapp.yml
secrets: inherit
secrets:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
with:
image_tag: ${{ inputs.image_tag }}
publish-worker:
needs: [typecheck]
permissions:
contents: read
packages: write
uses: ./.github/workflows/publish-worker.yml
secrets: inherit
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
with:
image_tag: ${{ inputs.image_tag }}
publish-worker-v4:
needs: [typecheck]
permissions:
contents: read
packages: write
id-token: write
uses: ./.github/workflows/publish-worker-v4.yml
with:
image_tag: ${{ inputs.image_tag }}
+158
View File
@@ -0,0 +1,158 @@
name: 🧭 Helm Chart Release
on:
push:
tags:
- 'helm-v*'
workflow_call:
inputs:
chart_version:
description: 'Chart version to release'
required: true
type: string
workflow_dispatch:
inputs:
chart_version:
description: 'Chart version to release'
required: true
type: string
env:
REGISTRY: ghcr.io
CHART_NAME: trigger
jobs:
lint-and-test:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Set up Helm
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
with:
version: "3.18.3"
- name: Build dependencies
run: helm dependency build ./hosting/k8s/helm/
- name: Extract dependency charts
run: |
cd ./hosting/k8s/helm/
for file in ./charts/*.tgz; do echo "Extracting $file"; tar -xzf "$file" -C ./charts; done
- name: Lint Helm Chart
run: |
helm lint ./hosting/k8s/helm/
- name: Render templates
run: |
helm template test-release ./hosting/k8s/helm/ \
--values ./hosting/k8s/helm/values.yaml \
--output-dir ./helm-output
- name: Validate manifests
uses: docker://ghcr.io/yannh/kubeconform:v0.7.0@sha256:85dbef6b4b312b99133decc9c6fc9495e9fc5f92293d4ff3b7e1b30f5611823c
with:
entrypoint: '/kubeconform'
args: "-summary -output json ./helm-output"
release:
needs: lint-and-test
runs-on: ubuntu-latest
permissions:
contents: write # for gh-release
packages: write
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Set up Helm
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
with:
version: "3.18.3"
- name: Build dependencies
run: helm dependency build ./hosting/k8s/helm/
- name: Extract dependency charts
run: |
cd ./hosting/k8s/helm/
for file in ./charts/*.tgz; do echo "Extracting $file"; tar -xzf "$file" -C ./charts; done
- name: Log in to Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version from tag or input
id: version
run: |
if [ -n "${INPUTS_CHART_VERSION}" ]; then
VERSION="${INPUTS_CHART_VERSION}"
else
VERSION="${GITHUB_REF_NAME}"
VERSION="${VERSION#helm-v}"
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Releasing version: $VERSION"
env:
INPUTS_CHART_VERSION: ${{ inputs.chart_version }}
- name: Check Chart.yaml version matches release version
run: |
VERSION="${STEPS_VERSION_OUTPUTS_VERSION}"
CHART_VERSION=$(grep '^version:' ./hosting/k8s/helm/Chart.yaml | awk '{print $2}')
echo "Chart.yaml version: $CHART_VERSION"
echo "Release version: $VERSION"
if [ "$CHART_VERSION" != "$VERSION" ]; then
echo "❌ Chart.yaml version does not match release version!"
exit 1
fi
echo "✅ Chart.yaml version matches release version."
env:
STEPS_VERSION_OUTPUTS_VERSION: ${{ steps.version.outputs.version }}
- name: Package Helm Chart
run: |
helm package ./hosting/k8s/helm/ --destination /tmp/
- name: Push Helm Chart to GHCR
run: |
VERSION="${STEPS_VERSION_OUTPUTS_VERSION}"
CHART_PACKAGE="/tmp/${{ env.CHART_NAME }}-${VERSION}.tgz"
# Push to GHCR OCI registry
helm push "$CHART_PACKAGE" "oci://${{ env.REGISTRY }}/${{ github.repository_owner }}/charts"
env:
STEPS_VERSION_OUTPUTS_VERSION: ${{ steps.version.outputs.version }}
- name: Create GitHub Release
id: release
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
with:
tag_name: helm-v${{ steps.version.outputs.version }}
name: "Helm Chart ${{ steps.version.outputs.version }}"
body: |
### Installation
```bash
helm upgrade --install trigger \
oci://${{ env.REGISTRY }}/${{ github.repository_owner }}/charts/${{ env.CHART_NAME }} \
--version "${{ steps.version.outputs.version }}"
```
### Changes
See commit history for detailed changes in this release.
files: |
/tmp/${{ env.CHART_NAME }}-${{ steps.version.outputs.version }}.tgz
token: ${{ secrets.GITHUB_TOKEN }}
draft: true
prerelease: true
+263 -56
View File
@@ -1,101 +1,308 @@
name: 🦋 Changesets Release
on:
push:
pull_request:
types: [closed]
branches:
- main
paths-ignore:
- "docs/**"
- "**.md"
- ".github/CODEOWNERS"
- ".github/ISSUE_TEMPLATE/**"
workflow_dispatch:
inputs:
type:
description: "Select release type"
required: true
type: choice
options:
- release
- prerelease
default: "prerelease"
ref:
description: "The ref (branch, tag, or SHA) to checkout and release from"
required: true
type: string
prerelease_tag:
description: "The npm dist-tag for the prerelease (e.g., 'v4-prerelease')"
required: false
type: string
default: "prerelease"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
group: ${{ github.workflow }}
cancel-in-progress: false
jobs:
release:
name: 🦋 Changesets Release
show-release-summary:
name: 📋 Release Summary
runs-on: ubuntu-latest
if: github.repository == 'triggerdotdev/trigger.dev'
permissions: {}
if: |
github.repository == 'triggerdotdev/trigger.dev' &&
github.event_name == 'pull_request' &&
github.event.pull_request.merged == true &&
github.event.pull_request.head.ref == 'changeset-release/main'
steps:
- name: Show release summary
env:
PR_BODY: ${{ github.event.pull_request.body }}
run: |
echo "$PR_BODY" | sed -n '/^# Releases/,$p' >> "$GITHUB_STEP_SUMMARY"
release:
name: 🚀 Release npm packages
runs-on: ubuntu-latest
environment: npm-publish
permissions:
contents: write
packages: write
id-token: write
if: |
github.repository == 'triggerdotdev/trigger.dev' &&
(
(github.event_name == 'workflow_dispatch' && github.event.inputs.type == 'release') ||
(github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.head.ref == 'changeset-release/main')
)
outputs:
published: ${{ steps.changesets.outputs.published }}
published_packages: ${{ steps.changesets.outputs.publishedPackages }}
published_package_version: ${{ steps.get_version.outputs.package_version }}
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v4
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # zizmor: ignore[artipacked] needs persisted git creds for tag push; no artifact upload here so no leak path
with:
fetch-depth: 0
ref: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.ref || github.sha }}
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 8.15.5
- name: Verify ref is on main
if: github.event_name == 'workflow_dispatch'
run: |
if ! git merge-base --is-ancestor "${GITHUB_EVENT_INPUTS_REF}" origin/main; then
echo "Error: ref must be an ancestor of main (i.e., already merged)"
exit 1
fi
env:
GITHUB_EVENT_INPUTS_REF: ${{ github.event.inputs.ref }}
- name: Setup node
uses: buildjet/setup-node@v4
- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
node-version: 20.11.1
version: 10.33.2
- name: Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
cache: "pnpm"
- name: 📥 Download deps
# npm v11.5.1 or newer is required for OIDC support
# https://github.blog/changelog/2025-07-31-npm-trusted-publishing-with-oidc-is-generally-available/#whats-new
- name: Setup npm 11.x for OIDC
run: npm install -g npm@11.6.4
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
- name: Generate Prisma client
run: pnpm run generate
- name: 🏗️ Build
- name: Build
run: pnpm run build --filter "@trigger.dev/*" --filter "trigger.dev"
- name: 🔎 Type check
- name: Type check
run: pnpm run typecheck --filter "@trigger.dev/*" --filter "trigger.dev"
- name: 🔐 Setup npm auth
run: |
echo "registry=https://registry.npmjs.org" >> ~/.npmrc
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc
# This action has two responsibilities. The first time the workflow runs
# (initial push to the `main` branch) it will create a new branch and
# then open a PR with the related changes for the new version. After the
# PR is merged, the workflow will run again and this action will build +
# publish to npm.
- name: 🚀 PR / Publish
if: ${{ !env.ACT }}
- name: Publish
id: changesets
uses: changesets/action@v1
uses: changesets/action@6a0a831ff30acef54f2c6aa1cbbc1096b066edaf # v1.7.0
with:
version: pnpm run changeset:version
commit: "chore: Update version for release"
title: "chore: Update version for release"
publish: pnpm run changeset:release
createGithubReleases: true
createGithubReleases: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# - name: 🚀 PR / Publish (mock)
# if: ${{ env.ACT }}
# id: changesets
# run: |
# echo "published=true" >> "$GITHUB_OUTPUT"
# echo "publishedPackages=[{\"name\": \"@xx/xx\", \"version\": \"1.2.0\"}, {\"name\": \"@xx/xy\", \"version\": \"0.8.9\"}]" >> "$GITHUB_OUTPUT"
- name: 📦 Get package version
- name: Show package version
if: steps.changesets.outputs.published == 'true'
id: get_version
run: |
package_version=$(echo '${{ steps.changesets.outputs.publishedPackages }}' | jq -r '.[0].version')
package_version=$(echo "${STEPS_CHANGESETS_OUTPUTS_PUBLISHEDPACKAGES}" | jq -r '.[0].version')
echo "package_version=${package_version}" >> "$GITHUB_OUTPUT"
env:
STEPS_CHANGESETS_OUTPUTS_PUBLISHEDPACKAGES: ${{ steps.changesets.outputs.publishedPackages }}
publish:
- name: Create unified GitHub release
if: steps.changesets.outputs.published == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_PR_BODY: ${{ github.event.pull_request.body }}
STEPS_GET_VERSION_OUTPUTS_PACKAGE_VERSION: ${{ steps.get_version.outputs.package_version }}
run: |
VERSION="${STEPS_GET_VERSION_OUTPUTS_PACKAGE_VERSION}"
node scripts/generate-github-release.mjs "$VERSION" > /tmp/release-body.md
gh release create "v${VERSION}" \
--title "trigger.dev v${VERSION}" \
--notes-file /tmp/release-body.md \
--target main
- name: Create and push Docker tag
if: steps.changesets.outputs.published == 'true'
run: |
set -e
git tag "v.docker.${STEPS_GET_VERSION_OUTPUTS_PACKAGE_VERSION}"
git push origin "v.docker.${STEPS_GET_VERSION_OUTPUTS_PACKAGE_VERSION}"
env:
STEPS_GET_VERSION_OUTPUTS_PACKAGE_VERSION: ${{ steps.get_version.outputs.package_version }}
- name: Create and push Helm chart tag
if: steps.changesets.outputs.published == 'true'
run: |
set -e
git tag "helm-v${STEPS_GET_VERSION_OUTPUTS_PACKAGE_VERSION}"
git push origin "helm-v${STEPS_GET_VERSION_OUTPUTS_PACKAGE_VERSION}"
env:
STEPS_GET_VERSION_OUTPUTS_PACKAGE_VERSION: ${{ steps.get_version.outputs.package_version }}
# Trigger Docker builds directly via workflow_call since tags pushed with
# GITHUB_TOKEN don't trigger other workflows (GitHub Actions limitation).
publish-docker:
name: 🐳 Publish Docker images
needs: release
if: needs.release.outputs.published == 'true'
permissions:
contents: read
packages: write
id-token: write
attestations: write
uses: ./.github/workflows/publish.yml
secrets: inherit
# if: needs.release.outputs.published == 'true'
# disable automatic publishing for now
if: false
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
with:
image_tag: v${{ needs.release.outputs.published_package_version }}
# Trigger Helm chart release directly via workflow_call (same GITHUB_TOKEN
# limitation as the Docker path). Runs after Docker images are published so
# the chart never references images that don't exist yet.
publish-helm:
name: 🧭 Publish Helm chart
needs: [release, publish-docker]
if: needs.release.outputs.published == 'true'
permissions:
contents: write
packages: write
uses: ./.github/workflows/release-helm.yml
with:
chart_version: ${{ needs.release.outputs.published_package_version }}
# After Docker images are published, update the GitHub release with the exact GHCR tag URL.
# The GHCR package version ID is only known after the image is pushed, so we query for it here.
update-release:
name: 🔗 Update release Docker link
needs: [release, publish-docker]
if: needs.release.outputs.published == 'true'
runs-on: ubuntu-latest
permissions:
contents: write
packages: read
steps:
- name: Update GitHub release with Docker image link
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NEEDS_RELEASE_OUTPUTS_PUBLISHED_PACKAGE_VERSION: ${{ needs.release.outputs.published_package_version }}
run: |
set -e
VERSION="${NEEDS_RELEASE_OUTPUTS_PUBLISHED_PACKAGE_VERSION}"
TAG="v${VERSION}"
# Query GHCR for the version ID matching this tag
VERSION_ID=$(gh api --paginate -H "Accept: application/vnd.github+json" \
/orgs/triggerdotdev/packages/container/trigger.dev/versions \
--jq ".[] | select(.metadata.container.tags[] == \"${TAG}\") | .id" \
| head -1)
if [ -z "$VERSION_ID" ]; then
echo "Warning: Could not find GHCR version ID for tag ${TAG}, skipping update"
exit 0
fi
DOCKER_URL="https://github.com/triggerdotdev/trigger.dev/pkgs/container/trigger.dev/${VERSION_ID}?tag=${TAG}"
GENERIC_URL="https://github.com/triggerdotdev/trigger.dev/pkgs/container/trigger.dev"
# Get current release body and replace the generic link with the tag-specific one.
# Use word boundary after GENERIC_URL (closing paren) to avoid matching URLs that
# already have a version ID appended (idempotent on re-runs).
gh release view "${TAG}" --repo triggerdotdev/trigger.dev --json body --jq '.body' > /tmp/release-body.md
sed -i "s|${GENERIC_URL})|${DOCKER_URL})|g" /tmp/release-body.md
gh release edit "${TAG}" --repo triggerdotdev/trigger.dev --notes-file /tmp/release-body.md
# Dispatch changelog entry creation to the marketing site repo.
# Runs after update-release so the GitHub release body already has the exact Docker image URL.
dispatch-changelog:
name: 📝 Dispatch changelog PR
needs: [release, update-release]
if: needs.release.outputs.published == 'true'
runs-on: ubuntu-latest
permissions: {}
steps:
- uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1
with:
token: ${{ secrets.CROSS_REPO_PAT }}
repository: triggerdotdev/trigger.dev-site-v3
event-type: new-release
client-payload: '{"version": "${{ needs.release.outputs.published_package_version }}"}'
# The prerelease job needs to be on the same workflow file due to a limitation related to how npm verifies OIDC claims.
prerelease:
name: 🧪 Prerelease
runs-on: ubuntu-latest
environment: npm-publish
permissions:
contents: read
id-token: write
if: github.repository == 'triggerdotdev/trigger.dev' && github.event_name == 'workflow_dispatch' && github.event.inputs.type == 'prerelease'
steps:
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
ref: ${{ github.event.inputs.ref }}
persist-credentials: false
- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
cache: "pnpm"
# npm v11.5.1 or newer is required for OIDC support
# https://github.blog/changelog/2025-07-31-npm-trusted-publishing-with-oidc-is-generally-available/#whats-new
- name: Setup npm 11.x for OIDC
run: npm install -g npm@11.6.4
- name: Download deps
run: pnpm install --frozen-lockfile
- name: Generate Prisma Client
run: pnpm run generate
- name: Snapshot version
run: pnpm exec changeset version --snapshot "${GITHUB_EVENT_INPUTS_PRERELEASE_TAG}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_EVENT_INPUTS_PRERELEASE_TAG: ${{ github.event.inputs.prerelease_tag }}
- name: Clean
run: pnpm run clean --filter "@trigger.dev/*" --filter "trigger.dev"
- name: Build
run: pnpm run build --filter "@trigger.dev/*" --filter "trigger.dev"
- name: Publish prerelease
run: pnpm exec changeset publish --no-git-tag --snapshot --tag "${GITHUB_EVENT_INPUTS_PRERELEASE_TAG}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_EVENT_INPUTS_PRERELEASE_TAG: ${{ github.event.inputs.prerelease_tag }}
+182
View File
@@ -0,0 +1,182 @@
name: "🔌 SDK Compatibility Tests"
permissions:
contents: read
on:
workflow_call:
jobs:
node-compat:
name: "Node.js ${{ matrix.node }} (${{ matrix.os }})"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
node: ["20.20", "22.12"]
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: ⎔ Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: ${{ matrix.node }}
cache: "pnpm"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
run: pnpm run generate
- name: 🔨 Build SDK dependencies
shell: bash
run: pnpm run build --filter '@trigger.dev/sdk^...'
- name: 🔨 Build SDK
shell: bash
run: pnpm run build --filter '@trigger.dev/sdk'
- name: 🧪 Run SDK Compatibility Tests
shell: bash
run: pnpm --filter @internal/sdk-compat-tests test
bun-compat:
name: "Bun Runtime"
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: ⎔ Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
cache: "pnpm"
- name: 🥟 Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: latest
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
run: pnpm run generate
- name: 🔨 Build SDK dependencies
run: pnpm run build --filter @trigger.dev/sdk^...
- name: 🔨 Build SDK
run: pnpm run build --filter @trigger.dev/sdk
- name: 🧪 Run Bun Compatibility Test
working-directory: internal-packages/sdk-compat-tests/src/fixtures/bun
run: bun run test.ts
deno-compat:
name: "Deno Runtime"
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: ⎔ Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
cache: "pnpm"
- name: 🦕 Setup Deno
uses: denoland/setup-deno@667a34cdef165d8d2b2e98dde39547c9daac7282 # v2.0.4
with:
deno-version: v2.x
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
run: pnpm run generate
- name: 🔨 Build SDK dependencies
run: pnpm run build --filter @trigger.dev/sdk^...
- name: 🔨 Build SDK
run: pnpm run build --filter @trigger.dev/sdk
- name: 🔗 Link node_modules for Deno fixture
working-directory: internal-packages/sdk-compat-tests/src/fixtures/deno
run: ln -s ../../../../../node_modules node_modules
- name: 🧪 Run Deno Compatibility Test
working-directory: internal-packages/sdk-compat-tests/src/fixtures/deno
run: deno run --allow-read --allow-env --allow-sys test.ts
cloudflare-compat:
name: "Cloudflare Workers"
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: ⎔ Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
cache: "pnpm"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
run: pnpm run generate
- name: 🔨 Build SDK dependencies
run: pnpm run build --filter @trigger.dev/sdk^...
- name: 🔨 Build SDK
run: pnpm run build --filter @trigger.dev/sdk
- name: 📥 Install Cloudflare fixture deps
working-directory: internal-packages/sdk-compat-tests/src/fixtures/cloudflare-worker
run: pnpm install
- name: 🧪 Run Cloudflare Workers Compatibility Test (dry-run)
working-directory: internal-packages/sdk-compat-tests/src/fixtures/cloudflare-worker
run: npx wrangler deploy --dry-run --outdir dist
+11 -5
View File
@@ -3,25 +3,29 @@ name: "ʦ TypeScript"
on:
workflow_call:
permissions:
contents: read
jobs:
typecheck:
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 8.15.5
version: 10.33.2
- name: ⎔ Setup node
uses: buildjet/setup-node@v4
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.11.1
node-version: 20.20.0
cache: "pnpm"
- name: 📥 Download deps
@@ -32,6 +36,8 @@ jobs:
- name: 🔎 Type check
run: pnpm run typecheck
env:
NODE_OPTIONS: --max-old-space-size=8192
- name: 🔎 Check exports
run: pnpm run check-exports
+148
View File
@@ -0,0 +1,148 @@
name: "🧪 Unit Tests: Internal"
permissions:
contents: read
on:
workflow_call:
secrets:
DOCKERHUB_USERNAME:
required: false
DOCKERHUB_TOKEN:
required: false
jobs:
unitTests:
name: "🧪 Unit Tests: Internal"
runs-on: ubuntu-latest
strategy:
matrix:
shardIndex: [1, 2, 3, 4, 5, 6, 7, 8]
shardTotal: [8]
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
SHARD_INDEX: ${{ matrix.shardIndex }}
SHARD_TOTAL: ${{ matrix.shardTotal }}
steps:
- name: 🔧 Disable IPv6
run: |
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=1
- name: 🔧 Configure docker address pool
run: |
CONFIG='{
"default-address-pools" : [
{
"base" : "172.17.0.0/12",
"size" : 20
},
{
"base" : "192.168.0.0/16",
"size" : 24
}
]
}'
mkdir -p /etc/docker
echo "$CONFIG" | sudo tee /etc/docker/daemon.json
- name: 🔧 Restart docker daemon
run: sudo systemctl restart docker
- name: ⬇️ Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: ⎔ Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
cache: "pnpm"
# ..to avoid rate limits when pulling images
- name: 🐳 Login to DockerHub
if: ${{ env.DOCKERHUB_USERNAME }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 🐳 Skipping DockerHub login (no secrets available)
if: ${{ !env.DOCKERHUB_USERNAME }}
run: echo "DockerHub login skipped because secrets are not available."
- name: 🐳 Pre-pull testcontainer images
if: ${{ env.DOCKERHUB_USERNAME }}
run: |
echo "Pre-pulling Docker images with authenticated session..."
docker pull postgres:14
docker pull clickhouse/clickhouse-server:25.4-alpine
docker pull redis:7-alpine
docker pull testcontainers/ryuk:0.11.0
docker pull electricsql/electric:1.2.4
echo "Image pre-pull complete"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
run: pnpm run generate
- name: 🧪 Run Internal Unit Tests
run: pnpm run test:internal --reporter=default --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
- name: Gather all reports
if: ${{ !cancelled() }}
run: |
mkdir -p .vitest-reports
find . -type f -path '*/.vitest-reports/blob-*.json' \
-exec bash -c 'src="$1"; basename=$(basename "$src"); pkg=$(dirname "$src" | sed "s|^\./||;s|/\.vitest-reports$||;s|/|_|g"); cp "$src" ".vitest-reports/${pkg}-${basename}"' _ {} \;
- name: Upload blob reports to GitHub Actions Artifacts
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: internal-blob-report-${{ matrix.shardIndex }}
path: .vitest-reports/*
include-hidden-files: true
retention-days: 1
merge-reports:
name: "📊 Merge Reports"
if: ${{ !cancelled() }}
needs: [unitTests]
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: ⎔ Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
# no cache enabled, we're not installing deps
- name: Download blob reports from GitHub Actions Artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: .vitest-reports
pattern: internal-blob-report-*
merge-multiple: true
- name: Merge reports
run: pnpm dlx vitest@3.1.4 run --merge-reports --pass-with-no-tests
+148
View File
@@ -0,0 +1,148 @@
name: "🧪 Unit Tests: Packages"
permissions:
contents: read
on:
workflow_call:
secrets:
DOCKERHUB_USERNAME:
required: false
DOCKERHUB_TOKEN:
required: false
jobs:
unitTests:
name: "🧪 Unit Tests: Packages"
runs-on: ubuntu-latest
strategy:
matrix:
shardIndex: [1]
shardTotal: [1]
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
SHARD_INDEX: ${{ matrix.shardIndex }}
SHARD_TOTAL: ${{ matrix.shardTotal }}
steps:
- name: 🔧 Disable IPv6
run: |
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=1
- name: 🔧 Configure docker address pool
run: |
CONFIG='{
"default-address-pools" : [
{
"base" : "172.17.0.0/12",
"size" : 20
},
{
"base" : "192.168.0.0/16",
"size" : 24
}
]
}'
mkdir -p /etc/docker
echo "$CONFIG" | sudo tee /etc/docker/daemon.json
- name: 🔧 Restart docker daemon
run: sudo systemctl restart docker
- name: ⬇️ Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: ⎔ Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
cache: "pnpm"
# ..to avoid rate limits when pulling images
- name: 🐳 Login to DockerHub
if: ${{ env.DOCKERHUB_USERNAME }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 🐳 Skipping DockerHub login (no secrets available)
if: ${{ !env.DOCKERHUB_USERNAME }}
run: echo "DockerHub login skipped because secrets are not available."
- name: 🐳 Pre-pull testcontainer images
if: ${{ env.DOCKERHUB_USERNAME }}
run: |
echo "Pre-pulling Docker images with authenticated session..."
docker pull postgres:14
docker pull clickhouse/clickhouse-server:25.4-alpine
docker pull redis:7-alpine
docker pull testcontainers/ryuk:0.11.0
docker pull electricsql/electric:1.2.4
echo "Image pre-pull complete"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
run: pnpm run generate
- name: 🧪 Run Package Unit Tests
run: pnpm run test:packages --reporter=default --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
- name: Gather all reports
if: ${{ !cancelled() }}
run: |
mkdir -p .vitest-reports
find . -type f -path '*/.vitest-reports/blob-*.json' \
-exec bash -c 'src="$1"; basename=$(basename "$src"); pkg=$(dirname "$src" | sed "s|^\./||;s|/\.vitest-reports$||;s|/|_|g"); cp "$src" ".vitest-reports/${pkg}-${basename}"' _ {} \;
- name: Upload blob reports to GitHub Actions Artifacts
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: packages-blob-report-${{ matrix.shardIndex }}
path: .vitest-reports/*
include-hidden-files: true
retention-days: 1
merge-reports:
name: "📊 Merge Reports"
if: ${{ !cancelled() }}
needs: [unitTests]
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: ⎔ Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
# no cache enabled, we're not installing deps
- name: Download blob reports from GitHub Actions Artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: .vitest-reports
pattern: packages-blob-report-*
merge-multiple: true
- name: Merge reports
run: pnpm dlx vitest@3.1.4 run --merge-reports --pass-with-no-tests
+156
View File
@@ -0,0 +1,156 @@
name: "🧪 Unit Tests: Webapp"
permissions:
contents: read
on:
workflow_call:
secrets:
DOCKERHUB_USERNAME:
required: false
DOCKERHUB_TOKEN:
required: false
jobs:
unitTests:
name: "🧪 Unit Tests: Webapp"
runs-on: ubuntu-latest
strategy:
matrix:
shardIndex: [1, 2, 3, 4, 5, 6, 7, 8]
shardTotal: [8]
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
SHARD_INDEX: ${{ matrix.shardIndex }}
SHARD_TOTAL: ${{ matrix.shardTotal }}
steps:
- name: 🔧 Disable IPv6
run: |
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=1
- name: 🔧 Configure docker address pool
run: |
CONFIG='{
"default-address-pools" : [
{
"base" : "172.17.0.0/12",
"size" : 20
},
{
"base" : "192.168.0.0/16",
"size" : 24
}
]
}'
mkdir -p /etc/docker
echo "$CONFIG" | sudo tee /etc/docker/daemon.json
- name: 🔧 Restart docker daemon
run: sudo systemctl restart docker
- name: ⬇️ Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: ⎔ Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
cache: "pnpm"
# ..to avoid rate limits when pulling images
- name: 🐳 Login to DockerHub
if: ${{ env.DOCKERHUB_USERNAME }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 🐳 Skipping DockerHub login (no secrets available)
if: ${{ !env.DOCKERHUB_USERNAME }}
run: echo "DockerHub login skipped because secrets are not available."
- name: 🐳 Pre-pull testcontainer images
if: ${{ env.DOCKERHUB_USERNAME }}
run: |
echo "Pre-pulling Docker images with authenticated session..."
docker pull postgres:14
docker pull clickhouse/clickhouse-server:25.4-alpine
docker pull redis:7-alpine
docker pull testcontainers/ryuk:0.11.0
docker pull electricsql/electric:1.2.4
echo "Image pre-pull complete"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
run: pnpm run generate
- name: 🧪 Run Webapp Unit Tests
run: pnpm run test:webapp --reporter=default --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres
DIRECT_URL: postgresql://postgres:postgres@localhost:5432/postgres
SESSION_SECRET: "secret"
MAGIC_LINK_SECRET: "secret"
ENCRYPTION_KEY: "dummy-encryption-keeeey-32-bytes"
DEPLOY_REGISTRY_HOST: "docker.io"
CLICKHOUSE_URL: "http://default:password@localhost:8123"
- name: Gather all reports
if: ${{ !cancelled() }}
run: |
mkdir -p .vitest-reports
find . -type f -path '*/.vitest-reports/blob-*.json' \
-exec bash -c 'src="$1"; basename=$(basename "$src"); pkg=$(dirname "$src" | sed "s|^\./||;s|/\.vitest-reports$||;s|/|_|g"); cp "$src" ".vitest-reports/${pkg}-${basename}"' _ {} \;
- name: Upload blob reports to GitHub Actions Artifacts
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: webapp-blob-report-${{ matrix.shardIndex }}
path: .vitest-reports/*
include-hidden-files: true
retention-days: 1
merge-reports:
name: "📊 Merge Reports"
if: ${{ !cancelled() }}
needs: [unitTests]
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: 10.33.2
- name: ⎔ Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 20.20.0
# no cache enabled, we're not installing deps
- name: Download blob reports from GitHub Actions Artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: .vitest-reports
pattern: webapp-blob-report-*
merge-multiple: true
- name: Merge reports
run: pnpm dlx vitest@3.1.4 run --merge-reports --pass-with-no-tests
+28 -47
View File
@@ -1,53 +1,34 @@
name: "🧪 Unit Tests"
permissions:
contents: read
on:
workflow_call:
secrets:
DOCKERHUB_USERNAME:
required: false
DOCKERHUB_TOKEN:
required: false
jobs:
unitTests:
name: "🧪 Unit Tests"
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 8.15.5
- name: ⎔ Setup node
uses: buildjet/setup-node@v4
with:
node-version: 20.11.1
cache: "pnpm"
# ..to avoid rate limits when pulling images
- name: 🐳 Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
run: pnpm run generate
- name: 🧪 Run Webapp Unit Tests
run: pnpm run test:webapp
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres
DIRECT_URL: postgresql://postgres:postgres@localhost:5432/postgres
SESSION_SECRET: "secret"
MAGIC_LINK_SECRET: "secret"
ENCRYPTION_KEY: "secret"
- name: 🧪 Run Package Unit Tests
run: pnpm run test:packages
- name: 🧪 Run Internal Unit Tests
run: pnpm run test:internal
webapp:
uses: ./.github/workflows/unit-tests-webapp.yml
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
e2e-webapp:
uses: ./.github/workflows/e2e-webapp.yml
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
packages:
uses: ./.github/workflows/unit-tests-packages.yml
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
internal:
uses: ./.github/workflows/unit-tests-internal.yml
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
+49
View File
@@ -0,0 +1,49 @@
name: Vouch - Check PR
on:
pull_request_target: # zizmor: ignore[dangerous-triggers] needed to comment/close fork PRs; safe because we never check out PR HEAD ref so no fork-controlled code runs
types: [opened, reopened]
permissions: {}
jobs:
check-vouch:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # auto-close unvouched PRs
issues: read
steps:
- uses: mitchellh/vouch/action/check-pr@c6d80ead49839655b61b422700b7a3bc9d0804a9 # v1.4.2
with:
pr-number: ${{ github.event.pull_request.number }}
auto-close: true
require-vouch: true
env:
GH_TOKEN: ${{ github.token }}
require-draft:
needs: check-vouch
permissions:
pull-requests: write # close non-draft PRs with a comment
if: >
github.event.pull_request.draft == false &&
github.event.pull_request.author_association != 'MEMBER' &&
github.event.pull_request.author_association != 'OWNER' &&
github.event.pull_request.author_association != 'COLLABORATOR' &&
github.event.pull_request.user.login != 'devin-ai-integration[bot]' &&
github.event.pull_request.user.login != 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- name: Close non-draft PR
env:
GH_TOKEN: ${{ github.token }}
run: |
STATE=$(gh pr view ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --json state -q '.state')
if [ "$STATE" != "OPEN" ]; then
echo "PR is already closed, skipping."
exit 0
fi
gh pr close ${{ github.event.pull_request.number }} \
--repo ${{ github.repository }} \
--comment "Thanks for your contribution! We require all external PRs to be opened in **draft** status first so you can address CodeRabbit review comments and ensure CI passes before requesting a review. Please re-open this PR as a draft. See [CONTRIBUTING.md](https://github.com/${{ github.repository }}/blob/main/CONTRIBUTING.md#pr-workflow) for details."
@@ -0,0 +1,24 @@
name: Vouch - Manage by Issue
on:
issue_comment:
types: [created]
permissions:
contents: write
issues: write
jobs:
manage:
runs-on: ubuntu-latest
if: >-
contains(github.event.comment.body, 'vouch') ||
contains(github.event.comment.body, 'denounce') ||
contains(github.event.comment.body, 'unvouch')
steps:
- uses: mitchellh/vouch/action/manage-by-issue@c6d80ead49839655b61b422700b7a3bc9d0804a9 # v1.4.2
with:
comment-id: ${{ github.event.comment.id }}
issue-id: ${{ github.event.issue.number }}
env:
GH_TOKEN: ${{ github.token }}
+51
View File
@@ -0,0 +1,51 @@
name: Workflow Checks
on:
push:
branches: [main]
paths:
- '.github/workflows/**'
- '.github/actions/**'
- '.github/zizmor.yml'
pull_request:
paths:
- '.github/workflows/**'
- '.github/actions/**'
- '.github/zizmor.yml'
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
actionlint:
name: Actionlint
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Run actionlint
uses: docker://rhysd/actionlint:1.7.12@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667
zizmor:
name: Zizmor
runs-on: ubuntu-latest
permissions:
security-events: write # Upload SARIF to GitHub Security tab
contents: read # Read workflow files for analysis
actions: read # Read workflow run metadata
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Run zizmor
uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3
+5
View File
@@ -0,0 +1,5 @@
rules:
unpinned-uses:
config:
policies:
'*': hash-pin
+11 -5
View File
@@ -15,6 +15,9 @@ out/
dist
packages/**/dist
# vendored bundles (generated during build)
packages/**/src/**/vendor
# Tailwind
apps/**/styles/tailwind.css
packages/**/styles/tailwind.css
@@ -29,12 +32,10 @@ yarn-debug.log*
yarn-error.log*
# local env files
.env.docker
.env
.env.*
.docker/*.env
.env.local
.env.development.local
.env.test.local
.env.production.local
!.env.example
# turbo
.turbo
@@ -63,3 +64,8 @@ apps/**/public/build
/packages/core/src/package.json
/packages/trigger-sdk/src/package.json
/packages/python/src/package.json
**/.claude/settings.local.json
.mcp.log
.mcp.json
.cursor/debug.log
ailogger-output.log
-5
View File
@@ -1,5 +0,0 @@
link-workspace-packages=false
public-hoist-pattern[]=*prisma*
prefer-workspace-packages=true
update-notifier=false
side-effects-cache=false
+1 -1
View File
@@ -1 +1 @@
v20.11.1
v20.20.0
View File
+81
View File
@@ -0,0 +1,81 @@
# Server Changes
This directory tracks changes to server-only components (webapp, supervisor, coordinator, etc.) that are not captured by changesets. Changesets only track published npm packages — server changes would otherwise go undocumented.
## When to add a file
**Server-only PRs**: If your PR only changes `apps/webapp/`, `apps/supervisor/`, `apps/coordinator/`, or other server components (and does NOT change anything in `packages/`), add a `.server-changes/` file.
**Mixed PRs** (both packages and server): Just add a changeset as usual. No `.server-changes/` file needed — the changeset covers it.
**Package-only PRs**: Just add a changeset as usual.
## File format
Create a markdown file with a descriptive name:
```
.server-changes/fix-batch-queue-stalls.md
```
With this format:
```markdown
---
area: webapp
type: fix
---
Speed up batch queue processing by removing stalls and fixing retry race
```
### Fields
- **area** (required): `webapp` | `supervisor` | `coordinator` | `kubernetes-provider` | `docker-provider`
- **type** (required): `feature` | `fix` | `improvement` | `breaking`
### Description
The body text (below the frontmatter) is a one-line description of the change. Keep it concise — it will appear in release notes.
## Lifecycle
1. Engineer adds a `.server-changes/` file in their PR
2. Files accumulate on `main` as PRs merge
3. The changeset release PR includes these in its summary
4. After the release merges, CI cleans up the consumed files
## Examples
**New feature:**
```markdown
---
area: webapp
type: feature
---
TRQL query language and the Query page
```
**Bug fix:**
```markdown
---
area: webapp
type: fix
---
Fix schedule limit counting for orgs with custom limits
```
**Improvement:**
```markdown
---
area: webapp
type: improvement
---
Use the replica for API auth queries to reduce primary load
```
+6
View File
@@ -0,0 +1,6 @@
---
area: webapp
type: feature
---
Added `/engine/v1/dev/disconnect` endpoint to auto-cancel runs when the CLI disconnects. Maximum of 500 runs can be cancelled. Uses the bulk action system when there are more than 25 runs to cancel.
+3
View File
@@ -0,0 +1,3 @@
vouch:
- github: edosrecki
- github: GautamBytes
+17 -8
View File
@@ -25,12 +25,21 @@
{
"type": "node-terminal",
"request": "launch",
"name": "Debug fairDequeuingStrategy.test.ts",
"command": "pnpm run test -t FairDequeuingStrategy",
"name": "Debug triggerTask.test.ts",
"command": "pnpm run test --run ./test/engine/triggerTask.test.ts",
"envFile": "${workspaceFolder}/.env",
"cwd": "${workspaceFolder}/apps/webapp",
"sourceMaps": true
},
{
"type": "node-terminal",
"request": "launch",
"name": "Debug opened test file",
"command": "pnpm run test -- ./${relativeFile}",
"envFile": "${workspaceFolder}/.env",
"cwd": "${workspaceFolder}",
"sourceMaps": true
},
{
"type": "chrome",
"request": "launch",
@@ -59,7 +68,7 @@
"request": "launch",
"name": "Debug V3 Dev CLI",
"command": "pnpm exec trigger dev",
"cwd": "${workspaceFolder}/references/v3-catalog",
"cwd": "${workspaceFolder}/references/hello-world",
"sourceMaps": true
},
{
@@ -83,7 +92,7 @@
"request": "launch",
"name": "Debug V3 Deploy CLI",
"command": "pnpm exec trigger deploy --self-hosted --load-image",
"cwd": "${workspaceFolder}/references/v3-catalog",
"cwd": "${workspaceFolder}/references/hello-world",
"sourceMaps": true
},
{
@@ -91,7 +100,7 @@
"request": "launch",
"name": "Debug V3 list-profiles CLI",
"command": "pnpm exec trigger list-profiles --log-level debug",
"cwd": "${workspaceFolder}/references/v3-catalog",
"cwd": "${workspaceFolder}/references/hello-world",
"sourceMaps": true
},
{
@@ -99,7 +108,7 @@
"request": "launch",
"name": "Debug V3 update CLI",
"command": "pnpm exec trigger update",
"cwd": "${workspaceFolder}/references/v3-catalog",
"cwd": "${workspaceFolder}/references/hello-world",
"sourceMaps": true
},
{
@@ -107,7 +116,7 @@
"request": "launch",
"name": "Debug V3 Management",
"command": "pnpm run management",
"cwd": "${workspaceFolder}/references/v3-catalog",
"cwd": "${workspaceFolder}/references/hello-world",
"sourceMaps": true
},
{
@@ -146,7 +155,7 @@
"type": "node-terminal",
"request": "launch",
"name": "Debug RunQueue tests",
"command": "pnpm run test ./src/run-queue/index.test.ts",
"command": "pnpm run test ./src/run-queue/index.test.ts --run",
"cwd": "${workspaceFolder}/internal-packages/run-engine",
"sourceMaps": true
},
+2 -1
View File
@@ -6,5 +6,6 @@
"**/node_modules/**": true,
"packages/cli-v3/e2e": true
},
"vitest.disableWorkspaceWarning": true
"vitest.disableWorkspaceWarning": true,
"chat.agent.maxRequests": 10000
}
+68
View File
@@ -0,0 +1,68 @@
# Guidance for Coding Agents
This repository is a pnpm monorepo managed with Turbo. It contains multiple apps and packages that make up the Trigger.dev platform and SDK.
## Repository layout
- `apps/webapp` Remix application that serves as the main API and dashboard.
- `apps/supervisor` Node application for executing built tasks.
- `packages/*` Published packages such as `@trigger.dev/sdk`, the CLI (`trigger.dev`), and shared libraries.
- `internal-packages/*` Internal-only packages used by the webapp and other apps.
- `references/*` Example projects for manual testing and development of new features.
- `ai/references` Contains additional documentation including an overview (`repo.md`) and testing guidelines (`tests.md`).
See `ai/references/repo.md` for a more complete explanation of the workspaces.
## Development setup
1. Install dependencies with `pnpm i` (pnpm `10.33.2` and Node.js `20.20.0` are required).
2. Copy `.env.example` to `.env` and generate a random 16 byte hex string for `ENCRYPTION_KEY` (`openssl rand -hex 16`). Update other secrets if needed.
3. Start the local services with Docker:
```bash
pnpm run docker
```
4. Run database migrations:
```bash
pnpm run db:migrate
```
5. Build the webapp, CLI and SDK packages:
```bash
pnpm run build --filter webapp && pnpm run build --filter trigger.dev && pnpm run build --filter @trigger.dev/sdk
```
6. Launch the development server:
```bash
pnpm run dev --filter webapp
```
The webapp runs on <http://localhost:3030>.
For full setup instructions see `CONTRIBUTING.md`.
## Running tests
- Unit tests use **vitest**. Run all tests:
```bash
pnpm run test
```
- Run tests for a specific workspace (example for `webapp`):
```bash
pnpm run test --filter webapp
```
- Prefer running a single test file from within its directory:
```bash
cd apps/webapp
pnpm run test ./src/components/Button.test.ts
```
If packages in that workspace need to be built first, run `pnpm run build --filter webapp`.
Refer to `ai/references/tests.md` for details on writing tests. Tests should avoid mocks or stubs and use the helpers from `@internal/testcontainers` when Redis or Postgres are needed.
## Coding style
- Formatting is enforced using Prettier. Run `pnpm run format` before committing.
- Follow the existing project conventions. Test files live beside the files under test and use descriptive `describe` and `it` blocks.
- Do not commit directly to the `main` branch. All changes should be made in a separate branch and go through a pull request.
## Additional docs
- The root `README.md` describes Trigger.dev and links to documentation.
- The `docs` workspace contains our documentation site, which can be run locally with:
```bash
pnpm run dev --filter docs
```
- `references/README.md` explains how to create new reference projects for manual testing.
+41 -28
View File
@@ -1,24 +1,49 @@
# Changesets
# Changesets and Server Changes
Trigger.dev uses [changesets](https://github.com/changesets/changesets) to manage updated our packages and releasing them to npm.
Trigger.dev uses [changesets](https://github.com/changesets/changesets) to manage package versions and releasing them to npm. For server-only changes, we use a lightweight `.server-changes/` convention.
## Adding a changeset
## Adding a changeset (package changes)
To add a changeset, use `pnpm run changeset:add` and follow the instructions [here](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md). Please only ever select one of our public packages when adding a changeset.
## Release instructions (local only)
## Adding a server change (server-only changes)
Based on the instructions [here](https://github.com/changesets/changesets/blob/main/docs/intro-to-using-changesets.md)
If your PR only changes server components (`apps/webapp/`, `apps/supervisor/`, etc.) and does NOT change any published packages, add a `.server-changes/` file instead of a changeset:
1. Run `pnpm run changeset:version`
2. Run `pnpm run changeset:release`
```sh
cat > .server-changes/fix-batch-queue-stalls.md << 'EOF'
---
area: webapp
type: fix
---
Speed up batch queue processing by removing stalls and fixing retry race
EOF
```
- `area`: `webapp` | `supervisor` | `coordinator` | `kubernetes-provider` | `docker-provider`
- `type`: `feature` | `fix` | `improvement` | `breaking`
For **mixed PRs** (both packages and server): just add a changeset. No `.server-changes/` file needed.
See `.server-changes/README.md` for full documentation.
## When to add which
| PR changes | What to add |
|---|---|
| Only packages (`packages/`) | Changeset (`pnpm run changeset:add`) |
| Only server (`apps/`) | `.server-changes/` file |
| Both packages and server | Just the changeset |
## Release instructions (CI)
Please follow the best-practice of adding changesets in the same commit as the code making the change with `pnpm run changeset:add`, as it will allow our release.yml CI workflow to function properly:
- Anytime new changesets are added in a commit in the `main` branch, the [release.yml](./.github/workflows/release.yml) workflow will run and will automatically create/update a PR with a fresh run of `pnpm run changeset:version`.
- When the version PR is merged into `main`, the release.yml workflow will automatically run `pnpm run changeset:release` to build and release packages to npm.
- Anytime new changesets are added in a commit in the `main` branch, the [changesets-pr.yml](./.github/workflows/changesets-pr.yml) workflow will run and will automatically create/update a PR with a fresh run of `pnpm run changeset:version`.
- The release PR body is automatically enhanced with a clean, deduplicated summary that includes both package changes and `.server-changes/` entries.
- Consumed `.server-changes/` files are removed on the `changeset-release/main` branch — the same way changesets deletes `.changeset/*.md` files. When the release PR merges, they're gone from main.
- When the version PR is merged into `main`, the [release.yml](./.github/workflows/release.yml) workflow will automatically build, release packages to npm, and create a single unified GitHub release.
## Pre-release instructions
@@ -30,28 +55,16 @@ Please follow the best-practice of adding changesets in the same commit as the c
## Snapshot instructions
!MAKE SURE TO UPDATE THE TAG IN THE INSTRUCTIONS BELOW!
1. Update the `.changeset/config.json` file to set the `"changelog"` field to this:
1. Add changesets as usual
```sh
pnpm run changeset:add
```json
"changelog": "@changesets/cli/changelog",
```
2. Create a snapshot version (replace "prerelease" with your tag)
2. Do a temporary commit (do NOT push this, you should undo it after)
```sh
pnpm exec changeset version --snapshot prerelease
```
3. Run `./scripts/publish-prerelease.sh prerelease`
3. Build the packages:
You can choose a different tag if you want, but usually `prerelease` is fine.
```sh
pnpm run build --filter "@trigger.dev/*" --filter "trigger.dev"
```
4. Publish the snapshot (replace "dev" with your tag)
```sh
pnpm exec changeset publish --no-git-tag --snapshot --tag prerelease
```
5. Undo the commit where you updated the config.json file.
+247
View File
@@ -0,0 +1,247 @@
# CLAUDE.md
This file provides guidance to Claude Code when working with this repository. Subdirectory CLAUDE.md files provide deeper context when you navigate into specific areas.
## Build and Development Commands
This is a pnpm 10.33.2 monorepo using Turborepo. Run commands from root with `pnpm run`.
```bash
pnpm run docker # Start Docker services (PostgreSQL, Redis, Electric)
pnpm run db:migrate # Run database migrations
pnpm run db:seed # Seed the database (required for reference projects)
# Build packages (required before running)
pnpm run build --filter webapp && pnpm run build --filter trigger.dev && pnpm run build --filter @trigger.dev/sdk
pnpm run dev --filter webapp # Run webapp (http://localhost:3030)
pnpm run dev --filter trigger.dev --filter "@trigger.dev/*" # Watch CLI and packages
```
### Verifying Changes
The verification command depends on where the change lives:
- **Apps and internal packages** (`apps/*`, `internal-packages/*`): Use `typecheck`. **Never use `build`** for these — building proves almost nothing about correctness.
- **Public packages** (`packages/*`): Use `build`.
```bash
# Apps and internal packages — use typecheck
pnpm run typecheck --filter webapp # ~1-2 minutes
pnpm run typecheck --filter @internal/run-engine
# Public packages — use build
pnpm run build --filter @trigger.dev/sdk
pnpm run build --filter @trigger.dev/core
```
Only run typecheck/build after major changes (new files, significant refactors, schema changes). For small edits, trust the types and let CI catch issues.
## Testing
We use vitest exclusively. **Never mock anything** - use testcontainers instead.
```bash
pnpm run test --filter webapp # All tests for a package
cd internal-packages/run-engine
pnpm run test ./src/engine/tests/ttl.test.ts --run # Single test file
pnpm run build --filter @internal/run-engine # May need to build deps first
```
Test files go next to source files (e.g., `MyService.ts` -> `MyService.test.ts`).
### Testcontainers for Redis/PostgreSQL
```typescript
import { redisTest, postgresTest, containerTest } from "@internal/testcontainers";
redisTest("should use redis", async ({ redisOptions }) => {
/* ... */
});
postgresTest("should use postgres", async ({ prisma }) => {
/* ... */
});
containerTest("should use both", async ({ prisma, redisOptions }) => {
/* ... */
});
```
## Changesets and Server Changes
When modifying any public package (`packages/*` or `integrations/*`), add a changeset:
```bash
pnpm run changeset:add
```
- Default to **patch** for bug fixes and minor changes
- Confirm with maintainers before selecting **minor** (new features)
- **Never** select major without explicit approval
When modifying only server components (`apps/webapp/`, `apps/supervisor/`, etc.) with no package changes, add a `.server-changes/` file instead. See `.server-changes/README.md` for format and documentation.
## Dependency Pinning
Zod is pinned to a single version across the entire monorepo (currently `3.25.76`). When adding zod to a new or existing package, use the **exact same version** as the rest of the repo - never a different version or a range. Mismatched zod versions cause runtime type incompatibilities (e.g., schemas from one package can't be used as body validators in another).
## Architecture Overview
### Request Flow
User API call -> Webapp routes -> Services -> RunEngine -> Redis Queue -> Supervisor -> Container execution -> Results back through RunEngine -> ClickHouse (analytics) + PostgreSQL (state)
### Apps
- **apps/webapp**: Remix 2.17.4 app - main API, dashboard, orchestration. Uses Express server.
- **apps/supervisor**: Manages task execution containers (Docker/Kubernetes).
### Public Packages
- **packages/trigger-sdk** (`@trigger.dev/sdk`): Main SDK for writing tasks
- **packages/cli-v3** (`trigger.dev`): CLI - also bundles code that goes into customer task images
- **packages/core** (`@trigger.dev/core`): Shared types. **Import subpaths only** (never root).
- **packages/build** (`@trigger.dev/build`): Build extensions and types
- **packages/react-hooks**: React hooks for realtime and triggering
- **packages/redis-worker** (`@trigger.dev/redis-worker`): Redis-based background job system
### Internal Packages
- **internal-packages/database**: Prisma 6.14.0 client and schema (PostgreSQL)
- **internal-packages/clickhouse**: ClickHouse client, schema migrations, analytics queries
- **internal-packages/run-engine**: "Run Engine 2.0" - core run lifecycle management
- **internal-packages/redis**: Redis client creation utilities (ioredis)
- **internal-packages/testcontainers**: Test helpers for Redis/PostgreSQL containers
- **internal-packages/schedule-engine**: Durable cron scheduling
- **internal-packages/zodworker**: Graphile-worker wrapper (DEPRECATED - use redis-worker)
### Legacy V1 Engine Code
The `apps/webapp/app/v3/` directory name is misleading - most code there is actively used by V2. Only specific files are V1-only legacy (MarQS queue, triggerTaskV1, cancelTaskRunV1, etc.). See `apps/webapp/CLAUDE.md` for the exact list. When you encounter V1/V2 branching in services, only modify V2 code paths. All new work uses Run Engine 2.0 (`@internal/run-engine`) and redis-worker.
### Documentation
Docs live in `docs/` as a Mintlify site (MDX format). See `docs/CLAUDE.md` for conventions.
### Reference Projects
The `references/` directory contains test workspaces for testing SDK and platform features. Use `references/hello-world` to manually test changes before submitting PRs.
## Docker Image Guidelines
When updating Docker image references:
- **Always use multiplatform/index digests**, not architecture-specific digests
- Architecture-specific digests cause CI failures on different build environments
- Use the digest from the main Docker Hub page, not from a specific OS/ARCH variant
## Writing Trigger.dev Tasks
Always import from `@trigger.dev/sdk`. Never use `@trigger.dev/sdk/v3` or deprecated `client.defineJob`.
```typescript
import { task } from "@trigger.dev/sdk";
export const myTask = task({
id: "my-task",
run: async (payload: { message: string }) => {
// Task logic
},
});
```
### SDK Documentation Rules
The `rules/` directory contains versioned SDK documentation distributed via the SDK installer. Current version: `rules/manifest.json`. Do NOT update `rules/` or `.claude/skills/trigger-dev-tasks/` unless explicitly asked - these are maintained in separate dedicated passes.
## Testing with hello-world Reference Project
First-time setup:
1. `pnpm run db:seed` to seed the database
2. Build CLI: `pnpm run build --filter trigger.dev && pnpm i`
3. Authorize: `cd references/hello-world && pnpm exec trigger login -a http://localhost:3030`
Running: `cd references/hello-world && pnpm exec trigger dev`
## Local Task Testing Workflow
### Step 1: Start Webapp in Background
```bash
# Run from repo root with run_in_background: true
pnpm run dev --filter webapp
curl -s http://localhost:3030/healthcheck # Verify running
```
### Step 2: Start Trigger Dev in Background
```bash
cd references/hello-world && pnpm exec trigger dev
# Wait for "Local worker ready [node]"
```
### Step 3: Trigger and Monitor Tasks via MCP
```
mcp__trigger__get_current_worker(projectRef: "proj_rrkpdguyagvsoktglnod", environment: "dev")
mcp__trigger__trigger_task(projectRef: "proj_rrkpdguyagvsoktglnod", environment: "dev", taskId: "hello-world", payload: {"message": "Hello"})
mcp__trigger__list_runs(projectRef: "proj_rrkpdguyagvsoktglnod", environment: "dev", taskIdentifier: "hello-world", limit: 5)
```
Dashboard: http://localhost:3030/orgs/references-9dfd/projects/hello-world-97DT/env/dev/runs
<!-- intent-skills:start -->
# Skill mappings — when working in these areas, load the linked skill file into context.
skills:
- task: "Using agentcrumbs for debug tracing, adding crumbs, trails, markers, querying traces, or stripping debug code before merge"
load: "node_modules/agentcrumbs/skills/agentcrumbs/SKILL.md"
- task: "Setting up agentcrumbs in the project, initializing namespace catalog, running crumbs init"
load: "node_modules/agentcrumbs/skills/agentcrumbs/init/SKILL.md"
<!-- intent-skills:end -->
## agentcrumbs
Add crumbs as you write code — not just when debugging. Mark lines with
`// @crumbs` or wrap blocks in `// #region @crumbs`. They stay on the
branch throughout development and are stripped by `agentcrumbs strip`
before merge.
### Namespaces
| Namespace | Description | Path |
| ----------------- | ---------------------------------------------- | ----------------------------------- |
| `webapp` | Main Remix app — API, dashboard, orchestration | `apps/webapp` |
| `supervisor` | Task execution container manager | `apps/supervisor` |
| `sdk` | Main SDK for writing tasks | `packages/trigger-sdk` |
| `cli` | CLI and task image bundling | `packages/cli-v3` |
| `core` | Shared types and subpath exports | `packages/core` |
| `build` | Build extensions and types | `packages/build` |
| `react-hooks` | React hooks for realtime/triggering | `packages/react-hooks` |
| `redis-worker` | Redis-based background job system | `packages/redis-worker` |
| `run-engine` | Run Engine 2.0 — core run lifecycle | `internal-packages/run-engine` |
| `database` | Prisma client and schema | `internal-packages/database` |
| `clickhouse` | ClickHouse client, migrations, analytics | `internal-packages/clickhouse` |
| `schedule-engine` | Durable cron scheduling | `internal-packages/schedule-engine` |
| `run-queue` | Run queue management | `internal-packages/run-queue` |
Do not invent new namespaces — pick from this table or ask first.
### For PR reviewers
Do not flag `// @crumbs` markers, `#region @crumbs` blocks, or agentcrumbs
imports in reviews. These are temporary debug instrumentation stripped
before merge. Data logged in crumbs (IDs, names, values) never reaches
production.
### CLI
```bash
pnpm exec agentcrumbs collect # start collector (multi-service)
pnpm exec agentcrumbs tail --app trigger # live tail
pnpm exec agentcrumbs clear --app trigger # remove crumbs before merge
```
The preferred way to query for crumbs is to use `pnpm exec agentcrumbs query --app trigger` with the `--limit` option and cursor pagination, and clear existing crumbs before reproducing a bug via `pnpm exec agentcrumbs clear --app trigger`.
+106 -137
View File
@@ -2,10 +2,25 @@
Thank you for taking the time to contribute to Trigger.dev. Your involvement is not just welcomed, but we encourage it! 🚀
Please take some time to read this guide to understand contributing best practices for Trigger.dev.
Please take some time to read this guide to understand contributing best practices for Trigger.dev. Note that we use [vouch](https://github.com/mitchellh/vouch) to manage contributor trust, so you'll need to be vouched before opening a PR.
Thank you for helping us make Trigger.dev even better! 🤩
> **Important:** We only accept PRs that address a single issue. Please do not submit PRs containing multiple unrelated fixes or features. If you have multiple contributions, open a separate PR for each one.
## Getting vouched (required before opening a PR)
We use [vouch](https://github.com/mitchellh/vouch) to manage contributor trust. **PRs from unvouched users are automatically closed.**
Before you open your first pull request, you need to be vouched by a maintainer. Here's how:
1. Open a [Vouch Request](https://github.com/triggerdotdev/trigger.dev/issues/new?template=vouch-request.yml) issue.
2. Tell us what you'd like to work on and share any relevant background.
3. A maintainer will review your request and vouch for you by commenting on the issue.
4. Once vouched, your PRs will be accepted normally.
If you're unsure whether you're already vouched, go ahead and open a PR — the check will tell you.
## Developing
The development branch is `main`. This is the branch that all pull
@@ -14,8 +29,8 @@ branch are tagged into a release periodically.
### Prerequisites
- [Node.js](https://nodejs.org/en) version 20.11.1
- [pnpm package manager](https://pnpm.io/installation) version 8.15.5
- [Node.js](https://nodejs.org/en) version 20.20.0
- [pnpm package manager](https://pnpm.io/installation) version 10.33.2
- [Docker](https://www.docker.com/get-started/)
- [protobuf](https://github.com/protocolbuffers/protobuf)
@@ -34,9 +49,9 @@ branch are tagged into a release periodically.
```
cd trigger.dev
```
3. Ensure you are on the correct version of Node.js (20.11.1). If you are using `nvm`, there is an `.nvmrc` file that will automatically select the correct version of Node.js when you navigate to the repository.
3. Ensure you are on the correct version of Node.js (20.20.0). If you are using `nvm`, there is an `.nvmrc` file that will automatically select the correct version of Node.js when you navigate to the repository.
4. Run `corepack enable` to use the correct version of pnpm (`8.15.5`) as specified in the root `package.json` file.
4. Run `corepack enable` to use the correct version of pnpm (`10.33.2`) as specified in the root `package.json` file.
5. Install the required packages using pnpm.
```
@@ -56,23 +71,25 @@ branch are tagged into a release periodically.
Feel free to update `SESSION_SECRET` and `MAGIC_LINK_SECRET` as well using the same method.
8. Start Docker. This starts the required services like Postgres & Redis. If this is your first time using Docker, consider going through this [guide](DOCKER_INSTALLATION.md)
8. Start Docker. This starts the required services: Postgres, Redis, Electric, and ClickHouse (the ClickHouse migrator runs once on first start). If this is your first time using Docker, consider going through this [guide](DOCKER_INSTALLATION.md).
```
pnpm run docker
```
This will also start and run a local instance of [pgAdmin](https://www.pgadmin.org/) on [localhost:5480](http://localhost:5480), preconfigured with email `admin@example.com` and pwd `admin`. Then use `postgres` as the password to the Trigger.dev server.
9. Migrate the database
```
pnpm run db:migrate
```
10. Build the server app
10. Build the webapp, CLI, and SDK
```
pnpm run build --filter webapp
pnpm run build --filter webapp --filter trigger.dev --filter @trigger.dev/sdk
```
11. Run the app. See the section below.
11. Seed the database. This creates a local user, a `References` org, and the reference projects (including `hello-world`) with stable IDs.
```
pnpm run db:seed
```
12. Run the app. See the section below.
## Running
@@ -86,33 +103,26 @@ branch are tagged into a release periodically.
2. Once the app is running click the magic link button and enter your email. You will automatically be logged in, since you are running locally. Create an Org and your first project in the dashboard.
## Manual testing using v3-catalog
## Manual testing using hello-world
We use the `<root>/references/v3-catalog` subdirectory as a staging ground for testing changes to the SDK (`@trigger.dev/sdk` at `<root>/packages/trigger-sdk`), the Core package (`@trigger.dev/core` at `<root>packages/core`), the CLI (`trigger.dev` at `<root>/packages/cli-v3`) and the platform (The remix app at `<root>/apps/webapp`). The instructions below will get you started on using the `v3-catalog` for local development of Trigger.dev (v3).
We use the `<root>/references/hello-world` subdirectory as a staging ground for testing changes to the SDK (`@trigger.dev/sdk` at `<root>/packages/trigger-sdk`), the Core package (`@trigger.dev/core` at `<root>packages/core`), the CLI (`trigger.dev` at `<root>/packages/cli-v3`) and the platform (The remix app at `<root>/apps/webapp`). The instructions below will get you started on using the `hello-world` for local development of Trigger.dev.
### First-time setup
First, make sure you are running the webapp according to the instructions above. Then:
First, make sure you are running the webapp according to the instructions above. The seed step from setup already created a `hello-world` project under the `References` org with the stable ref `proj_rrkpdguyagvsoktglnod` — log in at http://localhost:3030 with any email to access it. Then:
1. In Postgres go to the "Organizations" table and on your org set the `v3Enabled` column to `true`.
2. Visit http://localhost:3030 in your browser and create a new V3 project called "v3-catalog". If you don't see an option for V3, you haven't set the `v3Enabled` flag to true.
3. In Postgres go to the "Projects" table and for the project you create change the `externalRef` to `yubjwjsfkxnylobaqvqz`.
4. Build the CLI
1. Build the CLI (skip if you already ran the build step in setup)
```sh
# Build the CLI
pnpm run build --filter trigger.dev
# Make it accessible to `pnpm exec`
pnpm i
```
5. Change into the `<root>/references/v3-catalog` directory and authorize the CLI to the local server:
2. Change into the `<root>/references/hello-world` directory and authorize the CLI to the local server:
```sh
cd references/v3-catalog
cd references/hello-world
cp .env.example .env
pnpm exec trigger login -a http://localhost:3030
```
@@ -122,7 +132,7 @@ This will open a new browser window and authorize the CLI against your local use
You can optionally pass a `--profile` flag to the `login` command, which will allow you to use the CLI with separate accounts/servers. We suggest using a profile called `local` for your local development:
```sh
cd references/v3-catalog
cd references/hello-world
pnpm exec trigger login -a http://localhost:3030 --profile local
# later when you run the dev or deploy command:
pnpm exec trigger dev --profile local
@@ -131,7 +141,7 @@ pnpm exec trigger deploy --profile local
### Running
The following steps should be followed any time you start working on a new feature you want to test in v3:
The following steps should be followed any time you start working on a new feature you want to test:
1. Make sure the webapp is running on localhost:3030
@@ -141,95 +151,40 @@ The following steps should be followed any time you start working on a new featu
pnpm run dev --filter trigger.dev --filter "@trigger.dev/*"
```
3. Open another terminal window, and change into the `<root>/references/v3-catalog` directory.
3. Open another terminal window, and change into the `<root>/references/hello-world` directory.
4. You'll need to run the following commands to setup prisma and migrate the database:
4. Run the `dev` command, which will register all the local tasks with the platform and allow you to start testing task execution:
```sh
pnpm exec prisma migrate deploy
pnpm run generate:prisma
```
5. Run the `dev` command, which will register all the local tasks with the platform and allow you to start testing task execution:
```sh
# in <root>/references/v3-catalog
# in <root>/references/hello-world
pnpm exec trigger dev
```
If you want additional debug logging, you can use the `--log-level debug` flag:
```sh
# in <root>/references/v3-catalog
# in <root>/references/hello-world
pnpm exec trigger dev --log-level debug
```
6. If you make any changes in the CLI/Core/SDK, you'll need to `CTRL+C` to exit the `dev` command and restart it to pickup changes. Any changes to the files inside of the `v3-catalog/src/trigger` dir will automatically be rebuilt by the `dev` command.
5. If you make any changes in the CLI/Core/SDK, you'll need to `CTRL+C` to exit the `dev` command and restart it to pickup changes. Any changes to the files inside of the `hello-world/src/trigger` dir will automatically be rebuilt by the `dev` command.
7. Navigate to the `v3-catalog` project in your local dashboard at localhost:3030 and you should see the list of tasks.
6. Navigate to the `hello-world` project in your local dashboard at localhost:3030 and you should see the list of tasks.
8. Go to the "Test" page in the sidebar and select a task. Then enter a payload and click "Run test". You can tell what the payloads should be by looking at the relevant task file inside the `/references/v3-catalog/src/trigger` folder. Many of them accept an empty payload.
7. Go to the "Test" page in the sidebar and select a task. Then enter a payload and click "Run test". You can tell what the payloads should be by looking at the relevant task file inside the `/references/hello-world/src/trigger` folder. Many of them accept an empty payload.
9. Feel free to add additional files in `v3-catalog/src/trigger` to test out specific aspects of the system, or add in edge cases.
## Running end-to-end webapp tests (deprecated)
To run the end-to-end tests, follow the steps below:
1. Set up environment variables (copy example envs into the correct place)
```sh
cp ./.env.example ./.env
cp ./references/nextjs-test/.env.example ./references/nextjs-test/.env.local
```
2. Set up dependencies
```sh
# Build packages
pnpm run build --filter @references/nextjs-test^...
pnpm --filter @trigger.dev/database generate
# Move trigger-cli bin to correct place
pnpm install --frozen-lockfile
# Install playwrite browsers (ONE TIME ONLY)
npx playwright install
```
3. Set up the database
```sh
pnpm run docker
pnpm run db:migrate
pnpm run db:seed
```
4. Run the end-to-end tests
```sh
pnpm run test:e2e
```
### Cleanup
The end-to-end tests use a `setup` and `teardown` script to seed the database with test data. If the test runner doesn't exit cleanly, then the database can be left in a state where the tests can't run because the `setup` script will try to create data that already exists. If this happens, you can manually delete the `users` and `organizations` from the database using prisma studio:
```sh
# With the database running (i.e. pnpm run docker)
pnpm run db:studio
```
8. Feel free to add additional files in `hello-world/src/trigger` to test out specific aspects of the system, or add in edge cases.
## Adding and running migrations
1. Modify internal-packages/database/prisma/schema.prisma file
2. Change directory to the packages/database folder
1. Modify `internal-packages/database/prisma/schema.prisma`.
2. Change directory to the database package:
```sh
cd packages/database
cd internal-packages/database
```
3. Create a migration
3. Create a migration:
```
pnpm run db:migrate:dev:create
@@ -237,58 +192,39 @@ pnpm run db:studio
This creates a migration file. Check the migration file does only what you want. If you're adding any database indexes they must use `CONCURRENTLY`, otherwise they'll lock the table when executed.
4. Run the migration.
4. Run the migration:
```
pnpm run db:migrate:deploy
pnpm run generate
```
```
pnpm run db:migrate:deploy
pnpm run generate
```
This executes the migrations against your database and applies changes to the database schema(s), and then regenerates the Prisma client.
This executes the migrations against your database and applies changes to the database schema(s), and then regenerates the Prisma client.
4. Commit generated migrations as well as changes to the schema.prisma file
5. If you're using VSCode you may need to restart the Typescript server in the webapp to get updated type inference. Open a TypeScript file, then open the Command Palette (View > Command Palette) and run `TypeScript: Restart TS server`.
## Add sample jobs
The [references/job-catalog](./references/job-catalog/) project defines simple jobs you can get started with.
1. `cd` into `references/job-catalog`
2. Create a `.env` file with the following content,
replacing `<TRIGGER_DEV_API_KEY>` with an actual key:
```env
TRIGGER_API_KEY=[TRIGGER_DEV_API_KEY]
TRIGGER_API_URL=http://localhost:3030
```
`TRIGGER_API_URL` is used to configure the URL for your Trigger.dev instance,
where the jobs will be registered.
3. Run one of the the `job-catalog` files:
```sh
pnpm run events
```
This will open up a local server using `express` on port 8080. Then in a new terminal window you can run the trigger-cli dev command:
```sh
pnpm run dev:trigger
```
See the [Job Catalog](./references/job-catalog/README.md) file for more.
4. Navigate to your trigger.dev instance ([http://localhost:3030](http://localhost:3030/)), to see the jobs.
You can use the test feature to trigger them.
5. Commit the generated migration files as well as the changes to `schema.prisma`.
6. If you're using VSCode you may need to restart the TypeScript server in the webapp to get updated type inference. Open a TypeScript file, then open the Command Palette (View > Command Palette) and run `TypeScript: Restart TS server`.
## Making a pull request
**If you get errors, be sure to fix them before committing.**
- Be sure to [check the "Allow edits from maintainers" option](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) while creating you PR.
- If your PR refers to or fixes an issue, be sure to add `refs #XXX` or `fixes #XXX` to the PR description. Replacing `XXX` with the respective issue number. See more about [Linking a pull request to an issue
](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
> **Note:** We may close PRs if we decide that the cost of integrating the change outweighs the benefits. To improve the chances of your PR getting accepted, follow the guidelines below.
### PR workflow
1. **Always open your PR in draft status first.** Do not mark it as "Ready for Review" until the steps below are complete.
2. **Address all CodeRabbit code review comments.** Our CI runs an automated code review via CodeRabbit. Go through each comment and either fix the issue or resolve it with a comment explaining why no change is needed.
3. **Wait for all CI checks to pass.** Do not mark the PR as "Ready for Review" until every check is green.
4. **Then mark the PR as "Ready for Review"** so a maintainer can take a look.
### Cost/benefit analysis for risky changes
If your change touches core infrastructure, modifies widely-used code paths, or could introduce regressions, consider doing a brief cost/benefit analysis and including it in the PR description. Explain what the benefit is to users and why the risk is worth it. This goes a long way toward helping maintainers evaluate your contribution.
### General guidelines
- Be sure to [check the "Allow edits from maintainers" option](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) while creating your PR.
- If your PR refers to or fixes an issue, be sure to add `refs #XXX` or `fixes #XXX` to the PR description. Replacing `XXX` with the respective issue number. See more about [Linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
- Be sure to fill the PR Template accordingly.
## Adding changesets
@@ -311,6 +247,39 @@ You will be prompted to select which packages to include in the changeset. Only
Most of the time the changes you'll make are likely to be categorized as patch releases. If you feel like there is the need for a minor or major release of the package based on the changes being made, add the changeset as such and it will be discussed during PR review.
## Adding server changes
Changesets only track published npm packages. If your PR only changes server components (`apps/webapp/`, `apps/supervisor/`, `apps/coordinator/`, etc.) with no package changes, add a `.server-changes/` file so the change appears in release notes.
Create a markdown file with a descriptive name:
```sh
cat > .server-changes/fix-batch-queue-stalls.md << 'EOF'
---
area: webapp
type: fix
---
Speed up batch queue processing by removing stalls and fixing retry race
EOF
```
**Fields:**
- `area` (required): `webapp` | `supervisor` | `coordinator` | `kubernetes-provider` | `docker-provider`
- `type` (required): `feature` | `fix` | `improvement` | `breaking`
The body text (below the frontmatter) is a one-line description of the change. Keep it concise — it will appear in release notes.
**When to add which:**
| PR changes | What to add |
|---|---|
| Only packages (`packages/`) | Changeset |
| Only server (`apps/`) | `.server-changes/` file |
| Both packages and server | Just the changeset |
See `.server-changes/README.md` for more details.
## Troubleshooting
### EADDRINUSE: address already in use :::3030
+24 -15
View File
@@ -8,47 +8,56 @@ If you don't have Docker installed on your machine, you'll run into some complic
Below are the steps on how you can avoid that.
First you need to setup docker-compose as it is an underlying tool that this command: `pnpm run docker` fires behind the scene.
First you need to setup docker compose as it is an underlying tool that this command: `pnpm run docker` fires behind the scene.
## Linux
To install Docker Compose on Linux Ubuntu via the terminal, you can follow these steps:
To install Docker Compose on Linux Ubuntu, you can follow these steps:
1. Update the package index on your system by running the following command:
1. Create the Docker config directory and cli-plugins subdirectory:
```shell
sudo apt update
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
```
2. Install the required dependencies by running the following command:
2. Download the Docker Compose plugin:
```shell
sudo apt install curl
curl -SL "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o $DOCKER_CONFIG/cli-plugins/docker-compose
```
3. Download the Docker Compose binary into the `/usr/local/bin` directory using the `curl` command:
Note:
- To install for all users, replace `$DOCKER_CONFIG/cli-plugins` with `/usr/local/lib/docker/cli-plugins`
3. Set the appropriate permissions to make the Docker Compose plugin executable:
```shell
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
```
4. Set the appropriate permissions to make the `docker-compose` binary executable:
If you installed for all users:
```shell
sudo chmod +x /usr/local/bin/docker-compose
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
```
5. Verify that Docker Compose has been successfully installed by running the following command:
4. Verify that Docker Compose has been successfully installed:
```shell
docker-compose --version
docker compose version
```
This command should display the version information of Docker Compose without any errors.
You should see output similar to:
After following these steps, you should have Docker Compose installed on your Ubuntu system, and you can use it by running `docker-compose` commands in the terminal.
```
Docker Compose version vX.Y.Z
```
When you've verified that the `docker-compose` package is installed and you proceed to start Docker with `pnpm run docker`.
After following these steps, you should have Docker Compose installed on your Ubuntu system, and you can use it by running `docker compose` commands in the terminal.
When you've verified that the `docker compose` package is installed and you proceed to start Docker with `pnpm run docker`.
You'll probably get an error similar to the one below:
+68 -31
View File
@@ -1,44 +1,76 @@
<div align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://imagedelivery.net/3TbraffuDZ4aEf8KWOmI_w/a45d1fa2-0ae8-4a39-4409-f4f934bfae00/public">
<source media="(prefers-color-scheme: light)" srcset="https://imagedelivery.net/3TbraffuDZ4aEf8KWOmI_w/3f5ad4c1-c4c8-4277-b622-290e7f37bd00/public">
<img alt="Trigger.dev logo" src="https://imagedelivery.net/3TbraffuDZ4aEf8KWOmI_w/a45d1fa2-0ae8-4a39-4409-f4f934bfae00/public">
</picture>
### Open source background jobs and AI infrastructure
[Discord](https://trigger.dev/discord) | [Website](https://trigger.dev) | [Issues](https://github.com/triggerdotdev/trigger.dev/issues) | [Docs](https://trigger.dev/docs)
![Trigger.dev logo](https://content.trigger.dev/github-header-banner.jpg)
[![Twitter](https://img.shields.io/twitter/url/https/twitter.com/triggerdotdev.svg?style=social&label=Follow%20%40trigger.dev)](https://twitter.com/triggerdotdev)
### Build and deploy fullymanaged AI agents and workflows
[Website](https://trigger.dev) | [Docs](https://trigger.dev/docs) | [Issues](https://github.com/triggerdotdev/trigger.dev/issues) | [Example projects](https://github.com/triggerdotdev/examples) | [Feature requests](https://triggerdev.featurebase.app/) | [Public roadmap](https://triggerdev.featurebase.app/roadmap) | [Self-hosting](https://trigger.dev/docs/self-hosting/overview)
[![Open Source](https://img.shields.io/badge/Open%20Source-%E2%9D%A4-red.svg)](https://github.com/triggerdotdev/trigger.dev)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/triggerdotdev/trigger.dev/blob/main/LICENSE)
[![npm](https://img.shields.io/npm/v/@trigger.dev/sdk.svg?label=npm)](https://www.npmjs.com/package/@trigger.dev/sdk)
[![SDK downloads](https://img.shields.io/npm/dm/@trigger.dev/sdk.svg?label=SDK%20downloads)](https://www.npmjs.com/package/@trigger.dev/sdk)
[![Twitter Follow](https://img.shields.io/twitter/follow/triggerdotdev?style=social)](https://twitter.com/triggerdotdev)
[![Discord](https://img.shields.io/discord/1066956501299777596?logo=discord&logoColor=white&color=7289da)](https://discord.gg/nkqV9xBYWy)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/triggerdotdev/trigger.dev)
[![GitHub stars](https://img.shields.io/github/stars/triggerdotdev/trigger.dev?style=social)](https://github.com/triggerdotdev/trigger.dev)
</div>
## About Trigger.dev
Trigger.dev is an open source platform and SDK which allows you to create long-running background jobs. Write normal async code, deploy, and never hit a timeout.
Trigger.dev is the open-source platform for building AI workflows in TypeScript. Long-running tasks with retries, queues, observability, and elastic scaling.
### Key features:
## The platform designed for building AI agents
- JavaScript and TypeScript SDK
- No timeouts
- Retries (with exponential backoff)
- Queues and concurrency controls
- Schedules and crons
- Full Observability; logs, live trace views, advanced filtering
- React hooks to interact with the Trigger API from your React app
- Pipe LLM streams straight to your users through the Realtime API
- Trigger tasks and display the run status and metadata anywhere in your app
- Custom alerts, get notified by email, Slack or webhooks
- No infrastructure to manage
- Elastic (scaling)
- Works with your existing tech stack
Build [AI agents](https://trigger.dev/product/ai-agents) using all the frameworks, services and LLMs you're used to, deploy them to Trigger.dev and get durable, long-running tasks with retries, queues, observability, and elastic scaling out of the box.
## In your codebase
- **Long-running without timeouts**: Execute your tasks with absolutely no timeouts, unlike AWS Lambda, Vercel, and other serverless platforms.
- **Durability, retries & queues**: Build rock solid agents and AI applications using our durable tasks, retries, queues and idempotency.
- **True runtime freedom**: Customize your deployed tasks with system packages run browsers, Python scripts, FFmpeg and more.
- **Human-in-the-loop**: Programmatically pause your tasks until a human can approve, reject or give feedback.
- **Realtime apps & streaming**: Move your background jobs to the foreground by subscribing to runs or streaming AI responses to your app.
- **Observability & monitoring**: Each run has full tracing and logs. Configure error alerts to catch bugs fast.
## Key features:
- **[JavaScript and TypeScript SDK](https://trigger.dev/docs/tasks/overview)** - Build background tasks using familiar programming models
- **[Long-running tasks](https://trigger.dev/docs/runs/max-duration)** - Handle resource-heavy tasks without timeouts
- **[Durable cron schedules](https://trigger.dev/docs/tasks/scheduled#scheduled-tasks-cron)** - Create and attach recurring schedules of up to a year
- **[Trigger.dev Realtime](https://trigger.dev/docs/realtime/overview)** - Trigger, subscribe to, and get real-time updates for runs, with LLM streaming support
- **[Build extensions](https://trigger.dev/docs/config/extensions/overview#build-extensions)** - Hook directly into the build system and customize the build process. Run Python scripts, FFmpeg, browsers, and more.
- **[React hooks](https://trigger.dev/docs/frontend/react-hooks#react-hooks)** - Interact with the Trigger.dev API on your frontend using our React hooks package
- **[Batch triggering](https://trigger.dev/docs/triggering#tasks-batchtrigger)** - Use batchTrigger() to initiate multiple runs of a task with custom payloads and options
- **[Structured inputs / outputs](https://trigger.dev/docs/tasks/schemaTask#schematask)** - Define precise data schemas for your tasks with runtime payload validation
- **[Waits](https://trigger.dev/docs/wait)** - Add waits to your tasks to pause execution for a specified duration
- **[Preview branches](https://trigger.dev/docs/deployment/preview-branches)** - Create isolated environments for testing and development. Integrates with Vercel and git workflows
- **[Waitpoints](https://trigger.dev/docs/wait-for-token#wait-for-token)** - Add human-in-the-loop judgment at critical decision points without disrupting workflow
- **[Concurrency & queues](https://trigger.dev/docs/queue-concurrency#concurrency-and-queues)** - Set concurrency rules to manage how multiple tasks execute
- **[Multiple environments](https://trigger.dev/docs/how-it-works#dev-mode)** - Support for DEV, PREVIEW, STAGING, and PROD environments
- **[No infrastructure to manage](https://trigger.dev/docs/how-it-works#trigger-dev-architecture)** - Auto-scaling infrastructure that eliminates timeouts and server management
- **[Automatic retries](https://trigger.dev/docs/errors-retrying)** - If your task encounters an uncaught error, we automatically attempt to run it again
- **[Checkpointing](https://trigger.dev/docs/how-it-works#the-checkpoint-resume-system)** - Tasks are inherently durable, thanks to our checkpointing feature
- **[Versioning](https://trigger.dev/docs/versioning)** - Atomic versioning allows you to deploy new versions without affecting running tasks
- **[Machines](https://trigger.dev/docs/machines)** - Configure the number of vCPUs and GBs of RAM you want the task to use
- **[Observability & monitoring](https://trigger.dev/product/observability-and-monitoring)** - Monitor every aspect of your tasks' performance with comprehensive logging and visualization tools
- **[Logging & tracing](https://trigger.dev/docs/logging)** - Comprehensive logging and tracing for all your tasks
- **[Tags](https://trigger.dev/docs/tags#tags)** - Attach up to ten tags to each run, allowing you to filter via the dashboard, realtime, and the SDK
- **[Run metadata](https://trigger.dev/docs/runs/metadata#run-metadata)** - Attach metadata to runs which updates as the run progresses and is available to use in your frontend for live updates
- **[Bulk actions](https://trigger.dev/docs/bulk-actions)** - Perform actions on multiple runs simultaneously, including replaying and cancelling
- **[Real-time alerts](https://trigger.dev/docs/troubleshooting-alerts#alerts)** - Choose your preferred notification method for run failures and deployments
## Write tasks in your codebase
Create tasks where they belong: in your codebase. Version control, localhost, test and review like you're already used to.
```ts
import { task } from "@trigger.dev/sdk/v3";
import { task } from "@trigger.dev/sdk";
//1. You need to export each task
export const helloWorld = task({
@@ -58,13 +90,13 @@ Use our SDK to write tasks in your codebase. There's no infrastructure to manage
## Environments
We support `Development`, `Staging`, and `Production` environments, allowing you to test your tasks before deploying them to production.
We support `Development`, `Staging`, `Preview`, and `Production` environments, allowing you to test your tasks before deploying them to production.
## Full visibility of every job run
View every task in every run so you can tell exactly what happened. We provide a full trace view of every task run so you can see what happened at every step.
![Trace view image](https://imagedelivery.net/3TbraffuDZ4aEf8KWOmI_w/7c1b347f-004c-4482-38a7-3f6fa9c00d00/public)
![Trace view image](https://content.trigger.dev/trace-view.png)
# Getting started
@@ -73,14 +105,19 @@ The quickest way to get started is to create an account and project in our [web
### Useful links:
- [Quick start](https://trigger.dev/docs/quick-start) - get up and running in minutes
- [How it works](https://trigger.dev/docs/v3/how-it-works) - understand how Trigger.dev works under the hood
- [How it works](https://trigger.dev/docs/how-it-works) - understand how Trigger.dev works under the hood
- [Guides and examples](https://trigger.dev/docs/guides/introduction) - walk-through guides and code examples for popular frameworks and use cases
## Self-hosting
If you prefer to self-host Trigger.dev, you can follow our [self-hosting guide](https://trigger.dev/docs/v3/open-source-self-hosting#overview).
If you prefer to self-host Trigger.dev, you can follow our [self-hosting guides](https://trigger.dev/docs/self-hosting/overview):
We also have a dedicated self-hosting channel in our [Discord server](https://trigger.dev/discord) for support.
- [Docker self-hosting guide](https://trigger.dev/docs/self-hosting/docker) - use Docker Compose to spin up a Trigger.dev instance
- [Kubernetes self-hosting guide](https://trigger.dev/docs/self-hosting/kubernetes) - use our official Helm chart to deploy Trigger.dev to your Kubernetes cluster
## Support and community
We have a large active community in our official [Discord server](https://trigger.dev/discord) for support, including a dedicated channel for self-hosting.
## Development
+23
View File
@@ -1,5 +1,28 @@
## Guide on releasing a new version
### Automated release (v4+)
Releases are fully automated via CI:
1. PRs merge to `main` with changesets (for package changes) and/or `.server-changes/` files (for server-only changes).
2. The [changesets-pr.yml](./.github/workflows/changesets-pr.yml) workflow automatically creates/updates the `changeset-release/main` PR with version bumps and an enhanced summary of all changes. Consumed `.server-changes/` files are removed on the release branch (same approach changesets uses for `.changeset/` files — they're deleted on the branch, so merging the PR cleans them up).
3. When ready to release, merge the changeset release PR into `main`.
4. The [release.yml](./.github/workflows/release.yml) workflow automatically:
- Publishes all packages to npm
- Creates a single unified GitHub release (e.g., "trigger.dev v4.3.4")
- Tags and triggers Docker image builds
- After Docker images are pushed, updates the GitHub release with the exact GHCR tag link
### What engineers need to do
- **Package changes**: Add a changeset with `pnpm run changeset:add`
- **Server-only changes**: Add a `.server-changes/` file (see `.server-changes/README.md`)
- **Mixed PRs**: Just the changeset is enough
See `CHANGESETS.md` for full details on changesets and server changes.
### Legacy release (v3)
1. Merge in the changeset PR into main, making sure to cancel both the release and publish github actions from that merge.
2. Pull the changes locally into main
3. Run `pnpm i` which will update the pnpm lock file with the new versions
+121
View File
@@ -0,0 +1,121 @@
## Creating and applying migrations
We use prisma migrations to manage the database schema. Please follow the following steps when editing the `internal-packages/database/prisma/schema.prisma` file:
Edit the `schema.prisma` file to add or modify the schema.
Create a new migration file but don't apply it yet:
```bash
cd internal-packages/database
pnpm run db:migrate:dev:create --name "add_new_column_to_table"
```
The migration file will be created in the `prisma/migrations` directory, but it will have a bunch of edits to the schema that are not needed and will need to be removed before we can apply the migration. Here's an example of what the migration file might look like:
```sql
-- AlterEnum
ALTER TYPE "public"."TaskRunExecutionStatus" ADD VALUE 'DELAYED';
-- AlterTable
ALTER TABLE "public"."TaskRun" ADD COLUMN "debounce" JSONB;
-- AlterTable
ALTER TABLE "public"."_BackgroundWorkerToBackgroundWorkerFile" ADD CONSTRAINT "_BackgroundWorkerToBackgroundWorkerFile_AB_pkey" PRIMARY KEY ("A", "B");
-- DropIndex
DROP INDEX "public"."_BackgroundWorkerToBackgroundWorkerFile_AB_unique";
-- AlterTable
ALTER TABLE "public"."_BackgroundWorkerToTaskQueue" ADD CONSTRAINT "_BackgroundWorkerToTaskQueue_AB_pkey" PRIMARY KEY ("A", "B");
-- DropIndex
DROP INDEX "public"."_BackgroundWorkerToTaskQueue_AB_unique";
-- AlterTable
ALTER TABLE "public"."_TaskRunToTaskRunTag" ADD CONSTRAINT "_TaskRunToTaskRunTag_AB_pkey" PRIMARY KEY ("A", "B");
-- DropIndex
DROP INDEX "public"."_TaskRunToTaskRunTag_AB_unique";
-- AlterTable
ALTER TABLE "public"."_WaitpointRunConnections" ADD CONSTRAINT "_WaitpointRunConnections_AB_pkey" PRIMARY KEY ("A", "B");
-- DropIndex
DROP INDEX "public"."_WaitpointRunConnections_AB_unique";
-- AlterTable
ALTER TABLE "public"."_completedWaitpoints" ADD CONSTRAINT "_completedWaitpoints_AB_pkey" PRIMARY KEY ("A", "B");
-- DropIndex
DROP INDEX "public"."_completedWaitpoints_AB_unique";
-- CreateIndex
CREATE INDEX "SecretStore_key_idx" ON "public"."SecretStore"("key" text_pattern_ops);
-- CreateIndex
CREATE INDEX "TaskRun_runtimeEnvironmentId_id_idx" ON "public"."TaskRun"("runtimeEnvironmentId", "id" DESC);
-- CreateIndex
CREATE INDEX "TaskRun_runtimeEnvironmentId_createdAt_idx" ON "public"."TaskRun"("runtimeEnvironmentId", "createdAt" DESC);
```
All the following lines should be removed:
```sql
-- AlterTable
ALTER TABLE "public"."_BackgroundWorkerToBackgroundWorkerFile" ADD CONSTRAINT "_BackgroundWorkerToBackgroundWorkerFile_AB_pkey" PRIMARY KEY ("A", "B");
-- DropIndex
DROP INDEX "public"."_BackgroundWorkerToBackgroundWorkerFile_AB_unique";
-- AlterTable
ALTER TABLE "public"."_BackgroundWorkerToTaskQueue" ADD CONSTRAINT "_BackgroundWorkerToTaskQueue_AB_pkey" PRIMARY KEY ("A", "B");
-- DropIndex
DROP INDEX "public"."_BackgroundWorkerToTaskQueue_AB_unique";
-- AlterTable
ALTER TABLE "public"."_TaskRunToTaskRunTag" ADD CONSTRAINT "_TaskRunToTaskRunTag_AB_pkey" PRIMARY KEY ("A", "B");
-- DropIndex
DROP INDEX "public"."_TaskRunToTaskRunTag_AB_unique";
-- AlterTable
ALTER TABLE "public"."_WaitpointRunConnections" ADD CONSTRAINT "_WaitpointRunConnections_AB_pkey" PRIMARY KEY ("A", "B");
-- DropIndex
DROP INDEX "public"."_WaitpointRunConnections_AB_unique";
-- AlterTable
ALTER TABLE "public"."_completedWaitpoints" ADD CONSTRAINT "_completedWaitpoints_AB_pkey" PRIMARY KEY ("A", "B");
-- DropIndex
DROP INDEX "public"."_completedWaitpoints_AB_unique";
-- CreateIndex
CREATE INDEX "SecretStore_key_idx" ON "public"."SecretStore"("key" text_pattern_ops);
-- CreateIndex
CREATE INDEX "TaskRun_runtimeEnvironmentId_id_idx" ON "public"."TaskRun"("runtimeEnvironmentId", "id" DESC);
-- CreateIndex
CREATE INDEX "TaskRun_runtimeEnvironmentId_createdAt_idx" ON "public"."TaskRun"("runtimeEnvironmentId", "createdAt" DESC);
```
Leaving only this:
```sql
-- AlterEnum
ALTER TYPE "public"."TaskRunExecutionStatus" ADD VALUE 'DELAYED';
-- AlterTable
ALTER TABLE "public"."TaskRun" ADD COLUMN "debounce" JSONB;
```
After editing the migration file, apply the migration:
```bash
cd internal-packages/database
pnpm run db:migrate:deploy && pnpm run generate
```
+1 -1
View File
@@ -1,6 +1,6 @@
## Repo Overview
This is a pnpm 8.15.5 monorepo that uses turborepo @turbo.json. The following workspaces are relevant
This is a pnpm 10.33.2 monorepo that uses turborepo @turbo.json. The following workspaces are relevant
## Apps
View File
+1 -1
View File
@@ -35,7 +35,7 @@ COPY --from=pruner --chown=node:node /app/out/full/ .
COPY --from=dev-deps --chown=node:node /app/ .
COPY --chown=node:node turbo.json turbo.json
RUN pnpm run -r --filter coordinator build:bundle
RUN pnpm run -r --filter @trigger.dev/core bundle-vendor && pnpm run -r --filter coordinator build:bundle
FROM alpine AS cri-tools
+1 -1
View File
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es2018",
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true,
"resolveJsonModule": true,
+1 -1
View File
@@ -31,7 +31,7 @@ COPY --from=pruner --chown=node:node /app/out/full/ .
COPY --from=dev-deps --chown=node:node /app/ .
COPY --chown=node:node turbo.json turbo.json
RUN pnpm run -r --filter docker-provider build:bundle
RUN pnpm run -r --filter @trigger.dev/core bundle-vendor && pnpm run -r --filter docker-provider build:bundle
FROM base AS runner
+1 -1
View File
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es2018",
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
+1 -1
View File
@@ -31,7 +31,7 @@ COPY --from=pruner --chown=node:node /app/out/full/ .
COPY --from=dev-deps --chown=node:node /app/ .
COPY --chown=node:node turbo.json turbo.json
RUN pnpm run -r --filter kubernetes-provider build:bundle
RUN pnpm run -r --filter @trigger.dev/core bundle-vendor && pnpm run -r --filter kubernetes-provider build:bundle
FROM base AS runner
+1 -1
View File
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es2018",
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
+1 -2
View File
@@ -7,12 +7,11 @@ MANAGED_WORKER_SECRET=managed-secret
# Point this at the webapp in prod
TRIGGER_API_URL=http://localhost:3030
# Point this at the OTel collector in prod
# Point this at the webapp or an OTel collector in prod
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:3030/otel
# Use this on macOS
# OTEL_EXPORTER_OTLP_ENDPOINT=http://host.docker.internal:3030/otel
# Optional settings
DEBUG=1
ENFORCE_MACHINE_PRESETS=1
TRIGGER_DEQUEUE_INTERVAL_MS=1000
+20
View File
@@ -0,0 +1,20 @@
# Supervisor
Node.js app that manages task execution containers. Receives work from the platform, starts Docker/Kubernetes containers, monitors execution, and reports results.
## Key Directories
- `src/services/` - Core service logic
- `src/workloadManager/` - Container orchestration abstraction (Docker or Kubernetes)
- `src/workloadServer/` - HTTP server for workload communication (heartbeats, snapshots)
- `src/clients/` - Platform communication (webapp/coordinator)
- `src/env.ts` - Environment configuration
## Architecture
- **WorkloadManager**: Abstracts Docker vs Kubernetes execution
- **SupervisorSession**: Manages the dequeue loop with EWMA-based dynamic scaling
- **ResourceMonitor**: Tracks CPU/memory during execution
- **PodCleaner/FailedPodHandler**: Kubernetes-specific cleanup
Communicates with the platform via Socket.io and HTTP. Receives task assignments through the dequeue protocol from the webapp.
+4 -3
View File
@@ -5,7 +5,7 @@ WORKDIR /app
FROM node-22-alpine AS pruner
COPY --chown=node:node . .
RUN npx -q turbo@1.10.9 prune --scope=supervisor --docker
RUN npx -q turbo@2.5.4 prune --scope=supervisor --docker
FROM node-22-alpine AS base
@@ -16,9 +16,10 @@ COPY --from=pruner --chown=node:node /app/out/json/ .
COPY --from=pruner --chown=node:node /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
COPY --from=pruner --chown=node:node /app/out/pnpm-workspace.yaml ./pnpm-workspace.yaml
RUN corepack enable && corepack prepare --activate
RUN corepack enable && corepack prepare pnpm@10.33.2 --activate
FROM base AS deps-fetcher
RUN apk add --no-cache python3-dev py3-setuptools make g++ gcc linux-headers
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm fetch --frozen-lockfile
FROM deps-fetcher AS dev-deps
@@ -36,7 +37,7 @@ COPY --chown=node:node scripts/updateVersion.ts scripts/updateVersion.ts
RUN pnpm run generate && \
pnpm run --filter supervisor... build&& \
pnpm deploy --filter=supervisor --prod /prod/supervisor
pnpm deploy --legacy --filter=supervisor --prod /prod/supervisor
FROM base AS runner
+47 -9
View File
@@ -19,6 +19,8 @@ curl -sS \
-d "{\"name\": \"$wg_name\"}"
```
If the worker group is newly created, the response will include a `token` field. If the group already exists, no token is returned.
2. Create `.env` and set the worker token
```sh
@@ -34,7 +36,7 @@ TRIGGER_WORKER_TOKEN=tr_wgt_...
pnpm dev
```
4. Build CLI, then deploy a reference project
4. Build CLI, then deploy a test project
```sh
pnpm exec trigger deploy --self-hosted
@@ -43,16 +45,36 @@ pnpm exec trigger deploy --self-hosted
pnpm exec trigger deploy --self-hosted --network host
```
## Additional worker groups
## Worker group management
When adding more worker groups you might also want to make them the default for a specific project. This will allow you to test it without having to change the global default:
### Shared variables
```sh
api_url=http://localhost:3030
admin_pat=tr_pat_... # edit this
```
- These are used by all commands
### Create a worker group
```sh
wg_name=my-worker
# edit these
admin_pat=tr_pat_...
curl -sS \
-X POST \
"$api_url/admin/api/v1/workers" \
-H "Authorization: Bearer $admin_pat" \
-H "Content-Type: application/json" \
-d "{\"name\": \"$wg_name\"}"
```
- If the worker group already exists, no token will be returned
### Set a worker group as default for a project
```sh
wg_name=my-worker
project_id=clsw6q8wz...
curl -sS \
@@ -60,8 +82,24 @@ curl -sS \
"$api_url/admin/api/v1/workers" \
-H "Authorization: Bearer $admin_pat" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"$wg_name\",
\"makeDefaultForProjectId\": \"$project_id\"
}"
-d "{\"name\": \"$wg_name\", \"projectId\": \"$project_id\", \"makeDefaultForProject\": true}"
```
- If the worker group doesn't exist, yet it will be created
- If the worker group already exists, it will be attached to the project as default. No token will be returned.
### Remove the default worker group from a project
```sh
project_id=clsw6q8wz...
curl -sS \
-X POST \
"$api_url/admin/api/v1/workers" \
-H "Authorization: Bearer $admin_pat" \
-H "Content-Type: application/json" \
-d "{\"projectId\": \"$project_id\", \"removeDefaultFromProject\": true}"
```
- The project will then use the global default again
- When `removeDefaultFromProject: true` no other actions will be performed

Some files were not shown because too many files have changed in this diff Show More