Skip to content

feat(webapp): add region selector to test and replay task#3082

Merged
nicktrn merged 3 commits intomainfrom
feat/region-selector-test-replay
Feb 18, 2026
Merged

feat(webapp): add region selector to test and replay task#3082
nicktrn merged 3 commits intomainfrom
feat/region-selector-test-replay

Conversation

@nicktrn
Copy link
Collaborator

@nicktrn nicktrn commented Feb 17, 2026

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

Allow users to select which region to run a task in when testing or
replaying from the webapp dashboard. Previously this was only possible
via the SDK's trigger() options. The region selector appears in the
options panel alongside machine preset, and only shows when multiple
regions are available to the project.

Closes #3016
@changeset-bot
Copy link

changeset-bot bot commented Feb 17, 2026

⚠️ No Changeset found

Latest commit: c259bc1

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

This PR includes no changesets

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

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

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 17, 2026

Walkthrough

Region selection was added across replay and task submission flows. A new optional region field was introduced in RunOptionsData. Regions are fetched via RegionsPresenter and included in loaders; UI components (ReplayRunDialog, StandardTaskForm, ScheduledTaskForm) now render a region selector when multiple regions exist and accept regions in props. Replay and task services now accept/forward a region override when invoking runs. Loader/action payloads and response shapes were extended to include region/regions, and Prisma selects were expanded to expose workerQueue and slugs where needed.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is minimal and missing required sections from the repository template (Testing, Changelog, Screenshots). Add Testing section describing the test steps, expand Changelog section, and include relevant screenshots showing the region selector UI.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a region selector to test and replay task functionality in the webapp.
Linked Issues check ✅ Passed All code changes directly address issue #3016: region selector is added to Test task page and Replay run dialog, allowing users to override region from the dashboard.
Out of Scope Changes check ✅ Passed All changes are focused on implementing region selection for testing and replaying tasks; no unrelated modifications were introduced.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/region-selector-test-replay

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

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx (2)

1183-1215: ScheduledTaskForm region Select has two inconsistencies with StandardTaskForm.

  1. Missing isDev guard on defaultValue: StandardTaskForm (Line 624) passes defaultValue={isDev ? undefined : defaultRegion?.name}, preventing the disabled Select from showing a pre-selected region in dev. ScheduledTaskForm (Line 1193) uses defaultValue={defaultRegion?.name} unconditionally, so in dev the disabled field shows the default region as selected rather than the "–" placeholder.

  2. Missing placeholder prop: StandardTaskForm passes placeholder={isDev ? "–" : undefined} to show "–" in dev. ScheduledTaskForm omits this, so the field falls back to the Select's own empty state in dev.

🔧 Proposed fix for consistency with StandardTaskForm
  <Select
    {...conform.select(region)}
    variant="tertiary/small"
+   placeholder={isDev ? "–" : undefined}
    dropdownIcon
    items={regionItems}
-   defaultValue={defaultRegion?.name}
+   defaultValue={isDev ? undefined : defaultRegion?.name}
    value={regionValue}
    setValue={(e) => {
      if (Array.isArray(e)) return;
      setRegionValue(e);
    }}
    disabled={isDev}
  >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/webapp/app/routes/_app.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
around lines 1183 - 1215, ScheduledTaskForm's region Select is inconsistent with
StandardTaskForm: update the Select in ScheduledTaskForm (the Select component
inside the region InputGroup) to use the same isDev guards as StandardTaskForm
by changing defaultValue to defaultValue={isDev ? undefined :
defaultRegion?.name} and add placeholder={isDev ? "–" : undefined}; keep the
existing value/setValue/disabled logic intact so the disabled dev state shows
the "–" placeholder and no pre-selected region.

828-844: CreateTemplateModal omits region from template data, unlike other run options.

machine, queue, concurrencyKey, ttl, maxAttempts, maxDuration, and tags are all persisted to templates via rawTestTaskFormData. region is excluded, so selecting a region before saving a template loses that setting — and onTemplateSelected doesn't call setRegionValue. If this is intentional (treating region as an infra choice rather than task config), a comment would help clarify intent; otherwise, region should be added alongside machine.

♻️ Proposed addition to persist region in templates (if desired)

