Skip to content

fix(FR-2780): apply deployment launcher post-migration feedback#7167

Merged
graphite-app[bot] merged 1 commit into
mainfrom
04-30-fix_fr-2780_apply_deployment_launcher_post-migration_feedback
Apr 30, 2026
Merged

fix(FR-2780): apply deployment launcher post-migration feedback#7167
graphite-app[bot] merged 1 commit into
mainfrom
04-30-fix_fr-2780_apply_deployment_launcher_post-migration_feedback

Conversation

@ironAiken2
Copy link
Copy Markdown
Contributor

@ironAiken2 ironAiken2 commented Apr 30, 2026

Resolves #7166 (FR-2780)

Follow-up fixes after manually exercising the deployment launcher and detail page on the FR-2776 schema. Two commits on this branch:

  1. fix(FR-2780): apply deployment launcher post-migration feedback — launcher / VFolderSelect / start_command / Inference Runtime note / schema-sync.
  2. fix(FR-2780): consolidate deployment configuration queries — detail page query consolidation, RevisionInfo rework, Revision Tab "Deploy" UX.

Changes by area

Deployment Launcher (DeploymentLauncherPage, DeploymentAddRevisionModal)

  • Image global id → UUID before submitting addModelRevision. ImageInput.id is declared ID! but parsed as UUID! server-side, so the form's ImageV2:<uuid> (base64) value caused a Pydantic UUID error. Decoded with a shared safeDecodeUuid helper that accepts either a raw UUID or a Strawberry global id.
  • startCommand is now sent as a list of shell tokens. The server's ModelDefinition Pydantic validator rejects raw strings (models.0.service.start_command: Input should be a valid list), and a previously-saved string also broke myDeployments reads. Tokenization uses the existing tokenizeShellCommand helper, so the launcher submission and model-definition.yaml generation share one tokenizer.
  • Inference Runtime select shows a warning-style note for non-custom variants. New Form.Item rule with warningOnly: true (matching the cluster-size convention) reading "The default start command for the selected inference runtime will be applied automatically." Translated into 20 languages via modelService.RuntimeVariantDefaultCommandAppliedNote.

Model Folder picker (VFolderSelect)

  • Folder name is now shown in edit mode for user-scope folders too. The Select previously leaked the raw UUID when the form value wasn't returned by the project-scoped /folders?group_id=X endpoint. Two fallbacks were added:
    1. Look the value up in the unfiltered REST response (handles cases where the folder fails the prop filter but is still in data).
    2. Otherwise issue a vfolder_node Relay query (Suspense + ErrorBoundaryWithNullFallback) so the name resolves even when the folder is in a different scope. Silent fallback to UUID if the user lacks permission.

Detail page — Configuration / Revision Info card (DeploymentConfigurationSection)

  • Single combined DeploymentConfigurationSectionQuery replaces the previous OverviewQuery + RevisionInfoQuery + CurrentRevisionModalQuery. Metadata, network access, replica state, current revision, and deploying revision now load in one network roundtrip. The DeploymentConfigurationSection_deployment fragment and its spread in DeploymentDetailPageQuery are removed.
  • Revision Info card always renders. When the deployment has no current revision (just-created, scaled to zero, etc.), the card body shows an antd <Empty> with deployment.NoCurrentRevisionDeployed instead of being hidden.
  • Top banner driven by deployingRevision, not revisionHistory[0]. Shows "Deploying revision {{name}}." (deployment.DeployingRevisionApplying) only when deployingRevision.id !== currentRevision.id — server briefly leaves deployingRevisionId set after promotion, and showing the banner then reads as a contradiction. Action button renamed "View Current Revision" → "View Revision" (deployment.ViewRevision); clicking it opens the shared DeploymentRevisionDetailDrawer (the same drawer used in the Revision Tab) instead of the legacy modal.
  • Card body now uses currentRevision only. Dropped the previous "mix currentRevision metadata with revisionHistory[0] model definition" logic. The redundant "Model Version" row (which echoed the Revision ID) is removed.
  • image row spans the full width. antd v6 Descriptions truncates a span when the row's remaining columns can't fit it (rather than wrapping), so cluster-mode was reordered before image so the image item lands at column 1 and its span: { xxl: 3, xl: 2, lg: 2, md: 1, sm: 1, xs: 1 } actually applies. Same fix applied to environ.

