Skip to content

Commit bcca93c

Browse files
jiaenrenclaude
andcommitted
Add optional per-policy help_text appended to label messages
An admin can set help_text on a label policy to append one line of guidance (for example where to look up valid values) to that key's warn and enforce messages, without disclosing the allow_list. Empty by default, so OSS defaults and messages stay deployment-neutral; the NVIDIA AI Hub pointer lives only in internal ConfigMap values. Validated as a single line of at most 256 characters. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 6279cb8 commit bcca93c

5 files changed

Lines changed: 62 additions & 2 deletions

File tree

deployments/charts/service/values.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ services:
480480
## - key: cost-center
481481
## allow_list: [team-a, team-b] # empty allows any well-formed value
482482
## enforcement: warn # "off" | warn | enforce
483+
## help_text: "See the cost-center registry." # appended to messages
483484
## Quote "off" — unquoted YAML off parses as boolean false.
484485
##
485486
labels_config:

src/service/core/workflow/objects.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,8 +501,13 @@ def evaluate_workflow_label_policies(
501501
outcome = 'missing'
502502
elif label_policy.allow_list and value not in label_policy.allow_list:
503503
outcome = 'invalid'
504-
message = '' if outcome == 'ok' else _LABEL_POLICY_MESSAGES[
505-
outcome, label_policy.enforcement].format(key=label_policy.key)
504+
if outcome == 'ok':
505+
message = ''
506+
else:
507+
message = _LABEL_POLICY_MESSAGES[
508+
outcome, label_policy.enforcement].format(key=label_policy.key)
509+
if label_policy.help_text:
510+
message = f'{message} {label_policy.help_text}'
506511
outcomes.append(WorkflowLabelPolicyOutcome(
507512
label_policy, outcome, message))
508513
return outcomes

src/service/core/workflow/tests/test_workflow_labels.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ def _label_policy(
3232
key: str,
3333
enforcement: connectors.LabelEnforcement,
3434
allow_list: list[str] | None = None,
35+
help_text: str = '',
3536
) -> connectors.LabelPolicy:
3637
return connectors.LabelPolicy(
3738
key=key,
3839
enforcement=enforcement,
3940
allow_list=allow_list if allow_list is not None else [],
41+
help_text=help_text,
4042
)
4143

4244

@@ -296,6 +298,30 @@ def test_enforce_violation_rejects_when_another_policy_only_warns(self):
296298
'\n'.join(captured.output),
297299
)
298300

301+
def test_policy_help_text_is_appended_to_warn_and_enforce_messages(self):
302+
help_text = 'Look up valid values in the registry.'
303+
warn_info = _submit_info([
304+
_label_policy(
305+
'project', connectors.LabelEnforcement.WARN, help_text=help_text),
306+
])
307+
warnings = warn_info.validate_workflow_label_policy(_rendered_spec({}))
308+
self.assertEqual(
309+
warnings,
310+
["Workflow is missing label 'project'; add it now to avoid rejected "
311+
f'submissions once it is required. {help_text}'],
312+
)
313+
314+
enforce_info = _submit_info([
315+
_label_policy(
316+
'project', connectors.LabelEnforcement.ENFORCE, help_text=help_text),
317+
])
318+
with self.assertRaises(osmo_errors.OSMOUsageError) as raised:
319+
enforce_info.validate_workflow_label_policy(_rendered_spec({}))
320+
self.assertEqual(
321+
raised.exception.message,
322+
f"Workflow is missing required label 'project'. {help_text}",
323+
)
324+
299325
def test_warn_is_not_persisted_when_later_validation_fails(self):
300326
submit_info = _submit_info([
301327
_label_policy('team', connectors.LabelEnforcement.WARN, ['alpha']),

src/utils/connectors/postgres.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2950,6 +2950,10 @@ class LabelPolicy(ExtraArgBaseModel):
29502950
key: str
29512951
allow_list: List[str] = []
29522952
enforcement: LabelEnforcement = LabelEnforcement.OFF
2953+
# Optional single line appended to this key's warn/enforce messages, e.g.
2954+
# where to look up valid values. Empty by default so the OSS default and
2955+
# messages stay deployment-neutral.
2956+
help_text: str = ''
29532957

29542958
@pydantic.field_validator('key')
29552959
@classmethod
@@ -2961,6 +2965,16 @@ def validate_key(cls, key: str) -> str:
29612965
def validate_allow_list(cls, allow_list: List[str]) -> List[str]:
29622966
return [validation.validate_workflow_label_value(value) for value in allow_list]
29632967

2968+
@pydantic.field_validator('help_text')
2969+
@classmethod
2970+
def validate_help_text(cls, help_text: str) -> str:
2971+
help_text = help_text.strip()
2972+
if len(help_text) > 256:
2973+
raise ValueError('Label policy help_text must be at most 256 characters.')
2974+
if any(character in help_text for character in '\r\n'):
2975+
raise ValueError('Label policy help_text must be a single line.')
2976+
return help_text
2977+
29642978

29652979
class LabelsConfig(ExtraArgBaseModel):
29662980
"""Curated workflow label policy; empty by default, so no policy

src/utils/connectors/tests/test_workflow_config.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ def test_policy_defaults_to_off_and_rejects_unknown_mode(self):
5353
with self.assertRaises(pydantic.ValidationError):
5454
connectors.LabelPolicy(key='PPP', enforcement='block')
5555

56+
def test_help_text_defaults_empty_and_strips(self):
57+
self.assertEqual(connectors.LabelPolicy(key='project').help_text, '')
58+
self.assertEqual(
59+
connectors.LabelPolicy(
60+
key='project', help_text=' See the registry. ').help_text,
61+
'See the registry.',
62+
)
63+
64+
def test_help_text_rejects_multiline_and_overlong(self):
65+
with self.assertRaisesRegex(pydantic.ValidationError, 'single line'):
66+
connectors.LabelPolicy(key='project', help_text='line one\nline two')
67+
with self.assertRaisesRegex(pydantic.ValidationError, 'at most 256'):
68+
connectors.LabelPolicy(key='project', help_text='x' * 257)
69+
5670
def test_rejects_duplicate_policy_keys(self):
5771
with self.assertRaisesRegex(pydantic.ValidationError, 'Duplicate label policy key'):
5872
connectors.WorkflowConfig(labels_config={

0 commit comments

Comments
 (0)