In the CreateTemplateModal props type:

  rawTestTaskFormData: {
    ...
    machine?: string;
+   region?: string;
    externalId?: string;
    ...
  };

In the StandardTaskForm call site:

  rawTestTaskFormData={{
    ...
    machine: machineValue,
+   region: regionValue,
  }}

And in onTemplateSelected (both forms):

  setMachineValue(template.machinePreset ?? undefined);
+ setRegionValue(template.region ?? undefined);
  setTagsValue(template.tags ?? []);

Also applies to: 1391-1411

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/webapp/app/routes/_app.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
around lines 828 - 844, CreateTemplateModal currently omits the selected region
from the saved template data which causes region state to be lost when a
template is applied; update the rawTestTaskFormData passed to
CreateTemplateModal to include region: regionValue (alongside machine, queue,
concurrencyKey, ttlSeconds, maxAttempts, maxDurationSeconds, tags), extend the
CreateTemplateModal/CreateTemplateModal props type to accept region, and update
onTemplateSelected handlers (used by StandardTaskForm and any other forms) to
call setRegionValue(template.region) when a template with a region is chosen (or
add a clear comment in CreateTemplateModal/StandardTaskForm explaining that
region is intentionally excluded if that is desired behavior).
apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx (1)

361-389: Consider renaming disableVersionSelection to a more general isDevEnvironment flag.

disableVersionSelection is used as the disabled condition for the region selector (Line 373) and its placeholder/hint logic (Line 382), but the prop name only signals version-related behavior. As region selection (and potentially other controls) get disabled in the same context, a shared isDevEnvironment (or similar) flag passed down would be more self-documenting.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx` around lines 361 -
389, Rename the misleading replayData.disableVersionSelection flag to a more
general name like replayData.isDevEnvironment (or similar) and update all
usages: change the prop and checks in ReplayRunDialog where
disableVersionSelection is used (the Select disabled prop, placeholder logic,
and Hint conditional rendering that reference
replayData.disableVersionSelection), and also update any upstream
producers/consumers of replayData to populate the new flag name so type
definitions and callers remain consistent; ensure identifiers such as Select,
region, SelectItem, Hint, and FormError continue to reference the new flag and
run the app/tests to verify no remaining references to disableVersionSelection.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e0b54b and cfd8490.

📒 Files selected for processing (6)
  • apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
  • apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts
  • apps/webapp/app/v3/services/replayTaskRun.server.ts
  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/v3/testTask.ts
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}

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

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

**/*.{ts,tsx}: Always import tasks from @trigger.dev/sdk, never use @trigger.dev/sdk/v3 or deprecated client.defineJob pattern
Every Trigger.dev task must be exported and have a unique id property with no timeouts in the run function

Files:

  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/v3/services/replayTaskRun.server.ts
  • apps/webapp/app/v3/testTask.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
  • apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
  • apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}

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

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/v3/services/replayTaskRun.server.ts
  • apps/webapp/app/v3/testTask.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
  • apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
  • apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts
**/*.{ts,tsx,js,jsx}

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

Use function declarations instead of default exports

Import from @trigger.dev/core using subpaths only, never import from root

Files:

  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/v3/services/replayTaskRun.server.ts
  • apps/webapp/app/v3/testTask.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
  • apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
  • apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/v3/services/replayTaskRun.server.ts
  • apps/webapp/app/v3/testTask.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
  • apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
  • apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Access environment variables via env export from apps/webapp/app/env.server.ts, never use process.env directly

Files:

  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/v3/services/replayTaskRun.server.ts
  • apps/webapp/app/v3/testTask.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
  • apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
  • apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts
apps/webapp/app/v3/services/**/*.server.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Organize services in the webapp following the pattern app/v3/services/*/*.server.ts

Files:

  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/v3/services/replayTaskRun.server.ts
**/*.ts

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

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

Files:

  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/v3/services/replayTaskRun.server.ts
  • apps/webapp/app/v3/testTask.ts
  • apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/v3/services/replayTaskRun.server.ts
  • apps/webapp/app/v3/testTask.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
  • apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
  • apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts
🧠 Learnings (21)
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schedules.task()` for scheduled/cron tasks instead of regular `task()`

