Skip to content

feat: serverless worker create form wired to CreateWorkerDeployment API#3236

Draft
rossnelson wants to merge 9 commits intoworker-insightsfrom
serverless-workers-crud
Draft

feat: serverless worker create form wired to CreateWorkerDeployment API#3236
rossnelson wants to merge 9 commits intoworker-insightsfrom
serverless-workers-crud

Conversation

@rossnelson
Copy link
Collaborator

Summary

  • Add serverless worker CRUD pages under /workers/deployments/serverless/
  • Wire create form to CreateWorkerDeployment API: name → deploymentName, lambdaArn/iamRoleArn → computeConfig.provider.detailJson, min/maxInstances → computeConfig.scaler
  • Remove region field from form — parsed automatically from Lambda ARN (arn:aws:lambda:<region>:...)
  • Move ARN existence validation to submit (onUpdate handler) instead of a separate "Validate Connection" button — errors surface inline under the respective fields
  • Add ComputeProvider, ComputeScaler, CreateWorkerDeploymentRequest types
  • Add CapabilityGuard component and deployments empty state

Test plan

  • Create form renders with Name, Lambda ARN, IAM Role ARN fields
  • Zod format validation fires on submit for malformed ARNs
  • Lambda/IAM existence validation runs on submit, errors appear inline under the relevant field
  • Successful submit calls CreateWorkerDeployment with correct payload (region extracted from ARN)
  • Cancel navigates back to workers list
  • Scaling fields toggle correctly via "Show Scaling and Limits"

Brings in net-new files only — types, mocked service layer, form
components, pages, and routes for create/edit/detail/delete flows.
No existing files touched yet.
Additive-only changes: new worker API types (ListWorkers, DescribeWorker,
WorkerStatus, WorkerHostInfo), new route path types, and all i18n strings
for serverless worker CRUD flows.
- Route files at /workers/deployments/[namespace]/workers/deployments/serverless/{create,[id],[id]/edit}
- Route helpers: routeForServerlessWorkerCreate, routeForServerlessWorker, routeForServerlessWorkerEdit
- New Holocene components: RadioCard, Timeline, TimelineStep
- i18n strings for serverless worker detail page
- Fix HeartBeat usage in serverless-worker-status (no color prop)
- Map form fields to API: name→deploymentName, lambdaArn/iamRoleArn/region→computeConfig.provider.detailJson, minInstances/maxInstances→computeConfig.scaler
- Replace per-field blur validation with single Validate Connection button
- Add min/max instances scaling fields (hidden behind toggle)
- Add ComputeProvider, ComputeScaler, CreateWorkerDeploymentRequest types
- Drop region from createSchema and form UI
- Extract region from lambdaArn.split(':')[3] in create page
- Move validation to onUpdate handler (validates on submit, not separate button)
- Clean up unused imports (regions, ValidationState, validateRegion)
- Refactor deployments.svelte page layout and routing
- Slim down serverless-worker-service to remove mock validation stubs
- Add CapabilityGuard component and deployments empty state
- Update types index and layout for serverless deployments route
- Update deployments i18n strings
- Update server go.mod/go.sum dependencies
@vercel
Copy link

vercel bot commented Mar 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
holocene Ready Ready Preview, Comment Mar 19, 2026 9:12pm

Request Review

