Skip to content

Fix resource parsing#705

Merged
ecolternv merged 7 commits intomainfrom
ecolter/resource-parse-fix
Mar 13, 2026
Merged

Fix resource parsing#705
ecolternv merged 7 commits intomainfrom
ecolter/resource-parse-fix

Conversation

@ecolternv
Copy link
Contributor

@ecolternv ecolternv commented Mar 12, 2026

Description

Fix resource parsing

Issue - None

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

Summary by CodeRabbit

  • Tests

    • Added comprehensive unit tests for workflow spec parsing, covering valid cases, ordering, embedded template blocks, duplicate/extra-section handling, and error messages.
  • Bug Fixes

    • Preserve the 'default-values' section when processing workflows instead of removing it.
  • New Features

    • Improved workflow spec parsing with stricter validation: detects unknown or duplicate top-level sections and requires a workflow section.

@ecolternv ecolternv requested a review from a team as a code owner March 12, 2026 20:56
@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new test target and test module for workflow spec parsing, updates parse_workflow_spec to use a unified section parser for "workflow" and "default-values", and preserves the default-values key in workflow objects instead of deleting it after template processing.

Changes

Cohort / File(s) Summary
Tests
src/lib/utils/tests/BUILD, src/lib/utils/tests/test_workflow.py
Adds an osmo_py_test target and a new ParseWorkflowSpecTests test class with six test cases covering parsing order, Jinja blocks, duplicate top-level keys, and ignoring extra top-level sections.
Workflow parsing utilities
src/lib/utils/workflow.py
Reworks parse_workflow_spec to scan top-level sections via a general pattern, validate allowed section names (workflow, default-values), detect duplicates/unknowns, require workflow, and return parsed workflow content plus YAML-loaded default-values when present.
Workflow object handling
src/service/core/workflow/objects.py
Removed the step that deleted the default-values key from the workflow dictionary; default-values is now preserved after template loading/parsing.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped through specs, lines tidy and neat,
Kept defaults intact — no more delete.
Tests now prance, checking order and quirks,
Jinja and duplicates faced my small works.
Cheers from a rabbit for parsing complete!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title 'Fix resource parsing' is vague and doesn't accurately reflect the main changes, which involve workflow spec parsing, section handling, and default-values preservation rather than resource parsing. Update the title to be more specific about the actual changes, such as 'Refactor workflow spec parsing to handle multiple sections and preserve default-values' or 'Improve section parsing for workflow and default-values'.
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ecolter/resource-parse-fix
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/lib/utils/tests/test_workflow.py (1)

75-84: Consider adding test for duplicate non-workflow keys.

The test verifies duplicate workflow keys raise an error. Consider adding a test for duplicate default-values sections to ensure the duplicate detection is key-agnostic.

🧪 Additional test suggestion
def test_duplicate_default_values_raises(self):
    spec = """\
default-values:
  foo: bar
default-values:
  baz: qux
"""
    with self.assertRaises(osmo_errors.OSMOUserError) as context:
        workflow_utils.parse_workflow_spec(spec)
    self.assertIn('default-values', str(context.exception))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/utils/tests/test_workflow.py` around lines 75 - 84, Add a new unit
test to cover duplicate non-workflow keys by creating a test method similar to
test_duplicate_workflow_raises named test_duplicate_default_values_raises that
passes a YAML string with two duplicate default-values sections into
workflow_utils.parse_workflow_spec and asserts it raises
osmo_errors.OSMOUserError and that the exception message contains
"default-values"; reference the existing pattern in
test_duplicate_workflow_raises (use parse_workflow_spec and
osmo_errors.OSMOUserError) to mirror setup and assertions so duplicate detection
is verified for keys other than "workflow".
src/utils/job/app.py (1)

294-298: Consider consistent unknown section validation.

This function validates workflow section presence but doesn't check for unknown top-level keys, while TemplateSpec.load_template_with_variables in src/utils/job/workflow.py raises an error for unknown sections. If this difference is intentional (e.g., apps can have additional sections), the current code is fine. Otherwise, consider aligning the validation logic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/job/app.py` around lines 294 - 298, validate_app_content currently
only checks for presence of the 'workflow' section (using
workflow_utils.parse_workflow_spec) but does not validate unknown top-level keys
like TemplateSpec.load_template_with_variables does; decide whether apps should
allow extra sections—if not, update validate_app_content to compute the set
difference between parsed sections and the allowed set (e.g., {'workflow'}) and
raise an osmo_errors.OSMOUserError listing unknown sections, otherwise add a
comment explaining the intentional difference and/or mirror the same
allowed-sections logic used by TemplateSpec.load_template_with_variables for
consistency.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/utils/workflow.py`:
- Around line 40-61: The docstring for parse_workflow_spec incorrectly states it
raises OSMOUserError when no "workflow" section is found; update the docstring
to accurately describe behavior: say the function parses top-level sections into
a mapping of names to raw text and only raises OSMOUserError on duplicate
top-level keys (it does not validate presence of a specific "workflow" section),
and note that callers are responsible for ensuring required sections exist;
reference the parse_workflow_spec function and the duplicate-key behavior in the
updated description.

In `@src/utils/job/workflow.py`:
- Around line 788-799: The code currently sets template_data =
yaml.safe_load(sections['default-values'])['default-values'] which can produce
None when the YAML block exists but is empty; update the logic in workflow
parsing (around parse_workflow_spec usage and the template_data variable) to
safely handle that case by loading the YAML, extracting the 'default-values' key
via .get(...) or intermediate variable, and if the result is None set
template_data = {} (or cast to dict) so downstream code always receives a dict;
ensure you modify only the block that reads sections['default-values'] and
preserve existing behavior when a real mapping is present.

---

Nitpick comments:
In `@src/lib/utils/tests/test_workflow.py`:
- Around line 75-84: Add a new unit test to cover duplicate non-workflow keys by
creating a test method similar to test_duplicate_workflow_raises named
test_duplicate_default_values_raises that passes a YAML string with two
duplicate default-values sections into workflow_utils.parse_workflow_spec and
asserts it raises osmo_errors.OSMOUserError and that the exception message
contains "default-values"; reference the existing pattern in
test_duplicate_workflow_raises (use parse_workflow_spec and
osmo_errors.OSMOUserError) to mirror setup and assertions so duplicate detection
is verified for keys other than "workflow".

In `@src/utils/job/app.py`:
- Around line 294-298: validate_app_content currently only checks for presence
of the 'workflow' section (using workflow_utils.parse_workflow_spec) but does
not validate unknown top-level keys like
TemplateSpec.load_template_with_variables does; decide whether apps should allow
extra sections—if not, update validate_app_content to compute the set difference
between parsed sections and the allowed set (e.g., {'workflow'}) and raise an
osmo_errors.OSMOUserError listing unknown sections, otherwise add a comment
explaining the intentional difference and/or mirror the same allowed-sections
logic used by TemplateSpec.load_template_with_variables for consistency.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0aab3760-6caa-4859-9f3d-4da62e522b9b

📥 Commits

Reviewing files that changed from the base of the PR and between 4d51180 and 7bf64dd.

📒 Files selected for processing (7)
  • src/cli/workflow.py
  • src/lib/utils/tests/BUILD
  • src/lib/utils/tests/test_workflow.py
  • src/lib/utils/workflow.py
  • src/service/core/workflow/objects.py
  • src/utils/job/app.py
  • src/utils/job/workflow.py
💤 Files with no reviewable changes (1)
  • src/service/core/workflow/objects.py

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/lib/utils/workflow.py (1)

20-20: Consider using built-in dict for type hints (Python 3.9+ style).

Since Python 3.9+, you can use dict[str, str] directly without importing Dict from typing.

♻️ Proposed fix
-from typing import Dict
+# No typing import needed if using dict directly

Then update line 40 and 53:

-def parse_workflow_spec(workflow_spec: str) -> Dict[str, str]:
+def parse_workflow_spec(workflow_spec: str) -> dict[str, str]:
-    sections: Dict[str, str] = {}
+    sections: dict[str, str] = {}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/utils/workflow.py` at line 20, Remove the typing.Dict import and use
built-in generic dict annotations instead: replace the import "from typing
import Dict" with no import, and change any type hints that use Dict (those at
the occurrences around line 40 and line 53) to the modern syntax dict[str, str]
(or the appropriate key/value types used there) so annotations use native dict
generics.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/lib/utils/workflow.py`:
- Line 20: Remove the typing.Dict import and use built-in generic dict
annotations instead: replace the import "from typing import Dict" with no
import, and change any type hints that use Dict (those at the occurrences around
line 40 and line 53) to the modern syntax dict[str, str] (or the appropriate
key/value types used there) so annotations use native dict generics.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bb4bdd6d-f47a-4dd1-b74f-d1e2ad2a4ba1

📥 Commits

Reviewing files that changed from the base of the PR and between 7bf64dd and 65bec71.

📒 Files selected for processing (2)
  • src/lib/utils/tests/test_workflow.py
  • src/lib/utils/workflow.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/utils/tests/test_workflow.py

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/lib/utils/tests/test_workflow.py (2)

60-71: Consider clarifying the test name.

The test name test_jinja_content_not_at_root_indent is potentially misleading since the Jinja directives ({% for %}, {% endfor %}) ARE at root indent (column 0). The test appears to verify that Jinja syntax at column 0 doesn't break workflow extraction because it's not recognized as a YAML key.

A clearer name might be test_jinja_directives_at_column_zero or test_jinja_content_does_not_terminate_workflow_capture.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/utils/tests/test_workflow.py` around lines 60 - 71, Rename the test
function test_jinja_content_not_at_root_indent to a clearer name (e.g.,
test_jinja_directives_at_column_zero or
test_jinja_content_does_not_terminate_workflow_capture) in the test class so its
intent matches the assertion verifying workflow_utils.parse_workflow_spec
handles Jinja directives at column 0; update the test function name wherever
referenced (imports/pytest markers) to keep tests runnable.

73-82: Consider adding tests for other error conditions.

The test suite covers the duplicate workflow error case well. However, looking at parse_workflow_spec in src/lib/utils/workflow.py, there are two additional error conditions that aren't tested:

  1. Multiple default-values sections raises OSMOUserError
  2. Missing workflow spec (no workflow: key found) raises OSMOUserError

Adding tests for these would improve coverage of the error handling paths.

🧪 Suggested additional test cases
def test_duplicate_default_values_raises(self):
    spec = """\
default-values:
  foo: bar
default-values:
  baz: qux
workflow:
  name: my-wf
"""
    with self.assertRaises(osmo_errors.OSMOUserError) as context:
        workflow_utils.parse_workflow_spec(spec)
    self.assertIn('default-values', str(context.exception))

def test_missing_workflow_raises(self):
    spec = """\
default-values:
  foo: bar
"""
    with self.assertRaises(osmo_errors.OSMOUserError) as context:
        workflow_utils.parse_workflow_spec(spec)
    self.assertIn('Workflow spec not found', str(context.exception))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/utils/tests/test_workflow.py` around lines 73 - 82, Add two new unit
tests alongside test_duplicate_workflow_raises to cover the other error paths in
parse_workflow_spec: (1) test_duplicate_default_values_raises — feed a spec with
two "default-values:" sections and assert parse_workflow_spec raises
osmo_errors.OSMOUserError and the exception string contains "default-values";
(2) test_missing_workflow_raises — feed a spec with only "default-values:" and
assert parse_workflow_spec raises osmo_errors.OSMOUserError and the exception
string contains "Workflow spec not found". Place the tests in
src/lib/utils/tests/test_workflow.py near test_duplicate_workflow_raises and
reference parse_workflow_spec and osmo_errors.OSMOUserError in the assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/lib/utils/tests/test_workflow.py`:
- Around line 60-71: Rename the test function
test_jinja_content_not_at_root_indent to a clearer name (e.g.,
test_jinja_directives_at_column_zero or
test_jinja_content_does_not_terminate_workflow_capture) in the test class so its
intent matches the assertion verifying workflow_utils.parse_workflow_spec
handles Jinja directives at column 0; update the test function name wherever
referenced (imports/pytest markers) to keep tests runnable.
- Around line 73-82: Add two new unit tests alongside
test_duplicate_workflow_raises to cover the other error paths in
parse_workflow_spec: (1) test_duplicate_default_values_raises — feed a spec with
two "default-values:" sections and assert parse_workflow_spec raises
osmo_errors.OSMOUserError and the exception string contains "default-values";
(2) test_missing_workflow_raises — feed a spec with only "default-values:" and
assert parse_workflow_spec raises osmo_errors.OSMOUserError and the exception
string contains "Workflow spec not found". Place the tests in
src/lib/utils/tests/test_workflow.py near test_duplicate_workflow_raises and
reference parse_workflow_spec and osmo_errors.OSMOUserError in the assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8a9ba240-6e3e-4fc4-bf4f-4d0776d3c85f

📥 Commits

Reviewing files that changed from the base of the PR and between e5ce3d6 and 028649f.

📒 Files selected for processing (1)
  • src/lib/utils/tests/test_workflow.py

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/lib/utils/workflow.py (2)

64-65: Uncaught YAML parsing errors could expose internal exceptions to users.

If the default-values section contains malformed YAML, yaml.safe_load() will raise a yaml.YAMLError that propagates uncaught. Consider wrapping this in a try-except to provide a user-friendly error message consistent with other validation errors in this function.

♻️ Proposed fix to wrap YAML errors
     default_values = None
     if 'default-values' in sections:
-        default_values = yaml.safe_load(sections['default-values'])['default-values']
+        try:
+            default_values = yaml.safe_load(sections['default-values'])['default-values']
+        except yaml.YAMLError as e:
+            raise osmo_errors.OSMOUserError(
+                f'Invalid YAML in default-values section: {e}') from e
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/utils/workflow.py` around lines 64 - 65, The YAML parse of the
'default-values' section can raise yaml.YAMLError and currently propagates
uncaught; wrap the yaml.safe_load(sections['default-values']) call in a
try-except that catches yaml.YAMLError and re-raises a user-friendly validation
error (e.g., ValueError or the same ValidationError type used elsewhere in this
function) with a clear message referencing 'default-values' so callers see a
consistent, non-internal error; update the assignment to default_values only
after successful parsing.

42-43: Consider expanding the docstring to document the return value.

The docstring is minimal. It would help future maintainers to document what the tuple contains and what errors the function raises.

📝 Proposed docstring improvement
 def parse_workflow_spec(workflow_spec: str) -> Tuple[str, Dict | None]:
-    """ Parse the workflow spec. """
+    """
+    Parse the workflow spec into workflow content and default values.
+
+    Returns:
+        A tuple of (workflow_section_text, default_values_dict).
+        default_values_dict is None if no default-values section is present.
+
+    Raises:
+        OSMOUserError: If an unknown top-level key is found, a duplicate key exists,
+            or no workflow section is present.
+    """
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/utils/workflow.py` around lines 42 - 43, Update the docstring for
parse_workflow_spec to explicitly describe the return tuple (first element:
workflow name as str; second element: parameters as Dict or None), the possible
shapes of the Dict (e.g., mapping of parameter names to values), and the
exceptions the function may raise (e.g., ValueError, JSONDecodeError or other
parsing errors thrown by the implementation); keep it brief and follow the
project's docstring style (one-line summary, longer description, Returns,
Raises) so callers and maintainers know what to expect from parse_workflow_spec.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/lib/utils/workflow.py`:
- Around line 64-65: The YAML parse of the 'default-values' section can raise
yaml.YAMLError and currently propagates uncaught; wrap the
yaml.safe_load(sections['default-values']) call in a try-except that catches
yaml.YAMLError and re-raises a user-friendly validation error (e.g., ValueError
or the same ValidationError type used elsewhere in this function) with a clear
message referencing 'default-values' so callers see a consistent, non-internal
error; update the assignment to default_values only after successful parsing.
- Around line 42-43: Update the docstring for parse_workflow_spec to explicitly
describe the return tuple (first element: workflow name as str; second element:
parameters as Dict or None), the possible shapes of the Dict (e.g., mapping of
parameter names to values), and the exceptions the function may raise (e.g.,
ValueError, JSONDecodeError or other parsing errors thrown by the
implementation); keep it brief and follow the project's docstring style
(one-line summary, longer description, Returns, Raises) so callers and
maintainers know what to expect from parse_workflow_spec.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 90922ef4-c9fa-4202-9f8a-ed3aac4cb77d

📥 Commits

Reviewing files that changed from the base of the PR and between 028649f and f727bb1.

📒 Files selected for processing (1)
  • src/lib/utils/workflow.py

@ecolternv ecolternv force-pushed the ecolter/resource-parse-fix branch from aedaf8e to aa08dfd Compare March 13, 2026 15:10
@ecolternv ecolternv merged commit bc93ce7 into main Mar 13, 2026
8 checks passed
@ecolternv ecolternv deleted the ecolter/resource-parse-fix branch March 13, 2026 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants