fix(FR-2780): apply deployment launcher post-migration feedback#7167
Merged
graphite-app[bot] merged 1 commit intoApr 30, 2026
Conversation
8 tasks
Contributor
Author
Contributor
Coverage report for
|
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
c23da44 to
e1996c2
Compare
6350b34 to
3a901b2
Compare
e1996c2 to
8852947
Compare
9bb3801 to
2df5f6f
Compare
2df5f6f to
093418f
Compare
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
093418f to
90f2d85
Compare
Contributor
Coverage Report for react-coverage (./react)
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

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:
fix(FR-2780): apply deployment launcher post-migration feedback— launcher / VFolderSelect / start_command / Inference Runtime note / schema-sync.fix(FR-2780): consolidate deployment configuration queries— detail page query consolidation, RevisionInfo rework, Revision Tab "Deploy" UX.Changes by area
Deployment Launcher (
DeploymentLauncherPage,DeploymentAddRevisionModal)addModelRevision.ImageInput.idis declaredID!but parsed asUUID!server-side, so the form'sImageV2:<uuid>(base64) value caused a Pydantic UUID error. Decoded with a sharedsafeDecodeUuidhelper that accepts either a raw UUID or a Strawberry global id.startCommandis now sent as a list of shell tokens. The server'sModelDefinitionPydantic validator rejects raw strings (models.0.service.start_command: Input should be a valid list), and a previously-saved string also brokemyDeploymentsreads. Tokenization uses the existingtokenizeShellCommandhelper, so the launcher submission andmodel-definition.yamlgeneration share one tokenizer.customvariants. NewForm.Itemrule withwarningOnly: true(matching the cluster-size convention) reading "The default start command for the selected inference runtime will be applied automatically." Translated into 20 languages viamodelService.RuntimeVariantDefaultCommandAppliedNote.Model Folder picker (
VFolderSelect)/folders?group_id=Xendpoint. Two fallbacks were added:filterbut is still indata).vfolder_nodeRelay 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)DeploymentConfigurationSectionQueryreplaces the previousOverviewQuery+RevisionInfoQuery+CurrentRevisionModalQuery. Metadata, network access, replica state, current revision, and deploying revision now load in one network roundtrip. TheDeploymentConfigurationSection_deploymentfragment and its spread inDeploymentDetailPageQueryare removed.Revision Infocard always renders. When the deployment has no current revision (just-created, scaled to zero, etc.), the card body shows an antd<Empty>withdeployment.NoCurrentRevisionDeployedinstead of being hidden.deployingRevision, notrevisionHistory[0]. Shows "Deploying revision {{name}}." (deployment.DeployingRevisionApplying) only whendeployingRevision.id !== currentRevision.id— server briefly leavesdeployingRevisionIdset 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 sharedDeploymentRevisionDetailDrawer(the same drawer used in the Revision Tab) instead of the legacy modal.currentRevisiononly. Dropped the previous "mixcurrentRevisionmetadata withrevisionHistory[0]model definition" logic. The redundant "Model Version" row (which echoed the Revision ID) is removed.imagerow spans the full width. antd v6Descriptionstruncates a span when the row's remaining columns can't fit it (rather than wrapping), socluster-modewas reordered beforeimageso the image item lands at column 1 and itsspan: { xxl: 3, xl: 2, lg: 2, md: 1, sm: 1, xs: 1 }actually applies. Same fix applied toenviron.Detail page — Revision Tab (
DeploymentRevisionHistoryTab)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.updateModelDeploymentto the dedicatedactivateDeploymentRevision(added in 25.19.0). Input shape changes from{ id, activeRevisionId }to{ deploymentId, revisionId }; the payload now also surfacespreviousRevisionId/activatedRevisionId.isCurrent || isLatesttoisCurrent || isDeploying— usesdeployingRevisionId(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."currentRevisionId/deployingRevisionIdcome back as raw UUIDs from the scalar fields, whilerecord.idis the Strawberry global id. Both sides are now normalized throughtoLocalIdbefore comparing, so the disable check actually matches. Same fix applied insideDeploymentRevisionDetailDrawer.tsx(where theisCurrentindicator could receivecurrentRevisionIdin either form depending on the caller).Tag→BAITag(project convention). The "Current" tag is nowcolor="success"(wascolorPrimary), the link no longer appliesstrongfor the current row, and a new "Deploying" tag (color="warning"+<LoadingOutlined spin />) is shown for the row matchingdeployingRevisionId. Hidden on the row that is both current and deploying so the two tags don't contradict each other.Schema sync follow-up
useRuntimeParameterSchemaadapts toDeploymentRevisionPresetFilter.runtimeVariantIdchanging fromUUIDtoUUIDFilter({ runtimeVariantId: variantRowId }→{ runtimeVariantId: { equals: variantRowId } }).data/schema.graphqlsynced with the upstream changes uncovered by this work (runtimeVariantId,domainName,projectIdfilters → 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.RuntimeVariantDefaultCommandAppliedNotedeployment.NoCurrentRevisionDeployed(replaces the briefly-introducedNoCurrentRevisionApplied)deployment.DeployingRevisionApplying(with{{name}}placeholder)deployment.ViewRevisiondeployment.Deploy/DeployConfirm/DeployDisabled/DeploySuccess(replaceRollback*keys, fully removed from all locale files)deployment.DeployingTest plan
customvariant + custom start command — succeeds, no UUID parse error,start_commandpersists as a list.customvariant — orange warning note appears under the Inference Runtime select; submission succeeds./folders?group_id=X) — folder name (not UUID) renders in the Model Folder select.myDeploymentsafter a successful create with the new tokenizer — query returns rows and does not fail withmodels.0.service.start_command Input should be a valid list.currentRevision's details; only one combined GraphQL request goes out (verify in network panel).<Empty>"No revision is currently deployed." message.deployingRevision === currentRevision, the banner is hidden.environrow.activateDeploymentRevisionwith{ deploymentId, revisionId }(verify in network panel), success toast uses the new wording.bash scripts/verify.sh→=== ALL PASS ===.