Detail page — Revision Tab (DeploymentRevisionHistoryTab)

  • Action renamed "Rollback" → "Deploy" with icon change UndoOutlinedPlayCircleOutlined. The action conceptually "makes any revision active" rather than only rolling back, so the button label, modal title, confirm copy, and success notification all use the new wording. Replaces 4 i18n keys: Rollback, RollbackConfirm, RollbackDisabled, RollbackSuccessDeploy, DeployConfirm, DeployDisabled, DeploySuccess.
  • Mutation switched from generic updateModelDeployment to the dedicated activateDeploymentRevision (added in 25.19.0). Input shape changes from { id, activeRevisionId } to { deploymentId, revisionId }; the payload now also surfaces previousRevisionId / activatedRevisionId.
  • Disable rule changed from isCurrent || isLatest to isCurrent || isDeploying — uses deployingRevisionId (just added to the list query) instead of "the latest history entry". Tooltip copy updated to "Cannot select a revision that is being deployed or is currently deployed."
  • Id-format mismatch fixedcurrentRevisionId / deployingRevisionId come back as raw UUIDs from the scalar fields, while record.id is the Strawberry global id. Both sides are now normalized through toLocalId before comparing, so the disable check actually matches. Same fix applied inside DeploymentRevisionDetailDrawer.tsx (where the isCurrent indicator could receive currentRevisionId in either form depending on the caller).
  • Status tags reworked. TagBAITag (project convention). The "Current" tag is now color="success" (was colorPrimary), the link no longer applies strong for the current row, and a new "Deploying" tag (color="warning" + <LoadingOutlined spin />) is shown for the row matching deployingRevisionId. Hidden on the row that is both current and deploying so the two tags don't contradict each other.

Schema sync follow-up

  • useRuntimeParameterSchema adapts to DeploymentRevisionPresetFilter.runtimeVariantId changing from UUID to UUIDFilter ({ runtimeVariantId: variantRowId }{ runtimeVariantId: { equals: variantRowId } }).
  • data/schema.graphql synced with the upstream changes uncovered by this work (runtimeVariantId, domainName, projectId filters → typed Filter inputs).

i18n

All deployment-related copy added or modified in this PR is translated into the 20 target languages (de, el, es, fi, fr, id, it, ja, ko, mn, ms, pl, pt-BR, pt, ru, th, tr, vi, zh-CN, zh-TW). New / changed keys:

  • modelService.RuntimeVariantDefaultCommandAppliedNote
  • deployment.NoCurrentRevisionDeployed (replaces the briefly-introduced NoCurrentRevisionApplied)
  • deployment.DeployingRevisionApplying (with {{name}} placeholder)
  • deployment.ViewRevision
  • deployment.Deploy / DeployConfirm / DeployDisabled / DeploySuccess (replace Rollback* keys, fully removed from all locale files)
  • deployment.Deploying

Test plan

  • Create a deployment with a custom variant + custom start command — succeeds, no UUID parse error, start_command persists as a list.
  • Create a deployment with a non-custom variant — orange warning note appears under the Inference Runtime select; submission succeeds.
  • Edit a deployment whose model folder is user-scope (not in /folders?group_id=X) — folder name (not UUID) renders in the Model Folder select.
  • Run myDeployments after a successful create with the new tokenizer — query returns rows and does not fail with models.0.service.start_command Input should be a valid list.
  • Detail page with a current revision — RevisionInfo card shows currentRevision's details; only one combined GraphQL request goes out (verify in network panel).
  • Detail page without a current revision — RevisionInfo card stays visible and shows the <Empty> "No revision is currently deployed." message.
  • Detail page with a deploying revision ≠ current — banner "Deploying revision ." appears; clicking "View Revision" opens the drawer for the deploying revision. When deployingRevision === currentRevision, the banner is hidden.
  • Image row in the Revision Info card spans the full row at xxl/xl/lg breakpoints; same for the environ row.
  • Revision Tab — "Deploy" button (PlayCircle icon) is disabled with the new tooltip on the row that is current and on the row that is deploying; enabled on others. Status tags: green "Current" + yellow "Deploying" with spinner; both never appear together.
  • Click "Deploy" on a non-current revision — confirm modal uses the new copy, the request hits activateDeploymentRevision with { deploymentId, revisionId } (verify in network panel), success toast uses the new wording.
  • Switch the UI to a couple of non-English locales — all new copy renders in the target language.
  • bash scripts/verify.sh=== ALL PASS ===.

Copy link
Copy Markdown
Contributor Author

ironAiken2 commented Apr 30, 2026


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • flow:merge-queue - adds this PR to the back of the merge queue
  • flow:hotfix - for urgent changes, fast-track this PR to the front of the merge queue

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has required the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 30, 2026

Coverage report for ./react

St.
Category Percentage Covered / Total
🔴 Statements
8.11% (-0.01% 🔻)
1859/22930
🔴 Branches
7.33% (-0.01% 🔻)
1187/16189
🔴 Functions
4.82% (+0.01% 🔼)
297/6165
🔴 Lines
7.88% (-0.01% 🔻)
1750/22210

Test suite run success

865 tests passing in 40 suites.

Report generated by 🧪jest coverage report action from 093418f

@graphite-app graphite-app Bot changed the base branch from 04-30-fix_fr-2776_adapt_addmodelrevision_call_sites_to_new_schema to graphite-base/7167 April 30, 2026 07:06
@graphite-app graphite-app Bot force-pushed the 04-30-fix_fr-2780_apply_deployment_launcher_post-migration_feedback branch from c23da44 to e1996c2 Compare April 30, 2026 07:23
@graphite-app graphite-app Bot force-pushed the graphite-base/7167 branch from 6350b34 to 3a901b2 Compare April 30, 2026 07:23
@graphite-app graphite-app Bot changed the base branch from graphite-base/7167 to main April 30, 2026 07:24
@graphite-app graphite-app Bot force-pushed the 04-30-fix_fr-2780_apply_deployment_launcher_post-migration_feedback branch from e1996c2 to 8852947 Compare April 30, 2026 07:24
@github-actions github-actions Bot added size:XL 500~ LoC and removed size:L 100~500 LoC labels Apr 30, 2026
@ironAiken2 ironAiken2 force-pushed the 04-30-fix_fr-2780_apply_deployment_launcher_post-migration_feedback branch 9 times, most recently from 9bb3801 to 2df5f6f Compare April 30, 2026 11:51
@ironAiken2 ironAiken2 force-pushed the 04-30-fix_fr-2780_apply_deployment_launcher_post-migration_feedback branch from 2df5f6f to 093418f Compare April 30, 2026 11:54
@ironAiken2 ironAiken2 marked this pull request as ready for review April 30, 2026 12:00
@ironAiken2 ironAiken2 requested review from agatha197, Copilot, nowgnuesLee and yomybaby and removed request for Copilot April 30, 2026 12:00
Copy link
Copy Markdown
Contributor

@agatha197 agatha197 left a comment

Choose a reason for hiding this comment

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

LGTM

@graphite-app
Copy link
Copy Markdown

graphite-app Bot commented Apr 30, 2026

Merge activity

Resolves #7166 ([FR-2780](https://lablup.atlassian.net/browse/FR-2780))

Follow-up fixes after manually exercising the deployment launcher and detail page on the FR-2776 schema. Two commits on this branch:

1. `fix(FR-2780): apply deployment launcher post-migration feedback` — launcher / VFolderSelect / start_command / Inference Runtime note / schema-sync.
2. `fix(FR-2780): consolidate deployment configuration queries` — detail page query consolidation, RevisionInfo rework, Revision Tab "Deploy" UX.

## Changes by area

### Deployment Launcher (`DeploymentLauncherPage`, `DeploymentAddRevisionModal`)

- **Image global id → UUID before submitting `addModelRevision`.** `ImageInput.id` is declared `ID!` but parsed as `UUID!` server-side, so the form's `ImageV2:<uuid>` (base64) value caused a Pydantic UUID error. Decoded with a shared `safeDecodeUuid` helper that accepts either a raw UUID or a Strawberry global id.
- **`startCommand` is now sent as a list of shell tokens.** The server's `ModelDefinition` Pydantic validator rejects raw strings (`models.0.service.start_command: Input should be a valid list`), and a previously-saved string also broke `myDeployments` reads. Tokenization uses the existing `tokenizeShellCommand` helper, so the launcher submission and `model-definition.yaml` generation share one tokenizer.
- **Inference Runtime select shows a warning-style note for non-`custom` variants.** New `Form.Item` rule with `warningOnly: true` (matching the cluster-size convention) reading "The default start command for the selected inference runtime will be applied automatically." Translated into 20 languages via `modelService.RuntimeVariantDefaultCommandAppliedNote`.

### Model Folder picker (`VFolderSelect`)

- **Folder name is now shown in edit mode for user-scope folders too.** The Select previously leaked the raw UUID when the form value wasn't returned by the project-scoped `/folders?group_id=X` endpoint. Two fallbacks were added:
  1. Look the value up in the unfiltered REST response (handles cases where the folder fails the prop `filter` but is still in `data`).
  2. Otherwise issue a `vfolder_node` Relay query (Suspense + `ErrorBoundaryWithNullFallback`) so the name resolves even when the folder is in a different scope. Silent fallback to UUID if the user lacks permission.

### Detail page — Configuration / Revision Info card (`DeploymentConfigurationSection`)

- **Single combined `DeploymentConfigurationSectionQuery`** replaces the previous `OverviewQuery` + `RevisionInfoQuery` + `CurrentRevisionModalQuery`. Metadata, network access, replica state, current revision, and deploying revision now load in one network roundtrip. The `DeploymentConfigurationSection_deployment` fragment and its spread in `DeploymentDetailPageQuery` are removed.
- **`Revision Info` card always renders.** When the deployment has no current revision (just-created, scaled to zero, etc.), the card body shows an antd `<Empty>` with `deployment.NoCurrentRevisionDeployed` instead of being hidden.
- **Top banner driven by `deployingRevision`, not `revisionHistory[0]`.** Shows "Deploying revision {{name}}." (`deployment.DeployingRevisionApplying`) only when `deployingRevision.id !== currentRevision.id` — server briefly leaves `deployingRevisionId` set after promotion, and showing the banner then reads as a contradiction. Action button renamed "View Current Revision" → "View Revision" (`deployment.ViewRevision`); clicking it opens the shared `DeploymentRevisionDetailDrawer` (the same drawer used in the Revision Tab) instead of the legacy modal.
- **Card body now uses `currentRevision` only.** Dropped the previous "mix `currentRevision` metadata with `revisionHistory[0]` model definition" logic. The redundant "Model Version" row (which echoed the Revision ID) is removed.
- **`image` row spans the full width.** antd v6 `Descriptions` truncates a span when the row's remaining columns can't fit it (rather than wrapping), so `cluster-mode` was reordered before `image` so the image item lands at column 1 and its `span: { xxl: 3, xl: 2, lg: 2, md: 1, sm: 1, xs: 1 }` actually applies. Same fix applied to `environ`.

### Detail page — Revision Tab (`DeploymentRevisionHistoryTab`)

- **Action renamed "Rollback" → "Deploy"** with icon change `UndoOutlined` → `PlayCircleOutlined`. The action conceptually "makes any revision active" rather than only rolling back, so the button label, modal title, confirm copy, and success notification all use the new wording. Replaces 4 i18n keys: `Rollback`, `RollbackConfirm`, `RollbackDisabled`, `RollbackSuccess` → `Deploy`, `DeployConfirm`, `DeployDisabled`, `DeploySuccess`.
- **Mutation switched** from generic `updateModelDeployment` to the dedicated `activateDeploymentRevision` (added in 25.19.0). Input shape changes from `{ id, activeRevisionId }` to `{ deploymentId, revisionId }`; the payload now also surfaces `previousRevisionId` / `activatedRevisionId`.
- **Disable rule changed** from `isCurrent || isLatest` to `isCurrent || isDeploying` — uses `deployingRevisionId` (just added to the list query) instead of "the latest history entry". Tooltip copy updated to "Cannot select a revision that is being deployed or is currently deployed."
- **Id-format mismatch fixed** — `currentRevisionId` / `deployingRevisionId` come back as raw UUIDs from the scalar fields, while `record.id` is the Strawberry global id. Both sides are now normalized through `toLocalId` before comparing, so the disable check actually matches. Same fix applied inside `DeploymentRevisionDetailDrawer.tsx` (where the `isCurrent` indicator could receive `currentRevisionId` in either form depending on the caller).
- **Status tags reworked.** `Tag` → `BAITag` (project convention). The "Current" tag is now `color="success"` (was `colorPrimary`), the link no longer applies `strong` for the current row, and a new "Deploying" tag (`color="warning"` + `<LoadingOutlined spin />`) is shown for the row matching `deployingRevisionId`. Hidden on the row that is both current and deploying so the two tags don't contradict each other.

### Schema sync follow-up

- **`useRuntimeParameterSchema`** adapts to `DeploymentRevisionPresetFilter.runtimeVariantId` changing from `UUID` to `UUIDFilter` (`{ runtimeVariantId: variantRowId }` → `{ runtimeVariantId: { equals: variantRowId } }`).
- **`data/schema.graphql`** synced with the upstream changes uncovered by this work (`runtimeVariantId`, `domainName`, `projectId` filters → typed Filter inputs).

## i18n

All deployment-related copy added or modified in this PR is translated into the 20 target languages (`de, el, es, fi, fr, id, it, ja, ko, mn, ms, pl, pt-BR, pt, ru, th, tr, vi, zh-CN, zh-TW`). New / changed keys:

- `modelService.RuntimeVariantDefaultCommandAppliedNote`
- `deployment.NoCurrentRevisionDeployed` (replaces the briefly-introduced `NoCurrentRevisionApplied`)
- `deployment.DeployingRevisionApplying` (with `{{name}}` placeholder)
- `deployment.ViewRevision`
- `deployment.Deploy` / `DeployConfirm` / `DeployDisabled` / `DeploySuccess` (replace `Rollback*` keys, fully removed from all locale files)
- `deployment.Deploying`

## Test plan

- [ ] Create a deployment with a `custom` variant + custom start command — succeeds, no UUID parse error, `start_command` persists as a list.
- [ ] Create a deployment with a non-`custom` variant — orange warning note appears under the Inference Runtime select; submission succeeds.
- [ ] Edit a deployment whose model folder is user-scope (not in `/folders?group_id=X`) — folder name (not UUID) renders in the Model Folder select.
- [ ] Run `myDeployments` after a successful create with the new tokenizer — query returns rows and does not fail with `models.0.service.start_command Input should be a valid list`.
- [ ] Detail page **with a current revision** — RevisionInfo card shows `currentRevision`'s details; only one combined GraphQL request goes out (verify in network panel).
- [ ] Detail page **without a current revision** — RevisionInfo card stays visible and shows the `<Empty>` "No revision is currently deployed." message.
- [ ] Detail page **with a deploying revision** ≠ current — banner "Deploying revision <name>." appears; clicking "View Revision" opens the drawer for the deploying revision. When `deployingRevision === currentRevision`, the banner is hidden.
- [ ] Image row in the Revision Info card spans the full row at xxl/xl/lg breakpoints; same for the `environ` row.
- [ ] Revision Tab — "Deploy" button (PlayCircle icon) is disabled with the new tooltip on the row that is current and on the row that is deploying; enabled on others. Status tags: green "Current" + yellow "Deploying" with spinner; both never appear together.
- [ ] Click "Deploy" on a non-current revision — confirm modal uses the new copy, the request hits `activateDeploymentRevision` with `{ deploymentId, revisionId }` (verify in network panel), success toast uses the new wording.
- [ ] Switch the UI to a couple of non-English locales — all new copy renders in the target language.
- [ ] `bash scripts/verify.sh` → `=== ALL PASS ===`.

[FR-2780]: https://lablup.atlassian.net/browse/FR-2780?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
Copilot AI review requested due to automatic review settings April 30, 2026 12:42
@graphite-app graphite-app Bot force-pushed the 04-30-fix_fr-2780_apply_deployment_launcher_post-migration_feedback branch from 093418f to 90f2d85 Compare April 30, 2026 12:42
@ironAiken2 ironAiken2 review requested due to automatic review settings April 30, 2026 12:42
@graphite-app graphite-app Bot merged commit 90f2d85 into main Apr 30, 2026
13 checks passed
@graphite-app graphite-app Bot deleted the 04-30-fix_fr-2780_apply_deployment_launcher_post-migration_feedback branch April 30, 2026 12:43
@github-actions
Copy link
Copy Markdown
Contributor

Coverage Report for react-coverage (./react)

Status Category Percentage Covered / Total
🔵 Lines 6.88% 1781 / 25866
🔵 Statements 5.78% 1976 / 34138
🔵 Functions 5.34% 296 / 5539
🔵 Branches 4.11% 1291 / 31370
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
react/src/components/DeploymentAddRevisionModal.tsx 0% 0% 0% 0% 63-791
react/src/components/DeploymentConfigurationSection.tsx 0% 0% 0% 0% 59-395
react/src/components/DeploymentLauncherPageContent.tsx 0% 0% 0% 0% 88-662
react/src/components/DeploymentRevisionDetailDrawer.tsx 0% 0% 0% 0% 29-306
react/src/components/DeploymentRevisionHistoryTab.tsx 0% 0% 0% 0% 54-551
react/src/components/VFolderSelect.tsx 0% 0% 0% 0% 69-326
react/src/hooks/useRuntimeParameterSchema.ts 0% 0% 0% 0% 83-324
react/src/pages/DeploymentDetailPage.tsx 0% 0% 0% 0% 24-86
react/src/pages/DeploymentLauncherPage.tsx 0% 0% 0% 0% 62-671
Generated in workflow #115 for commit 90f2d85 by the Vitest Coverage Report Action

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:i18n Localization area:ux UI / UX issue. size:XL 500~ LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Apply deployment launcher post-migration feedback

2 participants