Applied to files:

  • apps/webapp/app/v3/services/testTask.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Export tasks with unique IDs within the project to enable proper task discovery and execution

Applied to files:

  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Attach metadata to task runs using the metadata option when triggering, and access/update it inside runs using metadata functions

Applied to files:

  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/v3/services/replayTaskRun.server.ts
  • apps/webapp/app/v3/testTask.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties

Applied to files:

  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/v3/testTask.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Specify task locations in trigger.config.ts using the `dirs` array, with automatic exclusion of .test and .spec files

Applied to files:

  • apps/webapp/app/v3/services/testTask.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schemaTask()` from `trigger.dev/sdk/v3` with Zod schema for payload validation

Applied to files:

  • apps/webapp/app/v3/services/testTask.server.ts
  • apps/webapp/app/v3/testTask.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `tasks.trigger()` with type-only imports to trigger tasks from backend code without importing the task implementation

Applied to files:

  • apps/webapp/app/v3/services/testTask.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Configure OpenTelemetry instrumentations and exporters in trigger.config.ts for enhanced logging

Applied to files:

  • apps/webapp/app/v3/services/testTask.server.ts
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to **/*.{ts,tsx} : Always import tasks from `trigger.dev/sdk`, never use `trigger.dev/sdk/v3` or deprecated `client.defineJob` pattern

Applied to files:

  • apps/webapp/app/v3/services/testTask.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Use build extensions in trigger.config.ts (additionalFiles, additionalPackages, aptGet, prismaExtension, etc.) to customize the build

Applied to files:

  • apps/webapp/app/v3/services/testTask.server.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to {packages/core,apps/webapp}/**/*.{ts,tsx} : Use zod for validation in packages/core and apps/webapp

Applied to files:

  • apps/webapp/app/v3/testTask.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Specify machine resources using the `machine` property with preset options like 'large-1x'

Applied to files:

  • apps/webapp/app/v3/testTask.ts
  • apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts
📚 Learning: 2025-01-13T18:31:48.160Z
Learnt from: nicktrn
Repo: triggerdotdev/trigger.dev PR: 1608
File: apps/webapp/app/v3/services/triggerTask.server.ts:418-418
Timestamp: 2025-01-13T18:31:48.160Z
Learning: The `MachinePresetName` schema is used to validate machine preset values in the trigger.dev codebase, ensuring type safety and validation of machine preset options.

Applied to files:

  • apps/webapp/app/v3/testTask.ts
📚 Learning: 2026-02-11T16:50:14.167Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3019
File: apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboards.$dashboardId.widgets.tsx:126-131
Timestamp: 2026-02-11T16:50:14.167Z
Learning: In apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboards.$dashboardId.widgets.tsx, MetricsDashboard entities are intentionally scoped to the organization level, not the project level. The dashboard lookup should filter by organizationId only (not projectId), allowing dashboards to be accessed across projects within the same organization. The optional projectId field on MetricsDashboard serves other purposes and should not be used as an authorization constraint.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2025-12-08T15:19:56.823Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.823Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2026-02-03T18:27:40.429Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx:553-555
Timestamp: 2026-02-03T18:27:40.429Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx, the menu buttons (e.g., Edit with PencilSquareIcon) in the TableCellMenu are intentionally icon-only with no text labels as a compact UI pattern. This is a deliberate design choice for this route; preserve the icon-only behavior for consistency in this file.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/app/v3/presenters/**/*.server.{ts,tsx} : Organize presenters in the webapp following the pattern `app/v3/presenters/*/*.server.ts` to move complex loader code into classes

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2026-02-04T16:34:48.876Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/routes/vercel.connect.tsx:13-27
Timestamp: 2026-02-04T16:34:48.876Z
Learning: In apps/webapp/app/routes/vercel.connect.tsx, configurationId may be absent for "dashboard" flows but must be present for "marketplace" flows. Enforce this with a Zod superRefine and pass installationId to repository methods only when configurationId is defined (omit the field otherwise).

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2026-02-11T16:37:32.429Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3019
File: apps/webapp/app/components/primitives/charts/Card.tsx:26-30
Timestamp: 2026-02-11T16:37:32.429Z
Learning: In projects using react-grid-layout, avoid relying on drag-handle class to imply draggability. Ensure drag-handle elements only affect dragging when the parent grid item is configured draggable in the layout; conditionally apply cursor styles based on the draggable prop. This improves correctness and accessibility.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
  • apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
📚 Learning: 2025-07-12T18:06:04.133Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2264
File: apps/webapp/app/services/runsRepository.server.ts:172-174
Timestamp: 2025-07-12T18:06:04.133Z
Learning: In apps/webapp/app/services/runsRepository.server.ts, the in-memory status filtering after fetching runs from Prisma is intentionally used as a workaround for ClickHouse data delays. This approach is acceptable because the result set is limited to a maximum of 100 runs due to pagination, making the performance impact negligible.

Applied to files:

  • apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts
🧬 Code graph analysis (2)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx (1)
apps/webapp/app/presenters/v3/RegionsPresenter.server.ts (2)
  • RegionsPresenter (18-159)
  • Region (7-16)
apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx (2)
apps/webapp/app/components/primitives/Label.tsx (1)
  • Label (25-41)
apps/webapp/app/components/primitives/Select.tsx (2)
  • Select (112-258)
  • SelectItem (452-501)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (27)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: typecheck / typecheck
🔇 Additional comments (4)
apps/webapp/app/v3/testTask.ts (1)

25-25: LGTM!

Using plain z.string().optional() is appropriate here since region names are dynamic (from DB), unlike MachinePresetName which is a closed enum.

apps/webapp/app/v3/services/testTask.server.ts (1)

14-78: LGTM!

data.region is propagated symmetrically to both the STANDARD and SCHEDULED trigger paths, consistent with how other RunOptionsData fields (e.g., machine, tags) are handled.

apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts (1)

115-130: LGTM for the region data fetching.

RegionsPresenter is fetched concurrently with prettyPrintPacket via Promise.all, correctly passing user.admin || user.isImpersonating for the isAdmin flag consistent with route.tsx. The same workerQueue-as-region concern flagged in replayTaskRun.server.ts applies to Line 129 — if run.workerQueue doesn't match a region name from RegionsPresenter, the defaultValue in the dropdown won't pre-select correctly.

apps/webapp/app/v3/services/replayTaskRun.server.ts (1)

62-67: The region Select defaultValue and SelectItem values use incompatible identifiers for unmanaged worker regions.

The loader sets region: run.workerQueue (which contains the masterQueue identifier), but the Select renders items with value={region.name}. For unmanaged regions, masterQueue differs from name (e.g., masterQueue="project_1-us-east-1" vs name="us-east-1"), causing the defaultValue to not match any SelectItem and leaving the dropdown with no selection. Additionally, when submitted, getWorkerQueue expects regionOverride to be a valid masterQueue, but receives the name value instead, causing validation to fail. Either align SelectItem values to use the masterQueue identifier, or update the loader to map run.workerQueue to the corresponding region.name.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx`:
- Around line 361-389: Rename the misleading replayData.disableVersionSelection
flag to a more general name like replayData.isDevEnvironment (or similar) and
update all usages: change the prop and checks in ReplayRunDialog where
disableVersionSelection is used (the Select disabled prop, placeholder logic,
and Hint conditional rendering that reference
replayData.disableVersionSelection), and also update any upstream
producers/consumers of replayData to populate the new flag name so type
definitions and callers remain consistent; ensure identifiers such as Select,
region, SelectItem, Hint, and FormError continue to reference the new flag and
run the app/tests to verify no remaining references to disableVersionSelection.

In
`@apps/webapp/app/routes/_app.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx:
- Around line 1183-1215: ScheduledTaskForm's region Select is inconsistent with
StandardTaskForm: update the Select in ScheduledTaskForm (the Select component
inside the region InputGroup) to use the same isDev guards as StandardTaskForm
by changing defaultValue to defaultValue={isDev ? undefined :
defaultRegion?.name} and add placeholder={isDev ? "–" : undefined}; keep the
existing value/setValue/disabled logic intact so the disabled dev state shows
the "–" placeholder and no pre-selected region.
- Around line 828-844: CreateTemplateModal currently omits the selected region
from the saved template data which causes region state to be lost when a
template is applied; update the rawTestTaskFormData passed to
CreateTemplateModal to include region: regionValue (alongside machine, queue,
concurrencyKey, ttlSeconds, maxAttempts, maxDurationSeconds, tags), extend the
CreateTemplateModal/CreateTemplateModal props type to accept region, and update
onTemplateSelected handlers (used by StandardTaskForm and any other forms) to
call setRegionValue(template.region) when a template with a region is chosen (or
add a clear comment in CreateTemplateModal/StandardTaskForm explaining that
region is intentionally excluded if that is desired behavior).

@nicktrn nicktrn marked this pull request as ready for review February 17, 2026 21:17
@nicktrn nicktrn changed the title feat: add region selector to test and replay task UI feat(webapp): add region selector to test and replay task Feb 17, 2026
devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx (1)

902-922: Consider extracting shared region logic into a reusable hook or component.

The region state (isDev, defaultRegion, regionValue, regionItems) and the region <Select> block are copy-pasted between StandardTaskForm (lines 388–406, 608–646) and ScheduledTaskForm (lines 902–922, 1183–1221). A small useRegionSelector(regions, environment) hook plus a <RegionSelect> wrapper would eliminate the duplication and make future changes (e.g., restoring region from templates) a single-site edit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/webapp/app/routes/_app.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
around lines 902 - 922, The region selection logic is duplicated between
StandardTaskForm and ScheduledTaskForm; extract it into a reusable hook and
wrapper component: create useRegionSelector(regions, environment) that returns
isDev, defaultRegion, regionValue, setRegionValue, and regionItems (derived from
regions.map) and create a RegionSelect component that consumes those values and
renders the Select block; replace the duplicated region state and JSX in
StandardTaskForm and ScheduledTaskForm with calls to useRegionSelector(...) and
the RegionSelect component to centralize behavior (including any defaulting
logic such as isDev ? undefined : defaultRegion?.name and tags like regionValue,
setRegionValue).
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cfd8490 and c259bc1.

📒 Files selected for processing (1)
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

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

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

**/*.{ts,tsx}: Always import tasks from @trigger.dev/sdk, never use @trigger.dev/sdk/v3 or deprecated client.defineJob pattern
Every Trigger.dev task must be exported and have a unique id property with no timeouts in the run function

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
{packages/core,apps/webapp}/**/*.{ts,tsx}

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

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
**/*.{ts,tsx,js,jsx}

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

Use function declarations instead of default exports

Import from @trigger.dev/core using subpaths only, never import from root

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Access environment variables via env export from apps/webapp/app/env.server.ts, never use process.env directly

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
🧠 Learnings (11)
📚 Learning: 2026-02-11T16:50:14.167Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3019
File: apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboards.$dashboardId.widgets.tsx:126-131
Timestamp: 2026-02-11T16:50:14.167Z
Learning: In apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboards.$dashboardId.widgets.tsx, MetricsDashboard entities are intentionally scoped to the organization level, not the project level. The dashboard lookup should filter by organizationId only (not projectId), allowing dashboards to be accessed across projects within the same organization. The optional projectId field on MetricsDashboard serves other purposes and should not be used as an authorization constraint.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2025-12-08T15:19:56.823Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.823Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Export tasks with unique IDs within the project to enable proper task discovery and execution

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/app/v3/presenters/**/*.server.{ts,tsx} : Organize presenters in the webapp following the pattern `app/v3/presenters/*/*.server.ts` to move complex loader code into classes

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2026-02-03T18:27:40.429Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx:553-555
Timestamp: 2026-02-03T18:27:40.429Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx, the menu buttons (e.g., Edit with PencilSquareIcon) in the TableCellMenu are intentionally icon-only with no text labels as a compact UI pattern. This is a deliberate design choice for this route; preserve the icon-only behavior for consistency in this file.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2026-02-04T16:34:48.876Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/routes/vercel.connect.tsx:13-27
Timestamp: 2026-02-04T16:34:48.876Z
Learning: In apps/webapp/app/routes/vercel.connect.tsx, configurationId may be absent for "dashboard" flows but must be present for "marketplace" flows. Enforce this with a Zod superRefine and pass installationId to repository methods only when configurationId is defined (omit the field otherwise).

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to **/*.{ts,tsx} : Every Trigger.dev task must be exported and have a unique `id` property with no timeouts in the run function

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schedules.task()` for scheduled/cron tasks instead of regular `task()`

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2025-08-19T09:49:07.011Z
Learnt from: julienvanbeveren
Repo: triggerdotdev/trigger.dev PR: 2417
File: apps/webapp/app/routes/api.v1.projects.$projectRef.envvars.$slug.import.ts:56-61
Timestamp: 2025-08-19T09:49:07.011Z
Learning: In the Trigger.dev codebase, environment variables should default to `isSecret: false` when not explicitly marked as secrets in the syncEnvVars functionality. This is the intended behavior for both regular variables and parent variables.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📚 Learning: 2026-02-11T16:37:32.429Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3019
File: apps/webapp/app/components/primitives/charts/Card.tsx:26-30
Timestamp: 2026-02-11T16:37:32.429Z
Learning: In projects using react-grid-layout, avoid relying on drag-handle class to imply draggability. Ensure drag-handle elements only affect dragging when the parent grid item is configured draggable in the layout; conditionally apply cursor styles based on the draggable prop. This improves correctness and accessibility.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
🧬 Code graph analysis (1)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx (3)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test/route.tsx (1)
  • loader (48-77)
apps/webapp/app/services/session.server.ts (1)
  • requireUser (39-62)
apps/webapp/app/presenters/v3/RegionsPresenter.server.ts (2)
  • RegionsPresenter (18-159)
  • Region (7-16)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (27)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: sdk-compat / Cloudflare Workers
🔇 Additional comments (4)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx (4)

290-323: LGTM — regions correctly propagated to both form variants.

The regions prop is properly passed from the loader result into both StandardTaskForm and ScheduledTaskForm through the trigger source switch.


57-57: Good use of requireUser to access admin/impersonation flags for region visibility.

The switch from requireUserId to requireUser cleanly enables user.admin || user.isImpersonating (line 114) for the RegionsPresenter call, and user.id is correctly threaded to all downstream lookups.

Also applies to: 78-78, 82-118


111-115: [No action required — RegionsPresenter() is instantiated correctly.]

BasePresenter has default parameters for both _prisma and _replica, defaulting to prisma and $replica respectively. Since RegionsPresenter does not override the constructor, calling new RegionsPresenter() without arguments is valid and will use the correct defaults. This pattern is used consistently across the codebase in multiple files.

Likely an incorrect or invalid review comment.


388-406: Use region id instead of name to reliably match against the worker instance group.

The form submits r.name as the region value (lines 391, 403), but the backend looks up worker groups by masterQueue (workerGroupService.ts:220), which is only guaranteed to equal the name for managed regions. Unmanaged regions have masterQueue prefixed with the project ID (e.g., "project_1-us-east-1"), so submitting the plain name will fail the lookup. Use r.id instead, which consistently maps to WorkerInstanceGroup.id and can be reliably resolved.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@apps/webapp/app/routes/_app.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx:
- Around line 902-922: The region selection logic is duplicated between
StandardTaskForm and ScheduledTaskForm; extract it into a reusable hook and
wrapper component: create useRegionSelector(regions, environment) that returns
isDev, defaultRegion, regionValue, setRegionValue, and regionItems (derived from
regions.map) and create a RegionSelect component that consumes those values and
renders the Select block; replace the duplicated region state and JSX in
StandardTaskForm and ScheduledTaskForm with calls to useRegionSelector(...) and
the RegionSelect component to centralize behavior (including any defaulting
logic such as isDev ? undefined : defaultRegion?.name and tags like regionValue,
setRegionValue).

Copy link

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

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 2 additional findings in Devin Review.

Open in Devin Review

@nicktrn nicktrn merged commit 59b6eb9 into main Feb 18, 2026
50 checks passed
@nicktrn nicktrn deleted the feat/region-selector-test-replay branch February 18, 2026 10:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Testing task and Replaying should allow selecting region

2 participants