Skip to content

fix to collapse consecutive dashes, strip edge dashes, and cap k8s name at 63 chars#2642

Open
Taj010 wants to merge 2 commits intokubeflow:mainfrom
Taj010:job-name-input-handle
Open

fix to collapse consecutive dashes, strip edge dashes, and cap k8s name at 63 chars#2642
Taj010 wants to merge 2 commits intokubeflow:mainfrom
Taj010:job-name-input-handle

Conversation

@Taj010
Copy link
Copy Markdown
Contributor

@Taj010 Taj010 commented Apr 24, 2026

Description

This PR addresses two issues with auto-generated Kubernetes resource names in the model registry UI:

  1. Bad slugs from display namestranslateDisplayNameForK8s now strips leading/trailing dashes, collapses consecutive dashes, and returns a stable gen-<suffix> when the name would otherwise be empty (e.g. punctuation- or dash-only input), matching the main dashboard behavior.

  2. Client vs BFF length mismatch — The register-and-store transfer job field now enforces a 63 character limit (was 253) so validation matches the BFF. Memo deps for autoGeneratedName / isTouched are fixed; the redundant useEffect was removed.

image image

How Has This Been Tested?

Manually tested UI and ran npm run test:unit -- --testPathPattern=K8sNameDescriptionField and npm run test:type-check.

Merge criteria:

  • All the commits have been signed-off (To pass the DCO check)
  • The commits have meaningful messages
  • Automated tests are provided as part of the PR for major new functionalities; testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
  • The developer has manually tested the changes and verified that the changes work.
  • Code changes follow the kubeflow contribution guidelines.
  • For first time contributors: Please reach out to the Reviewers to ensure all tests are being run, ensuring the label ok-to-test has been added to the PR.

If you have UI changes

  • The developer has added tests or explained why testing cannot be added.
  • Included any necessary screenshots or gifs if it was a UI change.
  • Verify that UI/UX changes conform the UX guidelines for Kubeflow.

Signed-off-by: Taj010 <rsheen003@gmail.com>
@google-oss-prow google-oss-prow Bot requested review from chambridge and fege April 24, 2026 21:27
@github-actions github-actions Bot added Area/UI and removed size/L labels Apr 24, 2026
Copy link
Copy Markdown
Contributor

@manaswinidas manaswinidas left a comment

Choose a reason for hiding this comment

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

Thanks for tackling this! The core dash-handling fix is solid. A few suggestions to simplify and align with the existing shared utility.

}
const alphanumeric = out.replace(/[^a-z0-9]/g, '');
return (alphanumeric.length >= 4 ? alphanumeric : `${alphanumeric}x0`).slice(0, 16);
};
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.

This function and the modified translateDisplayNameForK8s below can be dropped entirely. The full version — with dash collapsing, maxLength, safeK8sPrefix, digit-start protection, and empty-name gen- fallback — already exists in this repo at ~/app/shared/components/utils.ts.

Just import from there:

import { translateDisplayNameForK8s } from '~/app/shared/components/utils';

handleUpdateLogic in this file also calls translateDisplayNameForK8s, so both call sites benefit from the switch.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Adjusted this! Removed the local implementation and now import from ~/app/shared/components/utils.

registryName,
}: RegisterAndStoreFieldsProps<D>): React.ReactNode => {
const autoGeneratedName = React.useMemo(
() => translateDisplayNameForK8s(formData.jobName),
Copy link
Copy Markdown
Contributor

@manaswinidas manaswinidas Apr 28, 2026

Choose a reason for hiding this comment

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

The shared translateDisplayNameForK8s (from ~/app/shared/components/utils) uses genRandomChars() for the empty-name fallback, so calling it inside useMemo will produce a different value on every recompute — breaking the isTouched comparison.

Instead, push name generation through handleUpdateLogic/onDataChange (generate once, store in form state) like odh-dashboard does. In odh-dashboard's handleUpdateLogic, maxLength is read from existingData.k8sName.state and passed to translateDisplayNameForK8s automatically — so maxLength: 63 flows through without needing to pass it at the direct call site. The random value is computed once on name change and persisted, not re-derived every render.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed — removed render-time translation; generation now happens via handleUpdateLogic/onDataChange and is persisted in form state.

invalidLength: resourceName.length > 253,
maxLength: 253,
invalidLength: resourceName.length > 63,
maxLength: 63,
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.

The 253 → 63 fix is correct and should stay. 👍

it('prepends safePrefix when name normalizes to empty', () => {
expect(translateDisplayNameForK8s('!!!', 'safe-')).toBe('safe-');
});
});
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.

If translateDisplayNameForK8s is imported from the shared util instead of being defined locally, these tests become redundant — the shared version already has comprehensive test coverage. Consider testing the RegisterAndStoreFields wiring (e.g. 63-char limit, touched detection) instead.

Also note: expect(translateDisplayNameForK8s('!!!', 'safe-')).toBe('safe-') produces a name ending with -, which isn't valid for K8s. The shared version handles this correctly by appending genRandomChars() after the prefix.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed — removed redundant K8sNameDescriptionField util tests and added RegisterAndStoreFields wiring tests (63-char limit + touched/manual-name behavior).

* translateDisplayNameForK8sAndReport in app/shared/components/utils.ts, without per-call randomness).
* @see https://kubernetes.io/docs/concepts/overview/working-with-objects/names/
*/
export const translateDisplayNameForK8s = (name = '', safePrefix = ''): string => {
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.

We should get rid of this copy altogether

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed the local re-export

Signed-off-by: Taj010 <rsheen003@gmail.com>
@google-oss-prow
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from manaswinidas. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@Taj010 Taj010 requested a review from manaswinidas May 1, 2026 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants