Commit Graph

4755 Commits

Author SHA1 Message Date
Chris Arderne 2b2b047089 chore(webapp): scope imperative route refs (#4731)
## Summary

Scopes React Compiler diagnostics to route statements where refs
intentionally coordinate virtualized views, live reload state, transport
lifecycles, and deferred callbacks. Other compiler diagnostics remain
active in those routes.
2026-08-20 09:59:45 +01:00
Chris Arderne 4d040e13be chore(webapp): scope imperative component refs (#4730)
## Summary

Scopes React Compiler diagnostics to component and hook statements where
refs intentionally coordinate editors, animations, polling, deferred
callbacks, and other imperative integrations. Other compiler diagnostics
remain active in those components.
2026-08-20 09:59:45 +01:00
Chris Arderne a89ce5a709 refactor(webapp): replace render-time ref initialization (#4729)
## Summary

Replaces render-time ref initialization with lazy state for frozen form
defaults, the tooltip's virtual positioning element, and the side menu's
first-paint visuals. Editable alert fields now update immutable state
snapshots.
2026-08-20 09:59:44 +01:00
Chris Arderne 7ab437c8ad chore(webapp): scope route effect synchronization (#4728)
## Summary

Scopes React Compiler diagnostics for route effects that intentionally
synchronize loader data, navigation, submissions, polling, streams, and
transient UI state. Each suppression remains attached to the reported
synchronization call.
2026-08-20 09:59:44 +01:00
Chris Arderne 7673c46a02 chore(webapp): scope component effect synchronization (#4727)
## Summary

Scopes React Compiler diagnostics for component and hook effects that
intentionally synchronize with navigation, submissions, browser APIs,
streams, timers, or authoritative server values. Each suppression stays
on the reported synchronization call rather than disabling analysis for
the component.
2026-08-20 09:59:43 +01:00
Chris Arderne 101883c41c refactor(webapp): derive controlled UI state during render (#4726)
## Summary

Derives controlled tab, tag, and checkbox values directly during render
instead of copying them through effects. Modal drafts now reset from
their open event, and the route-backed alert dialog renders open
immediately without a mount-time state update.
2026-08-20 09:59:43 +01:00
Chris Arderne 00149675ac chore(webapp): scope intentional draft synchronization (#4725)
## Summary

Scopes state synchronization that intentionally resets editable drafts
from authoritative server values, deployment state, or programmatic
filter changes. These values cannot be derived during render without
removing user control between resets.
2026-08-20 09:59:42 +01:00
Chris Arderne f723e5a1b8 refactor(webapp): simplify manual memoization (#4722)
## Summary

Removes manual memoization where derived values are already rebuilt each
render, narrows the dashboard watch callback to a stable chat
identifier, and scopes two intentional memoization patterns that protect
local edits and serialized synchronization.
2026-08-20 09:59:42 +01:00
Chris Arderne cf96204c7f chore(webapp): scope memo dependency diagnostics (#4721)
## Summary

Makes stable dashboard history refs explicit memo inputs and scopes the
remaining compiler diagnostics to callbacks whose local handlers or
lifetime-stable values cannot be represented accurately in dependency
arrays.
2026-08-20 09:59:41 +01:00
Chris Arderne 7682a215db fix(webapp): stabilize time-sensitive UI renders (#4720)
## Summary

Captures chat-history age when the menu opens so rerenders cannot change
labels mid-view. The waitpoint deadline form also reuses one intentional
wall-clock snapshot for all calculations in a render.
2026-08-20 09:59:41 +01:00
Chris Arderne e394b5acf5 fix(webapp): timestamp live metric responses (#4719)
## Summary

Records when live metric responses arrive and uses that timestamp to
evaluate gauge freshness and waiting duration. Cached or failed
responses remain untrusted until revalidated, while rendered values stay
stable between polling updates.
2026-08-20 09:59:41 +01:00
Chris Arderne 34211e6649 fix(webapp): derive expiry status from loader time (#4718)
## Summary

Derives session and API key expiry states from a timestamp captured by
each route loader. Every status on a page now uses one consistent point
in time instead of changing according to when an individual component
rerenders.
2026-08-20 09:59:40 +01:00
Chris Arderne 11ea1f8ba9 fix(webapp): use stable chart bucket timestamps (#4717)
## Summary

Uses explicit bucket timestamps when rendering usage charts instead of
anchoring missing timestamps to the current render time. Tooltips now
remain stable across rerenders, and examples use a deterministic
timestamp.
2026-08-20 09:59:40 +01:00
Chris Arderne 7ea02716fc fix(webapp): avoid mutating render inputs (#4716)
## Summary

Keeps render inputs and shared regular expressions immutable. Grouped
selects now compute each section's shortcut offset directly from
preceding sections, which also makes numeric shortcuts follow the
displayed item order reliably.
2026-08-20 09:59:39 +01:00
Chris Arderne 176fb6daf4 fix(webapp): call hooks directly and unconditionally (#4715)
## Summary

Calls dashboard hooks directly instead of passing them as ordinary
callback values, and subscribes to optional Ariakit stores through an
unconditional hook. This keeps hook ordering stable while preserving the
existing behavior when a provider is absent.
2026-08-20 09:59:39 +01:00
Chris Arderne 6dfc54b75b chore(webapp): scope unsupported React Compiler diagnostics (#4713)
## Summary

Adds targeted lint suppressions for components built around libraries
that React Compiler intentionally declines to memoize, plus one
unsupported function-reference pattern. Each suppression is scoped to
the affected component so other compiler diagnostics remain actionable.
2026-08-20 09:59:39 +01:00
Chris Arderne 9dca03f682 chore: enforce exhaustive React hook dependencies (#4712)
## Summary

Enables exhaustive React Hook dependency checking and resolves the
existing violations across the dashboard and React hooks package.
Effects and callbacks now track current values without introducing
request, subscription, or render loops.

## Design

Dependencies are included directly when the hook lifecycle should follow
them. Timers, Remix fetchers, and realtime subscriptions use stable
callbacks or latest-value refs where restarting work would change
behavior.

Unnecessary memoization was removed where ordinary derivation is
clearer. Full lint and typechecks for the webapp and React hooks package
pass.
2026-08-20 09:59:38 +01:00
Chris Arderne 19908436b8 perf(ci): speed up webapp test execution (#4709)
## Summary

Speeds up webapp test jobs by balancing measured work across runners,
reducing repeated container setup, and ensuring test workers release
shutdown resources promptly. Unit tests run across 24 duration-aware
shards, while E2E tests run across two balanced shards.

## Design

`RunEngine` shutdown now closes processing resources before support
resources, continues cleanup if one close fails, and reuses one shutdown
promise for concurrent callers. Redis workers clear completed shutdown
deadlines so finished tests no longer wait on idle timers.

Container-heavy suites are split only where it improves parallelism, and
repeated replication and engine fixtures are consolidated where one
end-to-end case provides coverage. Timing weights are refreshed for all
affected files.

Dependency installation overlaps container pulls, and both workflows use
WarpBuild's Node setup action.
2026-08-20 07:08:22 +01:00
claude[bot] 447471843c fix(webapp): keep the branches list query string when archiving a branch (#4724)
<!-- ccr-slack-attribution -->
_Requested by **Iss** · [Slack
thread](https://triggerdotdev.slack.com/archives/C045W9WM3E1/p1787161814493949)_

**Before:** archiving a branch dropped the query string on the way back
to the branches list, so the list reset to page 1. Working down a long
list meant re-navigating to the page you were on after every archive.

**After:** you land back on the exact page you archived from, with
`page`, `search` and `showArchived` intact.

The archive action now redirects to the page the request came from
instead of rebuilding a bare branches path.

## How

The archive dialog already submits the page it was opened from as a
hidden `redirectPath` field (`${location.pathname}${location.search}`),
and the failure path already redirected to it — only the success path
ignored it and rebuilt the path with `branchesPath`/`branchesDevPath`,
which have no query string. Both paths now redirect to the submitted
path, run through the existing `sanitizeRedirectPath` helper to keep the
redirect same-origin (the same idiom used by
`resources.batches.$batchId.check-completion`).

##  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

Three files change:

- `apps/webapp/app/routes/resources.branches.archive.tsx` — the fix.
- `apps/webapp/test/archiveBranchRedirect.test.ts` — new test that
drives the archive action and asserts the redirect `Location`: the query
string survives on both success and failure, and an off-origin
`redirectPath` falls back to `/`. Reverting the fix makes two of the
three cases fail, so the test covers the regression.
- `.server-changes/archive-branch-keeps-list-page.md` — release-note
entry, since this is a user-facing server-only change.

Also ran `pnpm run typecheck` and `oxlint` for `apps/webapp` — both
clean.

---

## Changelog

Archiving a branch now returns you to the same page of the branches list
instead of resetting it to page 1.

---

## Screenshots

_None — no visual change._

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-19 16:45:47 -04:00
Oskar Otwinowski cde8919861 feat(webapp): show the external deployment id on deployments and runs (#4665)
Deployments page: an always-visible External ID column after Deployed
by, and an External ID row in the deployment inspector under Worker
type, both showing an en dash when a deploy carried no id. The Vercel
Linked column now renders before Git, still only when a Vercel
integration is connected. Also corrects the blank-row colSpan, which was
already off by one before this column existed.

Run inspector: an External deployment ID row between Version and SDK
version, read from the run annotations, so an operator can see which id
a run was pinned to - including a run that expired before its deployment
ever arrived, where the locked version is empty but the id is the whole
story. Buffered runs read the id from the same annotations rather than
reporting none.

Long ids are head-truncated with the full value behind the copy button:
a commit SHA is meaningful in its prefix, and the inspector panel can be
narrowed to 250px, where an unbroken 40-character SHA would otherwise
scroll the properties list sideways and push the copy button off-panel
(TRI-12923, TRI-13000).
2026-08-19 17:43:54 +02:00
Oskar Otwinowski 8b0385c429 feat(run-engine): trigger tasks pinned to an external deployment id (#4664)
The SDK discovers an external deployment id at runtime (explicit
TRIGGER_EXTERNAL_DEPLOYMENT_ID always; platform commit-SHA variables and
generic fallbacks when TRIGGER_AUTOMATIC_SKEW_VERSION_PROTECTION=1) and
sends it alongside lockToVersion; the server resolves precedence
(version > external id > current). An id held by a deployed deployment
pins the run to that worker; an in-flight or unknown id parks the run in
PENDING_VERSION with the id in TaskRun.annotations, wakes it pinned when
a deployment carrying the id finalizes (ClickHouse candidates, Postgres
authoritative), and expires it after a deadline that re-checks Postgres
before acting. Parking outranks delaying and preserves delayUntil. The
id is projected to ClickHouse task_runs_v2.external_deployment_id during
replication. Redis cache for id-to-worker resolution, guarded
version-aware writes.

Ids are not unique. Several deployments can hold one id - a --force
rebuild is the ordinary way to get there - so resolution always picks
the highest version among the candidates, never the newest by timestamp.
The rule is applied identically on both paths that can bind a run to a
worker: resolveExternalDeployment at trigger time, and
PendingVersionSystem when a landing deployment wakes a parked run.
Version comparison is numeric on the counter half, so 20260807.10
outranks 20260807.9.

A run whose id never lands expires at the deadline with
EXTERNAL_DEPLOYMENT_NOT_FOUND and an error naming the id it waited for,
which is what a failed build or a typo looks like from the caller.
Default deadline is one hour (EXTERNAL_DEPLOYMENT_PARK_DEADLINE_MS).

Debounce registration happens in both the parked and the delayed branch
through one helper, so a debounced run that parks still binds its
debounce key; without it every later trigger for the same key created
another parked run, and all of them executed when the deployment landed.
The two DELAYED-only status checks in DebounceSystem also accept
PENDING_VERSION, without which the lock-contention fallback would
rethrow a 5xx the SDK retries and amplifies, and the fast path would
push every trigger on a parked key through the redlock.

Resolution is skipped in development. A dev environment cannot hold a
WorkerDeployment - trigger dev registers a BackgroundWorker with nothing
behind it, and deploy --env refuses dev - so an external deployment id
there could only ever park, and the parked run then expired against the
dev TTL while a connected dev worker sat idle. The id is still annotated
so the dashboard shows what the app sent (TRI-13000).
2026-08-19 17:43:53 +02:00
Oskar Otwinowski 6bfce6387d feat(deploy): --external-id and --force for deploy idempotency (#4663)
A deploy can carry an opaque external id (commit SHA, CI run id, release
tag). Repeating an id that already deployed returns the existing version
as a no-op instead of rebuilding; an id with a build in flight is
rejected with 409 naming that version; a failed id rebuilds freely.
--force is non-destructive to deployments that already succeeded - both
persist and the higher version wins - but cancels a build still in
flight, so one id never has two live builds racing to define it.
Cancelling writes a terminal status and appends a finalized event, which
aborts a build the platform drives; a build it does not drive keeps
running but can never land, and the CLI says so. Ids are deliberately
not unique - reuse is resolved in application code by highest version,
never timestamps. The no-op path mints no build credentials and no event
stream (TRI-12923).

What that means for callers: a --force rebuild leaves two deployments
holding one id, and runs triggered with it go to the higher version once
the rebuild lands, so the takeover needs no separate promotion. Until a
successful build exists for an id, runs triggered with it park and then
expire rather than falling back to current - a failed build is therefore
visible to the caller as expired runs, not as runs on the wrong release.
2026-08-19 17:43:51 +02:00
Chris Arderne 23c5619dd1 fix(webapp): enforce keyboard interaction safeguards (#4702)
## Summary

Enable keyboard-event and static-element interaction safeguards across
the dashboard.

Earlier stack changes move actionable behavior to native controls. This
final enforcement keeps narrowly documented exceptions for focus
forwarding, scoped Escape handling, CodeMirror focus, and pointer-driven
table column resizing.

`jsx-a11y/no-autofocus` remains disabled.

Base: [#4701](https://github.com/triggerdotdev/trigger.dev/pull/4701)
2026-08-19 16:35:47 +01:00
Chris Arderne 5e50d2f80d fix(webapp): align tree mouse and keyboard interactions (#4701)
## Summary

Move tree selection onto semantic tree items and use native expansion
buttons.

Dashboard and story tree rows now share mouse and keyboard selection
through `getNodeProps`. Expand and collapse affordances are named
buttons instead of clickable layout elements.

Base: [#4700](https://github.com/triggerdotdev/trigger.dev/pull/4700)
2026-08-19 16:35:47 +01:00
Chris Arderne 5ae24710e4 fix(webapp): use native selectable row controls (#4700)
## Summary

Use native controls for sortable columns and selectable prompt versions.

Table headers keep filter actions separate from sort buttons, prompt
version rows expose pressed state, and a redundant deployment click
interceptor is removed.

Base: [#4699](https://github.com/triggerdotdev/trigger.dev/pull/4699)
2026-08-19 16:35:46 +01:00
Chris Arderne 3d650248fb fix(webapp): use native time filter mode controls (#4699)
## Summary

Make time-filter mode selection keyboard accessible.

Duration and exact-range modes now use native pressed buttons. Nested
date, duration, and quick-select controls no longer depend on click
propagation blockers.

Base: [#4698](https://github.com/triggerdotdev/trigger.dev/pull/4698)
2026-08-19 16:35:46 +01:00
Chris Arderne 73c8a4d975 fix(webapp): use native controls for inline actions (#4698)
## Summary

Replace mouse-only dashboard actions with native buttons.

Copy, remove, and stop-generation controls now expose keyboard focus and
accessible names. Hover-revealed actions remain mounted so keyboard
users can discover them, and a decorative clipboard icon no longer
captures clicks.

Base: [#4697](https://github.com/triggerdotdev/trigger.dev/pull/4697)
2026-08-19 16:35:45 +01:00
Chris Arderne 3d156dfd75 fix(webapp): use native checkbox label semantics (#4697)
## Summary

Use native label and checkbox behavior for `CheckboxWithLabel` and
enforce `jsx-a11y/no-noninteractive-element-interactions`.

The component no longer simulates checkbox activation with click
handlers on non-interactive wrappers. Native change events now drive the
controlled checked state.

Base: [#4696](https://github.com/triggerdotdev/trigger.dev/pull/4696)
2026-08-19 16:35:45 +01:00
Chris Arderne 646141199e fix(webapp): enforce accessible control names (#4696)
## Summary

Require accessible names for dashboard controls.

Filter menu action items and chart color controls now expose explicit
names. The chart legend action uses a native button, while lint depth
and spacer-cell configuration match the rendered control structure.

Base: [#4695](https://github.com/triggerdotdev/trigger.dev/pull/4695)
2026-08-19 16:35:44 +01:00
Chris Arderne 3a091eb764 fix(webapp): enforce associated form labels (#4695)
## Summary

Finish associating dashboard form labels with their controls and enforce
`jsx-a11y/label-has-associated-control`.

Repeated data store dialogs use unique generated IDs, story controls and
notification filters have explicit associations, and display-only status
text no longer uses label elements.

Base: [#4694](https://github.com/triggerdotdev/trigger.dev/pull/4694)
2026-08-19 16:35:44 +01:00
Chris Arderne 3ffd123d27 fix(webapp): associate model administration labels (#4694)
## Summary

Associate internal model administration labels with their form controls.

The model editor, creator, and tester now use explicit `htmlFor` and
`id` pairs. Section titles that do not label controls now use headings
instead of label elements.

Base: [#4693](https://github.com/triggerdotdev/trigger.dev/pull/4693)
2026-08-19 16:35:43 +01:00
Chris Arderne 4592fdf4d6 fix(webapp): enforce accessible image and role semantics (#4693)
## Summary

Enable foundational JSX accessibility checks for image text alternatives
and valid ARIA roles.

The avatar color picker now has an explicit accessible name and
decorative image alternative. Dashboard chat styling props no longer
reuse the reserved DOM `role` name.

Base: [#4692](https://github.com/triggerdotdev/trigger.dev/pull/4692)
2026-08-19 16:35:43 +01:00
Chris Arderne dda9504bdd fix(webapp): require explicit native button types (#4692)
## Summary

Add explicit types to native dashboard buttons and enforce
`react/button-has-type`.

This prevents action buttons from accidentally submitting a surrounding
form. Shared button primitives retain their caller-selected submit and
reset semantics with documented lint exceptions.

Base: [#4691](https://github.com/triggerdotdev/trigger.dev/pull/4691)
2026-08-19 16:35:42 +01:00
Chris Arderne a7a1e74fcb refactor(webapp): remove redundant React fragments (#4691)
## Summary

Remove redundant React fragments from the dashboard and enforce
`react/jsx-no-useless-fragment`.

The cleanup returns existing nodes, arrays, and empty states directly
without adding wrapper elements.

Base: [#4689](https://github.com/triggerdotdev/trigger.dev/pull/4689)
2026-08-19 16:35:42 +01:00
Chris Arderne a2cc315f40 perf(webapp): stabilize nested component identities (#4689)
## Summary

Keep component and renderer identities stable across dashboard renders.

Inline icon components, chart renderers, table cells, and select render
callbacks now use module-level implementations. Oxlint enforces the
pattern across the dashboard.

Base: [#4688](https://github.com/triggerdotdev/trigger.dev/pull/4688)
2026-08-19 16:35:41 +01:00
Chris Arderne 108f43ee9b fix(webapp,react-hooks): enforce stable hook ordering (#4688)
## Summary

Enforce stable React hook ordering in the dashboard and React hooks
package.

Conditional hook calls now keep a consistent order, and overloaded
realtime stream arguments are resolved before entering the shared hook
implementation.

Base: `main`
2026-08-19 16:35:41 +01:00
Eric Allam 32e647e020 perf(webapp): resolve schedule list run times per expression, not per row (#4703)
## Summary

Listing schedules could block the event loop for seconds. A page of 100
timezone-aware schedules spent over two seconds on cron arithmetic
alone, after the database work was already done, which stalls every
other request on that process. The same page now resolves in tens of
milliseconds.

## Root cause and fix

`cron-parser` walks the calendar unit by unit, and under a named
timezone every step goes through luxon. Parsing an expression is cheap
(single-digit microseconds); *stepping* it is not, ranging from a couple
of hundred microseconds for a common expression to several milliseconds
for a sparse one like `0 0 29 2 *`. The presenter did three independent
walks per row, one backwards for "last run" and two forwards (re-parsing
each time) for the next run and the occurrence after it. At 100 rows
that is 300 calendar walks in one uninterrupted tick.

Run times now resolve for the whole page in one pass, in a new
`resolveScheduleTimings` that takes plain values rather than Prisma rows
so it can be tested and benchmarked on its own.

- **Nominal times are cached per `(cron, timezone)`** against a single
`now` pinned for the batch, so cost scales with the number of distinct
expressions instead of the number of rows. Rows in one response also
stop disagreeing about the current time.
- **The backwards walk is opt-in.** It is the most expensive of the
three and only the dashboard renders the column; the public API never
returned it at all.
- **Windowless schedules take one step instead of two.** The second step
only measures the interval to the following occurrence, and that
interval reaches the result solely through `min(intervalMs,
max(MINIMUM_SCHEDULE_RANGE_MS, windowMs))`. With no window `windowMs` is
0, and `CronPattern` rejects expressions with a seconds field, so
occurrences are always at least `MINIMUM_SCHEDULE_RANGE_MS` apart and
that `min` can never bind. It is also the costlier step, since it walks
a whole period rather than the remainder of the current one.
- **`nextScheduledTimestamps` steps one parsed expression** instead of
re-parsing per step, which also helps the single-schedule callers.

Behaviour is unchanged, error semantics included: a malformed expression
still throws for the next run and still degrades to an undefined last
run.

## Verification

Measured inside a real request against a live environment, 100
schedules: sparse expressions went from 2250-2652 ms to 23-30 ms, and
five distinct timezone expressions from 463-500 ms to 9.7-10.6 ms.

The new suite checks the optimized code against an inline copy of the
previous implementation across eleven cron and timezone combinations
plus five DST transitions, so the rewrite is verified as
behaviour-preserving rather than just faster. Separate tests pin the
invariant the single-step path depends on, so if sub-minute crons are
ever allowed they fail loudly instead of the timings quietly going
wrong.

Worth knowing for later: `cron-parser` v5 is a much faster rewrite on
exactly this workload (`prev()` under a timezone drops from roughly 2700
to 60 microseconds), but it is a breaking API change across several call
sites including the schedule engine, so it belongs on its own. The
differential test added here is the tool to de-risk it.
2026-08-19 14:01:15 +01:00
Chris Arderne 4dabfca1d5 feat(webapp,cli,core): list production project runtime updates (#4659) 2026-08-19 13:44:55 +01:00
Chris Arderne 97461c08af refactor(webapp): remove redundant React fragments (#4683)
## Summary

Remove redundant React fragments from dashboard components, leaving
their rendered output unchanged while simplifying component trees.

Base: [#4682](https://github.com/triggerdotdev/trigger.dev/pull/4682)
2026-08-19 08:29:01 +01:00
Chris Arderne 219bc09d5f perf(webapp): stabilize chart loading line renderer (#4682)
## Summary

Keep the chart loading line renderer stable across parent renders so its
animated SVG paths retain their component identity.

Base: [#4681](https://github.com/triggerdotdev/trigger.dev/pull/4681)
2026-08-19 08:29:01 +01:00
Chris Arderne 1aeb356b9e fix(webapp): preserve React hook order (#4681)
## Summary

Call dashboard hooks unconditionally so components keep a stable hook
order when their props change.

Base: [#4680](https://github.com/triggerdotdev/trigger.dev/pull/4680)
2026-08-19 08:29:00 +01:00
Chris Arderne e0d96c3991 perf(webapp): memoize shared context values (#4678)
## Summary

Memoize shared context values so provider renders do not unnecessarily
rerender every consumer. Oxlint now enforces this pattern for the rest
of the dashboard.

Base: [#4677](https://github.com/triggerdotdev/trigger.dev/pull/4677)
2026-08-19 08:28:59 +01:00
Chris Arderne f4320937c5 chore: prefer direct iteration and function callback types (#4677)
## Summary

Enable lint rules that prefer direct iteration and concise function
callback types.

The existing code now uses direct iteration where no index is needed,
and callback contracts use function types consistently.

Base: [#4675](https://github.com/triggerdotdev/trigger.dev/pull/4675)
2026-08-19 08:28:58 +01:00
Chris Arderne b2afff252c chore: enable JSX cleanup rules (#4674)
## Summary

Enable JSX cleanup rules for shorthand fragments and self-closing
components.

The existing JSX is automatically simplified, and future components will
follow the same concise form.

Base: [#4673](https://github.com/triggerdotdev/trigger.dev/pull/4673)
2026-08-19 08:28:57 +01:00
Chris Arderne 0f725cf2ba chore: enable lint cleanup rules (#4673)
## Summary

Enable small cleanup rules for redundant boolean expressions, object
ownership checks, assignments, and object construction.

The existing call sites now use the simpler equivalent forms, keeping
future code consistent without changing behavior.

Base: [#4672](https://github.com/triggerdotdev/trigger.dev/pull/4672)
2026-08-19 08:28:57 +01:00
Chris Arderne fe1d5f6961 chore: enable additional correctness lint rules (#4672)
## Summary

Enable additional lint rules that catch unsafe optional-chain
assertions, inherited-property iteration, anonymous symbols, and unsafe
external links.

The existing violations now use explicit values and own-property checks,
so the rules can prevent those patterns from returning.
2026-08-19 08:28:56 +01:00
nicktrn cffaa05517 feat(supervisor): optional priority class for run pods (#4671)
Adds an optional priority class for run pods.

```
KUBERNETES_RUN_POD_PRIORITY_CLASS_NAME
```

When set, the value is applied as `priorityClassName` on the run pod
spec. When unset, pods are created exactly as before.

Off by default, and inert unless set. It sits beside the existing
`KUBERNETES_SCHEDULER_NAME` option and follows the same conditional
shape:

```ts
...(env.KUBERNETES_RUN_POD_PRIORITY_CLASS_NAME
  ? { priorityClassName: env.KUBERNETES_RUN_POD_PRIORITY_CLASS_NAME }
  : {}),
```

## Verification

`typecheck --filter supervisor`, `format` and `lint` clean. No changeset
or `.server-changes/` note: off by default, no user-visible behaviour
change.
2026-08-18 19:34:40 +01:00
Chris Arderne 12ec4667cb feat(webapp): enable development branches for all organizations (#4670) 2026-08-18 19:30:21 +01:00
claude[bot] d7056a9c67 chore(webapp): reword the no-billing-limit banner copy (#4656)
<!-- ccr-slack-attribution -->
_Requested by **Matt Aitken** · [Slack
thread](https://triggerdotdev.slack.com/archives/C0BKB98B84W/p1787045331358929)_

Copy-only reword of the banner shown to org admins who have not set a
billing limit yet.

**Before** — the banner read "Protect your organization from unexpected
usage spikes." with a button labelled "Configure billing limit".

**After** — it reads "Add a billing limit to your account to prevent
overspending" with a button labelled "Billing limit settings".

The new wording names the action up front and matches the destination it
sends you to, so the banner reads as a settings link rather than a
one-off setup step.

##  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

Formatting and linting pass (`oxfmt --check`, `oxlint`). No tests or
snapshots assert this copy. The change is two string literals in one
component, with no behaviour attached.

---

## Changelog

Reworded the billing-limit banner for organizations without a limit
configured, and relabelled its button to "Billing limit settings".

---

## How

Both strings live in `NoLimitConfiguredBanner` in
`apps/webapp/app/components/billing/OrgBanner.tsx`: the heading is the
`canManageBillingLimits` branch of the banner's children, and the label
is the `<span>` inside the `LinkButton`. Only those two literals
changed. The button still points at `v3BillingLimitsPath(organization)`
(`/orgs/{slug}/settings/billing-limits`), so routing, permissions and
the non-admin variant of the message are untouched.

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-18 18:50:32 +01:00
nicktrn e91fb746f7 feat(supervisor): configurable security context for run pods
Adds KUBERNETES_RUNNER_SECURITY_CONTEXT (off | baseline | restricted), selecting how constrained the run container is.

baseline drops the capability bounding set and blocks privilege escalation. restricted additionally pins the container to a non-root uid, chosen by runtime so bun images get their own.

Default is off, so this is inert on merge.
2026-08-18 18:40:18 +01:00