localFilters = [
createFilter({
attribute,
type: 'Keyword',
Copy link
Contributor

Choose a reason for hiding this comment

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

  • ⚠️ Type 'string | null' is not assignable to type 'string | undefined'.

createFilter({
attribute,
parenthesis: localFilters.length ? ')' : '',
type: 'Keyword',
Copy link
Contributor

Choose a reason for hiding this comment

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

  • ⚠️ Type 'string | null' is not assignable to type 'string | undefined'.

};

const superform = superForm(initialData, {
SPA: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

  • ⚠️ Type 'ClientValidationAdapter<{ name: string; lambdaArn: string; iamRoleArn: string; minInstances?: number | undefined; maxInstances?: number | undefined; }, { name: string; lambdaArn: string; iamRoleArn: string; minInstances?: number | undefined; maxInstances?: number | undefined; }>' is not assignable to type 'ClientValidationAdapter<Partial<{ name: string; lambdaArn: string; iamRoleArn: string; region: string; minInstances: undefined; maxInstances: undefined; }>, Record<string, unknown>> | ValidatorsOption<...> | undefined'.

? String($form.minInstances)
: ''}
oninput={(e) => {
const val = (e.currentTarget as HTMLInputElement).value;
Copy link
Contributor

Choose a reason for hiding this comment

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

  • ⚠️ Type 'number | undefined' is not assignable to type 'undefined'.

? String($form.maxInstances)
: ''}
oninput={(e) => {
const val = (e.currentTarget as HTMLInputElement).value;
Copy link
Contributor

Choose a reason for hiding this comment

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

  • ⚠️ Type 'number | undefined' is not assignable to type 'undefined'.


if (!filter || filter.value !== value) {
const newFilter: SearchAttributeFilter = createFilter({
attribute,
Copy link
Contributor

Choose a reason for hiding this comment

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

  • ⚠️ Type 'string | null | undefined' is not assignable to type 'string | undefined'.

/>
</div>
</div>
<CodecServerErrorBanner />
Copy link
Contributor

Choose a reason for hiding this comment

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

  • ⚠️ Type 'WorkflowExecution | null' is not assignable to type 'WorkflowExecution'.

{translate('workers.back-to-workers')}
</Link>
<span class="text-secondary">|</span>
<Link
Copy link
Contributor

Choose a reason for hiding this comment

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

  • ⚠️ Type 'string | undefined' is not assignable to type 'string'.

</td>
<td>
<Link
class="inline-flex items-center gap-1"
Copy link
Contributor

Choose a reason for hiding this comment

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

  • ⚠️ Type 'string | undefined' is not assignable to type 'string'.

@temporal-cicd
Copy link
Contributor

temporal-cicd bot commented Mar 19, 2026

Warnings
⚠️

📊 Strict Mode: 42 errors in 11 files (3.9% of 1077 total)

src/lib/utilities/route-for-api.ts (8)
  • L68:48: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.
  • L74:50: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.
  • L76:4: Type 'string | null' is not assignable to type 'string'.
  • L103:8: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ namespace: string; workflowId: string; scheduleId: string; queue: string; queryType: string; signalName: string; updateName: string; batchJobId: string; runId: string; activityId: string; endpointId: string; deploymentName: string; version: string; workerInstanceKey: string; }'.
  • L103:38: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Partial'.
  • L105:8: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ namespace: string; workflowId: string; scheduleId: string; queue: string; queryType: string; signalName: string; updateName: string; batchJobId: string; runId: string; activityId: string; endpointId: string; deploymentName: string; version: string; workerInstanceKey: string; }'.
  • L105:57: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Partial'.
  • L191:16: This overload signature is not compatible with its implementation signature.
src/lib/stores/filters.ts (2)
  • L114:2: Argument of type 'StartStopNotifier<EventTypeCategory[] | null>' is not assignable to parameter of type 'StartStopNotifier<EventTypeCategory[] | undefined>'.
  • L130:13: Argument of type 'StartStopNotifier<("Scheduled" | "Unspecified" | "Open" | "New" | "Started" | "Initiated" | "Running" | "Completed" | "Fired" | "Signaled" | "Canceled" | "Failed" | "Terminated" | "TimedOut" | "CancelRequested")[] | null>' is not assignable to parameter of type 'StartStopNotifier<("Scheduled" | "Unspecified" | "Open" | "New" | "Started" | "Initiated" | "Running" | "Completed" | "Fired" | "Signaled" | "Canceled" | "Failed" | "Terminated" | "TimedOut" | "CancelRequested")[] | undefined>'.
src/lib/utilities/screaming-enums.ts (2)
  • L92:14: Type 'PendingNexusOperationState.PENDING_NEXUS_OPERATION_STATE_UNSPECIFIED | undefined' is not assignable to type 'PendingNexusOperationState'.
  • L99:14: Type 'CallbackState.CALLBACK_STATE_UNSPECIFIED | undefined' is not assignable to type 'CallbackState'.
src/lib/components/worker-table.svelte (6)
  • L69:12: Type 'number | null | undefined' is not assignable to type 'string | number'.
  • L69:24: 'workers.versioningInfo' is possibly 'null' or 'undefined'.
  • L75:5: Parameter 'poller' implicitly has an 'any' type.
  • L158:35: 'poller.taskQueueTypes' is possibly 'undefined'.
  • L165:35: 'poller.taskQueueTypes' is possibly 'undefined'.
  • L172:35: 'poller.taskQueueTypes' is possibly 'undefined'.
src/lib/components/workflow/filter-bar/dropdown-filter-chip.svelte (2)
  • L4:33: Could not find a declaration file for module 'date-fns-tz'. '/home/runner/work/ui/ui/node_modules/.pnpm/date-fns-tz@1.3.8_date-fns@2.30.0/node_modules/date-fns-tz/index.js' implicitly has an 'any' type.
  • L316:12: Type 'null' is not assignable to type 'string'.
src/lib/components/shared-search-attribute-filter/status-filter-chip.svelte (2)
  • L79:10: Type 'string | null' is not assignable to type 'string | undefined'.
  • L90:10: Type 'string | null' is not assignable to type 'string | undefined'.
src/lib/components/workers/serverless-worker-form/serverless-worker-create-form.svelte (3)
  • L48:4: Type 'ClientValidationAdapter<{ name: string; lambdaArn: string; iamRoleArn: string; minInstances?: number | undefined; maxInstances?: number | undefined; }, { name: string; lambdaArn: string; iamRoleArn: string; minInstances?: number | undefined; maxInstances?: number | undefined; }>' is not assignable to type 'ClientValidationAdapter<Partial<{ name: string; lambdaArn: string; iamRoleArn: string; region: string; minInstances: undefined; maxInstances: undefined; }>, Record<string, unknown>> | ValidatorsOption<...> | undefined'.
  • L180:20: Type 'number | undefined' is not assignable to type 'undefined'.
  • L193:20: Type 'number | undefined' is not assignable to type 'undefined'.
src/lib/components/workers/workers-table/workers-table-cell.svelte (1)
  • L44:8: Type 'string | null | undefined' is not assignable to type 'string | undefined'.
src/lib/layouts/workflow-header.svelte (6)
  • L135:37: Argument of type 'WorkflowExecution | null' is not assignable to parameter of type 'WorkflowExecution'.
  • L136:45: Argument of type 'WorkflowExecution | null' is not assignable to parameter of type 'WorkflowExecution'.
  • L141:13: Type 'WorkflowExecution | null' is not assignable to type 'WorkflowExecution'.
  • L167:9: Type 'WorkflowExecution | null' is not assignable to type 'WorkflowExecution'.
  • L175:20: Type 'WorkflowExecution | null' is not assignable to type 'WorkflowExecution'.
  • L231:12: Type 'string | undefined' is not assignable to type 'string'.
src/lib/layouts/workflow-run-layout.svelte (8)
  • L102:39: Type 'string | undefined' is not assignable to type 'string'.
  • L118:8: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
  • L153:6: Type 'WorkflowExecution | undefined' is not assignable to type 'WorkflowExecution | null'.
  • L167:4: Type 'undefined' is not assignable to type 'NetworkError | null'.
  • L170:18: No overload matches this call.
  • L179:28: Parameter 'fullHistory' implicitly has an 'any' type.
  • L179:41: Parameter 'pause' implicitly has an 'any' type.
  • L211:35: Argument of type 'null' is not assignable to parameter of type '((key: string, value: { eventHistory: WorkflowEvents; workflow: WorkflowExecution | null; workers: IDescribeTaskQueueResponse; workersLoaded: boolean; metadata: WorkflowMetadata | null; userMetadata: { ...; }; }) => { ...; }) | undefined'.
src/lib/pages/serverless-worker-detail.svelte (2)
  • L77:8: Type 'string | undefined' is not assignable to type 'string'.
  • L503:22: Type 'string | undefined' is not assignable to type 'string'.

Generated by 🚫 dangerJS against 5a3156d

@rossnelson rossnelson changed the base branch from main to worker-insights March 19, 2026 20:19
On xl screens the setup guide stays as a sticky card in the right column.
Below xl a ghost button in the page title opens it in a right-side drawer.
The guide component is now pure content — Card and sticky are applied at the callsite.
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.

1 participant