Skip to content

feat(frontend): add the on-canvas per-execution warehouse picker - #8551

Merged
mengw15 merged 8 commits into
apache:mainfrom
mengw15:feat/warehouse-picker
Sep 18, 2026
Merged

mengw15 merged 8 commits into
apache:mainfrom
mengw15:feat/warehouse-picker

Conversation

@mengw15

@mengw15 mengw15 commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

The workspace-side half of per-user warehouses (#6870): a warehouse picker on the canvas, beside the computing-unit selector it mirrors, choosing which warehouse the next execution writes to.

  • The picker (inside ComputingUnitSelectionComponent, like the computing-unit dropdown it sits beside) — shown only while the deployment enables the feature; each entry carries the owner avatar and a per-row delete, plus a create entry opening the shared create dialog. The list refreshes on every dropdown open, and preselection picks the latest execution's warehouse, falling back to the user's first one — so a run needs no explicit pick. A status failure clears the pick rather than letting a stale id ride the next request.
  • Run gating — with the feature enabled, every execution must have a warehouse: while none is selected the Run button becomes "Create Warehouse" and leads to the create dialog, the same shape as the Connect flow. (The backend-side requirement follows separately — [BYO-S3] Require a warehouse for every execution while the feature is enabled #7751 stays the tracker.)
  • The request — the picked warehouseId rides the execute request (ExecuteWorkflowService reads the pick from WarehouseService, where it lives); executions expose whId so the preselect can read the latest run's warehouse.

Flag off (the default): the picker never renders, the Run button is untouched, and requests carry no warehouseId — no user-visible change.

demo

Screen.Recording.2026-09-16.at.3.18.52.PM.mov

Any related issues, documentation, discussions?

Closes #7817. Part of #6870, on top of the dashboard tab (#8005); the backend enforcement (#7751) follows.

How was this PR tested?

  • 20 new Vitest tests: 15 on the picker (preselect from the latest execution, first-warehouse fallback, disabled/failed states clearing the pick, manual pick surviving refreshes, create/delete flows, dropdown rendering), 3 on the Run gating, 1 pinning warehouseId on the execute request, 1 on the selection state. One pre-existing assertion modernized: the remembered-unit test asserted the latest-execution lookup's absence, which the warehouse preselect now legitimately performs — it asserts the unit choice directly instead.
  • The affected suites pass in full: 5083 tests across the workspace and dashboard trees.
  • Failure paths verified rather than assumed: the preselect, the Run gating, and the request field were each broken on purpose and the suite confirmed to fail for the expected reason before being restored.
  • Screenshots/video from a local flag-on deployment follow in the comments.

Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (claude-opus-5, claude-fable-5)

The workspace selector for which warehouse a run writes to (apache#7817),
mirroring the computing-unit picker: owner avatar per entry, per-row
delete, a create entry, and a refresh on every dropdown open,
preselecting the latest execution's warehouse and falling back to the
first one. With the feature enabled a run needs a warehouse, so the Run
button becomes "Create Warehouse" while none is selected, mirroring
the Connect flow, and the picked warehouseId rides the execute request.
The pick lives in WarehouseService, where ExecuteWorkflowService reads
it at execution time.
@github-actions github-actions Bot added feature frontend Changes related to the frontend GUI labels Sep 16, 2026
@github-actions

github-actions Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • Contributors with relevant context: @yangzhang75, @kunwp1, @Neilk1021
    You can notify them by mentioning @yangzhang75, @kunwp1, @Neilk1021 in a comment.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Warehouse state races and fail-open behavior can select the wrong warehouse or allow executions without one.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds a feature-gated warehouse picker to the workspace and attaches the selected warehouse to workflow executions.

Changes:

  • Adds warehouse selection, creation, deletion, and preselection.
  • Gates Run when no warehouse is selected.
  • Includes warehouseId in execution requests and expands test coverage.
File summaries
File Description
execute-workflow.service.ts Adds warehouse ID to execution requests.
execute-workflow.service.spec.ts Tests request serialization.
computing-unit-selection.component.ts Implements warehouse picker state and actions.
computing-unit-selection.component.spec.ts Tests picker behavior.
computing-unit-selection.component.scss Styles the picker.
computing-unit-selection.component.html Renders picker and creation modal.
menu.component.ts Adds missing-warehouse Run gating.
menu.component.spec.ts Tests Run behavior.
workflow-executions-entry.ts Exposes execution warehouse ID.
workflow-execution-history.component.spec.ts Updates execution fixtures.
warehouse.service.ts Stores the current warehouse selection.
warehouse.service.spec.ts Tests selection state.
Review details

Suppressed comments (2)

frontend/src/app/workspace/component/power-button/computing-unit-selection.component.ts:480

  • A status failure is treated as feature-disabled, then the selected ID is cleared. Consequently warehouseRequiredButMissing becomes false and runWorkflow() proceeds with warehouseId: undefined; until #7751 lands, an enabled deployment silently writes that run to shared storage. Keep an explicit failed/loading state and fail closed (disable or retry Run) unless the status request successfully reports enabled: false.
        error: (err: unknown) => {
          // The pick lives in the root-scoped service, so hiding the picker is not
          // enough: a stale id from a previous workflow would still ride the next
          // execution request. Clear it whenever the picker cannot be shown.
          this.warehouseEnabled = false;
          this.warehouses = [];
          this.warehouseService.selectWarehouse(undefined);

frontend/src/app/workspace/component/power-button/computing-unit-selection.component.html:126

  • Adding role="button" to an <i> does not make it keyboard-operable: this delete action cannot receive focus or be activated with Enter/Space. Prefer a real <button type="button">, or add tabindex="0" plus equivalent keyboard handlers.
            role="button"
            aria-label="Delete warehouse">
  • Files reviewed: 12/12 changed files
  • Comments generated: 4
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread frontend/src/app/workspace/component/menu/menu.component.ts Outdated
@codecov-commenter

codecov-commenter commented Sep 16, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.07692% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.92%. Comparing base (dcf8217) to head (5b76637).
⚠️ Report is 11 commits behind head on main.

Files with missing lines Patch % Lines
...wer-button/computing-unit-selection.component.html 87.80% 3 Missing and 2 partials ⚠️
...rvice/execute-workflow/execute-workflow.service.ts 85.71% 1 Missing and 1 partial ⚠️
...src/app/workspace/component/menu/menu.component.ts 90.90% 1 Missing ⚠️
...power-button/computing-unit-selection.component.ts 98.33% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #8551      +/-   ##
============================================
- Coverage     92.93%   92.92%   -0.02%     
  Complexity     4885     4885              
============================================
  Files          1231     1235       +4     
  Lines         51468    51966     +498     
  Branches       6327     6389      +62     
============================================
+ Hits          47833    48287     +454     
- Misses         2073     2105      +32     
- Partials       1562     1574      +12     
Flag Coverage Δ *Carryforward flag
access-control-service 71.78% <ø> (ø) Carriedforward from 6ab9fee
agent-service 99.32% <ø> (ø) Carriedforward from 6ab9fee
amber 89.02% <ø> (ø) Carriedforward from 6ab9fee
computing-unit-managing-service 54.61% <ø> (ø) Carriedforward from 6ab9fee
config-service 87.37% <ø> (ø) Carriedforward from 6ab9fee
file-service 81.53% <ø> (ø) Carriedforward from 6ab9fee
frontend 96.57% <93.07%> (-0.12%) ⬇️
notebook-migration-service 83.73% <ø> (ø) Carriedforward from 6ab9fee
pyamber 98.47% <ø> (ø) Carriedforward from 6ab9fee
workflow-compiling-service 74.09% <ø> (ø) Carriedforward from 6ab9fee

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

- The menu re-snapshots the Run button whenever the warehouse pick
  changes; every relevant transition (load, preselect, create, disable,
  failure) ends in a selectWarehouse call, so the pick stream covers
  them all.
- Warehouse refreshes flow through one switchMap'd stream, so an older
  response cannot restore a deleted row or clobber a newer answer.
- The previous workflow's last-execution warehouse is cleared on
  workflow change, so a workflow without history falls back to the
  first warehouse instead of the old workflow's.
- The warehouse rows carry unique DOM ids.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Status failures can bypass warehouse gating, and asynchronous preselection can overwrite a manual choice.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

frontend/src/app/workspace/component/power-button/computing-unit-selection.component.html:127

  • This icon has role="button" but is neither focusable nor keyboard-operable, so keyboard users cannot invoke the destructive action. Add tab focus plus Enter/Space handlers (including propagation prevention so the menu row is not selected).
    frontend/src/app/workspace/component/power-button/computing-unit-selection.component.ts:541
  • A manual choice does not invalidate the in-flight latest-execution lookup. If the user selects a row before either lookup callback runs, applyWarehousePreselect() later overwrites that explicit choice with the historical/default warehouse. Track a workflow/request generation (or whether the user has selected since lookup start) and ignore preselection callbacks after a manual pick.
  • Files reviewed: 12/12 changed files
  • Comments generated: 1
  • Review effort level: Balanced

A status transport failure no longer drops warehouseEnabled: the flag
initializes from the boot-time GUI config and only a status answer moves
it, so Run stays gated on an enabled deployment instead of silently
writing to the shared default storage. Explicit picks (dropdown or
create) are tracked and preselection never overrides one; switching
workflows clears the pick immediately, so nothing of the old workflow
rides an execution while the new preselect is still pending.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Several execution entry points bypass the warehouse gate and can still submit without a warehouse.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

frontend/src/app/workspace/component/power-button/computing-unit-selection.component.html:101

  • This class has no corresponding style rule and does not set Ng Zorro's menu-item selection state, so the open menu exposes no visual or ARIA indication of the current warehouse. Bind the menu item's nzSelected input instead.
    frontend/src/app/workspace/component/power-button/computing-unit-selection.component.html:127
  • This delete control is mouse-only: role="button" does not make the icon focusable or activate it from the keyboard. Add focusability and Enter/Space handlers (including propagation prevention so deletion does not select the row).
    frontend/src/app/workspace/component/power-button/computing-unit-selection.component.ts:605
  • After deletion succeeds, this callback starts another HTTP request but leaves the deleted warehouse selected until that request returns. During that window Run remains enabled and can submit the now-invalid ID; if the refresh stalls, the stale selection persists. Clear the selected ID synchronously when the deleted warehouse was selected, then refresh to choose the fallback.
  • Files reviewed: 12/12 changed files
  • Comments generated: 1
  • Review effort level: Balanced

The error path re-asserts the boot-time flag instead of the field being
config-initialized at construction: identical gating after a failure,
without a "Create Warehouse" flash on the Run button during the initial
load window.
The menu's Run button was the only gate, but the form view,
run-up-to-operator, and replay all call the execution service directly
and would fall through to the shared default storage. The guard now
lives in sendExecutionRequest — the one point every path funnels
through — refusing with a toast while the deployment requires a
warehouse and none is picked. (apache#7751 adds the backend-side rejection.)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Warehouse preselection, deletion timing, execution-state resets, and keyboard accessibility have unresolved defects.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

frontend/src/app/workspace/component/power-button/computing-unit-selection.component.html:126

  • role="button" does not make this <i> keyboard-focusable or activate it with Enter/Space, so keyboard-only users cannot delete a warehouse. Use a real button, or add tabindex="0" plus Enter/Space handlers that invoke the same confirmation without selecting the row.
    frontend/src/app/workspace/component/power-button/computing-unit-selection.component.ts:388
  • This lookup is still coupled to the computing-unit list becoming nonempty. If the workflow has a remembered CU that was terminated and the user currently has zero units, the filter(units => units.length > 0) above never emits, so the latest execution is never queried and the warehouse refresh permanently leaves the first warehouse selected instead of the latest execution's warehouse. Start warehouse preselection independently of the CU-list wait.
    frontend/src/app/workspace/component/power-button/computing-unit-selection.component.ts:601
  • After a selected warehouse is successfully deleted, this callback starts an asynchronous refresh but leaves the deleted ID selected until that request returns. A run during that interval sends a warehouse ID that is guaranteed not to exist. Clear the selection synchronously in the delete-success callback before refreshing.
  • Files reviewed: 12/12 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread frontend/src/app/workspace/service/execute-workflow/execute-workflow.service.ts Outdated
The public entry points now check the warehouse requirement before
resetExecutionState/resetStatus, so a refused click keeps the results
already on screen; sendExecutionRequest keeps the same check as the
shared belt for direct callers.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Unsaved workflows can lose automatic preselection, and the delete control is not keyboard accessible.

Review details

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

frontend/src/app/workspace/component/power-button/computing-unit-selection.component.html:127

  • This delete control has role="button" but is not focusable or keyboard-activatable, so keyboard-only users cannot delete a warehouse. Add focus and Enter/Space activation (or use a native button) while continuing to stop propagation to the parent menu item.
    frontend/src/app/workspace/component/power-button/computing-unit-selection.component.ts:352
  • Switching to a new unsaved workflow (wid === DEFAULT_WORKFLOW.wid) clears the warehouse selection and then skips every preselection path. If the warehouse list was already loaded, the Run button therefore offers “Create Warehouse” even when the user already has warehouses, until they manually reopen the dropdown. Apply the first-warehouse fallback immediately for the default workflow.
  • Files reviewed: 12/12 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@mengw15
mengw15 requested a review from kunwp1 September 16, 2026 22:20

@Ma77Ball Ma77Ball left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review summary

This is the workspace-side half of per-user warehouses (#6870): a warehouse picker inside ComputingUnitSelectionComponent beside the computing-unit dropdown, Run-button gating that redirects to a create-warehouse modal when a warehouse is required but missing, and a warehouseId on the execute request. The change is well structured and mirrors the existing computing-unit patterns closely; the concurrency handling (a single switchMap'd refresh stream, preselect re-running after whichever of the list/latest-execution responses lands last, fail-closed on a status error) is careful and matches the extensive tests. The pick lives in the root-scoped WarehouseService and is cleared on workflow switch, on status failure, and when nothing is selectable, so a stale id cannot ride the next request. I verified the contract holds on the backend side: /executions/{wid}/latest serializes whId, and WorkflowExecuteRequest already declares warehouseId: Option[Int], so nothing here breaks execution. No blocking issues.

The one real gap is behavioral: the Run-button gate sits ahead of the execution-state switch, so it can replace Pause/Kill while a workflow is actively running (see below). Flag-off behavior is a clean no-op as described.

Action items: Nothing blocking. Consider the P2 (don't let the warehouse gate hide Pause/Kill mid-run) before merge; the P3 is optional.


Findings

2 total: 0 P0, 0 P1, 1 P2, 1 P3.

Non-blocking (P2)

  • Don't let the warehouse gate override Pause/Kill during an active execution - frontend/src/app/workspace/component/menu/menu.component.ts:427 - see inline.

Nit (P3)

  • Run-gate reads a different "enabled" signal than the picker - frontend/src/app/workspace/service/execute-workflow/execute-workflow.service.ts:252 - see inline.

Verification

  • P2 (button gate vs active execution): with the feature enabled and a workflow Running (or Paused), deleting the currently-selected warehouse via the picker's delete icon calls confirmDeleteWarehouse -> refreshWarehouses -> applyWarehousePreselect; if it was the only/last warehouse, selectWarehouse(undefined) runs, so warehouseRequiredButMissing flips to true. getRunButtonBehavior checks that before the executionState switch, so the button becomes "Create Warehouse" and the user loses Pause/Kill on the in-flight run. Narrow trigger, real loss of control.
  • P3 (dual enabled source): confirmed both status.enabled (picker) and config.env.warehouseEnabled (execute-service gate) derive from the same StorageConfig.warehouseEnabled today, so they cannot diverge on a real deployment - hence P3, not a bug.
  • Not run: I did not execute the Vitest suites; findings are from static reading of the PR at head plus the backend contract at the same ref.

Comment thread frontend/src/app/workspace/component/menu/menu.component.ts Outdated
The warehouse gate on the Run button now applies only in the states
whose button would start a run; deleting the last warehouse during a
Running/Paused execution no longer replaces Pause/Resume with "Create
Warehouse".

@kunwp1 kunwp1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM!

Comment thread frontend/src/app/workspace/component/menu/menu.component.ts Outdated
Comment thread frontend/src/app/workspace/service/execute-workflow/execute-workflow.service.ts Outdated
- Create and delete update the picker's list locally, like the
  dashboard tab, instead of refetching; deleting the picked warehouse
  re-runs the preselect.
- A status transport failure now reports the error and keeps the last
  known list and pick; clearing is reserved for an authoritative answer
  (enabled:false, or a list that no longer holds the pick). The flag
  still falls back to the boot-time config so Run stays gated.
- The latest-execution lookup is one method: selectFromLastExecution
  takes a selectUnit flag for the remembered-unit path instead of a
  duplicate warehouse-only copy.
- The refresh path always re-runs the preselect; its manual-pick guard
  is the single condition, so the overlapping one at the call site is
  gone.
- sendExecutionRequest drops the warehouse belt: every production
  caller is one of the two public entry points, which already refuse
  before resetting state.
@mengw15
mengw15 added this pull request to the merge queue Sep 18, 2026
Merged via the queue into apache:main with commit 9264975 Sep 18, 2026
26 of 31 checks passed
@mengw15
mengw15 deleted the feat/warehouse-picker branch September 18, 2026 04:28
mengw15 added a commit to mengw15/texeraFork that referenced this pull request Sep 18, 2026
…tton

The form view's run button enumerates every state a run cannot start from —
invalid workflow, empty workflow, connecting, no computing unit, a read-only
unit — so that, in its own words, the reader is never sent to press a button
that does nothing. The warehouse requirement added in apache#8551 was missing from
that list: with the feature enabled and nothing picked, the button read
"Run" and looked ready, and the click was refused deeper down, in
ExecuteWorkflowService, with a toast.

It now names what is missing and stays disabled, after the computing unit as
the canvas orders them. The condition read is the one that service refuses
on — the boot-time flag and the picked warehouse, both root-scoped — so the
button predicts the refusal exactly.

Closes apache#8591.
renovate-bot pushed a commit to renovate-bot/apache-_-texera that referenced this pull request Sep 18, 2026
… and name the picker in its tooltip (apache#8589)

### What changes were proposed in this PR?

A follow-up to the warehouse picker (apache#8551).

- **The run button's label overflowed.** `#run-button` is a fixed 140px,
which fits `Empty Workflow` with about a pixel to spare; `Create
Warehouse` ran roughly 13px past it and spilled over the execution
timer. The label is now `Warehouse` — the same word the picker's own
empty state already shows, mirroring how the computing-unit flow repeats
`Connect` in both places — and the button keeps its fixed width, so
nothing else on the toolbar moves.
- **The trigger's tooltip now reads `Warehouse: <name>`.** Two pickers
sit side by side showing nothing but a name, and the trigger ellipsises
that name at 220px; one tooltip says which picker this is and carries
the name in full, in the same shape every time — short names included,
so there is nothing to learn about when it appears. It replaces
"Warehouse this execution writes to", which named the picker but not the
warehouse.

Flag off (the default): the picker never renders and the run button is
untouched.

### before:

<img width="715" height="208" alt="Screenshot 2026-09-17 at 11 28 13 PM"
src="https://github.com/user-attachments/assets/59f58e27-259d-413d-aca2-ce2bbf2aec24"
/>

<img width="761" height="191" alt="Screenshot 2026-09-17 at 11 29 10 PM"
src="https://github.com/user-attachments/assets/c0cd7e1e-ea60-4f0f-b5c0-48b445c42d12"
/>

### after:

<img width="657" height="165" alt="Screenshot 2026-09-17 at 11 30 12 PM"
src="https://github.com/user-attachments/assets/e007fcaf-7771-4030-a961-49e361cf14aa"
/>

<img width="758" height="278" alt="Screenshot 2026-09-17 at 11 30 45 PM"
src="https://github.com/user-attachments/assets/2771ae7d-0713-40a1-af96-7f0324996089"
/>

### Any related issues, documentation, discussions?

Follow-up to apache#8551. Part of apache#6870. The remaining divergences are on the
computing-unit side and are tracked separately in apache#8587; a warehouse
status badge needs a backend signal first (apache#8588).

### How was this PR tested?

- Label widths measured in a browser against the button's real clipping
width (140px minus padding, border and icon leaves ~106px for text)
across the font stack's macOS, Windows and Linux faces: `Warehouse`
72px, `Create Warehouse` 119px, and main's own `Empty Workflow`/`Invalid
Workflow` 105px.
- Vitest: the run-button label test updated, a tooltip test added
covering both a long and a short name and pinning one tooltip per
control; the workspace suite passes in full (3323 tests).
- Failure paths verified rather than assumed: the label and the
tooltip's name were each reverted on purpose and the suite confirmed to
fail for the expected reason before being restored.

### Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (claude-opus-5, claude-fable-5)
aicam added a commit to Texera/rodeo-pipeline that referenced this pull request Sep 18, 2026
…) and 18 other commits

Brings apache#8528, the last merged Form View PR staging lacked, with
the rest of main since the last sync: the warehouse run picker (apache#8551, apache#8589),
RustFS CORS for presigned URLs (apache#8562), and the curated-image PRs staging
already carried as open branches (apache#8485, apache#8518, apache#8546), now as merged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XnSFFbnmkjX9gxTFW1j7Wj

# Conflicts:
#	computing-unit-managing-service/src/test/scala/org/apache/texera/service/resource/CuratedImageResourceSpec.scala
#	frontend/src/app/common/component/computing-unit-create-modal/computing-unit-create-modal.component.spec.ts
#	frontend/src/app/common/component/computing-unit-create-modal/computing-unit-create-modal.component.ts
#	frontend/src/app/dashboard/component/dashboard.component.spec.ts
mengw15 added a commit to mengw15/texeraFork that referenced this pull request Sep 18, 2026
…tton

The form view's run button enumerates every state a run cannot start from —
invalid workflow, empty workflow, connecting, no computing unit, a read-only
unit — so that, in its own words, the reader is never sent to press a button
that does nothing. The warehouse requirement added in apache#8551 was missing from
that list: with the feature enabled and nothing picked, the button read
"Run" and looked ready, and the click was refused deeper down, in
ExecuteWorkflowService, with a toast.

It now names what is missing and stays disabled. The condition read is the
one that service refuses on — the boot-time flag and the picked warehouse,
both root-scoped — so the button predicts the refusal exactly.

The read-only check comes before the warehouse one: picking a warehouse is
the only blocked state a reader can act on here, so naming it first would
send someone without write access to fix the wrong thing.

Closes apache#8591.
renovate-bot pushed a commit to renovate-bot/apache-_-texera that referenced this pull request Sep 18, 2026
… and let its button be clicked (apache#8590)

### What changes were proposed in this PR?

The warehouse picker (apache#8551) now sits beside the computing-unit picker,
and the pair showed nothing but a name each. Fixes apache#8587.

- **The trigger says what it is.** It gains the `deployment-unit` icon
its own dashboard tab uses — the warehouse trigger already carries
`cloud-server` — and its tooltip reads `Computing Unit: <name>`, the
shape the warehouse trigger uses: one tooltip on the control rather than
one on the badge and another on the name. The status stays where it
already lives, the badge's colour here and its words in the dropdown
rows.
- **With nothing selected, both the trigger and the run button name what
is missing** — `Computing Unit`, as the warehouse side says `Warehouse`
— instead of `Connect`, so the two pickers read the same way. The form
view's run button follows, since it mirrors the canvas's disable
conditions.
- **That button was disabled in exactly the state it exists for.** The
run button's guard ended in `selectedComputingUnit?.accessPrivilege !==
Privilege.WRITE`; with no unit selected that compares against
`undefined` and is always true, so the button offered to connect and
refused every click, leaving `runWorkflow()`'s create-unit branch
unreachable — the branch the form view's own comments describe as the
canvas's click target, and which its test reaches only by calling the
method directly. The privilege is now asked only of a unit that exists;
a unit shared read-only still refuses to run.
- **The two triggers stop looking like different controls.** Sized to
content between a min and a max they came out visibly different widths,
so both are now 200px; a name too long for it is ellipsised and read
from the tooltip, which carries it in full. The avatar, shrunk with a
`transform` that changes only what is drawn, kept its 32px box inside a
32px-tall button and inflated it, so it is sized for real instead. The
form view matches both pickers to its Run button's height, not just the
computing-unit one that rule predates. And the gap between the pickers
no longer widens whenever a unit is running: the container gap and the
auto margin that exist to push the metrics block away now apply to the
metrics block itself.
- **The badge stops claiming work that is not happening.**
`computeStatus()` returned `"processing"` with nothing selected, which
ant renders as a pulsing blue dot; it is now `"default"`.

### before:

<img width="1066" height="289" alt="Screenshot 2026-09-18 at 12 23
44 AM"
src="https://github.com/user-attachments/assets/ae6ac7ec-2e2b-4d5e-b676-220e4a0a861e"
/>

<img width="706" height="180" alt="Screenshot 2026-09-18 at 12 24 07 AM"
src="https://github.com/user-attachments/assets/6667d342-87f8-43fa-a85b-cd4217a9d9c8"
/>

<img width="696" height="177" alt="Screenshot 2026-09-18 at 12 24 40 AM"
src="https://github.com/user-attachments/assets/2750dfa8-e026-4fda-983c-f7f0271d1dac"
/>

### after:

<img width="805" height="246" alt="Screenshot 2026-09-18 at 12 33 45 AM"
src="https://github.com/user-attachments/assets/e93b7e1b-251a-4347-bfbd-a949761229de"
/>

<img width="747" height="234" alt="Screenshot 2026-09-18 at 12 32 57 AM"
src="https://github.com/user-attachments/assets/8249e697-d136-465d-b81c-d2e9867233b5"
/>

<img width="751" height="192" alt="Screenshot 2026-09-18 at 12 34 00 AM"
src="https://github.com/user-attachments/assets/a77aa290-dac4-4861-b472-2c1581565152"
/>

### Any related issues, documentation, discussions?

Closes apache#8587. Follows apache#8551 and apache#8589 (the warehouse side of the same
pair). Part of apache#6870.

### How was this PR tested?

- Vitest: new tests for the trigger's tooltip (long name, short name,
nothing selected), for the no-unit button being clickable, and for a
read-only unit still disabling it; the existing badge and label
assertions updated. The workspace suite passes in full: 3326 tests.
- Label width measured in a browser against the run button's clipping
width (~106px for text): `Computing Unit` is 101px on macOS, 96px on
Windows and Linux faces.
- The sizing and spacing changes are CSS and out of reach of jsdom; they
were checked in a running workspace and form view, with and without a
selection on each picker and with a unit running.
- Failure paths verified rather than assumed: the privilege guard, the
badge state, the tooltip and the label were each reverted on purpose and
the suite confirmed to fail for the expected reason before being
restored.

### Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (claude-opus-5, claude-fable-5)
mengw15 added a commit to mengw15/texeraFork that referenced this pull request Sep 18, 2026
…tton

The form view's run button enumerates every state a run cannot start from —
invalid workflow, empty workflow, connecting, no computing unit, a read-only
unit — so that, in its own words, the reader is never sent to press a button
that does nothing. The warehouse requirement added in apache#8551 was missing from
that list: with the feature enabled and nothing picked, the button read
"Run" and looked ready, and the click was refused deeper down, in
ExecuteWorkflowService, with a toast.

It now names what is missing and stays disabled. The condition read is the
one that service refuses on — the boot-time flag and the picked warehouse,
both root-scoped — so the button predicts the refusal exactly.

The read-only check comes before the warehouse one: picking a warehouse is
the only blocked state a reader can act on here, so naming it first would
send someone without write access to fix the wrong thing.

Closes apache#8591.
renovate-bot pushed a commit to renovate-bot/apache-_-texera that referenced this pull request Sep 18, 2026
…tton (apache#8592)

### What changes were proposed in this PR?

The form view's run button enumerates every state a run cannot start
from — invalid workflow, empty workflow, connecting, no computing unit,
a read-only unit — so that, in its own words, "the reader is never sent
to press a button that does nothing". The warehouse requirement added in
apache#8551 was missing from that list: with the feature enabled and nothing
picked, the button read `Run` and looked ready, and the click was
refused deeper down in `ExecuteWorkflowService`, with a toast.

It now names what is missing, ordered after the computing unit as the
canvas orders them, and stays disabled — the warehouse is picked in the
embedded selector, the same reasoning the no-unit case already gives.
The condition it reads is the one `ExecuteWorkflowService` refuses on —
the boot-time flag and the picked warehouse, both root-scoped — so the
button predicts that refusal exactly.

Flag off (the default): `warehouseRequiredButMissing` is never true, so
the button behaves exactly as before.

### Any related issues, documentation, discussions?

Closes apache#8591. Follows apache#8551. Part of apache#6870.

### How was this PR tested?

- Two Vitest cases added: the button names the missing warehouse and
stays disabled, and returns to `Run` once one is picked. The workspace
suite passes in full: 3324 tests.
- Failure path verified rather than assumed: the new case was removed on
purpose and the suite confirmed to fail for the expected reason before
being restored.

### Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (claude-opus-5, claude-fable-5)
renovate-bot pushed a commit to renovate-bot/apache-_-texera that referenced this pull request Sep 18, 2026
…abled (apache#8586)

### What changes were proposed in this PR?

With per-user warehouses enabled, an execution carrying no `warehouseId`
silently wrote into the shared default warehouse:
`resolveLakekeeperWarehouseName` mapped `None` to `None` whenever the
flag was on. That made "a run writes into the user's own warehouse" a UI
convention rather than a system property — the frontend gates Run on a
pick (apache#7817), but nothing enforced it below, and one path already
violated it: agent-driven runs hardcoded `warehouseId = None`, bypassing
the picker entirely.

**The requirement.** `resolveLakekeeperWarehouseName` refuses an
execution that names no warehouse while the feature is enabled, the same
way an execution needs a computing unit. Not a privilege change: an
explicit `whid` was, and still is, checked against the caller's `uid`.
It is resolved before anything destructive happens — both in
`initExecutionService`, ahead of the teardown of the execution in
flight, and in the sync endpoint, ahead of its own shutdown — so a
request that will be refused never disturbs a run already going.

**The agent path**, which had no way to carry a pick at all.
`SyncExecutionRequest` accepts a `warehouseId` and
`SyncExecutionResource` forwards it; the workspace attaches the current
pick to each prompt, the agent service applies it before running, and
the execute request carries it to the backend. Per prompt rather than at
agent creation on purpose: an agent created before the picker had loaded
would otherwise carry no warehouse for its whole life, with every run
refused and nothing in the agent panel able to correct it. It also means
a warehouse chosen after the agent exists takes effect, and an absent
pick clears a previous one rather than leaving a stale id to be sent.

With the feature off (the default) nothing changes: no pick still means
the shared default warehouse, and an explicit pick is still refused
loudly (apache#6930).

### Any related issues, documentation, discussions?

Closes apache#7751. Part of apache#6870; the last of its Phase 0 items, on top of
the dashboard tab (apache#8005) and the on-canvas picker (apache#8551).

### How was this PR tested?

- Scala: `WorkflowServiceWarehouseSpec` (5) covers the requirement
alongside the existing ownership and flag-off cases, and
`WorkflowServiceSpec` (11) pins the new ordering — a refused request
leaves the previous execution attached. `sbt
'WorkflowExecutionService/testOnly *WorkflowServiceSpec
*WorkflowServiceWarehouseSpec'`
- `agent-service`: 309 tests (`bun test`, on CI's bun 1.3.3), covering
the delegate update and the execute request's body in both the picked
and unpicked cases.
- Frontend: 87 tests in `agent.service.spec.ts`, pinning the pick
attached to each prompt.
- Failure paths verified rather than assumed: the requirement, the
pre-teardown ordering, the per-prompt carry, the delegate update and the
request field were each broken on purpose and the suites confirmed to
fail for the expected reason before being restored.
- `scalafmtCheck` (both source sets), `tsc --noEmit` and `prettier
--check` for `agent-service`, eslint for the frontend files: all clean.

### Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (claude-opus-5, claude-fable-5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature frontend Changes related to the frontend GUI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BYO-S3] Frontend: on-canvas per-execution warehouse picker

5 participants